summaryrefslogtreecommitdiffstats
path: root/khtml/html
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /khtml/html
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'khtml/html')
-rw-r--r--khtml/html/Makefile.am54
-rw-r--r--khtml/html/doctypes.cpp1174
-rw-r--r--khtml/html/doctypes.gperf91
-rw-r--r--khtml/html/dtd.cpp918
-rw-r--r--khtml/html/dtd.dtd1072
-rw-r--r--khtml/html/dtd.h41
-rw-r--r--khtml/html/html_baseimpl.cpp708
-rw-r--r--khtml/html/html_baseimpl.h207
-rw-r--r--khtml/html/html_blockimpl.cpp371
-rw-r--r--khtml/html/html_blockimpl.h108
-rw-r--r--khtml/html/html_documentimpl.cpp537
-rw-r--r--khtml/html/html_documentimpl.h95
-rw-r--r--khtml/html/html_elementimpl.cpp678
-rw-r--r--khtml/html/html_elementimpl.h89
-rw-r--r--khtml/html/html_formimpl.cpp2984
-rw-r--r--khtml/html/html_formimpl.h606
-rw-r--r--khtml/html/html_headimpl.cpp649
-rw-r--r--khtml/html/html_headimpl.h233
-rw-r--r--khtml/html/html_imageimpl.cpp560
-rw-r--r--khtml/html/html_imageimpl.h150
-rw-r--r--khtml/html/html_inlineimpl.cpp298
-rw-r--r--khtml/html/html_inlineimpl.h75
-rw-r--r--khtml/html/html_listimpl.cpp169
-rw-r--r--khtml/html/html_listimpl.h112
-rw-r--r--khtml/html/html_miscimpl.cpp443
-rw-r--r--khtml/html/html_miscimpl.h150
-rw-r--r--khtml/html/html_objectimpl.cpp465
-rw-r--r--khtml/html/html_objectimpl.h145
-rw-r--r--khtml/html/html_tableimpl.cpp994
-rw-r--r--khtml/html/html_tableimpl.h329
-rw-r--r--khtml/html/htmlparser.cpp1733
-rw-r--r--khtml/html/htmlparser.h191
-rw-r--r--khtml/html/htmltokenizer.cpp1798
-rw-r--r--khtml/html/htmltokenizer.h358
34 files changed, 18585 insertions, 0 deletions
diff --git a/khtml/html/Makefile.am b/khtml/html/Makefile.am
new file mode 100644
index 000000000..ed7722517
--- /dev/null
+++ b/khtml/html/Makefile.am
@@ -0,0 +1,54 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1997 Martin Jones (mjones@kde.org)
+# (C) 1997 Torben Weis (weis@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+KDE_CXXFLAGS = $(WOVERLOADED_VIRTUAL)
+
+noinst_LTLIBRARIES = libkhtmlhtml.la
+libkhtmlhtml_la_SOURCES = \
+ htmlparser.cpp htmltokenizer.cpp \
+ dtd.cpp html_headimpl.cpp html_blockimpl.cpp \
+ html_elementimpl.cpp html_inlineimpl.cpp html_documentimpl.cpp \
+ html_baseimpl.cpp html_imageimpl.cpp html_listimpl.cpp \
+ html_miscimpl.cpp html_formimpl.cpp html_objectimpl.cpp \
+ html_tableimpl.cpp
+
+libkhtmlhtml_la_METASOURCES = AUTO
+
+
+noinst_HEADERS = \
+ dtd.h html_headimpl.h html_tableimpl.h \
+ html_baseimpl.h html_imageimpl.h htmlparser.h \
+ html_blockimpl.h html_inlineimpl.h \
+ html_documentimpl.h html_listimpl.h htmltokenizer.h \
+ html_elementimpl.h html_miscimpl.h \
+ html_formimpl.h html_objectimpl.h
+
+INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/dcop \
+ -I$(top_srcdir)/kio/kssl \
+ -I$(top_srcdir)/kjs -I$(top_srcdir)/khtml -I$(top_srcdir) \
+ -I$(top_srcdir)/kwallet/client -I$(top_srcdir)/kutils \
+ $(all_includes)
+
+# Use "make doctypes" to regenerate doctypes.cpp from doctypes.gperf
+doctypes: $(srcdir)/doctypes.gperf $(srcdir)/Makefile.am
+ gperf -CEot -L "ANSI-C" -k "*" -N findDoctypeEntry -F ,PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards $(srcdir)/doctypes.gperf > $(srcdir)/doctypes.cpp
+
+#html_documentimpl.lo: doctypes.cpp
+.PHONY: doctypes
+
diff --git a/khtml/html/doctypes.cpp b/khtml/html/doctypes.cpp
new file mode 100644
index 000000000..e79a56f34
--- /dev/null
+++ b/khtml/html/doctypes.cpp
@@ -0,0 +1,1174 @@
+/* ANSI-C code produced by gperf version 3.0.1 */
+/* Command-line: gperf -CEot -L ANSI-C -k '*' -N findDoctypeEntry -F ,PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards /opt/src/kde/kdelibs/khtml/html/doctypes.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 1 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+struct PubIDInfo {
+ enum eMode {
+ eQuirks, /* always quirks mode, unless there's an internal subset */
+ eQuirks3, /* ditto, but but pre-HTML4 (no tbody) */
+ eAlmostStandards,
+ eFullStandards
+ };
+
+ const char* name;
+ eMode mode_if_no_sysid;
+ eMode mode_if_sysid;
+};
+/* maximum key range = 727, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 0, 731, 731, 731, 731, 731, 731, 0,
+ 731, 731, 731, 0, 731, 0, 15, 0, 10, 25,
+ 5, 0, 5, 15, 5, 5, 731, 5, 0, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 10, 5, 0,
+ 40, 0, 20, 10, 0, 0, 0, 731, 0, 0,
+ 10, 45, 0, 0, 0, 0, 0, 0, 0, 0,
+ 10, 0, 5, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731, 731, 731, 731, 731,
+ 731, 731, 731, 731, 731, 731
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[79]];
+ /*FALLTHROUGH*/
+ case 79:
+ hval += asso_values[(unsigned char)str[78]];
+ /*FALLTHROUGH*/
+ case 78:
+ hval += asso_values[(unsigned char)str[77]];
+ /*FALLTHROUGH*/
+ case 77:
+ hval += asso_values[(unsigned char)str[76]];
+ /*FALLTHROUGH*/
+ case 76:
+ hval += asso_values[(unsigned char)str[75]];
+ /*FALLTHROUGH*/
+ case 75:
+ hval += asso_values[(unsigned char)str[74]];
+ /*FALLTHROUGH*/
+ case 74:
+ hval += asso_values[(unsigned char)str[73]];
+ /*FALLTHROUGH*/
+ case 73:
+ hval += asso_values[(unsigned char)str[72]];
+ /*FALLTHROUGH*/
+ case 72:
+ hval += asso_values[(unsigned char)str[71]];
+ /*FALLTHROUGH*/
+ case 71:
+ hval += asso_values[(unsigned char)str[70]];
+ /*FALLTHROUGH*/
+ case 70:
+ hval += asso_values[(unsigned char)str[69]];
+ /*FALLTHROUGH*/
+ case 69:
+ hval += asso_values[(unsigned char)str[68]];
+ /*FALLTHROUGH*/
+ case 68:
+ hval += asso_values[(unsigned char)str[67]];
+ /*FALLTHROUGH*/
+ case 67:
+ hval += asso_values[(unsigned char)str[66]];
+ /*FALLTHROUGH*/
+ case 66:
+ hval += asso_values[(unsigned char)str[65]];
+ /*FALLTHROUGH*/
+ case 65:
+ hval += asso_values[(unsigned char)str[64]];
+ /*FALLTHROUGH*/
+ case 64:
+ hval += asso_values[(unsigned char)str[63]];
+ /*FALLTHROUGH*/
+ case 63:
+ hval += asso_values[(unsigned char)str[62]];
+ /*FALLTHROUGH*/
+ case 62:
+ hval += asso_values[(unsigned char)str[61]];
+ /*FALLTHROUGH*/
+ case 61:
+ hval += asso_values[(unsigned char)str[60]];
+ /*FALLTHROUGH*/
+ case 60:
+ hval += asso_values[(unsigned char)str[59]];
+ /*FALLTHROUGH*/
+ case 59:
+ hval += asso_values[(unsigned char)str[58]];
+ /*FALLTHROUGH*/
+ case 58:
+ hval += asso_values[(unsigned char)str[57]];
+ /*FALLTHROUGH*/
+ case 57:
+ hval += asso_values[(unsigned char)str[56]];
+ /*FALLTHROUGH*/
+ case 56:
+ hval += asso_values[(unsigned char)str[55]];
+ /*FALLTHROUGH*/
+ case 55:
+ hval += asso_values[(unsigned char)str[54]];
+ /*FALLTHROUGH*/
+ case 54:
+ hval += asso_values[(unsigned char)str[53]];
+ /*FALLTHROUGH*/
+ case 53:
+ hval += asso_values[(unsigned char)str[52]];
+ /*FALLTHROUGH*/
+ case 52:
+ hval += asso_values[(unsigned char)str[51]];
+ /*FALLTHROUGH*/
+ case 51:
+ hval += asso_values[(unsigned char)str[50]];
+ /*FALLTHROUGH*/
+ case 50:
+ hval += asso_values[(unsigned char)str[49]];
+ /*FALLTHROUGH*/
+ case 49:
+ hval += asso_values[(unsigned char)str[48]];
+ /*FALLTHROUGH*/
+ case 48:
+ hval += asso_values[(unsigned char)str[47]];
+ /*FALLTHROUGH*/
+ case 47:
+ hval += asso_values[(unsigned char)str[46]];
+ /*FALLTHROUGH*/
+ case 46:
+ hval += asso_values[(unsigned char)str[45]];
+ /*FALLTHROUGH*/
+ case 45:
+ hval += asso_values[(unsigned char)str[44]];
+ /*FALLTHROUGH*/
+ case 44:
+ hval += asso_values[(unsigned char)str[43]];
+ /*FALLTHROUGH*/
+ case 43:
+ hval += asso_values[(unsigned char)str[42]];
+ /*FALLTHROUGH*/
+ case 42:
+ hval += asso_values[(unsigned char)str[41]];
+ /*FALLTHROUGH*/
+ case 41:
+ hval += asso_values[(unsigned char)str[40]];
+ /*FALLTHROUGH*/
+ case 40:
+ hval += asso_values[(unsigned char)str[39]];
+ /*FALLTHROUGH*/
+ case 39:
+ hval += asso_values[(unsigned char)str[38]];
+ /*FALLTHROUGH*/
+ case 38:
+ hval += asso_values[(unsigned char)str[37]];
+ /*FALLTHROUGH*/
+ case 37:
+ hval += asso_values[(unsigned char)str[36]];
+ /*FALLTHROUGH*/
+ case 36:
+ hval += asso_values[(unsigned char)str[35]];
+ /*FALLTHROUGH*/
+ case 35:
+ hval += asso_values[(unsigned char)str[34]];
+ /*FALLTHROUGH*/
+ case 34:
+ hval += asso_values[(unsigned char)str[33]];
+ /*FALLTHROUGH*/
+ case 33:
+ hval += asso_values[(unsigned char)str[32]];
+ /*FALLTHROUGH*/
+ case 32:
+ hval += asso_values[(unsigned char)str[31]];
+ /*FALLTHROUGH*/
+ case 31:
+ hval += asso_values[(unsigned char)str[30]];
+ /*FALLTHROUGH*/
+ case 30:
+ hval += asso_values[(unsigned char)str[29]];
+ /*FALLTHROUGH*/
+ case 29:
+ hval += asso_values[(unsigned char)str[28]];
+ /*FALLTHROUGH*/
+ case 28:
+ hval += asso_values[(unsigned char)str[27]];
+ /*FALLTHROUGH*/
+ case 27:
+ hval += asso_values[(unsigned char)str[26]];
+ /*FALLTHROUGH*/
+ case 26:
+ hval += asso_values[(unsigned char)str[25]];
+ /*FALLTHROUGH*/
+ case 25:
+ hval += asso_values[(unsigned char)str[24]];
+ /*FALLTHROUGH*/
+ case 24:
+ hval += asso_values[(unsigned char)str[23]];
+ /*FALLTHROUGH*/
+ case 23:
+ hval += asso_values[(unsigned char)str[22]];
+ /*FALLTHROUGH*/
+ case 22:
+ hval += asso_values[(unsigned char)str[21]];
+ /*FALLTHROUGH*/
+ case 21:
+ hval += asso_values[(unsigned char)str[20]];
+ /*FALLTHROUGH*/
+ case 20:
+ hval += asso_values[(unsigned char)str[19]];
+ /*FALLTHROUGH*/
+ case 19:
+ hval += asso_values[(unsigned char)str[18]];
+ /*FALLTHROUGH*/
+ case 18:
+ hval += asso_values[(unsigned char)str[17]];
+ /*FALLTHROUGH*/
+ case 17:
+ hval += asso_values[(unsigned char)str[16]];
+ /*FALLTHROUGH*/
+ case 16:
+ hval += asso_values[(unsigned char)str[15]];
+ /*FALLTHROUGH*/
+ case 15:
+ hval += asso_values[(unsigned char)str[14]];
+ /*FALLTHROUGH*/
+ case 14:
+ hval += asso_values[(unsigned char)str[13]];
+ /*FALLTHROUGH*/
+ case 13:
+ hval += asso_values[(unsigned char)str[12]];
+ /*FALLTHROUGH*/
+ case 12:
+ hval += asso_values[(unsigned char)str[11]];
+ /*FALLTHROUGH*/
+ case 11:
+ hval += asso_values[(unsigned char)str[10]];
+ /*FALLTHROUGH*/
+ case 10:
+ hval += asso_values[(unsigned char)str[9]];
+ /*FALLTHROUGH*/
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ /*FALLTHROUGH*/
+ case 8:
+ hval += asso_values[(unsigned char)str[7]];
+ /*FALLTHROUGH*/
+ case 7:
+ hval += asso_values[(unsigned char)str[6]];
+ /*FALLTHROUGH*/
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ hval += asso_values[(unsigned char)str[3]];
+ /*FALLTHROUGH*/
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+#ifdef __GNUC__
+__inline
+#endif
+const struct PubIDInfo *
+findDoctypeEntry (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 78,
+ MIN_WORD_LENGTH = 4,
+ MAX_WORD_LENGTH = 80,
+ MIN_HASH_VALUE = 4,
+ MAX_HASH_VALUE = 730
+ };
+
+ static const struct PubIDInfo wordlist[] =
+ {
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 91 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"html", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 81 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd w3 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 48 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 28 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 73 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 45 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 35 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 33 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 43 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 29 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 41 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 27 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 37 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 69 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w30//dtd w3 html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 24 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 50 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 25 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 31 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 22 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 49 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 47 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 36 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 3//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 39 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 21 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 46 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 44 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 3//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 18 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 34 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 72 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2 final//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 23 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.1e//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 75 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.0 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+#line 30 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 0//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 20 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 42 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 85 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 89 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//webtechs//dtd mozilla html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 86 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 84 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.1//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 38 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 0//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 70 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3 1995-03-24//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 87 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html strict 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 17 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 32 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 1//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 26 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.2 final//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 19 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 40 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 1//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 77 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.01 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eAlmostStandards},
+#line 71 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2 draft//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 74 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2s draft//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 82 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.0 frameset//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 80 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html experimental 970421//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 51 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//metrius//dtd metrius presentational//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 88 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//webtechs//dtd mozilla html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 90 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-/w3c/dtd html 4.0 transitional/en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 76 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.0 transitional//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 79 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html experimental 19960712//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 58 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//netscape comm. corp.//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 78 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.01 transitional//en", PubIDInfo::eQuirks, PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 83 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.0 transitional//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 59 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//netscape comm. corp.//dtd strict html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 65 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//spyglass//dtd html 2.0 extended//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 16 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//as//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 66 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//sq//dtd html 2.0 hotmetal + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 67 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//sun microsystems corp.//dtd hotjava html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 68 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//sun microsystems corp.//dtd hotjava strict html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 60 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//o'reilly and associates//dtd html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 56 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 3.0 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 53 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 2.0 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 55 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 3.0 html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 14 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"+//silmaril//dtd html pro v0r11 19970101//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 52 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 2.0 html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 57 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 3.0 tables//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 54 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 2.0 tables//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 15 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//advasoft ltd//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 61 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//o'reilly and associates//dtd html extended 1.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 62 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//o'reilly and associates//dtd html extended relaxed 1.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 64 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 63 "/opt/src/kde/kdelibs/khtml/html/doctypes.gperf"
+ {"-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register const char *s = wordlist[key].name;
+
+ if (*str == *s && !strcmp (str + 1, s + 1))
+ return &wordlist[key];
+ }
+ }
+ return 0;
+}
diff --git a/khtml/html/doctypes.gperf b/khtml/html/doctypes.gperf
new file mode 100644
index 000000000..97b10e258
--- /dev/null
+++ b/khtml/html/doctypes.gperf
@@ -0,0 +1,91 @@
+struct PubIDInfo {
+ enum eMode {
+ eQuirks, /* always quirks mode, unless there's an internal subset */
+ eQuirks3, /* ditto, but but pre-HTML4 (no tbody) */
+ eAlmostStandards,
+ eFullStandards
+ };
+
+ const char* name;
+ eMode mode_if_no_sysid;
+ eMode mode_if_sysid;
+}
+%%
+"+//silmaril//dtd html pro v0r11 19970101//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//advasoft ltd//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//as//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0 level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0 level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0 strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0 strict level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0 strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 2.1e//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 3.2 final//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 3.2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 0//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 1//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html level 3//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 0//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 1//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict level 3//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html strict//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//ietf//dtd html//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//metrius//dtd metrius presentational//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"-//microsoft//dtd internet explorer 2.0 html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//microsoft//dtd internet explorer 2.0 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//microsoft//dtd internet explorer 2.0 tables//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//microsoft//dtd internet explorer 3.0 html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//microsoft//dtd internet explorer 3.0 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//microsoft//dtd internet explorer 3.0 tables//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//netscape comm. corp.//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//netscape comm. corp.//dtd strict html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//o'reilly and associates//dtd html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//o'reilly and associates//dtd html extended 1.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//o'reilly and associates//dtd html extended relaxed 1.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"-//spyglass//dtd html 2.0 extended//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//sq//dtd html 2.0 hotmetal + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//sun microsystems corp.//dtd hotjava html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//sun microsystems corp.//dtd hotjava strict html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w30//dtd w3 html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 3 1995-03-24//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 3.2 draft//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 3.2 final//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 3.2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 3.2s draft//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html 4.0 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"-//w3c//dtd html 4.0 transitional//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"-//w3c//dtd html 4.01 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eAlmostStandards
+"-//w3c//dtd html 4.01 transitional//en", PubIDInfo::eQuirks, PubIDInfo::eAlmostStandards
+"-//w3c//dtd html experimental 19960712//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd html experimental 970421//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd w3 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3c//dtd xhtml 1.0 frameset//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards
+"-//w3c//dtd xhtml 1.0 transitional//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards
+"-//w3c//dtd xhtml 1.1//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards
+"-//w3o//dtd w3 html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3o//dtd w3 html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//w3o//dtd w3 html strict 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//webtechs//dtd mozilla html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-//webtechs//dtd mozilla html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3
+"-/w3c/dtd html 4.0 transitional/en", PubIDInfo::eQuirks, PubIDInfo::eQuirks
+"html", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3 \ No newline at end of file
diff --git a/khtml/html/dtd.cpp b/khtml/html/dtd.cpp
new file mode 100644
index 000000000..accc8b855
--- /dev/null
+++ b/khtml/html/dtd.cpp
@@ -0,0 +1,918 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "html/dtd.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+// priority of tags. Closing tags of higher priority close tags of lower
+// priority.
+// Update this list, whenever you change htmltags.*
+//
+// 0 elements with forbidden close tag and text. They don't get pushed
+// to the stack.
+// 1 inline elements
+// 2 form elements
+// 3 regular block level elements
+// 4 lists (OL UL DIR MENU)
+// 5 TD TH SELECT
+// 6 TR
+// 7 tbody thead tfoot caption object
+// 8 table
+// 9 body frameset
+// 10 html
+
+const unsigned short KDE_NO_EXPORT DOM::tagPriority[] = {
+ 0, // 0
+ 1, // ID_A == 1
+ 1, // ID_ABBR
+ 1, // ID_ACRONYM
+ 3, // ID_ADDRESS
+ 1, // ID_APPLET
+ 0, // ID_AREA
+ 1, // ID_B
+ 0, // ID_BASE
+ 0, // ID_BASEFONT
+ 1, // ID_BDO
+ 1, // ID_BIG
+ 5, // ID_BLOCKQUOTE
+ 10, // ID_BODY
+ 0, // ID_BR
+ 1, // ID_BUTTON
+ 5, // ID_CAPTION
+ 5, // ID_CENTER
+ 1, // ID_CITE
+ 1, // ID_CODE
+ 0, // ID_COL
+ 1, // ID_COLGROUP
+ 3, // ID_DD
+ 1, // ID_DEL
+ 1, // ID_DFN
+ 5, // ID_DIR
+ 5, // ID_DIV
+ 5, // ID_DL
+ 3, // ID_DT
+ 1, // ID_EM
+ 0, // ID_EMBED
+ 3, // ID_FIELDSET
+ 1, // ID_FONT
+ 3, // ID_FORM
+ 0, // ID_FRAME
+ 10,// ID_FRAMESET
+ 5, // ID_H1
+ 5, // ID_H2
+ 5, // ID_H3
+ 5, // ID_H4
+ 5, // ID_H5
+ 5, // ID_H6
+ 10,// ID_HEAD
+ 0, // ID_HR
+ 11,// ID_HTML
+ 1, // ID_I
+ 1, // ID_IFRAME
+ 1, // ID_ILAYER
+ 0, // ID_IMG
+ 0, // ID_INPUT
+ 1, // ID_INS
+ 0, // ID_ISINDEX
+ 1, // ID_KBD
+ 0, // ID_KEYGEN
+ 1, // ID_LABEL
+ 1, // ID_LAYER
+ 1, // ID_LEGEND
+ 3, // ID_LI
+ 0, // ID_LINK
+ 1, // ID_MAP
+ 3, // ID_MARQUEE
+ 5, // ID_MENU
+ 0, // ID_META
+ 5, // ID_NOBR
+ 10,// ID_NOEMBED
+ 10,// ID_NOFRAMES
+ 3, // ID_NOSCRIPT
+ 1, // ID_NOLAYER
+ 5, // ID_OBJECT
+ 5, // ID_OL
+ 1, // ID_OPTGROUP
+ 2, // ID_OPTION
+ 3, // ID_P
+ 0, // ID_PARAM
+ 5, // ID_PLAINTEXT
+ 5, // ID_PRE
+ 1, // ID_Q
+ 1, // ID_S
+ 1, // ID_SAMP
+ 1, // ID_SCRIPT
+ 6, // ID_SELECT
+ 1, // ID_SMALL
+ 1, // ID_SPAN
+ 1, // ID_STRIKE
+ 1, // ID_STRONG
+ 1, // ID_STYLE
+ 1, // ID_SUB
+ 1, // ID_SUP
+ 9,// ID_TABLE
+ 8, // ID_TBODY
+ 6, // ID_TD
+ 1, // ID_TEXTAREA
+ 8, // ID_TFOOT
+ 6, // ID_TH
+ 8, // ID_THEAD
+ 1, // ID_TITLE
+ 7, // ID_TR
+ 1, // ID_TT
+ 1, // ID_U
+ 5, // ID_UL
+ 1, // ID_VAR
+ 1, // ID_WBR
+ 5, // ID_XMP
+ 0, // ID_TEXT
+};
+
+const tagStatus DOM::endTag[] = {
+ REQUIRED, // 0
+ REQUIRED, // ID_A == 1
+ REQUIRED, // ID_ABBR
+ REQUIRED, // ID_ACRONYM
+ REQUIRED, // ID_ADDRESS
+ REQUIRED, // ID_APPLET
+ FORBIDDEN, // ID_AREA
+ REQUIRED, // ID_B
+ FORBIDDEN, // ID_BASE
+ FORBIDDEN, // ID_BASEFONT
+ REQUIRED, // ID_BDO
+ REQUIRED, // ID_BIG
+ REQUIRED, // ID_BLOCKQUOTE
+ REQUIRED, // ID_BODY
+ FORBIDDEN, // ID_BR
+ REQUIRED, // ID_BUTTON
+ REQUIRED, // ID_CAPTION
+ REQUIRED, // ID_CENTER
+ REQUIRED, // ID_CITE
+ REQUIRED, // ID_CODE
+ FORBIDDEN, // ID_COL
+ OPTIONAL, // ID_COLGROUP
+ OPTIONAL, // ID_DD
+ REQUIRED, // ID_DEL
+ REQUIRED, // ID_DFN
+ REQUIRED, // ID_DIR
+ REQUIRED, // ID_DIV
+ REQUIRED, // ID_DL
+ OPTIONAL, // ID_DT
+ REQUIRED, // ID_EM
+ REQUIRED, // ID_EMBED
+ REQUIRED, // ID_FIELDSET
+ REQUIRED, // ID_FONT
+ REQUIRED, // ID_FORM
+ FORBIDDEN, // ID_FRAME
+ REQUIRED, // ID_FRAMESET
+ REQUIRED, // ID_H1
+ REQUIRED, // ID_H2
+ REQUIRED, // ID_H3
+ REQUIRED, // ID_H4
+ REQUIRED, // ID_H5
+ REQUIRED, // ID_H6
+ OPTIONAL, // ID_HEAD
+ FORBIDDEN, // ID_HR
+ REQUIRED, // ID_HTML
+ REQUIRED, // ID_I
+ REQUIRED, // ID_IFRAME
+ REQUIRED, // ID_ILAYER
+ FORBIDDEN, // ID_IMG
+ FORBIDDEN, // ID_INPUT
+ REQUIRED, // ID_INS
+ FORBIDDEN, // ID_ISINDEX
+ REQUIRED, // ID_KBD
+ REQUIRED, // ID_KEYGEN
+ REQUIRED, // ID_LABEL
+ REQUIRED, // ID_LAYER
+ REQUIRED, // ID_LEGEND
+ OPTIONAL, // ID_LI
+ FORBIDDEN, // ID_LINK
+ REQUIRED, // ID_MAP
+ REQUIRED, // ID_MARQUEE
+ REQUIRED, // ID_MENU
+ FORBIDDEN, // ID_META
+ REQUIRED, // ID_NOBR
+ REQUIRED, // ID_NOEMBED
+ REQUIRED, // ID_NOFRAMES
+ REQUIRED, // ID_NOSCRIPT
+ REQUIRED, // ID_NOLAYER
+ REQUIRED, // ID_OBJECT
+ REQUIRED, // ID_OL
+ REQUIRED, // ID_OPTGROUP
+ OPTIONAL, // ID_OPTION
+ OPTIONAL, // ID_P
+ FORBIDDEN, // ID_PARAM
+ REQUIRED, // ID_PLAINTEXT
+ REQUIRED, // ID_PRE
+ REQUIRED, // ID_Q
+ REQUIRED, // ID_S
+ REQUIRED, // ID_SAMP
+ REQUIRED, // ID_SCRIPT
+ REQUIRED, // ID_SELECT
+ REQUIRED, // ID_SMALL
+ REQUIRED, // ID_SPAN
+ REQUIRED, // ID_STRIKE
+ REQUIRED, // ID_STRONG
+ REQUIRED, // ID_STYLE
+ REQUIRED, // ID_SUB
+ REQUIRED, // ID_SUP
+ REQUIRED, // ID_TABLE
+ OPTIONAL, // ID_TBODY
+ OPTIONAL, // ID_TD
+ REQUIRED, // ID_TEXTAREA
+ OPTIONAL, // ID_TFOOT
+ OPTIONAL, // ID_TH
+ OPTIONAL, // ID_THEAD
+ REQUIRED, // ID_TITLE
+ OPTIONAL, // ID_TR
+ REQUIRED, // ID_TT
+ REQUIRED, // ID_U
+ REQUIRED, // ID_UL
+ REQUIRED, // ID_VAR
+ OPTIONAL, // ID_WBR
+ REQUIRED, // ID_XMP
+ REQUIRED // ID_TEXT
+};
+
+
+static const ushort tag_list_0[] = {
+ ID_TEXT,
+ ID_TT,
+ ID_I,
+ ID_B,
+ ID_U,
+ ID_S,
+ ID_STRIKE,
+ ID_BIG,
+ ID_SMALL,
+ ID_EM,
+ ID_STRONG,
+ ID_DFN,
+ ID_CODE,
+ ID_SAMP,
+ ID_KBD,
+ ID_VAR,
+ ID_CITE,
+ ID_ABBR,
+ ID_ACRONYM,
+ ID_A,
+ ID_IMG,
+ ID_APPLET,
+ ID_OBJECT,
+ ID_EMBED,
+ ID_FONT,
+ ID_BASEFONT,
+ ID_BR,
+ ID_SCRIPT,
+ ID_MAP,
+ ID_Q,
+ ID_SUB,
+ ID_SUP,
+ ID_SPAN,
+ ID_BDO,
+ ID_IFRAME,
+ ID_INPUT,
+ ID_SELECT,
+ ID_TEXTAREA,
+ ID_LABEL,
+ ID_BUTTON,
+ ID_INS,
+ ID_DEL,
+ ID_COMMENT,
+ ID_NOBR,
+ ID_WBR,
+ 0
+};
+
+static const ushort tag_list_1[] = {
+ ID_TEXT,
+ ID_P,
+ ID_H1,
+ ID_H2,
+ ID_H3,
+ ID_H4,
+ ID_H5,
+ ID_H6,
+ ID_UL,
+ ID_OL,
+ ID_DIR,
+ ID_MENU,
+ ID_PRE,
+ ID_PLAINTEXT,
+ ID_DL,
+ ID_DIV,
+ ID_ILAYER,
+ ID_LAYER,
+ ID_CENTER,
+ ID_NOSCRIPT,
+ ID_NOFRAMES,
+ ID_BLOCKQUOTE,
+ ID_FORM,
+ ID_ISINDEX,
+ ID_HR,
+ ID_TABLE,
+ ID_FIELDSET,
+ ID_ADDRESS,
+ ID_TT,
+ ID_I,
+ ID_B,
+ ID_U,
+ ID_S,
+ ID_STRIKE,
+ ID_BIG,
+ ID_SMALL,
+ ID_EM,
+ ID_STRONG,
+ ID_DFN,
+ ID_CODE,
+ ID_SAMP,
+ ID_KBD,
+ ID_VAR,
+ ID_CITE,
+ ID_ABBR,
+ ID_ACRONYM,
+ ID_A,
+ ID_IMG,
+ ID_APPLET,
+ ID_OBJECT,
+ ID_EMBED,
+ ID_FONT,
+ ID_BASEFONT,
+ ID_BR,
+ ID_SCRIPT,
+ ID_MAP,
+ ID_Q,
+ ID_SUB,
+ ID_SUP,
+ ID_SPAN,
+ ID_BDO,
+ ID_IFRAME,
+ ID_INPUT,
+ ID_KEYGEN,
+ ID_SELECT,
+ ID_TEXTAREA,
+ ID_LABEL,
+ ID_BUTTON,
+ ID_COMMENT,
+ ID_LI,
+ ID_DD,
+ ID_XMP,
+ ID_INS,
+ ID_DEL,
+ ID_NOBR,
+ ID_WBR,
+ ID_MARQUEE,
+ 0
+};
+
+static const ushort tag_list_2[] = {
+ ID_COMMENT,
+ 0
+};
+
+static const ushort tag_list_3[] = {
+ ID_TEXT,
+ ID_P,
+ ID_H1,
+ ID_H2,
+ ID_H3,
+ ID_H4,
+ ID_H5,
+ ID_H6,
+ ID_UL,
+ ID_OL,
+ ID_DIR,
+ ID_MENU,
+ ID_PRE,
+ ID_PLAINTEXT,
+ ID_DL,
+ ID_DIV,
+ ID_ILAYER,
+ ID_LAYER,
+ ID_CENTER,
+ ID_NOSCRIPT,
+ ID_NOFRAMES,
+ ID_BLOCKQUOTE,
+ ID_FORM,
+ ID_ISINDEX,
+ ID_HR,
+ ID_TABLE,
+ ID_FIELDSET,
+ ID_ADDRESS,
+ ID_COMMENT,
+ ID_LI,
+ ID_DD,
+ ID_XMP,
+ ID_MARQUEE,
+ 0
+};
+
+static const ushort tag_list_4[] = {
+ ID_TEXT,
+ ID_PARAM,
+ ID_P,
+ ID_H1,
+ ID_H2,
+ ID_H3,
+ ID_H4,
+ ID_H5,
+ ID_H6,
+ ID_UL,
+ ID_OL,
+ ID_DIR,
+ ID_MENU,
+ ID_PRE,
+ ID_PLAINTEXT,
+ ID_DL,
+ ID_DIV,
+ ID_ILAYER,
+ ID_LAYER,
+ ID_CENTER,
+ ID_NOSCRIPT,
+ ID_NOFRAMES,
+ ID_BLOCKQUOTE,
+ ID_FORM,
+ ID_ISINDEX,
+ ID_HR,
+ ID_TABLE,
+ ID_FIELDSET,
+ ID_ADDRESS,
+ ID_TEXT,
+ ID_TT,
+ ID_I,
+ ID_B,
+ ID_U,
+ ID_S,
+ ID_STRIKE,
+ ID_BIG,
+ ID_SMALL,
+ ID_EM,
+ ID_STRONG,
+ ID_DFN,
+ ID_CODE,
+ ID_SAMP,
+ ID_KBD,
+ ID_VAR,
+ ID_CITE,
+ ID_ABBR,
+ ID_ACRONYM,
+ ID_A,
+ ID_IMG,
+ ID_APPLET,
+ ID_OBJECT,
+ ID_EMBED,
+ ID_FONT,
+ ID_BASEFONT,
+ ID_BR,
+ ID_SCRIPT,
+ ID_MAP,
+ ID_Q,
+ ID_SUB,
+ ID_SUP,
+ ID_SPAN,
+ ID_BDO,
+ ID_IFRAME,
+ ID_INPUT,
+ ID_SELECT,
+ ID_TEXTAREA,
+ ID_LABEL,
+ ID_BUTTON,
+ ID_COMMENT,
+ ID_LI,
+ ID_DD,
+ ID_XMP,
+ ID_MARQUEE,
+ 0
+};
+
+static const ushort tag_list_6[] = {
+ ID_DT,
+ ID_DD,
+ ID_COMMENT,
+ 0
+};
+
+static const ushort tag_list_7[] = {
+ ID_TEXT,
+ ID_OPTGROUP,
+ ID_OPTION,
+ ID_COMMENT,
+ ID_SCRIPT,
+ 0
+};
+
+static const ushort tag_list_10[] = {
+ ID_FRAMESET,
+ ID_FRAME,
+ ID_NOFRAMES,
+ ID_COMMENT,
+ 0
+};
+
+static const ushort tag_list_11[] = {
+ ID_SCRIPT,
+ ID_STYLE,
+ ID_META,
+ ID_LINK,
+ ID_TITLE,
+ ID_ISINDEX,
+ ID_BASE,
+ ID_COMMENT,
+ 0
+};
+
+static bool check_array(ushort child, const ushort *tagList)
+{
+ int i = 0;
+ while(tagList[i] != 0)
+ {
+ if(tagList[i] == child) return true;
+ i++;
+ }
+ return false;
+}
+
+
+bool DOM::checkChild(ushort tagID, ushort childID, bool strict)
+{
+ //kdDebug( 6030 ) << "checkChild: " << tagID << "/" << childID << endl;
+
+ // ### allow comments inside ANY node that can contain children
+
+ if (tagID >= 1000 || childID >= 1000)
+ return true; // one or both of the elements in an XML element; just allow for now
+
+ switch(tagID)
+ {
+ case ID_TT:
+ case ID_I:
+ case ID_B:
+ case ID_U:
+ case ID_S:
+ case ID_STRIKE:
+ case ID_BIG:
+ case ID_SMALL:
+ case ID_EM:
+ case ID_STRONG:
+ case ID_DFN:
+ case ID_CODE:
+ case ID_SAMP:
+ case ID_KBD:
+ case ID_VAR:
+ case ID_CITE:
+ case ID_ABBR:
+ case ID_ACRONYM:
+ case ID_SUB:
+ case ID_SUP:
+ case ID_BDO:
+ case ID_FONT:
+ case ID_LEGEND:
+ case ID_Q:
+ case ID_A:
+ case ID_NOBR:
+ case ID_WBR:
+ // _1 *
+ return check_array(childID, tag_list_1) || check_array(childID, tag_list_6);
+ case ID_P:
+ // P: ( _0 | TABLE | NOSCRIPT) *
+ return check_array(childID, tag_list_0) || (!strict && (childID == ID_TABLE || childID == ID_NOSCRIPT));
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ // _0 *
+ return check_array(childID, tag_list_0) ||
+ (!strict && check_array(childID, tag_list_3) && (childID < ID_H1 || childID > ID_H6));
+ case ID_BASEFONT:
+ case ID_BR:
+ case ID_AREA:
+ case ID_LINK:
+ case ID_IMG:
+ case ID_PARAM:
+ case ID_HR:
+ case ID_INPUT:
+ case ID_COL:
+ case ID_FRAME:
+ case ID_ISINDEX:
+ case ID_BASE:
+ case ID_META:
+ case ID_COMMENT:
+ // BASEFONT: EMPTY
+ return false;
+ case ID_BODY:
+ // BODY: _1 * + _2
+ return check_array(childID, tag_list_1) || check_array(childID, tag_list_2);
+ case ID_ADDRESS:
+ // ADDRESS: ( _0 | P ) *
+ return check_array(childID, tag_list_0) || childID == ID_P;
+ case ID_DT:
+ if ( childID == ID_DL ) return false;
+ case ID_LI:
+ case ID_DIV:
+ case ID_SPAN:
+ case ID_ILAYER:
+ case ID_LAYER:
+ case ID_CENTER:
+ case ID_BLOCKQUOTE:
+ case ID_INS:
+ case ID_DEL:
+ case ID_DD:
+ case ID_TH:
+ case ID_TD:
+ case ID_IFRAME:
+ case ID_NOFRAMES:
+ case ID_NOSCRIPT:
+ case ID_CAPTION:
+ case ID_MARQUEE:
+ // DIV: _1 *
+ return check_array(childID, tag_list_1);
+ case ID_MAP:
+ // We accept SCRIPT in client-side image maps as an extension to the DTD.
+ // MAP: ( _3 + | AREA + | SCRIPT + )
+ return check_array(childID, tag_list_3) ||
+ childID == ID_AREA ||
+ childID == ID_SCRIPT;
+ case ID_OBJECT:
+ case ID_EMBED:
+ case ID_APPLET:
+ // OBJECT: _4 *
+ return check_array(childID, tag_list_4);
+ case ID_PRE:
+ case ID_XMP:
+ case ID_PLAINTEXT:
+ // PRE: _0 * - _5
+ return check_array(childID, tag_list_1);
+ case ID_DL:
+ // DL: _6 +
+ return check_array(childID, tag_list_6) || check_array(childID, tag_list_1);
+ case ID_OL:
+ case ID_UL:
+ // OL: LI +
+ return check_array(childID, tag_list_1);
+ case ID_DIR:
+ case ID_MENU:
+ // (DIR|MENU): LI + - _3
+ if(childID == ID_LI) return true;
+ return false;
+ case ID_FORM:
+ // FORM: _1 * - FORM
+ return check_array(childID, tag_list_1);
+ case ID_LABEL:
+ // LABEL: _1 * - LABEL
+ return check_array(childID, tag_list_1);
+ // KEYGEN does not really allow any children
+ // from outside, just need this to be able
+ // to add the keylengths ourself
+ // Yes, consider it a hack (Dirk)
+ case ID_KEYGEN:
+ case ID_SELECT:
+ // SELECT: _7 +
+ return check_array(childID, tag_list_7);
+ case ID_OPTGROUP:
+ // OPTGROUP: OPTION +
+ if(childID == ID_OPTION) return true;
+ return false;
+ case ID_OPTION:
+ case ID_TEXTAREA:
+ case ID_TITLE:
+ case ID_STYLE:
+ case ID_SCRIPT:
+ // OPTION: TEXT
+ if(childID == ID_TEXT) return true;
+ return false;
+ case ID_FIELDSET:
+ // FIELDSET: ( TEXT , LEGEND , _1 * )
+ if(childID == ID_TEXT) return true;
+ if(childID == ID_LEGEND) return true;
+ return check_array(childID, tag_list_1);
+ case ID_BUTTON:
+ // BUTTON: _1 * - _8
+ return check_array(childID, tag_list_1);
+ case ID_TABLE:
+ // TABLE: ( CAPTION ? , ( COL * | COLGROUP * ) , THEAD ? , TFOOT ? , TBODY + )
+ switch(childID)
+ {
+ case ID_CAPTION:
+ case ID_COL:
+ case ID_COLGROUP:
+ case ID_THEAD:
+ case ID_TFOOT:
+ case ID_TBODY:
+ case ID_FORM:
+ case ID_SCRIPT:
+ return true;
+ default:
+ return false;
+ }
+ case ID_THEAD:
+ case ID_TFOOT:
+ case ID_TBODY:
+ // THEAD: TR +
+ if(childID == ID_TR || childID == ID_SCRIPT) return true;
+ return false;
+ case ID_COLGROUP:
+ // COLGROUP: COL *
+ if(childID == ID_COL) return true;
+ return false;
+ case ID_TR:
+ // TR: (TD, TH)
+ return (childID == ID_TH || childID == ID_TD || childID == ID_SCRIPT);
+ case ID_FRAMESET:
+ // FRAMESET: _10
+ return check_array(childID, tag_list_10);
+ case ID_HEAD:
+ // HEAD: _11
+ return check_array(childID, tag_list_11);
+ case ID_HTML:
+ // HTML: ( HEAD , COMMENT, ( BODY | ( FRAMESET & NOFRAMES ? ) ) )
+ switch(childID)
+ {
+ case ID_HEAD:
+ case ID_COMMENT:
+ case ID_BODY:
+ case ID_FRAMESET:
+ case ID_NOFRAMES:
+ case ID_SCRIPT:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ kdDebug( 6030 ) << "unhandled tag in dtd.cpp:checkChild(): tagID=" << tagID << "!" << endl;
+ return false;
+ }
+}
+
+void DOM::addForbidden(int tagId, ushort *forbiddenTags)
+{
+ switch(tagId)
+ {
+ case ID_A:
+ // we allow nested anchors. The innermost one wil be taken...
+ //forbiddenTags[ID_A]++;
+ break;
+ case ID_NOBR:
+ forbiddenTags[ID_PRE]++;
+ // fall through
+ case ID_PRE:
+ case ID_PLAINTEXT:
+ case ID_XMP:
+ //forbiddenTags[ID_IMG]++;
+ forbiddenTags[ID_OBJECT]++;
+ forbiddenTags[ID_EMBED]++;
+ forbiddenTags[ID_APPLET]++;
+ // why forbid them. We can deal with them in PRE
+ //forbiddenTags[ID_BIG]++;
+ //forbiddenTags[ID_SMALL]++;
+ //forbiddenTags[ID_SUB]++;
+ //forbiddenTags[ID_SUP]++;
+ forbiddenTags[ID_BASEFONT]++;
+ break;
+ case ID_DIR:
+ case ID_MENU:
+ forbiddenTags[ID_P]++;
+ forbiddenTags[ID_H1]++;
+ forbiddenTags[ID_H2]++;
+ forbiddenTags[ID_H3]++;
+ forbiddenTags[ID_H4]++;
+ forbiddenTags[ID_H5]++;
+ forbiddenTags[ID_H6]++;
+ forbiddenTags[ID_UL]++;
+ forbiddenTags[ID_OL]++;
+ forbiddenTags[ID_DIR]++;
+ forbiddenTags[ID_MENU]++;
+ forbiddenTags[ID_PRE]++;
+ forbiddenTags[ID_PLAINTEXT]++;
+ forbiddenTags[ID_XMP]++;
+ forbiddenTags[ID_DL]++;
+ forbiddenTags[ID_DIV]++;
+ forbiddenTags[ID_CENTER]++;
+ forbiddenTags[ID_NOSCRIPT]++;
+ forbiddenTags[ID_NOFRAMES]++;
+ forbiddenTags[ID_BLOCKQUOTE]++;
+ forbiddenTags[ID_FORM]++;
+ forbiddenTags[ID_ISINDEX]++;
+ forbiddenTags[ID_HR]++;
+ forbiddenTags[ID_TABLE]++;
+ forbiddenTags[ID_FIELDSET]++;
+ forbiddenTags[ID_ADDRESS]++;
+ break;
+ case ID_LABEL:
+ forbiddenTags[ID_LABEL]++;
+ break;
+ case ID_BUTTON:
+ forbiddenTags[ID_A]++;
+ forbiddenTags[ID_INPUT]++;
+ forbiddenTags[ID_SELECT]++;
+ forbiddenTags[ID_TEXTAREA]++;
+ forbiddenTags[ID_LABEL]++;
+ forbiddenTags[ID_BUTTON]++;
+ forbiddenTags[ID_FORM]++;
+ forbiddenTags[ID_ISINDEX]++;
+ forbiddenTags[ID_FIELDSET]++;
+ forbiddenTags[ID_IFRAME]++;
+ break;
+ default:
+ break;
+ }
+}
+
+void DOM::removeForbidden(int tagId, ushort *forbiddenTags)
+{
+ switch(tagId)
+ {
+ case ID_A:
+ //forbiddenTags[ID_A]--;
+ break;
+ case ID_NOBR:
+ forbiddenTags[ID_PRE]--;
+ // fall through
+ case ID_PRE:
+ case ID_XMP:
+ case ID_PLAINTEXT:
+ //forbiddenTags[ID_IMG]--;
+ forbiddenTags[ID_OBJECT]--;
+ forbiddenTags[ID_EMBED]--;
+ forbiddenTags[ID_APPLET]--;
+ //forbiddenTags[ID_BIG]--;
+ //forbiddenTags[ID_SMALL]--;
+ //forbiddenTags[ID_SUB]--;
+ //forbiddenTags[ID_SUP]--;
+ forbiddenTags[ID_BASEFONT]--;
+ break;
+ case ID_DIR:
+ case ID_MENU:
+ forbiddenTags[ID_P]--;
+ forbiddenTags[ID_H1]--;
+ forbiddenTags[ID_H2]--;
+ forbiddenTags[ID_H3]--;
+ forbiddenTags[ID_H4]--;
+ forbiddenTags[ID_H5]--;
+ forbiddenTags[ID_H6]--;
+ forbiddenTags[ID_UL]--;
+ forbiddenTags[ID_OL]--;
+ forbiddenTags[ID_DIR]--;
+ forbiddenTags[ID_MENU]--;
+ forbiddenTags[ID_PRE]--;
+ forbiddenTags[ID_PLAINTEXT]--;
+ forbiddenTags[ID_XMP]--;
+ forbiddenTags[ID_DL]--;
+ forbiddenTags[ID_DIV]--;
+ forbiddenTags[ID_CENTER]--;
+ forbiddenTags[ID_NOSCRIPT]--;
+ forbiddenTags[ID_NOFRAMES]--;
+ forbiddenTags[ID_BLOCKQUOTE]--;
+ forbiddenTags[ID_FORM]--;
+ forbiddenTags[ID_ISINDEX]--;
+ forbiddenTags[ID_HR]--;
+ forbiddenTags[ID_TABLE]--;
+ forbiddenTags[ID_FIELDSET]--;
+ forbiddenTags[ID_ADDRESS]--;
+ break;
+ case ID_LABEL:
+ forbiddenTags[ID_LABEL]--;
+ break;
+ case ID_BUTTON:
+ forbiddenTags[ID_A]--;
+ forbiddenTags[ID_INPUT]--;
+ forbiddenTags[ID_SELECT]--;
+ forbiddenTags[ID_TEXTAREA]--;
+ forbiddenTags[ID_LABEL]--;
+ forbiddenTags[ID_BUTTON]--;
+ forbiddenTags[ID_FORM]--;
+ forbiddenTags[ID_ISINDEX]--;
+ forbiddenTags[ID_FIELDSET]--;
+ forbiddenTags[ID_IFRAME]--;
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/khtml/html/dtd.dtd b/khtml/html/dtd.dtd
new file mode 100644
index 000000000..d6a5ac8f0
--- /dev/null
+++ b/khtml/html/dtd.dtd
@@ -0,0 +1,1072 @@
+<!--
+ This is the HTML 4.0 Transitional DTD, which includes
+ presentation attributes and elements that W3C expects to phase out
+ as support for style sheets matures. Authors should use the Strict
+ DTD when possible, but may use the Transitional DTD when support
+ for presentation attribute and elements is required.
+
+ HTML 4.0 includes mechanisms for style sheets, scripting,
+ embedding objects, improved support for right to left and mixed
+ direction text, and enhancements to forms for improved
+ accessibility for people with disabilities.
+
+ Draft: $Date$
+
+ Authors:
+ Dave Raggett <dsr@w3.org>
+ Arnaud Le Hors <lehors@w3.org>
+ Ian Jacobs <ij@w3.org>
+
+ Further information about HTML 4.0 is available at:
+
+ http://www.w3.org/TR/REC-html40
+-->
+<!ENTITY % HTML.Version "-//W3C//DTD HTML 4.0 Transitional//EN"
+ -- Typical usage:
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
+ "http://www.w3.org/TR/REC-html40/loose.dtd">
+ <html>
+ <head>
+ ...
+ </head>
+ <body>
+ ...
+ </body>
+ </html>
+
+ The URI used as a system identifier with the public identifier allows
+ the user agent to download the DTD and entity sets as needed.
+
+ The FPI for the Strict HTML 4.0 DTD is:
+
+ "-//W3C//DTD HTML 4.0//EN"
+
+ and its URI is:
+
+ http://www.w3.org/TR/REC-html40/strict.dtd
+
+ Authors should use the Strict DTD unless they need the
+ presentation control for user agents that don't (adequately)
+ support style sheets.
+
+ If you are writing a document that includes frames, use
+ the following FPI:
+
+ "-//W3C//DTD HTML 4.0 Frameset//EN"
+
+ with the URI:
+
+ http://www.w3.org/TR/REC-html40/frameset.dtd
+
+ The following URIs are supported in relation to HTML 4.0
+
+ "http://www.w3.org/TR/REC-html40/strict.dtd" (Strict DTD)
+ "http://www.w3.org/TR/REC-html40/loose.dtd" (Loose DTD)
+ "http://www.w3.org/TR/REC-html40/frameset.dtd" (Frameset DTD)
+ "http://www.w3.org/TR/REC-html40/HTMLlat1.ent" (Latin-1 entities)
+ "http://www.w3.org/TR/REC-html40/HTMLsymbol.ent" (Symbol entities)
+ "http://www.w3.org/TR/REC-html40/HTMLspecial.ent" (Special entities)
+
+ These URIs point to the latest version of each file. To reference
+ this specific revision use the following URIs:
+
+ "http://www.w3.org/TR/1998/REC-html40-19980424/strict.dtd"
+ "http://www.w3.org/TR/1998/REC-html40-19980424/loose.dtd"
+ "http://www.w3.org/TR/1998/REC-html40-19980424/frameset.dtd"
+ "http://www.w3.org/TR/1998/REC-html40-19980424/HTMLlat1.ent"
+ "http://www.w3.org/TR/1998/REC-html40-19980424/HTMLsymbol.ent"
+ "http://www.w3.org/TR/1998/REC-html40-19980424/HTMLspecial.ent"
+
+-->
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA"
+ -- media type, as per [RFC2045]
+ -->
+
+<!ENTITY % ContentTypes "CDATA"
+ -- comma-separated list of media types, as per [RFC2045]
+ -->
+
+<!ENTITY % Charset "CDATA"
+ -- a character encoding, as per [RFC2045]
+ -->
+
+<!ENTITY % Charsets "CDATA"
+ -- a space separated list of character encodings, as per [RFC2045]
+ -->
+
+<!ENTITY % LanguageCode "NAME"
+ -- a language code, as per [RFC1766]
+ -->
+
+<!ENTITY % Character "CDATA"
+ -- a single character from [ISO10646]
+ -->
+
+<!ENTITY % LinkTypes "CDATA"
+ -- space-separated list of link types
+ -->
+
+<!ENTITY % MediaDesc "CDATA"
+ -- single or comma-separated list of media descriptors
+ -->
+
+<!ENTITY % URI "CDATA"
+ -- a Uniform Resource Identifier,
+ see [URI]
+ -->
+
+<!ENTITY % Datetime "CDATA" -- date and time information. ISO date format -->
+
+
+<!ENTITY % Script "CDATA" -- script expression -->
+
+<!ENTITY % StyleSheet "CDATA" -- style sheet data -->
+
+<!ENTITY % FrameTarget "CDATA" -- render in this frame -->
+
+
+<!ENTITY % Text "CDATA">
+
+
+<!-- Parameter Entities -->
+
+<!ENTITY % head.misc "SCRIPT|STYLE|META|LINK|OBJECT" -- repeatable head elements -->
+
+<!ENTITY % heading "H1|H2|H3|H4|H5|H6">
+
+<!ENTITY % list "UL | OL | DIR | MENU">
+
+<!ENTITY % preformatted "PRE">
+
+<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+ Black = #000000 Green = #008000
+ Silver = #C0C0C0 Lime = #00FF00
+ Gray = #808080 Olive = #808000
+ White = #FFFFFF Yellow = #FFFF00
+ Maroon = #800000 Navy = #000080
+ Red = #FF0000 Blue = #0000FF
+ Purple = #800080 Teal = #008080
+ Fuchsia= #FF00FF Aqua = #00FFFF
+ -->
+
+<!ENTITY % bodycolors "
+ bgcolor %Color; #IMPLIED -- document background color --
+ text %Color; #IMPLIED -- document text color --
+ link %Color; #IMPLIED -- color of links --
+ vlink %Color; #IMPLIED -- color of visited links --
+ alink %Color; #IMPLIED -- color of selected links --
+ ">
+
+<!--=================== Generic Attributes ===============================-->
+
+<!ENTITY % coreattrs
+ "id ID #IMPLIED -- document-wide unique id --
+ class CDATA #IMPLIED -- space separated list of classes --
+ style %StyleSheet; #IMPLIED -- associated style info --
+ title %Text; #IMPLIED -- advisory title/amplification --"
+ >
+
+<!ENTITY % i18n
+ "lang %LanguageCode; #IMPLIED -- language code --
+ dir (ltr|rtl) #IMPLIED -- direction for weak/neutral text --"
+ >
+
+<!ENTITY % events
+ "onclick %Script; #IMPLIED -- a pointer button was clicked --
+ ondblclick %Script; #IMPLIED -- a pointer button was double clicked--
+ onmousedown %Script; #IMPLIED -- a pointer button was pressed down --
+ onmouseup %Script; #IMPLIED -- a pointer button was released --
+ onmouseover %Script; #IMPLIED -- a pointer was moved onto --
+ onmousemove %Script; #IMPLIED -- a pointer was moved within --
+ onmouseout %Script; #IMPLIED -- a pointer was moved away --
+ onkeypress %Script; #IMPLIED -- a key was pressed and released --
+ onkeydown %Script; #IMPLIED -- a key was pressed down --
+ onkeyup %Script; #IMPLIED -- a key was released --"
+ >
+
+<!-- Reserved Feature Switch -->
+<!ENTITY % HTML.Reserved "IGNORE">
+
+<!-- The following attributes are reserved for possible future use -->
+<![ %HTML.Reserved; [
+<!ENTITY % reserved
+ "datasrc %URI; #IMPLIED -- a single or tabular Data Source --
+ datafld CDATA #IMPLIED -- the property or column name --
+ dataformatas (plaintext|html) plaintext -- text or html --"
+ >
+]]>
+
+<!ENTITY % reserved "">
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!ENTITY % align "align (left|center|right|justify) #IMPLIED"
+ -- default is left for ltr paragraphs, right for rtl --
+ >
+
+<!--=================== Text Markup ======================================-->
+
+<!ENTITY % fontstyle
+ "TT | I | B | U | S | STRIKE | BIG | SMALL">
+
+<!ENTITY % phrase "EM | STRONG | DFN | CODE |
+ SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >
+
+<!ENTITY % special
+ "A | IMG | APPLET | OBJECT | FONT | BASEFONT | BR | SCRIPT |
+ MAP | Q | SUB | SUP | SPAN | BDO | IFRAME">
+
+<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">
+
+<!-- %inline; covers inline or "text-level" elements -->
+<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">
+
+<!ELEMENT (%fontstyle;|%phrase;) - - (%inline;)*>
+<!ATTLIST (%fontstyle;|%phrase;)
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!ELEMENT (SUB|SUP) - - (%inline;)* -- subscript, superscript -->
+<!ATTLIST (SUB|SUP)
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!ELEMENT SPAN - - (%inline;)* -- generic language/style container -->
+<!ATTLIST SPAN
+ %attrs; -- %coreattrs, %i18n, %events --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!ELEMENT BDO - - (%inline;)* -- I18N BiDi over-ride -->
+<!ATTLIST BDO
+ %coreattrs; -- id, class, style, title --
+ lang %LanguageCode; #IMPLIED -- language code --
+ dir (ltr|rtl) #REQUIRED -- directionality --
+ >
+
+<!ELEMENT BASEFONT - O EMPTY -- base font size -->
+<!ATTLIST BASEFONT
+ id ID #IMPLIED -- document-wide unique id --
+ size CDATA #REQUIRED -- base font size for FONT elements --
+ color %Color; #IMPLIED -- text color --
+ face CDATA #IMPLIED -- comma separated list of font names --
+ >
+
+<!ELEMENT FONT - - (%inline;)* -- local change to font -->
+<!ATTLIST FONT
+ %coreattrs; -- id, class, style, title --
+ %i18n; -- lang, dir --
+ size CDATA #IMPLIED -- [+|-]nn e.g. size="+1", size="4" --
+ color %Color; #IMPLIED -- text color --
+ face CDATA #IMPLIED -- comma separated list of font names --
+ >
+
+<!ELEMENT BR - O EMPTY -- forced line break -->
+<!ATTLIST BR
+ %coreattrs; -- id, class, style, title --
+ clear (left|all|right|none) none -- control of text flow --
+ >
+
+<!--================== HTML content models ===============================-->
+
+<!--
+ HTML has two basic content models:
+
+ %inline; character level elements and text strings
+ %block; block-like elements e.g. paragraphs and lists
+-->
+
+<!ENTITY % block
+ "P | %heading; | %list; | %preformatted; | DL | DIV | CENTER |
+ NOSCRIPT | NOFRAMES | BLOCKQUOTE | FORM | ISINDEX | HR |
+ TABLE | FIELDSET | ADDRESS">
+
+<!ENTITY % flow "%block; | %inline;">
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT BODY O O (%flow;)* +(INS|DEL) -- document body -->
+<!ATTLIST BODY
+ %attrs; -- %coreattrs, %i18n, %events --
+ onload %Script; #IMPLIED -- the document has been loaded --
+ onunload %Script; #IMPLIED -- the document has been removed --
+ background %URI; #IMPLIED -- texture tile for document
+ background --
+ %bodycolors; -- bgcolor, text, link, vlink, alink --
+ >
+
+<!ELEMENT ADDRESS - - ((%inline;)|P)* -- information on author -->
+<!ATTLIST ADDRESS
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!ELEMENT DIV - - (%flow;)* -- generic language/style container -->
+<!ATTLIST DIV
+ %attrs; -- %coreattrs, %i18n, %events --
+ %align; -- align, text alignment --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!ELEMENT CENTER - - (%flow;)* -- shorthand for DIV align=center -->
+<!ATTLIST CENTER
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!--================== The Anchor Element ================================-->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+<!ENTITY % Coords "CDATA" -- comma separated list of lengths -->
+
+<!ELEMENT A - - (%inline;)* -(A) -- anchor -->
+<!ATTLIST A
+ %attrs; -- %coreattrs, %i18n, %events --
+ charset %Charset; #IMPLIED -- char encoding of linked resource --
+ type %ContentType; #IMPLIED -- advisory content type --
+ name CDATA #IMPLIED -- named link end --
+ href %URI; #IMPLIED -- URI for linked resource --
+ hreflang %LanguageCode; #IMPLIED -- language code --
+ target %FrameTarget; #IMPLIED -- render in this frame --
+ rel %LinkTypes; #IMPLIED -- forward link types --
+ rev %LinkTypes; #IMPLIED -- reverse link types --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ shape %Shape; rect -- for use with client-side image maps --
+ coords %Coords; #IMPLIED -- for use with client-side image maps --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ >
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+ separate document although this isn't yet widely supported -->
+
+<!ELEMENT MAP - - ((%block;)+ | AREA+) -- client-side image map -->
+<!ATTLIST MAP
+ %attrs; -- %coreattrs, %i18n, %events --
+ name CDATA #REQUIRED -- for reference by usemap --
+ >
+
+<!ELEMENT AREA - O EMPTY -- client-side image map area -->
+<!ATTLIST AREA
+ %attrs; -- %coreattrs, %i18n, %events --
+ shape %Shape; rect -- controls interpretation of coords --
+ coords %Coords; #IMPLIED -- comma separated list of lengths --
+ href %URI; #IMPLIED -- URI for linked resource --
+ target %FrameTarget; #IMPLIED -- render in this frame --
+ nohref (nohref) #IMPLIED -- this region has no action --
+ alt %Text; #REQUIRED -- short description --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ >
+
+<!--================== The LINK Element ==================================-->
+
+<!--
+ Relationship values can be used in principle:
+
+ a) for document specific toolbars/menus when used
+ with the LINK element in document head e.g.
+ start, contents, previous, next, index, end, help
+ b) to link to a separate style sheet (rel=stylesheet)
+ c) to make a link to a script (rel=script)
+ d) by stylesheets to control how collections of
+ html nodes are rendered into printed documents
+ e) to make a link to a printable version of this document
+ e.g. a postscript or pdf version (rel=alternate media=print)
+-->
+
+<!ELEMENT LINK - O EMPTY -- a media-independent link -->
+<!ATTLIST LINK
+ %attrs; -- %coreattrs, %i18n, %events --
+ charset %Charset; #IMPLIED -- char encoding of linked resource --
+ href %URI; #IMPLIED -- URI for linked resource --
+ hreflang %LanguageCode; #IMPLIED -- language code --
+ type %ContentType; #IMPLIED -- advisory content type --
+ rel %LinkTypes; #IMPLIED -- forward link types --
+ rev %LinkTypes; #IMPLIED -- reverse link types --
+ media %MediaDesc; #IMPLIED -- for rendering on these media --
+ target %FrameTarget; #IMPLIED -- render in this frame --
+ >
+
+<!--=================== Images ===========================================-->
+
+<!-- Length defined in strict DTD for cellpadding/cellspacing -->
+<!ENTITY % Length "CDATA" -- nn for pixels or nn% for percentage length -->
+<!ENTITY % MultiLength "CDATA" -- pixel, percentage, or relative -->
+
+<!ENTITY % MultiLengths "CDATA" -- comma-separated list of MultiLength -->
+
+<!ENTITY % Pixels "CDATA" -- integer representing length in pixels -->
+
+<!ENTITY % IAlign "(top|middle|bottom|left|right)" -- center? -->
+
+<!-- To avoid problems with text-only UAs as well as
+ to make image content understandable and navigable
+ to users of non-visual UAs, you need to provide
+ a description with ALT, and avoid server-side image maps -->
+<!ELEMENT IMG - O EMPTY -- Embedded image -->
+<!ATTLIST IMG
+ %attrs; -- %coreattrs, %i18n, %events --
+ src %URI; #REQUIRED -- URI of image to embed --
+ alt %Text; #REQUIRED -- short description --
+ longdesc %URI; #IMPLIED -- link to long description
+ (complements alt) --
+ height %Length; #IMPLIED -- override height --
+ width %Length; #IMPLIED -- override width --
+ usemap %URI; #IMPLIED -- use client-side image map --
+ ismap (ismap) #IMPLIED -- use server-side image map --
+ align %IAlign; #IMPLIED -- vertical or horizontal alignment --
+ border %Length; #IMPLIED -- link border width --
+ hspace %Pixels; #IMPLIED -- horizontal gutter --
+ vspace %Pixels; #IMPLIED -- vertical gutter --
+ >
+
+<!-- USEMAP points to a MAP element which may be in this document
+ or an external document, although the latter is not widely supported -->
+
+<!--==================== OBJECT ======================================-->
+<!--
+ OBJECT is used to embed objects as part of HTML pages
+ PARAM elements should precede other content. SGML mixed content
+ model technicality precludes specifying this formally ...
+-->
+
+<!ELEMENT OBJECT - - (PARAM | %flow;)*
+ -- generic embedded object -->
+<!ATTLIST OBJECT
+ %attrs; -- %coreattrs, %i18n, %events --
+ declare (declare) #IMPLIED -- declare but don't instantiate flag --
+ classid %URI; #IMPLIED -- identifies an implementation --
+ codebase %URI; #IMPLIED -- base URI for classid, data, archive--
+ data %URI; #IMPLIED -- reference to object's data --
+ type %ContentType; #IMPLIED -- content type for data --
+ codetype %ContentType; #IMPLIED -- content type for code --
+ archive %URI; #IMPLIED -- space separated archive list --
+ standby %Text; #IMPLIED -- message to show while loading --
+ height %Length; #IMPLIED -- override height --
+ width %Length; #IMPLIED -- override width --
+ usemap %URI; #IMPLIED -- use client-side image map --
+ name CDATA #IMPLIED -- submit as part of form --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ align %IAlign; #IMPLIED -- vertical or horizontal alignment --
+ border %Length; #IMPLIED -- link border width --
+ hspace %Pixels; #IMPLIED -- horizontal gutter --
+ vspace %Pixels; #IMPLIED -- vertical gutter --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!ELEMENT PARAM - O EMPTY -- named property value -->
+<!ATTLIST PARAM
+ id ID #IMPLIED -- document-wide unique id --
+ name CDATA #REQUIRED -- property name --
+ value CDATA #IMPLIED -- property value --
+ valuetype (DATA|REF|OBJECT) DATA -- How to interpret value --
+ type %ContentType; #IMPLIED -- content type for value
+ when valuetype=ref --
+ >
+
+<!--=================== Java APPLET ==================================-->
+<!--
+ One of code or object attributes must be present.
+ Place PARAM elements before other content.
+-->
+<!ELEMENT APPLET - - (PARAM | %flow;)* -- Java applet -->
+<!ATTLIST APPLET
+ %coreattrs; -- id, class, style, title --
+ codebase %URI; #IMPLIED -- optional base URI for applet --
+ archive CDATA #IMPLIED -- comma separated archive list --
+ code CDATA #IMPLIED -- applet class file --
+ object CDATA #IMPLIED -- serialized applet file --
+ alt %Text; #IMPLIED -- short description --
+ name CDATA #IMPLIED -- allows applets to find each other --
+ width %Length; #REQUIRED -- initial width --
+ height %Length; #REQUIRED -- initial height --
+ align %IAlign; #IMPLIED -- vertical or horizontal alignment --
+ hspace %Pixels; #IMPLIED -- horizontal gutter --
+ vspace %Pixels; #IMPLIED -- vertical gutter --
+ >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT HR - O EMPTY -- horizontal rule -->
+<!ATTLIST HR
+ %coreattrs; -- id, class, style, title --
+ %events;
+ align (left|center|right) #IMPLIED
+ noshade (noshade) #IMPLIED
+ size %Pixels; #IMPLIED
+ width %Length; #IMPLIED
+ >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT P - O (%inline;)* -- paragraph -->
+<!ATTLIST P
+ %attrs; -- %coreattrs, %i18n, %events --
+ %align; -- align, text alignment --
+ >
+
+<!--=================== Headings =========================================-->
+
+<!--
+ There are six levels of headings from H1 (the most important)
+ to H6 (the least important).
+-->
+
+<!ELEMENT (%heading;) - - (%inline;)* -- heading -->
+<!ATTLIST (%heading;)
+ %attrs; -- %coreattrs, %i18n, %events --
+ %align; -- align, text alignment --
+ >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- excludes markup for images and changes in font size -->
+<!ENTITY % pre.exclusion "IMG|OBJECT|APPLET|BIG|SMALL|SUB|SUP|FONT|BASEFONT">
+
+<!ELEMENT PRE - - (%inline;)* -(%pre.exclusion;) -- preformatted text -->
+<!ATTLIST PRE
+ %attrs; -- %coreattrs, %i18n, %events --
+ width NUMBER #IMPLIED
+ >
+
+<!--===================== Inline Quotes ==================================-->
+
+<!ELEMENT Q - - (%inline;)* -- short inline quotation -->
+<!ATTLIST Q
+ %attrs; -- %coreattrs, %i18n, %events --
+ cite %URI; #IMPLIED -- URI for source document or msg --
+ >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT BLOCKQUOTE - - (%flow;)* -- long quotation -->
+<!ATTLIST BLOCKQUOTE
+ %attrs; -- %coreattrs, %i18n, %events --
+ cite %URI; #IMPLIED -- URI for source document or msg --
+ >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+
+<!-- INS/DEL are handled by inclusion on BODY -->
+<!ELEMENT (INS|DEL) - - (%flow;)* -- inserted text, deleted text -->
+<!ATTLIST (INS|DEL)
+ %attrs; -- %coreattrs, %i18n, %events --
+ cite %URI; #IMPLIED -- info on reason for change --
+ datetime %Datetime; #IMPLIED -- date and time of change --
+ >
+
+<!--=================== Lists ============================================-->
+
+<!-- definition lists - DT for term, DD for its definition -->
+
+<!ELEMENT DL - - (DT|DD)+ -- definition list -->
+<!ATTLIST DL
+ %attrs; -- %coreattrs, %i18n, %events --
+ compact (compact) #IMPLIED -- reduced interitem spacing --
+ >
+
+<!ELEMENT DT - O (%inline;)* -- definition term -->
+<!ELEMENT DD - O (%flow;)* -- definition description -->
+<!ATTLIST (DT|DD)
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!-- Ordered lists (OL) Numbering style
+
+ 1 arablic numbers 1, 2, 3, ...
+ a lower alpha a, b, c, ...
+ A upper alpha A, B, C, ...
+ i lower roman i, ii, iii, ...
+ I upper roman I, II, III, ...
+
+ The style is applied to the sequence number which by default
+ is reset to 1 for the first list item in an ordered list.
+
+ This can't be expressed directly in SGML due to case folding.
+-->
+
+<!ENTITY % OLStyle "CDATA" -- constrained to: "(1|a|A|i|I)" -->
+
+<!ELEMENT OL - - (LI)+ -- ordered list -->
+<!ATTLIST OL
+ %attrs; -- %coreattrs, %i18n, %events --
+ type %OLStyle; #IMPLIED -- numbering style --
+ compact (compact) #IMPLIED -- reduced interitem spacing --
+ start NUMBER #IMPLIED -- starting sequence number --
+ >
+
+<!-- Unordered Lists (UL) bullet styles -->
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!ELEMENT UL - - (LI)+ -- unordered list -->
+<!ATTLIST UL
+ %attrs; -- %coreattrs, %i18n, %events --
+ type %ULStyle; #IMPLIED -- bullet style --
+ compact (compact) #IMPLIED -- reduced interitem spacing --
+ >
+
+<!ELEMENT (DIR|MENU) - - (LI)+ -(%block;) -- directory list, menu list -->
+<!ATTLIST DIR
+ %attrs; -- %coreattrs, %i18n, %events --
+ compact (compact) #IMPLIED
+ >
+<!ATTLIST MENU
+ %attrs; -- %coreattrs, %i18n, %events --
+ compact (compact) #IMPLIED
+ >
+
+<!ENTITY % LIStyle "CDATA" -- constrained to: "(%ULStyle;|%OLStyle;)" -->
+
+<!ELEMENT LI - O (%flow;)* -- list item -->
+<!ATTLIST LI
+ %attrs; -- %coreattrs, %i18n, %events --
+ type %LIStyle; #IMPLIED -- list item style --
+ value NUMBER #IMPLIED -- reset sequence number --
+ >
+
+<!--================ Forms ===============================================-->
+<!ELEMENT FORM - - (%flow;)* -(FORM) -- interactive form -->
+<!ATTLIST FORM
+ %attrs; -- %coreattrs, %i18n, %events --
+ action %URI; #REQUIRED -- server-side form handler --
+ method (GET|POST) GET -- HTTP method used to submit the form--
+ enctype %ContentType; "application/x-www-form-urlencoded"
+ onsubmit %Script; #IMPLIED -- the form was submitted --
+ onreset %Script; #IMPLIED -- the form was reset --
+ target %FrameTarget; #IMPLIED -- render in this frame --
+ accept-charset %Charsets; #IMPLIED -- list of supported charsets --
+ >
+
+<!-- Each label must not contain more than ONE field -->
+<!ELEMENT LABEL - - (%inline;)* -(LABEL) -- form field label text -->
+<!ATTLIST LABEL
+ %attrs; -- %coreattrs, %i18n, %events --
+ for IDREF #IMPLIED -- matches field ID value --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ >
+
+<!ENTITY % InputType
+ "(TEXT | PASSWORD | CHECKBOX |
+ RADIO | SUBMIT | RESET |
+ FILE | HIDDEN | IMAGE | BUTTON)"
+ >
+
+<!-- attribute name required for all but submit & reset -->
+<!ELEMENT INPUT - O EMPTY -- form control -->
+<!ATTLIST INPUT
+ %attrs; -- %coreattrs, %i18n, %events --
+ type %InputType; TEXT -- what kind of widget is needed --
+ name CDATA #IMPLIED -- submit as part of form --
+ value CDATA #IMPLIED -- required for radio and checkboxes --
+ checked (checked) #IMPLIED -- for radio buttons and check boxes --
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ readonly (readonly) #IMPLIED -- for text and passwd --
+ size CDATA #IMPLIED -- specific to each type of field --
+ maxlength NUMBER #IMPLIED -- max chars for text fields --
+ src %URI; #IMPLIED -- for fields with images --
+ alt CDATA #IMPLIED -- short description --
+ usemap %URI; #IMPLIED -- use client-side image map --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ onselect %Script; #IMPLIED -- some text was selected --
+ onchange %Script; #IMPLIED -- the element value was changed --
+ accept %ContentTypes; #IMPLIED -- list of MIME types for file upload --
+ align %IAlign; #IMPLIED -- vertical or horizontal alignment --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!ELEMENT SELECT - - (OPTGROUP|OPTION)+ -- option selector -->
+<!ATTLIST SELECT
+ %attrs; -- %coreattrs, %i18n, %events --
+ name CDATA #IMPLIED -- field name --
+ size NUMBER #IMPLIED -- rows visible --
+ multiple (multiple) #IMPLIED -- default is single selection --
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ onchange %Script; #IMPLIED -- the element value was changed --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!ELEMENT OPTGROUP - - (OPTION)+ -- option group -->
+<!ATTLIST OPTGROUP
+ %attrs; -- %coreattrs, %i18n, %events --
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ label %Text; #REQUIRED -- for use in hierarchical menus --
+ >
+
+<!ELEMENT OPTION - O (#PCDATA) -- selectable choice -->
+<!ATTLIST OPTION
+ %attrs; -- %coreattrs, %i18n, %events --
+ selected (selected) #IMPLIED
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ label %Text; #IMPLIED -- for use in hierarchical menus --
+ value CDATA #IMPLIED -- defaults to element content --
+ >
+
+<!ELEMENT TEXTAREA - - (#PCDATA) -- multi-line text field -->
+<!ATTLIST TEXTAREA
+ %attrs; -- %coreattrs, %i18n, %events --
+ name CDATA #IMPLIED
+ rows NUMBER #REQUIRED
+ cols NUMBER #REQUIRED
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ readonly (readonly) #IMPLIED
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ onselect %Script; #IMPLIED -- some text was selected --
+ onchange %Script; #IMPLIED -- the element value was changed --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!--
+ #PCDATA is to solve the mixed content problem,
+ per specification only whitespace is allowed there!
+ -->
+<!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*) -- form control group -->
+<!ATTLIST FIELDSET
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!ELEMENT LEGEND - - (%inline;)* -- fieldset legend -->
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ATTLIST LEGEND
+ %attrs; -- %coreattrs, %i18n, %events --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ align %LAlign; #IMPLIED -- relative to fieldset --
+ >
+
+<!ELEMENT BUTTON - -
+ (%flow;)* -(A|%formctrl;|FORM|ISINDEX|FIELDSET|IFRAME)
+ -- push button -->
+<!ATTLIST BUTTON
+ %attrs; -- %coreattrs, %i18n, %events --
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED -- sent to server when submitted --
+ type (button|submit|reset) submit -- for use as form button --
+ disabled (disabled) #IMPLIED -- unavailable in this context --
+ tabindex NUMBER #IMPLIED -- position in tabbing order --
+ accesskey %Character; #IMPLIED -- accessibility key character --
+ onfocus %Script; #IMPLIED -- the element got the focus --
+ onblur %Script; #IMPLIED -- the element lost the focus --
+ %reserved; -- reserved for possible future use --
+ >
+
+<!--======================= Tables =======================================-->
+
+<!-- IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The BORDER attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The FRAME attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the VALIGN attribute.
+
+ The value "border" is included for backwards compatibility with
+ <TABLE BORDER> which yields frame=border and border=implied
+ For <TABLE BORDER=1> you get border=1 and frame=implied. In this
+ case, it is appropriate to treat this as frame=border for backwards
+ compatibility with deployed browsers.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The RULES attribute defines which rules to draw between cells:
+
+ If RULES is absent then assume:
+ "none" if BORDER is absent or BORDER=0 otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents -->
+<!ENTITY % cellhalign
+ "align (left|center|right|justify|char) #IMPLIED
+ char %Character; #IMPLIED -- alignment char, e.g. char=':' --
+ charoff %Length; #IMPLIED -- offset for alignment char --"
+ >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+ "valign (top|middle|bottom|baseline) #IMPLIED"
+ >
+
+<!ELEMENT TABLE - -
+ (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
+<!ELEMENT CAPTION - - (%inline;)* -- table caption -->
+<!ELEMENT THEAD - O (TR)+ -- table header -->
+<!ELEMENT TFOOT - O (TR)+ -- table footer -->
+<!ELEMENT TBODY O O (TR)+ -- table body -->
+<!ELEMENT COLGROUP - O (col)* -- table column group -->
+<!ELEMENT COL - O EMPTY -- table column -->
+<!ELEMENT TR - O (TH|TD)+ -- table row -->
+<!ELEMENT (TH|TD) - O (%flow;)* -- table header cell, table data cell-->
+
+<!ATTLIST TABLE -- table element --
+ %attrs; -- %coreattrs, %i18n, %events --
+ summary %Text; #IMPLIED -- purpose/structure for speech output--
+ width %Length; #IMPLIED -- table width --
+ border %Pixels; #IMPLIED -- controls frame width around table --
+ frame %TFrame; #IMPLIED -- which parts of frame to render --
+ rules %TRules; #IMPLIED -- rulings between rows and cols --
+ cellspacing %Length; #IMPLIED -- spacing between cells --
+ cellpadding %Length; #IMPLIED -- spacing within cells --
+ align %TAlign; #IMPLIED -- table position relative to window --
+ bgcolor %Color; #IMPLIED -- background color for cells --
+ %reserved; -- reserved for possible future use --
+ datapagesize CDATA #IMPLIED -- reserved for possible future use --
+ >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST CAPTION
+ %attrs; -- %coreattrs, %i18n, %events --
+ align %CAlign; #IMPLIED -- relative to table --
+ >
+
+<!--
+COLGROUP groups a set of COL elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST COLGROUP
+ %attrs; -- %coreattrs, %i18n, %events --
+ span NUMBER 1 -- default number of columns in group --
+ width %MultiLength; #IMPLIED -- default width for enclosed COLs --
+ %cellhalign; -- horizontal alignment in cells --
+ %cellvalign; -- vertical alignment in cells --
+ >
+
+<!--
+ COL elements define the alignment properties for cells in
+ one or more columns.
+
+ The WIDTH attribute specifies the width of the columns, e.g.
+
+ width=64 width in screen pixels
+ width=0.5* relative width of 0.5
+
+ The SPAN attribute causes the attributes of one
+ COL element to apply to more than one column.
+-->
+<!ATTLIST COL -- column groups and properties --
+ %attrs; -- %coreattrs, %i18n, %events --
+ span NUMBER 1 -- COL attributes affect N columns --
+ width %MultiLength; #IMPLIED -- column width specification --
+ %cellhalign; -- horizontal alignment in cells --
+ %cellvalign; -- vertical alignment in cells --
+ >
+
+<!--
+ Use THEAD to duplicate headers when breaking table
+ across page boundaries, or for static headers when
+ TBODY sections are rendered in scrolling panel.
+
+ Use TFOOT to duplicate footers when breaking table
+ across page boundaries, or for static footers when
+ TBODY sections are rendered in scrolling panel.
+
+ Use multiple TBODY sections when rules are needed
+ between groups of table rows.
+-->
+<!ATTLIST (THEAD|TBODY|TFOOT) -- table section --
+ %attrs; -- %coreattrs, %i18n, %events --
+ %cellhalign; -- horizontal alignment in cells --
+ %cellvalign; -- vertical alignment in cells --
+ >
+
+<!ATTLIST TR -- table row --
+ %attrs; -- %coreattrs, %i18n, %events --
+ %cellhalign; -- horizontal alignment in cells --
+ %cellvalign; -- vertical alignment in cells --
+ bgcolor %Color; #IMPLIED -- background color for row --
+ >
+
+
+<!-- Scope is simpler than axes attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- TH is for headers, TD for data, but for cells acting as both use TD -->
+<!ATTLIST (TH|TD) -- header or data cell --
+ %attrs; -- %coreattrs, %i18n, %events --
+ abbr %Text; #IMPLIED -- abbreviation for header cell --
+ axis CDATA #IMPLIED -- names groups of related headers--
+ headers IDREFS #IMPLIED -- list of id's for header cells --
+ scope %Scope; #IMPLIED -- scope covered by header cells --
+ rowspan NUMBER 1 -- number of rows spanned by cell --
+ colspan NUMBER 1 -- number of cols spanned by cell --
+ %cellhalign; -- horizontal alignment in cells --
+ %cellvalign; -- vertical alignment in cells --
+ nowrap (nowrap) #IMPLIED -- suppress word wrap --
+ bgcolor %Color; #IMPLIED -- cell background color --
+ width %Pixels; #IMPLIED -- width for cell --
+ height %Pixels; #IMPLIED -- height for cell --
+ >
+
+<!--================== Document Frames ===================================-->
+
+<!--
+ The content model for HTML documents depends on whether the HEAD is
+ followed by a FRAMESET or BODY element. The widespread omission of
+ the BODY start tag makes it impractical to define the content model
+ without the use of a marked section.
+-->
+
+<!ELEMENT FRAMESET - - ((FRAMESET|FRAME)+ & NOFRAMES?) -- window subdivision-->
+<!ATTLIST FRAMESET
+ %coreattrs; -- id, class, style, title --
+ rows %MultiLengths; #IMPLIED -- list of lengths,
+ default: 100% (1 row) --
+ cols %MultiLengths; #IMPLIED -- list of lengths,
+ default: 100% (1 col) --
+ onload %Script; #IMPLIED -- all the frames have been loaded --
+ onunload %Script; #IMPLIED -- all the frames have been removed --
+ >
+
+<!-- reserved frame names start with "_" otherwise starts with letter -->
+<!ELEMENT FRAME - O EMPTY -- subwindow -->
+<!ATTLIST FRAME
+ %coreattrs; -- id, class, style, title --
+ longdesc %URI; #IMPLIED -- link to long description
+ (complements title) --
+ name CDATA #IMPLIED -- name of frame for targetting --
+ src %URI; #IMPLIED -- source of frame content --
+ frameborder (1|0) 1 -- request frame borders? --
+ marginwidth %Pixels; #IMPLIED -- margin widths in pixels --
+ marginheight %Pixels; #IMPLIED -- margin height in pixels --
+ noresize (noresize) #IMPLIED -- allow users to resize frames? --
+ scrolling (yes|no|auto) auto -- scrollbar or none --
+ >
+
+<!ELEMENT IFRAME - - (%flow;)* -- inline subwindow -->
+<!ATTLIST IFRAME
+ %coreattrs; -- id, class, style, title --
+ longdesc %URI; #IMPLIED -- link to long description
+ (complements title) --
+ name CDATA #IMPLIED -- name of frame for targetting --
+ src %URI; #IMPLIED -- source of frame content --
+ frameborder (1|0) 1 -- request frame borders? --
+ marginwidth %Pixels; #IMPLIED -- margin widths in pixels --
+ marginheight %Pixels; #IMPLIED -- margin height in pixels --
+ scrolling (yes|no|auto) auto -- scrollbar or none --
+ align %IAlign; #IMPLIED -- vertical or horizontal alignment --
+ height %Length; #IMPLIED -- frame height --
+ width %Length; #IMPLIED -- frame width --
+ >
+
+<![ %HTML.Frameset; [
+<!ENTITY % noframes.content "(BODY) -(NOFRAMES)">
+]]>
+
+<!ENTITY % noframes.content "(%flow;)*">
+
+<!ELEMENT NOFRAMES - - %noframes.content;
+ -- alternate content container for non frame-based rendering -->
+<!ATTLIST NOFRAMES
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!--================ Document Head =======================================-->
+<!-- %head.misc; defined earlier on as "SCRIPT|STYLE|META|LINK|OBJECT" -->
+<!ENTITY % head.content "TITLE & ISINDEX? & BASE?">
+
+<!ELEMENT HEAD O O (%head.content;) +(%head.misc;) -- document head -->
+<!ATTLIST HEAD
+ %i18n; -- lang, dir --
+ profile %URI; #IMPLIED -- named dictionary of meta info --
+ >
+
+<!-- The TITLE element is not considered part of the flow of text.
+ It should be displayed, for example as the page header or
+ window title. Exactly one title is required per document.
+ -->
+<!-- Lars: small correction here... -->
+<!--ELEMENT TITLE - - (#PCDATA) -(%head.misc;) -- document title -- -->
+<!ELEMENT TITLE - - (#PCDATA) -- document title -->
+<!ATTLIST TITLE %i18n>
+
+<!ELEMENT ISINDEX - O EMPTY -- single line prompt -->
+<!ATTLIST ISINDEX
+ %coreattrs; -- id, class, style, title --
+ %i18n; -- lang, dir --
+ prompt %Text; #IMPLIED -- prompt message -->
+
+<!ELEMENT BASE - O EMPTY -- document base URI -->
+<!ATTLIST BASE
+ href %URI; #IMPLIED -- URI that acts as base URI --
+ target %FrameTarget; #IMPLIED -- render in this frame --
+ >
+
+<!ELEMENT META - O EMPTY -- generic metainformation -->
+<!ATTLIST META
+ %i18n; -- lang, dir, for use with content --
+ http-equiv NAME #IMPLIED -- HTTP response header name --
+ name NAME #IMPLIED -- metainformation name --
+ content CDATA #REQUIRED -- associated information --
+ scheme CDATA #IMPLIED -- select form of content --
+ >
+
+<!ELEMENT STYLE - - %StyleSheet -- style info -->
+<!ATTLIST STYLE
+ %i18n; -- lang, dir, for use with title --
+ type %ContentType; #REQUIRED -- content type of style language --
+ media %MediaDesc; #IMPLIED -- designed for use with these media --
+ title %Text; #IMPLIED -- advisory title --
+ >
+
+<!ELEMENT SCRIPT - - %Script; -- script statements -->
+<!ATTLIST SCRIPT
+ charset %Charset; #IMPLIED -- char encoding of linked resource --
+ type %ContentType; #REQUIRED -- content type of script language --
+ language CDATA #IMPLIED -- predefined script language name --
+ src %URI; #IMPLIED -- URI for an external script --
+ defer (defer) #IMPLIED -- UA may defer execution of script --
+ event CDATA #IMPLIED -- reserved for possible future use --
+ for %URI; #IMPLIED -- reserved for possible future use --
+ >
+
+<!ELEMENT NOSCRIPT - - (%flow;)*
+ -- alternate content container for non script-based rendering -->
+<!ATTLIST NOSCRIPT
+ %attrs; -- %coreattrs, %i18n, %events --
+ >
+
+<!--================ Document Structure ==================================-->
+<!ENTITY % version "version CDATA %HTML.Version;">
+
+<!--[ %HTML.Frameset; [
+<!ENTITY % html.content "HEAD, FRAMESET">
+]]-->
+
+<!-- Lars: slight correction here: include FRAMESET -->
+<!ENTITY % html.content "HEAD, (BODY|(FRAMESET&NOFRAMES?))">
+
+<!ELEMENT HTML O O (%html.content;) -- document root element -->
+<!ATTLIST HTML
+ %i18n; -- lang, dir --
+ %version;
+ >
diff --git a/khtml/html/dtd.h b/khtml/html/dtd.h
new file mode 100644
index 000000000..4192ce51c
--- /dev/null
+++ b/khtml/html/dtd.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef _DOM_dtd_h_
+#define _DOM_dtd_h_
+
+#include "dom/dom_string.h"
+
+namespace DOM
+{
+
+void addForbidden(int tagId, ushort *forbiddenTags);
+void removeForbidden(int tagId, ushort *forbiddenTags);
+
+enum tagStatus { OPTIONAL, REQUIRED, FORBIDDEN };
+
+bool checkChild(ushort tagID, ushort childID, bool strict = false);
+
+extern const unsigned short tagPriority[];
+extern const tagStatus endTag[];
+
+} //namespace DOM
+#endif
diff --git a/khtml/html/html_baseimpl.cpp b/khtml/html/html_baseimpl.cpp
new file mode 100644
index 000000000..babbac76d
--- /dev/null
+++ b/khtml/html/html_baseimpl.cpp
@@ -0,0 +1,708 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Simon Hausmann (hausmann@kde.org)
+ * (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+// -------------------------------------------------------------------------
+
+#include "html/html_baseimpl.h"
+#include "html/html_documentimpl.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include "rendering/render_frames.h"
+#include "rendering/render_body.h"
+#include "css/cssstyleselector.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/csshelper.h"
+#include "misc/loader.h"
+#include "misc/htmlhashes.h"
+#include "dom/dom_string.h"
+#include "dom/dom_doc.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <kurl.h>
+#include <kdebug.h>
+
+using namespace DOM;
+using namespace khtml;
+
+HTMLBodyElementImpl::HTMLBodyElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc),
+ m_bgSet( false ), m_fgSet( false )
+{
+ m_styleSheet = 0;
+}
+
+HTMLBodyElementImpl::~HTMLBodyElementImpl()
+{
+ if(m_styleSheet) m_styleSheet->deref();
+}
+
+NodeImpl::Id HTMLBodyElementImpl::id() const
+{
+ return ID_BODY;
+}
+
+void HTMLBodyElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+
+ case ATTR_BACKGROUND:
+ {
+ QString url = khtml::parseURL( attr->value() ).string();
+ if (!url.isEmpty()) {
+ url = getDocument()->completeURL( url );
+ addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" );
+ m_bgSet = true;
+ }
+ else {
+ removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE);
+ m_bgSet = false;
+ }
+ break;
+ }
+ case ATTR_MARGINWIDTH: {
+ KHTMLView* w = getDocument()->view();
+ if (w)
+ w->setMarginWidth( -1 ); // unset this, so it doesn't override the setting here
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value() );
+ }
+ /* nobreak; */
+ case ATTR_LEFTMARGIN:
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value() );
+ break;
+ case ATTR_MARGINHEIGHT: {
+ KHTMLView* w = getDocument()->view();
+ if (w)
+ w->setMarginHeight( -1 ); // unset this, so it doesn't override the setting here
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ }
+ /* nobreak */
+ case ATTR_TOPMARGIN:
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ break;
+ case ATTR_BGCOLOR:
+ addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
+ m_bgSet = !attr->value().isNull();
+ break;
+ case ATTR_TEXT:
+ addHTMLColor(CSS_PROP_COLOR, attr->value());
+ m_fgSet = !attr->value().isNull();
+ break;
+ case ATTR_BGPROPERTIES:
+ if ( strcasecmp( attr->value(), "fixed" ) == 0)
+ addCSSProperty(CSS_PROP_BACKGROUND_ATTACHMENT, CSS_VAL_FIXED);
+ break;
+ case ATTR_VLINK:
+ case ATTR_ALINK:
+ case ATTR_LINK:
+ {
+ if(!m_styleSheet) {
+ m_styleSheet = new CSSStyleSheetImpl(this,DOMString(),true);
+ m_styleSheet->ref();
+ }
+ QString aStr;
+ if ( attr->id() == ATTR_LINK )
+ aStr = "a:link";
+ else if ( attr->id() == ATTR_VLINK )
+ aStr = "a:visited";
+ else if ( attr->id() == ATTR_ALINK )
+ aStr = "a:active";
+ aStr += " { color: " + attr->value().string() + "; }";
+ m_styleSheet->parseString(aStr, !getDocument()->inCompatMode());
+ m_styleSheet->setNonCSSHints();
+ if (attached())
+ getDocument()->updateStyleSelector();
+ break;
+ }
+ case ATTR_ONLOAD:
+ getDocument()->setHTMLWindowEventListener(EventImpl::LOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onload", NULL));
+ break;
+ case ATTR_ONUNLOAD:
+ getDocument()->setHTMLWindowEventListener(EventImpl::UNLOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onunload", NULL));
+ break;
+ case ATTR_ONBLUR:
+ getDocument()->setHTMLWindowEventListener(EventImpl::BLUR_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onblur", NULL));
+ break;
+ case ATTR_ONFOCUS:
+ getDocument()->setHTMLWindowEventListener(EventImpl::FOCUS_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onfocus", NULL));
+ break;
+ case ATTR_ONRESIZE:
+ getDocument()->setHTMLWindowEventListener(EventImpl::RESIZE_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onresize", NULL));
+ break;
+ case ATTR_ONKEYUP:
+ getDocument()->setHTMLWindowEventListener(EventImpl::KEYUP_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeyup", NULL));
+ break;
+ case ATTR_ONKEYDOWN:
+ getDocument()->setHTMLWindowEventListener(EventImpl::KEYDOWN_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeydown", NULL));
+ break;
+ case ATTR_ONKEYPRESS:
+ getDocument()->setHTMLWindowEventListener(EventImpl::KEYPRESS_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeypress", NULL));
+ break;
+ case ATTR_ONSCROLL:
+ getDocument()->setHTMLWindowEventListener(EventImpl::SCROLL_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onscroll", NULL));
+ break;
+ case ATTR_NOSAVE:
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLBodyElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+
+ KHTMLView* w = getDocument()->view();
+ if(w && w->marginWidth() != -1) {
+ QString s;
+ s.sprintf( "%d", w->marginWidth() );
+ addCSSLength(CSS_PROP_MARGIN_LEFT, s);
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, s);
+ }
+ if(w && w->marginHeight() != -1) {
+ QString s;
+ s.sprintf( "%d", w->marginHeight() );
+ addCSSLength(CSS_PROP_MARGIN_TOP, s);
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, s);
+ }
+
+ if ( m_bgSet && !m_fgSet )
+ addCSSProperty(CSS_PROP_COLOR, CSS_VAL_BLACK);
+
+ if (m_styleSheet)
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLBodyElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+
+ if (m_styleSheet)
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLBodyElementImpl::attach()
+{
+ assert(!m_render);
+ assert(parentNode());
+
+ RenderStyle* style = getDocument()->styleSelector()->styleForElement(this);
+ style->ref();
+ if (parentNode()->renderer() && style->display() != NONE) {
+ if (style->display() == BLOCK)
+ // only use the quirky class for block display
+ m_render = new (getDocument()->renderArena()) RenderBody(this);
+ else
+ m_render = RenderObject::createObject(this, style);
+ m_render->setStyle(style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+ style->deref();
+
+ NodeBaseImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLFrameElementImpl::HTMLFrameElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+ frameBorder = true;
+ frameBorderSet = false;
+ marginWidth = -1;
+ marginHeight = -1;
+ scrolling = QScrollView::Auto;
+ noresize = false;
+ url = "about:blank";
+}
+
+HTMLFrameElementImpl::~HTMLFrameElementImpl()
+{
+}
+
+NodeImpl::Id HTMLFrameElementImpl::id() const
+{
+ return ID_FRAME;
+}
+
+void HTMLFrameElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_SRC:
+ setLocation(khtml::parseURL(attr->val()));
+ break;
+ case ATTR_FRAMEBORDER:
+ {
+ frameBorder = attr->value().toInt();
+ frameBorderSet = ( attr->val() != 0 );
+ // FIXME: when attached, has no effect
+ }
+ break;
+ case ATTR_MARGINWIDTH:
+ marginWidth = attr->val()->toInt();
+ // FIXME: when attached, has no effect
+ break;
+ case ATTR_MARGINHEIGHT:
+ marginHeight = attr->val()->toInt();
+ // FIXME: when attached, has no effect
+ break;
+ case ATTR_NORESIZE:
+ noresize = true;
+ // FIXME: when attached, has no effect
+ break;
+ case ATTR_SCROLLING:
+ if( strcasecmp( attr->value(), "auto" ) == 0 )
+ scrolling = QScrollView::Auto;
+ else if( strcasecmp( attr->value(), "yes" ) == 0 )
+ scrolling = QScrollView::AlwaysOn;
+ else if( strcasecmp( attr->value(), "no" ) == 0 )
+ scrolling = QScrollView::AlwaysOff;
+ // when attached, has no effect
+ break;
+ case ATTR_ONLOAD:
+ setHTMLEventListener(EventImpl::LOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onload", this));
+ break;
+ case ATTR_ONUNLOAD:
+ setHTMLEventListener(EventImpl::UNLOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onunload", this));
+ break;
+ case ATTR_ID:
+ case ATTR_NAME:
+ // FIXME: if already attached, doesn't change the frame name
+ // FIXME: frame name conflicts, no unique frame name anymore
+ name = attr->value();
+ //fallthrough intentional, let the base handle it
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLFrameElementImpl::attach()
+{
+ assert(!attached());
+ assert(parentNode());
+
+ name = getAttribute(ATTR_NAME);
+ if (name.isNull())
+ name = getAttribute(ATTR_ID);
+
+ // inherit default settings from parent frameset
+ HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
+ while(node)
+ {
+ if(node->id() == ID_FRAMESET)
+ {
+ HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
+ if(!frameBorderSet) frameBorder = frameset->frameBorder();
+ if(!noresize) noresize = frameset->noResize();
+ break;
+ }
+ node = static_cast<HTMLElementImpl*>(node->parentNode());
+ }
+
+ if (parentNode()->renderer() && getDocument()->isURLAllowed(url.string())) {
+ RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if ( _style->display() != NONE ) {
+ m_render = new (getDocument()->renderArena()) RenderFrame(this);
+ m_render->setStyle(_style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+ _style->deref();
+ }
+
+ NodeBaseImpl::attach();
+
+ if (!m_render)
+ return;
+
+ KHTMLView* w = getDocument()->view();
+ if (w) {
+ // we need a unique name for every frame in the frameset. Hope that's unique enough.
+ if(name.isEmpty() || w->part()->frameExists( name.string() ) )
+ name = DOMString(w->part()->requestFrameName());
+
+ // load the frame contents
+ w->part()->requestFrame( static_cast<RenderFrame*>(m_render), url.string(), name.string() );
+ }
+}
+
+void HTMLFrameElementImpl::setLocation( const DOMString& str )
+{
+
+ url = str;
+
+ if( !attached() )
+ return;
+
+ if( !m_render ) {
+ detach();
+ attach();
+ return;
+ }
+
+ if( !getDocument()->isURLAllowed(url.string()) )
+ return;
+
+ // load the frame contents
+ KHTMLView *w = getDocument()->view();
+ if (w) {
+ KHTMLPart *part = w->part()->findFrame( name.string() );
+ if ( part ) {
+ part->openURL( KURL( getDocument()->completeURL( url.string() ) ) );
+ } else {
+ w->part()->requestFrame( static_cast<RenderFrame*>( m_render ), url.string(), name.string() );
+ }
+ }
+}
+
+bool HTMLFrameElementImpl::isFocusable() const
+{
+ return m_render!=0;
+}
+
+void HTMLFrameElementImpl::setFocus(bool received)
+{
+ HTMLElementImpl::setFocus(received);
+ khtml::RenderFrame *renderFrame = static_cast<khtml::RenderFrame *>(m_render);
+ if (!renderFrame || !renderFrame->widget())
+ return;
+ if (received)
+ renderFrame->widget()->setFocus();
+ else
+ renderFrame->widget()->clearFocus();
+}
+
+DocumentImpl* HTMLFrameElementImpl::contentDocument() const
+{
+ if ( !m_render ) return 0;
+
+ RenderPart* render = static_cast<RenderPart*>( m_render );
+
+ if(render->widget() && ::qt_cast<KHTMLView*>( render->widget()) )
+ return static_cast<KHTMLView*>( render->widget() )->part()->xmlDocImpl();
+
+ return 0;
+}
+
+KHTMLPart* HTMLFrameElementImpl::contentPart() const
+{
+ if ( !m_render ) return 0;
+
+ RenderPart* render = static_cast<RenderPart*>( m_render );
+
+ if(render->widget() && ::qt_cast<KHTMLView*>( render->widget()) )
+ return static_cast<KHTMLView*>( render->widget() )->part();
+
+ return 0;
+}
+
+// -------------------------------------------------------------------------
+
+HTMLFrameSetElementImpl::HTMLFrameSetElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+ // default value for rows and cols...
+ m_totalRows = 1;
+ m_totalCols = 1;
+
+ m_rows = m_cols = 0;
+
+ frameborder = true;
+ frameBorderSet = false;
+ m_border = 4;
+ noresize = false;
+
+ m_resizing = false;
+
+ m_onLoad = m_onUnLoad = 0;
+}
+
+HTMLFrameSetElementImpl::~HTMLFrameSetElementImpl()
+{
+ //### this is likely not quite right since we may be effectively "overriding" some old value,
+ //which needs to be recomputed, but this is better than crashing...
+ if (getDocument()) {
+ if (m_onLoad && getDocument()->getHTMLEventListener(EventImpl::LOAD_EVENT) == m_onLoad)
+ getDocument()->setHTMLEventListener(EventImpl::LOAD_EVENT, 0);
+
+ if (m_onUnLoad && getDocument()->getHTMLEventListener(EventImpl::UNLOAD_EVENT) == m_onUnLoad)
+ getDocument()->setHTMLEventListener(EventImpl::UNLOAD_EVENT, 0);
+ }
+
+ delete [] m_rows;
+ delete [] m_cols;
+}
+
+NodeImpl::Id HTMLFrameSetElementImpl::id() const
+{
+ return ID_FRAMESET;
+}
+
+void HTMLFrameSetElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ROWS:
+ if (!attr->val()) break;
+ delete [] m_rows;
+ m_rows = attr->val()->toLengthArray(m_totalRows);
+ setChanged();
+ break;
+ case ATTR_COLS:
+ if (!attr->val()) break;
+ delete [] m_cols;
+ m_cols = attr->val()->toLengthArray(m_totalCols);
+ setChanged();
+ break;
+ case ATTR_FRAMEBORDER:
+ // false or "no" or "0"..
+ if ( attr->value().toInt() == 0 ) {
+ frameborder = false;
+ m_border = 0;
+ }
+ frameBorderSet = true;
+ break;
+ case ATTR_NORESIZE:
+ noresize = true;
+ break;
+ case ATTR_BORDER:
+ m_border = attr->val()->toInt();
+ if(!m_border)
+ frameborder = false;
+ break;
+ case ATTR_ONLOAD:
+ m_onLoad = getDocument()->createHTMLEventListener(attr->value().string(), "onload", this);
+ getDocument()->setHTMLEventListener(EventImpl::LOAD_EVENT, m_onLoad);
+ break;
+ case ATTR_ONUNLOAD:
+ m_onUnLoad = getDocument()->createHTMLEventListener(attr->value().string(), "onunload", this);
+ getDocument()->setHTMLEventListener(EventImpl::UNLOAD_EVENT, m_onUnLoad);
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLFrameSetElementImpl::attach()
+{
+ assert(!attached() );
+ assert(parentNode());
+
+ // inherit default settings from parent frameset
+ HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
+ while(node)
+ {
+ if(node->id() == ID_FRAMESET)
+ {
+ HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
+ if(!frameBorderSet) frameborder = frameset->frameBorder();
+ if(!noresize) noresize = frameset->noResize();
+ break;
+ }
+ node = static_cast<HTMLElementImpl*>(node->parentNode());
+ }
+
+ // ignore display: none
+ if ( parentNode()->renderer() ) {
+ m_render = new (getDocument()->renderArena()) RenderFrameSet(this);
+ m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+
+ NodeBaseImpl::attach();
+}
+
+void HTMLFrameSetElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ if (evt->isMouseEvent() && !noresize && m_render)
+ static_cast<khtml::RenderFrameSet *>(m_render)->userResize(static_cast<MouseEventImpl*>(evt));
+
+ evt->setDefaultHandled();
+ HTMLElementImpl::defaultEventHandler(evt);
+}
+
+void HTMLFrameSetElementImpl::detach()
+{
+ if(attached())
+ // ### send the event when we actually get removed from the doc instead of here
+ getDocument()->dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
+
+ HTMLElementImpl::detach();
+}
+
+void HTMLFrameSetElementImpl::recalcStyle( StyleChange ch )
+{
+ if (changed() && m_render) {
+ m_render->setNeedsLayout(true);
+// m_render->layout();
+ setChanged(false);
+ }
+ HTMLElementImpl::recalcStyle( ch );
+}
+
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLHeadElementImpl::id() const
+{
+ return ID_HEAD;
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLHtmlElementImpl::id() const
+{
+ return ID_HTML;
+}
+
+
+// -------------------------------------------------------------------------
+
+HTMLIFrameElementImpl::HTMLIFrameElementImpl(DocumentImpl *doc) : HTMLFrameElementImpl(doc)
+{
+ frameBorder = false;
+ marginWidth = 0;
+ marginHeight = 0;
+ needWidgetUpdate = false;
+ m_frame = true;
+}
+
+HTMLIFrameElementImpl::~HTMLIFrameElementImpl()
+{
+}
+
+NodeImpl::Id HTMLIFrameElementImpl::id() const
+{
+ return ID_IFRAME;
+}
+
+void HTMLIFrameElementImpl::parseAttribute(AttributeImpl *attr )
+{
+ switch ( attr->id() )
+ {
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_SRC:
+ needWidgetUpdate = true; // ### do this for scrolling, margins etc?
+ HTMLFrameElementImpl::parseAttribute( attr );
+ break;
+ case ATTR_FRAMEBORDER:
+ {
+ m_frame = (!attr->val() || attr->value().toInt() > 0);
+ if (attached()) updateFrame();
+ }
+ default:
+ HTMLFrameElementImpl::parseAttribute( attr );
+ }
+}
+
+void HTMLIFrameElementImpl::updateFrame()
+{
+ if (m_frame) {
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_OUTSET);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_OUTSET);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_OUTSET);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_OUTSET);
+ addCSSLength(CSS_PROP_BORDER_WIDTH, "2");
+ } else {
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_NONE);
+ removeCSSProperty(CSS_PROP_BORDER_WIDTH);
+ }
+
+}
+
+void HTMLIFrameElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ updateFrame();
+ name = getAttribute(ATTR_NAME);
+ if (name.isNull())
+ name = getAttribute(ATTR_ID);
+
+ RenderStyle* style = getDocument()->styleSelector()->styleForElement(this);
+ style->ref();
+ if (getDocument()->isURLAllowed(url.string()) &&
+ parentNode()->renderer() && style->display() != NONE) {
+ m_render = new (getDocument()->renderArena()) RenderPartObject(this);
+ m_render->setStyle(style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+ style->deref();
+
+ NodeBaseImpl::attach();
+
+ if (m_render) {
+ // we need a unique name for every frame in the frameset. Hope that's unique enough.
+ KHTMLView* w = getDocument()->view();
+ if(w && (name.isEmpty() || w->part()->frameExists( name.string() )))
+ name = DOMString(w->part()->requestFrameName());
+
+ needWidgetUpdate = false;
+ static_cast<RenderPartObject*>(m_render)->updateWidget();
+ }
+}
+
+void HTMLIFrameElementImpl::recalcStyle( StyleChange ch )
+{
+ if (needWidgetUpdate) {
+ needWidgetUpdate = false;
+ if(m_render) static_cast<RenderPartObject*>(m_render)->updateWidget();
+ }
+ HTMLElementImpl::recalcStyle( ch );
+}
+
diff --git a/khtml/html/html_baseimpl.h b/khtml/html/html_baseimpl.h
new file mode 100644
index 000000000..f30dc81f6
--- /dev/null
+++ b/khtml/html/html_baseimpl.h
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2002 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef HTML_BASEIMPL_H
+#define HTML_BASEIMPL_H
+
+#include "html/dtd.h"
+#include "html/html_elementimpl.h"
+#include "misc/khtmllayout.h"
+
+#include <qscrollview.h>
+
+class KHTMLView;
+class KHTMLPart;
+
+namespace khtml {
+ class RenderFrameSet;
+ class RenderFrame;
+ class RenderPartObject;
+}
+
+namespace DOM {
+
+class DOMString;
+class CSSStyleSheetImpl;
+class HTMLFrameElement;
+
+// -------------------------------------------------------------------------
+
+class HTMLBodyElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLBodyElementImpl(DocumentImpl *doc);
+ ~HTMLBodyElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *);
+ virtual void attach();
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
+ CSSStyleSheetImpl *sheet() const { return m_styleSheet; }
+
+protected:
+ CSSStyleSheetImpl *m_styleSheet;
+ bool m_bgSet;
+ bool m_fgSet;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLFrameElementImpl : public HTMLElementImpl
+{
+ friend class khtml::RenderFrame;
+ friend class khtml::RenderPartObject;
+
+public:
+ HTMLFrameElementImpl(DocumentImpl *doc);
+
+ ~HTMLFrameElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *);
+ virtual void attach();
+
+ bool noResize() { return noresize; }
+ void setLocation( const DOMString& str );
+
+ virtual bool isFocusable() const;
+ virtual void setFocus(bool);
+
+ DocumentImpl* contentDocument() const;
+ KHTMLPart* contentPart() const;
+
+ DOMString url;
+ DOMString name;
+
+ int marginWidth;
+ int marginHeight;
+ QScrollView::ScrollBarMode scrolling;
+
+ bool frameBorder : 1;
+ bool frameBorderSet : 1;
+ bool noresize : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLFrameSetElementImpl : public HTMLElementImpl
+{
+ friend class khtml::RenderFrameSet;
+public:
+ HTMLFrameSetElementImpl(DocumentImpl *doc);
+
+ ~HTMLFrameSetElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *);
+ virtual void attach();
+
+ virtual void defaultEventHandler(EventImpl *evt);
+
+ bool frameBorder() { return frameborder; }
+ bool noResize() { return noresize; }
+
+ int totalRows() const { return m_totalRows; }
+ int totalCols() const { return m_totalCols; }
+ int border() const { return m_border; }
+ virtual void detach();
+
+ virtual void recalcStyle( StyleChange ch );
+
+protected:
+ khtml::Length* m_rows;
+ khtml::Length* m_cols;
+
+ int m_totalRows;
+ int m_totalCols;
+ int m_border;
+
+ bool frameborder : 1;
+ bool frameBorderSet : 1;
+ bool noresize : 1;
+ bool m_resizing : 1; // is the user resizing currently
+
+ EventListener* m_onLoad;
+ EventListener* m_onUnLoad;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLHeadElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLHeadElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLHtmlElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLHtmlElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+};
+
+
+// -------------------------------------------------------------------------
+
+class HTMLIFrameElementImpl : public HTMLFrameElementImpl
+{
+public:
+ HTMLIFrameElementImpl(DocumentImpl *doc);
+
+ ~HTMLIFrameElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+ virtual void recalcStyle( StyleChange ch );
+
+protected:
+
+ void updateFrame();
+
+ bool needWidgetUpdate;
+ bool m_frame;
+};
+
+
+} //namespace
+
+#endif
+
diff --git a/khtml/html/html_blockimpl.cpp b/khtml/html/html_blockimpl.cpp
new file mode 100644
index 000000000..ac6d6436c
--- /dev/null
+++ b/khtml/html/html_blockimpl.cpp
@@ -0,0 +1,371 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2003 Apple Computer, Inc.
+ * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+// -------------------------------------------------------------------------
+//#define DEBUG
+#include "html_blockimpl.h"
+#include "html_documentimpl.h"
+#include "css/cssstyleselector.h"
+
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "misc/htmlhashes.h"
+
+#include <kdebug.h>
+
+using namespace khtml;
+using namespace DOM;
+
+void HTMLDivElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ALIGN:
+ {
+ DOMString v = attr->value().lower();
+ if ( strcmp( v, "middle" ) == 0 || strcmp( v, "center" ) == 0 )
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
+ else if (strcmp(v, "left") == 0)
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
+ else if (strcmp(v, "right") == 0)
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
+ else
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, v);
+ break;
+ }
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLHRElementImpl::id() const
+{
+ return ID_HR;
+}
+
+void HTMLHRElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch( attr->id() )
+ {
+ case ATTR_ALIGN: {
+ if (strcasecmp(attr->value(), "left") == 0) {
+ addCSSProperty(CSS_PROP_MARGIN_LEFT, "0");
+ addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
+ }
+ else if (strcasecmp(attr->value(), "right") == 0) {
+ addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
+ addCSSProperty(CSS_PROP_MARGIN_RIGHT, "0");
+ }
+ else {
+ addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
+ addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
+ }
+ break;
+ }
+ case ATTR_WIDTH:
+ {
+ if(!attr->val()) break;
+ // cheap hack to cause linebreaks
+ // khtmltests/html/strange_hr.html
+ bool ok;
+ int v = attr->val()->toInt(&ok);
+ if(ok && !v)
+ addCSSLength(CSS_PROP_WIDTH, "1");
+ else
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ }
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// ### make sure we undo what we did during detach
+void HTMLHRElementImpl::attach()
+{
+ if (attributes(true /* readonly */)) {
+ // there are some attributes, lets check
+ DOMString color = getAttribute(ATTR_COLOR);
+ DOMStringImpl* si = getAttribute(ATTR_SIZE).implementation();
+ int _s = si ? si->toInt() : -1;
+ DOMString n("1");
+ if (!color.isNull()) {
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString("0"));
+ addCSSLength(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString(si));
+ addHTMLColor(CSS_PROP_BORDER_COLOR, color);
+ }
+ else {
+ if (_s > 1 && getAttribute(ATTR_NOSHADE).isNull()) {
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, n);
+ addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, n);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_WIDTH, n);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_WIDTH, n);
+ addCSSLength(CSS_PROP_HEIGHT, DOMString(QString::number(_s-2)));
+ }
+ else if (_s >= 0) {
+ addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString(QString::number(_s)));
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString("0"));
+ }
+ }
+ if (_s == 0)
+ addCSSProperty(CSS_PROP_MARGIN_BOTTOM, n);
+ }
+
+ HTMLElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+long HTMLPreElementImpl::width() const
+{
+ // ###
+ return 0;
+}
+
+void HTMLPreElementImpl::setWidth( long /*w*/ )
+{
+ // ###
+}
+
+// -------------------------------------------------------------------------
+
+ // WinIE uses 60ms as the minimum delay by default.
+const int defaultMinimumDelay = 60;
+
+HTMLMarqueeElementImpl::HTMLMarqueeElementImpl(DocumentImpl *doc)
+: HTMLElementImpl(doc),
+ m_minimumDelay(defaultMinimumDelay)
+{
+}
+
+NodeImpl::Id HTMLMarqueeElementImpl::id() const
+{
+ return ID_MARQUEE;
+}
+
+void HTMLMarqueeElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_BGCOLOR:
+ if (!attr->value().isEmpty())
+ addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
+ break;
+ case ATTR_VSPACE:
+ if (!attr->value().isEmpty()) {
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ }
+ else {
+ removeCSSProperty(CSS_PROP_MARGIN_TOP);
+ removeCSSProperty(CSS_PROP_MARGIN_BOTTOM);
+ }
+ break;
+ case ATTR_HSPACE:
+ if (!attr->value().isEmpty()) {
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
+ }
+ else {
+ removeCSSProperty(CSS_PROP_MARGIN_LEFT);
+ removeCSSProperty(CSS_PROP_MARGIN_RIGHT);
+ }
+ break;
+ case ATTR_SCROLLAMOUNT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP__KHTML_MARQUEE_INCREMENT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP__KHTML_MARQUEE_INCREMENT);
+ break;
+ case ATTR_SCROLLDELAY:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP__KHTML_MARQUEE_SPEED, attr->value(), true);
+ else
+ removeCSSProperty(CSS_PROP__KHTML_MARQUEE_SPEED);
+ break;
+ case ATTR_LOOP:
+ if (!attr->value().isEmpty()) {
+ if (attr->value() == "-1" || strcasecmp(attr->value(), "infinite") == 0)
+ addCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION, CSS_VAL_INFINITE);
+ else
+ addCSSLength(CSS_PROP__KHTML_MARQUEE_REPETITION, attr->value().lower(), true);
+ }
+ else
+ removeCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION);
+ break;
+ case ATTR_BEHAVIOR:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE);
+ break;
+ case ATTR_DIRECTION:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION);
+ break;
+ case ATTR_TRUESPEED:
+ m_minimumDelay = attr->val() ? 0 : defaultMinimumDelay;
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+HTMLLayerElementImpl::HTMLLayerElementImpl(DocumentImpl *doc, ushort _tagid)
+ : HTMLDivElementImpl( doc, _tagid )
+{
+ transparent = fixed = false;
+}
+
+void HTMLLayerElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ // Layers are evil
+ // They are mainly implemented here to correctly parse the hidden attribute
+ switch(attr->id()) {
+ case ATTR_LEFT:
+ addCSSProperty(CSS_PROP_LEFT, attr->value());
+ break;
+ case ATTR_TOP:
+ addCSSProperty(CSS_PROP_TOP, attr->value());
+ break;
+ case ATTR_PAGEX:
+ if (!transparent && !fixed) {
+ addCSSProperty(CSS_PROP_POSITION, CSS_VAL_FIXED);
+ fixed = true;
+ }
+ addCSSProperty(CSS_PROP_LEFT, attr->value());
+ break;
+ case ATTR_PAGEY:
+ if (!transparent && !fixed) {
+ addCSSProperty(CSS_PROP_POSITION, CSS_VAL_FIXED);
+ fixed = true;
+ }
+ addCSSProperty(CSS_PROP_TOP, attr->value());
+ break;
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_BGCOLOR:
+ if (!attr->value().isEmpty())
+ addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
+ break;
+ case ATTR_Z_INDEX:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP_Z_INDEX, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_Z_INDEX);
+ break;
+ case ATTR_VISIBILITY:
+ if (attr->value().lower() == "show")
+ addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_VISIBLE);
+ else if (attr->value().lower() == "hide")
+ addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_HIDDEN);
+ else if (attr->value().lower() == "inherit")
+ addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_INHERIT);
+ break;
+ case ATTR_NAME:
+ if (id() == ID_LAYER && inDocument() && m_name != attr->value()) {
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ getDocument()->underDocNamedCache().add (attr->value().string(), this);
+ }
+ //fallthrough
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLLayerElementImpl::removedFromDocument()
+{
+ if (id() == ID_LAYER)
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ HTMLDivElementImpl::removedFromDocument();
+}
+
+void HTMLLayerElementImpl::insertedIntoDocument()
+{
+ if (id() == ID_LAYER)
+ getDocument()->underDocNamedCache().add(m_name.string(), this);
+ HTMLDivElementImpl::insertedIntoDocument();
+}
+
+void HTMLLayerElementImpl::removeId(const QString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLDivElementImpl::removeId(id);
+}
+
+void HTMLLayerElementImpl::addId (const QString& id)
+{
+ getDocument()->underDocNamedCache().add(id, this);
+ HTMLDivElementImpl::addId(id);
+}
+
+
+
+NodeImpl *HTMLLayerElementImpl::addChild(NodeImpl *child)
+{
+ NodeImpl *retval = HTMLDivElementImpl::addChild(child);
+ // When someone adds standard layers, we make sure not to interfere
+ if (retval && retval->id() == ID_DIV) {
+ if (!transparent)
+ addCSSProperty(CSS_PROP_POSITION, CSS_VAL_STATIC);
+ transparent = true;
+ }
+ return retval;
+}
diff --git a/khtml/html/html_blockimpl.h b/khtml/html/html_blockimpl.h
new file mode 100644
index 000000000..a3a1b8994
--- /dev/null
+++ b/khtml/html/html_blockimpl.h
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// -------------------------------------------------------------------------
+#ifndef HTML_BLOCKIMPL_H
+#define HTML_BLOCKIMPL_H
+
+#include "html_elementimpl.h"
+#include "dtd.h"
+
+namespace DOM {
+
+// -------------------------------------------------------------------------
+
+class HTMLDivElementImpl : public HTMLGenericElementImpl
+{
+public:
+ HTMLDivElementImpl(DocumentImpl *doc, ushort _tagid)
+ : HTMLGenericElementImpl(doc, _tagid) {}
+
+ virtual void parseAttribute(AttributeImpl *token);
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLHRElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLHRElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual NodeImpl::Id id() const;
+ virtual void parseAttribute(AttributeImpl *);
+ virtual void attach();
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLPreElementImpl : public HTMLGenericElementImpl
+{
+public:
+ HTMLPreElementImpl(DocumentImpl *doc, ushort _tagid)
+ : HTMLGenericElementImpl(doc, _tagid) {}
+
+ long width() const;
+ void setWidth( long w );
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLMarqueeElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLMarqueeElementImpl(DocumentImpl *doc);
+
+ virtual NodeImpl::Id id() const;
+ virtual void parseAttribute(AttributeImpl *token);
+
+ int minimumDelay() const { return m_minimumDelay; }
+
+private:
+ int m_minimumDelay;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLLayerElementImpl : public HTMLDivElementImpl
+{
+public:
+ HTMLLayerElementImpl( DocumentImpl *doc, ushort _tagid );
+
+ virtual void parseAttribute(AttributeImpl *);
+ virtual NodeImpl *addChild(NodeImpl *child);
+
+ virtual void removedFromDocument();
+ virtual void insertedIntoDocument();
+ virtual void addId(const QString& id);
+ virtual void removeId(const QString& id);
+private:
+ DOMString m_name;
+ bool fixed;
+ bool transparent;
+};
+
+} //namespace
+#endif
+
diff --git a/khtml/html/html_documentimpl.cpp b/khtml/html/html_documentimpl.cpp
new file mode 100644
index 000000000..59ec6859f
--- /dev/null
+++ b/khtml/html/html_documentimpl.cpp
@@ -0,0 +1,537 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "html/html_documentimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_headimpl.h"
+#include "html/html_baseimpl.h"
+#include "html/htmltokenizer.h"
+#include "html/html_miscimpl.h"
+#include "html/html_formimpl.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "khtmlpart_p.h"
+#include "khtml_settings.h"
+#include "misc/htmlattrs.h"
+#include "misc/htmlhashes.h"
+
+#include "xml/xml_tokenizer.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include "khtml_factory.h"
+#include "rendering/render_object.h"
+#include "dom/dom_exception.h"
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <kglobal.h>
+#include <kcharsets.h>
+#include <kglobalsettings.h>
+
+#include "css/cssproperties.h"
+#include "css/cssstyleselector.h"
+#include "css/css_stylesheetimpl.h"
+#include <stdlib.h>
+#include <qptrstack.h>
+
+// Turn off inlining to avoid warning with newer gcc.
+#undef __inline
+#define __inline
+#include "doctypes.cpp"
+#undef __inline
+
+template class QPtrStack<DOM::NodeImpl>;
+
+using namespace DOM;
+using namespace khtml;
+
+
+HTMLDocumentImpl::HTMLDocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
+ : DocumentImpl(_implementation, v)
+{
+// kdDebug( 6090 ) << "HTMLDocumentImpl constructor this = " << this << endl;
+ htmlElement = 0;
+
+ m_doAutoFill = false;
+
+/* dynamic history stuff to be fixed later (pfeiffer)
+ connect( KHTMLFactory::vLinks(), SIGNAL( removed( const QString& )),
+ SLOT( slotHistoryChanged() ));
+*/
+ connect( KHTMLFactory::vLinks(), SIGNAL( inserted( const QString& ) ),
+ SLOT( slotHistoryChanged() ));
+ connect( KHTMLFactory::vLinks(), SIGNAL( cleared()),
+ SLOT( slotHistoryChanged() ));
+}
+
+HTMLDocumentImpl::~HTMLDocumentImpl()
+{
+}
+
+DOMString HTMLDocumentImpl::referrer() const
+{
+ if ( view() )
+ return view()->part()->pageReferrer();
+ return DOMString();
+}
+
+DOMString HTMLDocumentImpl::lastModified() const
+{
+ if ( view() )
+ return view()->part()->lastModified();
+ return DOMString();
+}
+
+DOMString HTMLDocumentImpl::cookie() const
+{
+ long windowId = 0;
+ KHTMLView *v = view ();
+
+ if ( v && v->topLevelWidget() )
+ windowId = v->topLevelWidget()->winId();
+
+ QCString replyType;
+ QByteArray params, reply;
+ QDataStream stream(params, IO_WriteOnly);
+ stream << URL().url() << windowId;
+ if (!kapp->dcopClient()->call("kcookiejar", "kcookiejar",
+ "findDOMCookies(QString,long int)", params,
+ replyType, reply))
+ {
+ kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
+ return DOMString();
+ }
+
+ QDataStream stream2(reply, IO_ReadOnly);
+ if(replyType != "QString") {
+ kdError(6010) << "DCOP function findDOMCookies(...) returns "
+ << replyType << ", expected QString" << endl;
+ return DOMString();
+ }
+
+ QString result;
+ stream2 >> result;
+ return DOMString(result);
+}
+
+void HTMLDocumentImpl::setCookie( const DOMString & value )
+{
+ long windowId = 0;
+ KHTMLView *v = view ();
+
+ if ( v && v->topLevelWidget() )
+ windowId = v->topLevelWidget()->winId();
+
+ QByteArray params;
+ QDataStream stream(params, IO_WriteOnly);
+ QCString fake_header("Set-Cookie: ");
+ fake_header.append(value.string().latin1());
+ fake_header.append("\n");
+ stream << URL().url() << fake_header << windowId;
+ if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
+ "addCookies(QString,QCString,long int)", params))
+ {
+ // Maybe it wasn't running (e.g. we're opening local html files)
+ KApplication::startServiceByDesktopName( "kcookiejar");
+ if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
+ "addCookies(QString,QCString,long int)", params))
+ kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
+ }
+}
+
+
+
+HTMLElementImpl *HTMLDocumentImpl::body()
+{
+ NodeImpl *de = documentElement();
+ if (!de)
+ return 0;
+
+ // try to prefer a FRAMESET element over BODY
+ NodeImpl* body = 0;
+ for (NodeImpl* i = de->firstChild(); i; i = i->nextSibling()) {
+ if (i->id() == ID_FRAMESET)
+ return static_cast<HTMLElementImpl*>(i);
+
+ if (i->id() == ID_BODY)
+ body = i;
+ }
+ return static_cast<HTMLElementImpl *>(body);
+}
+
+void HTMLDocumentImpl::setBody(HTMLElementImpl *_body, int& exceptioncode)
+{
+ HTMLElementImpl *b = body();
+ if ( !_body ) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ if ( !b )
+ documentElement()->appendChild( _body, exceptioncode );
+ else
+ documentElement()->replaceChild( _body, b, exceptioncode );
+}
+
+Tokenizer *HTMLDocumentImpl::createTokenizer()
+{
+ return new HTMLTokenizer(docPtr(),m_view);
+}
+
+// --------------------------------------------------------------------------
+// not part of the DOM
+// --------------------------------------------------------------------------
+
+bool HTMLDocumentImpl::childAllowed( NodeImpl *newChild )
+{
+ // ### support comments. etc as a child
+ return (newChild->id() == ID_HTML || newChild->id() == ID_COMMENT);
+}
+
+ElementImpl *HTMLDocumentImpl::createElement( const DOMString &name, int* pExceptioncode )
+{
+ ElementImpl *e = createHTMLElement(name);
+ if ( e ) {
+ e->setHTMLCompat( htmlMode() != XHtml );
+ return e;
+ }
+ return DocumentImpl::createElement(name, pExceptioncode);
+}
+
+void HTMLDocumentImpl::slotHistoryChanged()
+{
+ if ( true || !m_render )
+ return;
+
+ recalcStyle( Force );
+ m_render->repaint();
+}
+
+HTMLMapElementImpl* HTMLDocumentImpl::getMap(const DOMString& _url)
+{
+ QString url = _url.string();
+ QString s;
+ int pos = url.find('#');
+ //kdDebug(0) << "map pos of #:" << pos << endl;
+ s = QString(_url.unicode() + pos + 1, _url.length() - pos - 1);
+
+ QMapConstIterator<QString,HTMLMapElementImpl*> it = mapMap.find(s);
+
+ if (it != mapMap.end())
+ return *it;
+ else
+ return 0;
+}
+
+void HTMLDocumentImpl::close()
+{
+ bool doload = !parsing() && m_tokenizer;
+
+ DocumentImpl::close();
+
+ if (doload) {
+
+ if (title().isEmpty()) // ensure setTitle is called at least once
+ setTitle( DOMString() );
+
+ // auto fill: walk the tree and try to fill in login credentials
+ if (view() && m_doAutoFill) {
+ for (NodeImpl* n = this; n; n = n->traverseNextNode())
+ if (n->id() == ID_FORM)
+ static_cast<HTMLFormElementImpl*>(n)->doAutoFill();
+ m_doAutoFill = false;
+ }
+
+ // According to dom the load event must not bubble
+ // but other browsers execute in a frameset document
+ // the first(IE)/last(Moz/Konq) registered onload on a <frame> and the
+ // first(IE)/last(Moz/Konq) registered onload on a <frameset>.
+
+ //kdDebug() << "dispatching LOAD_EVENT on document " << getDocument() << " " << (view()?view()->part()->name():0) << endl;
+
+ //Make sure to flush any pending image events now, as we want them out before the document's load event
+ dispatchImageLoadEventsNow();
+ getDocument()->dispatchWindowEvent(EventImpl::LOAD_EVENT, false, false);
+
+ // don't update rendering if we're going to redirect anyway
+ if ( view() && ( view()->part()->d->m_redirectURL.isNull() ||
+ view()->part()->d->m_delayRedirect > 1 ) )
+ updateRendering();
+ }
+}
+
+
+const int PARSEMODE_HAVE_DOCTYPE = (1<<0);
+const int PARSEMODE_HAVE_PUBLIC_ID = (1<<1);
+const int PARSEMODE_HAVE_SYSTEM_ID = (1<<2);
+const int PARSEMODE_HAVE_INTERNAL = (1<<3);
+
+static int parseDocTypePart(const QString& buffer, int index)
+{
+ while (true) {
+ QChar ch = buffer[index];
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ ++index;
+ else if (ch == '-') {
+ int tmpIndex=index;
+ if (buffer[index+1] == '-' &&
+ ((tmpIndex=buffer.find("--", index+2)) != -1))
+ index = tmpIndex+2;
+ else
+ return index;
+ }
+ else
+ return index;
+ }
+}
+
+static bool containsString(const char* str, const QString& buffer, int offset)
+{
+ QString startString(str);
+ if (offset + startString.length() > buffer.length())
+ return false;
+
+ QString bufferString = buffer.mid(offset, startString.length()).lower();
+ QString lowerStart = startString.lower();
+
+ return bufferString.startsWith(lowerStart);
+}
+
+static bool parseDocTypeDeclaration(const QString& buffer,
+ int* resultFlags,
+ QString& publicID,
+ QString& systemID)
+{
+ bool haveDocType = false;
+ *resultFlags = 0;
+
+ // Skip through any comments and processing instructions.
+ int index = 0;
+ do {
+ index = buffer.find('<', index);
+ if (index == -1) break;
+ QChar nextChar = buffer[index+1];
+ if (nextChar == '!') {
+ if (containsString("doctype", buffer, index+2)) {
+ haveDocType = true;
+ index += 9; // Skip "<!DOCTYPE"
+ break;
+ }
+ index = parseDocTypePart(buffer,index);
+ index = buffer.find('>', index);
+ }
+ else if (nextChar == '?')
+ index = buffer.find('>', index);
+ else
+ break;
+ } while (index != -1);
+
+ if (!haveDocType)
+ return true;
+ *resultFlags |= PARSEMODE_HAVE_DOCTYPE;
+
+ index = parseDocTypePart(buffer, index);
+ if (!containsString("html", buffer, index))
+ return false;
+
+ index = parseDocTypePart(buffer, index+4);
+ bool hasPublic = containsString("public", buffer, index);
+ if (hasPublic) {
+ index = parseDocTypePart(buffer, index+6);
+
+ // We've read <!DOCTYPE HTML PUBLIC (not case sensitive).
+ // Now we find the beginning and end of the public identifers
+ // and system identifiers (assuming they're even present).
+ QChar theChar = buffer[index];
+ if (theChar != '\"' && theChar != '\'')
+ return false;
+
+ // |start| is the first character (after the quote) and |end|
+ // is the final quote, so there are |end|-|start| characters.
+ int publicIDStart = index+1;
+ int publicIDEnd = buffer.find(theChar, publicIDStart);
+ if (publicIDEnd == -1)
+ return false;
+ index = parseDocTypePart(buffer, publicIDEnd+1);
+ QChar next = buffer[index];
+ if (next == '>') {
+ // Public identifier present, but no system identifier.
+ // Do nothing. Note that this is the most common
+ // case.
+ }
+ else if (next == '\"' || next == '\'') {
+ // We have a system identifier.
+ *resultFlags |= PARSEMODE_HAVE_SYSTEM_ID;
+ int systemIDStart = index+1;
+ int systemIDEnd = buffer.find(next, systemIDStart);
+ if (systemIDEnd == -1)
+ return false;
+ systemID = buffer.mid(systemIDStart, systemIDEnd - systemIDStart);
+ }
+ else if (next == '[') {
+ // We found an internal subset.
+ *resultFlags |= PARSEMODE_HAVE_INTERNAL;
+ }
+ else
+ return false; // Something's wrong.
+
+ // We need to trim whitespace off the public identifier.
+ publicID = buffer.mid(publicIDStart, publicIDEnd - publicIDStart);
+ publicID = publicID.simplifyWhiteSpace();
+ *resultFlags |= PARSEMODE_HAVE_PUBLIC_ID;
+ } else {
+ if (containsString("system", buffer, index)) {
+ // Doctype has a system ID but no public ID
+ *resultFlags |= PARSEMODE_HAVE_SYSTEM_ID;
+ index = parseDocTypePart(buffer, index+6);
+ QChar next = buffer[index];
+ if (next != '\"' && next != '\'')
+ return false;
+ int systemIDStart = index+1;
+ int systemIDEnd = buffer.find(next, systemIDStart);
+ if (systemIDEnd == -1)
+ return false;
+ systemID = buffer.mid(systemIDStart, systemIDEnd - systemIDStart);
+ index = parseDocTypePart(buffer, systemIDEnd+1);
+ }
+
+ QChar nextChar = buffer[index];
+ if (nextChar == '[')
+ *resultFlags |= PARSEMODE_HAVE_INTERNAL;
+ else if (nextChar != '>')
+ return false;
+ }
+
+ return true;
+}
+
+void HTMLDocumentImpl::determineParseMode( const QString &str )
+{
+ //kdDebug() << "DocumentImpl::determineParseMode str=" << str<< endl;
+ int oldPMode = pMode;
+
+ // This code more or less mimics Mozilla's implementation (specifically the
+ // doctype parsing implemented by David Baron in Mozilla's nsParser.cpp).
+ //
+ // There are three possible parse modes:
+ // COMPAT - quirks mode emulates WinIE
+ // and NS4. CSS parsing is also relaxed in this mode, e.g., unit types can
+ // be omitted from numbers.
+ // ALMOST STRICT - This mode is identical to strict mode
+ // except for its treatment of line-height in the inline box model. For
+ // now (until the inline box model is re-written), this mode is identical
+ // to STANDARDS mode.
+ // STRICT - no quirks apply. Web pages will obey the specifications to
+ // the letter.
+
+ QString systemID, publicID;
+ int resultFlags = 0;
+ if (parseDocTypeDeclaration(str, &resultFlags, publicID, systemID)) {
+ if (resultFlags & PARSEMODE_HAVE_DOCTYPE) {
+ m_doctype->setName("HTML");
+ m_doctype->setPublicId(publicID);
+ m_doctype->setSystemId(systemID);
+ }
+ if (!(resultFlags & PARSEMODE_HAVE_DOCTYPE)) {
+ // No doctype found at all. Default to quirks mode and Html4.
+ pMode = Compat;
+ hMode = Html4;
+ }
+ else if ((resultFlags & PARSEMODE_HAVE_INTERNAL) ||
+ !(resultFlags & PARSEMODE_HAVE_PUBLIC_ID)) {
+ // Internal subsets always denote full standards, as does
+ // a doctype without a public ID.
+ pMode = Strict;
+ hMode = Html4;
+ }
+ else {
+ // We have to check a list of public IDs to see what we
+ // should do.
+ QString lowerPubID = publicID.lower();
+ const char* pubIDStr = lowerPubID.latin1();
+
+ // Look up the entry in our gperf-generated table.
+ const PubIDInfo* doctypeEntry = findDoctypeEntry(pubIDStr, publicID.length());
+ if (!doctypeEntry) {
+ // The DOCTYPE is not in the list. Assume strict mode.
+ // ### Doesn't make any sense, but it's what Mozilla does.
+ pMode = Strict;
+ hMode = Html4;
+ return;
+ }
+
+ switch ((resultFlags & PARSEMODE_HAVE_SYSTEM_ID) ?
+ doctypeEntry->mode_if_sysid :
+ doctypeEntry->mode_if_no_sysid)
+ {
+ case PubIDInfo::eQuirks3:
+ pMode = Compat;
+ hMode = Html3;
+ break;
+ case PubIDInfo::eQuirks:
+ pMode = Compat;
+ hMode = Html4;
+ break;
+ case PubIDInfo::eAlmostStandards:
+ pMode = Transitional;
+ hMode = Html4;
+ break;
+ default:
+ assert(false);
+ }
+ }
+ }
+ else {
+ // Malformed doctype implies quirks mode.
+ pMode = Compat;
+ hMode = Html3;
+ }
+
+ // This needs to be done last, see tests/parser/compatmode_xhtml_mixed.html
+ if ( hMode == Html4 && !m_htmlRequested ) {
+ // this part is still debatable and possibly UA dependent
+ hMode = XHtml;
+ pMode = Transitional;
+ }
+
+ m_styleSelector->strictParsing = !inCompatMode();
+
+ // kdDebug() << "DocumentImpl::determineParseMode: publicId =" << publicID << " systemId = " << systemID << endl;
+ // kdDebug() << "DocumentImpl::determineParseMode: htmlMode = " << hMode<< endl;
+ if( pMode == Strict )
+ kdDebug(6030) << " using strict parseMode" << endl;
+ else if (pMode == Compat )
+ kdDebug(6030) << " using compatibility parseMode" << endl;
+ else
+ kdDebug(6030) << " using transitional parseMode" << endl;
+
+ // not sure this is needed
+ if ( pMode != oldPMode && styleSelector() )
+ recalcStyleSelector();
+
+}
+
+
+#include "html_documentimpl.moc"
diff --git a/khtml/html/html_documentimpl.h b/khtml/html/html_documentimpl.h
new file mode 100644
index 000000000..20f9ddb2f
--- /dev/null
+++ b/khtml/html/html_documentimpl.h
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef HTML_DOCUMENTIMPL_H
+#define HTML_DOCUMENTIMPL_H
+
+#include "xml/dom_docimpl.h"
+#include "html/html_miscimpl.h"
+
+#include <qmap.h>
+
+class KHTMLView;
+class QString;
+
+namespace DOM {
+
+ class Element;
+ class HTMLElement;
+ class HTMLElementImpl;
+ class DOMString;
+ class CSSStyleSheetImpl;
+ class HTMLMapElementImpl;
+
+class HTMLDocumentImpl : public DOM::DocumentImpl
+{
+ Q_OBJECT
+public:
+ HTMLDocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v = 0);
+ ~HTMLDocumentImpl();
+
+ virtual bool isHTMLDocument() const { return true; }
+
+ DOMString referrer() const;
+ DOMString lastModified() const;
+ DOMString cookie() const;
+ void setCookie( const DOMString &);
+
+ HTMLElementImpl *body();
+ void setBody(HTMLElementImpl *_body, int& exceptioncode);
+
+ virtual khtml::Tokenizer *createTokenizer();
+
+ virtual bool childAllowed( NodeImpl *newChild );
+
+ virtual ElementImpl *createElement ( const DOMString &tagName, int* pExceptioncode );
+
+ HTMLMapElementImpl* getMap(const DOMString& url_);
+
+ virtual void determineParseMode( const QString &str );
+ virtual void close();
+
+ void setAutoFill() { m_doAutoFill = true; }
+
+ // If true, HTML was requested by mimetype (e.g. HTTP Content-Type). Otherwise XHTML was requested.
+ // This is independent of the actual doctype, of course. (#86446)
+ void setHTMLRequested( bool html ) { m_htmlRequested = html; }
+
+protected:
+ HTMLElementImpl *htmlElement;
+ friend class HTMLMapElementImpl;
+ friend class HTMLImageElementImpl;
+ QMap<QString,HTMLMapElementImpl*> mapMap;
+ bool m_doAutoFill;
+ bool m_htmlRequested;
+
+protected slots:
+ /**
+ * Repaints, so that all links get the proper color
+ */
+ void slotHistoryChanged();
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_elementimpl.cpp b/khtml/html/html_elementimpl.cpp
new file mode 100644
index 000000000..9c0e58335
--- /dev/null
+++ b/khtml/html/html_elementimpl.cpp
@@ -0,0 +1,678 @@
+// -*- c-basic-offset: 4; -*-
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+// -------------------------------------------------------------------------
+//#define DEBUG
+//#define DEBUG_LAYOUT
+//#define PAR_DEBUG
+//#define EVENT_DEBUG
+//#define UNSUPPORTED_ATTR
+
+#include "html/dtd.h"
+#include "html/html_elementimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/htmltokenizer.h"
+
+#include "misc/htmlhashes.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include "rendering/render_object.h"
+#include "rendering/render_replaced.h"
+#include "css/css_valueimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include "html_elementimpl.h"
+
+using namespace DOM;
+using namespace khtml;
+
+HTMLElementImpl::HTMLElementImpl(DocumentImpl *doc)
+ : ElementImpl( doc )
+{
+ m_htmlCompat = doc && doc->htmlMode() != DocumentImpl::XHtml;
+}
+
+HTMLElementImpl::~HTMLElementImpl()
+{
+}
+
+bool HTMLElementImpl::isInline() const
+{
+ if (renderer())
+ return ElementImpl::isInline();
+
+ switch(id()) {
+ case ID_A:
+ case ID_FONT:
+ case ID_TT:
+ case ID_U:
+ case ID_B:
+ case ID_I:
+ case ID_S:
+ case ID_STRIKE:
+ case ID_BIG:
+ case ID_SMALL:
+
+ // %phrase
+ case ID_EM:
+ case ID_STRONG:
+ case ID_DFN:
+ case ID_CODE:
+ case ID_SAMP:
+ case ID_KBD:
+ case ID_VAR:
+ case ID_CITE:
+ case ID_ABBR:
+ case ID_ACRONYM:
+
+ // %special
+ case ID_SUB:
+ case ID_SUP:
+ case ID_SPAN:
+ case ID_NOBR:
+ case ID_WBR:
+ return true;
+
+ default:
+ return ElementImpl::isInline();
+ }
+}
+
+DOMString HTMLElementImpl::namespaceURI() const
+{
+ return (!m_htmlCompat) ?
+ DOMString(XHTML_NAMESPACE) : DOMString();
+}
+
+
+DOMString HTMLElementImpl::localName() const
+{
+ // We only have a localName if we were created by createElementNS(), in which
+ // case we are an XHTML element. This also means we have a lowercase name.
+ if (!m_htmlCompat) // XHTML == not HTMLCompat
+ {
+ NodeImpl::Id _id = id();
+ DOMString tn;
+ if ( _id >= ID_LAST_TAG )
+ tn = getDocument()->getName(ElementId, _id);
+ else // HTML tag
+ tn = getTagName( _id );
+ return tn; // lowercase already
+ }
+ // createElement() always returns elements with a null localName.
+ else
+ return DOMString();
+}
+
+DOMString HTMLElementImpl::tagName() const
+{
+ DOMString tn;
+ NodeImpl::Id _id = id();
+ if ( _id >= ID_LAST_TAG )
+ tn = getDocument()->getName(ElementId, _id);
+ else // HTML tag
+ tn = getTagName( _id );
+
+ if ( m_htmlCompat )
+ tn = tn.upper();
+
+ if (m_prefix)
+ return DOMString(m_prefix) + ":" + tn;
+
+ return tn;
+}
+
+void HTMLElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ DOMString indexstring;
+ switch( attr->id() )
+ {
+ case ATTR_ALIGN:
+ if (attr->val()) {
+ if ( strcasecmp(attr->value(), "middle" ) == 0 )
+ addCSSProperty( CSS_PROP_TEXT_ALIGN, CSS_VAL_CENTER );
+ else
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, attr->value().lower());
+ }
+ else
+ removeCSSProperty(CSS_PROP_TEXT_ALIGN);
+ break;
+// the core attributes...
+ case ATTR_ID:
+ // unique id
+ setHasID();
+ getDocument()->incDOMTreeVersion();
+ break;
+ case ATTR_CLASS:
+ if (attr->val()) {
+ DOMString v = attr->value();
+ const QChar* s = v.unicode();
+ int l = v.length();
+ while( l && !s->isSpace() )
+ l--,s++;
+ setHasClassList(l);
+ setHasClass(true);
+ } else {
+ setHasClassList(false);
+ setHasClass(false);
+ }
+ break;
+ case ATTR_NAME:
+ getDocument()->incDOMTreeVersion();
+ break;
+ case ATTR_STYLE:
+ if (m_styleDecls)
+ m_styleDecls->removeCSSHints();
+ else
+ createDecl();
+ m_styleDecls->setProperty(attr->value());
+ setChanged();
+ break;
+ case ATTR_TABINDEX:
+ indexstring=getAttribute(ATTR_TABINDEX);
+ if (indexstring.length())
+ setTabIndex(indexstring.toInt());
+ break;
+// i18n attributes
+ case ATTR_LANG:
+ break;
+ case ATTR_DIR:
+ addCSSProperty(CSS_PROP_DIRECTION, attr->value().lower());
+ addCSSProperty(CSS_PROP_UNICODE_BIDI, CSS_VAL_EMBED);
+ break;
+// standard events
+ case ATTR_ONCLICK:
+ setHTMLEventListener(EventImpl::KHTML_ECMA_CLICK_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onclick", this));
+ break;
+ case ATTR_ONDBLCLICK:
+ setHTMLEventListener(EventImpl::KHTML_ECMA_DBLCLICK_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "ondblclick", this));
+ break;
+ case ATTR_ONMOUSEDOWN:
+ setHTMLEventListener(EventImpl::MOUSEDOWN_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onmousedown", this));
+ break;
+ case ATTR_ONMOUSEMOVE:
+ setHTMLEventListener(EventImpl::MOUSEMOVE_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onmousemove", this));
+ break;
+ case ATTR_ONMOUSEOUT:
+ setHTMLEventListener(EventImpl::MOUSEOUT_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onmouseout", this));
+ break;
+ case ATTR_ONMOUSEOVER:
+ setHTMLEventListener(EventImpl::MOUSEOVER_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onmouseover", this));
+ break;
+ case ATTR_ONMOUSEUP:
+ setHTMLEventListener(EventImpl::MOUSEUP_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onmouseup", this));
+ break;
+ case ATTR_ONKEYDOWN:
+ setHTMLEventListener(EventImpl::KEYDOWN_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeydown", this));
+ break;
+ case ATTR_ONKEYPRESS:
+ setHTMLEventListener(EventImpl::KEYPRESS_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeypress", this));
+ break;
+ case ATTR_ONKEYUP:
+ setHTMLEventListener(EventImpl::KEYUP_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onkeyup", this));
+ break;
+ case ATTR_ONFOCUS:
+ setHTMLEventListener(EventImpl::FOCUS_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onfocus", this));
+ break;
+ case ATTR_ONBLUR:
+ setHTMLEventListener(EventImpl::BLUR_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onblur", this));
+ break;
+ case ATTR_ONSCROLL:
+ setHTMLEventListener(EventImpl::SCROLL_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onscroll", this));
+ break;
+// other misc attributes
+ default:
+#ifdef UNSUPPORTED_ATTR
+ kdDebug(6030) << "UATTR: <" << this->nodeName().string() << "> ["
+ << attr->name().string() << "]=[" << attr->value().string() << "]" << endl;
+#endif
+ break;
+ }
+}
+
+void HTMLElementImpl::recalcStyle( StyleChange ch )
+{
+ ElementImpl::recalcStyle( ch );
+
+ if (m_render /*&& changed*/)
+ m_render->updateFromElement();
+}
+
+void HTMLElementImpl::addCSSProperty(int id, const DOMString &value)
+{
+ if(!m_styleDecls) createDecl();
+ m_styleDecls->setProperty(id, value, false, true);
+ setChanged();
+}
+
+void HTMLElementImpl::addCSSProperty(int id, int value)
+{
+ if(!m_styleDecls) createDecl();
+ m_styleDecls->setProperty(id, value, false, true);
+ setChanged();
+}
+
+void HTMLElementImpl::addCSSLength(int id, const DOMString &value, bool numOnly, bool multiLength)
+{
+ if(!m_styleDecls) createDecl();
+
+ // strip attribute garbage to avoid CSS parsing errors
+ // ### create specialized hook that avoids parsing every
+ // value twice!
+ if ( value.implementation() ) {
+ // match \s*[+-]?\d*(\.\d*)?[%\*]?
+ unsigned i = 0, j = 0;
+ QChar* s = value.implementation()->s;
+ unsigned l = value.implementation()->l;
+
+ while (i < l && s[i].isSpace())
+ ++i;
+ if (i < l && (s[i] == '+' || s[i] == '-'))
+ ++i;
+ while (i < l && s[i].isDigit())
+ ++i,++j;
+
+ // no digits!
+ if (j == 0) return;
+
+ int v = kClamp( QConstString(s, i).string().toInt(), -8192, 8191 ) ;
+ const char* suffix = "px";
+ if (!numOnly || multiLength) {
+ // look if we find a % or *
+ while (i < l) {
+ if (multiLength && s[i] == '*') {
+ suffix = "";
+ break;
+ }
+ if (s[i] == '%') {
+ suffix = "%";
+ break;
+ }
+ ++i;
+ }
+ }
+ if (numOnly) suffix = "";
+
+ QString ns = QString::number(v) + suffix;
+ m_styleDecls->setLengthProperty( id, DOMString( ns ), false, true, multiLength );
+ setChanged();
+ return;
+ }
+
+ m_styleDecls->setLengthProperty(id, value, false, true, multiLength);
+ setChanged();
+}
+
+static inline bool isHexDigit( const QChar &c ) {
+ return ( c >= '0' && c <= '9' ) ||
+ ( c >= 'a' && c <= 'f' ) ||
+ ( c >= 'A' && c <= 'F' );
+}
+
+static inline int toHex( const QChar &c ) {
+ return ( (c >= '0' && c <= '9')
+ ? (c.unicode() - '0')
+ : ( ( c >= 'a' && c <= 'f' )
+ ? (c.unicode() - 'a' + 10)
+ : ( ( c >= 'A' && c <= 'F' )
+ ? (c.unicode() - 'A' + 10)
+ : -1 ) ) );
+}
+
+/* color parsing that tries to match as close as possible IE 6. */
+void HTMLElementImpl::addHTMLColor( int id, const DOMString &c )
+{
+ if(!m_styleDecls) createDecl();
+
+ // this is the only case no color gets applied in IE.
+ if ( !c.length() ) {
+ removeCSSProperty(id);
+ return;
+ }
+
+ if ( m_styleDecls->setProperty(id, c, false, true) )
+ return;
+
+ QString color = c.string();
+ // not something that fits the specs.
+
+ // we're emulating IEs color parser here. It maps transparent to black, otherwise it tries to build a rgb value
+ // out of everyhting you put in. The algorithm is experimentally determined, but seems to work for all test cases I have.
+
+ // the length of the color value is rounded up to the next
+ // multiple of 3. each part of the rgb triple then gets one third
+ // of the length.
+ //
+ // Each triplet is parsed byte by byte, mapping
+ // each number to a hex value (0-9a-fA-F to their values
+ // everything else to 0).
+ //
+ // The highest non zero digit in all triplets is remembered, and
+ // used as a normalization point to normalize to values between 0
+ // and 255.
+
+ if ( color.lower() != "transparent" ) {
+ if ( color[0] == '#' )
+ color.remove( 0, 1 );
+ int basicLength = (color.length() + 2) / 3;
+ if ( basicLength > 1 ) {
+ // IE ignores colors with three digits or less
+// qDebug("trying to fix up color '%s'. basicLength=%d, length=%d",
+// color.latin1(), basicLength, color.length() );
+ int colors[3] = { 0, 0, 0 };
+ int component = 0;
+ int pos = 0;
+ int maxDigit = basicLength-1;
+ while ( component < 3 ) {
+ // search forward for digits in the string
+ int numDigits = 0;
+ while ( pos < (int)color.length() && numDigits < basicLength ) {
+ int hex = toHex( color[pos] );
+ colors[component] = (colors[component] << 4);
+ if ( hex > 0 ) {
+ colors[component] += hex;
+ maxDigit = kMin( maxDigit, numDigits );
+ }
+ numDigits++;
+ pos++;
+ }
+ while ( numDigits++ < basicLength )
+ colors[component] <<= 4;
+ component++;
+ }
+ maxDigit = basicLength - maxDigit;
+// qDebug("color is %x %x %x, maxDigit=%d", colors[0], colors[1], colors[2], maxDigit );
+
+ // normalize to 00-ff. The highest filled digit counts, minimum is 2 digits
+ maxDigit -= 2;
+ colors[0] >>= 4*maxDigit;
+ colors[1] >>= 4*maxDigit;
+ colors[2] >>= 4*maxDigit;
+// qDebug("normalized color is %x %x %x", colors[0], colors[1], colors[2] );
+ // assert( colors[0] < 0x100 && colors[1] < 0x100 && colors[2] < 0x100 );
+
+ color.sprintf("#%02x%02x%02x", colors[0], colors[1], colors[2] );
+// qDebug( "trying to add fixed color string '%s'", color.latin1() );
+ if ( m_styleDecls->setProperty(id, DOMString(color), false, true) )
+ return;
+ }
+ }
+ m_styleDecls->setProperty(id, CSS_VAL_BLACK, false, true);
+}
+
+void HTMLElementImpl::removeCSSProperty(int id)
+{
+ if(!m_styleDecls)
+ return;
+ m_styleDecls->setParent(getDocument()->elementSheet());
+ m_styleDecls->removeProperty(id, true /*nonCSSHint */);
+ setChanged();
+}
+
+DOMString HTMLElementImpl::innerHTML() const
+{
+ QString result; //Use QString to accumulate since DOMString is poor for appends
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ DOMString kid = child->toString();
+ result += QConstString(kid.unicode(), kid.length()).string();
+ }
+ return result;
+}
+
+DOMString HTMLElementImpl::innerText() const
+{
+ QString text = "";
+ if(!firstChild())
+ return text;
+
+ const NodeImpl *n = this;
+ // find the next text/image after the anchor, to get a position
+ while(n) {
+ if(n->firstChild())
+ n = n->firstChild();
+ else if(n->nextSibling())
+ n = n->nextSibling();
+ else {
+ NodeImpl *next = 0;
+ while(!next) {
+ n = n->parentNode();
+ if(!n || n == (NodeImpl *)this ) goto end;
+ next = n->nextSibling();
+ }
+ n = next;
+ }
+ if(n->isTextNode() ) {
+ DOMStringImpl* data = static_cast<const TextImpl *>(n)->string();
+ text += QConstString(data->s, data->l).string();
+ }
+ }
+ end:
+ return text;
+}
+
+DocumentFragment HTMLElementImpl::createContextualFragment( const DOMString &html )
+{
+ // the following is in accordance with the definition as used by IE
+ if( endTag[id()] == FORBIDDEN )
+ return DocumentFragment();
+ // IE disallows innerHTML on inline elements.
+ // I don't see why we should have this restriction, as our
+ // dhtml engine can cope with it. Lars
+ //if ( isInline() ) return false;
+ switch( id() ) {
+ case ID_COL:
+ case ID_COLGROUP:
+ case ID_FRAMESET:
+ case ID_HEAD:
+ case ID_TABLE:
+ case ID_TBODY:
+ case ID_TFOOT:
+ case ID_THEAD:
+ case ID_TITLE:
+ return DocumentFragment();
+ default:
+ break;
+ }
+ if ( !getDocument()->isHTMLDocument() )
+ return DocumentFragment();
+
+ DocumentFragmentImpl* fragment = new DocumentFragmentImpl( docPtr() );
+ DocumentFragment f( fragment );
+ {
+ HTMLTokenizer tok( docPtr(), fragment );
+ tok.begin();
+ tok.write( html.string(), true );
+ tok.end();
+ }
+
+ // Exceptions are ignored because none ought to happen here.
+ int ignoredExceptionCode;
+
+ // we need to pop <html> and <body> elements and remove <head> to
+ // accomadate folks passing complete HTML documents to make the
+ // child of an element.
+ for ( NodeImpl* node = fragment->firstChild(); node; ) {
+ if (node->id() == ID_HTML || node->id() == ID_BODY) {
+ NodeImpl* firstChild = node->firstChild();
+ NodeImpl* child = firstChild;
+ while ( child ) {
+ NodeImpl *nextChild = child->nextSibling();
+ fragment->insertBefore(child, node, ignoredExceptionCode);
+ child = nextChild;
+ }
+ if ( !firstChild ) {
+ NodeImpl *nextNode = node->nextSibling();
+ fragment->removeChild(node, ignoredExceptionCode);
+ node = nextNode;
+ } else {
+ fragment->removeChild(node, ignoredExceptionCode);
+ node = firstChild;
+ }
+ } else if (node->id() == ID_HEAD) {
+ NodeImpl *nextNode = node->nextSibling();
+ fragment->removeChild(node, ignoredExceptionCode);
+ node = nextNode;
+ } else {
+ node = node->nextSibling();
+ }
+ }
+
+ return f;
+}
+
+void HTMLElementImpl::setInnerHTML( const DOMString &html, int &exceptioncode )
+{
+ DocumentFragment fragment = createContextualFragment( html );
+ if ( fragment.isNull() ) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // Make sure adding the new child is ok, before removing all children (#96187)
+ checkAddChild( fragment.handle(), exceptioncode );
+ if ( exceptioncode )
+ return;
+
+ removeChildren();
+ appendChild( fragment.handle(), exceptioncode );
+}
+
+void HTMLElementImpl::setInnerText( const DOMString &text, int& exceptioncode )
+{
+ // following the IE specs.
+ if( endTag[id()] == FORBIDDEN ) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+ // IE disallows innerHTML on inline elements. I don't see why we should have this restriction, as our
+ // dhtml engine can cope with it. Lars
+ //if ( isInline() ) return false;
+ switch( id() ) {
+ case ID_COL:
+ case ID_COLGROUP:
+ case ID_FRAMESET:
+ case ID_HEAD:
+ case ID_HTML:
+ case ID_TABLE:
+ case ID_TBODY:
+ case ID_TFOOT:
+ case ID_THEAD:
+ case ID_TR:
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ default:
+ break;
+ }
+
+ removeChildren();
+
+ TextImpl *t = new TextImpl( docPtr(), text.implementation() );
+ appendChild( t, exceptioncode );
+}
+
+void HTMLElementImpl::addHTMLAlignment( DOMString alignment )
+{
+ //qDebug("alignment is %s", alignment.string().latin1() );
+ // vertical alignment with respect to the current baseline of the text
+ // right or left means floating images
+ int propfloat = -1;
+ int propvalign = -1;
+ if ( strcasecmp( alignment, "absmiddle" ) == 0 ) {
+ propvalign = CSS_VAL_MIDDLE;
+ } else if ( strcasecmp( alignment, "absbottom" ) == 0 ) {
+ propvalign = CSS_VAL_BOTTOM;
+ } else if ( strcasecmp( alignment, "left" ) == 0 ) {
+ propfloat = CSS_VAL_LEFT;
+ propvalign = CSS_VAL_TOP;
+ } else if ( strcasecmp( alignment, "right" ) == 0 ) {
+ propfloat = CSS_VAL_RIGHT;
+ propvalign = CSS_VAL_TOP;
+ } else if ( strcasecmp( alignment, "top" ) == 0 ) {
+ propvalign = CSS_VAL_TOP;
+ } else if ( strcasecmp( alignment, "middle" ) == 0 ) {
+ propvalign = CSS_VAL__KHTML_BASELINE_MIDDLE;
+ } else if ( strcasecmp( alignment, "center" ) == 0 ) {
+ propvalign = CSS_VAL_MIDDLE;
+ } else if ( strcasecmp( alignment, "bottom" ) == 0 ) {
+ propvalign = CSS_VAL_BASELINE;
+ } else if ( strcasecmp ( alignment, "texttop") == 0 ) {
+ propvalign = CSS_VAL_TEXT_TOP;
+ }
+
+ if ( propfloat != -1 )
+ addCSSProperty( CSS_PROP_FLOAT, propfloat );
+ if ( propvalign != -1 )
+ addCSSProperty( CSS_PROP_VERTICAL_ALIGN, propvalign );
+}
+
+DOMString HTMLElementImpl::toString() const
+{
+ if (!hasChildNodes()) {
+ DOMString result = openTagStartToString();
+ result += ">";
+
+ if (endTag[id()] == REQUIRED) {
+ result += "</";
+ result += tagName();
+ result += ">";
+ }
+
+ return result;
+ }
+
+ return ElementImpl::toString();
+}
+
+// -------------------------------------------------------------------------
+HTMLGenericElementImpl::HTMLGenericElementImpl(DocumentImpl *doc, ushort i)
+ : HTMLElementImpl(doc)
+{
+ _id = i;
+}
+
+HTMLGenericElementImpl::~HTMLGenericElementImpl()
+{
+}
diff --git a/khtml/html/html_elementimpl.h b/khtml/html/html_elementimpl.h
new file mode 100644
index 000000000..f71ae9b23
--- /dev/null
+++ b/khtml/html/html_elementimpl.h
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_ELEMENTIMPL_H
+#define HTML_ELEMENTIMPL_H
+
+#include "xml/dom_elementimpl.h"
+
+namespace DOM {
+
+class DOMString;
+class CSSStyleDeclarationImpl;
+class HTMLFormElementImpl;
+class DocumentFragment;
+
+class HTMLElementImpl : public ElementImpl
+{
+public:
+ HTMLElementImpl(DocumentImpl *doc);
+
+ virtual ~HTMLElementImpl();
+
+ virtual bool isHTMLElement() const { return true; }
+
+ virtual bool isInline() const;
+
+ virtual Id id() const = 0;
+ virtual DOMString tagName() const;
+ virtual DOMString localName() const;
+ virtual DOMString namespaceURI() const;
+
+ virtual void parseAttribute(AttributeImpl *token);
+
+ void addCSSLength(int id, const DOMString &value, bool numOnly = false, bool multiLength = false);
+ void addCSSProperty(int id, const DOMString &value);
+ void addCSSProperty(int id, int value);
+ void addHTMLColor( int id, const DOMString &c );
+ void removeCSSProperty(int id);
+
+ virtual void recalcStyle( StyleChange );
+
+ DOMString innerHTML() const;
+ DOMString innerText() const;
+ DocumentFragment createContextualFragment( const DOMString &html );
+ void setInnerHTML( const DOMString &html, int& exceptioncode );
+ void setInnerText( const DOMString &text, int& exceptioncode );
+
+ virtual DOMString toString() const;
+
+protected:
+ // for IMG, OBJECT and APPLET
+ void addHTMLAlignment( DOMString alignment );
+};
+
+class HTMLGenericElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLGenericElementImpl(DocumentImpl *doc, ushort i);
+
+ virtual ~HTMLGenericElementImpl();
+
+ virtual Id id() const { return _id; };
+
+protected:
+ ushort _id;
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_formimpl.cpp b/khtml/html/html_formimpl.cpp
new file mode 100644
index 000000000..e59098499
--- /dev/null
+++ b/khtml/html/html_formimpl.cpp
@@ -0,0 +1,2984 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#undef FORMS_DEBUG
+//#define FORMS_DEBUG
+
+#include "html/html_formimpl.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "html/html_documentimpl.h"
+#include "khtml_settings.h"
+#include "misc/htmlhashes.h"
+
+#include "css/cssstyleselector.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/csshelper.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_restyler.h"
+#include "khtml_ext.h"
+
+#include "rendering/render_form.h"
+
+#include <kcharsets.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <klocale.h>
+#ifndef KHTML_NO_WALLET
+#include <kwallet.h>
+#endif
+#include <netaccess.h>
+#include <kfileitem.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qtextcodec.h>
+
+// for keygen
+#include <qstring.h>
+#include <ksslkeygen.h>
+
+#include <assert.h>
+
+
+using namespace DOM;
+using namespace khtml;
+
+HTMLFormElementImpl::HTMLFormElementImpl(DocumentImpl *doc, bool implicit)
+ : HTMLElementImpl(doc)
+{
+ m_implicit = implicit;
+ m_post = false;
+ m_multipart = false;
+ m_autocomplete = true;
+ m_insubmit = false;
+ m_doingsubmit = false;
+ m_inreset = false;
+ m_enctype = "application/x-www-form-urlencoded";
+ m_boundary = "----------" + KApplication::randomString( 42 + 13 );
+ m_acceptcharset = "UNKNOWN";
+ m_malformed = false;
+}
+
+HTMLFormElementImpl::~HTMLFormElementImpl()
+{
+ if (getDocument() && getDocument()->view() && getDocument()->view()->part()) {
+ getDocument()->view()->part()->dequeueWallet(this);
+ }
+ QPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
+ for (; it.current(); ++it)
+ it.current()->m_form = 0;
+ QPtrListIterator<HTMLImageElementImpl> it2(imgElements);
+ for (; it2.current(); ++it2)
+ it2.current()->m_form = 0;
+}
+
+NodeImpl::Id HTMLFormElementImpl::id() const
+{
+ return ID_FORM;
+}
+
+long HTMLFormElementImpl::length() const
+{
+ int len = 0;
+ QPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
+ for (; it.current(); ++it)
+ if (it.current()->isEnumeratable())
+ ++len;
+
+ return len;
+}
+
+static QCString encodeCString(const QCString& e)
+{
+ // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
+ // safe characters like NS handles them for compatibility
+ static const char *safe = "-._*";
+ QCString encoded(( e.length()+e.contains( '\n' ) )*3
+ +e.contains('\r') * 3 + 1);
+ int enclen = 0;
+ bool crmissing = false;
+ unsigned char oldc;
+ unsigned char c ='\0';
+
+ //QCString orig(e.data(), e.size());
+
+ unsigned len = e.length();
+ for(unsigned pos = 0; pos < len; pos++) {
+ oldc = c;
+ c = e[pos];
+
+ if (crmissing && c != '\n') {
+ encoded[enclen++] = '%';
+ encoded[enclen++] = '0';
+ encoded[enclen++] = 'D';
+ crmissing = false;
+ }
+
+ if ( (( c >= 'A') && ( c <= 'Z')) ||
+ (( c >= 'a') && ( c <= 'z')) ||
+ (( c >= '0') && ( c <= '9')) ||
+ (strchr(safe, c))
+ )
+ encoded[enclen++] = c;
+ else if ( c == ' ' )
+ encoded[enclen++] = '+';
+ else if ( c == '\n' )
+ {
+ encoded[enclen++] = '%';
+ encoded[enclen++] = '0';
+ encoded[enclen++] = 'D';
+ encoded[enclen++] = '%';
+ encoded[enclen++] = '0';
+ encoded[enclen++] = 'A';
+ crmissing = false;
+ }
+ else if (c == '\r' && oldc != '\n') {
+ crmissing = true;
+ }
+ else if ( c != '\r' )
+ {
+ encoded[enclen++] = '%';
+ unsigned int h = c / 16;
+ h += (h > 9) ? ('A' - 10) : '0';
+ encoded[enclen++] = h;
+
+ unsigned int l = c % 16;
+ l += (l > 9) ? ('A' - 10) : '0';
+ encoded[enclen++] = l;
+ }
+ }
+ encoded[enclen++] = '\0';
+ encoded.truncate(enclen);
+
+ return encoded;
+}
+
+// ### This function only encodes to numeric ampersand escapes,
+// ### we could use standard ampersand values as well.
+inline static QString escapeUnencodeable(const QTextCodec* codec, const QString& s) {
+ QString enc_string;
+ const int len = s.length();
+ for(int i=0; i <len; ++i) {
+ const QChar c = s[i];
+ if (codec->canEncode(c))
+ enc_string.append(c);
+ else {
+ QString ampersandEscape;
+ ampersandEscape.sprintf("&#%u;", c.unicode());
+ enc_string.append(ampersandEscape);
+ }
+ }
+ return enc_string;
+}
+
+inline static QCString fixUpfromUnicode(const QTextCodec* codec, const QString& s)
+{
+ QCString str = codec->fromUnicode(escapeUnencodeable(codec,s));
+ str.truncate(str.length());
+ return str;
+}
+
+QByteArray HTMLFormElementImpl::formData(bool& ok)
+{
+#ifdef FORMS_DEBUG
+ kdDebug( 6030 ) << "form: formData()" << endl;
+#endif
+
+ QByteArray form_data(0);
+ QCString enc_string = ""; // used for non-multipart data
+
+ // find out the QTextcodec to use
+ const QString str = m_acceptcharset.string();
+ const QChar space(' ');
+ const unsigned int strLength = str.length();
+ for(unsigned int i=0; i < strLength; ++i) if(str[i].latin1() == ',') str[i] = space;
+ const QStringList charsets = QStringList::split(' ', str);
+ QTextCodec* codec = 0;
+ KHTMLView *view = getDocument()->view();
+ {
+ QStringList::ConstIterator it = charsets.begin();
+ const QStringList::ConstIterator itEnd = charsets.end();
+
+ for ( ; it != itEnd; ++it )
+ {
+ QString enc = (*it);
+ if(enc.contains("UNKNOWN"))
+ {
+ // use standard document encoding
+ enc = "ISO 8859-1";
+ if(view && view->part())
+ enc = view->part()->encoding();
+ }
+ if((codec = KGlobal::charsets()->codecForName(enc.latin1())))
+ break;
+ }
+ }
+ if(!codec)
+ codec = QTextCodec::codecForLocale();
+
+ // we need to map visual hebrew to logical hebrew, as the web
+ // server alsways expects responses in logical ordering
+ if ( codec->mibEnum() == 11 )
+ codec = QTextCodec::codecForMib( 85 );
+
+ m_encCharset = codec->name();
+ const unsigned int m_encCharsetLength = m_encCharset.length();
+ for(unsigned int i=0; i < m_encCharsetLength; ++i)
+ m_encCharset[i] = m_encCharset[i].latin1() == ' ' ? QChar('-') : m_encCharset[i].lower();
+
+ QStringList fileUploads, fileNotUploads;
+
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ HTMLGenericFormElementImpl* const current = it.current();
+ khtml::encodingList lst;
+
+ if (!current->disabled() && current->encoding(codec, lst, m_multipart))
+ {
+ //kdDebug(6030) << "adding name '" << current->name().string() << "'" << endl;
+ khtml::encodingList::ConstIterator it = lst.begin();
+ const khtml::encodingList::ConstIterator itEnd = lst.end();
+ for( it = lst.begin(); it != itEnd; ++it )
+ {
+ if (!m_multipart)
+ {
+ // handle ISINDEX / <input name=isindex> special
+ // but only if its the first entry
+ if ( enc_string.isEmpty() && *it == "isindex" ) {
+ ++it;
+ enc_string += encodeCString( *it );
+ }
+ else {
+ if(!enc_string.isEmpty())
+ enc_string += '&';
+
+ enc_string += encodeCString(*it);
+ enc_string += "=";
+ ++it;
+ enc_string += encodeCString(*it);
+ }
+ }
+ else
+ {
+ QCString hstr("--");
+ hstr += m_boundary.latin1();
+ hstr += "\r\n";
+ hstr += "Content-Disposition: form-data; name=\"";
+ hstr += (*it).data();
+ hstr += "\"";
+
+ // if the current type is FILE, then we also need to
+ // include the filename
+ if (current->id() == ID_INPUT &&
+ static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::FILE &&
+ current->renderer())
+ {
+ KURL path;
+ QString val = static_cast<HTMLInputElementImpl*>(current)->value().string().stripWhiteSpace();
+ if (!val.isEmpty() &&
+ QDir::isRelativePath(val) &&
+ QFile::exists(KGlobalSettings::documentPath() + val)) {
+ path.setPath(KGlobalSettings::documentPath() + val);
+ } else {
+ path = KURL::fromPathOrURL(val);
+ }
+
+ hstr += fixUpfromUnicode(codec, "; filename=\"" + path.fileName() + "\"");
+ if (path.isValid()) {
+ fileUploads << path.prettyURL(0, KURL::StripFileProtocol);
+ const KMimeType::Ptr ptr = KMimeType::findByURL(path);
+ if (!ptr->name().isEmpty()) {
+ hstr += "\r\nContent-Type: ";
+ hstr += ptr->name().ascii();
+ }
+ } else if (!val.isEmpty()) {
+ fileNotUploads << path.prettyURL(0, KURL::StripFileProtocol);
+ }
+ }
+
+ hstr += "\r\n\r\n";
+ ++it;
+
+ // append body
+ const unsigned int old_size = form_data.size();
+ form_data.resize( old_size + hstr.length() + (*it).size() + 1);
+ memcpy(form_data.data() + old_size, hstr.data(), hstr.length());
+ memcpy(form_data.data() + old_size + hstr.length(), *it, (*it).size());
+ form_data[form_data.size()-2] = '\r';
+ form_data[form_data.size()-1] = '\n';
+
+ // reset unsubmittedFormChange flag
+ if (current->id() == ID_INPUT &&
+ static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::TEXT)
+ static_cast<HTMLInputElementImpl*>(current)->setUnsubmittedFormChange(false);
+
+ if (current->id() == ID_TEXTAREA)
+ static_cast<HTMLTextAreaElementImpl*>(current)->setUnsubmittedFormChange(false);
+
+ }
+ }
+ }
+ }
+
+ if (fileNotUploads.count()) {
+ const int result = KMessageBox::warningContinueCancelList( 0,
+ i18n("The following files will not be uploaded"
+ " because they could not be found.\n"
+ "Do you want to continue?"),
+ fileNotUploads,
+ i18n("Submit Confirmation"),KGuiItem(i18n("&Submit Anyway")));
+
+
+ if (result == KMessageBox::Cancel) {
+ ok = false;
+ return QByteArray();
+ }
+ }
+
+ if (fileUploads.count()) {
+ const int result = KMessageBox::warningContinueCancelList( 0,
+ i18n("You're about to transfer the following files from "
+ "your local computer to the Internet.\n"
+ "Do you really want to continue?"),
+ fileUploads,
+ i18n("Send Confirmation"),KGuiItem(i18n("&Send Files")));
+
+
+ if (result == KMessageBox::Cancel) {
+ ok = false;
+ return QByteArray();
+ }
+ }
+
+ if (m_multipart)
+ enc_string = ("--" + m_boundary + "--\r\n").ascii();
+
+ const int old_size = form_data.size();
+ form_data.resize( form_data.size() + enc_string.length() );
+ memcpy(form_data.data() + old_size, enc_string.data(), enc_string.length() );
+
+ ok = true;
+ return form_data;
+}
+
+void HTMLFormElementImpl::setEnctype( const DOMString& type )
+{
+ if(type.string().find("multipart", 0, false) != -1 || type.string().find("form-data", 0, false) != -1)
+ {
+ m_enctype = "multipart/form-data";
+ m_multipart = true;
+ m_post = true;
+ } else if (type.string().find("text", 0, false) != -1 || type.string().find("plain", 0, false) != -1)
+ {
+ m_enctype = "text/plain";
+ m_multipart = false;
+ }
+ else
+ {
+ m_enctype = "application/x-www-form-urlencoded";
+ m_multipart = false;
+ }
+ m_encCharset = QString::null;
+}
+
+static QString calculateAutoFillKey(const HTMLFormElementImpl& e)
+{
+ KURL k(e.getDocument()->URL());
+ k.setRef(QString::null);
+ k.setQuery(QString::null);
+ // ensure that we have the user / password inside the url
+ // otherwise we might have a potential security problem
+ // by saving passwords under wrong lookup key.
+ const QString name = e.getAttribute(ATTR_NAME).string().stripWhiteSpace();
+ const QRegExp re("[;,!]");
+ const QStringList url = QStringList::split(re, k.url());
+ return url[0] + '#' + name;
+}
+
+void HTMLFormElementImpl::doAutoFill()
+{
+#ifndef KHTML_NO_WALLET
+ const QString key = calculateAutoFillKey(*this);
+
+ if (KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(),
+ KWallet::Wallet::FormDataFolder(),
+ key))
+ return;
+
+ // assert(view())
+ getDocument()->view()->part()->openWallet(this);
+#endif // KHTML_NO_WALLET
+}
+
+
+void HTMLFormElementImpl::walletOpened(KWallet::Wallet *w) {
+#ifndef KHTML_NO_WALLET
+ assert(w);
+ const QString key = calculateAutoFillKey(*this);
+ if (!w->hasFolder(KWallet::Wallet::FormDataFolder())) {
+ return; // failed
+ }
+ w->setFolder(KWallet::Wallet::FormDataFolder());
+ QMap<QString, QString> map;
+ if (w->readMap(key, map))
+ return; // failed, abort
+
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ if (it.current()->id() == ID_INPUT) {
+ HTMLInputElementImpl* const current = static_cast<HTMLInputElementImpl*>(it.current());
+ if ((current->inputType() == HTMLInputElementImpl::PASSWORD ||
+ current->inputType() == HTMLInputElementImpl::TEXT) &&
+ !current->readOnly() &&
+ map.contains(current->name().string())) {
+ getDocument()->setFocusNode(current);
+ current->setValue(map[current->name().string()]);
+ }
+ }
+ }
+#endif // KHTML_NO_WALLET
+}
+
+void HTMLFormElementImpl::submitFromKeyboard()
+{
+ // Activate the first nondisabled submit button
+ // if there is none, do a submit anyway if not more
+ // than one <input type=text> or <input type=password>
+ unsigned int inputtext = 0;
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ if (it.current()->id() == ID_BUTTON) {
+ HTMLButtonElementImpl* const current = static_cast<HTMLButtonElementImpl *>(it.current());
+ if (current->buttonType() == HTMLButtonElementImpl::SUBMIT && !current->disabled()) {
+ current->click();
+ return;
+ }
+ } else if (it.current()->id() == ID_INPUT) {
+ HTMLInputElementImpl* const current = static_cast<HTMLInputElementImpl *>(it.current());
+ switch(current->inputType()) {
+ case HTMLInputElementImpl::SUBMIT:
+ case HTMLInputElementImpl::IMAGE:
+ if(!current->disabled()) {
+ current->click();
+ return;
+ }
+ break;
+ case HTMLInputElementImpl::TEXT:
+ case HTMLInputElementImpl::PASSWORD:
+ ++inputtext;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (inputtext <= 1)
+ prepareSubmit();
+}
+
+
+void HTMLFormElementImpl::gatherWalletData()
+{
+#ifndef KHTML_NO_WALLET
+ KHTMLView* const view = getDocument()->view();
+ // check if we have any password input's
+ m_walletMap.clear();
+ m_havePassword = false;
+ m_haveTextarea = false;
+ const KURL formUrl(getDocument()->URL());
+ if (view && !view->nonPasswordStorableSite(formUrl.host())) {
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ if (it.current()->id() == ID_INPUT) {
+ HTMLInputElementImpl* const c = static_cast<HTMLInputElementImpl*> (it.current());
+ if ((c->inputType() == HTMLInputElementImpl::TEXT ||
+ c->inputType() == HTMLInputElementImpl::PASSWORD) &&
+ !c->readOnly()) {
+ m_walletMap.insert(c->name().string(), c->value().string());
+ if (c->inputType() == HTMLInputElementImpl::PASSWORD &&
+ !c->value().isEmpty())
+ m_havePassword = true;
+ }
+ }
+ else if (it.current()->id() == ID_TEXTAREA)
+ m_haveTextarea = true;
+ }
+ }
+#endif // KHTML_NO_WALLET
+}
+
+
+bool HTMLFormElementImpl::prepareSubmit()
+{
+ KHTMLView* const view = getDocument()->view();
+ if(m_insubmit || !view || !view->part() || view->part()->onlyLocalReferences())
+ return m_insubmit;
+
+ gatherWalletData();
+
+ m_insubmit = true;
+ m_doingsubmit = false;
+
+ if ( dispatchHTMLEvent(EventImpl::SUBMIT_EVENT,true,true) && !m_doingsubmit )
+ m_doingsubmit = true;
+
+ m_insubmit = false;
+
+ if ( m_doingsubmit )
+ submit();
+
+ return m_doingsubmit;
+}
+
+void HTMLFormElementImpl::submit( )
+{
+ if ( m_insubmit ) {
+ m_doingsubmit = true;
+ return;
+ }
+
+ m_insubmit = true;
+
+#ifdef FORMS_DEBUG
+ kdDebug( 6030 ) << "submitting!" << endl;
+#endif
+
+ bool ok;
+ KHTMLView* const view = getDocument()->view();
+ const QByteArray form_data = formData(ok);
+ const KURL formUrl(getDocument()->URL());
+
+ if (ok && view) {
+ if (m_walletMap.isEmpty()) {
+ gatherWalletData();
+ }
+#ifndef KHTML_NO_WALLET
+ if (m_havePassword && !m_haveTextarea && KWallet::Wallet::isEnabled()) {
+ const QString key = calculateAutoFillKey(*this);
+ const bool doesnotexist = KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::FormDataFolder(), key);
+ KWallet::Wallet* const w = view->part()->wallet();
+ bool login_changed = false;
+
+ if (!doesnotexist && w) {
+ // check if the login information changed from what
+ // we had so far.
+ if (w->hasFolder(KWallet::Wallet::FormDataFolder())) {
+ w->setFolder(KWallet::Wallet::FormDataFolder());
+ QMap<QString, QString> map;
+ if (!w->readMap(key, map)) {
+ QMapConstIterator<QString, QString> it = map.begin();
+ const QMapConstIterator<QString, QString> itEnd = map.end();
+ for ( ; it != itEnd; ++it )
+ if ( map[it.key()] != m_walletMap[it.key()] ) {
+ login_changed = true;
+ break;
+ }
+ } else {
+ login_changed = true;
+ }
+ }
+ }
+
+ if ( doesnotexist || !w || login_changed ) {
+ // TODO use KMessageBox::questionYesNoCancel() again, if you can pass a KGuiItem for Cancel
+ KDialogBase* const dialog = new KDialogBase(i18n("Save Login Information"),
+ KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel,
+ KDialogBase::Yes, KDialogBase::Cancel,
+ 0, "questionYesNoCancel", true, true,
+ i18n("Store"), KGuiItem(i18n("Ne&ver for This Site")), i18n("Do Not Store"));
+
+ bool checkboxResult = false;
+ const int savePassword = KMessageBox::createKMessageBox(dialog, QMessageBox::Information,
+ formUrl.host().isEmpty() ? // e.g. local file
+ i18n("Konqueror has the ability to store the password "
+ "in an encrypted wallet. When the wallet is unlocked, it "
+ "can then automatically restore the login information "
+ "next time you submit this form. Do you want to store "
+ "the information now?") :
+ i18n("Konqueror has the ability to store the password "
+ "in an encrypted wallet. When the wallet is unlocked, it "
+ "can then automatically restore the login information "
+ "next time you visit %1. Do you want to store "
+ "the information now?").arg(formUrl.host()),
+ QStringList(), QString::null, &checkboxResult, KMessageBox::Notify);
+
+ if ( savePassword == KDialogBase::Yes ) {
+ // ensure that we have the user / password inside the url
+ // otherwise we might have a potential security problem
+ // by saving passwords under wrong lookup key.
+
+ if (view->part()) {
+ view->part()->saveToWallet(key, m_walletMap);
+ }
+ } else if ( savePassword == KDialogBase::No ) {
+ view->addNonPasswordStorableSite(formUrl.host());
+ }
+ }
+ }
+#endif // KHTML_NO_WALLET
+
+ const DOMString url(khtml::parseURL(getAttribute(ATTR_ACTION)));
+ if(m_post) {
+ view->part()->submitForm( "post", url.string(), form_data,
+ m_target.string(),
+ enctype().string(),
+ m_boundary );
+ }
+ else {
+ view->part()->submitForm( "get", url.string(), form_data,
+ m_target.string() );
+ }
+ }
+
+ m_walletMap.clear(); // done with it
+ m_havePassword = m_haveTextarea= false;
+ m_doingsubmit = m_insubmit = false;
+}
+
+void HTMLFormElementImpl::reset( )
+{
+ KHTMLView* const view = getDocument()->view();
+ if(m_inreset || !view || !view->part()) return;
+
+ m_inreset = true;
+
+#ifdef FORMS_DEBUG
+ kdDebug( 6030 ) << "reset pressed!" << endl;
+#endif
+
+ // ### DOM2 labels this event as not cancelable, however
+ // common browsers( sick! ) allow it be cancelled.
+ if ( !dispatchHTMLEvent(EventImpl::RESET_EVENT,true, true) ) {
+ m_inreset = false;
+ return;
+ }
+
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it)
+ it.current()->reset();
+
+ m_inreset = false;
+}
+
+void HTMLFormElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ACTION:
+ break;
+ case ATTR_TARGET:
+ m_target = attr->value();
+ break;
+ case ATTR_METHOD:
+ m_post = ( strcasecmp( attr->value(), "post" ) == 0 );
+ break;
+ case ATTR_ENCTYPE:
+ setEnctype( attr->value() );
+ break;
+ case ATTR_ACCEPT_CHARSET:
+ // space separated list of charsets the server
+ // accepts - see rfc2045
+ m_acceptcharset = attr->value();
+ break;
+ case ATTR_ACCEPT:
+ // ignore this one for the moment...
+ break;
+ case ATTR_AUTOCOMPLETE:
+ m_autocomplete = strcasecmp( attr->value(), "off" );
+ break;
+ case ATTR_ONSUBMIT:
+ setHTMLEventListener(EventImpl::SUBMIT_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onsubmit", this));
+ break;
+ case ATTR_ONRESET:
+ setHTMLEventListener(EventImpl::RESET_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onreset", this));
+ break;
+ case ATTR_NAME:
+ if (inDocument() && m_name != attr->value()) {
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ getDocument()->underDocNamedCache().add (attr->value().string(), this);
+ }
+ m_name = attr->value();
+ //Fallthrough intentional
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLFormElementImpl::removedFromDocument()
+{
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ HTMLElementImpl::removedFromDocument();
+}
+
+void HTMLFormElementImpl::insertedIntoDocument()
+{
+ getDocument()->underDocNamedCache().add(m_name.string(), this);
+ HTMLElementImpl::insertedIntoDocument();
+}
+
+void HTMLFormElementImpl::removeId(const QString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLFormElementImpl::addId (const QString& id)
+{
+ getDocument()->underDocNamedCache().add(id, this);
+ HTMLElementImpl::addId(id);
+}
+
+
+void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller )
+{
+ for (QPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ HTMLGenericFormElementImpl* const current = it.current();
+ if (current->id() == ID_INPUT &&
+ static_cast<HTMLInputElementImpl*>(current)->inputType() == HTMLInputElementImpl::RADIO &&
+ current != caller && current->form() == caller->form() && current->name() == caller->name())
+ static_cast<HTMLInputElementImpl*>(current)->setChecked(false);
+ }
+}
+
+void HTMLFormElementImpl::registerFormElement(HTMLGenericFormElementImpl *e)
+{
+ formElements.append(e);
+}
+
+void HTMLFormElementImpl::removeFormElement(HTMLGenericFormElementImpl *e)
+{
+ formElements.remove(e);
+}
+
+void HTMLFormElementImpl::registerImgElement(HTMLImageElementImpl *e)
+{
+ imgElements.append(e);
+}
+
+void HTMLFormElementImpl::removeImgElement(HTMLImageElementImpl *e)
+{
+ imgElements.remove(e);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLGenericFormElementImpl::HTMLGenericFormElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLElementImpl(doc)
+{
+ m_disabled = m_readOnly = false;
+ m_name = 0;
+
+ if (f)
+ m_form = f;
+ else
+ m_form = getForm();
+ if (m_form)
+ m_form->registerFormElement(this);
+}
+
+void HTMLGenericFormElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+
+ if (!m_form) {
+ HTMLFormElementImpl* const newform = getForm();
+ if (newform) {
+ m_form = newform;
+ m_form->registerFormElement(this);
+ }
+ }
+}
+
+void HTMLGenericFormElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+
+ if (m_form)
+ m_form->removeFormElement(this);
+
+ m_form = 0;
+}
+
+HTMLGenericFormElementImpl::~HTMLGenericFormElementImpl()
+{
+ if (m_form)
+ m_form->removeFormElement(this);
+ if (m_name) m_name->deref();
+}
+
+void HTMLGenericFormElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_DISABLED:
+ setDisabled( attr->val() != 0 );
+ break;
+ case ATTR_READONLY:
+ {
+ const bool m_oldreadOnly = m_readOnly;
+ m_readOnly = attr->val() != 0;
+ if (m_oldreadOnly != m_readOnly) setChanged();
+ break;
+ }
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLGenericFormElementImpl::attach()
+{
+ assert(!attached());
+
+ if (m_render) {
+ assert(m_render->style());
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+
+ // FIXME: This handles the case of a new form element being created by
+ // JavaScript and inserted inside a form. What it does not handle is
+ // a form element being moved from inside a form to outside, or from one
+ // inside one form to another. The reason this other case is hard to fix
+ // is that during parsing, we may have been passed a form that we are not
+ // inside, DOM-tree-wise. If so, it's hard for us to know when we should
+ // be removed from that form's element list.
+ if (!m_form) {
+ m_form = getForm();
+ if (m_form)
+ m_form->registerFormElement(this);
+ }
+
+ NodeBaseImpl::attach();
+
+ // The call to updateFromElement() needs to go after the call through
+ // to the base class's attach() because that can sometimes do a close
+ // on the renderer.
+ if (m_render)
+ m_render->updateFromElement();
+
+}
+
+HTMLFormElementImpl *HTMLGenericFormElementImpl::getForm() const
+{
+ NodeImpl *p = parentNode();
+ while(p)
+ {
+ if( p->id() == ID_FORM )
+ return static_cast<HTMLFormElementImpl *>(p);
+ if( p->parentNode() && p->parentNode()->id() == ID_TABLE && p->previousSibling() )
+ {
+ p = p->previousSibling();
+ continue;
+ }
+ p = p->parentNode();
+ }
+#ifdef FORMS_DEBUG
+ kdDebug( 6030 ) << "couldn't find form!" << endl;
+ kdDebug( 6030 ) << kdBacktrace() << endl;
+#endif
+ return 0;
+}
+
+DOMString HTMLGenericFormElementImpl::name() const
+{
+ if (m_name) return m_name;
+
+// ###
+// DOMString n = getDocument()->htmlMode() != DocumentImpl::XHtml ?
+// getAttribute(ATTR_NAME) : getAttribute(ATTR_ID);
+ const DOMString n = getAttribute(ATTR_NAME);
+ if (n.isNull())
+ return new DOMStringImpl("");
+
+ return n;
+}
+
+void HTMLGenericFormElementImpl::setName(const DOMString& name)
+{
+ if (m_name) m_name->deref();
+ m_name = name.implementation();
+ setAttribute( ATTR_NAME, name );
+ if (m_name) m_name->ref();
+}
+
+void HTMLGenericFormElementImpl::onSelect()
+{
+ // ### make this work with new form events architecture
+ dispatchHTMLEvent(EventImpl::SELECT_EVENT,true,false);
+}
+
+void HTMLGenericFormElementImpl::onChange()
+{
+ // ### make this work with new form events architecture
+ dispatchHTMLEvent(EventImpl::CHANGE_EVENT,true,false);
+}
+
+void HTMLGenericFormElementImpl::setDisabled( bool _disabled )
+{
+ if ( m_disabled != _disabled ) {
+ m_disabled = _disabled;
+ // Trigger dynamic restyles
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency);
+ // We need to update rendering under all circumstances
+ if (!changed() && m_render) {
+ m_render->updateFromElement();
+ }
+ }
+}
+
+bool HTMLGenericFormElementImpl::isFocusable() const
+{
+ if (disabled())
+ return false;
+
+ //Non-widget INPUT TYPE="image" and <BUTTON> support focus, too.
+ if (id() == ID_INPUT && static_cast<const HTMLInputElementImpl *>(this)->inputType() == HTMLInputElementImpl::IMAGE)
+ return true;
+
+ if (id() == ID_BUTTON)
+ return true;
+
+ if (!m_render || !m_render->isWidget())
+ return false;
+
+ QWidget* widget = static_cast<RenderWidget*>(m_render)->widget();
+ return widget && widget->focusPolicy() >= QWidget::TabFocus;
+}
+
+class FocusHandleWidget : public QWidget
+{
+public:
+ void focusNextPrev(bool n) {
+ if (!focusNextPrevChild(n) && inherits("QTextEdit"))
+ QWidget::focusNextPrevChild(n);
+ }
+};
+
+void HTMLGenericFormElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ if (evt->target() == this && renderer() && renderer()->isWidget()) {
+ switch(evt->id()) {
+ case EventImpl::MOUSEDOWN_EVENT:
+ case EventImpl::MOUSEUP_EVENT:
+ case EventImpl::MOUSEMOVE_EVENT:
+ case EventImpl::MOUSEOUT_EVENT:
+ case EventImpl::MOUSEOVER_EVENT:
+ case EventImpl::KEYDOWN_EVENT:
+ case EventImpl::KEYUP_EVENT:
+ case EventImpl::KEYPRESS_EVENT:
+ if (static_cast<RenderWidget*>(renderer())->handleEvent(*evt))
+ evt->setDefaultHandled();
+ default:
+ break;
+ }
+ }
+
+ if (evt->target()==this && !m_disabled)
+ {
+ // Report focus in/out changes to the browser extension (editable widgets only)
+ KHTMLView* const view = getDocument()->view();
+ if (view && evt->id() == EventImpl::DOMFOCUSIN_EVENT && isEditable() && m_render && m_render->isWidget()) {
+ KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension());
+ QWidget* const widget = static_cast<RenderWidget*>(m_render)->widget();
+ if (ext)
+ ext->editableWidgetFocused(widget);
+ }
+ if (evt->id()==EventImpl::MOUSEDOWN_EVENT || evt->id()==EventImpl::KEYDOWN_EVENT)
+ {
+ setActive();
+ }
+ else if (evt->id() == EventImpl::MOUSEUP_EVENT || evt->id()==EventImpl::KEYUP_EVENT)
+ {
+ if (m_active)
+ {
+ setActive(false);
+ setFocus();
+ }
+ else {
+ setActive(false);
+ }
+ }
+
+ if (!evt->defaultHandled() && m_render && m_render->isWidget()) {
+ // handle tabbing out, either from a single or repeated key event.
+ if ( evt->id() == EventImpl::KEYPRESS_EVENT && evt->isKeyRelatedEvent() ) {
+ QKeyEvent* const k = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent();
+ if ( k && (k->key() == Qt::Key_Tab || k->key() == Qt::Key_BackTab) ) {
+ QWidget* const widget = static_cast<RenderWidget*>(m_render)->widget();
+ QFocusEvent::setReason( k->key() == Qt::Key_Tab ? QFocusEvent::Tab : QFocusEvent::Backtab );
+ if (widget)
+ static_cast<FocusHandleWidget *>(widget)
+ ->focusNextPrev(k->key() == Qt::Key_Tab);
+ QFocusEvent::resetReason();
+ evt->setDefaultHandled();
+ }
+ }
+ }
+
+
+ if (view && evt->id() == EventImpl::DOMFOCUSOUT_EVENT && isEditable() && m_render && m_render->isWidget()) {
+ KHTMLPartBrowserExtension* const ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension());
+ QWidget* const widget = static_cast<RenderWidget*>(m_render)->widget();
+ if (ext)
+ ext->editableWidgetBlurred(widget);
+
+ // ### Don't count popup as a valid reason for losing the focus (example: opening the options of a select
+ // combobox shouldn't emit onblur)
+ }
+ }
+ if (evt->target() == this && evt->isMouseEvent() && renderer())
+ evt->setDefaultHandled();
+
+ HTMLElementImpl::defaultEventHandler(evt);
+}
+
+bool HTMLGenericFormElementImpl::isEditable()
+{
+ return false;
+}
+
+// -------------------------------------------------------------------------
+
+HTMLButtonElementImpl::HTMLButtonElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+ m_clicked = false;
+ m_type = SUBMIT;
+ m_dirty = true;
+ m_activeSubmit = false;
+}
+
+HTMLButtonElementImpl::~HTMLButtonElementImpl()
+{
+}
+
+NodeImpl::Id HTMLButtonElementImpl::id() const
+{
+ return ID_BUTTON;
+}
+
+DOMString HTMLButtonElementImpl::type() const
+{
+ return getAttribute(ATTR_TYPE);
+}
+
+void HTMLButtonElementImpl::blur()
+{
+ if(getDocument()->focusNode() == this)
+ getDocument()->setFocusNode(0);
+}
+
+void HTMLButtonElementImpl::focus()
+{
+ getDocument()->setFocusNode(this);
+}
+
+void HTMLButtonElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_TYPE:
+ if ( strcasecmp( attr->value(), "submit" ) == 0 )
+ m_type = SUBMIT;
+ else if ( strcasecmp( attr->value(), "reset" ) == 0 )
+ m_type = RESET;
+ else if ( strcasecmp( attr->value(), "button" ) == 0 )
+ m_type = BUTTON;
+ break;
+ case ATTR_VALUE:
+ m_value = attr->value();
+ m_currValue = m_value.string();
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ case ATTR_ALIGN:
+ break;
+ default:
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLButtonElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ if (m_type != BUTTON && !m_disabled) {
+ bool act = (evt->id() == EventImpl::DOMACTIVATE_EVENT);
+ if (!act && evt->id()==EventImpl::KEYUP_EVENT && evt->isKeyRelatedEvent()) {
+ QKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent();
+ if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space))
+ act = true;
+ }
+ if (act)
+ activate();
+ }
+ HTMLGenericFormElementImpl::defaultEventHandler(evt);
+}
+
+void HTMLButtonElementImpl::activate()
+{
+ m_clicked = true;
+
+ if(m_form && m_type == SUBMIT) {
+ m_activeSubmit = true;
+ m_form->prepareSubmit();
+ m_activeSubmit = false; // in case we were canceled
+ }
+ if(m_form && m_type == RESET)
+ m_form->reset();
+}
+
+void HTMLButtonElementImpl::click()
+{
+ QMouseEvent me(QEvent::MouseButtonRelease, QPoint(0,0),Qt::LeftButton, 0);
+ dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1);
+}
+
+bool HTMLButtonElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoding, bool /*multipart*/)
+{
+ if (m_type != SUBMIT || name().isEmpty() || !m_activeSubmit)
+ return false;
+
+ encoding += fixUpfromUnicode(codec, name().string());
+ const QString enc_str = m_currValue.isNull() ? QString("") : m_currValue;
+ encoding += fixUpfromUnicode(codec, enc_str);
+
+ return true;
+}
+
+void HTMLButtonElementImpl::attach()
+{
+ // skip the generic handler
+ HTMLElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLFieldSetElementImpl::HTMLFieldSetElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+}
+
+HTMLFieldSetElementImpl::~HTMLFieldSetElementImpl()
+{
+}
+
+NodeImpl::Id HTMLFieldSetElementImpl::id() const
+{
+ return ID_FIELDSET;
+}
+
+void HTMLFieldSetElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && _style->display() != NONE) {
+ m_render = new (getDocument()->renderArena()) RenderFieldset(this);
+ m_render->setStyle(_style);
+ }
+ HTMLGenericFormElementImpl::attach();
+ _style->deref();
+}
+
+void HTMLFieldSetElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ HTMLElementImpl::parseAttribute(attr);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLInputElementImpl::HTMLInputElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+ m_type = TEXT;
+ m_maxLen = -1;
+ m_size = 20;
+ m_clicked = false;
+ m_checked = false;
+ m_defaultChecked = false;
+ m_useDefaultChecked = true;
+ m_indeterminate = false;
+
+ m_haveType = false;
+ m_activeSubmit = false;
+ m_autocomplete = true;
+ m_inited = false;
+ m_unsubmittedFormChange = false;
+
+ xPos = 0;
+ yPos = 0;
+
+ if ( m_form )
+ m_autocomplete = f->autoComplete();
+}
+
+HTMLInputElementImpl::~HTMLInputElementImpl()
+{
+ if (getDocument()) getDocument()->deregisterMaintainsState(this);
+}
+
+NodeImpl::Id HTMLInputElementImpl::id() const
+{
+ return ID_INPUT;
+}
+
+// Called from JS. Can't merge with parseType since we
+// also need to actually set ATTR_TYPE, which can't be done there.
+void HTMLInputElementImpl::setType(const DOMString& t)
+{
+ setAttribute(ATTR_TYPE, t);
+}
+
+void HTMLInputElementImpl::parseType(const DOMString& t)
+{
+ typeEnum newType;
+
+ if ( strcasecmp( t, "password" ) == 0 )
+ newType = PASSWORD;
+ else if ( strcasecmp( t, "checkbox" ) == 0 )
+ newType = CHECKBOX;
+ else if ( strcasecmp( t, "radio" ) == 0 )
+ newType = RADIO;
+ else if ( strcasecmp( t, "submit" ) == 0 )
+ newType = SUBMIT;
+ else if ( strcasecmp( t, "reset" ) == 0 )
+ newType = RESET;
+ else if ( strcasecmp( t, "file" ) == 0 )
+ newType = FILE;
+ else if ( strcasecmp( t, "hidden" ) == 0 )
+ newType = HIDDEN;
+ else if ( strcasecmp( t, "image" ) == 0 )
+ newType = IMAGE;
+ else if ( strcasecmp( t, "button" ) == 0 )
+ newType = BUTTON;
+ else if ( strcasecmp( t, "khtml_isindex" ) == 0 )
+ newType = ISINDEX;
+ else
+ newType = TEXT;
+
+ // ### IMPORTANT: Don't allow the type to be changed to FILE after the first
+ // type change, otherwise a JavaScript programmer would be able to set a text
+ // field's value to something like /etc/passwd and then change it to a file field.
+ if (m_type != newType) {
+ if (newType == FILE && m_haveType) {
+ // Set the attribute back to the old value.
+ // Note that this calls parseAttribute again.
+ setAttribute(ATTR_TYPE, type());
+ } else {
+ m_type = newType;
+
+ // force reattach if need be.
+ if (attached()) {
+ detach();
+ attach();
+ }
+ }
+ }
+ m_haveType = true;
+}
+
+DOMString HTMLInputElementImpl::type() const
+{
+ // needs to be lowercase according to DOM spec
+ switch (m_type) {
+ case TEXT: return "text";
+ case PASSWORD: return "password";
+ case CHECKBOX: return "checkbox";
+ case RADIO: return "radio";
+ case SUBMIT: return "submit";
+ case RESET: return "reset";
+ case FILE: return "file";
+ case HIDDEN: return "hidden";
+ case IMAGE: return "image";
+ case BUTTON: return "button";
+ default: return "";
+ }
+}
+
+QString HTMLInputElementImpl::state( )
+{
+ switch (m_type) {
+ case PASSWORD:
+ return QString::fromLatin1("."); // empty string, avoid restoring
+ case CHECKBOX:
+ case RADIO:
+ return QString::fromLatin1(checked() ? "on" : "off");
+ case TEXT:
+ if (autoComplete() && value() != getAttribute(ATTR_VALUE) && getDocument()->view())
+ getDocument()->view()->addFormCompletionItem(name().string(), value().string());
+ /* nobreak */
+ default:
+ return value().string() + (m_unsubmittedFormChange ? 'M' : '.');
+ }
+}
+
+void HTMLInputElementImpl::restoreState(const QString &state)
+{
+ switch (m_type) {
+ case CHECKBOX:
+ case RADIO:
+ setChecked((state == QString::fromLatin1("on")));
+ break;
+ case FILE:
+ m_value = DOMString(state.left(state.length()-1));
+ setChanged();
+ break;
+ default:
+ setValue(DOMString(state.left(state.length()-1)));
+ m_unsubmittedFormChange = state.endsWith("M");
+ break;
+ }
+}
+
+void HTMLInputElementImpl::select( )
+{
+ if(!m_render) return;
+
+ if (m_type == TEXT || m_type == PASSWORD)
+ static_cast<RenderLineEdit*>(m_render)->select();
+ else if (m_type == FILE)
+ static_cast<RenderFileButton*>(m_render)->select();
+}
+
+void HTMLInputElementImpl::click()
+{
+ QMouseEvent me(QEvent::MouseButtonRelease, QPoint(0,0),Qt::LeftButton, 0);
+ dispatchMouseEvent(&me,0, 1);
+ dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1);
+}
+
+void HTMLInputElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_AUTOCOMPLETE:
+ m_autocomplete = strcasecmp( attr->value(), "off" );
+ break;
+ case ATTR_TYPE:
+ parseType(attr->value());
+ break;
+ case ATTR_VALUE:
+ if (m_value.isNull()) {// We only need to setChanged if the form is looking
+ setChanged(); // at the default value right now.
+ if (m_type == TEXT && m_render)
+ m_render->updateFromElement();
+ }
+ break;
+ case ATTR_CHECKED:
+ m_defaultChecked = attr->val();
+ if (m_useDefaultChecked) // We only need to setChanged if the form is looking
+ setChanged(); // at the default checked state right now.
+ break;
+ case ATTR_MAXLENGTH:
+ {
+ m_maxLen = -1;
+ if (!attr->val()) break;
+ bool ok;
+ const int ml = attr->val()->toInt(&ok);
+ if (ml > 0 && ml < 32767)
+ m_maxLen = ml;
+ else if (ok && ml <= 0)
+ m_maxLen = 0;
+ setChanged();
+ }
+ break;
+ case ATTR_SIZE:
+ m_size = attr->val() ? attr->val()->toInt() : 20;
+ break;
+ case ATTR_ALT:
+ case ATTR_SRC:
+ if (m_type == IMAGE)
+ setChanged();
+ break;
+ case ATTR_USEMAP:
+ // ### ignore for the moment
+ break;
+ case ATTR_ALIGN:
+ if ( m_inited && m_type == IMAGE )
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ case ATTR_WIDTH:
+ if ( m_type == IMAGE )
+ addCSSLength(CSS_PROP_WIDTH, attr->value() );
+ break;
+ case ATTR_HEIGHT:
+ if ( m_type == IMAGE )
+ addCSSLength(CSS_PROP_HEIGHT, attr->value() );
+ break;
+ case ATTR_ONSELECT:
+ setHTMLEventListener(EventImpl::SELECT_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onselect", this));
+ break;
+ case ATTR_ONCHANGE:
+ setHTMLEventListener(EventImpl::CHANGE_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this));
+ break;
+ default:
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLInputElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ if (!m_inited) {
+ // FIXME: This needs to be dynamic, doesn't it, since someone could set this
+ // after attachment?
+ if ((uint) m_type <= ISINDEX && !m_value.isEmpty()) {
+ const QString value = m_value.string();
+ // remove newline stuff..
+ QString nvalue;
+ unsigned int valueLength = value.length();
+ for (unsigned int i = 0; i < valueLength; ++i)
+ if (value[i] >= ' ')
+ nvalue += value[i];
+ m_value = nvalue;
+ }
+ m_defaultChecked = (getAttribute(ATTR_CHECKED) != 0);
+ if ( m_type == IMAGE )
+ addHTMLAlignment( getAttribute( ATTR_ALIGN ) );
+ m_inited = true;
+ }
+
+ switch( m_type ) {
+ case PASSWORD:
+ if (getDocument()->isHTMLDocument())
+ static_cast<HTMLDocumentImpl*>(getDocument())->setAutoFill();
+ break;
+ case HIDDEN:
+ case IMAGE:
+ if (!getAttribute(ATTR_WIDTH).isNull())
+ addCSSLength(CSS_PROP_WIDTH, getAttribute(ATTR_WIDTH));
+ if (!getAttribute(ATTR_HEIGHT).isNull())
+ addCSSLength(CSS_PROP_HEIGHT, getAttribute(ATTR_HEIGHT));
+ default:
+ break;
+ };
+
+ RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && _style->display() != NONE) {
+ switch(m_type)
+ {
+ case TEXT:
+ case PASSWORD:
+ case ISINDEX: m_render = new (getDocument()->renderArena()) RenderLineEdit(this); break;
+ case CHECKBOX: m_render = new (getDocument()->renderArena()) RenderCheckBox(this); break;
+ case RADIO: m_render = new (getDocument()->renderArena()) RenderRadioButton(this); break;
+ case SUBMIT: m_render = new (getDocument()->renderArena()) RenderSubmitButton(this); break;
+ case IMAGE: m_render = new (getDocument()->renderArena()) RenderImageButton(this); break;
+ case RESET: m_render = new (getDocument()->renderArena()) RenderResetButton(this); break;
+ case FILE: m_render = new (getDocument()->renderArena()) RenderFileButton(this); break;
+ case BUTTON: m_render = new (getDocument()->renderArena()) RenderPushButton(this);
+ case HIDDEN: break;
+ }
+ }
+
+ // Let check and radio boxes start indeterminate
+ setIndeterminate(true);
+
+ if (m_render)
+ m_render->setStyle(_style);
+
+ HTMLGenericFormElementImpl::attach();
+ _style->deref();
+}
+
+DOMString HTMLInputElementImpl::altText() const
+{
+ // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
+ // also heavily discussed by Hixie on bugzilla
+ // note this is intentionally different to HTMLImageElementImpl::altText()
+ DOMString alt = getAttribute( ATTR_ALT );
+ // fall back to title attribute
+ if ( alt.isNull() )
+ alt = getAttribute( ATTR_TITLE );
+ if ( alt.isNull() )
+ alt = getAttribute( ATTR_VALUE );
+ if ( alt.isEmpty() )
+ alt = i18n( "Submit" );
+
+ return alt;
+}
+
+bool HTMLInputElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoding, bool multipart)
+{
+ const QString nme = name().string();
+
+ // image generates its own name's
+ if (nme.isEmpty() && m_type != IMAGE) return false;
+
+ // IMAGE needs special handling later
+ if(m_type != IMAGE) encoding += fixUpfromUnicode(codec, nme);
+
+ switch (m_type) {
+ case CHECKBOX:
+
+ if( checked() ) {
+ encoding += fixUpfromUnicode(codec, value().string());
+ return true;
+ }
+ break;
+
+ case RADIO:
+
+ if( checked() ) {
+ encoding += fixUpfromUnicode(codec, value().string());
+ return true;
+ }
+ break;
+
+ case BUTTON:
+ case RESET:
+ // those buttons are never successful
+ return false;
+
+ case IMAGE:
+
+ if(m_clicked)
+ {
+ m_clicked = false;
+ QString astr(nme.isEmpty() ? QString::fromLatin1("x") : nme + ".x");
+
+ encoding += fixUpfromUnicode(codec, astr);
+ astr.setNum(KMAX( clickX(), 0 ));
+ encoding += fixUpfromUnicode(codec, astr);
+ astr = nme.isEmpty() ? QString::fromLatin1("y") : nme + ".y";
+ encoding += fixUpfromUnicode(codec, astr);
+ astr.setNum(KMAX( clickY(), 0 ) );
+ encoding += fixUpfromUnicode(codec, astr);
+ astr = value().string();
+ if(astr.length() > 0) {
+ encoding += fixUpfromUnicode(codec, nme);
+ encoding += fixUpfromUnicode(codec, astr);
+ }
+
+ return true;
+ }
+ break;
+
+ case SUBMIT:
+
+ if (m_activeSubmit)
+ {
+ QString enc_str = valueWithDefault().string();
+ if(!enc_str.isEmpty())
+ {
+ encoding += fixUpfromUnicode(codec, enc_str);
+ return true;
+ }
+ }
+ break;
+
+ case FILE: // hmm, we have the type FILE also. bad choice here...
+ {
+ // don't submit if display: none or display: hidden
+ if(!renderer() || renderer()->style()->visibility() != khtml::VISIBLE)
+ return false;
+
+ QString local;
+ KURL fileurl;
+ QString val = value().string();
+ if (!val.isEmpty() &&
+ QDir::isRelativePath(val) &&
+ QFile::exists(KGlobalSettings::documentPath() + val)) {
+ fileurl.setPath(KGlobalSettings::documentPath() + val);
+ } else {
+ fileurl = KURL::fromPathOrURL(val);
+ }
+
+ KIO::UDSEntry filestat;
+
+ // can't submit file in www-url-form encoded
+ QWidget* const toplevel = static_cast<RenderSubmitButton*>(m_render)->widget()->topLevelWidget();
+ if (multipart) {
+ QCString filearray( "" );
+ if ( KIO::NetAccess::stat(fileurl, filestat, toplevel)) {
+ const KFileItem fileitem(filestat, fileurl, true, false);
+ if ( fileitem.isFile() &&
+ KIO::NetAccess::download(fileurl, local, toplevel) ) {
+ QFile file(local);
+ filearray.resize(file.size()+1);
+ if ( file.open( IO_ReadOnly ) ) {
+ const int readbytes = file.readBlock( filearray.data(), file.size());
+ if ( readbytes >= 0 )
+ filearray[readbytes] = '\0';
+ file.close();
+ }
+ KIO::NetAccess::removeTempFile( local );
+ }
+ }
+ encoding += filearray;
+ return true;
+ }
+ // else fall through
+ }
+ case HIDDEN:
+ case TEXT:
+ case PASSWORD:
+ // always successful
+ encoding += fixUpfromUnicode(codec, value().string());
+ return true;
+ case ISINDEX:
+ encoding += fixUpfromUnicode(codec, value().string());
+ return true;
+ }
+ return false;
+}
+
+void HTMLInputElementImpl::reset()
+{
+ if (m_type == FILE) {
+ // set directly to bypass security check. emptying the value
+ // should mean no risk.
+ if (!m_value.isEmpty()) {
+ m_value = DOMString();
+ setChanged();
+ }
+ } else {
+ setValue(getAttribute(ATTR_VALUE));
+ }
+ m_useDefaultChecked = true;
+ m_checked = m_defaultChecked;
+ setIndeterminate(true);
+}
+
+void HTMLInputElementImpl::setChecked(bool _checked)
+{
+ if (m_form && m_type == RADIO && _checked && !name().isEmpty())
+ m_form->radioClicked(this);
+
+ if (checked() == _checked) return;
+ m_useDefaultChecked = false;
+ m_checked = _checked;
+
+// setIndeterminate(false);
+
+ // Trigger dynamic restyles
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency);
+ // We need to update rendering under all circumstances
+ if (!changed() && m_render) {
+ m_render->updateFromElement();
+ }
+}
+
+void HTMLInputElementImpl::setIndeterminate(bool _indeterminate)
+{
+ // Only checkboxes and radio-boxes honor indeterminate.
+ if (inputType() != CHECKBOX || inputType() != RADIO || indeterminate() == _indeterminate)
+ return;
+
+ m_indeterminate = _indeterminate;
+
+ // Trigger dynamic restyles
+// getDocument()->dynamicDomRestyler().restyleDepedent(this, OtherStateDependency);
+ // We need to update rendering under all circumstances
+ if (!changed() && m_render) {
+ m_render->updateFromElement();
+ }
+}
+
+DOMString HTMLInputElementImpl::value() const
+{
+ if (m_type == CHECKBOX || m_type == RADIO) {
+ const DOMString val = getAttribute(ATTR_VALUE);
+ // If no attribute exists, then we'll just return "on" as
+ // other browsers strangely seem to do without respecting the
+ // checked() state of the control.
+ if (val.isNull())
+ return DOMString("on");
+ return val;
+ }
+
+ DOMString val = m_value;
+ // It's important *not* to fall back to the value attribute for file inputs,
+ // because that would allow a malicious web page to upload files by setting the
+ // value attribute in markup.
+ if (val.isNull() && m_type != FILE)
+ val = getAttribute(ATTR_VALUE);
+
+ return val.isNull() ? DOMString("") : val;
+}
+
+
+void HTMLInputElementImpl::setValue(DOMString val)
+{
+ if (m_type == FILE) return;
+
+ m_value = (val.isNull() ? DOMString("") : val);
+ // ### set attribute for other types, too. no need for m_value
+ // ### in those cases.
+ if (m_type == RADIO || m_type == CHECKBOX)
+ setAttribute(ATTR_VALUE, m_value);
+ if (m_type == TEXT && m_render)
+ m_render->updateFromElement();
+ setChanged();
+}
+
+void HTMLInputElementImpl::blur()
+{
+ if(getDocument()->focusNode() == this)
+ getDocument()->setFocusNode(0);
+}
+
+void HTMLInputElementImpl::focus()
+{
+ getDocument()->setFocusNode(this);
+}
+
+void HTMLInputElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ if ( !m_disabled )
+ {
+
+ if (evt->isMouseEvent()) {
+ MouseEventImpl* const me = static_cast<MouseEventImpl*>(evt);
+ if ((m_type == RADIO || m_type == CHECKBOX)
+ && me->id() == EventImpl::MOUSEUP_EVENT && me->detail() > 0) {
+ // click will follow
+ setChecked(m_type == RADIO ? true : !checked());
+ }
+ if (evt->id() == EventImpl::CLICK_EVENT && m_type == IMAGE && m_render) {
+ // record the mouse position for when we get the DOMActivate event
+ int offsetX, offsetY;
+ m_render->absolutePosition(offsetX,offsetY);
+ xPos = me->clientX()-offsetX;
+ yPos = me->clientY()-offsetY;
+ KHTMLView* v = getDocument()->view();
+ if ( v ) {
+ xPos += v->contentsX();
+ yPos += v->contentsY();
+ }
+ }
+ }
+
+ if (m_type == RADIO || m_type == CHECKBOX || m_type == SUBMIT || m_type == RESET || m_type == BUTTON ) {
+ bool check = false;
+ if (active() && ( evt->id() == EventImpl::KEYUP_EVENT ||
+ evt->id() == EventImpl::KEYPRESS_EVENT ) ) {
+ TextEventImpl* const te = static_cast<TextEventImpl *>(evt);
+ if (te->keyVal() == ' ')
+ check = true;
+ else if (te->keyVal() == '\r' && (m_type == BUTTON || m_type == RESET || m_type == SUBMIT))
+ check = true;
+ }
+ if (check) {
+ if (evt->id() == EventImpl::KEYUP_EVENT)
+ click();
+ // Tell the parent that we handle this key (keyup and keydown), even though only keyup activates (#70478)
+ evt->setDefaultHandled();
+ }
+ }
+
+
+ // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
+ // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
+ // on the element, or presses enter while it is the active element. Javascript code wishing to activate the element
+ // must dispatch a DOMActivate event - a click event will not do the job.
+ if (m_type == IMAGE || m_type == SUBMIT || m_type == RESET) {
+ bool act = (evt->id() == EventImpl::DOMACTIVATE_EVENT);
+ if (!act && evt->id() == EventImpl::KEYUP_EVENT && evt->isKeyRelatedEvent()) {
+ QKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent();
+ if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space))
+ act = true;
+ }
+ if (act)
+ activate();
+ }
+ }
+ HTMLGenericFormElementImpl::defaultEventHandler(evt);
+}
+
+void HTMLInputElementImpl::activate()
+{
+ if (!m_form)
+ return;
+
+ m_clicked = true;
+ if (m_type == RESET) {
+ m_form->reset();
+ }
+ else {
+ m_activeSubmit = true;
+ if (!m_form->prepareSubmit()) {
+ xPos = 0;
+ yPos = 0;
+ }
+ m_activeSubmit = false;
+ }
+}
+
+bool HTMLInputElementImpl::isEditable()
+{
+ return ((m_type == TEXT) || (m_type == PASSWORD) || (m_type == ISINDEX) || (m_type == FILE));
+}
+
+long HTMLInputElementImpl::selectionStart()
+{
+ if (m_type != TEXT || !m_render) return -1;
+ return static_cast<RenderLineEdit*>(m_render)->selectionStart();
+}
+
+long HTMLInputElementImpl::selectionEnd()
+{
+ if (m_type != TEXT || !m_render) return -1;
+ return static_cast<RenderLineEdit*>(m_render)->selectionEnd();
+}
+
+void HTMLInputElementImpl::setSelectionStart(long pos)
+{
+ if (m_type != TEXT || !m_render) return;
+ static_cast<RenderLineEdit*>(m_render)->setSelectionStart(pos);
+}
+
+void HTMLInputElementImpl::setSelectionEnd (long pos)
+{
+ if (m_type != TEXT || !m_render) return;
+ static_cast<RenderLineEdit*>(m_render)->setSelectionEnd(pos);
+}
+
+void HTMLInputElementImpl::setSelectionRange(long start, long end)
+{
+ if (m_type != TEXT || !m_render) return;
+ static_cast<RenderLineEdit*>(m_render)->setSelectionRange(start, end);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLLabelElementImpl::HTMLLabelElementImpl(DocumentImpl *doc)
+ : HTMLGenericFormElementImpl(doc)
+{
+}
+
+HTMLLabelElementImpl::~HTMLLabelElementImpl()
+{
+}
+
+NodeImpl::Id HTMLLabelElementImpl::id() const
+{
+ return ID_LABEL;
+}
+
+void HTMLLabelElementImpl::attach()
+{
+ // skip the generic handler
+ HTMLElementImpl::attach();
+}
+
+NodeImpl* HTMLLabelElementImpl::getFormElement()
+{
+ const DOMString formElementId = getAttribute(ATTR_FOR);
+ NodeImpl *newNode=0L;
+ if (!formElementId.isEmpty())
+ newNode=getDocument()->getElementById(formElementId);
+ if (!newNode){
+ const uint children=childNodeCount();
+ if (children>1)
+ for (unsigned int i=0;i<children;++i){
+ const uint nodeId=childNode(i)->id();
+ if (nodeId==ID_INPUT || nodeId==ID_SELECT || nodeId==ID_TEXTAREA){
+ newNode=childNode(i);
+ break;
+ }
+ }
+ }
+return newNode;
+}
+
+void HTMLLabelElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ if ( !m_disabled ) {
+ bool act = false;
+ if ( evt->id() == EventImpl::CLICK_EVENT ) {
+ act = true;
+ }
+ else if ( evt->isKeyRelatedEvent() && ( evt->id() == EventImpl::KEYUP_EVENT ||
+ evt->id() == EventImpl::KEYPRESS_EVENT ) ) {
+ QKeyEvent* const ke = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent();
+ if (ke && active() && (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Space))
+ act = true;
+ }
+
+ if (act) {
+ NodeImpl* const formNode=getFormElement();
+ if (formNode && evt->target() != formNode) {
+ getDocument()->setFocusNode(formNode);
+ if (formNode->id()==ID_INPUT)
+ static_cast<DOM::HTMLInputElementImpl*>(formNode)->click();
+ evt->setDefaultHandled();
+ }
+ }
+ }
+ HTMLGenericFormElementImpl::defaultEventHandler(evt);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLLegendElementImpl::HTMLLegendElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+}
+
+HTMLLegendElementImpl::~HTMLLegendElementImpl()
+{
+}
+
+NodeImpl::Id HTMLLegendElementImpl::id() const
+{
+ return ID_LEGEND;
+}
+
+void HTMLLegendElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+ RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && _style->display() != NONE) {
+ m_render = new (getDocument()->renderArena()) RenderLegend(this);
+ m_render->setStyle(_style);
+ }
+ HTMLGenericFormElementImpl::attach();
+ _style->deref();
+}
+
+void HTMLLegendElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ACCESSKEY:
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+HTMLSelectElementImpl::HTMLSelectElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+ m_multiple = false;
+ m_recalcListItems = false;
+ // 0 means invalid (i.e. not set)
+ m_size = 0;
+ m_minwidth = 0;
+ m_length = 0;
+}
+
+HTMLSelectElementImpl::~HTMLSelectElementImpl()
+{
+ if (getDocument()) getDocument()->deregisterMaintainsState(this);
+}
+
+NodeImpl::Id HTMLSelectElementImpl::id() const
+{
+ return ID_SELECT;
+}
+
+DOMString HTMLSelectElementImpl::type() const
+{
+ return (m_multiple ? "select-multiple" : "select-one");
+}
+
+long HTMLSelectElementImpl::selectedIndex() const
+{
+ // return the number of the first option selected
+ uint o = 0;
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ const unsigned int itemsSize = items.size();
+ for (unsigned int i = 0; i < itemsSize; ++i) {
+ if (items[i]->id() == ID_OPTION) {
+ if (static_cast<HTMLOptionElementImpl*>(items[i])->selected())
+ return o;
+ o++;
+ }
+ }
+ Q_ASSERT(m_multiple || items.isEmpty());
+ return -1;
+}
+
+void HTMLSelectElementImpl::setSelectedIndex( long index )
+{
+ // deselect all other options and select only the new one
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ int listIndex;
+ const int itemsSize = int(items.size());
+ for (listIndex = 0; listIndex < itemsSize; ++listIndex) {
+ if (items[listIndex]->id() == ID_OPTION)
+ static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(false);
+ }
+ listIndex = optionToListIndex(index);
+ if (listIndex >= 0)
+ static_cast<HTMLOptionElementImpl*>(items[listIndex])->setSelected(true);
+
+ setChanged(true);
+}
+
+long HTMLSelectElementImpl::length() const
+{
+ if (m_recalcListItems)
+ recalcListItems();
+ return m_length;
+}
+
+void HTMLSelectElementImpl::add( const HTMLElement &element, const HTMLElement &before, int& exceptioncode )
+{
+ if(element.isNull() || element.handle()->id() != ID_OPTION)
+ return;
+
+ HTMLOptionElementImpl* option = static_cast<HTMLOptionElementImpl*>(element.handle());;
+ //Fast path for appending an item. Can't be done if it is selected and
+ //we're single-select, since we may need to drop an implicitly-selected item
+ bool fastAppendLast = false;
+ if (before.handle() == 0 && (m_multiple || !option->selected()) && !m_recalcListItems)
+ fastAppendLast = true;
+
+ insertBefore(option, before.handle(), exceptioncode );
+
+ if (fastAppendLast) {
+ m_listItems.resize(m_listItems.size() + 1);
+ m_listItems[m_listItems.size() - 1] = option;
+ ++m_length;
+ m_recalcListItems = false;
+ } else if (!exceptioncode)
+ setRecalcListItems();
+}
+
+void HTMLSelectElementImpl::remove( long index )
+{
+ int exceptioncode = 0;
+ const int listIndex = optionToListIndex(index);
+
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ if(listIndex < 0 || index >= int(items.size()))
+ return; // ### what should we do ? remove the last item?
+
+ //Fast path for last element, for e.g. clearing the box
+ //Note that if this is a single-select, we may have to recompute
+ //anyway if the item was selected, since we may want to set
+ //a different one
+ bool fastRemoveLast = false;
+ if ((listIndex == (signed)items.size() - 1) && !m_recalcListItems &&
+ (m_multiple || !static_cast<HTMLOptionElementImpl*>(items[listIndex])->selected()))
+ fastRemoveLast = true;
+
+ removeChild(items[listIndex], exceptioncode);
+
+ if (fastRemoveLast) {
+ m_listItems.resize(m_listItems.size() - 1);
+ --m_length;
+ m_recalcListItems = false;
+ } else if( !exceptioncode)
+ setRecalcListItems();
+}
+
+void HTMLSelectElementImpl::blur()
+{
+ if(getDocument()->focusNode() == this)
+ getDocument()->setFocusNode(0);
+}
+
+void HTMLSelectElementImpl::focus()
+{
+ getDocument()->setFocusNode(this);
+}
+
+DOMString HTMLInputElementImpl::valueWithDefault() const
+{
+ DOMString v = value();
+ if (v.isEmpty()) {
+ switch (m_type) {
+ case RESET:
+#ifdef APPLE_CHANGES
+ v = resetButtonDefaultLabel();
+#else
+ v = i18n("Reset");
+#endif
+ break;
+
+ case SUBMIT:
+#ifdef APPLE_CHANGES
+ v = submitButtonDefaultLabel();
+#else
+ v = i18n("Submit");
+#endif
+ break;
+
+ case BUTTON:
+ case CHECKBOX:
+ case FILE:
+ case HIDDEN:
+ case IMAGE:
+ case ISINDEX:
+ case PASSWORD:
+ case RADIO:
+ #ifdef APPLE_CHANGES
+ case RANGE:
+ case SEARCH:
+ #endif
+ case TEXT:
+ break;
+ }
+ }
+ return v;
+}
+
+DOMString HTMLSelectElementImpl::value( ) const
+{
+ uint i;
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ const uint itemsSize = items.size();
+ for (i = 0; i < itemsSize; ++i) {
+ if ( items[i]->id() == ID_OPTION
+ && static_cast<HTMLOptionElementImpl*>(items[i])->selected())
+ return static_cast<HTMLOptionElementImpl*>(items[i])->value();
+ }
+ return DOMString("");
+}
+
+void HTMLSelectElementImpl::setValue(DOMStringImpl* value)
+{
+ // find the option with value() matching the given parameter
+ // and make it the current selection.
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ for (unsigned i = 0; i < items.size(); i++)
+ if (items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->value() == value) {
+ static_cast<HTMLOptionElementImpl*>(items[i])->setSelected(true);
+ return;
+ }
+}
+
+QString HTMLSelectElementImpl::state( )
+{
+ QString state;
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+
+ const int l = items.count();
+
+ state.fill('.', l);
+ for(int i = 0; i < l; ++i)
+ if(items[i]->id() == ID_OPTION && static_cast<HTMLOptionElementImpl*>(items[i])->selected())
+ state[i] = 'X';
+
+ return state;
+}
+
+void HTMLSelectElementImpl::restoreState(const QString &_state)
+{
+ recalcListItems();
+
+ QString state = _state;
+ if(!state.isEmpty() && !state.contains('X') && !m_multiple && m_size <= 1) {
+ qWarning("should not happen in restoreState!");
+ state[0] = 'X';
+ }
+
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+
+ const int l = items.count();
+ for(int i = 0; i < l; ++i) {
+ if(items[i]->id() == ID_OPTION) {
+ HTMLOptionElementImpl* const oe = static_cast<HTMLOptionElementImpl*>(items[i]);
+ oe->setSelected(state[i] == 'X');
+ }
+ }
+ setChanged(true);
+}
+
+NodeImpl *HTMLSelectElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
+{
+ NodeImpl* const result = HTMLGenericFormElementImpl::insertBefore(newChild,refChild, exceptioncode );
+ if (!exceptioncode)
+ setRecalcListItems();
+ return result;
+}
+
+void HTMLSelectElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
+{
+ HTMLGenericFormElementImpl::replaceChild(newChild,oldChild, exceptioncode);
+ if( !exceptioncode )
+ setRecalcListItems();
+}
+
+void HTMLSelectElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
+{
+ HTMLGenericFormElementImpl::removeChild(oldChild, exceptioncode);
+ if( !exceptioncode )
+ setRecalcListItems();
+}
+
+NodeImpl *HTMLSelectElementImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
+{
+ NodeImpl* const result = HTMLGenericFormElementImpl::appendChild(newChild, exceptioncode);
+ if( !exceptioncode )
+ setRecalcListItems();
+ setChanged(true);
+ return result;
+}
+
+NodeImpl* HTMLSelectElementImpl::addChild(NodeImpl* newChild)
+{
+ setRecalcListItems();
+ return HTMLGenericFormElementImpl::addChild(newChild);
+}
+
+void HTMLSelectElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_SIZE:
+ m_size = kMax( attr->val()->toInt(), 1 );
+ setChanged();
+ break;
+ case ATTR_WIDTH:
+ m_minwidth = kMax( attr->val()->toInt(), 0 );
+ break;
+ case ATTR_MULTIPLE:
+ m_multiple = (attr->val() != 0);
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_ONCHANGE:
+ setHTMLEventListener(EventImpl::CHANGE_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this));
+ break;
+ default:
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLSelectElementImpl::attach()
+{
+ assert(!attached());
+ assert(parentNode());
+ assert(!renderer());
+
+ RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && _style->display() != NONE) {
+ m_render = new (getDocument()->renderArena()) RenderSelect(this);
+ m_render->setStyle(_style);
+ }
+
+ HTMLGenericFormElementImpl::attach();
+ _style->deref();
+}
+
+bool HTMLSelectElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoded_values, bool)
+{
+ bool successful = false;
+ const QCString enc_name = fixUpfromUnicode(codec, name().string());
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+
+ uint i;
+ const uint itemsSize = items.size();
+ for (i = 0; i < itemsSize; ++i) {
+ if (items[i]->id() == ID_OPTION) {
+ HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[i]);
+ if (option->selected()) {
+ encoded_values += enc_name;
+ encoded_values += fixUpfromUnicode(codec, option->value().string());
+ successful = true;
+ }
+ }
+ }
+
+ // ### this case should not happen. make sure that we select the first option
+ // in any case. otherwise we have no consistency with the DOM interface. FIXME!
+ // we return the first one if it was a combobox select
+ if (!successful && !m_multiple && m_size <= 1 && itemsSize &&
+ (items[0]->id() == ID_OPTION) ) {
+ HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[0]);
+ encoded_values += enc_name;
+ if (option->value().isNull())
+ encoded_values += fixUpfromUnicode(codec, option->text().string().stripWhiteSpace());
+ else
+ encoded_values += fixUpfromUnicode(codec, option->value().string());
+ successful = true;
+ }
+
+ return successful;
+}
+
+int HTMLSelectElementImpl::optionToListIndex(int optionIndex) const
+{
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ const int itemsSize = int(items.size());
+ if (optionIndex < 0 || optionIndex >= itemsSize)
+ return -1;
+
+ //See if we're asked for the very last item, and check whether it's an <option>
+ //to fastpath clear
+ if ((unsigned int)optionIndex == (m_length - 1) && items[itemsSize - 1]->id() == ID_OPTION)
+ return itemsSize - 1;
+
+ int listIndex = 0;
+ int optionIndex2 = 0;
+ for (;
+ optionIndex2 < itemsSize && optionIndex2 <= optionIndex;
+ ++listIndex) { // not a typo!
+ if (items[listIndex]->id() == ID_OPTION)
+ ++optionIndex2;
+ }
+ --listIndex;
+ return listIndex;
+}
+
+int HTMLSelectElementImpl::listToOptionIndex(int listIndex) const
+{
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ if (listIndex < 0 || listIndex >= int(items.size()) ||
+ items[listIndex]->id() != ID_OPTION)
+ return -1;
+
+ int optionIndex = 0; // actual index of option not counting OPTGROUP entries that may be in list
+ int i;
+ for (i = 0; i < listIndex; i++)
+ if (items[i]->id() == ID_OPTION)
+ optionIndex++;
+ return optionIndex;
+}
+
+void HTMLSelectElementImpl::recalcListItems() const
+{
+ NodeImpl* current = firstChild();
+ m_listItems.resize(0);
+ HTMLOptionElementImpl* foundSelected = 0;
+ m_length = 0;
+ while(current) {
+ if (current->id() == ID_OPTGROUP && current->firstChild()) {
+ // ### what if optgroup contains just comments? don't want one of no options in it...
+ m_listItems.resize(m_listItems.size()+1);
+ m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current);
+ current = current->firstChild();
+ }
+ if (current->id() == ID_OPTION) {
+ ++m_length;
+ m_listItems.resize(m_listItems.size()+1);
+ m_listItems[m_listItems.size()-1] = static_cast<HTMLGenericFormElementImpl*>(current);
+ if (!foundSelected && !m_multiple && m_size <= 1) {
+ foundSelected = static_cast<HTMLOptionElementImpl*>(current);
+ foundSelected->m_selected = true;
+ }
+ else if (foundSelected && !m_multiple && static_cast<HTMLOptionElementImpl*>(current)->selected()) {
+ foundSelected->m_selected = false;
+ foundSelected = static_cast<HTMLOptionElementImpl*>(current);
+ }
+ }
+ NodeImpl* const parent = current->parentNode();
+ current = current->nextSibling();
+ if (!current) {
+ if (static_cast<const NodeImpl *>(parent) != this)
+ current = parent->nextSibling();
+ }
+ }
+ m_recalcListItems = false;
+}
+
+void HTMLSelectElementImpl::childrenChanged()
+{
+ setRecalcListItems();
+
+ HTMLGenericFormElementImpl::childrenChanged();
+}
+
+void HTMLSelectElementImpl::setRecalcListItems()
+{
+ m_recalcListItems = true;
+ if (m_render)
+ static_cast<khtml::RenderSelect*>(m_render)->setOptionsChanged(true);
+ setChanged();
+}
+
+void HTMLSelectElementImpl::reset()
+{
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ uint i;
+ const uint itemsSize = items.size();
+ bool anySelected = false;
+ for (i = 0; i < itemsSize; ++i) {
+ if (items[i]->id() == ID_OPTION) {
+ HTMLOptionElementImpl* const option = static_cast<HTMLOptionElementImpl*>(items[i]);
+ const bool selected = (!option->getAttribute(ATTR_SELECTED).isNull());
+ option->setSelected(selected);
+ if (selected)
+ anySelected = true;
+ }
+ }
+ // If this is a single-row SELECT and there is no default selection, jump to first option.
+ if ( !anySelected && m_size <= 1 ) {
+ for (i = 0; i < itemsSize; ++i) {
+ if (items[i]->id() == ID_OPTION) {
+ static_cast<HTMLOptionElementImpl*>(items[i])->setSelected(true);
+ break;
+ }
+ }
+ }
+ if ( m_render )
+ static_cast<RenderSelect*>(m_render)->setSelectionChanged(true);
+ setChanged( true );
+}
+
+void HTMLSelectElementImpl::notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected)
+{
+ if (selected && !m_multiple) {
+ // deselect all other options
+ QMemArray<HTMLGenericFormElementImpl*> items = listItems();
+ uint i;
+ const uint itemsSize = items.size();
+ for (i = 0; i < itemsSize; ++i) {
+ if (items[i]->id() == ID_OPTION)
+ static_cast<HTMLOptionElementImpl*>(items[i])->m_selected = (items[i] == selectedOption);
+ }
+ }
+ if (m_render)
+ static_cast<RenderSelect*>(m_render)->setSelectionChanged(true);
+
+ setChanged(true);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLKeygenElementImpl::HTMLKeygenElementImpl(DocumentImpl* doc, HTMLFormElementImpl* f)
+ : HTMLSelectElementImpl(doc, f)
+{
+ const QStringList keys = KSSLKeyGen::supportedKeySizes();
+ QStringList::ConstIterator i = keys.begin();
+ const QStringList::ConstIterator iEnd = keys.end();
+ for ( ; i != iEnd; ++i) {
+ HTMLOptionElementImpl* const o = new HTMLOptionElementImpl(doc, form());
+ addChild(o);
+ o->addChild(doc->createTextNode(DOMString(*i).implementation()));
+ }
+}
+
+NodeImpl::Id HTMLKeygenElementImpl::id() const
+{
+ return ID_KEYGEN;
+}
+
+void HTMLKeygenElementImpl::parseAttribute(AttributeImpl* attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_CHALLENGE:
+ break;
+ default:
+ // skip HTMLSelectElementImpl parsing!
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+bool HTMLKeygenElementImpl::encoding(const QTextCodec* codec, khtml::encodingList& encoded_values, bool)
+{
+ bool successful = false;
+ const QCString enc_name = fixUpfromUnicode(codec, name().string());
+
+ encoded_values += enc_name;
+
+ // pop up the fancy certificate creation dialog here
+ KSSLKeyGen* const kg = new KSSLKeyGen(getDocument()->view(), "Key Generator", true);
+
+ kg->setKeySize(0);
+ successful = (QDialog::Accepted == kg->exec());
+
+ delete kg;
+
+ encoded_values += "deadbeef";
+
+ return successful;
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLOptGroupElementImpl::id() const
+{
+ return ID_OPTGROUP;
+}
+
+// -------------------------------------------------------------------------
+
+HTMLOptionElementImpl::HTMLOptionElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+ m_selected = false;
+}
+
+NodeImpl::Id HTMLOptionElementImpl::id() const
+{
+ return ID_OPTION;
+}
+
+DOMString HTMLOptionElementImpl::text() const
+{
+ if (firstChild() && firstChild()->nodeType() == Node::TEXT_NODE) {
+ if (firstChild()->nextSibling()) {
+ DOMString ret = "";
+ NodeImpl *n = firstChild();
+ for (; n; n = n->nextSibling()) {
+ if (n->nodeType() == Node::TEXT_NODE ||
+ n->nodeType() == Node::CDATA_SECTION_NODE)
+ ret += n->nodeValue();
+ }
+ return ret;
+ }
+ else
+ return firstChild()->nodeValue();
+ }
+ return "";
+}
+
+long HTMLOptionElementImpl::index() const
+{
+ // Let's do this dynamically. Might be a bit slow, but we're sure
+ // we won't forget to update a member variable in some cases...
+ QMemArray<HTMLGenericFormElementImpl*> items = getSelect()->listItems();
+ const int l = items.count();
+ int optionIndex = 0;
+ for(int i = 0; i < l; ++i) {
+ if(items[i]->id() == ID_OPTION)
+ {
+ if (static_cast<HTMLOptionElementImpl*>(items[i]) == this)
+ return optionIndex;
+ ++optionIndex;
+ }
+ }
+ kdWarning() << "HTMLOptionElementImpl::index(): option not found!" << endl;
+ return 0;
+}
+
+void HTMLOptionElementImpl::setIndex( long )
+{
+ kdWarning() << "Unimplemented HTMLOptionElementImpl::setIndex(long) called" << endl;
+ // ###
+}
+
+void HTMLOptionElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_SELECTED:
+ m_selected = (attr->val() != 0);
+ break;
+ case ATTR_VALUE:
+ m_value = attr->value();
+ break;
+ default:
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+DOMString HTMLOptionElementImpl::value() const
+{
+ if ( !m_value.isNull() )
+ return m_value;
+ // Use the text if the value wasn't set.
+ return text().string().simplifyWhiteSpace();
+}
+
+void HTMLOptionElementImpl::setValue(DOMStringImpl* value)
+{
+ setAttribute(ATTR_VALUE, value);
+}
+
+void HTMLOptionElementImpl::setSelected(bool _selected)
+{
+ if(m_selected == _selected)
+ return;
+ m_selected = _selected;
+ HTMLSelectElementImpl* const select = getSelect();
+ if (select)
+ select->notifyOptionSelected(this,_selected);
+}
+
+HTMLSelectElementImpl *HTMLOptionElementImpl::getSelect() const
+{
+ NodeImpl *select = parentNode();
+ while (select && select->id() != ID_SELECT)
+ select = select->parentNode();
+ return static_cast<HTMLSelectElementImpl*>(select);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLTextAreaElementImpl::HTMLTextAreaElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLGenericFormElementImpl(doc, f)
+{
+ // DTD requires rows & cols be specified, but we will provide reasonable defaults
+ m_rows = 2;
+ m_cols = 20;
+ m_wrap = ta_Virtual;
+ m_changed = false;
+ m_dirtyvalue = true;
+ m_initialized = false;
+ m_unsubmittedFormChange = false;
+}
+
+HTMLTextAreaElementImpl::~HTMLTextAreaElementImpl()
+{
+ if (getDocument()) getDocument()->deregisterMaintainsState(this);
+}
+
+NodeImpl::Id HTMLTextAreaElementImpl::id() const
+{
+ return ID_TEXTAREA;
+}
+
+DOMString HTMLTextAreaElementImpl::type() const
+{
+ return "textarea";
+}
+
+QString HTMLTextAreaElementImpl::state( )
+{
+ return value().string() + (m_unsubmittedFormChange ? 'M' : '.');
+}
+
+void HTMLTextAreaElementImpl::restoreState(const QString &state)
+{
+ setDefaultValue(state.left(state.length()-1));
+ m_unsubmittedFormChange = state.endsWith("M");
+ // the close() in the rendertree will take care of transferring defaultvalue to 'value'
+}
+
+void HTMLTextAreaElementImpl::select( )
+{
+ if (m_render)
+ static_cast<RenderTextArea*>(m_render)->select();
+ onSelect();
+}
+
+void HTMLTextAreaElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ROWS:
+ m_rows = 0;
+ if (attr->val())
+ m_rows = DOMString(attr->val()).string().toInt();
+ if (!m_rows) m_rows = 2;
+ if (renderer())
+ renderer()->setNeedsLayoutAndMinMaxRecalc();
+ break;
+ case ATTR_COLS:
+ m_cols = 0;
+ if (attr->val())
+ m_cols = DOMString(attr->val()).string().toInt();
+ if (!m_cols) m_cols = 20;
+ if (renderer())
+ renderer()->setNeedsLayoutAndMinMaxRecalc();
+ break;
+ case ATTR_WRAP:
+ // virtual / physical is Netscape extension of HTML 3.0, now deprecated
+ // soft/ hard / off is recommendation for HTML 4 extension by IE and NS 4
+ if ( strcasecmp( attr->value(), "virtual" ) == 0 || strcasecmp( attr->value(), "soft") == 0)
+ m_wrap = ta_Virtual;
+ else if ( strcasecmp ( attr->value(), "physical" ) == 0 || strcasecmp( attr->value(), "hard") == 0)
+ m_wrap = ta_Physical;
+ else if(strcasecmp( attr->value(), "on" ) == 0)
+ m_wrap = ta_Physical;
+ else if(strcasecmp( attr->value(), "off") == 0)
+ m_wrap = ta_NoWrap;
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ case ATTR_ALIGN:
+ break;
+ case ATTR_ONSELECT:
+ setHTMLEventListener(EventImpl::SELECT_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onselect", this));
+ break;
+ case ATTR_ONCHANGE:
+ setHTMLEventListener(EventImpl::CHANGE_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onchange", this));
+ break;
+ default:
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLTextAreaElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ RenderStyle* const _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && _style->display() != NONE) {
+ m_render = new (getDocument()->renderArena()) RenderTextArea(this);
+ m_render->setStyle(_style);
+ }
+
+ HTMLGenericFormElementImpl::attach();
+ _style->deref();
+}
+
+
+static QString expandLF(const QString& s)
+{
+ // LF -> CRLF
+ unsigned crs = s.contains( '\n' );
+ if (crs == 0)
+ return s;
+ unsigned len = s.length();
+
+ QString r;
+ r.reserve(len + crs + 1);
+ unsigned pos2 = 0;
+ for(unsigned pos = 0; pos < len; pos++)
+ {
+ QChar c = s.at(pos);
+ switch(c.unicode())
+ {
+ case '\n':
+ r[pos2++] = '\r';
+ r[pos2++] = '\n';
+ break;
+
+ case '\r':
+ break;
+
+ default:
+ r[pos2++]= c;
+ break;
+ }
+ }
+ r.squeeze();
+ return r;
+}
+
+
+bool HTMLTextAreaElementImpl::encoding(const QTextCodec* codec, encodingList& encoding, bool)
+{
+ if (name().isEmpty()) return false;
+
+ encoding += fixUpfromUnicode(codec, name().string());
+ encoding += fixUpfromUnicode(codec, expandLF(value().string()));
+
+ return true;
+}
+
+void HTMLTextAreaElementImpl::reset()
+{
+ setValue(defaultValue());
+}
+
+
+DOMString HTMLTextAreaElementImpl::value()
+{
+ if ( m_dirtyvalue) {
+ if ( m_render && m_initialized ) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ m_value = renderArea->text();
+ m_dirtyvalue = false;
+ } else {
+ m_value = defaultValue().string();
+ m_initialized = true;
+ m_dirtyvalue = false;
+ }
+ }
+
+ if ( m_value.isNull() ) return "";
+
+ return m_value;
+}
+
+void HTMLTextAreaElementImpl::setValue(DOMString _value)
+{
+ // \r\n -> \n, \r -> \n
+ QString str = _value.string().replace( "\r\n", "\n" );
+ m_value = str.replace( '\r', '\n' );
+ m_dirtyvalue = false;
+ m_initialized = true;
+ setChanged(true);
+}
+
+DOMString HTMLTextAreaElementImpl::defaultValue()
+{
+ DOMString val = "";
+ // there may be comments - just grab the text nodes
+ NodeImpl *n;
+ for (n = firstChild(); n; n = n->nextSibling())
+ if (n->isTextNode())
+ val += static_cast<TextImpl*>(n)->data();
+
+ if (val[0] == '\r' && val[1] == '\n') {
+ val = val.copy();
+ val.remove(0,2);
+ }
+ else if (val[0] == '\r' || val[0] == '\n') {
+ val = val.copy();
+ val.remove(0,1);
+ }
+
+ return val;
+}
+
+void HTMLTextAreaElementImpl::setDefaultValue(DOMString _defaultValue)
+{
+ // there may be comments - remove all the text nodes and replace them with one
+ QPtrList<NodeImpl> toRemove;
+ NodeImpl *n;
+ for (n = firstChild(); n; n = n->nextSibling())
+ if (n->isTextNode())
+ toRemove.append(n);
+ QPtrListIterator<NodeImpl> it(toRemove);
+ int exceptioncode = 0;
+ for (; it.current(); ++it) {
+ removeChild(it.current(), exceptioncode);
+ }
+ insertBefore(getDocument()->createTextNode(_defaultValue.implementation()),firstChild(), exceptioncode);
+ setValue(_defaultValue);
+}
+
+void HTMLTextAreaElementImpl::blur()
+{
+ if(getDocument()->focusNode() == this)
+ getDocument()->setFocusNode(0);
+}
+
+void HTMLTextAreaElementImpl::focus()
+{
+ getDocument()->setFocusNode(this);
+}
+
+bool HTMLTextAreaElementImpl::isEditable()
+{
+ return true;
+}
+
+//Mozilla extensions.
+long HTMLTextAreaElementImpl::selectionStart()
+{
+ if (m_render) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ return renderArea->selectionStart();
+ }
+
+ return 0;
+}
+
+long HTMLTextAreaElementImpl::selectionEnd()
+{
+ if (m_render) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ return renderArea->selectionEnd();
+ }
+
+ return 0;
+}
+
+void HTMLTextAreaElementImpl::setSelectionStart(long pos)
+{
+ if (m_render) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ renderArea->setSelectionStart( pos );
+ }
+}
+
+void HTMLTextAreaElementImpl::setSelectionEnd(long pos)
+{
+ if (m_render) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ renderArea->setSelectionEnd( pos );
+ }
+}
+
+void HTMLTextAreaElementImpl::setSelectionRange(long start, long end)
+{
+ if (m_render) {
+ RenderTextArea* renderArea = static_cast<RenderTextArea*>( m_render );
+ renderArea->setSelectionRange( start, end );
+ }
+}
+
+long HTMLTextAreaElementImpl::textLength()
+{
+ return value().length();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLIsIndexElementImpl::HTMLIsIndexElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLInputElementImpl(doc, f)
+{
+ m_type = TEXT;
+ setName("isindex");
+}
+
+HTMLIsIndexElementImpl::~HTMLIsIndexElementImpl()
+{
+}
+
+NodeImpl::Id HTMLIsIndexElementImpl::id() const
+{
+ return ID_ISINDEX;
+}
+
+void HTMLIsIndexElementImpl::parseAttribute(AttributeImpl* attr)
+{
+ // don't call HTMLInputElement::parseAttribute here, as it would
+ // accept attributes this element does not support
+ HTMLGenericFormElementImpl::parseAttribute(attr);
+}
+
+DOMString HTMLIsIndexElementImpl::prompt() const
+{
+ // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created.
+ // So we have to look at the previous sibling to find the prompt text
+ DOM::NodeImpl* const prev = previousSibling();
+ if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE)
+ return prev->nodeValue();
+ return "";
+}
+
+void HTMLIsIndexElementImpl::setPrompt(const DOMString& str)
+{
+ // When IsIndex is parsed, <HR/>Prompt: <ISINDEX/><HR/> is created.
+ // So we have to look at the previous sibling to find the prompt text
+ int exceptioncode = 0;
+ DOM::NodeImpl* const prev = previousSibling();
+ if ( prev && prev->nodeType() == DOM::Node::TEXT_NODE)
+ static_cast<DOM::TextImpl *>(prev)->setData(str, exceptioncode);
+}
+
+// -------------------------------------------------------------------------
+
diff --git a/khtml/html/html_formimpl.h b/khtml/html/html_formimpl.h
new file mode 100644
index 000000000..f12821340
--- /dev/null
+++ b/khtml/html/html_formimpl.h
@@ -0,0 +1,606 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_FORMIMPL_H
+#define HTML_FORMIMPL_H
+
+#include "html/html_elementimpl.h"
+#include "html/html_imageimpl.h"
+#include "dom/html_element.h"
+
+#include <qvaluelist.h>
+#include <qptrlist.h>
+#include <qcstring.h>
+#include <qmemarray.h>
+
+class KHTMLView;
+class QTextCodec;
+
+namespace khtml
+{
+ class RenderFormElement;
+ class RenderTextArea;
+ class RenderSelect;
+ class RenderLineEdit;
+ class RenderRadioButton;
+ class RenderFileButton;
+
+ typedef QValueList<QCString> encodingList;
+}
+
+namespace KWallet {
+ class Wallet;
+}
+
+namespace DOM {
+
+class HTMLFormElement;
+class DOMString;
+class HTMLGenericFormElementImpl;
+class HTMLOptionElementImpl;
+
+// -------------------------------------------------------------------------
+
+class HTMLFormElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLFormElementImpl(DocumentImpl *doc, bool implicit);
+ virtual ~HTMLFormElementImpl();
+
+ virtual Id id() const;
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void addId(const QString& id);
+ virtual void removeId(const QString& id);
+
+
+ long length() const;
+
+ QByteArray formData(bool& ok);
+
+ DOMString enctype() const { return m_enctype; }
+ void setEnctype( const DOMString & );
+
+ bool autoComplete() const { return m_autocomplete; }
+ void doAutoFill();
+ void walletOpened(KWallet::Wallet *w);
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ void radioClicked( HTMLGenericFormElementImpl *caller );
+
+ void registerFormElement(HTMLGenericFormElementImpl *);
+ void removeFormElement(HTMLGenericFormElementImpl *);
+ void registerImgElement(HTMLImageElementImpl *);
+ void removeImgElement(HTMLImageElementImpl *);
+
+ void submitFromKeyboard();
+ bool prepareSubmit();
+ void submit();
+ void reset();
+
+ void setMalformed(bool malformed) { m_malformed = malformed; }
+ bool isMalformed() const { return m_malformed; }
+
+ friend class HTMLFormElement;
+ friend class HTMLFormCollectionImpl;
+
+private:
+ void gatherWalletData();
+ QPtrList<HTMLGenericFormElementImpl> formElements;
+ QPtrList<HTMLImageElementImpl> imgElements;
+ DOMString m_target;
+ DOMString m_enctype;
+ QString m_boundary;
+ DOMString m_acceptcharset;
+ QString m_encCharset;
+ bool m_post : 1;
+ bool m_multipart : 1;
+ bool m_autocomplete : 1;
+ bool m_insubmit : 1;
+ bool m_doingsubmit : 1;
+ bool m_inreset : 1;
+ bool m_malformed : 1;
+ bool m_haveTextarea : 1; // for wallet storage
+ bool m_havePassword : 1; // for wallet storage
+ DOMString m_name; // our name
+ QMap<QString, QString> m_walletMap; // for wallet storage
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLGenericFormElementImpl : public HTMLElementImpl
+{
+ friend class HTMLFormElementImpl;
+ friend class khtml::RenderFormElement;
+
+public:
+ HTMLGenericFormElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ virtual ~HTMLGenericFormElementImpl();
+
+ HTMLFormElementImpl *form() { return m_form; }
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+ virtual void reset() {}
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
+ void onSelect();
+ void onChange();
+
+ bool disabled() const { return m_disabled; }
+ void setDisabled(bool _disabled);
+
+ virtual bool isFocusable() const;
+ virtual bool isEnumeratable() const { return false; }
+
+ bool readOnly() const { return m_readOnly; }
+ void setReadOnly(bool _readOnly) { m_readOnly = _readOnly; }
+
+ DOMString name() const;
+ void setName(const DOMString& name);
+
+ virtual bool isGenericFormElement() const { return true; }
+
+ /*
+ * override in derived classes to get the encoded name=value pair
+ * for submitting
+ * return true for a successful control (see HTML4-17.13.2)
+ */
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool) { return false; }
+
+ virtual void defaultEventHandler(EventImpl *evt);
+ virtual bool isEditable();
+
+protected:
+ HTMLFormElementImpl *getForm() const;
+
+ DOMStringImpl* m_name;
+ HTMLFormElementImpl *m_form;
+ bool m_disabled, m_readOnly;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLButtonElementImpl : public HTMLGenericFormElementImpl
+{
+public:
+ HTMLButtonElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+
+ virtual ~HTMLButtonElementImpl();
+
+ enum typeEnum {
+ SUBMIT,
+ RESET,
+ BUTTON
+ };
+
+ virtual Id id() const;
+ virtual bool isEnumeratable() const { return true; }
+
+ DOMString type() const;
+ typeEnum buttonType() const { return m_type; }
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void defaultEventHandler(EventImpl *evt);
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool);
+ void activate();
+ virtual void attach();
+ void click();
+ void blur();
+ void focus();
+
+protected:
+ DOMString m_value;
+ QString m_currValue;
+ typeEnum m_type : 2;
+ bool m_dirty : 1;
+ bool m_clicked : 1;
+ bool m_activeSubmit : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLFieldSetElementImpl : public HTMLGenericFormElementImpl
+{
+public:
+ HTMLFieldSetElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+
+ virtual ~HTMLFieldSetElementImpl();
+
+ virtual Id id() const;
+ virtual void attach();
+ virtual void parseAttribute(AttributeImpl *attr);
+
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLInputElementImpl : public HTMLGenericFormElementImpl
+{
+ friend class khtml::RenderLineEdit;
+ friend class khtml::RenderRadioButton;
+ friend class khtml::RenderFileButton;
+
+public:
+ // do not change the order!
+ enum typeEnum {
+ TEXT,
+ PASSWORD,
+ ISINDEX,
+ CHECKBOX,
+ RADIO,
+ SUBMIT,
+ RESET,
+ FILE,
+ HIDDEN,
+ IMAGE,
+ BUTTON
+ };
+
+ HTMLInputElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ virtual ~HTMLInputElementImpl();
+
+ virtual Id id() const;
+
+ virtual bool isEnumeratable() const { return inputType() != IMAGE; }
+
+ bool autoComplete() const { return m_autocomplete; }
+
+ bool checked() const { return m_useDefaultChecked ? m_defaultChecked : m_checked; }
+ void setChecked(bool);
+ bool indeterminate() const { return m_indeterminate; }
+ void setIndeterminate(bool);
+ long maxLength() const { return m_maxLen; }
+ int size() const { return m_size; }
+ DOMString type() const;
+ void setType(const DOMString& t);
+
+ DOMString value() const;
+ void setValue(DOMString val);
+
+ DOMString valueWithDefault() const;
+
+ void blur();
+ void focus();
+
+ virtual bool maintainsState() { return true; }
+ virtual QString state();
+ virtual void restoreState(const QString &state);
+
+ void select();
+ void click();
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ virtual void attach();
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool);
+
+ typeEnum inputType() const { return m_type; }
+ virtual void reset();
+
+ // used in case input type=image was clicked.
+ int clickX() const { return xPos; }
+ int clickY() const { return yPos; }
+
+ virtual void defaultEventHandler(EventImpl *evt);
+ virtual bool isEditable();
+
+ DOMString altText() const;
+ void activate();
+
+ void setUnsubmittedFormChange(bool unsubmitted) { m_unsubmittedFormChange = unsubmitted; }
+
+ //Mozilla extensions.
+ long selectionStart();
+ long selectionEnd();
+ void setSelectionStart(long pos);
+ void setSelectionEnd (long pos);
+ void setSelectionRange(long start, long end);
+protected:
+ void parseType(const DOMString& t);
+
+ DOMString m_value;
+ int xPos;
+ short m_maxLen;
+ short m_size;
+ short yPos;
+
+ typeEnum m_type : 4;
+ bool m_clicked : 1 ;
+ bool m_checked : 1;
+ bool m_defaultChecked : 1; // could do without by checking ATTR_CHECKED
+ bool m_useDefaultChecked : 1;
+ bool m_indeterminate : 1;
+ bool m_haveType : 1;
+ bool m_activeSubmit : 1;
+ bool m_autocomplete : 1;
+ bool m_inited : 1;
+ bool m_unsubmittedFormChange : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLLabelElementImpl : public HTMLGenericFormElementImpl
+{
+public:
+ HTMLLabelElementImpl(DocumentImpl *doc);
+ virtual ~HTMLLabelElementImpl();
+
+ virtual Id id() const;
+ virtual void attach();
+ virtual void defaultEventHandler(EventImpl *evt);
+ virtual bool isFocusable() const { return true; };
+ virtual bool isTabFocusable() const { return false; };
+ NodeImpl* getFormElement();
+
+ private:
+ DOMString m_formElementID;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLLegendElementImpl : public HTMLGenericFormElementImpl
+{
+public:
+ HTMLLegendElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ virtual ~HTMLLegendElementImpl();
+
+ virtual Id id() const;
+ virtual void attach();
+ virtual void parseAttribute(AttributeImpl *attr);
+};
+
+
+// -------------------------------------------------------------------------
+
+class HTMLSelectElementImpl : public HTMLGenericFormElementImpl
+{
+ friend class khtml::RenderSelect;
+
+public:
+ HTMLSelectElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ ~HTMLSelectElementImpl();
+
+ virtual Id id() const;
+
+ DOMString type() const;
+
+ long selectedIndex() const;
+ void setSelectedIndex( long index );
+
+ virtual bool isEnumeratable() const { return true; }
+
+ long length() const;
+
+ long minWidth() const { return m_minwidth; }
+
+ long size() const { return m_size; }
+
+ bool multiple() const { return m_multiple; }
+
+ void add ( const HTMLElement &element, const HTMLElement &before, int& exceptioncode );
+ void remove ( long index );
+ void blur();
+ void focus();
+
+ DOMString value() const;
+ void setValue(DOMStringImpl* value);
+
+ virtual bool maintainsState() { return true; }
+ virtual QString state();
+ virtual void restoreState(const QString &state);
+
+ virtual NodeImpl *insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode );
+ virtual void replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode );
+ virtual void removeChild ( NodeImpl *oldChild, int &exceptioncode );
+ virtual NodeImpl *appendChild ( NodeImpl *newChild, int &exceptioncode );
+ virtual NodeImpl *addChild( NodeImpl* newChild );
+
+ virtual void childrenChanged();
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ virtual void attach();
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool);
+
+ // get the actual listbox index of the optionIndexth option
+ int optionToListIndex(int optionIndex) const;
+ // reverse of optionToListIndex - get optionIndex from listboxIndex
+ int listToOptionIndex(int listIndex) const;
+
+ void setRecalcListItems();
+
+ QMemArray<HTMLGenericFormElementImpl*> listItems() const
+ {
+ if (m_recalcListItems) const_cast<HTMLSelectElementImpl*>(this)->recalcListItems();
+ return m_listItems;
+ }
+ virtual void reset();
+ void notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected);
+
+private:
+ void recalcListItems() const;
+
+protected:
+ mutable QMemArray<HTMLGenericFormElementImpl*> m_listItems;
+ short m_minwidth;
+ signed short m_size : 15;
+ bool m_multiple : 1;
+ mutable bool m_recalcListItems :1;
+ mutable unsigned int m_length:31;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLKeygenElementImpl : public HTMLSelectElementImpl
+{
+public:
+ HTMLKeygenElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+
+ virtual Id id() const;
+
+ DOMString type() const;
+
+ long selectedIndex() const;
+ void setSelectedIndex( long index );
+
+ // ### this is just a rough guess
+ virtual bool isEnumeratable() const { return false; }
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool);
+
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLOptGroupElementImpl : public HTMLGenericFormElementImpl
+{
+public:
+ HTMLOptGroupElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0)
+ : HTMLGenericFormElementImpl(doc, f) {}
+
+ virtual Id id() const;
+};
+
+
+// ---------------------------------------------------------------------------
+
+class HTMLOptionElementImpl : public HTMLGenericFormElementImpl
+{
+ friend class khtml::RenderSelect;
+ friend class DOM::HTMLSelectElementImpl;
+
+public:
+ HTMLOptionElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+
+ virtual Id id() const;
+
+ DOMString text() const;
+
+ long index() const;
+ void setIndex( long );
+ virtual void parseAttribute(AttributeImpl *attr);
+ DOMString value() const;
+ void setValue(DOMStringImpl* value);
+
+ bool selected() const { return m_selected; }
+ void setSelected(bool _selected);
+
+ HTMLSelectElementImpl *getSelect() const;
+
+protected:
+ DOMString m_value;
+ bool m_selected;
+};
+
+
+// -------------------------------------------------------------------------
+
+class HTMLTextAreaElementImpl : public HTMLGenericFormElementImpl
+{
+ friend class khtml::RenderTextArea;
+
+public:
+ enum WrapMethod {
+ ta_NoWrap,
+ ta_Virtual,
+ ta_Physical
+ };
+
+ HTMLTextAreaElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ ~HTMLTextAreaElementImpl();
+
+ virtual Id id() const;
+
+ long cols() const { return m_cols; }
+
+ long rows() const { return m_rows; }
+
+ WrapMethod wrap() const { return m_wrap; }
+
+ virtual bool isEnumeratable() const { return true; }
+
+ DOMString type() const;
+
+ virtual bool maintainsState() { return true; }
+ virtual QString state();
+ virtual void restoreState(const QString &state);
+
+ void select ( );
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+ virtual bool encoding(const QTextCodec*, khtml::encodingList&, bool);
+ virtual void reset();
+ DOMString value();
+ void setValue(DOMString _value);
+ DOMString defaultValue();
+ void setDefaultValue(DOMString _defaultValue);
+ void blur();
+ void focus();
+
+ virtual bool isEditable();
+ void setUnsubmittedFormChange(bool unsubmitted) { m_unsubmittedFormChange = unsubmitted; }
+
+ //Mozilla extensions.
+ long selectionStart();
+ long selectionEnd();
+ void setSelectionStart(long pos);
+ void setSelectionEnd (long pos);
+ void setSelectionRange(long start, long end);
+ long textLength();
+protected:
+ int m_rows;
+ int m_cols;
+ WrapMethod m_wrap;
+ QString m_value;
+ bool m_changed: 1; //States whether the contents has been editted
+ bool m_dirtyvalue: 1; //States whether m_value is out-of-date compared to the renderer or default
+ bool m_unsubmittedFormChange: 1;
+ bool m_initialized: 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLIsIndexElementImpl : public HTMLInputElementImpl
+{
+public:
+ HTMLIsIndexElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ ~HTMLIsIndexElementImpl();
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ DOMString prompt() const;
+ void setPrompt(const DOMString& _value);
+};
+
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_headimpl.cpp b/khtml/html/html_headimpl.cpp
new file mode 100644
index 000000000..6808f27bf
--- /dev/null
+++ b/khtml/html/html_headimpl.cpp
@@ -0,0 +1,649 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2002-2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+// -------------------------------------------------------------------------
+
+#include "html/html_headimpl.h"
+#include "html/html_documentimpl.h"
+#include "xml/dom_textimpl.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include "misc/htmlhashes.h"
+#include "misc/loader.h"
+#include "misc/helper.h"
+
+#include "css/cssstyleselector.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/csshelper.h"
+
+#include "ecma/kjs_proxy.h"
+
+#include <kurl.h>
+#include <kdebug.h>
+
+using namespace khtml;
+
+NodeImpl::Id HTMLBaseElementImpl::id() const
+{
+ return ID_BASE;
+}
+
+void HTMLBaseElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_HREF:
+ m_href = khtml::parseURL(attr->value());
+ process();
+ break;
+ case ATTR_TARGET:
+ m_target = attr->value();
+ process();
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLBaseElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+ process();
+}
+
+void HTMLBaseElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+
+ // Since the document doesn't have a base element...
+ // (This will break in the case of multiple base elements, but that's not valid anyway (?))
+ getDocument()->setBaseURL( KURL() );
+ getDocument()->setBaseTarget( QString::null );
+}
+
+void HTMLBaseElementImpl::process()
+{
+ if (!inDocument())
+ return;
+
+ if(!m_href.isEmpty() && getDocument()->view())
+ getDocument()->setBaseURL( KURL( getDocument()->view()->part()->url(), m_href.string() ) );
+
+ if(!m_target.isEmpty())
+ getDocument()->setBaseTarget( m_target.string() );
+
+ // ### should changing a document's base URL dynamically automatically update all images, stylesheets etc?
+}
+
+// -------------------------------------------------------------------------
+
+
+HTMLLinkElementImpl::~HTMLLinkElementImpl()
+{
+ if(m_sheet) m_sheet->deref();
+ if(m_cachedSheet) m_cachedSheet->deref(this);
+}
+
+NodeImpl::Id HTMLLinkElementImpl::id() const
+{
+ return ID_LINK;
+}
+
+void HTMLLinkElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch (attr->id())
+ {
+ case ATTR_HREF:
+ m_url = getDocument()->completeURL( khtml::parseURL(attr->value()).string() );
+ process();
+ break;
+ case ATTR_REL:
+ case ATTR_TYPE:
+ process();
+ break;
+ case ATTR_TITLE:
+ // ### when title changes we have to reconsider our alternative
+ // stylesheet choice
+ break;
+ case ATTR_MEDIA:
+ m_media = attr->value().string().lower();
+ process();
+ break;
+ case ATTR_DISABLED: {
+ bool m_oldisDisabled = m_isDisabled;
+ m_isDisabled = attr->val();
+ if (m_oldisDisabled != m_isDisabled) {
+ if (isLoading()) {
+ if (m_oldisDisabled)
+ getDocument()->addPendingSheet();
+ else if (!m_alternate)
+ getDocument()->styleSheetLoaded();
+ }
+ if (m_oldisDisabled) {
+ // enabling: if it's an alternate sheet, pretend it's not.
+ m_alternate = false;
+ } else if (!m_alternate) {
+ // disabling: recheck alternate status
+ QString rel = getAttribute(ATTR_REL).string().lower();
+ QString type = getAttribute(ATTR_TYPE).string().lower();
+ m_alternate = (type.contains("text/css") || rel.contains("stylesheet")) && rel.contains("alternate");
+ }
+ if (isLoading())
+ break;
+ if (!m_sheet && !m_isDisabled) {
+ process();
+ if (isLoading() && m_alternate)
+ getDocument()->addPendingSheet();
+ m_alternate = false;
+ } else
+ getDocument()->updateStyleSelector(); // Update the style selector.
+ }
+ break;
+ }
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLLinkElementImpl::process()
+{
+ if (!inDocument())
+ return;
+
+ QString type = getAttribute(ATTR_TYPE).string().lower();
+ QString rel = getAttribute(ATTR_REL).string().lower();
+
+ KHTMLPart* part = getDocument()->view() ? getDocument()->view()->part() : 0;
+
+ // IE extension: location of small icon for locationbar / bookmarks
+ // Uses both "shortcut icon" and "icon"
+ if ( part && rel.contains("icon") && !m_url.isEmpty() && !part->parentPart())
+ part->browserExtension()->setIconURL( KURL(m_url.string()) );
+
+ // Stylesheet
+ else if (!m_isDisabled &&
+ (type.contains("text/css") || rel.contains("stylesheet"))) {
+ // no need to load style sheets which aren't for the screen output
+ // ### there may be in some situations e.g. for an editor or script to manipulate
+ if( m_media.isNull() || m_media.contains("screen") || m_media.contains("all") || m_media.contains("print") ) {
+ m_loading = true;
+ // Add ourselves as a pending sheet, but only if we aren't an alternate
+ // stylesheet. Alternate stylesheets don't hold up render tree construction.
+ m_alternate = rel.contains("alternate");
+ if (!isAlternate())
+ getDocument()->addPendingSheet();
+
+ QString chset = getAttribute( ATTR_CHARSET ).string();
+ // set chset to charset of referring document when attribute CHARSET is absent.
+ // http://www.w3.org/TR/CSS21/syndata.html(4.4)
+ if (chset.isEmpty() && part) chset = part->encoding();
+ if (m_cachedSheet)
+ m_cachedSheet->deref(this);
+ m_cachedSheet = getDocument()->docLoader()->requestStyleSheet(m_url, chset);
+ if (m_cachedSheet) {
+ m_isCSSSheet = true;
+ m_cachedSheet->ref(this);
+ }
+ else if (!isAlternate()) {
+ // Error requesting sheet; decrement pending sheet count
+ getDocument()->styleSheetLoaded();
+ }
+ }
+ }
+ else if (m_sheet) {
+ // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
+ m_sheet->deref();
+ m_sheet = 0;
+ m_isCSSSheet = false;
+ getDocument()->updateStyleSelector();
+ }
+}
+
+void HTMLLinkElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+ process();
+}
+
+void HTMLLinkElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLLinkElementImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheetStr, const DOM::DOMString &charset)
+{
+ if (m_sheet)
+ m_sheet->deref();
+ m_sheet = new CSSStyleSheetImpl(this, url);
+ m_sheet->ref();
+ m_sheet->setCharset(charset);
+ m_sheet->parseString( sheetStr, !getDocument()->inCompatMode() );
+
+ MediaListImpl *media = new MediaListImpl( m_sheet, m_media );
+ m_sheet->setMedia( media );
+
+ finished();
+}
+
+void HTMLLinkElementImpl::finished()
+{
+ m_loading = false;
+
+ // Tell the doc about the sheet.
+ if (!isLoading() && !isDisabled() && !isAlternate())
+ getDocument()->styleSheetLoaded();
+
+ // ### major inefficiency, but currently necessary for proper
+ // alternate styles support. don't recalc the styleselector
+ // when nothing actually changed!
+ if ( isAlternate() && m_sheet && !isDisabled())
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLLinkElementImpl::error( int, const QString& )
+{
+ finished();
+}
+
+bool HTMLLinkElementImpl::isLoading() const
+{
+// kdDebug( 6030 ) << "link: checking if loading!" << endl;
+ if(m_loading) return true;
+ if(!m_sheet) return false;
+ //if(!m_sheet->isCSSStyleSheet()) return false;
+ return static_cast<CSSStyleSheetImpl *>(m_sheet)->isLoading();
+}
+
+void HTMLLinkElementImpl::sheetLoaded()
+{
+ if (!isLoading() && !isDisabled() && !isAlternate())
+ getDocument()->styleSheetLoaded();
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLMetaElementImpl::id() const
+{
+ return ID_META;
+}
+
+void HTMLMetaElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_HTTP_EQUIV:
+ m_equiv = attr->value();
+ process();
+ break;
+ case ATTR_CONTENT:
+ m_content = attr->value();
+ process();
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLMetaElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+ process();
+}
+
+void HTMLMetaElementImpl::process()
+{
+ // Get the document to process the tag, but only if we're actually part of DOM tree (changing a meta tag while
+ // it's not in the tree shouldn't have any effect on the document)
+ if (inDocument() && !m_equiv.isNull() && !m_content.isNull())
+ getDocument()->processHttpEquiv(m_equiv,m_content);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLScriptElementImpl::HTMLScriptElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc), m_cachedScript(0), m_createdByParser(false), m_evaluated(false)
+{
+}
+
+HTMLScriptElementImpl::~HTMLScriptElementImpl()
+{
+ if (m_cachedScript)
+ m_cachedScript->deref(this);
+}
+
+NodeImpl::Id HTMLScriptElementImpl::id() const
+{
+ return ID_SCRIPT;
+}
+
+bool HTMLScriptElementImpl::isURLAttribute(AttributeImpl *attr) const
+{
+ return attr->id() == ATTR_SRC;
+}
+
+void HTMLScriptElementImpl::childrenChanged()
+{
+ // If a node is inserted as a child of the script element
+ // and the script element has been inserted in the document
+ // we evaluate the script.
+ if (!m_createdByParser && inDocument() && firstChild())
+ evaluateScript(getDocument()->URL().url(), text());
+}
+
+void HTMLScriptElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+
+ assert(!m_cachedScript);
+
+ if (m_createdByParser)
+ return;
+
+ QString url = getAttribute(ATTR_SRC).string();
+ if (!url.isEmpty()) {
+ QString charset = getAttribute(ATTR_CHARSET).string();
+ m_cachedScript = getDocument()->docLoader()->requestScript(DOMString(url), charset);
+ if (m_cachedScript)
+ m_cachedScript->ref(this);
+ return;
+ }
+
+ // If there's an empty script node, we shouldn't evaluate the script
+ // because if a script is inserted afterwards (by setting text or innerText)
+ // it should be evaluated, and evaluateScript only evaluates a script once.
+ DOMString scriptString = text();
+ if (!scriptString.isEmpty())
+ evaluateScript(getDocument()->URL().url(), scriptString);
+}
+
+void HTMLScriptElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+
+ if (m_cachedScript) {
+ m_cachedScript->deref(this);
+ m_cachedScript = 0;
+ }
+}
+
+void HTMLScriptElementImpl::notifyFinished(CachedObject* o)
+{
+ CachedScript *cs = static_cast<CachedScript *>(o);
+
+ assert(cs == m_cachedScript);
+
+ QString URL = cs->url().string();
+ DOMString script = cs->script();
+ cs->deref(this);
+ m_cachedScript = 0;
+
+ evaluateScript(URL, script);
+}
+
+void HTMLScriptElementImpl::evaluateScript(const QString &URL, const DOMString &script)
+{
+ if (m_evaluated)
+ return;
+
+ KHTMLPart *part = getDocument()->part();
+ if (part) {
+ KJSProxy *proxy = KJSProxy::proxy(part);
+ if (proxy) {
+ m_evaluated = true;
+ proxy->evaluate(URL, 0, script.string(), 0);
+ DocumentImpl::updateDocumentsRendering();
+ }
+ }
+}
+
+DOMString HTMLScriptElementImpl::text() const
+{
+ DOMString val = "";
+
+ for (NodeImpl *n = firstChild(); n; n = n->nextSibling()) {
+ if (n->isTextNode())
+ val += static_cast<TextImpl *>(n)->data();
+ }
+
+ return val;
+}
+
+void HTMLScriptElementImpl::setText(const DOMString &value)
+{
+ int exceptioncode = 0;
+ int numChildren = childNodeCount();
+
+ if (numChildren == 1 && firstChild()->isTextNode()) {
+ static_cast<DOM::TextImpl *>(firstChild())->setData(value, exceptioncode);
+ return;
+ }
+
+ if (numChildren > 0) {
+ removeChildren();
+ }
+
+ appendChild(getDocument()->createTextNode(value.implementation()), exceptioncode);
+}
+
+DOMString HTMLScriptElementImpl::htmlFor() const
+{
+ // DOM Level 1 says: reserved for future use.
+ return DOMString();
+}
+
+void HTMLScriptElementImpl::setHtmlFor(const DOMString &/*value*/)
+{
+ // DOM Level 1 says: reserved for future use.
+}
+
+DOMString HTMLScriptElementImpl::event() const
+{
+ // DOM Level 1 says: reserved for future use.
+ return DOMString();
+}
+
+void HTMLScriptElementImpl::setEvent(const DOMString &/*value*/)
+{
+ // DOM Level 1 says: reserved for future use.
+}
+
+DOMString HTMLScriptElementImpl::charset() const
+{
+ return getAttribute(ATTR_CHARSET);
+}
+
+void HTMLScriptElementImpl::setCharset(const DOMString &value)
+{
+ setAttribute(ATTR_CHARSET, value);
+}
+
+bool HTMLScriptElementImpl::defer() const
+{
+ return !getAttribute(ATTR_DEFER).isNull();
+}
+
+void HTMLScriptElementImpl::setDefer(bool defer)
+{
+ setAttribute(ATTR_DEFER, defer ? "" : 0);
+}
+
+DOMString HTMLScriptElementImpl::src() const
+{
+ return getDocument()->completeURL(getAttribute(ATTR_SRC).string());
+}
+
+void HTMLScriptElementImpl::setSrc(const DOMString &value)
+{
+ setAttribute(ATTR_SRC, value);
+}
+
+DOMString HTMLScriptElementImpl::type() const
+{
+ return getAttribute(ATTR_TYPE);
+}
+
+void HTMLScriptElementImpl::setType(const DOMString &value)
+{
+ setAttribute(ATTR_TYPE, value);
+}
+
+// -------------------------------------------------------------------------
+
+HTMLStyleElementImpl::~HTMLStyleElementImpl()
+{
+ if(m_sheet) m_sheet->deref();
+}
+
+NodeImpl::Id HTMLStyleElementImpl::id() const
+{
+ return ID_STYLE;
+}
+
+// other stuff...
+void HTMLStyleElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch (attr->id())
+ {
+ case ATTR_TYPE:
+ m_type = attr->value().lower();
+ break;
+ case ATTR_MEDIA:
+ m_media = attr->value().string().lower();
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLStyleElementImpl::insertedIntoDocument()
+{
+ HTMLElementImpl::insertedIntoDocument();
+ if (m_sheet)
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLStyleElementImpl::removedFromDocument()
+{
+ HTMLElementImpl::removedFromDocument();
+ if (m_sheet)
+ getDocument()->updateStyleSelector();
+}
+
+void HTMLStyleElementImpl::childrenChanged()
+{
+ HTMLElementImpl::childrenChanged();
+
+ DOMString text = "";
+
+ for (NodeImpl *c = firstChild(); c != 0; c = c->nextSibling()) {
+ if ((c->nodeType() == Node::TEXT_NODE) ||
+ (c->nodeType() == Node::CDATA_SECTION_NODE) ||
+ (c->nodeType() == Node::COMMENT_NODE))
+ text += c->nodeValue();
+ }
+
+ if (m_sheet) {
+ m_sheet->deref();
+ m_sheet = 0;
+ }
+
+ m_loading = false;
+ if ((m_type.isEmpty() || m_type == "text/css") // Type must be empty or CSS
+ && (m_media.isNull() || m_media.contains("screen") || m_media.contains("all") || m_media.contains("print"))) {
+ getDocument()->addPendingSheet();
+ m_loading = true;
+ m_sheet = new CSSStyleSheetImpl(this);
+ m_sheet->ref();
+ m_sheet->parseString( text, !getDocument()->inCompatMode() );
+ MediaListImpl* media = new MediaListImpl( m_sheet, DOMString( m_media ) );
+ m_sheet->setMedia( media );
+ m_loading = false;
+ }
+
+ if (!isLoading() && m_sheet)
+ getDocument()->styleSheetLoaded();
+}
+
+bool HTMLStyleElementImpl::isLoading() const
+{
+ if (m_loading) return true;
+ if(!m_sheet) return false;
+ return static_cast<CSSStyleSheetImpl *>(m_sheet)->isLoading();
+}
+
+void HTMLStyleElementImpl::sheetLoaded()
+{
+ if (!isLoading())
+ getDocument()->styleSheetLoaded();
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLTitleElementImpl::id() const
+{
+ return ID_TITLE;
+}
+
+void HTMLTitleElementImpl::childrenChanged()
+{
+ HTMLElementImpl::childrenChanged();
+
+ m_title = "";
+ for (NodeImpl *c = firstChild(); c != 0; c = c->nextSibling()) {
+ if ((c->nodeType() == Node::TEXT_NODE) || (c->nodeType() == Node::CDATA_SECTION_NODE))
+ m_title += c->nodeValue();
+ }
+ if ( !m_title.isEmpty() && inDocument())
+ getDocument()->setTitle(m_title);
+}
+
+DOMString HTMLTitleElementImpl::text()
+{
+ if (firstChild() && firstChild()->nodeType() == Node::TEXT_NODE) {
+ return firstChild()->nodeValue();
+ }
+ return "";
+}
+
+void HTMLTitleElementImpl::setText( const DOMString& str )
+{
+ int exceptioncode = 0;
+ // Look for an existing text child node
+ DOM::NodeListImpl* nl(childNodes());
+ if (nl)
+ {
+ for (unsigned int i = 0; i < nl->length(); i++) {
+ if (nl->item(i)->nodeType() == DOM::Node::TEXT_NODE) {
+ static_cast<DOM::TextImpl *>(nl->item(i))->setData(str, exceptioncode);
+ return;
+ }
+ }
+ delete nl;
+ }
+ // No child text node found, creating one
+ DOM::TextImpl* t = getDocument()->createTextNode(str.implementation());
+ appendChild(t, exceptioncode);
+}
diff --git a/khtml/html/html_headimpl.h b/khtml/html/html_headimpl.h
new file mode 100644
index 000000000..3fa72c928
--- /dev/null
+++ b/khtml/html/html_headimpl.h
@@ -0,0 +1,233 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_HEADIMPL_H
+#define HTML_HEADIMPL_H
+
+#include "html/html_elementimpl.h"
+#include "misc/loader_client.h"
+#include "css/css_stylesheetimpl.h"
+
+class KHTMLView;
+
+namespace khtml {
+ class CachedCSSStyleSheet;
+ class CachedObject;
+}
+
+
+namespace DOM {
+
+class DOMString;
+class HTMLFormElementImpl;
+class StyleSheetImpl;
+class CSSStyleSheetImpl;
+
+class HTMLBaseElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLBaseElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ DOMString href() const { return m_href; }
+ DOMString target() const { return m_target; }
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
+ void process();
+
+protected:
+ DOMString m_href;
+ DOMString m_target;
+};
+
+
+
+// -------------------------------------------------------------------------
+
+class HTMLLinkElementImpl : public khtml::CachedObjectClient, public HTMLElementImpl
+{
+public:
+ HTMLLinkElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc), m_cachedSheet(0), m_sheet(0), m_isDisabled(false),
+ m_loading(false), m_alternate(false), m_isCSSSheet(false) {}
+
+ ~HTMLLinkElementImpl();
+
+ virtual Id id() const;
+
+ const StyleSheetImpl* sheet() const { return m_sheet; }
+ StyleSheetImpl* sheet() { return m_sheet; }
+
+ // overload from HTMLElementImpl
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ void process();
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
+ // from CachedObjectClient
+ virtual void setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset);
+ virtual void error(int err, const QString &text);
+ bool isLoading() const;
+ void sheetLoaded();
+
+ bool isAlternate() const { return m_alternate; }
+ bool isCSSStyleSheet() const { return m_isCSSSheet; }
+ bool isDisabled() const { return m_isDisabled; }
+ void setDisabled(bool disabled) { m_isDisabled = disabled; }
+
+protected:
+ void finished();
+
+ khtml::CachedCSSStyleSheet *m_cachedSheet;
+ CSSStyleSheetImpl *m_sheet;
+ DOMString m_url;
+ QString m_media;
+ bool m_isDisabled : 1;
+ bool m_loading : 1;
+ bool m_alternate : 1;
+ bool m_isCSSSheet : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLMetaElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLMetaElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void insertedIntoDocument();
+
+ void process();
+
+protected:
+ DOMString m_equiv;
+ DOMString m_content;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLScriptElementImpl : public HTMLElementImpl, public khtml::CachedObjectClient
+{
+public:
+ HTMLScriptElementImpl(DocumentImpl *doc);
+ ~HTMLScriptElementImpl();
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void notifyFinished(khtml::CachedObject *finishedObj);
+ virtual void childrenChanged();
+
+ virtual Id id() const;
+ virtual bool isURLAttribute(AttributeImpl *attr) const;
+
+ void setCreatedByParser(bool createdByParser) { m_createdByParser = createdByParser; }
+
+ void evaluateScript(const QString &, const DOMString &);
+
+ DOMString text() const;
+ void setText( const DOMString& str );
+
+ DOMString htmlFor() const;
+ void setHtmlFor(const DOMString &);
+
+ DOMString event() const;
+ void setEvent(const DOMString &);
+
+ DOMString charset() const;
+ void setCharset(const DOMString &);
+
+ bool defer() const;
+ void setDefer(bool);
+
+ DOMString src() const;
+ void setSrc(const DOMString &);
+
+ DOMString type() const;
+ void setType(const DOMString &);
+
+private:
+ khtml::CachedScript *m_cachedScript;
+ bool m_createdByParser;
+ bool m_evaluated;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLStyleElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLStyleElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc), m_sheet(0), m_loading(false) {}
+ ~HTMLStyleElementImpl();
+
+ virtual Id id() const;
+
+ CSSStyleSheetImpl *sheet() { return m_sheet; }
+
+ // overload from HTMLElementImpl
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void childrenChanged();
+
+ bool isLoading() const;
+ void sheetLoaded();
+
+protected:
+ CSSStyleSheetImpl *m_sheet;
+ DOMString m_type;
+ QString m_media;
+ bool m_loading;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTitleElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLTitleElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ DOMString text();
+ void setText( const DOMString& str );
+
+ virtual Id id() const;
+
+ virtual void childrenChanged();
+
+protected:
+ DOMString m_title;
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_imageimpl.cpp b/khtml/html/html_imageimpl.cpp
new file mode 100644
index 000000000..1c755920b
--- /dev/null
+++ b/khtml/html/html_imageimpl.cpp
@@ -0,0 +1,560 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "html/html_imageimpl.h"
+#include "html/html_formimpl.h"
+#include "html/html_documentimpl.h"
+
+#include "misc/htmlhashes.h"
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include <kstringhandler.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include "rendering/render_image.h"
+#include "rendering/render_flow.h"
+#include "css/cssstyleselector.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/csshelper.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <qstring.h>
+#include <qpoint.h>
+#include <qregion.h>
+#include <qptrstack.h>
+#include <qimage.h>
+#include <qpointarray.h>
+
+using namespace DOM;
+using namespace khtml;
+
+// -------------------------------------------------------------------------
+
+HTMLImageElementImpl::HTMLImageElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f)
+ : HTMLElementImpl(doc), ismap(false), loadEventSent(true), m_image(0), m_form(f)
+{
+ if (m_form)
+ m_form->registerImgElement(this);
+}
+
+HTMLImageElementImpl::~HTMLImageElementImpl()
+{
+ if (getDocument())
+ getDocument()->removeImage(this);
+
+ if (m_image)
+ m_image->deref(this);
+
+ if (m_form)
+ m_form->removeImgElement(this);
+}
+
+NodeImpl::Id HTMLImageElementImpl::id() const
+{
+ return ID_IMG;
+}
+
+void HTMLImageElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch (attr->id())
+ {
+ case ATTR_ALT:
+ setChanged();
+ break;
+ case ATTR_SRC: {
+ setChanged();
+
+ //Start loading the image already, to generate events
+ DOMString url = attr->value();
+ if (!url.isEmpty()) { //### why do we not hide or something when setting this?
+ CachedImage* newImage = getDocument()->docLoader()->requestImage(khtml::parseURL(url));
+ if (newImage && newImage != m_image) {
+ CachedImage* oldImage = m_image;
+ loadEventSent = false;
+ m_image = newImage;
+ m_image->ref(this);
+ if (oldImage)
+ oldImage->deref(this);
+ }
+ }
+ }
+ break;
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_BORDER:
+ // border="noborder" -> border="0"
+ if(attr->value().toInt()) {
+ addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
+ addCSSProperty( CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID );
+ } else {
+ removeCSSProperty( CSS_PROP_BORDER_WIDTH );
+ removeCSSProperty( CSS_PROP_BORDER_TOP_STYLE );
+ removeCSSProperty( CSS_PROP_BORDER_RIGHT_STYLE );
+ removeCSSProperty( CSS_PROP_BORDER_BOTTOM_STYLE );
+ removeCSSProperty( CSS_PROP_BORDER_LEFT_STYLE );
+ }
+ break;
+ case ATTR_VSPACE:
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ break;
+ case ATTR_HSPACE:
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_VALIGN:
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
+ break;
+ case ATTR_USEMAP:
+ if ( attr->value()[0] == '#' )
+ usemap = attr->value().lower();
+ else {
+ QString url = getDocument()->completeURL( khtml::parseURL( attr->value() ).string() );
+ // ### we remove the part before the anchor and hope
+ // the map is on the same html page....
+ usemap = url;
+ }
+ m_hasAnchor = attr->val() != 0;
+ case ATTR_ISMAP:
+ ismap = true;
+ break;
+ case ATTR_ONABORT: // ### add support for this
+ setHTMLEventListener(EventImpl::ABORT_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onabort", this));
+ break;
+ case ATTR_ONERROR:
+ setHTMLEventListener(EventImpl::ERROR_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onerror", this));
+ break;
+ case ATTR_ONLOAD:
+ setHTMLEventListener(EventImpl::LOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onload", this));
+ break;
+ case ATTR_NOSAVE:
+ break;
+ case ATTR_NAME:
+ if (inDocument() && m_name != attr->value()) {
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ getDocument()->underDocNamedCache().add (attr->value().string(), this);
+ }
+ m_name = attr->value();
+ //fallthrough
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLImageElementImpl::notifyFinished(CachedObject *finishedObj)
+{
+ if (m_image == finishedObj) {
+ getDocument()->dispatchImageLoadEventSoon(this);
+ }
+}
+
+void HTMLImageElementImpl::dispatchLoadEvent()
+{
+ if (!loadEventSent) {
+ loadEventSent = true;
+ if (m_image->isErrorImage()) {
+ dispatchHTMLEvent(EventImpl::ERROR_EVENT, false, false);
+ } else {
+ dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
+ }
+ }
+}
+
+DOMString HTMLImageElementImpl::altText() const
+{
+ // lets figure out the alt text.. magic stuff
+ // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
+ // also heavily discussed by Hixie on bugzilla
+ DOMString alt( getAttribute( ATTR_ALT ) );
+ // fall back to title attribute
+ if ( alt.isNull() )
+ alt = getAttribute( ATTR_TITLE );
+#if 0
+ if ( alt.isNull() ) {
+ QString p = KURL( getDocument()->completeURL( getAttribute(ATTR_SRC).string() ) ).prettyURL();
+ int pos;
+ if ( ( pos = p.findRev( '.' ) ) > 0 )
+ p.truncate( pos );
+ alt = DOMString( KStringHandler::csqueeze( p ) );
+ }
+#endif
+
+ return alt;
+}
+
+void HTMLImageElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+ if (parentNode()->renderer() && parentNode()->renderer()->childAllowed() &&
+ _style->display() != NONE)
+ {
+ m_render = new (getDocument()->renderArena()) RenderImage(this);
+ m_render->setStyle(_style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+ _style->deref();
+
+ NodeBaseImpl::attach();
+ if (m_render)
+ m_render->updateFromElement();
+}
+
+void HTMLImageElementImpl::removedFromDocument()
+{
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ HTMLElementImpl::removedFromDocument();
+}
+
+void HTMLImageElementImpl::insertedIntoDocument()
+{
+ getDocument()->underDocNamedCache().add(m_name.string(), this);
+ HTMLElementImpl::insertedIntoDocument();
+}
+
+void HTMLImageElementImpl::removeId(const QString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLImageElementImpl::addId (const QString& id)
+{
+ getDocument()->underDocNamedCache().add(id, this);
+ HTMLElementImpl::addId(id);
+}
+
+
+long HTMLImageElementImpl::width() const
+{
+ if (!m_render) {
+ DOMString widthAttr = getAttribute(ATTR_WIDTH);
+ if (!widthAttr.isNull())
+ return widthAttr.toInt();
+ else if (m_image && m_image->pixmap_size().isValid())
+ return m_image->pixmap_size().width();
+ else
+ return 0;
+ }
+
+ // ### make a unified call for this
+ if (changed()) {
+ getDocument()->updateRendering();
+ if (getDocument()->view())
+ getDocument()->view()->layout();
+ }
+
+ return m_render ? m_render->contentWidth() :
+ getAttribute(ATTR_WIDTH).toInt();
+}
+
+long HTMLImageElementImpl::height() const
+{
+ if (!m_render) {
+ DOMString heightAttr = getAttribute(ATTR_HEIGHT);
+ if (!heightAttr.isNull())
+ return heightAttr.toInt();
+ else if (m_image && m_image->pixmap_size().isValid())
+ return m_image->pixmap_size().height();
+ else
+ return 0;
+ }
+
+ // ### make a unified call for this
+ if (changed()) {
+ getDocument()->updateRendering();
+ if (getDocument()->view())
+ getDocument()->view()->layout();
+ }
+
+ return m_render ? m_render->contentHeight() :
+ getAttribute(ATTR_HEIGHT).toInt();
+}
+
+QImage HTMLImageElementImpl::currentImage() const
+{
+ RenderImage *r = static_cast<RenderImage*>(renderer());
+
+ if(r)
+ return r->pixmap().convertToImage();
+
+ return QImage();
+}
+
+QPixmap HTMLImageElementImpl::currentPixmap() const
+{
+ RenderImage *r = static_cast<RenderImage*>(renderer());
+
+ if(r)
+ return r->pixmap();
+
+ return QPixmap();
+}
+
+bool HTMLImageElementImpl::complete() const
+{
+ return m_image && m_image->valid_rect().size() == m_image->pixmap_size();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLMapElementImpl::HTMLMapElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+}
+
+HTMLMapElementImpl::~HTMLMapElementImpl()
+{
+ if(getDocument() && getDocument()->isHTMLDocument())
+ static_cast<HTMLDocumentImpl*>(getDocument())->mapMap.remove(name);
+}
+
+NodeImpl::Id HTMLMapElementImpl::id() const
+{
+ return ID_MAP;
+}
+
+bool
+HTMLMapElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
+ RenderObject::NodeInfo& info)
+{
+ //cout << "map:mapMouseEvent " << endl;
+ //cout << x_ << " " << y_ <<" "<< width_ <<" "<< height_ << endl;
+ QPtrStack<NodeImpl> nodeStack;
+
+ NodeImpl *current = firstChild();
+ while(1)
+ {
+ if(!current)
+ {
+ if(nodeStack.isEmpty()) break;
+ current = nodeStack.pop();
+ current = current->nextSibling();
+ continue;
+ }
+ if(current->id()==ID_AREA)
+ {
+ //cout << "area found " << endl;
+ HTMLAreaElementImpl* area=static_cast<HTMLAreaElementImpl*>(current);
+ if (area->mapMouseEvent(x_,y_,width_,height_, info))
+ return true;
+ }
+ NodeImpl *child = current->firstChild();
+ if(child)
+ {
+ nodeStack.push(current);
+ current = child;
+ }
+ else
+ {
+ current = current->nextSibling();
+ }
+ }
+
+ return false;
+}
+
+void HTMLMapElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch (attr->id())
+ {
+ case ATTR_ID:
+ if (getDocument()->htmlMode() != DocumentImpl::XHtml) {
+ HTMLElementImpl::parseAttribute(attr);
+ break;
+ }
+ else {
+ // add name with full url:
+ QString url = getDocument()->completeURL( khtml::parseURL( attr->value() ).string() );
+ if(getDocument()->isHTMLDocument())
+ static_cast<HTMLDocumentImpl*>(getDocument())->mapMap[url] = this;
+ }
+ // fall through
+ case ATTR_NAME:
+ {
+ DOMString s = attr->value();
+ if(*s.unicode() == '#')
+ name = QString(s.unicode()+1, s.length()-1).lower();
+ else
+ name = s.string().lower();
+ // ### make this work for XML documents, e.g. in case of <html:map...>
+ if(getDocument()->isHTMLDocument())
+ static_cast<HTMLDocumentImpl*>(getDocument())->mapMap[name] = this;
+
+ //fallthrough
+ }
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+HTMLAreaElementImpl::HTMLAreaElementImpl(DocumentImpl *doc)
+ : HTMLAnchorElementImpl(doc)
+{
+ m_coords=0;
+ m_coordsLen = 0;
+ nohref = false;
+ shape = Unknown;
+ lasth = lastw = -1;
+}
+
+HTMLAreaElementImpl::~HTMLAreaElementImpl()
+{
+ delete [] m_coords;
+}
+
+NodeImpl::Id HTMLAreaElementImpl::id() const
+{
+ return ID_AREA;
+}
+
+void HTMLAreaElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch (attr->id())
+ {
+ case ATTR_SHAPE:
+ if ( strcasecmp( attr->value(), "default" ) == 0 )
+ shape = Default;
+ else if ( strcasecmp( attr->value(), "circle" ) == 0 )
+ shape = Circle;
+ else if ( strcasecmp( attr->value(), "poly" ) == 0 || strcasecmp( attr->value(), "polygon" ) == 0 )
+ shape = Poly;
+ else if ( strcasecmp( attr->value(), "rect" ) == 0 )
+ shape = Rect;
+ break;
+ case ATTR_COORDS:
+ delete [] m_coords;
+ m_coords = attr->val()->toCoordsArray(m_coordsLen);
+ break;
+ case ATTR_NOHREF:
+ nohref = attr->val() != 0;
+ break;
+ case ATTR_TARGET:
+ m_hasTarget = attr->val() != 0;
+ break;
+ case ATTR_ALT:
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ default:
+ HTMLAnchorElementImpl::parseAttribute(attr);
+ }
+}
+
+bool HTMLAreaElementImpl::mapMouseEvent(int x_, int y_, int width_, int height_,
+ RenderObject::NodeInfo& info)
+{
+ bool inside = false;
+ if (width_ != lastw || height_ != lasth)
+ {
+ region=getRegion(width_, height_);
+ lastw=width_; lasth=height_;
+ }
+ if (region.contains(QPoint(x_,y_)))
+ {
+ inside = true;
+ info.setInnerNode(this);
+ info.setURLElement(this);
+ }
+
+ return inside;
+}
+
+QRect HTMLAreaElementImpl::getRect() const
+{
+ if (parentNode()->renderer()==0)
+ return QRect();
+ int dx, dy;
+ if (!parentNode()->renderer()->absolutePosition(dx, dy))
+ return QRect();
+ QRegion region = getRegion(lastw,lasth);
+ region.translate(dx, dy);
+ return region.boundingRect();
+}
+
+QRegion HTMLAreaElementImpl::getRegion(int width_, int height_) const
+{
+ QRegion region;
+ if (!m_coords)
+ return region;
+
+ // added broken HTML support (Dirk): some pages omit the SHAPE
+ // attribute, so we try to guess by looking at the coords count
+ // what the HTML author tried to tell us.
+
+ // a Poly needs at least 3 points (6 coords), so this is correct
+ if ((shape==Poly || shape==Unknown) && m_coordsLen > 5) {
+ // make sure its even
+ int len = m_coordsLen >> 1;
+ QPointArray points(len);
+ for (int i = 0; i < len; ++i)
+ points.setPoint(i, m_coords[(i<<1)].minWidth(width_),
+ m_coords[(i<<1)+1].minWidth(height_));
+ region = QRegion(points);
+ }
+ else if (shape==Circle && m_coordsLen>=3 || shape==Unknown && m_coordsLen == 3) {
+ int r = kMin(m_coords[2].minWidth(width_), m_coords[2].minWidth(height_));
+ region = QRegion(m_coords[0].minWidth(width_)-r,
+ m_coords[1].minWidth(height_)-r, 2*r, 2*r,QRegion::Ellipse);
+ }
+ else if (shape==Rect && m_coordsLen>=4 || shape==Unknown && m_coordsLen == 4) {
+ int x0 = m_coords[0].minWidth(width_);
+ int y0 = m_coords[1].minWidth(height_);
+ int x1 = m_coords[2].minWidth(width_);
+ int y1 = m_coords[3].minWidth(height_);
+ region = QRegion(x0,y0,x1-x0,y1-y0);
+ }
+ else if (shape==Default)
+ region = QRegion(0,0,width_,height_);
+ // else
+ // return null region
+
+ return region;
+}
diff --git a/khtml/html/html_imageimpl.h b/khtml/html/html_imageimpl.h
new file mode 100644
index 000000000..8fc00b027
--- /dev/null
+++ b/khtml/html/html_imageimpl.h
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_IMAGEIMPL_H
+#define HTML_IMAGEIMPL_H
+
+#include "html/html_inlineimpl.h"
+#include "misc/khtmllayout.h"
+#include "misc/loader_client.h"
+#include "rendering/render_object.h"
+
+#include <qregion.h>
+
+namespace DOM {
+
+class DOMString;
+class HTMLFormElementImpl;
+
+class HTMLImageElementImpl
+ : public HTMLElementImpl, public khtml::CachedObjectClient
+{
+ friend class HTMLFormElementImpl;
+public:
+ HTMLImageElementImpl(DocumentImpl *doc, HTMLFormElementImpl *f = 0);
+ ~HTMLImageElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *);
+
+ virtual void attach();
+ virtual void removedFromDocument();
+ virtual void insertedIntoDocument();
+ virtual void addId(const QString& id);
+ virtual void removeId(const QString& id);
+
+
+ long width() const;
+ long height() const;
+
+ bool isServerMap() const { return ( ismap && !usemap.length() ); }
+ /** Return the image for this element.
+ * This has to convert the pixmap into an image first.
+ * This will return undefined results if complete() is not true.
+ */
+ QImage currentImage() const;
+ /** Return the pixmap for this element.
+ * This will return undefined results if complete() is not true.
+ */
+ QPixmap currentPixmap() const;
+
+ DOMString altText() const;
+
+ DOMString imageMap() const { return usemap; }
+ /** See if the image has been completely downloaded.
+ * @return True if and only if the image is completely downloaded yet*/
+ bool complete() const;
+
+ virtual void notifyFinished(khtml::CachedObject *finishedObj);
+ void dispatchLoadEvent();
+protected:
+ DOMString usemap;
+ bool ismap : 1;
+ bool loadEventSent : 1;
+ khtml::CachedImage *m_image;
+ HTMLFormElementImpl *m_form;
+ DOMString m_name;
+};
+
+
+//------------------------------------------------------------------
+
+class HTMLAreaElementImpl : public HTMLAnchorElementImpl
+{
+public:
+
+ enum Shape { Default, Poly, Rect, Circle, Unknown };
+
+ HTMLAreaElementImpl(DocumentImpl *doc);
+ ~HTMLAreaElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ bool isDefault() const { return shape==Default; }
+
+ bool mapMouseEvent(int x_, int y_, int width_, int height_,
+ khtml::RenderObject::NodeInfo& info);
+
+ virtual QRect getRect() const;
+
+ QRegion cachedRegion() const { return region; }
+
+protected:
+ QRegion getRegion(int width_, int height) const;
+ QRegion region;
+ khtml::Length* m_coords;
+ int m_coordsLen;
+ int lastw, lasth;
+ Shape shape : 3;
+ bool nohref : 1;
+};
+
+
+// -------------------------------------------------------------------------
+
+class HTMLMapElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLMapElementImpl(DocumentImpl *doc);
+
+ ~HTMLMapElementImpl();
+
+ virtual Id id() const;
+
+ virtual DOMString getName() const { return name; }
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ bool mapMouseEvent(int x_, int y_, int width_, int height_,
+ khtml::RenderObject::NodeInfo& info);
+private:
+
+ QString name;
+};
+
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_inlineimpl.cpp b/khtml/html/html_inlineimpl.cpp
new file mode 100644
index 000000000..08bbbb177
--- /dev/null
+++ b/khtml/html/html_inlineimpl.cpp
@@ -0,0 +1,298 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2002 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+// -------------------------------------------------------------------------
+
+#include "html/html_inlineimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_documentimpl.h"
+
+#include "misc/htmlhashes.h"
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "css/csshelper.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/cssstyleselector.h"
+#include "xml/dom2_eventsimpl.h"
+#include "rendering/render_br.h"
+#include "rendering/render_image.h"
+
+#include <kdebug.h>
+
+using namespace khtml;
+using namespace DOM;
+
+NodeImpl::Id HTMLAnchorElementImpl::id() const
+{
+ return ID_A;
+}
+
+void HTMLAnchorElementImpl::defaultEventHandler(EventImpl *evt)
+{
+ bool keydown = evt->id() == EventImpl::KEYDOWN_EVENT && evt->isKeyRelatedEvent();
+
+ // React on clicks and on keypresses.
+ // Don't make this KEYUP_EVENT again, it makes khtml follow links
+ // it shouldn't, when pressing Enter in the combo.
+ if ( ( (evt->id() == EventImpl::CLICK_EVENT && !static_cast<MouseEventImpl*>(evt)->isDoubleClick()) ||
+ ( keydown && m_focused)) && m_hasAnchor) {
+
+ MouseEventImpl *e = 0;
+ if ( evt->id() == EventImpl::CLICK_EVENT )
+ e = static_cast<MouseEventImpl*>( evt );
+
+ KeyEventBaseImpl *k = 0;
+ if (keydown)
+ k = static_cast<KeyEventBaseImpl *>( evt );
+
+ QString utarget;
+ QString url;
+ if ( e && e->button() == 2 ) {
+ HTMLElementImpl::defaultEventHandler(evt);
+ return;
+ }
+
+ if ( k ) {
+ if (k->virtKeyVal() != KeyEventBaseImpl::DOM_VK_ENTER) {
+ if (k->qKeyEvent())
+ k->qKeyEvent()->ignore();
+ HTMLElementImpl::defaultEventHandler(evt);
+ return;
+ }
+ if (k->qKeyEvent()) k->qKeyEvent()->accept();
+ }
+
+ url = khtml::parseURL(getAttribute(ATTR_HREF)).string();
+
+ utarget = getAttribute(ATTR_TARGET).string();
+
+ if ( e && e->button() == 1 )
+ utarget = "_blank";
+
+ if ( evt->target()->id() == ID_IMG ) {
+ HTMLImageElementImpl* img = static_cast<HTMLImageElementImpl*>( evt->target() );
+ if ( img && img->isServerMap() )
+ {
+ khtml::RenderImage *r = static_cast<khtml::RenderImage *>(img->renderer());
+ if(r && e)
+ {
+ KHTMLView* v = getDocument()->view();
+ int x = e->clientX();
+ int y = e->clientY();
+ int absx = 0;
+ int absy = 0;
+ if ( v ) {
+ x += v->contentsX();
+ y += v->contentsY();
+ }
+ r->absolutePosition(absx, absy);
+ url += QString("?%1,%2").arg( x - absx ).arg( y - absy );
+ }
+ else {
+ evt->setDefaultHandled();
+ HTMLElementImpl::defaultEventHandler(evt);
+ return;
+ }
+ }
+ }
+ if ( !evt->defaultPrevented() ) {
+ int state = 0;
+ int button = 0;
+
+ if ( e ) {
+ if ( e->ctrlKey() )
+ state |= Qt::ControlButton;
+ if ( e->shiftKey() )
+ state |= Qt::ShiftButton;
+ if ( e->altKey() )
+ state |= Qt::AltButton;
+ if ( e->metaKey() )
+ state |= Qt::MetaButton;
+
+ if ( e->button() == 0 )
+ button = Qt::LeftButton;
+ else if ( e->button() == 1 )
+ button = Qt::MidButton;
+ else if ( e->button() == 2 )
+ button = Qt::RightButton;
+ }
+ else if ( k )
+ {
+ if ( k->checkModifier(Qt::ShiftButton) )
+ state |= Qt::ShiftButton;
+ if ( k->checkModifier(Qt::AltButton) )
+ state |= Qt::AltButton;
+ if ( k->checkModifier(Qt::ControlButton) )
+ state |= Qt::ControlButton;
+ }
+
+ // ### also check if focused node is editable if not in designmode,
+ // and prevent link loading then (LS)
+ if (getDocument()->view() && !getDocument()->designMode()) {
+ if (k)
+ click();
+ else
+ getDocument()->view()->part()->
+ urlSelected( url, button, state, utarget );
+ }
+ }
+ evt->setDefaultHandled();
+ }
+ HTMLElementImpl::defaultEventHandler(evt);
+}
+
+
+void HTMLAnchorElementImpl::click()
+{
+ QMouseEvent me(QEvent::MouseButtonRelease, QPoint(0,0),Qt::LeftButton, 0);
+ dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1);
+}
+
+void HTMLAnchorElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_HREF:
+ {
+ bool hadAnchor = m_hasAnchor;
+ m_hasAnchor = attr->val() != 0;
+ getDocument()->incDOMTreeVersion();
+ if (hadAnchor != m_hasAnchor)
+ setChanged();
+ }
+ break;
+ case ATTR_TARGET:
+ m_hasTarget = attr->val() != 0;
+ break;
+ case ATTR_TITLE:
+ case ATTR_REL:
+ break;
+ case ATTR_ACCESSKEY:
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLBRElementImpl::id() const
+{
+ return ID_BR;
+}
+
+void HTMLBRElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_CLEAR:
+ {
+ DOMString str = attr->value().lower();
+ if( str.isEmpty() ) str = "none";
+ else if( strcmp (str,"all")==0 ) str = "both";
+ addCSSProperty(CSS_PROP_CLEAR, str);
+ break;
+ }
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLBRElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+ if (parentNode()->renderer()) {
+ RenderStyle* style = getDocument()->styleSelector()->styleForElement( this );
+ style->ref();
+ if( style->display() != NONE ) {
+ m_render = new (getDocument()->renderArena()) RenderBR(this);
+ m_render->setStyle(style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ }
+ style->deref();
+ }
+ NodeImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLFontElementImpl::id() const
+{
+ return ID_FONT;
+}
+
+void HTMLFontElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_SIZE:
+ {
+ DOMStringImpl* v = attr->val();
+ if(v) {
+ const QChar* s = v->s;
+ int num = v->toInt();
+ int len = v->l;
+ while( len && s->isSpace() )
+ len--,s++;
+ if ( len && *s == '+' )
+ num += 3;
+ int size;
+ switch (num)
+ {
+ case -2:
+ case 1: size = CSS_VAL_XX_SMALL; break;
+ case -1:
+ case 2: size = CSS_VAL_SMALL; break;
+ case 0: // treat 0 the same as 3, because people
+ // expect it to be between -1 and +1
+ case 3: size = CSS_VAL_MEDIUM; break;
+ case 4: size = CSS_VAL_LARGE; break;
+ case 5: size = CSS_VAL_X_LARGE; break;
+ case 6: size = CSS_VAL_XX_LARGE; break;
+ default:
+ if (num > 6)
+ size = CSS_VAL__KHTML_XXX_LARGE;
+ else
+ size = CSS_VAL_XX_SMALL;
+ }
+ addCSSProperty(CSS_PROP_FONT_SIZE, size);
+ }
+ break;
+ }
+ case ATTR_COLOR:
+ addHTMLColor(CSS_PROP_COLOR, attr->value());
+ break;
+ case ATTR_FACE:
+ addCSSProperty(CSS_PROP_FONT_FAMILY, attr->value());
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+
diff --git a/khtml/html/html_inlineimpl.h b/khtml/html/html_inlineimpl.h
new file mode 100644
index 000000000..252e64e41
--- /dev/null
+++ b/khtml/html/html_inlineimpl.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_INLINEIMPL_H
+#define HTML_INLINEIMPL_H
+
+#include "html_elementimpl.h"
+
+namespace DOM {
+
+class DOMString;
+
+class HTMLAnchorElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLAnchorElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc), m_hasTarget(false) {}
+
+ virtual bool isFocusable() const { return m_hasAnchor; }
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void defaultEventHandler(EventImpl *evt);
+ void click();
+protected:
+ bool m_hasTarget : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLBRElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLBRElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLFontElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLFontElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_listimpl.cpp b/khtml/html/html_listimpl.cpp
new file mode 100644
index 000000000..e1650af46
--- /dev/null
+++ b/khtml/html/html_listimpl.cpp
@@ -0,0 +1,169 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include "html_listimpl.h"
+
+using namespace DOM;
+
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "rendering/render_list.h"
+#include "misc/htmlhashes.h"
+#include "xml/dom_docimpl.h"
+
+using namespace khtml;
+
+NodeImpl::Id HTMLUListElementImpl::id() const
+{
+ return ID_UL;
+}
+
+void HTMLUListElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_TYPE:
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, attr->value());
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLDirectoryElementImpl::id() const
+{
+ return ID_DIR;
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLMenuElementImpl::id() const
+{
+ return ID_MENU;
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLOListElementImpl::id() const
+{
+ return ID_OL;
+}
+
+void HTMLOListElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_TYPE:
+ if ( strcmp( attr->value(), "a" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ALPHA);
+ else if ( strcmp( attr->value(), "A" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ALPHA);
+ else if ( strcmp( attr->value(), "i" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ROMAN);
+ else if ( strcmp( attr->value(), "I" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ROMAN);
+ else if ( strcmp( attr->value(), "1" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_DECIMAL);
+ break;
+ case ATTR_START:
+ _start = attr->val() ? attr->val()->toInt() : 1;
+ break;
+ default:
+ HTMLUListElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLLIElementImpl::id() const
+{
+ return ID_LI;
+}
+
+void HTMLLIElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_VALUE:
+ if(m_render && m_render->isListItem() && m_render->style()->display() == LIST_ITEM)
+ static_cast<RenderListItem*>(m_render)->setValue(attr->value().toInt());
+ break;
+ case ATTR_TYPE:
+ if ( strcmp( attr->value(), "a" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ALPHA);
+ else if ( strcmp( attr->value(), "A" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ALPHA);
+ else if ( strcmp( attr->value(), "i" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_LOWER_ROMAN);
+ else if ( strcmp( attr->value(), "I" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_UPPER_ROMAN);
+ else if ( strcmp( attr->value(), "1" ) == 0 )
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_DECIMAL);
+ else
+ addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, attr->value());
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLLIElementImpl::attach()
+{
+ assert(!attached());
+
+ HTMLElementImpl::attach();
+
+ if ( m_render && m_render->style()->display() == LIST_ITEM ) {
+ RenderListItem* render = static_cast<RenderListItem*>( renderer() );
+ NodeImpl* listNode = 0;
+ NodeImpl* n = parentNode();
+ while ( !listNode && n ) {
+ switch( n->id() ) {
+ case ID_UL:
+ case ID_OL:
+ listNode = n;
+ break;
+ }
+ n = n->parentNode();
+ }
+
+ // if we are not in a list, then position us inside
+ // can't use addCSSProperty cause its inherited attribute
+ render->setInsideList( listNode );
+
+ DOMString v = getAttribute(ATTR_VALUE);
+ if ( !v.isEmpty() )
+ render->setValue( v.implementation()->toInt() );
+ }
+}
+
+
+// -------------------------------------------------------------------------
+
+
+NodeImpl::Id HTMLDListElementImpl::id() const
+{
+ return ID_DL;
+}
+
diff --git a/khtml/html/html_listimpl.h b/khtml/html/html_listimpl.h
new file mode 100644
index 000000000..d4a9f4436
--- /dev/null
+++ b/khtml/html/html_listimpl.h
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_LISTIMPL_H
+#define HTML_LISTIMPL_H
+
+/*
+ * we ignore the deprecated compact attribute. Netscape does so too...
+ */
+
+#include "html_elementimpl.h"
+
+namespace DOM
+{
+
+class DOMString;
+
+class HTMLUListElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLUListElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *);
+
+ virtual int start() const { return 1; }
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLDirectoryElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLDirectoryElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLMenuElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLMenuElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc) {}
+ virtual ~HTMLMenuElementImpl() {}
+
+ virtual Id id() const;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLOListElementImpl : public HTMLUListElementImpl
+{
+public:
+ HTMLOListElementImpl(DocumentImpl *doc)
+ : HTMLUListElementImpl(doc), _start(1) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *);
+
+ int start() const { return _start; }
+private:
+ int _start;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLLIElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLLIElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLDListElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLDListElementImpl(DocumentImpl *doc) : HTMLElementImpl(doc) {}
+ virtual ~HTMLDListElementImpl() {}
+
+ virtual Id id() const;
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_miscimpl.cpp b/khtml/html/html_miscimpl.cpp
new file mode 100644
index 000000000..bf0c56e00
--- /dev/null
+++ b/khtml/html/html_miscimpl.cpp
@@ -0,0 +1,443 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2005 Maksim Orlovich (maksim@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+// -------------------------------------------------------------------------
+#include "html/html_tableimpl.h"
+#include "html/html_miscimpl.h"
+#include "html/html_formimpl.h"
+#include "html/html_documentimpl.h"
+
+#include "misc/htmlhashes.h"
+#include "dom/dom_node.h"
+
+using namespace DOM;
+
+#include <kdebug.h>
+
+HTMLBaseFontElementImpl::HTMLBaseFontElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+}
+
+HTMLBaseFontElementImpl::~HTMLBaseFontElementImpl()
+{
+}
+
+NodeImpl::Id HTMLBaseFontElementImpl::id() const
+{
+ return ID_BASEFONT;
+}
+
+// -------------------------------------------------------------------------
+
+struct CollectionCache: public NodeListImpl::Cache
+{
+ static Cache* make() { return new CollectionCache; }
+
+ QDict<QValueList<NodeImpl*> > nameCache;
+
+ CollectionCache(): nameCache(127)
+ {
+ nameCache.setAutoDelete(true);
+ }
+
+ virtual void clear(DocumentImpl* doc)
+ {
+ Cache::clear(doc);
+ //qDeletaAll here in Qt4
+ nameCache.clear();
+ }
+};
+
+HTMLCollectionImpl::HTMLCollectionImpl(NodeImpl *_base, int _type):
+ NodeListImpl(_base, _type, CollectionCache::make)
+{
+ type = _type;
+}
+
+bool HTMLCollectionImpl::nodeMatches(NodeImpl *current, bool& deep) const
+{
+ if ( current->nodeType() != Node::ELEMENT_NODE )
+ {
+ deep = false;
+ return false;
+ }
+
+ bool check = false;
+ HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
+ switch(type)
+ {
+ case DOC_IMAGES:
+ if(e->id() == ID_IMG)
+ check = true;
+ break;
+ case DOC_SCRIPTS:
+ if(e->id() == ID_SCRIPT)
+ check = true;
+ break;
+ case DOC_FORMS:
+ if(e->id() == ID_FORM)
+ check = true;
+ break;
+ case DOC_LAYERS:
+ if(e->id() == ID_LAYER || e->id() == ID_ILAYER)
+ check = true;
+ break;
+ case TABLE_TBODIES:
+ if(e->id() == ID_TBODY)
+ check = true;
+ else if(e->id() == ID_TABLE)
+ deep = false;
+ break;
+ case TR_CELLS:
+ if(e->id() == ID_TD || e->id() == ID_TH)
+ check = true;
+ else if(e->id() == ID_TABLE)
+ deep = false;
+ break;
+ case TABLE_ROWS:
+ case TSECTION_ROWS:
+ if(e->id() == ID_TR)
+ check = true;
+ else if(e->id() == ID_TABLE)
+ deep = false;
+ break;
+ case SELECT_OPTIONS:
+ if(e->id() == ID_OPTION)
+ check = true;
+ break;
+ case MAP_AREAS:
+ if(e->id() == ID_AREA)
+ check = true;
+ break;
+ case DOC_APPLETS: // all OBJECT and APPLET elements
+ if(e->id() == ID_OBJECT || e->id() == ID_APPLET || e->id() == ID_EMBED)
+ check = true;
+ break;
+ case DOC_LINKS: // all A _and_ AREA elements with a value for href
+ if(e->id() == ID_A || e->id() == ID_AREA)
+ if(!e->getAttribute(ATTR_HREF).isNull())
+ check = true;
+ break;
+ case DOC_ANCHORS: // all A elements with a value for name and/or id
+ if(e->id() == ID_A) {
+ if(e->hasID() || !e->getAttribute(ATTR_NAME).isNull())
+ check = true;
+ }
+ break;
+ case DOC_ALL: // "all" elements
+ check = true;
+ break;
+ case NODE_CHILDREN: // first-level children
+ check = true;
+ deep = false;
+ break;
+ default:
+ kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
+ }
+
+ return check;
+}
+
+bool HTMLCollectionImpl::checkForNameMatch(NodeImpl *node, const DOMString &name) const
+{
+ if ( node->nodeType() != Node::ELEMENT_NODE )
+ return false;
+
+ HTMLElementImpl *e = static_cast<HTMLElementImpl *>(node);
+
+ //If ID matches, this is definitely a match
+ if (e->getAttribute(ATTR_ID) == name)
+ return true;
+
+ //Despite what the DOM spec says, neither IE nor Gecko actually
+ //care to prefer IDs. Instead, they just match everything
+ //that has ID or a name for nodes that have a name.
+ //Except for the form elements collection, Gecko always returns
+ //just one item. IE is more complex: its namedItem
+ //and call notation access return everything that matches,
+ //but the subscript notation is sometimes different.
+ //For now, we try to match IE, but without the subscript
+ //oddness, which I don't understand -- Maks.
+
+ bool checkName;
+ switch (e->id())
+ {
+ case ID_A:
+ case ID_APPLET:
+ case ID_BUTTON:
+ case ID_EMBED:
+ case ID_FORM:
+ case ID_IMG:
+ case ID_INPUT:
+ case ID_MAP:
+ case ID_META:
+ case ID_OBJECT:
+ case ID_SELECT:
+ case ID_TEXTAREA:
+ case ID_FRAME:
+ case ID_IFRAME:
+ case ID_FRAMESET:
+ checkName = true;
+ break;
+ default:
+ checkName = false;
+ }
+
+ if (checkName)
+ return e->getAttribute(ATTR_NAME) == name;
+ else
+ return false;
+}
+
+NodeImpl *HTMLCollectionImpl::item ( unsigned long index ) const
+{
+ //Most of the time, we just go in normal document order
+ if (type != TABLE_ROWS)
+ return NodeListImpl::item(index);
+
+ //For table.rows, we first need to check header, then bodies, then footer.
+ //we pack any extra headers/footer with bodies. This matches IE, and
+ //means doing the usual thing with length is right
+ const HTMLTableElementImpl* table = static_cast<const HTMLTableElementImpl*>(m_refNode);
+
+ long sectionIndex;
+ HTMLTableSectionElementImpl* section;
+
+ NodeImpl* found = 0;
+ if (table->findRowSection(index, section, sectionIndex)) {
+ HTMLCollectionImpl rows(section, TSECTION_ROWS);
+ found = rows.item(sectionIndex);
+ }
+
+ m_cache->current.node = found; //namedItem needs this.
+ m_cache->position = index;
+ return found;
+}
+
+unsigned long HTMLCollectionImpl::calcLength(NodeImpl *start) const
+{
+ if (type != TABLE_ROWS)
+ return NodeListImpl::calcLength(start);
+
+ unsigned length = 0;
+ const HTMLTableElementImpl* table = static_cast<const HTMLTableElementImpl*>(m_refNode);
+ for (NodeImpl* kid = table->firstChild(); kid; kid = kid->nextSibling()) {
+ HTMLCollectionImpl rows(kid, TSECTION_ROWS);
+ length += rows.length();
+ }
+ return length;
+}
+
+NodeImpl *HTMLCollectionImpl::firstItem() const
+{
+ return item(0);
+}
+
+NodeImpl *HTMLCollectionImpl::nextItem() const
+{
+ //### this assumes this is called immediately after nextItem --
+ //it this sane?
+ return item(m_cache->position + 1);
+}
+
+NodeImpl *HTMLCollectionImpl::namedItem( const DOMString &name ) const
+{
+ //Reset the position. The invariant is that nextNamedItem will start looking
+ //from the current position.
+ firstItem();
+
+ return nextNamedItem(name);
+}
+
+NodeImpl *HTMLCollectionImpl::nextNamedItem( const DOMString &name ) const
+{
+ while (NodeImpl* candidate = m_cache->current.node)
+ {
+ //Always advance, for next call
+ nextItem();
+ if (checkForNameMatch(candidate, name))
+ return candidate;
+ }
+ return 0;
+}
+
+QValueList<NodeImpl*> HTMLCollectionImpl::namedItems( const DOMString &name ) const
+{
+ QString key = name.string();
+
+ //We use a work-conserving design for the name cache presently -- only
+ //remember stuff about elements we were asked for.
+ m_cache->updateNodeListInfo(m_refNode->getDocument());
+ CollectionCache* cache = static_cast<CollectionCache*>(m_cache);
+ if (QValueList<NodeImpl*>* info = cache->nameCache.find(key)) {
+ return *info;
+ }
+ else {
+ QValueList<NodeImpl*>* newInfo = new QValueList<NodeImpl*>;
+
+ NodeImpl* match = namedItem(name);
+ while (match) {
+ newInfo->append(match);
+ match = nextNamedItem(name);
+ }
+
+ cache->nameCache.insert(key, newInfo);
+ return *newInfo;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+HTMLFormCollectionImpl::HTMLFormCollectionImpl(NodeImpl* _base)
+ : HTMLCollectionImpl(_base, FORM_ELEMENTS), currentNamePos(0), currentNameImgPos(0)
+{}
+
+NodeImpl *HTMLFormCollectionImpl::item( unsigned long index ) const
+{
+ m_cache->updateNodeListInfo(m_refNode->getDocument());
+
+ unsigned int dist = index;
+ unsigned int strt = 0;
+ if (m_cache->current.index && m_cache->position <= index)
+ {
+ dist = index - m_cache->position;
+ strt = m_cache->current.index;
+ }
+
+ QPtrList<HTMLGenericFormElementImpl>& l = static_cast<HTMLFormElementImpl*>( m_refNode )->formElements;
+ for (unsigned i = strt; i < l.count(); i++)
+ {
+ if (l.at( i )->isEnumeratable())
+ {
+ if (dist == 0)
+ {
+ //Found it!
+ m_cache->position = index;
+ m_cache->current.index = i;
+ return l.at( i );
+ }
+ else
+ --dist;
+ }
+ }
+ return 0;
+}
+
+unsigned long HTMLFormCollectionImpl::calcLength(NodeImpl *start) const
+{
+ unsigned length = 0;
+ QPtrList<HTMLGenericFormElementImpl> l = static_cast<HTMLFormElementImpl*>( start )->formElements;
+ for ( unsigned i = 0; i < l.count(); i++ )
+ if ( l.at( i )->isEnumeratable() )
+ ++length;
+ return length;
+}
+
+NodeImpl *HTMLFormCollectionImpl::namedItem( const DOMString &name ) const
+{
+ currentNamePos = 0;
+ currentNameImgPos = 0;
+ foundInput = false;
+ return nextNamedItem(name);
+}
+
+NodeImpl *HTMLFormCollectionImpl::nextNamedItem( const DOMString &name ) const
+{
+ QPtrList<HTMLGenericFormElementImpl>& l = static_cast<HTMLFormElementImpl*>( m_refNode )->formElements;
+
+ //Go through the list, trying to find the appropriate named form element.
+ for ( ; currentNamePos < l.count(); ++currentNamePos )
+ {
+ HTMLGenericFormElementImpl* el = l.at(currentNamePos);
+ if (el->isEnumeratable() &&
+ ((el->getAttribute(ATTR_ID) == name) ||
+ (el->getAttribute(ATTR_NAME) == name)))
+ {
+ ++currentNamePos; //Make next call start after this
+ foundInput = true;//No need to look for img
+ return el;
+ }
+ }
+
+ //If we got this far, we may need to start looking through the images,
+ //but only if no input tags were matched
+ if (foundInput) return 0;
+
+ QPtrList<HTMLImageElementImpl>& il = static_cast<HTMLFormElementImpl*>( m_refNode )->imgElements;
+ for ( ; currentNameImgPos < il.count(); ++currentNameImgPos )
+ {
+ HTMLImageElementImpl* el = il.at(currentNameImgPos);
+ if ((el->getAttribute(ATTR_ID) == name) ||
+ (el->getAttribute(ATTR_NAME) == name))
+ {
+ ++currentNameImgPos; //Make next call start after this
+ return el;
+ }
+ }
+
+ return 0;
+}
+
+// -------------------------------------------------------------------------
+HTMLMappedNameCollectionImpl::HTMLMappedNameCollectionImpl(NodeImpl* _base, int _type, const DOMString& _name):
+ HTMLCollectionImpl(_base, NodeListImpl::UNCACHEABLE), name(_name)
+{
+ type = _type; //We pass uncacheable to collection, but need our own type internally.
+}
+
+bool HTMLMappedNameCollectionImpl::nodeMatches(NodeImpl *current, bool& deep) const
+{
+ if ( current->nodeType() != Node::ELEMENT_NODE )
+ {
+ deep = false;
+ return false;
+ }
+
+ HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
+
+ return matchesName(e, type, name);
+}
+
+bool HTMLMappedNameCollectionImpl::matchesName( ElementImpl* el, int type, const DOMString& name )
+{
+ switch (el->id())
+ {
+ case ID_IMG:
+ case ID_FORM:
+ //Under document. these require non-empty name to see the element
+ if (type == DOCUMENT_NAMED_ITEMS && el->getAttribute(ATTR_NAME).isNull())
+ return false;
+ //Otherwise, fallthrough
+ case ID_OBJECT:
+ case ID_EMBED:
+ case ID_APPLET:
+ case ID_LAYER:
+ if (el->getAttribute(ATTR_NAME) == name || el->getAttribute(ATTR_ID) == name)
+ return true;
+ else
+ return false;
+ default:
+ return false;
+ }
+}
diff --git a/khtml/html/html_miscimpl.h b/khtml/html/html_miscimpl.h
new file mode 100644
index 000000000..beff1fe7d
--- /dev/null
+++ b/khtml/html/html_miscimpl.h
@@ -0,0 +1,150 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_MISCIMPL_H
+#define HTML_MISCIMPL_H
+
+#include <qvaluelist.h>
+#include "html_elementimpl.h"
+#include "misc/shared.h"
+
+namespace DOM {
+
+class Node;
+class DOMString;
+class HTMLCollection;
+
+class HTMLBaseFontElementImpl : public HTMLElementImpl
+{
+public:
+ HTMLBaseFontElementImpl(DocumentImpl *doc);
+
+ ~HTMLBaseFontElementImpl();
+
+ virtual Id id() const;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLCollectionImpl : public NodeListImpl
+{
+ friend class DOM::HTMLCollection;
+public:
+ enum Type {
+ // from HTMLDocument
+ DOC_IMAGES = LAST_NODE_LIST + 1, // all IMG elements in the document
+ DOC_APPLETS, // all OBJECT and APPLET elements
+ DOC_FORMS, // all FORMS
+ DOC_LAYERS, // all LAYERS
+ DOC_LINKS, // all A _and_ AREA elements with a value for href
+ DOC_ANCHORS, // all A elements with a value for name
+ DOC_SCRIPTS, // all SCRIPT elements
+ // from HTMLTable, HTMLTableSection, HTMLTableRow
+ TABLE_ROWS, // all rows in this table
+ TABLE_TBODIES, // all TBODY elements in this table
+ TSECTION_ROWS, // all rows elements in this table section
+ TR_CELLS, // all CELLS in this row
+ // from SELECT
+ SELECT_OPTIONS,
+ // from HTMLMap
+ MAP_AREAS,
+ DOC_ALL, // "all" elements (IE)
+ NODE_CHILDREN, // first-level children (IE)
+ FORM_ELEMENTS, // input elements in a form
+ WINDOW_NAMED_ITEMS,
+ DOCUMENT_NAMED_ITEMS,
+ LAST_TYPE
+ };
+
+ HTMLCollectionImpl(NodeImpl *_base, int _tagId);
+
+ virtual NodeImpl *item ( unsigned long index ) const;
+
+ // obsolete and not domtree changes save
+ virtual NodeImpl *firstItem() const;
+ virtual NodeImpl *nextItem() const;
+
+ virtual NodeImpl *namedItem ( const DOMString &name ) const;
+ // In case of multiple items named the same way
+ virtual NodeImpl *nextNamedItem( const DOMString &name ) const;
+
+ QValueList<NodeImpl*> namedItems( const DOMString &name ) const;
+
+ int getType() const {
+ return type;
+ }
+protected:
+ virtual unsigned long calcLength(NodeImpl *start) const;
+
+ // The collection list the following elements
+ int type:8;
+
+ // Reimplemented from NodeListImpl
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const;
+
+ // Helper for name iteration: checks whether ID matches,
+ // and inserts any name-matching things into namedItemsWithName
+ bool checkForNameMatch(NodeImpl *node, const DOMString &name) const;
+};
+
+// this whole class is just a big hack to find form elements even in
+// malformed HTML elements
+// the famous <table><tr><form><td> problem
+class HTMLFormCollectionImpl : public HTMLCollectionImpl
+{
+public:
+ // base must inherit HTMLGenericFormElementImpl or this won't work
+ HTMLFormCollectionImpl(NodeImpl* _base);
+ ~HTMLFormCollectionImpl() { }
+
+ virtual NodeImpl *item ( unsigned long index ) const;
+
+ virtual NodeImpl *namedItem ( const DOMString &name ) const;
+ // In case of multiple items named the same way
+ virtual NodeImpl *nextNamedItem( const DOMString &name ) const;
+protected:
+ virtual unsigned long calcLength( NodeImpl *start ) const;
+
+private:
+ mutable unsigned currentNamePos;
+ mutable unsigned currentNameImgPos;
+ mutable bool foundInput;
+};
+
+/*
+ Special collection for items of given name/id under document. or window.; but using
+ iteration interface
+*/
+class HTMLMappedNameCollectionImpl : public HTMLCollectionImpl
+{
+public:
+ HTMLMappedNameCollectionImpl(NodeImpl* _base, int type, const DOMString& name);
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const;
+
+ static bool matchesName( ElementImpl* el, int type, const DOMString& name);
+private:
+ DOMString name;
+};
+
+} //namespace
+
+#endif
diff --git a/khtml/html/html_objectimpl.cpp b/khtml/html/html_objectimpl.cpp
new file mode 100644
index 000000000..8a60ba41f
--- /dev/null
+++ b/khtml/html/html_objectimpl.cpp
@@ -0,0 +1,465 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "html/html_objectimpl.h"
+
+#include "khtml_part.h"
+#include "dom/dom_string.h"
+#include "misc/htmlhashes.h"
+#include "khtmlview.h"
+#include <qstring.h>
+#include <qvariant.h>
+#include <qmap.h>
+#include <qtimer.h>
+
+#include <kdebug.h>
+#include <kimageio.h>
+
+#include "xml/dom_docimpl.h"
+#include "css/cssstyleselector.h"
+#include "css/csshelper.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "rendering/render_applet.h"
+#include "rendering/render_frames.h"
+#include "rendering/render_image.h"
+#include "xml/dom2_eventsimpl.h"
+
+using namespace DOM;
+using namespace khtml;
+
+// -------------------------------------------------------------------------
+HTMLObjectBaseElementImpl::HTMLObjectBaseElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+ needWidgetUpdate = false;
+ m_renderAlternative = false;
+}
+
+void HTMLObjectBaseElementImpl::setServiceType(const QString & val) {
+ serviceType = val.lower();
+ int pos = serviceType.find( ";" );
+ if ( pos!=-1 )
+ serviceType.truncate( pos );
+}
+
+void HTMLObjectBaseElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch ( attr->id() )
+ {
+ case ATTR_TYPE:
+ case ATTR_CODETYPE:
+ if (attr->val()) {
+ DOM::DOMStringImpl *stringImpl = attr->val();
+ QString val = QConstString( stringImpl->s, stringImpl->l ).string();
+ setServiceType( val );
+ needWidgetUpdate = true;
+ }
+ break;
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_NAME:
+ if (inDocument() && m_name != attr->value()) {
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ getDocument()->underDocNamedCache().add (attr->value().string(), this);
+ }
+ m_name = attr->value();
+ //fallthrough
+ default:
+ HTMLElementImpl::parseAttribute( attr );
+ }
+}
+
+void HTMLObjectBaseElementImpl::removedFromDocument()
+{
+ getDocument()->underDocNamedCache().remove(m_name.string(), this);
+ HTMLElementImpl::removedFromDocument();
+}
+
+void HTMLObjectBaseElementImpl::insertedIntoDocument()
+{
+ getDocument()->underDocNamedCache().add(m_name.string(), this);
+ HTMLElementImpl::insertedIntoDocument();
+}
+
+void HTMLObjectBaseElementImpl::removeId(const QString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLObjectBaseElementImpl::addId (const QString& id)
+{
+ getDocument()->underDocNamedCache().add(id, this);
+ HTMLElementImpl::addId(id);
+}
+
+void HTMLObjectBaseElementImpl::recalcStyle( StyleChange ch )
+{
+ if (needWidgetUpdate) {
+ if(m_render && strcmp( m_render->renderName(), "RenderPartObject" ) == 0 )
+ static_cast<RenderPartObject*>(m_render)->updateWidget();
+ needWidgetUpdate = false;
+ }
+ HTMLElementImpl::recalcStyle( ch );
+}
+
+void HTMLObjectBaseElementImpl::renderAlternative()
+{
+ if ( m_renderAlternative ) return;
+ QTimer::singleShot( 0, this, SLOT( slotRenderAlternative() ) );
+}
+
+void HTMLObjectBaseElementImpl::slotRenderAlternative()
+{
+ // the singleshot timer might have fired after we're removed
+ // from the document, but not yet deleted due to references
+ if ( !inDocument() || m_renderAlternative ) return;
+
+ // ### there can be a m_render if this is called from our attach indirectly
+ if ( attached() || m_render)
+ detach();
+
+ m_renderAlternative = true;
+
+ attach();
+}
+
+void HTMLObjectBaseElementImpl::attach() {
+ assert(!attached());
+ assert(!m_render);
+
+ if (serviceType.isEmpty() && url.startsWith("data:")) {
+ // Extract the MIME type from the data URL.
+ int index = url.find(';');
+ if (index == -1)
+ index = url.find(',');
+ if (index != -1) {
+ int len = index - 5;
+ if (len > 0)
+ serviceType = url.mid(5, len);
+ else
+ serviceType = "text/plain"; // Data URLs with no MIME type are considered text/plain.
+ }
+ }
+
+ bool imagelike = serviceType.startsWith("image/") &&
+ !KImageIO::typeForMime(serviceType).isNull();
+
+ if (m_renderAlternative && !imagelike) {
+ // render alternative content
+ ElementImpl::attach();
+ return;
+ }
+
+ if (!parentNode()->renderer()) {
+ NodeBaseImpl::attach();
+ return;
+ }
+
+ RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
+ _style->ref();
+
+ if (parentNode()->renderer() && parentNode()->renderer()->childAllowed() &&
+ _style->display() != NONE)
+ {
+ needWidgetUpdate = false;
+
+ if (imagelike) {
+ m_render = new (getDocument()->renderArena()) RenderImage(this);
+ // make sure we don't attach the inner contents
+ addCSSProperty(CSS_PROP_DISPLAY, CSS_VAL_NONE);
+ }
+ else
+ m_render = new (getDocument()->renderArena())RenderPartObject(this);
+
+ m_render->setStyle(_style);
+ parentNode()->renderer()->addChild(m_render, nextRenderer());
+ if (imagelike)
+ m_render->updateFromElement();
+ }
+
+ _style->deref();
+ NodeBaseImpl::attach();
+
+ // ### do this when we are actually finished loading instead
+ if (m_render) dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false);
+}
+
+
+// -------------------------------------------------------------------------
+
+HTMLAppletElementImpl::HTMLAppletElementImpl(DocumentImpl *doc)
+ : HTMLObjectBaseElementImpl(doc)
+{
+ serviceType = "application/x-java-applet";
+ needWidgetUpdate = true;
+}
+
+HTMLAppletElementImpl::~HTMLAppletElementImpl()
+{
+}
+
+NodeImpl::Id HTMLAppletElementImpl::id() const
+{
+ return ID_APPLET;
+}
+
+void HTMLAppletElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch( attr->id() )
+ {
+ case ATTR_CODEBASE:
+ case ATTR_ARCHIVE:
+ case ATTR_CODE:
+ case ATTR_OBJECT:
+ case ATTR_ALT:
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_VSPACE:
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ break;
+ case ATTR_HSPACE:
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
+ break;
+ case ATTR_VALIGN:
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower() );
+ break;
+ default:
+ HTMLObjectBaseElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLAppletElementImpl::attach()
+{
+ KHTMLView* w = getDocument()->view();
+
+#ifndef Q_WS_QWS // FIXME?
+ DOMString codeBase = getAttribute( ATTR_CODEBASE );
+ DOMString code = getAttribute( ATTR_CODE );
+ if ( !codeBase.isEmpty() )
+ url = codeBase.string();
+ if ( !code.isEmpty() )
+ url = code.string();
+
+ if (!w || !w->part()->javaEnabled())
+#endif
+ m_renderAlternative = true;
+
+ HTMLObjectBaseElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLEmbedElementImpl::HTMLEmbedElementImpl(DocumentImpl *doc)
+ : HTMLObjectBaseElementImpl(doc)
+{
+}
+
+HTMLEmbedElementImpl::~HTMLEmbedElementImpl()
+{
+}
+
+NodeImpl::Id HTMLEmbedElementImpl::id() const
+{
+ return ID_EMBED;
+}
+
+void HTMLEmbedElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch ( attr->id() )
+ {
+ case ATTR_CODE:
+ case ATTR_SRC:
+ url = khtml::parseURL(attr->val()).string();
+ needWidgetUpdate = true;
+ break;
+ case ATTR_BORDER:
+ addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
+ addCSSProperty( CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID );
+ addCSSProperty( CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID );
+ break;
+ case ATTR_VSPACE:
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ break;
+ case ATTR_HSPACE:
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_VALIGN:
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower() );
+ break;
+ case ATTR_PLUGINPAGE:
+ case ATTR_PLUGINSPAGE: {
+ pluginPage = attr->value().string();
+ break;
+ }
+ case ATTR_HIDDEN:
+ if (strcasecmp( attr->value(), "yes" ) == 0 || strcasecmp( attr->value() , "true") == 0 )
+ hidden = true;
+ else
+ hidden = false;
+ break;
+ default:
+ HTMLObjectBaseElementImpl::parseAttribute( attr );
+ }
+}
+
+void HTMLEmbedElementImpl::attach()
+{
+ KHTMLView* w = getDocument()->view();
+
+ if (!w || !w->part()->pluginsEnabled())
+ m_renderAlternative = true;
+
+ if (parentNode()->id() == ID_OBJECT)
+ NodeBaseImpl::attach();
+ else
+ HTMLObjectBaseElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentImpl *doc)
+ : HTMLObjectBaseElementImpl(doc)
+{
+}
+
+HTMLObjectElementImpl::~HTMLObjectElementImpl()
+{
+}
+
+NodeImpl::Id HTMLObjectElementImpl::id() const
+{
+ return ID_OBJECT;
+}
+
+HTMLFormElementImpl *HTMLObjectElementImpl::form() const
+{
+ return 0;
+}
+
+void HTMLObjectElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch ( attr->id() )
+ {
+ case ATTR_DATA:
+ url = khtml::parseURL( attr->val() ).string();
+ needWidgetUpdate = true;
+ break;
+ case ATTR_CLASSID:
+ classId = attr->value().string();
+ needWidgetUpdate = true;
+ break;
+ case ATTR_ONLOAD: // ### support load/unload on object elements
+ setHTMLEventListener(EventImpl::LOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onload", this));
+ break;
+ case ATTR_ONUNLOAD:
+ setHTMLEventListener(EventImpl::UNLOAD_EVENT,
+ getDocument()->createHTMLEventListener(attr->value().string(), "onunload", this));
+ break;
+ case ATTR_VSPACE:
+ addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
+ break;
+ case ATTR_HSPACE:
+ addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
+ break;
+ case ATTR_ALIGN:
+ addHTMLAlignment( attr->value() );
+ break;
+ case ATTR_VALIGN:
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower() );
+ break;
+ default:
+ HTMLObjectBaseElementImpl::parseAttribute( attr );
+ }
+}
+
+DocumentImpl* HTMLObjectElementImpl::contentDocument() const
+{
+ if ( !m_render ) return 0;
+ if ( !m_render->isWidget() ) return 0;
+ QWidget* widget = static_cast<RenderWidget*>( m_render )->widget();
+ if( widget && ::qt_cast<KHTMLView*>( widget ) )
+ return static_cast<KHTMLView*>( widget )->part()->xmlDocImpl();
+ return 0;
+}
+
+void HTMLObjectElementImpl::attach()
+{
+ KHTMLView* w = getDocument()->view();
+
+ if (!w || !w->part()->pluginsEnabled())
+ m_renderAlternative = true;
+
+ HTMLObjectBaseElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLParamElementImpl::id() const
+{
+ return ID_PARAM;
+}
+
+void HTMLParamElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch( attr->id() )
+ {
+ case ATTR_VALUE:
+ m_value = attr->value().string();
+ break;
+ case ATTR_ID:
+ if (getDocument()->htmlMode() != DocumentImpl::XHtml) break;
+ // fall through
+ case ATTR_NAME:
+ m_name = attr->value().string();
+ // fall through
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+#include "html_objectimpl.moc"
diff --git a/khtml/html/html_objectimpl.h b/khtml/html/html_objectimpl.h
new file mode 100644
index 000000000..a33786442
--- /dev/null
+++ b/khtml/html/html_objectimpl.h
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_OBJECTIMPL_H
+#define HTML_OBJECTIMPL_H
+
+#include "html_elementimpl.h"
+#include "xml/dom_stringimpl.h"
+#include <qobject.h>
+#include <qstringlist.h>
+
+class KHTMLView;
+
+// -------------------------------------------------------------------------
+namespace DOM {
+
+class HTMLFormElementImpl;
+class DOMStringImpl;
+
+class HTMLObjectBaseElementImpl : public QObject, public HTMLElementImpl
+{
+ Q_OBJECT
+public:
+ HTMLObjectBaseElementImpl(DocumentImpl *doc);
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+
+ virtual void recalcStyle( StyleChange ch );
+
+ void renderAlternative();
+
+ void setServiceType(const QString &);
+
+ QString url;
+ QString classId;
+ QString serviceType;
+ bool needWidgetUpdate;
+ bool m_renderAlternative;
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void addId(const QString& id);
+ virtual void removeId(const QString& id);
+protected slots:
+ void slotRenderAlternative();
+protected:
+ DOMString m_name;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLAppletElementImpl : public HTMLObjectBaseElementImpl
+{
+public:
+ HTMLAppletElementImpl(DocumentImpl *doc);
+
+ ~HTMLAppletElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *token);
+ virtual void attach();
+protected:
+ khtml::VAlign valign;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLEmbedElementImpl : public HTMLObjectBaseElementImpl
+{
+public:
+ HTMLEmbedElementImpl(DocumentImpl *doc);
+ ~HTMLEmbedElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+
+ QString pluginPage;
+ bool hidden;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLObjectElementImpl : public HTMLObjectBaseElementImpl
+{
+public:
+ HTMLObjectElementImpl(DocumentImpl *doc);
+
+ ~HTMLObjectElementImpl();
+
+ virtual Id id() const;
+
+ HTMLFormElementImpl *form() const;
+
+ virtual void parseAttribute(AttributeImpl *token);
+
+ virtual void attach();
+
+ DocumentImpl* contentDocument() const;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLParamElementImpl : public HTMLElementImpl
+{
+ friend class HTMLAppletElementImpl;
+public:
+ HTMLParamElementImpl(DocumentImpl* _doc) : HTMLElementImpl(_doc) {}
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *token);
+
+ QString name() const { return m_name; }
+ QString value() const { return m_value; }
+
+ protected:
+ QString m_name;
+ QString m_value;
+};
+
+} // namespace
+#endif
diff --git a/khtml/html/html_tableimpl.cpp b/khtml/html/html_tableimpl.cpp
new file mode 100644
index 000000000..3d11c5e98
--- /dev/null
+++ b/khtml/html/html_tableimpl.cpp
@@ -0,0 +1,994 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ * (C) 1997 Torben Weis (weis@kde.org)
+ * (C) 1998 Waldo Bastian (bastian@kde.org)
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2003 Apple Computer, Inc.
+ * (C) 2006 Maksim Orlovich (maksim@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "html/html_documentimpl.h"
+#include "html/html_tableimpl.h"
+
+#include "dom/dom_exception.h"
+#include "dom/dom_node.h"
+
+#include "misc/htmlhashes.h"
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include "css/cssstyleselector.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/csshelper.h"
+
+#include "rendering/render_table.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+using namespace khtml;
+using namespace DOM;
+
+HTMLTableElementImpl::HTMLTableElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+ rules = None;
+ frame = Void;
+
+ padding = 1;
+
+ m_solid = false;
+
+ // reset font color and sizes here, if we don't have strict parse mode.
+ // this is 90% compatible to ie and mozilla, and the by way easiest solution...
+ // only difference to 100% correct is that in strict mode <font> elements are propagated into tables.
+ if ( getDocument()->parseMode() < DocumentImpl::Transitional ) {
+ addCSSProperty( CSS_PROP_FONT_SIZE, CSS_VAL_MEDIUM );
+ addCSSProperty( CSS_PROP_COLOR, CSS_VAL__KHTML_TEXT );
+ }
+}
+
+HTMLTableElementImpl::~HTMLTableElementImpl()
+{
+}
+
+NodeImpl::Id HTMLTableElementImpl::id() const
+{
+ return ID_TABLE;
+}
+
+NodeImpl* HTMLTableElementImpl::setCaption( HTMLTableCaptionElementImpl *c )
+{
+ int exceptioncode = 0;
+ NodeImpl* r;
+ if(ElementImpl* cap = caption()) {
+ replaceChild ( c, cap, exceptioncode );
+ r = c;
+ }
+ else
+ r = insertBefore( c, firstChild(), exceptioncode );
+ tCaption = c;
+ return r;
+}
+
+NodeImpl* HTMLTableElementImpl::setTHead( HTMLTableSectionElementImpl *s )
+{
+ int exceptioncode = 0;
+ NodeImpl* r;
+ if( ElementImpl* head = tHead() ) {
+ replaceChild( s, head, exceptioncode );
+ r = s;
+ }
+ else if(ElementImpl* foot = tFoot())
+ r = insertBefore( s, foot, exceptioncode );
+ else if(ElementImpl* firstBody = tFirstBody())
+ r = insertBefore( s, firstBody, exceptioncode );
+ else
+ r = appendChild( s, exceptioncode );
+
+ head = s;
+ return r;
+}
+
+NodeImpl* HTMLTableElementImpl::setTFoot( HTMLTableSectionElementImpl *s )
+{
+ int exceptioncode = 0;
+ NodeImpl* r;
+ if(ElementImpl* foot = tFoot()) {
+ replaceChild ( s, foot, exceptioncode );
+ r = s;
+ } else if(ElementImpl* firstBody = tFirstBody())
+ r = insertBefore( s, firstBody, exceptioncode );
+ else
+ r = appendChild( s, exceptioncode );
+ foot = s;
+ return r;
+}
+
+NodeImpl* HTMLTableElementImpl::setTBody( HTMLTableSectionElementImpl *s )
+{
+ int exceptioncode = 0;
+ NodeImpl* r;
+
+ if(ElementImpl* firstBody = tFirstBody()) {
+ replaceChild ( s, firstBody, exceptioncode );
+ r = s;
+ } else
+ r = appendChild( s, exceptioncode );
+ firstBody = s;
+
+ return r;
+}
+
+HTMLElementImpl *HTMLTableElementImpl::createTHead( )
+{
+ if(!tHead())
+ {
+ int exceptioncode = 0;
+ ElementImpl* head = new HTMLTableSectionElementImpl(docPtr(), ID_THEAD, true /* implicit */);
+ if(ElementImpl* foot = tFoot())
+ insertBefore( head, foot, exceptioncode );
+ else if(ElementImpl* firstBody = tFirstBody())
+ insertBefore( head, firstBody, exceptioncode);
+ else
+ appendChild(head, exceptioncode);
+ }
+ return tHead();
+}
+
+void HTMLTableElementImpl::deleteTHead( )
+{
+ if(ElementImpl* head = tHead()) {
+ int exceptioncode = 0;
+ removeChild(head, exceptioncode);
+ }
+}
+
+HTMLElementImpl *HTMLTableElementImpl::createTFoot( )
+{
+ if(!tFoot())
+ {
+ int exceptioncode = 0;
+ ElementImpl* foot = new HTMLTableSectionElementImpl(docPtr(), ID_TFOOT, true /*implicit */);
+ if(ElementImpl* firstBody = tFirstBody())
+ insertBefore( foot, firstBody, exceptioncode );
+ else
+ appendChild(foot, exceptioncode);
+ }
+ return tFoot();
+}
+
+void HTMLTableElementImpl::deleteTFoot( )
+{
+ if(ElementImpl* foot = tFoot()) {
+ int exceptioncode = 0;
+ removeChild(foot, exceptioncode);
+ }
+}
+
+HTMLElementImpl *HTMLTableElementImpl::createCaption( )
+{
+ if(!caption())
+ {
+ int exceptioncode = 0;
+ ElementImpl* tCaption = new HTMLTableCaptionElementImpl(docPtr());
+ insertBefore( tCaption, firstChild(), exceptioncode );
+ }
+ return caption();
+}
+
+void HTMLTableElementImpl::deleteCaption( )
+{
+ if(ElementImpl* tCaption = caption()) {
+ int exceptioncode = 0;
+ removeChild(tCaption, exceptioncode);
+ }
+}
+
+/**
+ Helper. This checks whether the section contains the desired index, and if so,
+ returns the section. Otherwise, it adjust the index, and returns 0.
+ indeces < 0 are considered to be infinite.
+
+ lastSection is adjusted to reflect the parameter passed in.
+*/
+static inline HTMLTableSectionElementImpl* processSection(HTMLTableSectionElementImpl* section,
+ HTMLTableSectionElementImpl* &lastSection, long& index)
+{
+ lastSection = section;
+ if ( index < 0 ) //append/last mode
+ return 0;
+
+ long rows = section->numRows();
+ if ( index >= rows ) {
+ section = 0;
+ index -= rows;
+ }
+ return section;
+}
+
+
+bool HTMLTableElementImpl::findRowSection(long index,
+ HTMLTableSectionElementImpl*& outSection,
+ long& outIndex) const
+{
+ HTMLTableSectionElementImpl* foot = tFoot();
+ HTMLTableSectionElementImpl* head = tHead();
+
+ HTMLTableSectionElementImpl* section = 0L;
+ HTMLTableSectionElementImpl* lastSection = 0L;
+
+ if ( head )
+ section = processSection( head, lastSection, index );
+
+ if ( !section ) {
+ for ( NodeImpl *node = firstChild(); node; node = node->nextSibling() ) {
+ if ( ( node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY ) &&
+ node != foot && node != head ) {
+ section = processSection( static_cast<HTMLTableSectionElementImpl *>(node),
+ lastSection, index );
+ if ( section )
+ break;
+ }
+ }
+ }
+
+ if ( !section && foot )
+ section = processSection( foot, lastSection, index );
+
+ outIndex = index;
+ if ( section ) {
+ outSection = section;
+ return true;
+ } else {
+ outSection = lastSection;
+ return false;
+ }
+}
+
+HTMLElementImpl *HTMLTableElementImpl::insertRow( long index, int &exceptioncode )
+{
+ // The DOM requires that we create a tbody if the table is empty
+ // (cf DOM2TS HTMLTableElement31 test). This includes even the cases where
+ // there are <tr>'s immediately under the table, as they're essentially
+ // ignored by these functions.
+ HTMLTableSectionElementImpl* foot = tFoot();
+ HTMLTableSectionElementImpl* head = tHead();
+ if(!tFirstBody() && !foot && !head)
+ setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY, true /* implicit */) );
+
+ //kdDebug(6030) << k_funcinfo << index << endl;
+
+ long sectionIndex;
+ HTMLTableSectionElementImpl* section;
+ if ( findRowSection( index, section, sectionIndex ) )
+ return section->insertRow( sectionIndex, exceptioncode );
+ else if ( index == -1 || sectionIndex == 0 )
+ return section->insertRow( section->numRows(), exceptioncode );
+
+ // The index is too big.
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ return 0L;
+}
+
+void HTMLTableElementImpl::deleteRow( long index, int &exceptioncode )
+{
+ long sectionIndex;
+ HTMLTableSectionElementImpl* section;
+ if ( findRowSection( index, section, sectionIndex ) )
+ section->deleteRow( sectionIndex, exceptioncode );
+ else if ( section && index == -1 )
+ section->deleteRow( -1, exceptioncode );
+ else
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+}
+
+NodeImpl *HTMLTableElementImpl::appendChild(NodeImpl *child, int &exceptioncode)
+{
+ NodeImpl* retval = HTMLElementImpl::appendChild( child, exceptioncode );
+ if(retval)
+ handleChildAppend( child );
+ return retval;
+}
+
+void HTMLTableElementImpl::handleChildAdd( NodeImpl *child )
+{
+ if (!child) return;
+ switch(child->id()) {
+ case ID_CAPTION:
+ tCaption.childAdded(this, child);
+ break;
+ case ID_THEAD:
+ head.childAdded(this, child);
+ break;
+ case ID_TFOOT:
+ foot.childAdded(this, child);
+ break;
+ case ID_TBODY:
+ firstBody.childAdded(this, child);
+ break;
+ }
+}
+
+void HTMLTableElementImpl::handleChildAppend( NodeImpl *child )
+{
+ if (!child) return;
+ switch(child->id()) {
+ case ID_CAPTION:
+ tCaption.childAppended(child);
+ break;
+ case ID_THEAD:
+ head.childAppended(child);
+ break;
+ case ID_TFOOT:
+ foot.childAppended(child);
+ break;
+ case ID_TBODY:
+ firstBody.childAppended(child);
+ break;
+ }
+}
+
+void HTMLTableElementImpl::handleChildRemove( NodeImpl *child )
+{
+ if (!child) return;
+ switch(child->id()) {
+ case ID_CAPTION:
+ tCaption.childRemoved(this, child);
+ break;
+ case ID_THEAD:
+ head.childRemoved(this, child);
+ break;
+ case ID_TFOOT:
+ foot.childRemoved(this, child);
+ break;
+ case ID_TBODY:
+ firstBody.childRemoved(this, child);
+ break;
+ }
+}
+
+NodeImpl *HTMLTableElementImpl::addChild(NodeImpl *child)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child->nodeName().string() << " )" << endl;
+#endif
+
+ NodeImpl *retval = HTMLElementImpl::addChild( child );
+ if ( retval )
+ handleChildAppend( child );
+
+ return retval;
+}
+
+NodeImpl *HTMLTableElementImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
+{
+ NodeImpl* retval = HTMLElementImpl::insertBefore( newChild, refChild, exceptioncode);
+ if (retval)
+ handleChildAdd( newChild );
+
+ return retval;
+}
+
+void HTMLTableElementImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
+{
+ handleChildRemove( oldChild ); //Always safe.
+ HTMLElementImpl::replaceChild( newChild, oldChild, exceptioncode );
+ if ( !exceptioncode )
+ handleChildAdd( newChild );
+}
+
+void HTMLTableElementImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
+{
+ handleChildRemove( oldChild );
+ HTMLElementImpl::removeChild( oldChild, exceptioncode);
+}
+
+void HTMLTableElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ // ### to CSS!!
+ switch(attr->id())
+ {
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength( CSS_PROP_WIDTH, attr->value() );
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_BORDER:
+ {
+ int border;
+ // ### this needs more work, as the border value is not only
+ // the border of the box, but also between the cells
+ if(!attr->val())
+ border = 0;
+ else if(attr->val()->l == 0)
+ border = 1;
+ else
+ border = attr->val()->toInt();
+#ifdef DEBUG_DRAW_BORDER
+ border=1;
+#endif
+ DOMString v = QString::number( border );
+ addCSSLength(CSS_PROP_BORDER_WIDTH, v );
+
+ // wanted by HTML4 specs
+ if(!border)
+ frame = Void, rules = None;
+ else
+ frame = Box, rules = All;
+
+
+ if (attached()) updateFrame();
+ break;
+ }
+ case ATTR_BGCOLOR:
+ if (!attr->value().isEmpty())
+ addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
+ break;
+ case ATTR_BORDERCOLOR:
+ if(!attr->value().isEmpty()) {
+ addHTMLColor(CSS_PROP_BORDER_COLOR, attr->value());
+ m_solid = true;
+ }
+
+ if (attached()) updateFrame();
+ break;
+ case ATTR_BACKGROUND:
+ {
+ if (!attr->value().isEmpty()) {
+ QString url = khtml::parseURL( attr->value() ).string();
+ url = getDocument()->completeURL( url );
+ addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" );
+ }
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE);
+ break;
+ }
+ case ATTR_FRAME:
+
+ if ( strcasecmp( attr->value(), "void" ) == 0 )
+ frame = Void;
+ else if ( strcasecmp( attr->value(), "border" ) == 0 )
+ frame = Box;
+ else if ( strcasecmp( attr->value(), "box" ) == 0 )
+ frame = Box;
+ else if ( strcasecmp( attr->value(), "hsides" ) == 0 )
+ frame = Hsides;
+ else if ( strcasecmp( attr->value(), "vsides" ) == 0 )
+ frame = Vsides;
+ else if ( strcasecmp( attr->value(), "above" ) == 0 )
+ frame = Above;
+ else if ( strcasecmp( attr->value(), "below" ) == 0 )
+ frame = Below;
+ else if ( strcasecmp( attr->value(), "lhs" ) == 0 )
+ frame = Lhs;
+ else if ( strcasecmp( attr->value(), "rhs" ) == 0 )
+ frame = Rhs;
+
+ if (attached()) updateFrame();
+ break;
+ case ATTR_RULES:
+ if ( strcasecmp( attr->value(), "none" ) == 0 )
+ rules = None;
+ else if ( strcasecmp( attr->value(), "groups" ) == 0 )
+ rules = Groups;
+ else if ( strcasecmp( attr->value(), "rows" ) == 0 )
+ rules = Rows;
+ else if ( strcasecmp( attr->value(), "cols" ) == 0 )
+ rules = Cols;
+ else if ( strcasecmp( attr->value(), "all" ) == 0 )
+ rules = All;
+ if (attached()) updateFrame();
+ break;
+ case ATTR_CELLSPACING:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_BORDER_SPACING, attr->value(), true);
+ else
+ removeCSSProperty(CSS_PROP_BORDER_SPACING);
+ break;
+ case ATTR_CELLPADDING:
+ if (!attr->value().isEmpty())
+ padding = kMax( 0, attr->value().toInt() );
+ else
+ padding = 1;
+ if (m_render && m_render->isTable()) {
+ static_cast<RenderTable *>(m_render)->setCellPadding(padding);
+ if (!m_render->needsLayout())
+ m_render->setNeedsLayout(true);
+ }
+ break;
+ case ATTR_COLS:
+ {
+ // ###
+#if 0
+ int c;
+ c = attr->val()->toInt();
+ addColumns(c-totalCols);
+#endif
+ break;
+
+ }
+ case ATTR_ALIGN:
+ setChanged();
+ break;
+ case ATTR_VALIGN:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
+ break;
+ case ATTR_NOSAVE:
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLTableElementImpl::attach()
+{
+ updateFrame();
+ HTMLElementImpl::attach();
+ if ( m_render && m_render->isTable() )
+ static_cast<RenderTable *>(m_render)->setCellPadding( padding );
+}
+
+void HTMLTableElementImpl::close()
+{
+ ElementImpl* firstBody = tFirstBody();
+ if (firstBody && !firstBody->closed())
+ firstBody->close();
+ HTMLElementImpl::close();
+}
+
+void HTMLTableElementImpl::updateFrame()
+{
+ int v = m_solid ? CSS_VAL_SOLID : CSS_VAL_OUTSET;
+ if ( frame & Above )
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, v);
+ else
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_NONE);
+ if ( frame & Below )
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v);
+ else
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_NONE);
+ if ( frame & Lhs )
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, v);
+ else
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_NONE);
+ if ( frame & Rhs )
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, v);
+ else
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_NONE);
+}
+
+// --------------------------------------------------------------------------
+
+void HTMLTablePartElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_BGCOLOR:
+ if (attr->val())
+ addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value() );
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
+ break;
+ case ATTR_BACKGROUND:
+ {
+ if (attr->val()) {
+ QString url = khtml::parseURL( attr->value() ).string();
+ url = getDocument()->completeURL( url );
+ addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" );
+ }
+ else
+ removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE);
+ break;
+ }
+ case ATTR_BORDERCOLOR:
+ {
+ if(!attr->value().isEmpty()) {
+ addHTMLColor(CSS_PROP_BORDER_COLOR, attr->value());
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
+ }
+ break;
+ }
+ case ATTR_ALIGN:
+ {
+ DOMString v = attr->value();
+ if ( strcasecmp( attr->value(), "middle" ) == 0 || strcasecmp( attr->value(), "center" ) == 0 )
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
+ else if (strcasecmp(attr->value(), "absmiddle") == 0)
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL_CENTER);
+ else if (strcasecmp(attr->value(), "left") == 0)
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
+ else if (strcasecmp(attr->value(), "right") == 0)
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
+ else
+ addCSSProperty(CSS_PROP_TEXT_ALIGN, v);
+ break;
+ }
+ case ATTR_VALIGN:
+ {
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
+ break;
+ }
+ case ATTR_HEIGHT:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_HEIGHT, attr->value());
+ else
+ removeCSSProperty(CSS_PROP_HEIGHT);
+ break;
+ case ATTR_NOSAVE:
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+HTMLTableSectionElementImpl::HTMLTableSectionElementImpl(DocumentImpl *doc,
+ ushort tagid, bool implicit)
+ : HTMLTablePartElementImpl(doc)
+{
+ _id = tagid;
+ m_implicit = implicit;
+}
+
+HTMLTableSectionElementImpl::~HTMLTableSectionElementImpl()
+{
+}
+
+NodeImpl::Id HTMLTableSectionElementImpl::id() const
+{
+ return _id;
+}
+
+// these functions are rather slow, since we need to get the row at
+// the index... but they aren't used during usual HTML parsing anyway
+HTMLElementImpl *HTMLTableSectionElementImpl::insertRow( long index, int& exceptioncode )
+{
+ HTMLTableRowElementImpl *r = 0L;
+ HTMLCollectionImpl rows(const_cast<HTMLTableSectionElementImpl*>(this), HTMLCollectionImpl::TSECTION_ROWS);
+ int numRows = rows.length();
+ //kdDebug(6030) << k_funcinfo << "index=" << index << " numRows=" << numRows << endl;
+ if ( index < -1 || index > numRows ) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
+ }
+ else
+ {
+ r = new HTMLTableRowElementImpl(docPtr());
+ if ( numRows == index || index == -1 )
+ appendChild(r, exceptioncode);
+ else {
+ NodeImpl *n;
+ if(index < 1)
+ n = firstChild();
+ else
+ n = rows.item(index);
+ insertBefore(r, n, exceptioncode );
+ }
+ }
+ return r;
+}
+
+void HTMLTableSectionElementImpl::deleteRow( long index, int &exceptioncode )
+{
+ HTMLCollectionImpl rows(const_cast<HTMLTableSectionElementImpl*>(this), HTMLCollectionImpl::TSECTION_ROWS);
+ int numRows = rows.length();
+ if ( index == -1 ) index = numRows - 1;
+ if( index >= 0 && index < numRows )
+ HTMLElementImpl::removeChild(rows.item(index), exceptioncode);
+ else
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+}
+
+
+int HTMLTableSectionElementImpl::numRows() const
+{
+ HTMLCollectionImpl rows(const_cast<HTMLTableSectionElementImpl*>(this), HTMLCollectionImpl::TSECTION_ROWS);
+ return rows.length();
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLTableRowElementImpl::id() const
+{
+ return ID_TR;
+}
+
+long HTMLTableRowElementImpl::rowIndex() const
+{
+ int rIndex = 0;
+
+ NodeImpl *table = parentNode();
+ if ( !table )
+ return -1;
+ table = table->parentNode();
+ if ( !table || table->id() != ID_TABLE )
+ return -1;
+
+ HTMLTableSectionElementImpl *head = static_cast<HTMLTableElementImpl *>(table)->tHead();
+ HTMLTableSectionElementImpl *foot = static_cast<HTMLTableElementImpl *>(table)->tFoot();
+
+ if ( head ) {
+ const NodeImpl *row = head->firstChild();
+ while ( row ) {
+ if ( row == this )
+ return rIndex;
+ rIndex++;
+ row = row->nextSibling();
+ }
+ }
+
+ NodeImpl *node = table->firstChild();
+ while ( node ) {
+ if ( node != foot && node != head && (node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY) ) {
+ HTMLTableSectionElementImpl* section = static_cast<HTMLTableSectionElementImpl *>(node);
+ const NodeImpl *row = section->firstChild();
+ while ( row ) {
+ if ( row == this )
+ return rIndex;
+ rIndex++;
+ row = row->nextSibling();
+ }
+ }
+ node = node->nextSibling();
+ }
+ const NodeImpl *row = foot->firstChild();
+ while ( row ) {
+ if ( row == this )
+ return rIndex;
+ rIndex++;
+ row = row->nextSibling();
+ }
+ // should never happen
+ return -1;
+}
+
+long HTMLTableRowElementImpl::sectionRowIndex() const
+{
+ int rIndex = 0;
+ const NodeImpl *n = this;
+ do {
+ n = n->previousSibling();
+ if (n && n->id() == ID_TR)
+ rIndex++;
+ }
+ while (n);
+
+ return rIndex;
+}
+
+HTMLElementImpl *HTMLTableRowElementImpl::insertCell( long index, int &exceptioncode )
+{
+ HTMLTableCellElementImpl *c = 0L;
+ NodeListImpl *children = childNodes();
+ int numCells = children ? children->length() : 0;
+ if ( index < -1 || index > numCells )
+ exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
+ else
+ {
+ c = new HTMLTableCellElementImpl(docPtr(), ID_TD);
+ if(numCells == index || index == -1)
+ appendChild(c, exceptioncode);
+ else {
+ NodeImpl *n;
+ if(index < 1)
+ n = firstChild();
+ else
+ n = children->item(index);
+ insertBefore(c, n, exceptioncode);
+ }
+ }
+ delete children;
+ return c;
+}
+
+void HTMLTableRowElementImpl::deleteCell( long index, int &exceptioncode )
+{
+ NodeListImpl *children = childNodes();
+ int numCells = children ? children->length() : 0;
+ if ( index == -1 ) index = numCells-1;
+ if( index >= 0 && index < numCells )
+ HTMLElementImpl::removeChild(children->item(index), exceptioncode);
+ else
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ delete children;
+}
+
+// -------------------------------------------------------------------------
+
+HTMLTableCellElementImpl::HTMLTableCellElementImpl(DocumentImpl *doc, int tag)
+ : HTMLTablePartElementImpl(doc)
+{
+ _col = -1;
+ _row = -1;
+ cSpan = rSpan = 1;
+ _id = tag;
+ rowHeight = 0;
+ m_solid = false;
+}
+
+HTMLTableCellElementImpl::~HTMLTableCellElementImpl()
+{
+}
+
+long HTMLTableCellElementImpl::cellIndex() const
+{
+ int index = 0;
+ for (const NodeImpl * node = previousSibling(); node; node = node->previousSibling()) {
+ if (node->id() == ID_TD || node->id() == ID_TH)
+ index++;
+ }
+
+ return index;
+}
+
+void HTMLTableCellElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_BORDER:
+ // euhm? not supported by other browsers as far as I can see (Dirk)
+ //addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
+ break;
+ case ATTR_ROWSPAN:
+ // ###
+ rSpan = attr->val() ? attr->val()->toInt() : 1;
+ // limit this to something not causing an overflow with short int
+ if(rSpan < 1 || rSpan > 1024) rSpan = 1;
+ break;
+ case ATTR_COLSPAN:
+ // ###
+ cSpan = attr->val() ? attr->val()->toInt() : 1;
+ // limit this to something not causing an overflow with short int
+ if(cSpan < 1 || cSpan > 1024) cSpan = 1;
+ break;
+ case ATTR_NOWRAP:
+ if (attr->val() != 0)
+ addCSSProperty(CSS_PROP_WHITE_SPACE, CSS_VAL__KHTML_NOWRAP);
+ else
+ removeCSSProperty(CSS_PROP_WHITE_SPACE);
+ break;
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength( CSS_PROP_WIDTH, attr->value() );
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_NOSAVE:
+ break;
+ default:
+ HTMLTablePartElementImpl::parseAttribute(attr);
+ }
+}
+
+void HTMLTableCellElementImpl::attach()
+{
+ HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parentNode());
+ while(p && p->id() != ID_TABLE)
+ p = static_cast<HTMLElementImpl*>(p->parentNode());
+
+ if(p) {
+ HTMLTableElementImpl* table = static_cast<HTMLTableElementImpl*>(p);
+ if (table->rules == HTMLTableElementImpl::None) {
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_NONE);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_NONE);
+ }
+ else {
+ addCSSProperty(CSS_PROP_BORDER_WIDTH, "1px");
+ int v = (table->m_solid || m_solid) ? CSS_VAL_SOLID : CSS_VAL_INSET;
+ addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, v);
+ addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v);
+ addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, v);
+ addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, v);
+
+ if (!m_solid)
+ addCSSProperty(CSS_PROP_BORDER_COLOR, CSS_VAL_INHERIT);
+ }
+ }
+
+ HTMLTablePartElementImpl::attach();
+}
+
+// -------------------------------------------------------------------------
+
+HTMLTableColElementImpl::HTMLTableColElementImpl(DocumentImpl *doc, ushort i)
+ : HTMLTablePartElementImpl(doc)
+{
+ _id = i;
+ _span = 1;
+}
+
+NodeImpl::Id HTMLTableColElementImpl::id() const
+{
+ return _id;
+}
+
+
+void HTMLTableColElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_SPAN:
+ _span = attr->val() ? attr->val()->toInt() : 1;
+ if (_span < 1) _span = 1;
+ break;
+ case ATTR_WIDTH:
+ if (!attr->value().isEmpty())
+ addCSSLength(CSS_PROP_WIDTH, attr->value(), false, true );
+ else
+ removeCSSProperty(CSS_PROP_WIDTH);
+ break;
+ case ATTR_VALIGN:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
+ break;
+ default:
+ HTMLTablePartElementImpl::parseAttribute(attr);
+ }
+
+}
+
+// -------------------------------------------------------------------------
+
+NodeImpl::Id HTMLTableCaptionElementImpl::id() const
+{
+ return ID_CAPTION;
+}
+
+
+void HTMLTableCaptionElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_ALIGN:
+ if (!attr->value().isEmpty())
+ addCSSProperty(CSS_PROP_CAPTION_SIDE, attr->value().lower());
+ else
+ removeCSSProperty(CSS_PROP_CAPTION_SIDE);
+ break;
+ default:
+ HTMLElementImpl::parseAttribute(attr);
+ }
+
+}
diff --git a/khtml/html/html_tableimpl.h b/khtml/html/html_tableimpl.h
new file mode 100644
index 000000000..76d81ce50
--- /dev/null
+++ b/khtml/html/html_tableimpl.h
@@ -0,0 +1,329 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ * (C) 1997 Torben Weis (weis@kde.org)
+ * (C) 1998 Waldo Bastian (bastian@kde.org)
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2006 Maksim Orlovich (maksim@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef HTML_TABLEIMPL_H
+#define HTML_TABLEIMPL_H
+
+#include "misc/htmltags.h"
+#include "html/html_elementimpl.h"
+
+namespace DOM {
+
+class DOMString;
+class HTMLTableElementImpl;
+class HTMLTableSectionElementImpl;
+class HTMLTableSectionElement;
+class HTMLTableRowElementImpl;
+class HTMLTableRowElement;
+class HTMLTableCellElementImpl;
+class HTMLTableCellElement;
+class HTMLTableColElementImpl;
+class HTMLTableColElement;
+class HTMLTableCaptionElementImpl;
+class HTMLTableCaptionElement;
+class HTMLElement;
+class HTMLCollection;
+
+// -------------------------------------------------------------------------
+
+class HTMLTablePartElementImpl : public HTMLElementImpl
+
+{
+public:
+ HTMLTablePartElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+ { }
+
+ virtual void parseAttribute(AttributeImpl *attr);
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTableSectionElementImpl : public HTMLTablePartElementImpl
+{
+public:
+ HTMLTableSectionElementImpl(DocumentImpl *doc, ushort tagid, bool implicit);
+
+ ~HTMLTableSectionElementImpl();
+
+ virtual Id id() const;
+
+ HTMLElementImpl *insertRow ( long index, int& exceptioncode );
+ void deleteRow ( long index, int& exceptioncode );
+
+ int numRows() const;
+
+protected:
+ ushort _id;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTableRowElementImpl : public HTMLTablePartElementImpl
+{
+public:
+ HTMLTableRowElementImpl(DocumentImpl *doc)
+ : HTMLTablePartElementImpl(doc) {}
+
+ virtual Id id() const;
+
+ long rowIndex() const;
+ long sectionRowIndex() const;
+
+ HTMLElementImpl *insertCell ( long index, int &exceptioncode );
+ void deleteCell ( long index, int &exceptioncode );
+
+protected:
+ int ncols;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTableCellElementImpl : public HTMLTablePartElementImpl
+{
+public:
+ HTMLTableCellElementImpl(DocumentImpl *doc, int tagId);
+ ~HTMLTableCellElementImpl();
+
+ long cellIndex() const;
+
+ int col() const { return _col; }
+ void setCol(int col) { _col = col; }
+ int row() const { return _row; }
+ void setRow(int r) { _row = r; }
+
+ int colSpan() const { return cSpan; }
+ int rowSpan() const { return rSpan; }
+
+ virtual Id id() const { return _id; }
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+
+protected:
+ int _row;
+ int _col;
+ int rSpan;
+ int cSpan;
+ int _id;
+ int rowHeight;
+ bool m_solid : 1;
+ bool m_nowrap : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTableColElementImpl : public HTMLTablePartElementImpl
+{
+public:
+ HTMLTableColElementImpl(DocumentImpl *doc, ushort i);
+
+ virtual Id id() const;
+
+ void setTable(HTMLTableElementImpl *t) { table = t; }
+
+ // overrides
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ int span() const { return _span; }
+
+protected:
+ // could be ID_COL or ID_COLGROUP ... The DOM is not quite clear on
+ // this, but since both elements work quite similar, we use one
+ // DOMElement for them...
+ ushort _id;
+ int _span;
+ HTMLTableElementImpl *table;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLTableCaptionElementImpl : public HTMLTablePartElementImpl
+{
+public:
+ HTMLTableCaptionElementImpl(DocumentImpl *doc)
+ : HTMLTablePartElementImpl(doc) {}
+
+ virtual Id id() const;
+ virtual void parseAttribute(AttributeImpl *attr);
+};
+
+// -------------------------------------------------------------------------
+
+/*
+This class helps memorize pointers to child objects that may be
+yanked around via the DOM. It always picks the first pointer of the
+given type.
+
+The pointer it stores can have 3 meanings:
+0 -- no child
+parent -- no idea about the state
+other -- pointer to the child
+*/
+template<typename ChildType, int ChildId> class ChildHolder
+{
+public:
+ ChildHolder():ptr(0) {}
+
+ ChildType* get(const ElementImpl* parent) const {
+ if (static_cast<const NodeImpl *>(ptr) == parent) {
+ //Do lookup.
+ ptr = 0;
+ for (NodeImpl* child = parent->firstChild(); child; child = child->nextSibling())
+ if (child->id() == ChildId) {
+ ptr = static_cast<ElementImpl*>(child);
+ break;
+ }
+ }
+ return static_cast<ChildType*>(ptr);
+ }
+
+ void childAdded(ElementImpl* parent, NodeImpl* child) {
+ if (ptr)
+ ptr = parent; //No clue now..
+ else
+ ptr = child;
+ }
+
+ void childAppended(NodeImpl* child) {
+ if (!ptr)
+ ptr = child;
+ }
+
+ void childRemoved(ElementImpl* parent, NodeImpl* child) {
+ if (child == ptr)
+ ptr = parent; //We removed what was pointing - no clue now..
+ //else things are unchanged.
+ }
+
+ void operator =(ChildType* child) {
+ ptr = child;
+ }
+private:
+ mutable NodeImpl* ptr;
+};
+
+// -------------------------------------------------------------------------
+class HTMLTableElementImpl : public HTMLElementImpl
+{
+public:
+ enum Rules {
+ None = 0x00,
+ RGroups = 0x01,
+ CGroups = 0x02,
+ Groups = 0x03,
+ Rows = 0x05,
+ Cols = 0x0a,
+ All = 0x0f
+ };
+ enum Frame {
+ Void = 0x00,
+ Above = 0x01,
+ Below = 0x02,
+ Lhs = 0x04,
+ Rhs = 0x08,
+ Hsides = 0x03,
+ Vsides = 0x0c,
+ Box = 0x0f
+ };
+
+ HTMLTableElementImpl(DocumentImpl *doc);
+ ~HTMLTableElementImpl();
+
+ virtual Id id() const;
+
+ HTMLTableCaptionElementImpl *caption() const { return tCaption.get(this); }
+ NodeImpl *setCaption( HTMLTableCaptionElementImpl * );
+
+ HTMLTableSectionElementImpl *tHead() const { return head.get(this); }
+ NodeImpl *setTHead( HTMLTableSectionElementImpl * );
+
+ HTMLTableSectionElementImpl *tFoot() const { return foot.get(this); }
+ NodeImpl *setTFoot( HTMLTableSectionElementImpl * );
+
+ NodeImpl *setTBody( HTMLTableSectionElementImpl * );
+
+ HTMLElementImpl *createTHead ( );
+ void deleteTHead ( );
+ HTMLElementImpl *createTFoot ( );
+ void deleteTFoot ( );
+ HTMLElementImpl *createCaption ( );
+ void deleteCaption ( );
+ HTMLElementImpl *insertRow ( long index, int &exceptioncode );
+ void deleteRow ( long index, int &exceptioncode );
+
+ // overrides
+ virtual NodeImpl *addChild(NodeImpl *child);
+ virtual NodeImpl *insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode );
+ virtual void replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode );
+ virtual void removeChild ( NodeImpl *oldChild, int &exceptioncode );
+ virtual NodeImpl *appendChild ( NodeImpl *newChild, int &exceptioncode );
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+ virtual void close();
+
+ /* Tries to find the section containing row number outIndex.
+ Returns whether it succeeded or not. negative outIndex values
+ are interpreted as being infinite.
+
+ On success, outSection, outIndex points to section, and index in that
+ section.
+
+ On failure, outSection points to the last section of the table, and
+ index is the offset the row would have if there was an additional section.
+ */
+ bool findRowSection(long inIndex,
+ HTMLTableSectionElementImpl*& outSection,
+ long& outIndex) const;
+protected:
+ //Actual implementations of keeping things in place.
+ void handleChildAdd ( NodeImpl *newChild );
+ void handleChildAppend( NodeImpl *newChild );
+ void handleChildRemove( NodeImpl *oldChild );
+
+ void updateFrame();
+
+ ChildHolder<HTMLTableSectionElementImpl, ID_THEAD> head;
+ ChildHolder<HTMLTableSectionElementImpl, ID_TFOOT> foot;
+ ChildHolder<HTMLTableSectionElementImpl, ID_TBODY> firstBody;
+ ChildHolder<HTMLTableCaptionElementImpl, ID_CAPTION> tCaption;
+
+ HTMLTableSectionElementImpl *tFirstBody() const { return firstBody.get(this); }
+
+ Frame frame : 4;
+ Rules rules : 4;
+
+ bool m_solid : 1;
+ uint unused : 7;
+ ushort padding : 16;
+ friend class HTMLTableCellElementImpl;
+};
+
+
+} //namespace
+
+#endif
+
diff --git a/khtml/html/htmlparser.cpp b/khtml/html/htmlparser.cpp
new file mode 100644
index 000000000..1fe79f9e0
--- /dev/null
+++ b/khtml/html/htmlparser.cpp
@@ -0,0 +1,1733 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1997 Torben Weis (weis@kde.org)
+ (C) 1999,2001 Lars Knoll (knoll@kde.org)
+ (C) 2000,2001 Dirk Mueller (mueller@kde.org)
+ (C) 2003 Apple Computer, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- HTML Parser
+// #define PARSER_DEBUG
+
+#include "dom/dom_exception.h"
+
+#include "html/html_baseimpl.h"
+#include "html/html_blockimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_elementimpl.h"
+#include "html/html_formimpl.h"
+#include "html/html_headimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_inlineimpl.h"
+#include "html/html_listimpl.h"
+#include "html/html_miscimpl.h"
+#include "html/html_tableimpl.h"
+#include "html/html_objectimpl.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_nodeimpl.h"
+#include "misc/htmlhashes.h"
+#include "html/htmltokenizer.h"
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "khtml_factory.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "css/csshelper.h"
+
+#include "rendering/render_object.h"
+
+#include "html/htmlparser.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace DOM;
+using namespace khtml;
+
+//----------------------------------------------------------------------------
+
+/**
+ * @internal
+ */
+class HTMLStackElem
+{
+public:
+ HTMLStackElem( int _id,
+ int _level,
+ DOM::NodeImpl *_node,
+ bool _inline,
+ HTMLStackElem * _next )
+ :
+ id(_id),
+ level(_level),
+ strayTableContent(false),
+ m_inline(_inline),
+ node(_node),
+ next(_next)
+ { node->ref(); }
+
+ ~HTMLStackElem()
+ { node->deref(); }
+
+ void setNode(NodeImpl* newNode)
+ {
+ newNode->ref();
+ node->deref();
+ node = newNode;
+ }
+
+ int id;
+ int level;
+ bool strayTableContent;
+ bool m_inline;
+ NodeImpl *node;
+ HTMLStackElem *next;
+};
+
+/**
+ * @internal
+ *
+ * The parser parses tokenized input into the document, building up the
+ * document tree. If the document is wellformed, parsing it is
+ * straightforward.
+ * Unfortunately, people can't write wellformed HTML documents, so the parser
+ * has to be tolerant about errors.
+ *
+ * We have to take care of the following error conditions:
+ * 1. The element being added is explicitly forbidden inside some outer tag.
+ * In this case we should close all tags up to the one, which forbids
+ * the element, and add it afterwards.
+ * 2. We are not allowed to add the element directly. It could be, that
+ * the person writing the document forgot some tag inbetween (or that the
+ * tag inbetween is optional...) This could be the case with the following
+ * tags: HTML HEAD BODY TBODY TR TD LI (did I forget any?)
+ * 3. We wan't to add a block element inside to an inline element. Close all
+ * inline elements up to the next higher block element.
+ * 4. If this doesn't help close elements, until we are allowed to add the
+ * element or ignore the tag.
+ *
+ */
+
+KHTMLParser::KHTMLParser( KHTMLView *_parent, DocumentImpl *doc)
+{
+ //kdDebug( 6035 ) << "parser constructor" << endl;
+#if SPEED_DEBUG > 0
+ qt.start();
+#endif
+
+ HTMLWidget = _parent;
+ document = doc;
+
+ blockStack = 0;
+ current = 0;
+
+ // ID_CLOSE_TAG == Num of tags
+ forbiddenTag = new ushort[ID_CLOSE_TAG+1];
+
+ reset();
+}
+
+KHTMLParser::KHTMLParser( DOM::DocumentFragmentImpl *i, DocumentImpl *doc )
+{
+ HTMLWidget = 0;
+ document = doc;
+
+ forbiddenTag = new ushort[ID_CLOSE_TAG+1];
+
+ blockStack = 0;
+ current = 0;
+
+ reset();
+
+ setCurrent(i);
+
+ inBody = true;
+}
+
+KHTMLParser::~KHTMLParser()
+{
+#if SPEED_DEBUG > 0
+ kdDebug( ) << "TIME: parsing time was = " << qt.elapsed() << endl;
+#endif
+
+ freeBlock();
+
+ if (current) current->deref();
+
+ delete [] forbiddenTag;
+ delete isindex;
+}
+
+void KHTMLParser::reset()
+{
+ setCurrent ( document );
+
+ freeBlock();
+
+ // before parsing no tags are forbidden...
+ memset(forbiddenTag, 0, (ID_CLOSE_TAG+1)*sizeof(ushort));
+
+ inBody = false;
+ haveFrameSet = false;
+ haveContent = false;
+ haveBody = false;
+ haveTitle = false;
+ inSelect = false;
+ inStrayTableContent = 0;
+ m_inline = false;
+
+ form = 0;
+ map = 0;
+ head = 0;
+ end = false;
+ isindex = 0;
+
+ discard_until = 0;
+}
+
+void KHTMLParser::parseToken(Token *t)
+{
+ if (t->tid > 2*ID_CLOSE_TAG)
+ {
+ kdDebug( 6035 ) << "Unknown tag!! tagID = " << t->tid << endl;
+ return;
+ }
+ if(discard_until) {
+ if(t->tid == discard_until)
+ discard_until = 0;
+
+ // do not skip </iframe>
+ if ( discard_until || current->id() + ID_CLOSE_TAG != t->tid )
+ return;
+ }
+
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "\n\n==> parser: processing token " << getTagName(t->tid) << "(" << t->tid << ")"
+ << " current = " << getTagName(current->id()) << "(" << current->id() << ")" << endl;
+ kdDebug(6035) << "inline=" << m_inline << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << " haveContent=" << haveContent << endl;
+#endif
+
+ // holy shit. apparently some sites use </br> instead of <br>
+ // be compatible with IE and NS
+ if(t->tid == ID_BR+ID_CLOSE_TAG && document->inCompatMode())
+ t->tid -= ID_CLOSE_TAG;
+
+ if(t->tid > ID_CLOSE_TAG)
+ {
+ processCloseTag(t);
+ return;
+ }
+
+ // ignore spaces, if we're not inside a paragraph or other inline code
+ if( t->tid == ID_TEXT && t->text ) {
+ if(inBody && !skipMode() &&
+ current->id() != ID_STYLE && current->id() != ID_TITLE &&
+ current->id() != ID_SCRIPT &&
+ !t->text->containsOnlyWhitespace()) haveContent = true;
+#ifdef PARSER_DEBUG
+ kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl;
+#endif
+ }
+
+ NodeImpl *n = getElement(t);
+ // just to be sure, and to catch currently unimplemented stuff
+ if(!n)
+ return;
+
+ // set attributes
+ if(n->isElementNode() && t->tid != ID_ISINDEX)
+ {
+ ElementImpl *e = static_cast<ElementImpl *>(n);
+ e->setAttributeMap(t->attrs);
+
+ // take care of optional close tags
+ if(endTag[e->id()] == DOM::OPTIONAL)
+ popBlock(t->tid);
+ }
+
+ // if this tag is forbidden inside the current context, pop
+ // blocks until we are allowed to add it...
+ while(blockStack && forbiddenTag[t->tid]) {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "t->id: " << t->tid << " is forbidden :-( " << endl;
+#endif
+ popOneBlock();
+ }
+
+ // sometimes flat doesn't make sense
+ switch(t->tid) {
+ case ID_SELECT:
+ case ID_OPTION:
+ t->flat = false;
+ }
+
+ // the tokenizer needs the feedback for space discarding
+ if ( tagPriority[t->tid] == 0 )
+ t->flat = true;
+
+ if ( !insertNode(n, t->flat) ) {
+ // we couldn't insert the node...
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "insertNode failed current=" << current->id() << ", new=" << n->id() << "!" << endl;
+#endif
+ if (map == n)
+ {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << " --> resetting map!" << endl;
+#endif
+ map = 0;
+ }
+ if (form == n)
+ {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << " --> resetting form!" << endl;
+#endif
+ form = 0;
+ }
+ delete n;
+ }
+}
+
+static bool isTableRelatedTag(int id)
+{
+ return (id == ID_TR || id == ID_TD || id == ID_TABLE || id == ID_TBODY || id == ID_TFOOT || id == ID_THEAD ||
+ id == ID_TH);
+}
+
+bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
+{
+ int id = n->id();
+
+ // let's be stupid and just try to insert it.
+ // this should work if the document is wellformed
+#ifdef PARSER_DEBUG
+ NodeImpl *tmp = current;
+#endif
+ NodeImpl *newNode = current->addChild(n);
+ if ( newNode ) {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "added " << n->nodeName().string() << " to " << tmp->nodeName().string() << ", new current=" << newNode->nodeName().string() << endl;
+#endif
+ // We allow TABLE > FORM in dtd.cpp, but do not allow the form have children in this case
+ if (current->id() == ID_TABLE && id == ID_FORM) {
+ flat = true;
+ static_cast<HTMLFormElementImpl*>(n)->setMalformed(true);
+ }
+
+ // don't push elements without end tag on the stack
+ if(tagPriority[id] != 0 && !flat) {
+#if SPEED_DEBUG < 2
+ if(!n->attached() && HTMLWidget )
+ n->attach();
+#endif
+ if(n->isInline()) m_inline = true;
+ pushBlock(id, tagPriority[id]);
+ setCurrent( newNode );
+ } else {
+#if SPEED_DEBUG < 2
+ if(!n->attached() && HTMLWidget)
+ n->attach();
+ if (n->maintainsState()) {
+ document->registerMaintainsState(n);
+ QString state(document->nextState());
+ if (!state.isNull()) n->restoreState(state);
+ }
+ n->close();
+#endif
+ if(n->isInline()) m_inline = true;
+ }
+
+
+#if SPEED_DEBUG < 1
+ if(tagPriority[id] == 0 && n->renderer())
+ n->renderer()->calcMinMaxWidth();
+#endif
+ return true;
+ } else {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "ADDING NODE FAILED!!!! current = " << current->nodeName().string() << ", new = " << n->nodeName().string() << endl;
+#endif
+ // error handling...
+ HTMLElementImpl *e;
+ bool handled = false;
+
+ // first switch on current element for elements with optional end-tag and inline-only content
+ switch(current->id())
+ {
+ case ID_P:
+ case ID_DT:
+ if(!n->isInline())
+ {
+ popBlock(current->id());
+ return insertNode(n);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // switch according to the element to insert
+ switch(id)
+ {
+ case ID_TR:
+ case ID_TH:
+ case ID_TD:
+ if (inStrayTableContent && !isTableRelatedTag(current->id())) {
+ // pop out to the nearest enclosing table-related tag.
+ while (blockStack && !isTableRelatedTag(current->id()))
+ popOneBlock();
+ return insertNode(n);
+ }
+ break;
+ case ID_COMMENT:
+ break;
+ case ID_HEAD:
+ // ### allow not having <HTML> in at all, as per HTML spec
+ if (!current->isDocumentNode() && current->id() != ID_HTML )
+ return false;
+ break;
+ case ID_META:
+ case ID_LINK:
+ case ID_ISINDEX:
+ case ID_BASE:
+ if( !head )
+ createHead();
+ if( head ) {
+ if ( head->addChild(n) ) {
+#if SPEED_DEBUG < 2
+ if(!n->attached() && HTMLWidget)
+ n->attach();
+#endif
+ }
+
+ return true;
+ }
+
+ break;
+ case ID_HTML:
+ if (!current->isDocumentNode() ) {
+ if ( doc()->firstChild()->id() == ID_HTML) {
+ // we have another <HTML> element.... apply attributes to existing one
+ // make sure we don't overwrite already existing attributes
+ NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
+ NamedAttrMapImpl *bmap = static_cast<ElementImpl*>(doc()->firstChild())->attributes(false);
+ bool changed = false;
+ for (unsigned long l = 0; map && l < map->length(); ++l) {
+ NodeImpl::Id attrId = map->idAt(l);
+ DOMStringImpl *attrValue = map->valueAt(l);
+ changed = !bmap->getValue(attrId);
+ bmap->setValue(attrId,attrValue);
+ }
+ if ( changed )
+ doc()->recalcStyle( NodeImpl::Inherit );
+ }
+ return false;
+ }
+ break;
+ case ID_TITLE:
+ case ID_STYLE:
+ if ( !head )
+ createHead();
+ if ( head ) {
+ DOM::NodeImpl *newNode = head->addChild(n);
+ if ( newNode ) {
+ pushBlock(id, tagPriority[id]);
+ setCurrent ( newNode );
+#if SPEED_DEBUG < 2
+ if(!n->attached() && HTMLWidget)
+ n->attach();
+#endif
+ } else {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "adding style before to body failed!!!!" << endl;
+#endif
+ discard_until = ID_STYLE + ID_CLOSE_TAG;
+ return false;
+ }
+ return true;
+ } else if(inBody) {
+ discard_until = id + ID_CLOSE_TAG;
+ return false;
+ }
+ break;
+ case ID_SCRIPT:
+ // if we failed to insert it, go into skip mode
+ discard_until = id + ID_CLOSE_TAG;
+ break;
+ case ID_BODY:
+ if(inBody && doc()->body()) {
+ // we have another <BODY> element.... apply attributes to existing one
+ // make sure we don't overwrite already existing attributes
+ // some sites use <body bgcolor=rightcolor>...<body bgcolor=wrongcolor>
+ NamedAttrMapImpl *map = static_cast<ElementImpl*>(n)->attributes(true);
+ NamedAttrMapImpl *bmap = doc()->body()->attributes(false);
+ bool changed = false;
+ for (unsigned long l = 0; map && l < map->length(); ++l) {
+ NodeImpl::Id attrId = map->idAt(l);
+ DOMStringImpl *attrValue = map->valueAt(l);
+ if ( !bmap->getValue(attrId) ) {
+ bmap->setValue(attrId,attrValue);
+ changed = true;
+ }
+ }
+ if ( changed )
+ doc()->recalcStyle( NodeImpl::Inherit );
+ } else if ( current->isDocumentNode() )
+ break;
+ return false;
+ break;
+
+ // the following is a hack to move non rendered elements
+ // outside of tables.
+ // needed for broken constructs like <table><form ...><tr>....
+ case ID_INPUT:
+ {
+ ElementImpl *e = static_cast<ElementImpl *>(n);
+ DOMString type = e->getAttribute(ATTR_TYPE);
+
+ if ( strcasecmp( type, "hidden" ) != 0 )
+ break;
+ // Fall through!
+ }
+ case ID_TEXT:
+ {
+ // Don't try to fit random white-space anywhere
+ TextImpl *t = static_cast<TextImpl *>(n);
+ if (t->containsOnlyWhitespace())
+ return false;
+ // ignore text inside the following elements.
+ switch(current->id())
+ {
+ case ID_SELECT:
+ return false;
+ default:
+ ;
+ // fall through!!
+ };
+ break;
+ }
+ case ID_DL:
+ popBlock( ID_DT );
+ if ( current->id() == ID_DL ) {
+ e = new HTMLGenericElementImpl( document, ID_DD );
+ insertNode( e );
+ handled = true;
+ }
+ break;
+ case ID_DT:
+ e = new HTMLDListElementImpl(document);
+ if ( insertNode(e) ) {
+ insertNode(n);
+ return true;
+ }
+ break;
+ case ID_AREA:
+ {
+ if(map)
+ {
+ map->addChild(n);
+#if SPEED_DEBUG < 2
+ if(!n->attached() && HTMLWidget)
+ n->attach();
+#endif
+ handled = true;
+ return true;
+ }
+ else
+ return false;
+ }
+ case ID_CAPTION: {
+ switch (current->id()) {
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT:
+ case ID_TR:
+ case ID_TH:
+ case ID_TD: {
+ NodeImpl* tsection = current;
+ if (current->id() == ID_TR)
+ tsection = current->parent();
+ else if (current->id() == ID_TD || current->id() == ID_TH)
+ tsection = current->parent()->parent();
+ NodeImpl* table = tsection->parent();
+ int exceptioncode = 0;
+ table->insertBefore(n, tsection, exceptioncode);
+ pushBlock(id, tagPriority[id]);
+ setCurrent(n);
+ inStrayTableContent++;
+ blockStack->strayTableContent = true;
+ return true;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT:
+ case ID_COLGROUP: {
+ if (isTableRelatedTag(current->id())) {
+ while (blockStack && current->id() != ID_TABLE && isTableRelatedTag(current->id()))
+ popOneBlock();
+ return insertNode(n);
+ }
+ }
+ default:
+ break;
+ }
+
+ // switch on the currently active element
+ switch(current->id())
+ {
+ case ID_HTML:
+ switch(id)
+ {
+ case ID_SCRIPT:
+ case ID_STYLE:
+ case ID_META:
+ case ID_LINK:
+ case ID_OBJECT:
+ case ID_EMBED:
+ case ID_TITLE:
+ case ID_ISINDEX:
+ case ID_BASE:
+ if(!head) {
+ head = new HTMLHeadElementImpl(document);
+ e = head;
+ insertNode(e);
+ handled = true;
+ }
+ break;
+ case ID_TEXT: {
+ TextImpl *t = static_cast<TextImpl *>(n);
+ if (t->containsOnlyWhitespace())
+ return false;
+ /* Fall through to default */
+ }
+ default:
+ if ( haveFrameSet ) break;
+ e = new HTMLBodyElementImpl(document);
+ startBody();
+ insertNode(e);
+ handled = true;
+ break;
+ }
+ break;
+ case ID_HEAD:
+ // we can get here only if the element is not allowed in head.
+ if (id == ID_HTML)
+ return false;
+ else {
+ // This means the body starts here...
+ if ( haveFrameSet ) break;
+ popBlock(ID_HEAD);
+ e = new HTMLBodyElementImpl(document);
+ startBody();
+ insertNode(e);
+ handled = true;
+ }
+ break;
+ case ID_BODY:
+ break;
+ case ID_CAPTION:
+ // Illegal content in a caption. Close the caption and try again.
+ popBlock(ID_CAPTION);
+ switch( id ) {
+ case ID_THEAD:
+ case ID_TFOOT:
+ case ID_TBODY:
+ case ID_TR:
+ case ID_TD:
+ case ID_TH:
+ return insertNode(n, flat);
+ }
+ break;
+ case ID_TABLE:
+ case ID_THEAD:
+ case ID_TFOOT:
+ case ID_TBODY:
+ case ID_TR:
+ switch(id)
+ {
+ case ID_TABLE:
+ popBlock(ID_TABLE); // end the table
+ handled = checkChild( current->id(), id, !doc()->inCompatMode());
+ break;
+ default:
+ {
+ NodeImpl *node = current;
+ NodeImpl *parent = node->parentNode();
+ // A script may have removed the current node's parent from the DOM
+ // http://bugzilla.opendarwin.org/show_bug.cgi?id=7137
+ // FIXME: we should do real recovery here and re-parent with the correct node.
+ if (!parent)
+ return false;
+ NodeImpl *parentparent = parent->parentNode();
+
+ if (n->isTextNode() ||
+ ( node->id() == ID_TR &&
+ ( parent->id() == ID_THEAD ||
+ parent->id() == ID_TBODY ||
+ parent->id() == ID_TFOOT ) && parentparent->id() == ID_TABLE ) ||
+ ( !checkChild( ID_TR, id ) && ( node->id() == ID_THEAD || node->id() == ID_TBODY || node->id() == ID_TFOOT ) &&
+ parent->id() == ID_TABLE ) )
+ {
+ node = (node->id() == ID_TABLE) ? node :
+ ((node->id() == ID_TR ) ? parentparent : parent);
+ NodeImpl *parent = node->parentNode();
+ if (!parent)
+ return false;
+ int exceptioncode = 0;
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "calling insertBefore(" << n->nodeName().string() << "," << node->nodeName().string() << ")" << endl;
+#endif
+ parent->insertBefore(n, node, exceptioncode);
+ if (exceptioncode) {
+#ifndef PARSER_DEBUG
+ if (!n->isTextNode())
+#endif
+ kdDebug(6035) << "adding content before table failed.." << endl;
+ break;
+ }
+ if ( n->isElementNode() && tagPriority[id] != 0 &&
+ !flat && endTag[id] != DOM::FORBIDDEN ) {
+
+ pushBlock(id, tagPriority[id]);
+ setCurrent ( n );
+ inStrayTableContent++;
+ blockStack->strayTableContent = true;
+ }
+ return true;
+ }
+
+ if ( current->id() == ID_TR )
+ e = new HTMLTableCellElementImpl(document, ID_TD);
+ else if ( current->id() == ID_TABLE )
+ e = new HTMLTableSectionElementImpl( document, ID_TBODY, true /* implicit */ );
+ else
+ e = new HTMLTableRowElementImpl( document );
+
+ insertNode(e);
+ handled = true;
+ break;
+ } // end default
+ } // end switch
+ break;
+ case ID_OBJECT:
+ discard_until = id + ID_CLOSE_TAG;
+ return false;
+ case ID_UL:
+ case ID_OL:
+ case ID_DIR:
+ case ID_MENU:
+ e = new HTMLLIElementImpl(document);
+ e->addCSSProperty(CSS_PROP_LIST_STYLE_TYPE, CSS_VAL_NONE);
+ insertNode(e);
+ handled = true;
+ break;
+ case ID_DL:
+ popBlock(ID_DL);
+ handled = true;
+ break;
+ case ID_DT:
+ popBlock(ID_DT);
+ handled = true;
+ break;
+ case ID_FORM:
+ popBlock(ID_FORM);
+ handled = true;
+ break;
+ case ID_SELECT:
+ if( n->isInline() )
+ return false;
+ break;
+ case ID_P:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ if(!n->isInline())
+ {
+ popBlock(current->id());
+ handled = true;
+ }
+ break;
+ case ID_OPTION:
+ case ID_OPTGROUP:
+ if (id == ID_OPTGROUP)
+ {
+ popBlock(current->id());
+ handled = true;
+ }
+ else if(id == ID_SELECT)
+ {
+ // IE treats a nested select as </select>. Let's do the same
+ popBlock( ID_SELECT );
+ break;
+ }
+ break;
+ // head elements in the body should be ignored.
+
+ case ID_ADDRESS:
+ case ID_COLGROUP:
+ case ID_FONT:
+ popBlock(current->id());
+ handled = true;
+ break;
+ default:
+ if(current->isDocumentNode())
+ {
+ if(current->firstChild() == 0) {
+ e = new HTMLHtmlElementImpl(document);
+ insertNode(e);
+ handled = true;
+ }
+ }
+ else if(current->isInline())
+ {
+ popInlineBlocks();
+ handled = true;
+ }
+ }
+
+ // if we couldn't handle the error, just rethrow the exception...
+ if(!handled)
+ {
+ //kdDebug( 6035 ) << "Exception handler failed in HTMLPArser::insertNode()" << endl;
+ return false;
+ }
+
+ return insertNode(n);
+ }
+}
+
+
+NodeImpl *KHTMLParser::getElement(Token* t)
+{
+ NodeImpl *n = 0;
+
+ switch(t->tid)
+ {
+ case ID_HTML:
+ n = new HTMLHtmlElementImpl(document);
+ break;
+ case ID_HEAD:
+ if(!head && current->id() == ID_HTML) {
+ head = new HTMLHeadElementImpl(document);
+ n = head;
+ }
+ break;
+ case ID_BODY:
+ // body no longer allowed if we have a frameset
+ if(haveFrameSet) break;
+ popBlock(ID_HEAD);
+ n = new HTMLBodyElementImpl(document);
+ haveBody = true;
+ startBody();
+ break;
+
+// head elements
+ case ID_BASE:
+ n = new HTMLBaseElementImpl(document);
+ break;
+ case ID_LINK:
+ n = new HTMLLinkElementImpl(document);
+ break;
+ case ID_META:
+ n = new HTMLMetaElementImpl(document);
+ break;
+ case ID_STYLE:
+ n = new HTMLStyleElementImpl(document);
+ break;
+ case ID_TITLE:
+ // only one non-empty <title> allowed
+ if (haveTitle) {
+ discard_until = ID_TITLE+ID_CLOSE_TAG;
+ break;
+ }
+ n = new HTMLTitleElementImpl(document);
+ // we'll set haveTitle when closing the tag
+ break;
+
+// frames
+ case ID_FRAME:
+ n = new HTMLFrameElementImpl(document);
+ break;
+ case ID_FRAMESET:
+ popBlock(ID_HEAD);
+ if ( inBody && !haveFrameSet && !haveContent && !haveBody) {
+ popBlock( ID_BODY );
+ // ### actually for IE document.body returns the now hidden "body" element
+ // we can't implement that behavior now because it could cause too many
+ // regressions and the headaches are not worth the work as long as there is
+ // no site actually relying on that detail (Dirk)
+ if (static_cast<HTMLDocumentImpl*>(document)->body())
+ static_cast<HTMLDocumentImpl*>(document)->body()
+ ->addCSSProperty(CSS_PROP_DISPLAY, CSS_VAL_NONE);
+ inBody = false;
+ }
+ if ( (haveBody || haveContent || haveFrameSet) && current->id() == ID_HTML)
+ break;
+ n = new HTMLFrameSetElementImpl(document);
+ haveFrameSet = true;
+ startBody();
+ break;
+ // a bit a special case, since the frame is inlined...
+ case ID_IFRAME:
+ n = new HTMLIFrameElementImpl(document);
+ if (!t->flat) discard_until = ID_IFRAME+ID_CLOSE_TAG;
+ break;
+
+// form elements
+ case ID_FORM:
+ // thou shall not nest <form> - NS/IE quirk
+ if (form) break;
+ n = form = new HTMLFormElementImpl(document, false);
+ break;
+ case ID_BUTTON:
+ n = new HTMLButtonElementImpl(document, form);
+ break;
+ case ID_FIELDSET:
+ n = new HTMLFieldSetElementImpl(document, form);
+ break;
+ case ID_INPUT:
+ if ( t->attrs &&
+ KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled() &&
+ KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() &&
+ !strcasecmp( t->attrs->getValue( ATTR_TYPE ), "image" ) )
+ {
+ if (KHTMLFactory::defaultHTMLSettings()->isAdFiltered( doc()->completeURL( khtml::parseURL(t->attrs->getValue(ATTR_SRC)).string() ) ))
+ return 0;
+ }
+ n = new HTMLInputElementImpl(document, form);
+ break;
+ case ID_ISINDEX:
+ n = handleIsindex(t);
+ if( !inBody ) {
+ isindex = n;
+ n = 0;
+ } else
+ t->flat = true;
+ break;
+ case ID_KEYGEN:
+ n = new HTMLKeygenElementImpl(document, form);
+ break;
+ case ID_LABEL:
+ n = new HTMLLabelElementImpl(document);
+ break;
+ case ID_LEGEND:
+ n = new HTMLLegendElementImpl(document, form);
+ break;
+ case ID_OPTGROUP:
+ n = new HTMLOptGroupElementImpl(document, form);
+ break;
+ case ID_OPTION:
+ n = new HTMLOptionElementImpl(document, form);
+ break;
+ case ID_SELECT:
+ inSelect = true;
+ n = new HTMLSelectElementImpl(document, form);
+ break;
+ case ID_TEXTAREA:
+ n = new HTMLTextAreaElementImpl(document, form);
+ break;
+
+// lists
+ case ID_DL:
+ n = new HTMLDListElementImpl(document);
+ break;
+ case ID_DD:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ popBlock(ID_DT);
+ popBlock(ID_DD);
+ break;
+ case ID_DT:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ popBlock(ID_DD);
+ popBlock(ID_DT);
+ break;
+ case ID_UL:
+ {
+ n = new HTMLUListElementImpl(document);
+ break;
+ }
+ case ID_OL:
+ {
+ n = new HTMLOListElementImpl(document);
+ break;
+ }
+ case ID_DIR:
+ n = new HTMLDirectoryElementImpl(document);
+ break;
+ case ID_MENU:
+ n = new HTMLMenuElementImpl(document);
+ break;
+ case ID_LI:
+ popBlock(ID_LI);
+ n = new HTMLLIElementImpl(document);
+ break;
+// formatting elements (block)
+ case ID_BLOCKQUOTE:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+ case ID_LAYER:
+ case ID_ILAYER:
+ n = new HTMLLayerElementImpl(document, t->tid);
+ break;
+ case ID_P:
+ case ID_DIV:
+ n = new HTMLDivElementImpl(document, t->tid);
+ break;
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+ case ID_HR:
+ n = new HTMLHRElementImpl(document);
+ break;
+ case ID_PRE:
+ case ID_XMP:
+ case ID_PLAINTEXT:
+ n = new HTMLPreElementImpl(document, t->tid);
+ break;
+
+// font stuff
+ case ID_BASEFONT:
+ n = new HTMLBaseFontElementImpl(document);
+ break;
+ case ID_FONT:
+ n = new HTMLFontElementImpl(document);
+ break;
+
+// ins/del
+ case ID_DEL:
+ case ID_INS:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+
+// anchor
+ case ID_A:
+ popBlock(ID_A);
+
+ n = new HTMLAnchorElementImpl(document);
+ break;
+
+// images
+ case ID_IMG:
+ if (t->attrs&&
+ KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled()&&
+ KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled())
+ {
+ QString url = doc()->completeURL( khtml::parseURL(t->attrs->getValue(ATTR_SRC)).string() );
+ if (KHTMLFactory::defaultHTMLSettings()->isAdFiltered(url))
+ return 0;
+ }
+ n = new HTMLImageElementImpl(document, form);
+ break;
+
+ case ID_MAP:
+ map = new HTMLMapElementImpl(document);
+ n = map;
+ break;
+ case ID_AREA:
+ n = new HTMLAreaElementImpl(document);
+ break;
+
+// objects, applets and scripts
+ case ID_APPLET:
+ n = new HTMLAppletElementImpl(document);
+ break;
+ case ID_EMBED:
+ n = new HTMLEmbedElementImpl(document);
+ break;
+ case ID_OBJECT:
+ n = new HTMLObjectElementImpl(document);
+ break;
+ case ID_PARAM:
+ n = new HTMLParamElementImpl(document);
+ break;
+ case ID_SCRIPT:
+ {
+ HTMLScriptElementImpl *scriptElement = new HTMLScriptElementImpl(document);
+ scriptElement->setCreatedByParser(true);
+ n = scriptElement;
+ break;
+ }
+
+// tables
+ case ID_TABLE:
+ n = new HTMLTableElementImpl(document);
+ break;
+ case ID_CAPTION:
+ n = new HTMLTableCaptionElementImpl(document);
+ break;
+ case ID_COLGROUP:
+ case ID_COL:
+ n = new HTMLTableColElementImpl(document, t->tid);
+ break;
+ case ID_TR:
+ popBlock(ID_TR);
+ n = new HTMLTableRowElementImpl(document);
+ break;
+ case ID_TD:
+ case ID_TH:
+ popBlock(ID_TH);
+ popBlock(ID_TD);
+ n = new HTMLTableCellElementImpl(document, t->tid);
+ break;
+ case ID_TBODY:
+ case ID_THEAD:
+ case ID_TFOOT:
+ popBlock( ID_THEAD );
+ popBlock( ID_TBODY );
+ popBlock( ID_TFOOT );
+ n = new HTMLTableSectionElementImpl(document, t->tid, false);
+ break;
+
+// inline elements
+ case ID_BR:
+ n = new HTMLBRElementImpl(document);
+ break;
+ case ID_Q:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+
+// elements with no special representation in the DOM
+
+// block:
+ case ID_ADDRESS:
+ case ID_CENTER:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+// inline
+ // %fontstyle
+ case ID_TT:
+ case ID_U:
+ case ID_B:
+ case ID_I:
+ case ID_S:
+ case ID_STRIKE:
+ case ID_BIG:
+ case ID_SMALL:
+
+ // %phrase
+ case ID_EM:
+ case ID_STRONG:
+ case ID_DFN:
+ case ID_CODE:
+ case ID_SAMP:
+ case ID_KBD:
+ case ID_VAR:
+ case ID_CITE:
+ case ID_ABBR:
+ case ID_ACRONYM:
+
+ // %special
+ case ID_SUB:
+ case ID_SUP:
+ case ID_SPAN:
+ case ID_WBR:
+ case ID_NOBR:
+ if ( t->tid == ID_NOBR || t->tid == ID_WBR )
+ popBlock( t->tid );
+ case ID_BDO:
+ n = new HTMLGenericElementImpl(document, t->tid);
+ break;
+
+ // these are special, and normally not rendered
+ case ID_NOEMBED:
+ if (!t->flat) {
+ n = new HTMLGenericElementImpl(document, t->tid);
+ discard_until = ID_NOEMBED + ID_CLOSE_TAG;
+ }
+ return n;
+ case ID_NOFRAMES:
+ if (!t->flat) {
+ n = new HTMLGenericElementImpl(document, t->tid);
+ discard_until = ID_NOFRAMES + ID_CLOSE_TAG;
+ }
+ return n;
+ case ID_NOSCRIPT:
+ if (!t->flat) {
+ n = new HTMLGenericElementImpl(document, t->tid);
+ if(HTMLWidget && HTMLWidget->part()->jScriptEnabled())
+ discard_until = ID_NOSCRIPT + ID_CLOSE_TAG;
+ }
+ return n;
+ case ID_NOLAYER:
+// discard_until = ID_NOLAYER + ID_CLOSE_TAG;
+ return 0;
+ break;
+ case ID_MARQUEE:
+ n = new HTMLMarqueeElementImpl(document);
+ break;
+// text
+ case ID_TEXT:
+// kdDebug(6035) << "ID_TEXT: \"" << DOMString(t->text).string() << "\"" << endl;
+ n = new TextImpl(document, t->text);
+ break;
+ case ID_COMMENT:
+#ifdef COMMENTS_IN_DOM
+ n = new CommentImpl(document, t->text);
+#endif
+ break;
+ default:
+ kdDebug( 6035 ) << "Unknown tag " << t->tid << "!" << endl;
+ }
+ return n;
+}
+
+void KHTMLParser::processCloseTag(Token *t)
+{
+ // support for really broken html. Can't believe I'm supporting such crap (lars)
+ switch(t->tid)
+ {
+ case ID_HTML+ID_CLOSE_TAG:
+ case ID_BODY+ID_CLOSE_TAG:
+ // we never trust those close tags, since stupid webpages close
+ // them prematurely
+ return;
+ case ID_FORM+ID_CLOSE_TAG:
+ form = 0;
+ // this one is to get the right style on the body element
+ break;
+ case ID_MAP+ID_CLOSE_TAG:
+ map = 0;
+ break;
+ case ID_SELECT+ID_CLOSE_TAG:
+ inSelect = false;
+ break;
+ case ID_TITLE+ID_CLOSE_TAG:
+ // Set haveTitle only if <title> isn't empty
+ if ( current->firstChild() )
+ haveTitle = true;
+ break;
+ default:
+ break;
+ }
+
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "added the following children to " << current->nodeName().string() << endl;
+ NodeImpl *child = current->firstChild();
+ while(child != 0)
+ {
+ kdDebug( 6035 ) << " " << child->nodeName().string() << endl;
+ child = child->nextSibling();
+ }
+#endif
+ popBlock(t->tid-ID_CLOSE_TAG);
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "closeTag --> current = " << current->nodeName().string() << endl;
+#endif
+}
+
+bool KHTMLParser::isResidualStyleTag(int _id)
+{
+ switch (_id) {
+ case ID_A:
+ case ID_FONT:
+ case ID_TT:
+ case ID_U:
+ case ID_B:
+ case ID_I:
+ case ID_S:
+ case ID_STRIKE:
+ case ID_BIG:
+ case ID_SMALL:
+ case ID_EM:
+ case ID_STRONG:
+ case ID_DFN:
+ case ID_CODE:
+ case ID_SAMP:
+ case ID_KBD:
+ case ID_VAR:
+ case ID_DEL:
+ case ID_INS:
+ case ID_WBR:
+ case ID_NOBR:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool KHTMLParser::isAffectedByResidualStyle(int _id)
+{
+ if (isResidualStyleTag(_id))
+ return true;
+
+ switch (_id) {
+ case ID_P:
+ case ID_DIV:
+ case ID_BLOCKQUOTE:
+ case ID_ADDRESS:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ case ID_CENTER:
+ case ID_UL:
+ case ID_OL:
+ case ID_LI:
+ case ID_DL:
+ case ID_DT:
+ case ID_DD:
+ case ID_PRE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void KHTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
+{
+ // Find the element that crosses over to a higher level.
+ // ### For now, if there is more than one, we will only make sure we close the residual style.
+ int exceptionCode = 0;
+ HTMLStackElem* curr = blockStack;
+ HTMLStackElem* maxElem = 0;
+ HTMLStackElem* endElem = 0;
+ HTMLStackElem* prev = 0;
+ HTMLStackElem* prevMaxElem = 0;
+ bool advancedResidual = false; // ### if set we only close the residual style
+ while (curr && curr != elem) {
+ if (curr->level > elem->level) {
+ if (!isAffectedByResidualStyle(curr->id)) return;
+ if (maxElem) advancedResidual = true;
+ else
+ endElem = curr;
+ maxElem = curr;
+ prevMaxElem = prev;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (!curr || !maxElem ) return;
+
+ NodeImpl* residualElem = prev->node;
+ NodeImpl* blockElem = prevMaxElem ? prevMaxElem->node : current;
+ NodeImpl* parentElem = elem->node;
+
+ // Check to see if the reparenting that is going to occur is allowed according to the DOM.
+ // FIXME: We should either always allow it or perform an additional fixup instead of
+ // just bailing here.
+ // Example: <p><font><center>blah</font></center></p> isn't doing a fixup right now.
+ if (!parentElem->childAllowed(blockElem))
+ return;
+
+ if (maxElem->node->parentNode() != elem->node && !advancedResidual) {
+ // Walk the stack and remove any elements that aren't residual style tags. These
+ // are basically just being closed up. Example:
+ // <font><span>Moo<p>Goo</font></p>.
+ // In the above example, the <span> doesn't need to be reopened. It can just close.
+ HTMLStackElem* currElem = maxElem->next;
+ HTMLStackElem* prevElem = maxElem;
+ while (currElem != elem) {
+ HTMLStackElem* nextElem = currElem->next;
+ if (!isResidualStyleTag(currElem->id)) {
+ prevElem->next = nextElem;
+ prevElem->setNode(currElem->node);
+ delete currElem;
+ }
+ else
+ prevElem = currElem;
+ currElem = nextElem;
+ }
+
+ // We have to reopen residual tags in between maxElem and elem. An example of this case s:
+ // <font><i>Moo<p>Foo</font>.
+ // In this case, we need to transform the part before the <p> into:
+ // <font><i>Moo</i></font><i>
+ // so that the <i> will remain open. This involves the modification of elements
+ // in the block stack.
+ // This will also affect how we ultimately reparent the block, since we want it to end up
+ // under the reopened residual tags (e.g., the <i> in the above example.)
+ NodeImpl* prevNode = 0;
+ NodeImpl* currNode = 0;
+ currElem = maxElem;
+ while (currElem->node != residualElem) {
+ if (isResidualStyleTag(currElem->node->id())) {
+ // Create a clone of this element.
+ currNode = currElem->node->cloneNode(false);
+ currElem->node->close();
+ removeForbidden(currElem->id, forbiddenTag);
+
+ // Change the stack element's node to point to the clone.
+ currElem->setNode(currNode);
+
+ // Attach the previous node as a child of this new node.
+ if (prevNode)
+ currNode->appendChild(prevNode, exceptionCode);
+ else // The new parent for the block element is going to be the innermost clone.
+ parentElem = currNode;
+
+ prevNode = currNode;
+ }
+
+ currElem = currElem->next;
+ }
+
+ // Now append the chain of new residual style elements if one exists.
+ if (prevNode)
+ elem->node->appendChild(prevNode, exceptionCode);
+ }
+
+ // We need to make a clone of |residualElem| and place it just inside |blockElem|.
+ // All content of |blockElem| is reparented to be under this clone. We then
+ // reparent |blockElem| using real DOM calls so that attachment/detachment will
+ // be performed to fix up the rendering tree.
+ // So for this example: <b>...<p>Foo</b>Goo</p>
+ // The end result will be: <b>...</b><p><b>Foo</b>Goo</p>
+ //
+ // Step 1: Remove |blockElem| from its parent, doing a batch detach of all the kids.
+ SharedPtr<NodeImpl> guard(blockElem);
+ blockElem->parentNode()->removeChild(blockElem, exceptionCode);
+
+ if (!advancedResidual) {
+ // Step 2: Clone |residualElem|.
+ NodeImpl* newNode = residualElem->cloneNode(false); // Shallow clone. We don't pick up the same kids.
+
+ // Step 3: Place |blockElem|'s children under |newNode|. Remove all of the children of |blockElem|
+ // before we've put |newElem| into the document. That way we'll only do one attachment of all
+ // the new content (instead of a bunch of individual attachments).
+ NodeImpl* currNode = blockElem->firstChild();
+ while (currNode) {
+ NodeImpl* nextNode = currNode->nextSibling();
+ SharedPtr<NodeImpl> guard(currNode); //Protect from deletion while moving
+ blockElem->removeChild(currNode, exceptionCode);
+ newNode->appendChild(currNode, exceptionCode);
+ currNode = nextNode;
+
+ // TODO - To be replaced.
+ // Re-register form elements with currently active form, step 1 will have removed them
+ if (form && currNode && currNode->isGenericFormElement())
+ {
+ HTMLGenericFormElementImpl *e = static_cast<HTMLGenericFormElementImpl *>(currNode);
+ form->registerFormElement(e);
+ }
+ }
+
+ // Step 4: Place |newNode| under |blockElem|. |blockElem| is still out of the document, so no
+ // attachment can occur yet.
+ blockElem->appendChild(newNode, exceptionCode);
+ }
+
+ // Step 5: Reparent |blockElem|. Now the full attachment of the fixed up tree takes place.
+ parentElem->appendChild(blockElem, exceptionCode);
+
+ // Step 6: Elide |elem|, since it is effectively no longer open. Also update
+ // the node associated with the previous stack element so that when it gets popped,
+ // it doesn't make the residual element the next current node.
+ HTMLStackElem* currElem = maxElem;
+ HTMLStackElem* prevElem = 0;
+ while (currElem != elem) {
+ prevElem = currElem;
+ currElem = currElem->next;
+ }
+ prevElem->next = elem->next;
+ prevElem->setNode(elem->node);
+ delete elem;
+
+ // Step 7: Reopen intermediate inlines, e.g., <b><p><i>Foo</b>Goo</p>.
+ // In the above example, Goo should stay italic.
+ curr = blockStack;
+ HTMLStackElem* residualStyleStack = 0;
+ while (curr && curr != endElem) {
+ // We will actually schedule this tag for reopening
+ // after we complete the close of this entire block.
+ NodeImpl* currNode = current;
+ if (isResidualStyleTag(curr->id)) {
+ // We've overloaded the use of stack elements and are just reusing the
+ // struct with a slightly different meaning to the variables. Instead of chaining
+ // from innermost to outermost, we build up a list of all the tags we need to reopen
+ // from the outermost to the innermost, i.e., residualStyleStack will end up pointing
+ // to the outermost tag we need to reopen.
+ // We also set curr->node to be the actual element that corresponds to the ID stored in
+ // curr->id rather than the node that you should pop to when the element gets pulled off
+ // the stack.
+ popOneBlock(false);
+ curr->setNode(currNode);
+ curr->next = residualStyleStack;
+ residualStyleStack = curr;
+ }
+ else
+ popOneBlock();
+
+ curr = blockStack;
+ }
+
+ reopenResidualStyleTags(residualStyleStack, 0); // FIXME: Deal with stray table content some day
+ // if it becomes necessary to do so.
+}
+
+void KHTMLParser::reopenResidualStyleTags(HTMLStackElem* elem, DOM::NodeImpl* malformedTableParent)
+{
+ // Loop for each tag that needs to be reopened.
+ while (elem) {
+ // Create a shallow clone of the DOM node for this element.
+ NodeImpl* newNode = elem->node->cloneNode(false);
+
+ // Append the new node. In the malformed table case, we need to insert before the table,
+ // which will be the last child.
+ int exceptionCode = 0;
+ if (malformedTableParent)
+ malformedTableParent->insertBefore(newNode, malformedTableParent->lastChild(), exceptionCode);
+ else
+ current->appendChild(newNode, exceptionCode);
+ // FIXME: Is it really OK to ignore the exceptions here?
+
+ // Now push a new stack element for this node we just created.
+ pushBlock(elem->id, elem->level);
+
+ // Set our strayTableContent boolean if needed, so that the reopened tag also knows
+ // that it is inside a malformed table.
+ blockStack->strayTableContent = malformedTableParent != 0;
+ if (blockStack->strayTableContent)
+ inStrayTableContent++;
+
+ // Clear our malformed table parent variable.
+ malformedTableParent = 0;
+
+ // Update |current| manually to point to the new node.
+ setCurrent(newNode);
+
+ // Advance to the next tag that needs to be reopened.
+ HTMLStackElem* next = elem->next;
+ delete elem;
+ elem = next;
+ }
+}
+
+void KHTMLParser::pushBlock(int _id, int _level)
+{
+ HTMLStackElem *Elem = new HTMLStackElem(_id, _level, current, m_inline, blockStack);
+
+ blockStack = Elem;
+ addForbidden(_id, forbiddenTag);
+}
+
+void KHTMLParser::popBlock( int _id )
+{
+ HTMLStackElem *Elem = blockStack;
+ int maxLevel = 0;
+
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "popBlock(" << getTagName(_id) << ")" << endl;
+ while(Elem) {
+ kdDebug( 6035) << " > " << getTagName(Elem->id) << endl;
+ Elem = Elem->next;
+ }
+ Elem = blockStack;
+#endif
+
+ while( Elem && (Elem->id != _id))
+ {
+ if (maxLevel < Elem->level)
+ {
+ maxLevel = Elem->level;
+ }
+ Elem = Elem->next;
+ }
+ if (!Elem)
+ return;
+
+ if (maxLevel > Elem->level) {
+ // We didn't match because the tag is in a different scope, e.g.,
+ // <b><p>Foo</b>. Try to correct the problem.
+ if (!isResidualStyleTag(_id))
+ return;
+ return handleResidualStyleCloseTagAcrossBlocks(Elem);
+ }
+
+ bool isAffectedByStyle = isAffectedByResidualStyle(Elem->id);
+ HTMLStackElem* residualStyleStack = 0;
+ NodeImpl* malformedTableParent = 0;
+
+ Elem = blockStack;
+
+ while (Elem)
+ {
+ if (Elem->id == _id)
+ {
+ int strayTable = inStrayTableContent;
+ popOneBlock();
+ Elem = 0;
+
+ // This element was the root of some malformed content just inside an implicit or
+ // explicit <tbody> or <tr>.
+ // If we end up needing to reopen residual style tags, the root of the reopened chain
+ // must also know that it is the root of malformed content inside a <tbody>/<tr>.
+ if (strayTable && (inStrayTableContent < strayTable) && residualStyleStack) {
+ NodeImpl* curr = current;
+ while (curr && curr->id() != ID_TABLE)
+ curr = curr->parentNode();
+ malformedTableParent = curr ? curr->parentNode() : 0;
+ }
+ }
+ else
+ {
+ // Schedule this tag for reopening
+ // after we complete the close of this entire block.
+ NodeImpl* currNode = current;
+ if (isAffectedByStyle && isResidualStyleTag(Elem->id)) {
+ // We've overloaded the use of stack elements and are just reusing the
+ // struct with a slightly different meaning to the variables. Instead of chaining
+ // from innermost to outermost, we build up a list of all the tags we need to reopen
+ // from the outermost to the innermost, i.e., residualStyleStack will end up pointing
+ // to the outermost tag we need to reopen.
+ // We also set Elem->node to be the actual element that corresponds to the ID stored in
+ // Elem->id rather than the node that you should pop to when the element gets pulled off
+ // the stack.
+ popOneBlock(false);
+ Elem->next = residualStyleStack;
+ Elem->setNode(currNode);
+ residualStyleStack = Elem;
+ }
+ else
+ popOneBlock();
+ Elem = blockStack;
+ }
+ }
+
+ reopenResidualStyleTags(residualStyleStack, malformedTableParent);
+}
+
+void KHTMLParser::popOneBlock(bool delBlock)
+{
+ HTMLStackElem *Elem = blockStack;
+
+ // we should never get here, but some bad html might cause it.
+#ifndef PARSER_DEBUG
+ if(!Elem) return;
+#else
+ kdDebug( 6035 ) << "popping block: " << getTagName(Elem->id) << "(" << Elem->id << ")" << endl;
+#endif
+
+#if SPEED_DEBUG < 1
+ if((Elem->node != current)) {
+ if (current->maintainsState() && document){
+ document->registerMaintainsState(current);
+ QString state(document->nextState());
+ if (!state.isNull()) current->restoreState(state);
+ }
+ current->close();
+ }
+#endif
+
+ removeForbidden(Elem->id, forbiddenTag);
+
+ blockStack = Elem->next;
+ // we only set inline to false, if the element we close is a block level element.
+ // This helps getting cases as <p><b>bla</b> <b>bla</b> right.
+
+ m_inline = Elem->m_inline;
+
+ if (current->id() == ID_FORM && form && inStrayTableContent)
+ form->setMalformed(true);
+
+ setCurrent( Elem->node );
+
+ if (Elem->strayTableContent)
+ inStrayTableContent--;
+
+ if (delBlock)
+ delete Elem;
+}
+
+void KHTMLParser::popInlineBlocks()
+{
+ while(blockStack && current->isInline() && current->id() != ID_FONT)
+ popOneBlock();
+}
+
+void KHTMLParser::freeBlock()
+{
+ while (blockStack)
+ popOneBlock();
+ blockStack = 0;
+}
+
+void KHTMLParser::createHead()
+{
+ if(head || !doc()->firstChild())
+ return;
+
+ head = new HTMLHeadElementImpl(document);
+ HTMLElementImpl *body = doc()->body();
+ int exceptioncode = 0;
+ doc()->firstChild()->insertBefore(head, body, exceptioncode);
+ if ( exceptioncode ) {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "creation of head failed!!!!" << endl;
+#endif
+ delete head;
+ head = 0;
+ }
+}
+
+NodeImpl *KHTMLParser::handleIsindex( Token *t )
+{
+ NodeImpl *n;
+ HTMLFormElementImpl *myform = form;
+ if ( !myform ) {
+ myform = new HTMLFormElementImpl(document, true);
+ n = myform;
+ } else
+ n = new HTMLDivElementImpl( document, ID_DIV );
+ NodeImpl *child = new HTMLHRElementImpl( document );
+ n->addChild( child );
+ DOMStringImpl* a = t->attrs ? t->attrs->getValue(ATTR_PROMPT) : 0;
+ DOMString text = i18n("This is a searchable index. Enter search keywords: ");
+ if (a)
+ text = a;
+ child = new TextImpl(document, text.implementation());
+ n->addChild( child );
+ child = new HTMLIsIndexElementImpl(document, myform);
+ static_cast<ElementImpl *>(child)->setAttribute(ATTR_TYPE, "khtml_isindex");
+ n->addChild( child );
+ child = new HTMLHRElementImpl( document );
+ n->addChild( child );
+
+ return n;
+}
+
+void KHTMLParser::startBody()
+{
+ if(inBody) return;
+
+ inBody = true;
+
+ if( isindex ) {
+ insertNode( isindex, true /* don't decend into this node */ );
+ isindex = 0;
+ }
+}
diff --git a/khtml/html/htmlparser.h b/khtml/html/htmlparser.h
new file mode 100644
index 000000000..e09eefbae
--- /dev/null
+++ b/khtml/html/htmlparser.h
@@ -0,0 +1,191 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1997 Torben Weis (weis@kde.org)
+ (C) 1998 Waldo Bastian (bastian@kde.org)
+ (C) 1999 Lars Knoll (knoll@kde.org)
+ (C) 2003 Apple Computer, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- HTML Parser
+
+#ifndef HTMLPARSER_H
+#define HTMLPARSER_H
+
+// 0 all
+// 1 domtree + rendertree + styleForElement, no layouting
+// 2 domtree only
+#define SPEED_DEBUG 0
+
+#ifdef SPEED_DEBUG
+#include <qdatetime.h>
+#endif
+
+
+#include "dom/dom_string.h"
+#include "xml/dom_nodeimpl.h"
+#include "html/html_documentimpl.h"
+
+class KHTMLView;
+class HTMLStackElem;
+
+namespace DOM {
+ class HTMLDocumentImpl;
+ class DocumentImpl;
+ class HTMLElementImpl;
+ class NodeImpl;
+ class HTMLFormElementImpl;
+ class HTMLMapElementImpl;
+ class HTMLHeadElementImpl;
+ class DocumentFragmentImpl;
+}
+
+namespace khtml {
+
+class Token;
+
+/**
+ * The parser for html. It receives a stream of tokens from the HTMLTokenizer, and
+ * builds up the Document structure form it.
+ */
+class KHTMLParser
+{
+public:
+ KHTMLParser( KHTMLView *w, DOM::DocumentImpl *i );
+ KHTMLParser( DOM::DocumentFragmentImpl *frag, DOM::DocumentImpl *doc );
+ virtual ~KHTMLParser();
+
+ /**
+ * parses one token delivered by the tokenizer
+ */
+ void parseToken(Token *_t);
+
+ /**
+ * resets the parser
+ */
+ void reset();
+
+ bool skipMode() const { return (discard_until != 0); }
+ bool noSpaces() const { return (inSelect || !m_inline || !inBody); }
+ bool selectMode() const { return inSelect; }
+
+ DOM::HTMLDocumentImpl *doc() const { return static_cast<DOM::HTMLDocumentImpl *>(document); }
+ DOM::DocumentImpl *docPtr() const { return document; }
+
+protected:
+
+ KHTMLView *HTMLWidget;
+ DOM::DocumentImpl *document;
+
+ /*
+ * generate an element from the token
+ */
+ DOM::NodeImpl *getElement(Token *);
+
+ void processCloseTag(Token *);
+
+ bool insertNode(DOM::NodeImpl *n, bool flat = false);
+
+ /*
+ * The currently active element (the one new elements will be added to)
+ */
+ void setCurrent( DOM::NodeImpl* newNode )
+ {
+ if ( newNode ) newNode->ref();
+ if ( current ) current->deref();
+ current = newNode;
+ }
+
+private:
+ DOM::NodeImpl *current;
+
+ HTMLStackElem *blockStack;
+
+ void pushBlock( int _id, int _level);
+
+ void popBlock( int _id );
+ void popOneBlock(bool delBlock = true);
+ void popInlineBlocks();
+
+ void freeBlock( void);
+
+ void createHead();
+
+ bool isResidualStyleTag(int _id);
+ bool isAffectedByResidualStyle(int _id);
+ void handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem);
+ void reopenResidualStyleTags(HTMLStackElem* elem, DOM::NodeImpl* malformedTableParent);
+
+ ushort *forbiddenTag;
+
+ /*
+ * currently active form
+ */
+ DOM::HTMLFormElementImpl *form;
+
+ /*
+ * current map
+ */
+ DOM::HTMLMapElementImpl *map;
+
+ /*
+ * the head element. Needed for crappy html which defines <base> after </head>
+ */
+ DOM::HTMLHeadElementImpl *head;
+
+ /*
+ * a possible <isindex> element in the head. Compatibility hack for
+ * html from the stone age
+ */
+ DOM::NodeImpl *isindex;
+ DOM::NodeImpl *handleIsindex( Token *t );
+
+ /*
+ * inserts the stupid isIndex element.
+ */
+ void startBody();
+
+ bool inBody;
+ bool haveContent;
+ bool haveBody;
+ bool haveFrameSet;
+ bool haveTitle;
+ bool m_inline;
+ bool end;
+ bool inSelect;
+
+
+ /*
+ * tells the parser to discard all tags, until it reaches the one specified
+ */
+ int discard_until;
+
+ bool headLoaded;
+ int inStrayTableContent;
+
+#if SPEED_DEBUG > 0
+ QTime qt;
+#endif
+};
+
+} // namespace khtml
+
+#endif // HTMLPARSER_H
+
diff --git a/khtml/html/htmltokenizer.cpp b/khtml/html/htmltokenizer.cpp
new file mode 100644
index 000000000..e0983582a
--- /dev/null
+++ b/khtml/html/htmltokenizer.cpp
@@ -0,0 +1,1798 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1997 Torben Weis (weis@kde.org)
+ (C) 1998 Waldo Bastian (bastian@kde.org)
+ (C) 1999 Lars Knoll (knoll@kde.org)
+ (C) 1999 Antti Koivisto (koivisto@kde.org)
+ (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ (C) 2004 Apple Computer, Inc.
+ (C) 2006 Germain Garand (germain@ebooksfrance.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget - Tokenizers
+
+//#define TOKEN_DEBUG 1
+//#define TOKEN_DEBUG 2
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "html/htmltokenizer.h"
+#include "html/html_documentimpl.h"
+#include "html/htmlparser.h"
+#include "html/dtd.h"
+
+#include "misc/loader.h"
+#include "misc/htmlhashes.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "xml/dom_docimpl.h"
+#include "css/csshelper.h"
+#include "ecma/kjs_proxy.h"
+#include <kcharsets.h>
+#include <kglobal.h>
+#include <ctype.h>
+#include <assert.h>
+#include <qvariant.h>
+#include <kdebug.h>
+#include <stdlib.h>
+
+#include "kentities.c"
+
+using namespace khtml;
+
+static const QChar commentStart [] = { '<','!','-','-', QChar::null };
+
+static const char scriptEnd [] = "</script";
+static const char xmpEnd [] = "</xmp";
+static const char styleEnd [] = "</style";
+static const char textareaEnd [] = "</textarea";
+static const char titleEnd [] = "</title";
+
+#define KHTML_ALLOC_QCHAR_VEC( N ) (QChar*) malloc( sizeof(QChar)*( N ) )
+#define KHTML_REALLOC_QCHAR_VEC(P, N ) (QChar*) realloc(P, sizeof(QChar)*( N ))
+#define KHTML_DELETE_QCHAR_VEC( P ) free((char*)( P ))
+
+// Full support for MS Windows extensions to Latin-1.
+// Technically these extensions should only be activated for pages
+// marked "windows-1252" or "cp1252", but
+// in the standard Microsoft way, these extensions infect hundreds of thousands
+// of web pages. Note that people with non-latin-1 Microsoft extensions
+// are SOL.
+//
+// See: http://www.microsoft.com/globaldev/reference/WinCP.asp
+// http://www.bbsinc.com/iso8859.html
+// http://www.obviously.com/
+//
+// There may be better equivalents
+#if 0
+#define fixUpChar(x)
+#else
+#define fixUpChar(x) \
+ switch ((x).unicode()) \
+ { \
+ case 0x80: (x) = 0x20ac; break; \
+ case 0x82: (x) = 0x201a; break; \
+ case 0x83: (x) = 0x0192; break; \
+ case 0x84: (x) = 0x201e; break; \
+ case 0x85: (x) = 0x2026; break; \
+ case 0x86: (x) = 0x2020; break; \
+ case 0x87: (x) = 0x2021; break; \
+ case 0x88: (x) = 0x02C6; break; \
+ case 0x89: (x) = 0x2030; break; \
+ case 0x8A: (x) = 0x0160; break; \
+ case 0x8b: (x) = 0x2039; break; \
+ case 0x8C: (x) = 0x0152; break; \
+ case 0x8E: (x) = 0x017D; break; \
+ case 0x91: (x) = 0x2018; break; \
+ case 0x92: (x) = 0x2019; break; \
+ case 0x93: (x) = 0x201C; break; \
+ case 0x94: (x) = 0X201D; break; \
+ case 0x95: (x) = 0x2022; break; \
+ case 0x96: (x) = 0x2013; break; \
+ case 0x97: (x) = 0x2014; break; \
+ case 0x98: (x) = 0x02DC; break; \
+ case 0x99: (x) = 0x2122; break; \
+ case 0x9A: (x) = 0x0161; break; \
+ case 0x9b: (x) = 0x203A; break; \
+ case 0x9C: (x) = 0x0153; break; \
+ case 0x9E: (x) = 0x017E; break; \
+ case 0x9F: (x) = 0x0178; break; \
+ default: break; \
+ }
+#endif
+// ----------------------------------------------------------------------------
+
+HTMLTokenizer::HTMLTokenizer(DOM::DocumentImpl *_doc, KHTMLView *_view)
+{
+ view = _view;
+ buffer = 0;
+ scriptCode = 0;
+ scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0;
+ charsets = KGlobal::charsets();
+ parser = new KHTMLParser(_view, _doc);
+ m_executingScript = 0;
+ m_autoCloseTimer = 0;
+ onHold = false;
+
+ reset();
+}
+
+HTMLTokenizer::HTMLTokenizer(DOM::DocumentImpl *_doc, DOM::DocumentFragmentImpl *i)
+{
+ view = 0;
+ buffer = 0;
+ scriptCode = 0;
+ scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0;
+ charsets = KGlobal::charsets();
+ parser = new KHTMLParser( i, _doc );
+ m_executingScript = 0;
+ m_autoCloseTimer = 0;
+ onHold = false;
+
+ reset();
+}
+
+void HTMLTokenizer::reset()
+{
+ assert(m_executingScript == 0);
+ Q_ASSERT(onHold == false);
+ m_abort = false;
+
+ while (!cachedScript.isEmpty())
+ cachedScript.dequeue()->deref(this);
+
+ if ( buffer )
+ KHTML_DELETE_QCHAR_VEC(buffer);
+ buffer = dest = 0;
+ size = 0;
+
+ if ( scriptCode )
+ KHTML_DELETE_QCHAR_VEC(scriptCode);
+ scriptCode = 0;
+ scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0;
+
+ if (m_autoCloseTimer) {
+ killTimer(m_autoCloseTimer);
+ m_autoCloseTimer = 0;
+ }
+
+ currToken.reset();
+}
+
+void HTMLTokenizer::begin()
+{
+ m_executingScript = 0;
+ onHold = false;
+ reset();
+ size = 254;
+ buffer = KHTML_ALLOC_QCHAR_VEC( 255 );
+ dest = buffer;
+ tag = NoTag;
+ pending = NonePending;
+ discard = NoneDiscard;
+ pre = false;
+ prePos = 0;
+ plaintext = false;
+ xmp = false;
+ processingInstruction = false;
+ script = false;
+ escaped = false;
+ style = false;
+ skipLF = false;
+ select = false;
+ comment = false;
+ server = false;
+ textarea = false;
+ title = false;
+ startTag = false;
+ tquote = NoQuote;
+ searchCount = 0;
+ Entity = NoEntity;
+ noMoreData = false;
+ brokenComments = false;
+ brokenServer = false;
+ brokenScript = false;
+ lineno = 0;
+ scriptStartLineno = 0;
+ tagStartLineno = 0;
+}
+
+void HTMLTokenizer::processListing(TokenizerString list)
+{
+ bool old_pre = pre;
+
+ // This function adds the listing 'list' as
+ // preformatted text-tokens to the token-collection
+ // thereby converting TABs.
+ if(!style) pre = true;
+ prePos = 0;
+
+ while ( !list.isEmpty() )
+ {
+ checkBuffer(3*TAB_SIZE);
+
+ if (skipLF && ( *list != '\n' ))
+ {
+ skipLF = false;
+ }
+
+ if (skipLF)
+ {
+ skipLF = false;
+ ++list;
+ }
+ else if (( *list == '\n' ) || ( *list == '\r' ))
+ {
+ if (discard == LFDiscard)
+ {
+ // Ignore this LF
+ discard = NoneDiscard; // We have discarded 1 LF
+ }
+ else
+ {
+ // Process this LF
+ if (pending)
+ addPending();
+
+ // we used to do it not at all and we want to have
+ // it fixed for textarea. So here we are
+ if ( textarea ) {
+ prePos++;
+ *dest++ = *list;
+ } else
+ pending = LFPending;
+ }
+ /* Check for MS-DOS CRLF sequence */
+ if (*list == '\r')
+ {
+ skipLF = true;
+ }
+ ++list;
+ }
+ else if (( *list == ' ' ) || ( *list == '\t'))
+ {
+ if (pending)
+ addPending();
+ if (*list == ' ')
+ pending = SpacePending;
+ else
+ pending = TabPending;
+
+ ++list;
+ }
+ else
+ {
+ discard = NoneDiscard;
+ if (pending)
+ addPending();
+
+ prePos++;
+ *dest++ = *list;
+ ++list;
+ }
+
+ }
+
+ if ((pending == SpacePending) || (pending == TabPending))
+ addPending();
+ else
+ pending = NonePending;
+
+ prePos = 0;
+ pre = old_pre;
+}
+
+void HTMLTokenizer::parseSpecial(TokenizerString &src)
+{
+ assert( textarea || title || !Entity );
+ assert( !tag );
+ assert( xmp+textarea+title+style+script == 1 );
+ if (script)
+ scriptStartLineno = lineno+src.lineCount();
+
+ if ( comment ) parseComment( src );
+
+ while ( !src.isEmpty() ) {
+ checkScriptBuffer();
+ unsigned char ch = src->latin1();
+ if ( !scriptCodeResync && !brokenComments && !textarea && !xmp && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && QConstString( scriptCode+scriptCodeSize-3, 3 ).string() == "<!-" ) {
+ comment = true;
+ scriptCode[ scriptCodeSize++ ] = ch;
+ ++src;
+ parseComment( src );
+ continue;
+ }
+ if ( scriptCodeResync && !tquote && ( ch == '>' ) ) {
+ ++src;
+ scriptCodeSize = scriptCodeResync-1;
+ scriptCodeResync = 0;
+ scriptCode[ scriptCodeSize ] = scriptCode[ scriptCodeSize + 1 ] = 0;
+ if ( script )
+ scriptHandler();
+ else {
+ processListing(TokenizerString(scriptCode, scriptCodeSize));
+ processToken();
+ if ( style ) { currToken.tid = ID_STYLE + ID_CLOSE_TAG; }
+ else if ( textarea ) { currToken.tid = ID_TEXTAREA + ID_CLOSE_TAG; }
+ else if ( title ) { currToken.tid = ID_TITLE + ID_CLOSE_TAG; }
+ else if ( xmp ) { currToken.tid = ID_XMP + ID_CLOSE_TAG; }
+ processToken();
+ script = style = textarea = title = xmp = false;
+ tquote = NoQuote;
+ scriptCodeSize = scriptCodeResync = 0;
+ }
+ return;
+ }
+ // possible end of tagname, lets check.
+ if ( !scriptCodeResync && !escaped && !src.escaped() && ( ch == '>' || ch == '/' || ch <= ' ' ) && ch &&
+ scriptCodeSize >= searchStopperLen &&
+ !QConstString( scriptCode+scriptCodeSize-searchStopperLen, searchStopperLen ).string().find( searchStopper, 0, false )) {
+ scriptCodeResync = scriptCodeSize-searchStopperLen+1;
+ tquote = NoQuote;
+ continue;
+ }
+ if ( scriptCodeResync && !escaped ) {
+ if(ch == '\"')
+ tquote = (tquote == NoQuote) ? DoubleQuote : ((tquote == SingleQuote) ? SingleQuote : NoQuote);
+ else if(ch == '\'')
+ tquote = (tquote == NoQuote) ? SingleQuote : (tquote == DoubleQuote) ? DoubleQuote : NoQuote;
+ else if (tquote != NoQuote && (ch == '\r' || ch == '\n'))
+ tquote = NoQuote;
+ }
+ escaped = ( !escaped && ch == '\\' );
+ if (!scriptCodeResync && (textarea||title) && !src.escaped() && ch == '&') {
+ QChar *scriptCodeDest = scriptCode+scriptCodeSize;
+ ++src;
+ parseEntity(src,scriptCodeDest,true);
+ scriptCodeSize = scriptCodeDest-scriptCode;
+ }
+ else {
+ scriptCode[ scriptCodeSize++ ] = *src;
+ ++src;
+ }
+ }
+}
+
+void HTMLTokenizer::scriptHandler()
+{
+ QString currentScriptSrc = scriptSrc;
+ scriptSrc = QString::null;
+
+ processListing(TokenizerString(scriptCode, scriptCodeSize));
+ QString exScript( buffer, dest-buffer );
+
+ processToken();
+ currToken.tid = ID_SCRIPT + ID_CLOSE_TAG;
+ processToken();
+
+ // Scripts following a frameset element should not be executed or even loaded in the case of extern scripts.
+ bool followingFrameset = (parser->doc()->body() && parser->doc()->body()->id() == ID_FRAMESET);
+ bool effectiveScript = !parser->skipMode() && !followingFrameset;
+ bool deferredScript = false;
+
+ if ( effectiveScript ) {
+ CachedScript* cs = 0;
+
+ // forget what we just got, load from src url instead
+ if ( !currentScriptSrc.isEmpty() && javascript &&
+ (cs = parser->doc()->docLoader()->requestScript(currentScriptSrc, scriptSrcCharset) )) {
+ cachedScript.enqueue(cs);
+ }
+
+ if (cs) {
+ pendingQueue.push(src);
+ uint scriptCount = cachedScript.count();
+ setSrc(TokenizerString());
+ scriptCodeSize = scriptCodeResync = 0;
+ cs->ref(this);
+ if (cachedScript.count() == scriptCount)
+ deferredScript = true;
+ }
+ else if (currentScriptSrc.isEmpty() && view && javascript ) {
+ pendingQueue.push(src);
+ setSrc(TokenizerString());
+ scriptCodeSize = scriptCodeResync = 0;
+ scriptExecution( exScript, QString::null, tagStartLineno /*scriptStartLineno*/ );
+ } else {
+ // script was filtered or disallowed
+ effectiveScript = false;
+ }
+ }
+
+ script = false;
+ scriptCodeSize = scriptCodeResync = 0;
+
+ if ( !effectiveScript )
+ return;
+
+ if ( !m_executingScript && cachedScript.isEmpty() ) {
+ src.append(pendingQueue.pop());
+ } else if ( cachedScript.isEmpty() ) {
+ write( pendingQueue.pop(), false );
+ } else if ( !deferredScript && pendingQueue.count() > 1) {
+ TokenizerString t = pendingQueue.pop();
+ pendingQueue.top().prepend( t );
+ }
+}
+
+void HTMLTokenizer::scriptExecution( const QString& str, const QString& scriptURL,
+ int baseLine)
+{
+ bool oldscript = script;
+ m_executingScript++;
+ script = false;
+ QString url;
+ if (scriptURL.isNull() && view)
+ url = static_cast<DocumentImpl*>(view->part()->document().handle())->URL().url();
+ else
+ url = scriptURL;
+
+ if (view)
+ view->part()->executeScript(url,baseLine+1,Node(),str);
+ m_executingScript--;
+ script = oldscript;
+}
+
+void HTMLTokenizer::parseComment(TokenizerString &src)
+{
+ // SGML strict
+ bool strict = parser->doc()->inStrictMode() && parser->doc()->htmlMode() != DocumentImpl::XHtml && !script && !style;
+ int delimiterCount = 0;
+ bool canClose = false;
+
+ checkScriptBuffer(src.length());
+ while ( src.length() ) {
+ scriptCode[ scriptCodeSize++ ] = *src;
+
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("comment is now: *%s*", src.toString().left(16).latin1());
+#endif
+
+ if (strict)
+ {
+ if (src->unicode() == '-') {
+ delimiterCount++;
+ if (delimiterCount == 2) {
+ delimiterCount = 0;
+ canClose = !canClose;
+ }
+ }
+ else
+ delimiterCount = 0;
+ }
+
+ if ((!strict || canClose) && src->unicode() == '>')
+ {
+ bool handleBrokenComments = brokenComments && !( script || style );
+ bool scriptEnd=false;
+ if (!strict)
+ {
+ if ( scriptCodeSize > 2 && scriptCode[scriptCodeSize-3] == '-' &&
+ scriptCode[scriptCodeSize-2] == '-' )
+ scriptEnd=true;
+ }
+
+ if (canClose || handleBrokenComments || scriptEnd ){
+ ++src;
+ if ( !( title || script || xmp || textarea || style) ) {
+#ifdef COMMENTS_IN_DOM
+ checkScriptBuffer();
+ scriptCode[ scriptCodeSize ] = 0;
+ scriptCode[ scriptCodeSize + 1 ] = 0;
+ currToken.tid = ID_COMMENT;
+ processListing(DOMStringIt(scriptCode, scriptCodeSize - 2));
+ processToken();
+ currToken.tid = ID_COMMENT + ID_CLOSE_TAG;
+ processToken();
+#endif
+ scriptCodeSize = 0;
+ }
+ comment = false;
+ return; // Finished parsing comment
+ }
+ }
+ ++src;
+ }
+}
+
+void HTMLTokenizer::parseServer(TokenizerString &src)
+{
+ checkScriptBuffer(src.length());
+ while ( !src.isEmpty() ) {
+ scriptCode[ scriptCodeSize++ ] = *src;
+ if (src->unicode() == '>' &&
+ scriptCodeSize > 1 && scriptCode[scriptCodeSize-2] == '%') {
+ ++src;
+ server = false;
+ scriptCodeSize = 0;
+ return; // Finished parsing server include
+ }
+ ++src;
+ }
+}
+
+void HTMLTokenizer::parseProcessingInstruction(TokenizerString &src)
+{
+ char oldchar = 0;
+ while ( !src.isEmpty() )
+ {
+ unsigned char chbegin = src->latin1();
+ if(chbegin == '\'') {
+ tquote = tquote == SingleQuote ? NoQuote : SingleQuote;
+ }
+ else if(chbegin == '\"') {
+ tquote = tquote == DoubleQuote ? NoQuote : DoubleQuote;
+ }
+ // Look for '?>'
+ // some crappy sites omit the "?" before it, so
+ // we look for an unquoted '>' instead. (IE compatible)
+ else if ( chbegin == '>' && ( !tquote || oldchar == '?' ) )
+ {
+ // We got a '?>' sequence
+ processingInstruction = false;
+ ++src;
+ discard=LFDiscard;
+ return; // Finished parsing comment!
+ }
+ ++src;
+ oldchar = chbegin;
+ }
+}
+
+void HTMLTokenizer::parseText(TokenizerString &src)
+{
+ while ( !src.isEmpty() )
+ {
+ // do we need to enlarge the buffer?
+ checkBuffer();
+
+ // ascii is okay because we only do ascii comparisons
+ unsigned char chbegin = src->latin1();
+
+ if (skipLF && ( chbegin != '\n' ))
+ {
+ skipLF = false;
+ }
+
+ if (skipLF)
+ {
+ skipLF = false;
+ ++src;
+ }
+ else if (( chbegin == '\n' ) || ( chbegin == '\r' ))
+ {
+ if (chbegin == '\r')
+ skipLF = true;
+
+ *dest++ = '\n';
+ ++src;
+ }
+ else {
+ *dest++ = *src;
+ ++src;
+ }
+ }
+}
+
+
+void HTMLTokenizer::parseEntity(TokenizerString &src, QChar *&dest, bool start)
+{
+ if( start )
+ {
+ cBufferPos = 0;
+ entityLen = 0;
+ Entity = SearchEntity;
+ }
+
+ while( !src.isEmpty() )
+ {
+ ushort cc = src->unicode();
+ switch(Entity) {
+ case NoEntity:
+ return;
+
+ break;
+ case SearchEntity:
+ if(cc == '#') {
+ cBuffer[cBufferPos++] = cc;
+ ++src;
+ Entity = NumericSearch;
+ }
+ else
+ Entity = EntityName;
+
+ break;
+
+ case NumericSearch:
+ if(cc == 'x' || cc == 'X') {
+ cBuffer[cBufferPos++] = cc;
+ ++src;
+ Entity = Hexadecimal;
+ }
+ else if(cc >= '0' && cc <= '9')
+ Entity = Decimal;
+ else
+ Entity = SearchSemicolon;
+
+ break;
+
+ case Hexadecimal:
+ {
+ int uc = EntityChar.unicode();
+ int ll = kMin<uint>(src.length(), 8);
+ while(ll--) {
+ QChar csrc(src->lower());
+ cc = csrc.cell();
+
+ if(csrc.row() || !((cc >= '0' && cc <= '9') || (cc >= 'a' && cc <= 'f'))) {
+ break;
+ }
+ uc = uc*16 + (cc - ( cc < 'a' ? '0' : 'a' - 10));
+ cBuffer[cBufferPos++] = cc;
+ ++src;
+ }
+ EntityChar = QChar(uc);
+ Entity = SearchSemicolon;
+ break;
+ }
+ case Decimal:
+ {
+ int uc = EntityChar.unicode();
+ int ll = kMin(src.length(), 9-cBufferPos);
+ while(ll--) {
+ cc = src->cell();
+
+ if(src->row() || !(cc >= '0' && cc <= '9')) {
+ Entity = SearchSemicolon;
+ break;
+ }
+
+ uc = uc * 10 + (cc - '0');
+ cBuffer[cBufferPos++] = cc;
+ ++src;
+ }
+ EntityChar = QChar(uc);
+ if(cBufferPos == 9) Entity = SearchSemicolon;
+ break;
+ }
+ case EntityName:
+ {
+ int ll = kMin(src.length(), 9-cBufferPos);
+ while(ll--) {
+ QChar csrc = *src;
+ cc = csrc.cell();
+
+ if(csrc.row() || !((cc >= 'a' && cc <= 'z') ||
+ (cc >= '0' && cc <= '9') || (cc >= 'A' && cc <= 'Z'))) {
+ Entity = SearchSemicolon;
+ break;
+ }
+
+ cBuffer[cBufferPos++] = cc;
+ ++src;
+
+ // be IE compatible and interpret even unterminated entities
+ // outside tags. like "foo &nbspstuff bla".
+ if ( tag == NoTag ) {
+ const entity* e = kde_findEntity(cBuffer, cBufferPos);
+ if ( e && e->code < 256 ) {
+ EntityChar = e->code;
+ entityLen = cBufferPos;
+ }
+ }
+ }
+ if(cBufferPos == 9) Entity = SearchSemicolon;
+ if(Entity == SearchSemicolon) {
+ if(cBufferPos > 1) {
+ const entity *e = kde_findEntity(cBuffer, cBufferPos);
+ // IE only accepts unterminated entities < 256,
+ // Gecko accepts them all, but only outside tags
+ if(e && ( tag == NoTag || e->code < 256 || *src == ';' )) {
+ EntityChar = e->code;
+ entityLen = cBufferPos;
+ }
+ }
+ }
+ break;
+ }
+ case SearchSemicolon:
+#ifdef TOKEN_DEBUG
+ kdDebug( 6036 ) << "ENTITY " << EntityChar.unicode() << endl;
+#endif
+ fixUpChar(EntityChar);
+
+ if (*src == ';')
+ ++src;
+
+ if ( !EntityChar.isNull() ) {
+ checkBuffer();
+ if (entityLen > 0 && entityLen < cBufferPos) {
+ int rem = cBufferPos - entityLen;
+ src.prepend( TokenizerString(QString::fromAscii(cBuffer+entityLen, rem)) );
+ }
+ src.push( EntityChar );
+ } else {
+#ifdef TOKEN_DEBUG
+ kdDebug( 6036 ) << "unknown entity!" << endl;
+#endif
+ checkBuffer(11);
+ // ignore the sequence, add it to the buffer as plaintext
+ *dest++ = '&';
+ for(unsigned int i = 0; i < cBufferPos; i++)
+ dest[i] = cBuffer[i];
+ dest += cBufferPos;
+ if (pre)
+ prePos += cBufferPos+1;
+ }
+
+ Entity = NoEntity;
+ EntityChar = QChar::null;
+ return;
+ };
+ }
+}
+
+void HTMLTokenizer::parseTag(TokenizerString &src)
+{
+ assert(!Entity );
+ checkScriptBuffer( src.length() );
+
+ while ( !src.isEmpty() )
+ {
+ checkBuffer();
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ uint l = 0;
+ while(l < src.length() && (src.toString()[l]).latin1() != '>')
+ l++;
+ qDebug("src is now: *%s*, tquote: %d",
+ src.toString().left(l).latin1(), tquote);
+#endif
+ switch(tag) {
+ case NoTag:
+ return;
+ case TagName:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("TagName");
+#endif
+ if (searchCount > 0)
+ {
+ if (*src == commentStart[searchCount])
+ {
+ searchCount++;
+ if (searchCount == 4)
+ {
+#ifdef TOKEN_DEBUG
+ kdDebug( 6036 ) << "Found comment" << endl;
+#endif
+ // Found '<!--' sequence
+ ++src;
+ dest = buffer; // ignore the previous part of this tag
+ tag = NoTag;
+
+ comment = true;
+ parseComment(src);
+ return; // Finished parsing tag!
+ }
+ // cuts of high part, is okay
+ cBuffer[cBufferPos++] = src->cell();
+ ++src;
+ break;
+ }
+ else
+ searchCount = 0; // Stop looking for '<!--' sequence
+ }
+
+ bool finish = false;
+ unsigned int ll = kMin(src.length(), CBUFLEN-cBufferPos);
+ while(ll--) {
+ ushort curchar = *src;
+ if(curchar <= ' ' || curchar == '>' ) {
+ finish = true;
+ break;
+ }
+ // this is a nasty performance trick. will work for the A-Z
+ // characters, but not for others. if it contains one,
+ // we fail anyway
+ char cc = curchar;
+ cBuffer[cBufferPos++] = cc | 0x20;
+ ++src;
+ }
+
+ // Disadvantage: we add the possible rest of the tag
+ // as attribute names. ### judge if this causes problems
+ if(finish || CBUFLEN == cBufferPos) {
+ bool beginTag;
+ char* ptr = cBuffer;
+ unsigned int len = cBufferPos;
+ cBuffer[cBufferPos] = '\0';
+ if ((cBufferPos > 0) && (*ptr == '/'))
+ {
+ // End Tag
+ beginTag = false;
+ ptr++;
+ len--;
+ }
+ else
+ // Start Tag
+ beginTag = true;
+ // Accept empty xml tags like <br/>
+ if(len > 1 && ptr[len-1] == '/' ) {
+ ptr[--len] = '\0';
+ // if its like <br/> and not like <input/ value=foo>, take it as flat
+ if (*src == '>')
+ currToken.flat = true;
+ }
+
+ uint tagID = khtml::getTagID(ptr, len);
+ if (!tagID) {
+#ifdef TOKEN_DEBUG
+ QCString tmp(ptr, len+1);
+ kdDebug( 6036 ) << "Unknown tag: \"" << tmp.data() << "\"" << endl;
+#endif
+ dest = buffer;
+ }
+ else
+ {
+#ifdef TOKEN_DEBUG
+ QCString tmp(ptr, len+1);
+ kdDebug( 6036 ) << "found tag id=" << tagID << ": " << tmp.data() << endl;
+#endif
+ currToken.tid = beginTag ? tagID : tagID + ID_CLOSE_TAG;
+ dest = buffer;
+ }
+ tag = SearchAttribute;
+ cBufferPos = 0;
+ }
+ break;
+ }
+ case SearchAttribute:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("SearchAttribute");
+#endif
+ bool atespace = false;
+ ushort curchar;
+ while(!src.isEmpty()) {
+ curchar = *src;
+ if(curchar > ' ') {
+ if(curchar == '<' || curchar == '>')
+ tag = SearchEnd;
+ else if(atespace && (curchar == '\'' || curchar == '"'))
+ {
+ tag = SearchValue;
+ *dest++ = 0;
+ attrName = QString::null;
+ }
+ else
+ tag = AttributeName;
+
+ cBufferPos = 0;
+ break;
+ }
+ atespace = true;
+ ++src;
+ }
+ break;
+ }
+ case AttributeName:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("AttributeName");
+#endif
+ ushort curchar;
+ int ll = kMin(src.length(), CBUFLEN-cBufferPos);
+
+ while(ll--) {
+ curchar = *src;
+ if(curchar <= '>') {
+ if(curchar <= ' ' || curchar == '=' || curchar == '>') {
+ unsigned int a;
+ cBuffer[cBufferPos] = '\0';
+ a = khtml::getAttrID(cBuffer, cBufferPos);
+ if ( !a ) {
+ // did we just get /> or e.g checked/>
+ if (curchar == '>' && cBufferPos >=1 && cBuffer[cBufferPos-1] == '/') {
+ currToken.flat = true;
+ if (cBufferPos>1)
+ a = khtml::getAttrID(cBuffer, cBufferPos-1);
+ }
+ if (!a)
+ attrName = QString::fromLatin1(QCString(cBuffer, cBufferPos+1).data());
+ }
+
+ dest = buffer;
+ *dest++ = a;
+#ifdef TOKEN_DEBUG
+ if (!a || (cBufferPos && *cBuffer == '!'))
+ kdDebug( 6036 ) << "Unknown attribute: *" << QCString(cBuffer, cBufferPos+1).data() << "*" << endl;
+ else
+ kdDebug( 6036 ) << "Known attribute: " << QCString(cBuffer, cBufferPos+1).data() << endl;
+#endif
+
+ tag = SearchEqual;
+ break;
+ }
+ }
+ cBuffer[cBufferPos++] =
+ ( curchar >= 'A' && curchar <= 'Z' ) ? curchar | 0x20 : curchar;
+ ++src;
+ }
+ if ( cBufferPos == CBUFLEN ) {
+ cBuffer[cBufferPos] = '\0';
+ attrName = QString::fromLatin1(QCString(cBuffer, cBufferPos+1).data());
+ dest = buffer;
+ *dest++ = 0;
+ tag = SearchEqual;
+ }
+ break;
+ }
+ case SearchEqual:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("SearchEqual");
+#endif
+ ushort curchar;
+ bool atespace = false;
+ while(!src.isEmpty()) {
+ curchar = src->unicode();
+ if(curchar > ' ') {
+ if(curchar == '=') {
+#ifdef TOKEN_DEBUG
+ kdDebug(6036) << "found equal" << endl;
+#endif
+ tag = SearchValue;
+ ++src;
+ }
+ else if(atespace && (curchar == '\'' || curchar == '"'))
+ {
+ tag = SearchValue;
+ *dest++ = 0;
+ attrName = QString::null;
+ }
+ else {
+ DOMString v("");
+ currToken.addAttribute(parser->docPtr(), buffer, attrName, v);
+ dest = buffer;
+ tag = SearchAttribute;
+ }
+ break;
+ }
+ atespace = true;
+ ++src;
+ }
+ break;
+ }
+ case SearchValue:
+ {
+ ushort curchar;
+ while(!src.isEmpty()) {
+ curchar = src->unicode();
+ if(curchar > ' ') {
+ if(( curchar == '\'' || curchar == '\"' )) {
+ tquote = curchar == '\"' ? DoubleQuote : SingleQuote;
+ tag = QuotedValue;
+ ++src;
+ } else
+ tag = Value;
+
+ break;
+ }
+ ++src;
+ }
+ break;
+ }
+ case QuotedValue:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("QuotedValue");
+#endif
+ ushort curchar;
+ while(!src.isEmpty()) {
+ checkBuffer();
+
+ curchar = src->unicode();
+ if(curchar <= '\'' && !src.escaped()) {
+ // ### attributes like '&{blaa....};' are supposed to be treated as jscript.
+ if ( curchar == '&' )
+ {
+ ++src;
+ parseEntity(src, dest, true);
+ break;
+ }
+ else if ( (tquote == SingleQuote && curchar == '\'') ||
+ (tquote == DoubleQuote && curchar == '\"') )
+ {
+ // some <input type=hidden> rely on trailing spaces. argh
+ while(dest > buffer+1 && (*(dest-1) == '\n' || *(dest-1) == '\r'))
+ dest--; // remove trailing newlines
+ DOMString v(buffer+1, dest-buffer-1);
+ currToken.addAttribute(parser->docPtr(), buffer, attrName, v);
+
+ dest = buffer;
+ tag = SearchAttribute;
+ tquote = NoQuote;
+ ++src;
+ break;
+ }
+ }
+ *dest++ = *src;
+ ++src;
+ }
+ break;
+ }
+ case Value:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("Value");
+#endif
+ ushort curchar;
+ while(!src.isEmpty()) {
+ checkBuffer();
+ curchar = src->unicode();
+ if(curchar <= '>' && !src.escaped()) {
+ // parse Entities
+ if ( curchar == '&' )
+ {
+ ++src;
+ parseEntity(src, dest, true);
+ break;
+ }
+ // no quotes. Every space means end of value
+ // '/' does not delimit in IE!
+ if ( curchar <= ' ' || curchar == '>' )
+ {
+ DOMString v(buffer+1, dest-buffer-1);
+ currToken.addAttribute(parser->docPtr(), buffer, attrName, v);
+ dest = buffer;
+ tag = SearchAttribute;
+ break;
+ }
+ }
+
+ *dest++ = *src;
+ ++src;
+ }
+ break;
+ }
+ case SearchEnd:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ qDebug("SearchEnd");
+#endif
+ while(!src.isEmpty()) {
+ if(*src == '<' || *src == '>')
+ break;
+
+ if (*src == '/')
+ currToken.flat = true;
+
+ ++src;
+ }
+ if(src.isEmpty() && *src != '<' && *src != '>') break;
+
+ searchCount = 0; // Stop looking for '<!--' sequence
+ tag = NoTag;
+ tquote = NoQuote;
+ if ( *src == '>' )
+ ++src;
+
+ if ( !currToken.tid ) //stop if tag is unknown
+ return;
+
+ uint tagID = currToken.tid;
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 0
+ kdDebug( 6036 ) << "appending Tag: " << tagID << endl;
+#endif
+ // If the tag requires an end tag it cannot be flat,
+ // unless we are using the HTML parser to parse XHTML
+ // The only exception is SCRIPT and priority 0 tokens.
+ if (tagID < ID_CLOSE_TAG && tagID != ID_SCRIPT &&
+ DOM::endTag[tagID] == DOM::REQUIRED &&
+ parser->doc()->htmlMode() != DocumentImpl::XHtml)
+ currToken.flat = false;
+
+ bool beginTag = !currToken.flat && (tagID < ID_CLOSE_TAG);
+
+ if(tagID >= ID_CLOSE_TAG)
+ tagID -= ID_CLOSE_TAG;
+ else if ( !brokenScript && tagID == ID_SCRIPT ) {
+ DOMStringImpl* a = 0;
+ bool foundTypeAttribute = false;
+ scriptSrc = scriptSrcCharset = QString::null;
+ if ( currToken.attrs && /* potentially have a ATTR_SRC ? */
+ view && /* are we a regular tokenizer or just for innerHTML ? */
+ parser->doc()->view()->part()->jScriptEnabled() /* jscript allowed at all? */
+ ) {
+ if ( ( a = currToken.attrs->getValue( ATTR_SRC ) ) )
+ scriptSrc = parser->doc()->completeURL(khtml::parseURL( DOMString(a) ).string() );
+ if ( ( a = currToken.attrs->getValue( ATTR_CHARSET ) ) )
+ scriptSrcCharset = DOMString(a).string().stripWhiteSpace();
+ if ( scriptSrcCharset.isEmpty() && view)
+ scriptSrcCharset = parser->doc()->view()->part()->encoding();
+ /* Check type before language, since language is deprecated */
+ if ((a = currToken.attrs->getValue(ATTR_TYPE)) != 0 && !DOMString(a).string().isEmpty())
+ foundTypeAttribute = true;
+ else
+ a = currToken.attrs->getValue(ATTR_LANGUAGE);
+ }
+ javascript = true;
+
+ if( foundTypeAttribute ) {
+ /*
+ Mozilla 1.5 doesn't accept the text/javascript1.x formats, but WinIE 6 does.
+ Mozilla 1.5 doesn't accept text/jscript, text/ecmascript, and text/livescript, but WinIE 6 does.
+ Mozilla 1.5 accepts application/x-javascript, WinIE 6 doesn't.
+ Mozilla 1.5 allows leading and trailing whitespace, but WinIE 6 doesn't.
+ Mozilla 1.5 and WinIE 6 both accept the empty string, but neither accept a whitespace-only string.
+ We want to accept all the values that either of these browsers accept, but not other values.
+ */
+ QString type = DOMString(a).string().stripWhiteSpace().lower();
+ if( type.compare("text/javascript") != 0 &&
+ type.compare("text/javascript1.0") != 0 &&
+ type.compare("text/javascript1.1") != 0 &&
+ type.compare("text/javascript1.2") != 0 &&
+ type.compare("text/javascript1.3") != 0 &&
+ type.compare("text/javascript1.4") != 0 &&
+ type.compare("text/javascript1.5") != 0 &&
+ type.compare("text/jscript") != 0 &&
+ type.compare("text/ecmascript") != 0 &&
+ type.compare("text/livescript") != 0 &&
+ type.compare("application/x-javascript") != 0 &&
+ type.compare("application/x-ecmascript") != 0 &&
+ type.compare("application/javascript") != 0 &&
+ type.compare("application/ecmascript") != 0 )
+ javascript = false;
+ } else if( a ) {
+ /*
+ Mozilla 1.5 doesn't accept jscript or ecmascript, but WinIE 6 does.
+ Mozilla 1.5 accepts javascript1.0, javascript1.4, and javascript1.5, but WinIE 6 accepts only 1.1 - 1.3.
+ Neither Mozilla 1.5 nor WinIE 6 accept leading or trailing whitespace.
+ We want to accept all the values that either of these browsers accept, but not other values.
+ */
+ QString lang = DOMString(a).string();
+ lang = lang.lower();
+ if( lang.compare("") != 0 &&
+ lang.compare("javascript") != 0 &&
+ lang.compare("javascript1.0") != 0 &&
+ lang.compare("javascript1.1") != 0 &&
+ lang.compare("javascript1.2") != 0 &&
+ lang.compare("javascript1.3") != 0 &&
+ lang.compare("javascript1.4") != 0 &&
+ lang.compare("javascript1.5") != 0 &&
+ lang.compare("ecmascript") != 0 &&
+ lang.compare("livescript") != 0 &&
+ lang.compare("jscript") )
+ javascript = false;
+ }
+ }
+
+ processToken();
+
+ if ( parser->selectMode() && beginTag)
+ discard = AllDiscard;
+
+ switch( tagID ) {
+ case ID_PRE:
+ pre = beginTag;
+ if (beginTag)
+ discard = LFDiscard;
+ prePos = 0;
+ break;
+ case ID_BR:
+ prePos = 0;
+ break;
+ case ID_SCRIPT:
+ if (beginTag) {
+ searchStopper = scriptEnd;
+ searchStopperLen = 8;
+ script = true;
+ parseSpecial(src);
+ }
+ else if (tagID < ID_CLOSE_TAG) // Handle <script src="foo"/>
+ scriptHandler();
+ break;
+ case ID_STYLE:
+ if (beginTag) {
+ searchStopper = styleEnd;
+ searchStopperLen = 7;
+ style = true;
+ parseSpecial(src);
+ }
+ break;
+ case ID_TEXTAREA:
+ if(beginTag) {
+ searchStopper = textareaEnd;
+ searchStopperLen = 10;
+ textarea = true;
+ discard = NoneDiscard;
+ parseSpecial(src);
+ }
+ break;
+ case ID_TITLE:
+ if (beginTag) {
+ searchStopper = titleEnd;
+ searchStopperLen = 7;
+ title = true;
+ parseSpecial(src);
+ }
+ break;
+ case ID_XMP:
+ if (beginTag) {
+ searchStopper = xmpEnd;
+ searchStopperLen = 5;
+ xmp = true;
+ parseSpecial(src);
+ }
+ break;
+ case ID_SELECT:
+ select = beginTag;
+ break;
+ case ID_PLAINTEXT:
+ plaintext = beginTag;
+ break;
+ }
+ return; // Finished parsing tag!
+ }
+ } // end switch
+ }
+ return;
+}
+
+void HTMLTokenizer::addPending()
+{
+ if ( select && !(comment || script))
+ {
+ *dest++ = ' ';
+ }
+ else if ( textarea )
+ {
+ switch(pending) {
+ case LFPending: *dest++ = '\n'; prePos = 0; break;
+ case SpacePending: *dest++ = ' '; ++prePos; break;
+ case TabPending: *dest++ = '\t'; prePos += TAB_SIZE - (prePos % TAB_SIZE); break;
+ case NonePending:
+ assert(0);
+ }
+ }
+ else
+ {
+ int p;
+
+ switch (pending)
+ {
+ case SpacePending:
+ // Insert a breaking space
+ *dest++ = QChar(' ');
+ prePos++;
+ break;
+
+ case LFPending:
+ *dest = '\n';
+ dest++;
+ prePos = 0;
+ break;
+
+ case TabPending:
+ p = TAB_SIZE - ( prePos % TAB_SIZE );
+ for ( int x = 0; x < p; x++ )
+ *dest++ = QChar(' ');
+ prePos += p;
+ break;
+
+ case NonePending:
+ assert(0);
+ break;
+ }
+ }
+
+ pending = NonePending;
+}
+
+void HTMLTokenizer::write( const TokenizerString &str, bool appendData )
+{
+#ifdef TOKEN_DEBUG
+ kdDebug( 6036 ) << this << " Tokenizer::write(\"" << str.toString() << "\"," << appendData << ")" << endl;
+#endif
+
+ if ( !buffer )
+ return;
+
+ if ( ( m_executingScript && appendData ) || cachedScript.count() ) {
+ // don't parse; we will do this later
+ if (pendingQueue.isEmpty())
+ pendingQueue.push(str);
+ else if (appendData)
+ pendingQueue.bottom().append(str);
+ else
+ pendingQueue.top().append(str);
+ return;
+ }
+
+ if ( onHold ) {
+ src.append(str);
+ return;
+ }
+
+ if (!src.isEmpty())
+ src.append(str);
+ else
+ setSrc(str);
+ m_abort = false;
+
+// if (Entity)
+// parseEntity(src, dest);
+
+ while ( !src.isEmpty() )
+ {
+ if ( m_abort )
+ return;
+ // do we need to enlarge the buffer?
+ checkBuffer();
+
+ ushort cc = src->unicode();
+
+ if (skipLF && (cc != '\n'))
+ skipLF = false;
+
+ if (skipLF) {
+ skipLF = false;
+ ++src;
+ }
+ else if ( Entity )
+ parseEntity( src, dest );
+ else if ( plaintext )
+ parseText( src );
+ else if (script)
+ parseSpecial(src);
+ else if (style)
+ parseSpecial(src);
+ else if (xmp)
+ parseSpecial(src);
+ else if (textarea)
+ parseSpecial(src);
+ else if (title)
+ parseSpecial(src);
+ else if (comment)
+ parseComment(src);
+ else if (server)
+ parseServer(src);
+ else if (processingInstruction)
+ parseProcessingInstruction(src);
+ else if (tag)
+ parseTag(src);
+ else if ( startTag )
+ {
+ startTag = false;
+ bool endTag = false;
+
+ switch(cc) {
+ case '/':
+ endTag = true;
+ break;
+ case '!':
+ {
+ // <!-- comment -->
+ searchCount = 1; // Look for '<!--' sequence to start comment
+
+ break;
+ }
+ case '?':
+ {
+ // xml processing instruction
+ processingInstruction = true;
+ tquote = NoQuote;
+ parseProcessingInstruction(src);
+ continue;
+
+ break;
+ }
+ case '%':
+ if (!brokenServer) {
+ // <% server stuff, handle as comment %>
+ server = true;
+ tquote = NoQuote;
+ parseServer(src);
+ continue;
+ }
+ // else fall through
+ default:
+ {
+ if( ((cc >= 'a') && (cc <= 'z')) || ((cc >= 'A') && (cc <= 'Z')))
+ {
+ // Start of a Start-Tag
+ }
+ else
+ {
+ // Invalid tag
+ // Add as is
+ if (pending)
+ addPending();
+ *dest = '<';
+ dest++;
+ continue;
+ }
+ }
+ }; // end case
+
+ // According to SGML any LF immediately after a starttag, or
+ // immediately before an endtag should be ignored.
+ // ### Gecko and MSIE though only ignores LF immediately after
+ // starttags and only for PRE elements -- asj (28/06-2005)
+ if ( pending )
+ if (!select)
+ addPending();
+ else
+ pending = NonePending;
+
+ // Cancel unused discards
+ discard = NoneDiscard;
+ // if (!endTag) discard = LFDiscard;
+
+ processToken();
+
+ cBufferPos = 0;
+ tag = TagName;
+ parseTag(src);
+ }
+ else if ( cc == '&' && !src.escaped())
+ {
+ ++src;
+ if ( pending )
+ addPending();
+ discard = NoneDiscard;
+ parseEntity(src, dest, true);
+ }
+ else if ( cc == '<' && !src.escaped())
+ {
+ tagStartLineno = lineno+src.lineCount();
+ ++src;
+ discard = NoneDiscard;
+ startTag = true;
+ }
+ else if (( cc == '\n' ) || ( cc == '\r' ))
+ {
+ if (discard == SpaceDiscard)
+ discard = NoneDiscard;
+
+ if (discard == LFDiscard) {
+ // Ignore one LF
+ discard = NoneDiscard;
+ }
+ else if (discard == AllDiscard)
+ {
+ // Ignore
+ }
+ else
+ {
+ if (select && !script) {
+ pending = LFPending;
+ } else {
+ if (pending)
+ addPending();
+ pending = LFPending;
+ }
+ }
+
+ /* Check for MS-DOS CRLF sequence */
+ if (cc == '\r')
+ {
+ skipLF = true;
+ }
+ ++src;
+ }
+ else if (( cc == ' ' ) || ( cc == '\t' ))
+ {
+ if(discard == LFDiscard)
+ discard = NoneDiscard;
+
+ if(discard == SpaceDiscard) {
+ // Ignore one space
+ discard = NoneDiscard;
+ }
+ else if(discard == AllDiscard)
+ {
+ // Ignore
+ }
+ else {
+ if (select && !script) {
+ if (!pending)
+ pending = SpacePending;
+ } else {
+ if (pending)
+ addPending();
+ if (cc == ' ')
+ pending = SpacePending;
+ else
+ pending = TabPending;
+ }
+ }
+
+ ++src;
+ }
+ else
+ {
+ if (pending)
+ addPending();
+
+ discard = NoneDiscard;
+ if ( pre )
+ {
+ prePos++;
+ }
+ *dest = *src;
+ fixUpChar( *dest );
+ ++dest;
+ ++src;
+ }
+ }
+
+ if (noMoreData && cachedScript.isEmpty() && !m_executingScript)
+ end(); // this actually causes us to be deleted
+}
+
+void HTMLTokenizer::timerEvent( QTimerEvent *e )
+{
+ if ( e->timerId() == m_autoCloseTimer && cachedScript.isEmpty() ) {
+ finish();
+ }
+}
+
+void HTMLTokenizer::setAutoClose( bool b ) {
+ killTimer( m_autoCloseTimer );
+ m_autoCloseTimer = 0;
+ if ( b )
+ m_autoCloseTimer = startTimer(100);
+}
+
+void HTMLTokenizer::end()
+{
+ if ( buffer == 0 ) {
+ emit finishedParsing();
+ return;
+ }
+
+ // parseTag is using the buffer for different matters
+ if ( !tag )
+ processToken();
+
+ if(buffer)
+ KHTML_DELETE_QCHAR_VEC(buffer);
+
+ if(scriptCode)
+ KHTML_DELETE_QCHAR_VEC(scriptCode);
+
+ scriptCode = 0;
+ scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0;
+ buffer = 0;
+ emit finishedParsing();
+}
+
+void HTMLTokenizer::finish()
+{
+ if ( m_autoCloseTimer ) {
+ killTimer( m_autoCloseTimer );
+ m_autoCloseTimer = 0;
+ }
+ // do this as long as we don't find matching comment ends
+ while((title || script || comment || server) && scriptCode && scriptCodeSize)
+ {
+ // we've found an unmatched comment start
+ if (comment)
+ brokenComments = true;
+ else if (server)
+ brokenServer = true;
+ else if (script)
+ brokenScript = true;
+
+ checkScriptBuffer();
+ scriptCode[ scriptCodeSize ] = 0;
+ scriptCode[ scriptCodeSize + 1 ] = 0;
+ int pos;
+ QString food;
+ if (title || style || script)
+ food.setUnicode(scriptCode, scriptCodeSize);
+ else if (server) {
+ food = "<";
+ food += QString(scriptCode, scriptCodeSize);
+ }
+ else {
+ pos = QConstString(scriptCode, scriptCodeSize).string().find('>');
+ food.setUnicode(scriptCode+pos+1, scriptCodeSize-pos-1); // deep copy
+ }
+ KHTML_DELETE_QCHAR_VEC(scriptCode);
+ scriptCode = 0;
+ scriptCodeSize = scriptCodeMaxSize = scriptCodeResync = 0;
+ if (script)
+ scriptHandler();
+
+ comment = title = server = script = false;
+ if ( !food.isEmpty() )
+ write(food, true);
+ }
+ // this indicates we will not receive any more data... but if we are waiting on
+ // an external script to load, we can't finish parsing until that is done
+ noMoreData = true;
+ if (cachedScript.isEmpty() && !m_executingScript && !onHold)
+ end(); // this actually causes us to be deleted
+}
+
+void HTMLTokenizer::processToken()
+{
+ KJSProxy *jsProxy = view ? view->part()->jScript() : 0L;
+ if (jsProxy)
+ jsProxy->setEventHandlerLineno(tagStartLineno+1);
+ if ( dest > buffer )
+ {
+#if 0
+ if(currToken.tid) {
+ qDebug( "unexpected token id: %d, str: *%s*", currToken.tid,QConstString( buffer,dest-buffer ).string().latin1() );
+ assert(0);
+ }
+
+#endif
+ currToken.text = new DOMStringImpl( buffer, dest - buffer );
+ currToken.text->ref();
+ currToken.tid = ID_TEXT;
+ }
+ else if(!currToken.tid) {
+ currToken.reset();
+ if (jsProxy)
+ jsProxy->setEventHandlerLineno(lineno+src.lineCount()+1);
+ return;
+ }
+
+ dest = buffer;
+
+#ifdef TOKEN_DEBUG
+ QString name = QString( getTagName(currToken.tid) );
+ QString text;
+ if(currToken.text)
+ text = QConstString(currToken.text->s, currToken.text->l).string();
+
+ kdDebug( 6036 ) << "Token --> " << name << " id = " << currToken.tid << endl;
+ if (currToken.flat)
+ kdDebug( 6036 ) << "Token is FLAT!" << endl;
+ if(!text.isNull())
+ kdDebug( 6036 ) << "text: \"" << text << "\"" << endl;
+ unsigned long l = currToken.attrs ? currToken.attrs->length() : 0;
+ if(l) {
+ kdDebug( 6036 ) << "Attributes: " << l << endl;
+ for (unsigned long i = 0; i < l; ++i) {
+ NodeImpl::Id tid = currToken.attrs->idAt(i);
+ DOMString value = currToken.attrs->valueAt(i);
+ kdDebug( 6036 ) << " " << tid << " " << parser->doc()->getDocument()->getName(NodeImpl::AttributeId, tid).string()
+ << "=\"" << value.string() << "\"" << endl;
+ }
+ }
+ kdDebug( 6036 ) << endl;
+#endif
+
+ // In some cases, parseToken() can cause javascript code to be executed
+ // (for example, when setting an attribute that causes an event handler
+ // to be created). So we need to protect against re-entrancy into the parser
+ m_executingScript++;
+
+ // pass the token over to the parser, the parser DOES NOT delete the token
+ parser->parseToken(&currToken);
+
+ m_executingScript--;
+
+ if ( currToken.flat && currToken.tid != ID_TEXT && !parser->noSpaces() )
+ discard = NoneDiscard;
+
+ currToken.reset();
+ if (jsProxy)
+ jsProxy->setEventHandlerLineno(1);
+}
+
+
+HTMLTokenizer::~HTMLTokenizer()
+{
+ reset();
+ delete parser;
+}
+
+
+void HTMLTokenizer::enlargeBuffer(int len)
+{
+ int newsize = kMax(size*2, size+len);
+ int oldoffs = (dest - buffer);
+
+ buffer = KHTML_REALLOC_QCHAR_VEC(buffer, newsize);
+ dest = buffer + oldoffs;
+ size = newsize;
+}
+
+void HTMLTokenizer::enlargeScriptBuffer(int len)
+{
+ int newsize = kMax(scriptCodeMaxSize*2, scriptCodeMaxSize+len);
+ scriptCode = KHTML_REALLOC_QCHAR_VEC(scriptCode, newsize);
+ scriptCodeMaxSize = newsize;
+}
+
+void HTMLTokenizer::notifyFinished(CachedObject* /*finishedObj*/)
+{
+ assert(!cachedScript.isEmpty());
+ bool done = false;
+ while (!done && cachedScript.head()->isLoaded()) {
+
+ kdDebug( 6036 ) << "Finished loading an external script" << endl;
+
+ CachedScript* cs = cachedScript.dequeue();
+ DOMString scriptSource = cs->script();
+#ifdef TOKEN_DEBUG
+ kdDebug( 6036 ) << "External script is:" << endl << scriptSource.string() << endl;
+#endif
+ setSrc(TokenizerString());
+
+ // make sure we forget about the script before we execute the new one
+ // infinite recursion might happen otherwise
+ QString cachedScriptUrl( cs->url().string() );
+ cs->deref(this);
+
+ scriptExecution( scriptSource.string(), cachedScriptUrl );
+
+ done = cachedScript.isEmpty();
+
+ // 'script' is true when we are called synchronously from
+ // scriptHandler(). In that case scriptHandler() will take care
+ // of 'scriptOutput'.
+ if ( !script ) {
+ while (pendingQueue.count() > 1) {
+ TokenizerString t = pendingQueue.pop();
+ pendingQueue.top().prepend( t );
+ }
+ if (done) {
+ write(pendingQueue.pop(), false);
+ }
+ // we might be deleted at this point, do not
+ // access any members.
+ }
+ }
+}
+
+bool HTMLTokenizer::isWaitingForScripts() const
+{
+ return cachedScript.count();
+}
+
+bool HTMLTokenizer::isExecutingScript() const
+{
+ return (m_executingScript > 0);
+}
+
+void HTMLTokenizer::setSrc(const TokenizerString& source)
+{
+ lineno += src.lineCount();
+ src = source;
+ src.resetLineCount();
+}
+
+void HTMLTokenizer::setOnHold(bool _onHold)
+{
+ if (onHold == _onHold) return;
+ onHold = _onHold;
+}
+
diff --git a/khtml/html/htmltokenizer.h b/khtml/html/htmltokenizer.h
new file mode 100644
index 000000000..5e4186d58
--- /dev/null
+++ b/khtml/html/htmltokenizer.h
@@ -0,0 +1,358 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1997 Torben Weis (weis@kde.org)
+ (C) 1998 Waldo Bastian (bastian@kde.org)
+ (C) 2001 Dirk Mueller (mueller@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- Tokenizers
+
+#ifndef HTMLTOKENIZER_H
+#define HTMLTOKENIZER_H
+
+#include <qstring.h>
+#include <qobject.h>
+#include <qptrqueue.h>
+
+#include "misc/loader_client.h"
+#include "misc/htmltags.h"
+#include "misc/stringit.h"
+#include "xml/dom_stringimpl.h"
+#include "xml/xml_tokenizer.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_docimpl.h"
+
+class KCharsets;
+class KHTMLView;
+
+namespace DOM {
+ class DocumentImpl;
+ class DocumentFragmentImpl;
+}
+
+namespace khtml {
+ class CachedScript;
+ class KHTMLParser;
+
+ /**
+ * @internal
+ * represents one HTML tag. Consists of a numerical id, and the list
+ * of attributes. Can also represent text. In this case the id = 0 and
+ * text contains the text.
+ */
+ class Token
+ {
+ public:
+ Token() {
+ tid = 0;
+ attrs = 0;
+ text = 0;
+ flat = false;
+ //qDebug("new token, creating %08lx", attrs);
+ }
+ ~Token() {
+ if(attrs) attrs->deref();
+ if(text) text->deref();
+ }
+ void addAttribute(DocumentImpl* doc, QChar* buffer, const QString& attrName, const DOMString& v)
+ {
+ DOMStringImpl *value = 0;
+ NodeImpl::Id tid = 0;
+ if(buffer->unicode()) {
+ tid = buffer->unicode();
+ value = v.implementation();
+ }
+ else if ( !attrName.isEmpty() && attrName != "/" ) {
+ tid = doc->getId(NodeImpl::AttributeId, DOMString(attrName).implementation(), false, true);
+ value = v.implementation();
+ }
+
+ if (value && tid) {
+ if(!attrs) {
+ attrs = new DOM::NamedAttrMapImpl(0);
+ attrs->ref();
+ }
+ if (!attrs->getValue(tid))
+ attrs->setValue(tid,value);
+ }
+ }
+ void reset()
+ {
+ if(attrs) {
+ attrs->deref();
+ attrs = 0;
+ }
+ tid = 0;
+ if(text) {
+ text->deref();
+ text = 0;
+ }
+ flat = false;
+ }
+ DOM::NamedAttrMapImpl* attrs;
+ DOMStringImpl* text;
+ ushort tid;
+ bool flat;
+ };
+
+// The count of spaces used for each tab.
+#define TAB_SIZE 8
+
+//-----------------------------------------------------------------------------
+
+class HTMLTokenizer : public Tokenizer, public CachedObjectClient
+{
+ friend class KHTMLParser;
+public:
+ HTMLTokenizer(DOM::DocumentImpl *, KHTMLView * = 0);
+ HTMLTokenizer(DOM::DocumentImpl *, DOM::DocumentFragmentImpl *frag);
+ virtual ~HTMLTokenizer();
+
+ void begin();
+ void write( const khtml::TokenizerString &str, bool appendData );
+ void end();
+ void finish();
+ void timerEvent( QTimerEvent *e );
+ virtual void setOnHold(bool _onHold);
+ void abort() { m_abort = true; }
+ virtual void setAutoClose(bool b=true);
+ virtual bool isWaitingForScripts() const;
+ virtual bool isExecutingScript() const;
+
+protected:
+ void reset();
+ void addPending();
+ void processToken();
+ void processListing(khtml::TokenizerString list);
+
+ void parseComment(khtml::TokenizerString &str);
+ void parseServer(khtml::TokenizerString &str);
+ void parseText(khtml::TokenizerString &str);
+ void parseListing(khtml::TokenizerString &str);
+ void parseSpecial(khtml::TokenizerString &str);
+ void parseTag(khtml::TokenizerString &str);
+ void parseEntity(khtml::TokenizerString &str, QChar *&dest, bool start = false);
+ void parseProcessingInstruction(khtml::TokenizerString &str);
+ void scriptHandler();
+ void scriptExecution(const QString& script, const QString& scriptURL = QString::null, int baseLine = 0);
+ void setSrc(const TokenizerString& source);
+
+ // check if we have enough space in the buffer.
+ // if not enlarge it
+ inline void checkBuffer(int len = 10)
+ {
+ if ( (dest - buffer) > size-len )
+ enlargeBuffer(len);
+ }
+ inline void checkScriptBuffer(int len = 10)
+ {
+ if ( scriptCodeSize + len >= scriptCodeMaxSize )
+ enlargeScriptBuffer(len);
+ }
+
+ void enlargeBuffer(int len);
+ void enlargeScriptBuffer(int len);
+
+ // from CachedObjectClient
+ void notifyFinished(khtml::CachedObject *finishedObj);
+
+protected:
+ // Internal buffers
+ ///////////////////
+ QChar *buffer;
+ QChar *dest;
+
+ khtml::Token currToken;
+
+ // the size of buffer
+ int size;
+
+ // Tokenizer flags
+ //////////////////
+ // are we in quotes within a html tag
+ enum
+ {
+ NoQuote = 0,
+ SingleQuote,
+ DoubleQuote
+ } tquote;
+
+ enum
+ {
+ NonePending = 0,
+ SpacePending,
+ LFPending,
+ TabPending
+ } pending;
+
+ enum
+ {
+ NoneDiscard = 0,
+ SpaceDiscard, // Discard spaces after '=' within tags
+ LFDiscard, // Discard line breaks immediately after start-tags
+ AllDiscard // discard all spaces, LF's etc until next non white char
+ } discard;
+
+ // Discard the LF part of CRLF sequence
+ bool skipLF;
+
+ // Flag to say that we have the '<' but not the character following it.
+ bool startTag;
+
+ // Flag to say, we are just parsing a tag, meaning, we are in the middle
+ // of <tag...
+ enum {
+ NoTag = 0,
+ TagName,
+ SearchAttribute,
+ AttributeName,
+ SearchEqual,
+ SearchValue,
+ QuotedValue,
+ Value,
+ SearchEnd
+ } tag;
+
+ // Are we in a &... character entity description?
+ enum {
+ NoEntity = 0,
+ SearchEntity,
+ NumericSearch,
+ Hexadecimal,
+ Decimal,
+ EntityName,
+ SearchSemicolon
+ } Entity;
+
+ // are we in a <script> ... </script> block
+ bool script;
+
+ QChar EntityChar;
+
+ // Are we in a <pre> ... </pre> block
+ bool pre;
+
+ // if 'pre == true' we track in which column we are
+ int prePos;
+
+ // Are we in a <style> ... </style> block
+ bool style;
+
+ // Are we in a <select> ... </select> block
+ bool select;
+
+ // Are we in a <xmp> ... </xmp> block
+ bool xmp;
+
+ // Are we in a <title> ... </title> block
+ bool title;
+
+ // Are we in plain textmode ?
+ bool plaintext;
+
+ // XML processing instructions. Ignored at the moment
+ bool processingInstruction;
+
+ // Area we in a <!-- comment --> block
+ bool comment;
+
+ // Are we in a <textarea> ... </textarea> block
+ bool textarea;
+
+ // was the previous character escaped ?
+ bool escaped;
+
+ // are we in a server includes statement?
+ bool server;
+
+ bool brokenServer;
+
+ bool brokenScript;
+
+ // name of an unknown attribute
+ QString attrName;
+
+ // Used to store the code of a srcipting sequence
+ QChar *scriptCode;
+ // Size of the script sequenze stored in scriptCode
+ int scriptCodeSize;
+ // Maximal size that can be stored in scriptCode
+ int scriptCodeMaxSize;
+ // resync point of script code size
+ int scriptCodeResync;
+
+ // Stores characters if we are scanning for a string like "</script>"
+ QChar searchBuffer[ 10 ];
+ // Counts where we are in the string we are scanning for
+ int searchCount;
+ // The string we are searching for
+ const QChar *searchFor;
+ // the stopper string
+ const char* searchStopper;
+ // the stopper len
+ int searchStopperLen;
+ // if no more data is coming, just parse what we have (including ext scripts that
+ // may be still downloading) and finish
+ bool noMoreData;
+ // URL to get source code of script from
+ QString scriptSrc;
+ QString scriptSrcCharset;
+ bool javascript;
+ // the HTML code we will parse after the external script we are waiting for has loaded
+ TokenizerQueue pendingQueue;
+ // true if we are executing a script while parsing a document. This causes the parsing of
+ // the output of the script to be postponed until after the script has finished executing
+ int m_executingScript;
+ QPtrQueue<khtml::CachedScript> cachedScript;
+ // you can pause the tokenizer if you need to display a dialog or something
+ bool onHold;
+ // you can ask the tokenizer to abort the current write() call, e.g. to redirect somewhere else
+ bool m_abort;
+
+ // if we found one broken comment, there are most likely others as well
+ // store a flag to get rid of the O(n^2) behavior in such a case.
+ bool brokenComments;
+ // current line number
+ int lineno;
+ // line number at which the current <script> started
+ int scriptStartLineno;
+ int tagStartLineno;
+ // autoClose mode is used when the tokenizer was created by a script document.writing
+ // on an already loaded document
+ int m_autoCloseTimer;
+
+#define CBUFLEN 1024
+ char cBuffer[CBUFLEN+2];
+ unsigned int cBufferPos;
+ unsigned int entityLen;
+
+ khtml::TokenizerString src;
+
+ KCharsets *charsets;
+ KHTMLParser *parser;
+
+ KHTMLView *view;
+};
+
+} // namespace
+
+#endif // HTMLTOKENIZER
+