summaryrefslogtreecommitdiffstats
path: root/tdehtml
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-01-26 13:17:21 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-01-26 13:17:21 -0600
commitdfe289850f068f19ba4a83ab4e7e22a7e09c13c9 (patch)
treec297348a55df66c571de4525646e0b9762427353 /tdehtml
parentb7658a0d5eca24a9d37c6e04f88298ef02389db0 (diff)
downloadtdelibs-dfe289850f068f19ba4a83ab4e7e22a7e09c13c9.tar.gz
tdelibs-dfe289850f068f19ba4a83ab4e7e22a7e09c13c9.zip
Rename a number of libraries and executables to avoid conflicts with KDE4
Diffstat (limited to 'tdehtml')
-rw-r--r--tdehtml/.emacs-dirvars9
-rw-r--r--tdehtml/CMakeLists.txt137
-rw-r--r--tdehtml/ChangeLog3874
-rw-r--r--tdehtml/DESIGN.html346
-rw-r--r--tdehtml/Mainpage.dox46
-rw-r--r--tdehtml/Makefile.am133
-rw-r--r--tdehtml/README.HTMLWidget66
-rw-r--r--tdehtml/SAFARI_MERGE161
-rw-r--r--tdehtml/TODO60
-rw-r--r--tdehtml/configure.in.in57
-rw-r--r--tdehtml/css/CMakeLists.txt47
-rw-r--r--tdehtml/css/Makefile.am60
-rw-r--r--tdehtml/css/css_base.cpp419
-rw-r--r--tdehtml/css/css_base.h271
-rw-r--r--tdehtml/css/css_extensionsimpl.cpp366
-rw-r--r--tdehtml/css/css_extensionsimpl.h205
-rw-r--r--tdehtml/css/css_renderstyledeclarationimpl.cpp1147
-rw-r--r--tdehtml/css/css_renderstyledeclarationimpl.h75
-rw-r--r--tdehtml/css/css_ruleimpl.cpp391
-rw-r--r--tdehtml/css/css_ruleimpl.h237
-rw-r--r--tdehtml/css/css_stylesheetimpl.cpp436
-rw-r--r--tdehtml/css/css_stylesheetimpl.h192
-rw-r--r--tdehtml/css/css_valueimpl.cpp1073
-rw-r--r--tdehtml/css/css_valueimpl.h461
-rw-r--r--tdehtml/css/csshelper.cpp87
-rw-r--r--tdehtml/css/csshelper.h51
-rw-r--r--tdehtml/css/cssparser.cpp2614
-rw-r--r--tdehtml/css/cssparser.h201
-rw-r--r--tdehtml/css/cssproperties.c678
-rw-r--r--tdehtml/css/cssproperties.h144
-rw-r--r--tdehtml/css/cssproperties.in148
-rw-r--r--tdehtml/css/cssstyleselector.cpp4217
-rw-r--r--tdehtml/css/cssstyleselector.h333
-rw-r--r--tdehtml/css/cssvalues.c1344
-rw-r--r--tdehtml/css/cssvalues.h290
-rw-r--r--tdehtml/css/cssvalues.in478
-rw-r--r--tdehtml/css/html4.css549
-rw-r--r--tdehtml/css/makeprop57
-rwxr-xr-xtdehtml/css/makevalues63
-rw-r--r--tdehtml/css/parser.cpp2875
-rw-r--r--tdehtml/css/parser.h164
-rw-r--r--tdehtml/css/parser.y1064
-rw-r--r--tdehtml/css/quirks.css41
-rw-r--r--tdehtml/css/tokenizer.cpp930
-rw-r--r--tdehtml/css/tokenizer.flex92
-rw-r--r--tdehtml/design.h58
-rw-r--r--tdehtml/dom/CMakeLists.txt58
-rw-r--r--tdehtml/dom/Makefile.am58
-rw-r--r--tdehtml/dom/css_extensions.cpp2043
-rw-r--r--tdehtml/dom/css_extensions.h2702
-rw-r--r--tdehtml/dom/css_rule.cpp546
-rw-r--r--tdehtml/dom/css_rule.h534
-rw-r--r--tdehtml/dom/css_stylesheet.cpp457
-rw-r--r--tdehtml/dom/css_stylesheet.h496
-rw-r--r--tdehtml/dom/css_value.cpp587
-rw-r--r--tdehtml/dom/css_value.h745
-rw-r--r--tdehtml/dom/dom2_events.cpp725
-rw-r--r--tdehtml/dom/dom2_events.h846
-rw-r--r--tdehtml/dom/dom2_range.cpp406
-rw-r--r--tdehtml/dom/dom2_range.h475
-rw-r--r--tdehtml/dom/dom2_traversal.cpp381
-rw-r--r--tdehtml/dom/dom2_traversal.h617
-rw-r--r--tdehtml/dom/dom2_views.cpp95
-rw-r--r--tdehtml/dom/dom2_views.h90
-rw-r--r--tdehtml/dom/dom_core.h34
-rw-r--r--tdehtml/dom/dom_doc.cpp684
-rw-r--r--tdehtml/dom/dom_doc.h1107
-rw-r--r--tdehtml/dom/dom_element.cpp409
-rw-r--r--tdehtml/dom/dom_element.h600
-rw-r--r--tdehtml/dom/dom_exception.h92
-rw-r--r--tdehtml/dom/dom_html.h40
-rw-r--r--tdehtml/dom/dom_misc.cpp37
-rw-r--r--tdehtml/dom/dom_misc.h60
-rw-r--r--tdehtml/dom/dom_node.cpp495
-rw-r--r--tdehtml/dom/dom_node.h991
-rw-r--r--tdehtml/dom/dom_string.cpp300
-rw-r--r--tdehtml/dom/dom_string.h144
-rw-r--r--tdehtml/dom/dom_text.cpp237
-rw-r--r--tdehtml/dom/dom_text.h312
-rw-r--r--tdehtml/dom/dom_xml.cpp293
-rw-r--r--tdehtml/dom/dom_xml.h310
-rw-r--r--tdehtml/dom/html_base.cpp533
-rw-r--r--tdehtml/dom/html_base.h610
-rw-r--r--tdehtml/dom/html_block.cpp443
-rw-r--r--tdehtml/dom/html_block.h406
-rw-r--r--tdehtml/dom/html_document.cpp233
-rw-r--r--tdehtml/dom/html_document.h304
-rw-r--r--tdehtml/dom/html_element.cpp186
-rw-r--r--tdehtml/dom/html_element.h221
-rw-r--r--tdehtml/dom/html_form.cpp1302
-rw-r--r--tdehtml/dom/html_form.h1427
-rw-r--r--tdehtml/dom/html_head.cpp515
-rw-r--r--tdehtml/dom/html_head.h552
-rw-r--r--tdehtml/dom/html_image.cpp413
-rw-r--r--tdehtml/dom/html_image.h431
-rw-r--r--tdehtml/dom/html_inline.cpp434
-rw-r--r--tdehtml/dom/html_inline.h463
-rw-r--r--tdehtml/dom/html_list.cpp354
-rw-r--r--tdehtml/dom/html_list.h341
-rw-r--r--tdehtml/dom/html_misc.cpp214
-rw-r--r--tdehtml/dom/html_misc.h222
-rw-r--r--tdehtml/dom/html_object.cpp535
-rw-r--r--tdehtml/dom/html_object.h630
-rw-r--r--tdehtml/dom/html_table.cpp868
-rw-r--r--tdehtml/dom/html_table.h997
-rw-r--r--tdehtml/domtreeview.cpp97
-rw-r--r--tdehtml/domtreeview.h54
-rw-r--r--tdehtml/ecma/AUTHORS4
-rw-r--r--tdehtml/ecma/CMakeLists.txt61
-rw-r--r--tdehtml/ecma/Makefile.am90
-rw-r--r--tdehtml/ecma/README21
-rw-r--r--tdehtml/ecma/THANKS9
-rw-r--r--tdehtml/ecma/TODO12
-rw-r--r--tdehtml/ecma/domparser.cpp112
-rw-r--r--tdehtml/ecma/domparser.h58
-rw-r--r--tdehtml/ecma/jsk.html113
-rw-r--r--tdehtml/ecma/kjs_binding.cpp467
-rw-r--r--tdehtml/ecma/kjs_binding.h409
-rw-r--r--tdehtml/ecma/kjs_css.cpp1302
-rw-r--r--tdehtml/ecma/kjs_css.h304
-rw-r--r--tdehtml/ecma/kjs_debugwin.cpp1139
-rw-r--r--tdehtml/ecma/kjs_debugwin.h285
-rw-r--r--tdehtml/ecma/kjs_dom.cpp1849
-rw-r--r--tdehtml/ecma/kjs_dom.h299
-rw-r--r--tdehtml/ecma/kjs_events.cpp993
-rw-r--r--tdehtml/ecma/kjs_events.h250
-rw-r--r--tdehtml/ecma/kjs_html.cpp3946
-rw-r--r--tdehtml/ecma/kjs_html.h294
-rw-r--r--tdehtml/ecma/kjs_mozilla.cpp94
-rw-r--r--tdehtml/ecma/kjs_mozilla.h44
-rw-r--r--tdehtml/ecma/kjs_navigator.cpp670
-rw-r--r--tdehtml/ecma/kjs_navigator.h53
-rw-r--r--tdehtml/ecma/kjs_proxy.cpp411
-rw-r--r--tdehtml/ecma/kjs_proxy.h91
-rw-r--r--tdehtml/ecma/kjs_range.cpp233
-rw-r--r--tdehtml/ecma/kjs_range.h71
-rw-r--r--tdehtml/ecma/kjs_traversal.cpp327
-rw-r--r--tdehtml/ecma/kjs_traversal.h108
-rw-r--r--tdehtml/ecma/kjs_views.cpp91
-rw-r--r--tdehtml/ecma/kjs_views.h53
-rw-r--r--tdehtml/ecma/kjs_window.cpp2935
-rw-r--r--tdehtml/ecma/kjs_window.h309
-rw-r--r--tdehtml/ecma/testecma.cpp67
-rw-r--r--tdehtml/ecma/xmlhttprequest.cpp810
-rw-r--r--tdehtml/ecma/xmlhttprequest.h142
-rw-r--r--tdehtml/ecma/xmlserializer.cpp109
-rw-r--r--tdehtml/ecma/xmlserializer.h54
-rw-r--r--tdehtml/html/AlwaysInline.h49
-rw-r--r--tdehtml/html/CMakeLists.txt44
-rw-r--r--tdehtml/html/Makefile.am54
-rw-r--r--tdehtml/html/Platform.h218
-rw-r--r--tdehtml/html/RefPtr.h202
-rw-r--r--tdehtml/html/doctypes.cpp1174
-rw-r--r--tdehtml/html/doctypes.gperf91
-rw-r--r--tdehtml/html/dtd.cpp918
-rw-r--r--tdehtml/html/dtd.dtd1072
-rw-r--r--tdehtml/html/dtd.h41
-rw-r--r--tdehtml/html/html_baseimpl.cpp708
-rw-r--r--tdehtml/html/html_baseimpl.h207
-rw-r--r--tdehtml/html/html_blockimpl.cpp371
-rw-r--r--tdehtml/html/html_blockimpl.h108
-rw-r--r--tdehtml/html/html_documentimpl.cpp537
-rw-r--r--tdehtml/html/html_documentimpl.h95
-rw-r--r--tdehtml/html/html_elementimpl.cpp685
-rw-r--r--tdehtml/html/html_elementimpl.h89
-rw-r--r--tdehtml/html/html_formimpl.cpp2980
-rw-r--r--tdehtml/html/html_formimpl.h606
-rw-r--r--tdehtml/html/html_headimpl.cpp649
-rw-r--r--tdehtml/html/html_headimpl.h233
-rw-r--r--tdehtml/html/html_imageimpl.cpp560
-rw-r--r--tdehtml/html/html_imageimpl.h150
-rw-r--r--tdehtml/html/html_inlineimpl.cpp298
-rw-r--r--tdehtml/html/html_inlineimpl.h75
-rw-r--r--tdehtml/html/html_listimpl.cpp169
-rw-r--r--tdehtml/html/html_listimpl.h112
-rw-r--r--tdehtml/html/html_miscimpl.cpp443
-rw-r--r--tdehtml/html/html_miscimpl.h150
-rw-r--r--tdehtml/html/html_objectimpl.cpp465
-rw-r--r--tdehtml/html/html_objectimpl.h145
-rw-r--r--tdehtml/html/html_tableimpl.cpp994
-rw-r--r--tdehtml/html/html_tableimpl.h329
-rw-r--r--tdehtml/html/htmlparser.cpp1731
-rw-r--r--tdehtml/html/htmlparser.h192
-rw-r--r--tdehtml/html/htmltokenizer.cpp1798
-rw-r--r--tdehtml/html/htmltokenizer.h358
-rw-r--r--tdehtml/htmlpageinfo.ui301
-rw-r--r--tdehtml/java/CMakeLists.txt76
-rw-r--r--tdehtml/java/ChangeLog19
-rw-r--r--tdehtml/java/KJAS_GRAMMAR.txt82
-rw-r--r--tdehtml/java/Makefile.am37
-rw-r--r--tdehtml/java/README20
-rw-r--r--tdehtml/java/TODO22
-rw-r--r--tdehtml/java/build.properties9
-rw-r--r--tdehtml/java/build.xml49
-rw-r--r--tdehtml/java/configure.in.in5
-rw-r--r--tdehtml/java/cr16-action-java.pngbin0 -> 1051 bytes
-rw-r--r--tdehtml/java/dummy/CMakeLists.txt30
-rw-r--r--tdehtml/java/dummy/Makefile.am13
-rw-r--r--tdehtml/java/images/animbean.gifbin0 -> 4376 bytes
-rw-r--r--tdehtml/java/images/beanicon.pngbin0 -> 569 bytes
-rw-r--r--tdehtml/java/images/brokenbean.gifbin0 -> 1195 bytes
-rw-r--r--tdehtml/java/kjava.jarbin0 -> 157645 bytes
-rw-r--r--tdehtml/java/kjava.policy.in8
-rw-r--r--tdehtml/java/kjavaapplet.cpp288
-rw-r--r--tdehtml/java/kjavaapplet.h251
-rw-r--r--tdehtml/java/kjavaappletcontext.cpp274
-rw-r--r--tdehtml/java/kjavaappletcontext.h141
-rw-r--r--tdehtml/java/kjavaappletserver.cpp833
-rw-r--r--tdehtml/java/kjavaappletserver.h180
-rw-r--r--tdehtml/java/kjavaappletviewer.cpp635
-rw-r--r--tdehtml/java/kjavaappletviewer.desktop82
-rw-r--r--tdehtml/java/kjavaappletviewer.h145
-rw-r--r--tdehtml/java/kjavaappletwidget.cpp140
-rw-r--r--tdehtml/java/kjavaappletwidget.h125
-rw-r--r--tdehtml/java/kjavadownloader.cpp298
-rw-r--r--tdehtml/java/kjavadownloader.h90
-rw-r--r--tdehtml/java/kjavaprocess.cpp397
-rw-r--r--tdehtml/java/kjavaprocess.h164
-rw-r--r--tdehtml/java/kqeventutil.cpp200
-rw-r--r--tdehtml/java/kqeventutil.h34
-rw-r--r--tdehtml/java/kxeventutil.cpp408
-rw-r--r--tdehtml/java/kxeventutil.h51
-rwxr-xr-xtdehtml/java/make-jar12
-rw-r--r--tdehtml/java/netscape/javascript/JSException.java20
-rw-r--r--tdehtml/java/netscape/javascript/JSObject.java21
-rw-r--r--tdehtml/java/netscape/plugin/Plugin.java28
-rw-r--r--tdehtml/java/netscape/security/ForbiddenTargetException.java10
-rw-r--r--tdehtml/java/netscape/security/Principal.java4
-rw-r--r--tdehtml/java/netscape/security/PrivilegeManager.java109
-rw-r--r--tdehtml/java/netscape/security/Target.java4
-rw-r--r--tdehtml/java/org/kde/javascript/JSObject.java183
-rw-r--r--tdehtml/java/org/kde/kjas/server/Console.java20
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASAppletClassLoader.java360
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASAppletContext.java473
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASAppletPanel.java113
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASAppletStub.java807
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASAudioClip.java98
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java132
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASConsole.java93
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASConsoleStream.java46
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASProtocolHandler.java900
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASSecurityManager.java243
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASSoundPlayer.java36
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASSwingConsole.java325
-rw-r--r--tdehtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java609
-rw-r--r--tdehtml/java/org/kde/kjas/server/Main.java178
-rw-r--r--tdehtml/java/org/kde/kjas/server/StatusListener.java5
-rw-r--r--tdehtml/java/pluginsinfo7
-rw-r--r--tdehtml/java/tests/Makefile.am9
-rw-r--r--tdehtml/java/tests/badapplets/BadApplet.jarbin0 -> 7233 bytes
-rw-r--r--tdehtml/java/tests/badapplets/BadApplet.java202
-rw-r--r--tdehtml/java/tests/badapplets/applet.html14
-rw-r--r--tdehtml/java/tests/good_sites44
-rw-r--r--tdehtml/java/tests/testkjavaappletserver.cpp41
-rw-r--r--tdehtml/kjserrordlg.ui133
-rw-r--r--tdehtml/kjserrordlg.ui.h32
-rw-r--r--tdehtml/libtdehtml.map22
-rw-r--r--tdehtml/misc/CMakeLists.txt41
-rw-r--r--tdehtml/misc/Makefile.am43
-rw-r--r--tdehtml/misc/arena.cpp333
-rw-r--r--tdehtml/misc/arena.h123
-rw-r--r--tdehtml/misc/blocked_icon.cpp41
-rw-r--r--tdehtml/misc/blocked_icon.pngbin0 -> 599 bytes
-rw-r--r--tdehtml/misc/decoder.cpp790
-rw-r--r--tdehtml/misc/decoder.h115
-rw-r--r--tdehtml/misc/guess_ja.cpp379
-rw-r--r--tdehtml/misc/guess_ja.h122
-rw-r--r--tdehtml/misc/helper.cpp144
-rw-r--r--tdehtml/misc/helper.h55
-rw-r--r--tdehtml/misc/htmlattrs.c1019
-rw-r--r--tdehtml/misc/htmlattrs.h168
-rw-r--r--tdehtml/misc/htmlattrs.in157
-rw-r--r--tdehtml/misc/htmlhashes.cpp45
-rw-r--r--tdehtml/misc/htmlhashes.h14
-rw-r--r--tdehtml/misc/htmltags.c687
-rw-r--r--tdehtml/misc/htmltags.h119
-rw-r--r--tdehtml/misc/htmltags.in102
-rw-r--r--tdehtml/misc/knsplugininstaller.cpp671
-rw-r--r--tdehtml/misc/knsplugininstaller.h268
-rw-r--r--tdehtml/misc/loader.cpp1679
-rw-r--r--tdehtml/misc/loader.h522
-rw-r--r--tdehtml/misc/loader_client.h35
-rw-r--r--tdehtml/misc/loader_jpeg.cpp548
-rw-r--r--tdehtml/misc/loader_jpeg.h50
-rw-r--r--tdehtml/misc/makeattrs113
-rw-r--r--tdehtml/misc/maketags124
-rw-r--r--tdehtml/misc/multimap.h345
-rw-r--r--tdehtml/misc/seed.h46
-rw-r--r--tdehtml/misc/shared.h227
-rw-r--r--tdehtml/misc/stringit.cpp138
-rw-r--r--tdehtml/misc/stringit.h203
-rw-r--r--tdehtml/misc/tdehtmllayout.h112
-rw-r--r--tdehtml/pics/CMakeLists.txt20
-rw-r--r--tdehtml/pics/Makefile.am10
-rw-r--r--tdehtml/pics/cr128-action-bug.pngbin0 -> 13453 bytes
-rw-r--r--tdehtml/pics/cr16-action-bug.pngbin0 -> 1107 bytes
-rw-r--r--tdehtml/pics/cr16-action-images_display.pngbin0 -> 539 bytes
-rw-r--r--tdehtml/pics/cr16-action-wallet_open.pngbin0 -> 781 bytes
-rw-r--r--tdehtml/pics/cr22-action-bug.pngbin0 -> 1914 bytes
-rw-r--r--tdehtml/pics/cr22-action-dbgnext.pngbin0 -> 187 bytes
-rw-r--r--tdehtml/pics/cr22-action-dbgrun.pngbin0 -> 244 bytes
-rw-r--r--tdehtml/pics/cr22-action-dbgrunto.pngbin0 -> 275 bytes
-rw-r--r--tdehtml/pics/cr22-action-dbgstep.pngbin0 -> 182 bytes
-rw-r--r--tdehtml/pics/cr22-action-images_display.pngbin0 -> 1270 bytes
-rw-r--r--tdehtml/pics/cr32-action-bug.pngbin0 -> 2994 bytes
-rw-r--r--tdehtml/pics/cr32-action-images_display.pngbin0 -> 2191 bytes
-rw-r--r--tdehtml/pics/cr48-action-bug.pngbin0 -> 5091 bytes
-rw-r--r--tdehtml/pics/cr64-action-bug.pngbin0 -> 7630 bytes
-rw-r--r--tdehtml/rendering/CMakeLists.txt46
-rw-r--r--tdehtml/rendering/Makefile.am57
-rw-r--r--tdehtml/rendering/bidi.cpp2250
-rw-r--r--tdehtml/rendering/bidi.h172
-rw-r--r--tdehtml/rendering/break_lines.cpp126
-rw-r--r--tdehtml/rendering/break_lines.h163
-rw-r--r--tdehtml/rendering/counter_tree.cpp222
-rw-r--r--tdehtml/rendering/counter_tree.h114
-rw-r--r--tdehtml/rendering/enumerate.cpp411
-rw-r--r--tdehtml/rendering/enumerate.h66
-rw-r--r--tdehtml/rendering/font.cpp502
-rw-r--r--tdehtml/rendering/font.h188
-rw-r--r--tdehtml/rendering/img-loading.pngbin0 -> 318 bytes
-rw-r--r--tdehtml/rendering/loading_icon.cpp25
-rw-r--r--tdehtml/rendering/render_applet.cpp145
-rw-r--r--tdehtml/rendering/render_applet.h60
-rw-r--r--tdehtml/rendering/render_arena.cpp146
-rw-r--r--tdehtml/rendering/render_arena.h72
-rw-r--r--tdehtml/rendering/render_block.cpp3155
-rw-r--r--tdehtml/rendering/render_block.h378
-rw-r--r--tdehtml/rendering/render_body.cpp121
-rw-r--r--tdehtml/rendering/render_body.h56
-rw-r--r--tdehtml/rendering/render_box.cpp2325
-rw-r--r--tdehtml/rendering/render_box.h213
-rw-r--r--tdehtml/rendering/render_br.cpp79
-rw-r--r--tdehtml/rendering/render_br.h77
-rw-r--r--tdehtml/rendering/render_canvas.cpp780
-rw-r--r--tdehtml/rendering/render_canvas.h250
-rw-r--r--tdehtml/rendering/render_container.cpp597
-rw-r--r--tdehtml/rendering/render_container.h85
-rw-r--r--tdehtml/rendering/render_flow.cpp412
-rw-r--r--tdehtml/rendering/render_flow.h96
-rw-r--r--tdehtml/rendering/render_form.cpp1914
-rw-r--r--tdehtml/rendering/render_form.h511
-rw-r--r--tdehtml/rendering/render_frames.cpp1025
-rw-r--r--tdehtml/rendering/render_frames.h172
-rw-r--r--tdehtml/rendering/render_generated.cpp392
-rw-r--r--tdehtml/rendering/render_generated.h125
-rw-r--r--tdehtml/rendering/render_image.cpp604
-rw-r--r--tdehtml/rendering/render_image.h105
-rw-r--r--tdehtml/rendering/render_inline.cpp935
-rw-r--r--tdehtml/rendering/render_inline.h94
-rw-r--r--tdehtml/rendering/render_layer.cpp1830
-rw-r--r--tdehtml/rendering/render_layer.h342
-rw-r--r--tdehtml/rendering/render_line.cpp996
-rw-r--r--tdehtml/rendering/render_line.h310
-rw-r--r--tdehtml/rendering/render_list.cpp586
-rw-r--r--tdehtml/rendering/render_list.h140
-rw-r--r--tdehtml/rendering/render_object.cpp2330
-rw-r--r--tdehtml/rendering/render_object.h866
-rw-r--r--tdehtml/rendering/render_replaced.cpp940
-rw-r--r--tdehtml/rendering/render_replaced.h169
-rw-r--r--tdehtml/rendering/render_style.cpp1301
-rw-r--r--tdehtml/rendering/render_style.h1524
-rw-r--r--tdehtml/rendering/render_table.cpp3070
-rw-r--r--tdehtml/rendering/render_table.h524
-rw-r--r--tdehtml/rendering/render_text.cpp1546
-rw-r--r--tdehtml/rendering/render_text.h345
-rw-r--r--tdehtml/rendering/table_layout.cpp1193
-rw-r--r--tdehtml/rendering/table_layout.h112
-rw-r--r--tdehtml/rendering/table_layout.txt74
-rw-r--r--tdehtml/tdehtml-devel-gdb22
-rw-r--r--tdehtml/tdehtml.desktop93
-rw-r--r--tdehtml/tdehtml.rc16
-rw-r--r--tdehtml/tdehtml_browser.rc49
-rw-r--r--tdehtml/tdehtml_caret.cpp2664
-rw-r--r--tdehtml/tdehtml_caret_p.h1109
-rw-r--r--tdehtml/tdehtml_events.cpp92
-rw-r--r--tdehtml/tdehtml_events.h157
-rw-r--r--tdehtml/tdehtml_ext.cpp1032
-rw-r--r--tdehtml/tdehtml_ext.h177
-rw-r--r--tdehtml/tdehtml_factory.cpp207
-rw-r--r--tdehtml/tdehtml_factory.h76
-rw-r--r--tdehtml/tdehtml_iface.cc233
-rw-r--r--tdehtml/tdehtml_iface.h242
-rw-r--r--tdehtml/tdehtml_pagecache.cpp313
-rw-r--r--tdehtml/tdehtml_pagecache.h134
-rw-r--r--tdehtml/tdehtml_part.cpp7471
-rw-r--r--tdehtml/tdehtml_part.h1683
-rw-r--r--tdehtml/tdehtml_popupmenu.rc39
-rw-r--r--tdehtml/tdehtml_printsettings.cpp108
-rw-r--r--tdehtml/tdehtml_printsettings.h43
-rw-r--r--tdehtml/tdehtml_run.cpp92
-rw-r--r--tdehtml/tdehtml_run.h59
-rw-r--r--tdehtml/tdehtml_settings.cc1064
-rw-r--r--tdehtml/tdehtml_settings.h232
-rw-r--r--tdehtml/tdehtmldefaults.h33
-rw-r--r--tdehtml/tdehtmlimage.cpp357
-rw-r--r--tdehtml/tdehtmlimage.desktop170
-rw-r--r--tdehtml/tdehtmlimage.h119
-rw-r--r--tdehtml/tdehtmlpart_p.h569
-rw-r--r--tdehtml/tdehtmlview.cpp4623
-rw-r--r--tdehtml/tdehtmlview.h624
-rw-r--r--tdehtml/tdemultipart/CMakeLists.txt48
-rw-r--r--tdehtml/tdemultipart/Makefile.am17
-rw-r--r--tdehtml/tdemultipart/README16
-rw-r--r--tdehtml/tdemultipart/tdemultipart.cpp613
-rw-r--r--tdehtml/tdemultipart/tdemultipart.desktop73
-rw-r--r--tdehtml/tdemultipart/tdemultipart.h118
-rw-r--r--tdehtml/test/README6
-rw-r--r--tdehtml/test/align.html21
-rw-r--r--tdehtml/test/align1.html21
-rw-r--r--tdehtml/test/align2.html126
-rw-r--r--tdehtml/test/anchor1.html25
-rw-r--r--tdehtml/test/anchor2.html85
-rw-r--r--tdehtml/test/button.html14
-rw-r--r--tdehtml/test/color.html60
-rw-r--r--tdehtml/test/fixed-background.html47
-rw-r--r--tdehtml/test/image.gifbin0 -> 1476 bytes
-rw-r--r--tdehtml/test/image_map.html24
-rw-r--r--tdehtml/test/java.html15
-rw-r--r--tdehtml/test/jsplugins.html73
-rw-r--r--tdehtml/test/konqi.gifbin0 -> 39318 bytes
-rw-r--r--tdehtml/test/lake.classbin0 -> 3636 bytes
-rw-r--r--tdehtml/test/lists.html221
-rw-r--r--tdehtml/test/nav_bar.gifbin0 -> 1059 bytes
-rw-r--r--tdehtml/test/nbsp.html20
-rw-r--r--tdehtml/test/object.html4
-rw-r--r--tdehtml/test/pseudo.html27
-rw-r--r--tdehtml/test/testpages.html34
-rw-r--r--tdehtml/test_regression.cpp1644
-rw-r--r--tdehtml/test_regression.h194
-rw-r--r--tdehtml/test_regression_fontoverload.cpp384
-rw-r--r--tdehtml/testtdehtml.cpp210
-rw-r--r--tdehtml/testtdehtml.h55
-rw-r--r--tdehtml/xml/CMakeLists.txt43
-rw-r--r--tdehtml/xml/Makefile.am48
-rw-r--r--tdehtml/xml/dom2_eventsimpl.cpp969
-rw-r--r--tdehtml/xml/dom2_eventsimpl.h513
-rw-r--r--tdehtml/xml/dom2_rangeimpl.cpp1640
-rw-r--r--tdehtml/xml/dom2_rangeimpl.h127
-rw-r--r--tdehtml/xml/dom2_traversalimpl.cpp667
-rw-r--r--tdehtml/xml/dom2_traversalimpl.h196
-rw-r--r--tdehtml/xml/dom2_viewsimpl.cpp50
-rw-r--r--tdehtml/xml/dom2_viewsimpl.h50
-rw-r--r--tdehtml/xml/dom_docimpl.cpp2892
-rw-r--r--tdehtml/xml/dom_docimpl.h763
-rw-r--r--tdehtml/xml/dom_elementimpl.cpp1301
-rw-r--r--tdehtml/xml/dom_elementimpl.h392
-rw-r--r--tdehtml/xml/dom_nodeimpl.cpp2068
-rw-r--r--tdehtml/xml/dom_nodeimpl.h736
-rw-r--r--tdehtml/xml/dom_restyler.cpp122
-rw-r--r--tdehtml/xml/dom_restyler.h102
-rw-r--r--tdehtml/xml/dom_stringimpl.cpp460
-rw-r--r--tdehtml/xml/dom_stringimpl.h104
-rw-r--r--tdehtml/xml/dom_textimpl.cpp522
-rw-r--r--tdehtml/xml/dom_textimpl.h176
-rw-r--r--tdehtml/xml/dom_xmlimpl.cpp498
-rw-r--r--tdehtml/xml/dom_xmlimpl.h181
-rw-r--r--tdehtml/xml/xml_tokenizer.cpp609
-rw-r--r--tdehtml/xml/xml_tokenizer.h198
459 files changed, 196663 insertions, 0 deletions
diff --git a/tdehtml/.emacs-dirvars b/tdehtml/.emacs-dirvars
new file mode 100644
index 000000000..36219bd6b
--- /dev/null
+++ b/tdehtml/.emacs-dirvars
@@ -0,0 +1,9 @@
+;; -*- emacs-lisp -*-
+;;
+;; This file is processed by the dirvars emacs package. Each variable
+;; setting below is performed when this dirvars file is loaded.
+;;
+indent-tabs-mode: nil
+tab-width: 8
+c-basic-offset: 4
+evaluate: (c-set-offset 'innamespace '0)
diff --git a/tdehtml/CMakeLists.txt b/tdehtml/CMakeLists.txt
new file mode 100644
index 000000000..bab7d78e2
--- /dev/null
+++ b/tdehtml/CMakeLists.txt
@@ -0,0 +1,137 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WOVERLOADED_VIRTUAL}" )
+
+add_subdirectory( misc )
+add_subdirectory( dom )
+add_subdirectory( css )
+add_subdirectory( xml )
+add_subdirectory( html )
+add_subdirectory( rendering )
+add_subdirectory( pics )
+add_subdirectory( java )
+add_subdirectory( ecma )
+add_subdirectory( tdemultipart )
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/kjs
+ ${CMAKE_BINARY_DIR}/kio/kssl
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdefx
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/kio/kfile
+ ${CMAKE_SOURCE_DIR}/kio/kssl
+ ${CMAKE_SOURCE_DIR}/tdeutils
+ ${CMAKE_SOURCE_DIR}/tdewallet/client
+ ${CMAKE_SOURCE_DIR}/tdeprint
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### headers ###################################
+
+install( FILES
+ tdehtmlview.h tdehtml_part.h tdehtml_events.h
+ tdehtml_settings.h tdehtmldefaults.h
+ DESTINATION ${INCLUDE_INSTALL_DIR} )
+
+
+##### other data ################################
+
+install( FILES tdehtml.desktop tdehtmlimage.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES tdehtml.rc tdehtml_browser.rc tdehtml_popupmenu.rc DESTINATION ${DATA_INSTALL_DIR}/tdehtml )
+
+
+##### tdehtml #####################################
+
+set( target tdehtml )
+
+set( ${target}_SRCS
+ tdehtmlview.cpp tdehtml_part.cpp tdehtml_run.cpp
+ tdehtml_factory.cpp tdehtml_settings.cc tdehtml_events.cpp
+ tdehtml_ext.cpp tdehtml_pagecache.cpp tdehtml_iface.cc
+ tdehtml_printsettings.cpp tdehtmlimage.cpp kjserrordlg.ui
+ htmlpageinfo.ui tdehtml_iface.skel
+)
+
+### FIXME what is this?
+### if include_VERSION_SCRIPT
+### VSCRIPT = -Wl,--version-script=$(srcdir)/libtdehtml.map
+### endif
+
+### FIXME what about java?
+### FIXME maybe static libs must be embedded?
+
+tde_add_library( ${target} SHARED AUTOMOC
+ SOURCES ${${target}_SRCS}
+ VERSION 4.2.0
+ LINK ${VSCRIPT} kjava-static kjs_html-static tdehtmldom-static tdehtmlcss-static
+ tdehtmlhtml-static tdehtmlxml-static tdehtmlrender-static tdehtmlmisc-static
+ tdeutils-shared tdeprint-shared kjs-shared ${JPEG_LIBRARIES}
+ DESTINATION ${LIB_INSTALL_DIR}
+ DEPENDENCIES dcopidl
+)
+
+
+##### libtdehtmlpart ##############################
+
+set( target libtdehtmlpart )
+
+set( ${target}_SRCS
+ dummy.cpp
+)
+
+file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
+"#include <tdelibs_export.h>
+extern \"C\" KDE_EXPORT void* init_libtdehtml();
+extern \"C\" KDE_EXPORT void* init_libtdehtmlpart() { return init_libtdehtml(); }
+" )
+
+tde_add_kpart( ${target}
+ SOURCES ${${target}_SRCS}
+ LINK tdehtml-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+
+##### tdehtmlimagepart ############################
+
+set( target tdehtmlimagepart )
+
+set( ${target}_SRCS
+ imgdummy.cpp
+)
+
+file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/imgdummy.cpp
+"
+#include <tdelibs_export.h>
+extern \"C\" KDE_EXPORT void* init_tdehtmlimagefactory();
+extern \"C\" KDE_EXPORT void* init_tdehtmlimagepart() { return init_tdehtmlimagefactory(); }
+" )
+
+tde_add_kpart( ${target}
+ SOURCES ${${target}_SRCS}
+ LINK tdehtml-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
diff --git a/tdehtml/ChangeLog b/tdehtml/ChangeLog
new file mode 100644
index 000000000..ea77bf459
--- /dev/null
+++ b/tdehtml/ChangeLog
@@ -0,0 +1,3874 @@
+2007-10-09 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Optimize the case of double descendant selectors "a b c",
+ to avoid O(n^2) run-time where n is the depth of the DOM tree.
+
+ * css/cssstyleselector.h: Define new early termination value for checkSelector
+ * css/cssstyleselector.cpp: Bail-out when the selector-chain can't possibly match
+
+2007-04-22 Harri Porten <porten@kde.org>
+
+ * ecma/xmlhttprequest.cpp: allow Accept header overrides
+
+2007-04-21 Harri Porten <porten@kde.org>
+
+ * ecma/xmlhttprequest.cpp: implemented
+ XMLHttpRequest.overrideMimeType() function
+
+2007-02-21 Harri Porten <porten@kde.org>
+
+ * html/html_formimpl.cpp: mimmick .value behavior of other
+ browsers if no value attribute was set for an input element of
+ type radio and checkbox.
+
+2007-02-18 Harri Porten <porten@kde.org>
+
+ * html/html_formimpl.cpp: fixed bug #120582 ("cloneNode does not
+ clone `checked' attribute in form inputs")
+
+ * html/html_formimpl.cpp: fixed reset of file upload form elements
+
+2007-02-11 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_window.cpp (executeOpenWindow): fixed location href
+ and pathname for about:blank windows
+
+ * tdehtml_part.cpp (findFrameParent): made frame name lookup locale
+ independant. Was mostly problematic with non-ascii names.
+
+ * html/html_formimpl.cpp (gatherWalletData): prevent crash occuring
+ on double form submits (bug report #105899)
+
+2006-11-14 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement overflow-x and overflow-y
+
+ * css/*.*: New properties
+ * rendering/render_style.{h,cpp}: New properties
+ * rendering/render_object.h: New functions scrollsOverflowX() and scrollsOverflowY
+ * rendering/render_layer.h: Remove depricated function moveScrollbarsAside()
+ * rendering/render_layer.cpp: More fine grained creation of scrollbars
+ * tdehtmlview.cpp: More fine grained creation of scrollbars
+ * rendering/render_block.cpp: Use new functions
+ * rendering/render_box.cpp: Use new functions
+ * rendering/bidi.cpp: Use new functions
+
+2006-11-13 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge text-overflow:ellipis from WebCore
+
+ * css/*.*: New property and values
+ * rendering/render_style.{h,cpp}: New property and values
+ * rendering/render_line.{h,cpp}: New line-box for ellipsis
+ * rendering/bidi.cpp: Two functions to remove and create ellipsis boxes
+ * rendering/render_text.{h,cpp}: Add the ability to truncate text at a certain point.
+
+2006-06-28 Germain Garand <germain@ebooksfrance.org>
+
+ make updating of addRule/removeRule/insertRule work
+ cf. http://www.quirksmode.org/dom/w3c_css.html#change
+
+ * css/css_stylesheetimpl.cpp
+ (insertRule/deleteRule): shallow update of styleselector.
+ * xml/dom_docimpl.{h,cpp}
+ (updateStyleSelector): new boolean argument for shallow recalculation, when all sheets are known.
+ (DocumentImpl::recalcStyleSelector): split.
+ (DocumentImpl::rebuildStyleSelector): new from split. Recreate styleselector with known sheets.
+
+2006-06-27 Germain Garand <germain@ebooksfrance.org>
+
+ . Correct drawing of borders on iframes and objects (#118277/#56109)
+ . Frameborder attribute for iframes (http://www.w3.org/TR/html401/present/frames.html#adef-frameborder)
+ . Fix widget counter-mask not being updated in time, thus sometimes missing a repaint (e.g: http://lequipe.fr)
+
+ * html/html_baseimpl.{h,cpp} (HTMLIFrameElementImpl::parseAttribute): parse frameborder attribute. Defaults to true as per specification.
+ (HTMLIFrameElementImpl::updateFrame/attach): apply/remove frameborder style at attachment time.
+ * tdehtmlview.cpp (drawContents): fix counter-mask problem. Widget geometry is not accurate before painting, so we must
+ use the RenderObject's.
+ * rendering/render_frames.h (paddingTop/paddingBottom/paddingLeft/paddingRight): reimplement. Frames have no padding.
+ (RenderPartObject::canHaveBorder): reimplement. True.
+ * rendering/render_object.cpp (RenderObject::updateWidgetMasks): clip mask to correct width/height, though it doesn't matter much on X11.
+ * rendering/render_replaced.h (RenderWidget::borderTop/borderBottom/borderLeft/borderRight): percolated down from RenderForm.
+ Frames/Iframes also need that reimplementation.
+
+2006-06-22 Germain Garand <germain@ebooksfrance.org>
+
+ Implement floating auto-width table quirk
+
+ * rendering/render_block.cpp (positionNewFloats): in quirkmode, floated auto-width
+ tables try to fit within remaining linewidth, so look for minWidth, and relayout if
+ position found ends up being narrower than current table width.
+
+2006-06-20 Germain Garand <germain@ebooksfrance.org>
+
+ Don't let a float serie grow an object's maxwidth beyond the available width
+
+ * rendering/render_block.cpp (calcInlineMinMaxWidth/calcBlockMinMaxWidth): lazzily check available width
+ so floats don't overflow it if they can break line.
+ * rendering/render_box.{h,cpp} (availableWidth{,Using}): new. Like availableHeight{,Using}
+ * rendering/render_canvas.cpp (RenderCanvas::layout): set m_viewportWidth before recalculating minmax, as
+ availableWidth needs it.
+
+2006-06-15 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge CSS3 properties background-size, background-origin and background-clip from WebCore
+
+ * rendering/render_style.{h,cpp}: New properties
+ * rendering/render_box.cpp: Handle the values in paintBackgroundExtended.
+ * dom/css_value.h: Add CSS_PAIR primitive value
+ * css/css_valueimpl.{h,cpp}: Add PairImpl primitive value
+ * css/cssstyleselector.cpp: New properties
+ * css/cssvalues.in: New values
+ * css/cssproperties.in: New properties
+ * css/cssparser.{h,cpp}: Clean-up short-hand parsing WC style
+
+2006-06-14 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement replaced CSS(3) content, and fix various details in generated pseudo elements for CSS 2.1
+
+ * rendering/render_style.{h,cpp}: Add REPLACED and MARKER pseudo styles
+ * rendering/render_container.{h,cpp}:
+ (updatePseudoChild) Allow display: block as per CSS 2.1 standard
+ (updateReplacedContent) Handle changes in Replaced content.
+ (childrenAllowed) forbid children when generated content is used, this prevents
+ their render-objects from being attached.
+ * rendering/render_block.cpp: Postpone updatePseudoChilden to attachment because block
+ children might need the elements parents.
+ * rendering/render_inline.cpp: ditto
+ * rendering/render_generated.{h,cpp}: Add new class RenderGlyph to render list-style glyphs (square, disc, etc.)
+ * xml/dom_nodeimpl.cpp:
+ (NodeImpl::diff) detect changes in content and return Detach
+ * css/css_base.{h,cpp}: Add marker and replaced pseudo-styles
+ * css/cssstyleselector.cpp:
+ (checkOneSelector) Allow content on more elements
+ (precomputeAttributeDependencies) Track attributes inside :not elements as well
+
+2006-06-08 George Staikos <staikos@kde.org>
+
+ Fix <a><label><img not in a form not being clickable
+
+ * html/html_formimpl.cpp: let the event bubble
+
+2006-05-31 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge WC bug-fixes and clean-up for positioned box-model
+
+ * rendering/Render_box.{h,cpp}:
+ (RenderBox::calcAbsoluteHorizontal):
+ (RenderBox::calcAbsoluteHorizontalValues):
+ (RenderBox::calcAbsoluteVertical):
+ (RenderBox::calcAbsoluteVerticalValues):
+ (RenderBox::calcAbsoluteHorizontalReplaced): Handle replaced case separately.
+ (RenderBox::calcAbsoluteVerticalReplaced): ditto.
+
+2006-04-20 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement full support for CSS updates on dynamic DOM and user-interaction
+
+ * misc/multimap.h: NEW: A "fast on insert" map with multiple values per key
+ * xml/dom_restyler.{h,cpp}: NEW: The dynamic DOM restyler keeps track of changes and issues restyles
+ * xml/dom_docimpl.h:
+ Remove obsolete usesDescendencyRules.
+ Add a dynamicDomRestyler to the document.
+ * xml/dom_nodeimpl.{h,cpp}: Add dynamic DOM restyler hooks.
+ * xml/dom_elementimpl.{h,cpp}:
+ Remove obsolete usesDescendencyRules logic.
+ Remove obsolete laterestyle logic.
+ Implement DOM restyler hooks.
+ * css/cssstyleselector.{h,cpp}:
+ Clean-up checkSelector, removing obsolete and redundant arguments
+ Fix :link and :visited selector.
+ Setup all dynamic dependencies in checkOneSelector.
+ * css/cssparser.{h,cpp}: Remove defaultNamespace
+ * css/css_stylesheetimpl.{h,cpp}: Add defaultNamespace
+ * css/parser.{y,cpp}:
+ Remove calls to usesDescendencyRules.
+ Use defaultNamespace from stylesheet rather than parser.
+ * rendering/render_style.h: Remove obsolete affectedByHoverRules and affectedByActiveRules
+ * rendering/render_layer.cpp: Use dynamic DOM restyler to restyle :hover and :active nodes.
+ * html/html_formimpl.cpp: Call dynamic restyler for changes to disabled state
+
+2006-04-09 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Distinguish between having no determined namespace, and determined to have no namespace
+
+ * xml/dom_nodeimpl.h: Split noNamespace into defaultNamespace and emptyNamespace
+ * css/cssstyleselector.cpp: Change HTML-hack to only trigger on undetermined namespace.
+
+2006-04-04 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Make so-called nondeterministic CSS matching work
+
+ * css/cssstyleselector.{h,cpp} (checkSubSelector/checkOneSelector):
+ Extract combinator matching from checkSelector and make it a recursive function. Clean-up checkOneSelector.
+
+2006-03-25 Germain Garand <germain@ebooksfrance.org>
+
+ Scope: fix handling of nested/external scripts in the tokenizer (#91701)
+
+ * misc/stringit.h (TokenizerQueue): a LIFO stack of TokenizerStrings
+ * html/htmltokenizer.{h,cpp} (scriptHandler/write/notifyFinished): use a TokenizerQueue to store
+ postponed fragments while executing/loading scripts.
+ (fixUpChar): unrelated - fill in missing unicode replacements.
+
+2006-03-20 Dirk Mueller <mueller@kde.org>
+
+ * misc/loader.cpp: fix pixmap leak in tiled_pixmap()
+
+2006-03-20 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Improve the CSS :lang() selector to match clarified specification
+
+ * tdehtml_part.cpp: parse HTTP content-language
+ * xml/dom_docimpl.cpp: parse HTTP-EQUIV content-language
+ * css/cssstyleselector.cpp: match :lang() against parents and ultimately the document
+
+2006-03-07 Germain Garand <germain@ebooksfrance.org>
+
+ Scope: relayout/repaint/widget masks fixes. Refine stacking context exploration. Optimise.
+
+ * tdehtmlview.cpp (drawContents): use widget geometry rather than the RenderWidget's rect (fixes widget borders not being updated)
+ Check if widget is in the dirty rect before doing any work.
+
+ * rendering/render_block.cpp (layoutBlockChildren): I meant !child->isPositioned() here, not isPositioned(). No need to
+ dirty positioned children as this is handled by the containing block chain through layoutPositionedObjects
+ (layoutPositionedObjects): always relayout fixed objects.
+
+ * rendering/render_canvas.cpp (layout): check canvas dimensions and call layoutBlock directly with relayoutChildren boolean.
+
+ * rendering/render_layer.{h,cpp} (paintedRegion): constrain our shape to the visibleRect. Use convertToLayerCoords to get a correct
+ visibleFlowRegion (updateWidgetMasks): don't forget to update the mask if it reverts to none at all.
+
+ * rendering/render_object.{h,cpp} (containingBlock): for relpos inlines, return the nearest block (skipping to next containingBlock gives
+ stalled layout flags problems - #121653). (updateWidgetMasks): mask the content box, not the border box.
+ (enclosingStackingContext) new. Returns the layer defining current stacking context.
+
+ * rendering/render_replaced.{h,cpp} (isKHTMLWidget): new flag for KHTML-proxied widgets.
+ (detach/resizeWidget/setQWidget/layout/updateFromElement/slotWidgetDestructed/setStyle/paint): use the flag insead of strcmp's
+ Only allow !tdehtml widgets to register in the view (only those need masking).
+
+2006-03-05 Charles Samuels <charles@kde.org>
+ * link not accessable with negative text-indent (#96275)
+ * Wrong :hover effect with negative text-indent (#90510)
+ * text not selectable if it has a negative text-indent
+
+2006-03-05 Charles Samuels <charles@kde.org>
+ * javascript timeouts that cross a midnight boundary shall not occur early
+
+2006-03-03 Germain Garand <germain@ebooksfrance.org>
+
+ get iframes, objects and some other overlaid widgets to obey their stacking context (#31121)
+
+ * tdehtmlview.cpp: mask widgets more precisely (i.e. allow layers to paint over overlaid widgets,
+ when they ought to).
+
+ * rendering/render_canvas.{cpp,h}: update widget masks after pos child layout/positioning;
+ set a boolean m_needsWidgetMasks to optimise for common case (where we have no such widgets).
+
+ * rendering/render_layer.{cpp,h} (updateWidgetMasks/paintedRegion): build a rough mask for the positive Z order
+ childs. We'll apply that mask later to widgets that are under our aegis.
+
+ * rendering/render_object.{cpp,h} (visibleFlowRegion): helper for calculation of broad region we want to mask in flows.
+ (updateWidgetMasks): walk our children looking for widgets suitable to masking. Apply our enclosingLayer's mask,
+ transformis transformandi.
+
+ * rendering/render_replaced.cpp: overlaid widgets must advertise their existence to the enclosing layer.
+
+2006-03-01 Germain Garand <germain@ebooksfrance.org>
+
+ Improve selectorText
+
+ * css/css_base.cpp (extractPseudoType): don't reset 'value' after parsing the pseudo-style, we need it for selectorText.
+ (selectorText): - correctly handle CSS3 pseudo selectors,
+ - merge some improvements from WebCore (Mitz Pettel sub-selector patch + fix ::Set handling)
+ * css/css_ruleimpl.cpp (selectorText): handle of multiple, comma-separated selectors
+
+2006-02-28 Germain Garand <germain@ebooksfrance.org>
+
+ Common-case style selection optimisation inspired from WebCore.
+
+ * css/css_base.cpp/.h: add 'Class' to possible matching modes
+ * css/cssstyleselector.cpp: treat 'Class' extra, not anymore as an ordinary List.
+ * css/parser.cpp/y: use 'Class' matching mode
+ * html/html_elementimpl.cpp: when parsing ATTR_CLASS, set a boolean to remember if it is or not a class list.
+ * xml/dom_elementimpl.{cpp,h}: add m_hasClassList boolean + setter/getter
+
+2006-02-28 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (layoutBlockChildren): be more efficient with regard to positioned objects relayout.
+ Merge WC margin-collapse regression fix (WC/#3508).
+ (layoutPositionedObjects) Objects with staticX() need a relayout too.
+ * rendering/render_canvas.cpp (layout): no need to relayout positioned objects here. This would mark entire branches of the tree
+ as needing a layout, thus stalling update requests in those branches (#116626)
+
+2006-01-14 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_image.cpp (calcReplacedWidth,calcReplacedHeight):
+ Respect both min/max sizes and aspect-ratio when resizing.
+
+2006-01-03 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * css/cssparser.cpp: Allow content: normal | none
+ * css/cssstyleselector.cpp: Handle content: normal | none
+
+2005-12-09 Germain Garand <germain@ebooksfrance.org>
+
+ implement quirky HTML alignment ; introduce special float values
+ -tdehtml-left/-tdehtml-right to this effect.
+
+ * css/cssparser.cpp: ditto. Fix memory leak from Function struct deletion also.
+ * css/cssstyleselector.cpp: ditto.
+ * css/html4.css: set as default style for table[align="left/right"]
+ * html/html_tableimpl.cpp (parseAttribute): remove setting of float property
+ * rendering/render_block{h,cpp}: quirky HTML alignment never clears, and never cause fafs to clear.
+ Only examine the last floating object on line, so as to match MSIE behaviour.
+ * rendering/render_style.h: extra float enumeration values
+ * css/css_renderstyledeclarationimpl.cpp (getPropertyCSSValue): adjust
+
+2005-12-06 Dirk Mueller <mueller@kde.org>
+
+ * html/htmltokenizer.cpp: don't treat <!---> specially.
+ fixes bug 93799.
+
+2005-12-02 Charles Samuels <charles@kde.org>
+ rendering/bidi.cpp: don't sometimes take text far past the end
+ of the block's margin on justified text. bug #106081
+
+2005-11-08 Germain Garand <germain@ebooksfrance.org>
+
+ sizing of percent objects within table cells
+
+ * rendering/render_box.cpp (calcPercentageHeight): transfer most of the logic for table cells in render_table as
+ it was partly redundant here. Don't apply the table cell sizing hacks in strict mode - no other engine does that.
+ Don't forget anonymous blocks - those must not stop recursion obviously.
+ Move substraction of the border/padding after calculation (spotted in WC)
+
+ * rendering/render_table.{cpp,h}:
+ had member booleans to hold whether flexing of cells in a row is
+ needed, and in the affirmative, whether we need to mark our anonymous childs for relayout (hence go one level deeper).
+ Part of line 1394 comes from WebCore.
+ Also: don't allow negative offset in vertical alignment when content overflows ; matches MSIE better.
+
+2005-10-28 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/table_layout.cpp (calcEffectiveWidth): do proportional distribution of overflowing minwidth
+ when all cols are percent (#104156)
+
+2005-10-21 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/bidi.cpp (findNextLineBreak): implement needed quirk for line breaking of
+ replaced elements within table cells.
+ * rendering/render_block.cpp (calcInlineMinMaxWidth): ditto.
+ Bugs #93745, #72457
+
+2005-10-20 Dawit Alemayehu <adawit@kde.org>
+ * ecma/xmlhttprequest.cpp:
+ -Add support for default HTTP referer header. Fixes bug# 113962.
+ - Sanitize all setRequestHeader calls:
+ - We now use a BANNED_HTTP_HEADERS list to filter out
+ potentially problematic headers.
+ - We always call open on "get" and "post" requests set
+ through this function.
+ - We sanitize any attempts to set the "referer" field.
+
+2005-10-15 Dawit Alemayehu <adawit@kde.org>
+ * ecma/xmlhttprequest.cpp: Handle HTTP response headers case insensitively.
+ Fix for bug 110768.
+
+2005-10-14 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp: show accesskeys for all frames
+
+2005-10-13 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ WebCore merge: correct name on IFrames
+
+ * html/html_baseimpl.cpp: copied FrameElementImpl behavior for initializing name
+
+2005-10-13 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ WebCore merge: blur and focus on buttons
+
+ * html/html_formimpl.{cpp.h}: Add form and blur
+ * dom/html_form.{cpp,h}: ditto
+ * ecma/kjs_html.{cpp,h}: ditto
+
+2005-10-08 Germain Garand <germain@ebooksfrance.org>
+
+ Port soft-hyphen support from WebCore
+
+ * rendering/bidi.cpp (findNextLineBreak): main skipping/breaking logic
+
+ * rendering/render_text.{cpp,h} (calcMinMaxWidth): account for soft hyphen
+
+2005-10-08 Dawit Alemayehu <adawit@kde.org>
+ * ecma/xmlhttprequest.cpp: Do not append NULL character to end of posted
+ data. Fix for bug 113393.
+
+2005-10-08 Germain Garand <germain@ebooksfrance.org>
+
+ Follow Mozilla/Opera in considering the Window object as an implementation of the AbstractView/ViewCSS
+ DOM2 interfaces. Return the Window object when available ; an AbstractView if not.
+
+ * ecma/kjs_dom.cpp (DefaultView): return the view's Window object if available.
+
+ * ecma/kjs_window.{cpp,h} (GetComputedStyle): implement, as in AbstractView.
+
+2005-10-07 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/bidi.cpp (findNextLineBreak): integrate all positioned inlines in the lineboxes to get a correct static position
+ in initial whitespace. Use some midpoints voodoo to take care of whitespace.
+
+ cf. unsorted/113527.html
+
+2005-10-03 Germain Garand <germain@ebooksfrance.org>
+
+ let the initial containing block be the Canvas, as mandated by latest
+ draft of CSS 2.1 10.1.1
+
+ * rendering/render_object.cpp (containingBlock, container): don't special case the Root, it's no more
+ an initial containing block.
+
+ * rendering/render_block.{cpp,h} (*AbsolutePosition): separate calculation
+ of positioned objects' contribution to the object's rightmost/lower/leftmost position.
+
+ * rendering/render_box.cpp (setStyle, containingBlockWidth): checking for isCanvas where applicable.
+
+ * rendering/render_canvas.cpp (docWidth, docHeight):
+ take into account absolutely positioned objects from the canvas itself.
+
+2005-09-18 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implementation of real page-breaking algorithm respecting the CSS 2.1 specification.
+
+ * tdehtmlview.cpp:
+ Do layout for page-breaks before printing.
+ Use screen resolution as default instead of 72DPI.
+ * css/html4.css: Add the print media default styles
+ * rendering/render_style.*: Add RenderPageStyle as the style for the page-context. Not yet used.
+ * rendering/render_canvas.*:
+ Separate paged and static properties of printing.
+ Use rootHeight as pageHeight.
+ Add RenderPage as the page-context(@page). Not yet used.
+ * rendering/render_flow.*:
+ (deleteLastLineBox) new function to remove the last line (in order to redo it).
+ * rendering/render_line.*:
+ (removeFromLine) ditto
+ * rendering/bidi.cpp: New algorithm in layoutInlineChildren for doing page-breaks at layout-time,
+ and respecting orphans/widows CSS settings.
+ * rendering/render_block.cpp:
+ (makePageBreakAvoidBlocks) Function for collecting runs of page-break-after/before: avoid blocks, so
+ they can be moved across page-breaks collectively.
+ (layoutBlockChildren) New algorithm for doing page-breaks at layout time,
+ and respecting page-break-after/before/inside
+ * rendering/render_table.cpp: Force page-breaks to happen inside cells and not between rows.
+ (RenderTableSection::addSpaceAt) moves later table-rows down when one cell expands to handle a
+ page-break.
+ * rendering/render_list.cpp: Remove truncation logic from paint
+ * rendering/render_text.cpp: ditto
+
+2005-08-18 Luís Pedro Coelho <luis@luispedro.org>
+ * rendering/render_image.cpp: Scale images correctly (adjust both height and width)
+ when max-width is used.
+
+2005-08-10 Dawit Alemayehu <adawit@kde.org>
+ * ecma/xmlhttprequest.cpp: Convert a 304 (Not Modified) HTTP response in
+ XMLHttpRequest to a 200 (OK) response to make KHTML conform to IE's and
+ Mozilla's behavior. BUG: 110272
+
+ * ecma/xmlhttprequest.cpp: Factored out the HTTP status line parsing code
+ into a single function.
+
+2005-08-02 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Imported background parsing and painting from WebCore.
+
+ * css/cssparser.{h,cpp}: New short-hand parser for background
+ * css/cssstyleselector.{h,cpp}:
+ * rendering/render_style.{h,cpp}: Support multiple backgrounds using BackgroundLayer
+ * rendering/render_box.{h,cpp}: Use paingBackgrounds to paint multiple backgrounds
+ * rendering/render_line.{h,cpp}: ditto
+ * rendering/render_object.{h,cpp}: ditto
+ * rendering/render_form.cpp:
+ * tdehtml/rendering/render_table.cpp:
+
+2005-08-02 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_block.{h,cpp}: Split layoutBlockChildren into several auxilary functions.
+
+2005-07-26 Andreas Kling <kling@impul.se>
+
+ * html/htmlparser.cpp: Block <input type="image"> elements if SRC attribute is ad-filtered.
+ * tdehtml_part.cpp: Include <input type="image"> elements in AdBlocK filter runs.
+
+2005-07-25 Dawit Alemayehu <adawit@kde.org>
+ * ecma/xmlhttprequest.cpp: Use the charset provided by the remote host through the HTTP headers.
+
+2005-07-25 Andreas Kling <kling@impul.se>
+
+ Make new ad filters have instant effect (either hide affected elements
+ replace them with the "blocked" pixmap.)
+
+ * tdehtml_part.{cpp,h}: Added runAdFilters() function which is called from reparseConfiguration()
+ * tdehtml_ext.cpp: Call KHTMLPart::reparseConfiguration() after adding new filters.
+ * misc/loader.cpp: Create blockedPixmap in Cache::init() instead of the CachedImage constructor.
+
+2005-07-19 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_box.{h,cpp}: Make sure we get content-sizes when reading fixed length values.
+
+2005-07-19 Andreas Kling <kling@impul.se>
+
+ * xml/dom_docimpl.cpp (isURLAllowed): Match ad filters against fully
+ expanded URL.
+
+2005-07-18 Andreas Kling <kling@impul.se>
+
+ "Block IFrame..." context menu option
+
+ * tdehtml_ext.{cpp,h}: Added "blockiframe" to context popup menu
+ * tdehtml_popupmenu.rc: Same
+ * tdehtml_part.h: added KHTMLPopupGUIClient to friend classes
+
+2005-07-08 Germain Garand <germain@ebooksfrance.org>
+
+ vertical-align fixes
+
+ * rendering/render_object.cpp (getVerticalPosition): block level
+ elements must ignore vertical alignment (#92118). For Length values, check the parent
+ too. Don't use the parent's position if it's top/bottom - it's waiting for
+ our subtree's to complete! (cf. css/vertical-align.html)
+
+ * rendering/render_list.cpp (calcMinMaxWidth): if the marker is the error image,
+ avoid calculating bogus values.
+
+2005-07-07 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ There is nothing KHTML specific about keypress events. They might not be DOM2 or 3,
+ but MSIE, Mozilla and Safari all handles them as a valid event class.
+
+ * xml/dom2_eventsimpl.{h,cpp}: Allow KEYPRESS as a valid event type
+ * ./.: Rename KHTML_KEYPRESS_EVENT to KEYPRESS_EVENT
+
+2005-07-05 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmlparser.cpp(insertElement): Do not create DLs for stray DT and DD
+ (popBlock): Reopen residual tags
+ * html/dtd.cpp: Allow more elements under DL
+
+2005-06-29 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmltokenizer.cpp: Reset discard when encountering tags or entities
+
+2005-06-28 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/html_tableimpl.cpp (appendChild): Always add TBody to XHTML rows
+ * xml/xml_tokenizer.cpp (startElement): Remove hack for adding TBody to any row
+
+2005-06-27 Stephan Kulow <coolo@kde.org>
+
+ * html/html_formimpl.cpp (parseAttribute): Fix ignoring of align
+ attribute on form elements !image (patch by OpenDarwing #3360)
+
+2005-06-25 David Faure <faure@kde.org>
+
+ * html/htmlparser.cpp (insertNode): Fix parsing of <table><tr><caption>,
+ with code from WebCore, http://www.cs.cornell.edu/~maksim/WC/changesets/3747.html
+
+2005-06-23 David Faure <faure@kde.org>
+
+ * html/html_tableimpl.cpp (appendChild): Improve fix for bug #105586 to avoid
+ side effects with tfoot.
+
+ * tdehtml_run.cpp (foundMimeType): Mark child object (e.g. <embed>) as completed
+ after saving, running in external viewer, or cancelling, so that e.g. scheduled redirects
+ can happen. Patch by Andreas Kling <kling@impul.se>.
+
+2005-06-20 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * ecma/kjs_events.cpp: Respect the DOM for MouseEvent::Button atleast when simulating Mozilla
+
+2005-06-20 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp (openWindow): Treat empty string the same
+ as missing for third argument of window.open().
+
+2005-06-20 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge handling of dynamically inserted scripts.
+
+ * html/html_headimpl.{h,cpp}: Load and execute dynamic scripts
+ * html/htmlparser.cpp: Set a createdByParser to not execute scripts twice.
+ * xml/xml_tokenizer.cpp: Ditto.
+
+2005-06-19 George Staikos <staikos@kde.org>
+ * css/css_renderstyledeclarationimpl.{h,cpp}: Merge crash fix from
+ webcore (See bug #107460).
+ * css/css_valueimpl.{h,cpp}: Make m_node SharedPtr<>.
+
+2005-06-18 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_window.cpp (openWindow): patch by Andreas Kling that
+ adds support for "scrollbars" option to window.open().
+
+2005-06-14 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_style.{h,cpp}: Remove the quotes as counters hack
+ * css/cssstyleselectors.cpp: ditto
+ * rendering/render_container.{h,cpp} (updatePseudoChild): Clean and simplify
+ * rendering/render_generated.{h,cpp}: Split quotes from counters and
+ create new base class RenderCounterBase.
+ * rendering/render_object.cpp: Count quotes correctly
+
+2005-06-14 Dirk Mueller <mueller@kde.org>
+ * ecma/domparser.{h,cpp}: Unbreak compilation.
+
+2005-06-13 George Staikos <staikos@kde.org>
+ * ecma/xmlhttprequest.{h,cpp}: Disallow duplicated headers, and always
+ disallow Content-Length setting.
+
+2005-06-09 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implementing Mozilla extension DOMParser
+
+ * ecma/domparser.{h,cpp}: Implementation
+ * ecma/kjs_window.{h,cpp}: Exposing DOMParser
+ * misc/shared.h: tdehtml::SharedPtr<>
+
+2005-06-08 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/html_tableimpl.{h,cpp}: Implement FRAME attribute
+
+2005-06-03 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_window.cpp (put): don't crash on attempts to set a
+ property on a deleted window (bug #106697).
+
+2005-06-03 George Staikos <staikos@kde.org>
+ * ecma/kjs_window.cpp: Escape HTML in message boxes like window.alert()
+
+2005-06-02 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_block: Merge margin collapsing improvement from WebCore-146
+
+2005-06-01 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_window.cpp: fixed prototype property lookup order of
+ global window object. Fixes endless loop on maps.google.com
+ (bug #98979).
+
+2005-05-28 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement ideographic enumeration including the CSS 2.1 cjk-ideographic and several from CSS 3 List (working draft).
+ Also add three more numeric: (Lao, Thai and Tibetan)
+
+ * css/cssvalues.in: Add new CSS3 values with -tdehtml-
+ * rendering/render_style.h: Add new enums
+ * rendering/enumerate.cpp: Implement the ideographic algorithm.
+
+2005-05-24 David Faure <faure@kde.org>
+
+ * html/html_tableimpl.cpp (appendChild): Allow javascript to insert
+ a TR directly into a TABLE, creating a TBODY section if needed (bug #105586).
+
+2005-05-21 Harri Porten <porten@kde.org>
+
+ * html/html_documentimpl.cpp: emit onload event even if the
+ document has no body element (bug #105798).
+
+2005-05-20 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement/fix CSS namespace selector and other XHTML fixes.
+
+ * css/css_base.h: Merge CSSNamespace from WebCore
+ * css/css_stylesheetimpl.{h,cpp}: Port determineNamespace and addNamespace from WC
+ * css/parser.y: Parse namespaces better
+ * xml/dom_docimpl.cpp: Add noNamespace to namespace functions
+ * xml/dom_nodeimpl.h: Add constants for any, no and xhtml namespaces
+ * xml/xml_tokenizer.cpp: Parse white space.
+
+2005-05-18 Harri Porten <porten@kde.org>
+
+ * xml/dom2_eventsimpl.cpp: recognize "dblclick" type in
+ addEventListener() calls (bug #98994).
+
+2005-05-16 Harri Porten <porten@kde.org>
+
+ * ecma/*.cpp: removed usage of deprecated KJS::Value::isNull()
+
+ * ecma/kjs_dom.cpp: reverted "null" change from previous day
+ until the compatibility to other browsers is investigated.
+
+2005-05-15 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_dom.cpp: return "null" from getAttribute() and
+ getAttributeNS() if the attribute isn't set.
+
+ * html/html_elementimpl.cpp: always return a non-null string
+ from innerHTML() and innerText()
+
+2005-05-14 Ivor Hewitt <ivor@ivor.org>
+ * tdehtml_settings.cc: Support full wildcard expressions in AdblocK
+
+2005-05-12 Luciano Montanaro <mikelima@cirulla.net>
+ * html/html_formimpl.cpp: Make a return keypress activate form
+ buttons. Matches Mozilla.
+
+ * html/html_inlineimpl.cpp: make onclick() work for links too.
+
+2005-05-12 David Faure <faure@kde.org>
+
+ * tdehtmlview.cpp (dispatchKeyEvent): Don't send DOM keypress if
+ the DOM keydown that precedes it was blocked by javascript, as in IE.
+
+ * rendering/render_replaced.cpp (handleEvent): send Qt::KeyPress to the
+ widget for DOM keypress and not DOM keydown to allow sites to block a key
+ with onkeypress, #99749.
+
+2005-05-11 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/html_objectimpl.cpp: Extract service-type from "data:" url and create
+ renderer for all images
+
+2005-05-09 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Speed-up white-space collapsing by only allocating once.
+
+ * renderer/render_table.cpp: Remove static function cleanString
+ * xml/dom_stringimpl.cpp: Add collapseWhiteSpace function
+
+2005-05-07 Harri Porten <porten@kde.org>
+
+ * html/html_tableimpl.cpp (cellIndex): return meaningful values
+ using patch suggested by Rob in bug report #7690.
+
+ * ecma/kjs_window.cpp: allow setting location.href on foreign
+ windows opened by window.open() again (bug #101178).
+
+2005-05-06 Ivor Hewitt <ivor@ivor.org>
+
+ fix #15848: First implementation of AdBlocK.
+
+ * tdehtml_ext.{cpp,h}: Add Blockimage to context popup menu
+ * tdehtml_popupmenu.rc: ditto
+ * tdehtml_settings.{cc,h}: Add adFilter settings and helper functions
+ * html/htmlparser.cpp: Strip blocked IMG tags
+ * misc/loader.{cpp,h}: Return replacement blocked images and refuse to load blocked scripts.
+ * misc/blocked_icon.{cpp,png}: Image for above
+ * xml/dom_docimpl.cpp: isURLAllowed returns false for blocked URL's
+
+2005-05-02 David Faure <faure@kde.org>
+
+ * ecma/kjs_html.cpp (HTMLCollectionProtoFunc::tryCall): Support for
+ non-standard item('<name>').
+
+2005-05-02 David Faure <faure@kde.org>
+
+ Propagate correct DOM exception code from checkAddChild to setInnerHTML.
+ * html/html_elementimpl.cpp (setInnerHTML, setInnerText)
+ * dom/html_element.cpp (setInnerHTML, setInnerText)
+
+2005-05-01 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ The mergeable of Daves Acid2 patches.
+
+ * renderer/render_block.cpp:
+ - Make sure that percentages that go to auto don't mess up the self-collapsing block check.
+ - Fix floats to not grow if child floats overhang but the height of the outer float is auto.
+ * renderer/render_box.{h,cpp}:
+ - Add support for min/max-width/height for positioned elements.
+ - Make sure percentage min-height goes to 0 and not auto when the percentage does not apply.
+ * renderer/render_table.cpp:
+ - Make sure empty tables honor CSS-specified height in strict mode.
+ - Fix baseline alignment within table cells to use the bottom of empty blocks.
+
+2005-04-30 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_window.cpp: unbreak calling close() on other
+ windows. It has it own set of security checks.
+
+2005-04-24 Harri Porten <porten@kde.org>
+
+ * html/html_formimpl.cpp (value): never return a null string from
+ the value() function of input elements.
+
+2005-04-18 David Faure <faure@kde.org>
+
+ Special scope entries for event handlers are based on the DOM node on
+ which the handler is an attribute, not the event target, which also
+ allows to set it up at the time the event handler is created, not at
+ the time it fires (Safari merge).
+
+ Many files touched to simply pass the NodeImpl around.
+
+ Testcase events/eventhandlerscope.{html,js}
+
+2005-04-15 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.{h,cpp}: Assign unused accesskeys automatically to elements
+ without accesskeys.
+
+2005-04-06 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.{h,cpp}: Use KActions for type ahead find.
+ * tdehtml_part.{h,cpp}: ditto.
+ * tdehtml_part.{h,cpp}: Add Find Previous action.
+ * tdehtml_part.cpp (findTextNext): Fix changing direction while searching text.
+
+2005-04-05 Lubos Lunak <l.lunak@kde.org>
+
+ * misc/loader_jpeg.cpp: Fix loading of progressive JPEGs.
+
+2005-04-04 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp: Don't use keyboard grab for type-ahead find.
+
+2005-04-03 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * ecma/kjs_html.{h,cpp}: Implement frame and iframe .contentWindow
+ * ecma/kjs_window.{h,cpp}: Implement window.frameElement
+
+2005-03-30 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmlparser.{h,cpp}: Merge WebCore handling of residual styles.
+
+2005-03-29 Germain Garand <germain@ebooksfrance.org>
+
+ Layer related fixes.
+
+ * ecma/kjs_dom.cpp (putValueProperty): scrollLeft/scrollTop need an
+ up-to-date rendering.
+
+ * rendering/render_box.cpp (repaintRectangle): apply scroll offset
+ to the repaint rectangle (overflow != visible objects).
+
+ * rendering/render_layer.{h,cpp} (repaint): rename markForRepaint to
+ less equivocal repaint.
+ (updateLayerPositions): small fixes.
+ (scrollToOffset): update our child layers (#102235)
+
+ * rendering/render_object.cpp (setStyle/repaintDuringLayout): rename ditto.
+
+2005-03-29 Germain Garand <germain@ebooksfrance.org>
+
+ offsetLeft/Top/width/Height/Parent improvements
+
+ * rendering/render_object.cpp (offsetLeft/offsetTop/offsetParent):
+ match IE behaviour in strict mode.
+
+ * rendering/render_table.{h,cpp} (RenderTableRow::offsetLeft/offsetTop/offsetHeight/offsetWidth):
+ reimplemented to return meaningful values (#102127)
+
+2005-03-22 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * css/parser.y: Parse pseudo-elements and pseudo-classes separately.
+ * css/css_base.{h,cpp}: Treat pseudoElements and pseudoClass as differing match-types and
+ add compatibility transform from pseudoClass to pseudoElement for CSS2 pseudo-elements.
+
+2005-03-22 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmltokenizer.cpp: Implement SGML attribute-value white-space parsing rules.
+
+2005-03-22 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmlblockimpl.cpp: When a NS-layer gets DIV layer children. The NS layer should
+ let the DIV layer control position.
+
+2005-03-22 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * misc/loader.cpp: Do not override existing charset with an empty one.
+
+2005-03-21 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/htmltokenizer.cpp:
+ - Only skip first LF if immediately after PRE tag.
+ - Set prePos to 0 after BR tag
+
+2005-03-18 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * xml/dom_docimpl.h: Add dictionary of CounterNodes
+ * rendering/render_object.{h,cpp}: Save 8 bytes overhead by moving counternodes to document
+ * rendering/render_list.cpp: Do not calculate counter value for unordered lists
+
+2005-03-18 Germain Garand <germain@ebooksfrance.org>
+
+ * xml/dom_nodeimpl.cpp (traverseNextNode): fix broken algorithm for stayWithin
+ case (#101711)
+
+2005-03-18 Germain Garand <germain@ebooksfrance.org>
+
+ make disabling of CSSheets via DOM actually do something.
+
+ * css/css_stylesheetimpl.{cpp,h} (setDisabled): update style selector.
+
+ * css/cssstyleselector.cpp (CSSStyleSelector): do not append rules
+ from disabled sheets.
+
+2005-03-17 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_flow.cpp (repaint): Calculate height, do not simply
+ use the bottom overflow of the root line box.
+
+2005-03-16 George Staikos <staikos@kde.org>
+
+ * rendering/render_frames.cpp: some sites put width and height on <embed>
+ inside <object> instead of on <object>, so push that attribute up to
+ <object> and report it to the plugin
+
+2005-03-14 Germain Garand <germain@ebooksfrance.org>
+
+ * css/html4.css: horizontal rules are centered by default (HTML-4.01 15.3)
+
+2005-03-12 Germain Garand <germain@ebooksfrance.org>
+
+ * ecma/kjs_window.{cpp,h}: implement JS 1.2's window.atob/btoa (base-64 codec interface)
+
+2005-03-10 David Faure <faure@kde.org>
+
+ * ecma/kjs_events.cpp (handleEvent): Move "pushing element/form/doc onto the scope"
+ from JSEventListener::handleEvent to JSLazyEventListener::handleEvent so that
+ it only happens with listeners set from html attributes, not from JS - in which
+ case the function already got a correct scope when created.
+ Testcase events/eventhandlerscope.{html,js}
+
+2005-03-04 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge table padding from WebCore
+
+ * html/html_tableimpl.cpp: CELLPADDING should not set normal padding
+ * rendering/render_table.cpp: Respect padding
+ * rendering/render_table.h: bordersAndSpacing() -> bordersPaddingAndSpacing()
+
+2005-03-04 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (layoutBlockChildren): percent width
+ children behaves like fixed width children with regard to float
+ clearing. In both cases we need to check if current line as enough width to
+ hold the (flowing-around-float) child. If not, we need to clear.
+
+2005-03-04 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_table.cpp (calcWidth): always use lineWidth for
+ table margins calculation (#89900)
+
+2005-03-03 Germain Garand <germain@ebooksfrance.org>
+
+ * ecma/kjs_dom.cpp (getValueProperty/putValueProperty):
+ Mozilla/IE strict compatibility: document.documentElement.scroll{Top,Left}
+ concern the canvas, not the root block.
+ Cf. http://www.quirksmode.org/viewport/compatibility.html
+
+2005-03-01 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/html_formimpl.cpp: Report content position rather than viewport position in "image" forms
+
+2005-03-01 David Faure <faure@kde.org>
+
+ * html/html_formimpl.cpp (setType): Implemented, to make it possible
+ to set the type of an input element created with createElement.
+ Partially inspired by WebCore's setType(), but for getAttribute("type")
+ to work, setType() must set ATTR_TYPE. So parseAttribute() has to call
+ another method which doesn't do that, which is now parseType(), to
+ avoid an infinite recursion. Testcase forms/input_setType.html
+
+2005-02-28 Harri Porten <porten@kde.org>
+
+ * xml/dom2_eventsimpl.cpp: always return a non-zero keyCode()
+ value even if it is Qt::Key_unknown as it is the case with the
+ AltGr key for example.
+
+2005-02-28 David Faure <faure@kde.org>
+
+ * html/html_formimpl.cpp (setName): Also set ATTR_NAME so that
+ form.foo finds the input element. Testcase forms/input_setName.html.
+
+2005-02-27 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/font.cpp (drawText): Only pass text from inline text box to
+ QPainter::drawText, not the whole RenderText's text.
+
+2005-02-27 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_events.cpp: bind keyboard modifier properties like ctrlKey
+
+ * xml/dom2_eventsimpl.cpp: returning meaningful keyCode() values
+ for "special" keys
+
+ * dom/dom2_events.cpp: make which() equivalent to keyCode()
+
+2005-02-20 Germain Garand <germain@ebooksfrance.org>
+
+ * html/html_formimpl.cpp (FocusHandleWidget::focusNextPrev): TextEdit
+ needs to use QWidget::focusNextPrevChild.
+ (defaultEventHandler): only handle key tab if it wasn't accepted by the widget (#58247)
+
+ * rendering/render_replaced.cpp (RenderWidget::handleEvent): return
+ something meaningful.
+
+2005-02-18 Germain Garand <germain@ebooksfrance.org>
+
+ scope: table percentage height, replaced element height calculation.
+
+ * rendering/render_body.cpp (layout): pre-calculate our margins in
+ quirk mode, to be able to compute calcPercentageHeight in a const way.
+
+ * rendering/render_box.{h,cpp}
+ (calcPercentageHeight): make const. Fix calculation of percentage
+ height within table cells to match other engines.
+ Do not subtract PB for table elements.
+ (calcReplacedHeightUsing): use calcPercentageHeight for Percent.
+ Looking for available height is an IE quirk and is thusly only done in quirk mode now.
+ When it is not computable, it behaves like 'auto', so use the intrinsicHeight (cf.10.6.2).
+
+ * rendering/render_table.cpp (layoutRows): fix vertical alignment within
+ percentage driven cells. Subtract the cell's PB from cellPercentageHeight.
+
+2005-02-18 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_layer.cpp (updateHoverActiveState): Also mark
+ textnodes as being active. Use NodeImpl's implementation of setActive
+ for efficiency reasons, the style is updated anyway afterwards.
+
+2005-02-16 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtmlview.cpp (dispatchMouseEvent): Walk upwards the parent chain
+ from the target node and set the focus to the nearest focusable
+ ancestor (merged from WebCore).
+
+2005-02-16 Germain Garand <germain@ebooksfrance.org>
+
+ - sanitize part/tokenizer state (for cross-document scripts).
+ - don't delete a tokenizer still executing a script on explicit close (patch from Allan Sandfeld
+ and Sarah <sarah@b0rked.dhs.org>)
+ fixes #68523 + crashes on early pop-up closing.
+
+ * html/htmltokenizer.{h,cpp} (setAutoClose/timerEvent/...): add timer driven auto-close mode for
+ e.g cross-frame scripts.
+
+ * tdehtml_part.{h,cpp} (resetFromScript): reset the part to a sane state before reopening
+ a closed document.
+
+ * xml/dom_docimpl.cpp (write): ditto.
+ (close): Check for isExecutingScript before deciding to delete the tokenizer.
+
+ * xml/xml_tokenizer.h (setAutoClose/isExecutingScript): ditto.
+
+2005-02-15 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_table.{cpp,h} (RenderCell::nodeAtPoint):
+ Including top and bottom extra space in hit testing.
+
+2005-02-15 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement genererated content: counter and quotes
+
+ * css/*: Parse new counter and quote content, and counter acts. Quotes are parsed to a special type of counter.
+ * rendering/counter_tree.{h,cpp}: Adds a dynamic counter-tree to keep counter values up-to-date
+ * rendering/render_generated.{h,cpp}: New renderCounter class to renders counters as text
+ * rendering/render_container.cpp: Content now only inherits style from the pseudo-container rather than use an exact duplicate.
+ * rendering/render_object.cpp: Add new functions to find and attach counter-tree nodes.
+ * rendering/render_style.cpp: New counter content and counter acts
+ * rendering/render_list.cpp: Use the new counters to count lists
+
+2005-02-14 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_flow.cpp (repaint): Only include top and bottom
+ overflow while not relayouting, otherwise root inline box may not be
+ available yet.
+
+2005-02-14 David Faure <faure@kde.org>
+
+ * html/html_formimpl.cpp (value): Fix for textarea onChange not emitted:
+ emit it when updating m_value in value(), since this happens before the
+ focusOut event, which doesn't do it since m_dirtyvalue is then false.
+
+2005-02-13 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_block.{cpp,h} (paintObject): Added parameter to only
+ paint the block's outline on demand.
+
+ * rendering/render_flow.cpp (repaint): Fix repaint rectangle to also
+ encompass the top and bottom overflow of the root inline box.
+
+ * rendering/render_line.{cpp,h} (InlineBox::root): Ported over from
+ WebCore. Returns the root inline box of this box.
+
+ * rendering/render_table.{cpp,h} (RenderTableCell::repaintRectangle):
+ Use full height of table cell, otherwise outline won't be fully
+ repainted.
+ (RenderTableCell::paint): Paint outline of table cells explicitly,
+ and keep the underlying render block from painting it itself.
+ (RenderTableCell::paintObject): Removed. Nowhere used anymore.
+
+2005-02-13 Harri Porten <porten@kde.org>
+
+ * xml/dom2_eventsimpl.*: updated virtual key codes to a more recent
+ version. Added mapping for Up and Down cursor keys. Made keyCode()
+ always return the uppercase value of characters.
+
+2005-02-12 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (slotRedirect): No reload should happen when redirecting
+ to sameurl#anchor via Javascript or META refresh. This happened due to the
+ setRedirectedRequest(true), which wasn't necessary for the webmin tree.cgi
+ fix - setRedirectedRequest is called by KonqRun for that one.
+ The other redirectedRequest check was used for adding cross-domain, I simply
+ moved that code from urlSelected to slotRedirect.
+
+2005-02-12 Germain Garand <germain@ebooksfrance.org>
+
+ fix inline formatting model
+
+ * rendering/render_line.cpp (placeBoxesVertically): shrink/enlarge inlineboxes' height according to rendered gliphes,
+ but only if the calculated leading delta is superior to our font's natural leading
+
+ * rendering/render_text.cpp (paintSelection): use the linebox's height, not the line-height anymore.
+
+ * rendering/render_inline.cpp (collectVerticalBoxCoordinates): previous linebox's bottomPosition
+ might now be lower than current linebox's topPosition. Adjust outline algorithm.
+
+2005-02-08 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (executeScript): Handle immediate redirects, scheduled
+ by JS with e.g. location='foo', as soon as the current script finishes.
+
+2005-02-07 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_image.cpp (paint): Regard inline offset when
+ painting outline.
+
+ * rendering/render_table.{cpp,h} (RenderTable::paint): Added missing painting of table outlines.
+ (firstTableRow): added
+ (nextTableRow): added
+ (RenderTableSection::paint): When painting the rows, also traverse
+ the according RenderTableRows, and call their paintRow routine.
+ Fixed overflow size of damage rectangle.
+ (RenderTableRow::paintRow): Added. Can't use paint() because
+ RenderTableRow is not a RenderBox, and hence doesn't store layout
+ information.
+ (RenderTableCell::paint): Added painting of the table cell's outline
+ herein instead in RenderBlock to encompass the extra table cell top
+ and bottom margins.
+
+2005-02-07 Germain Garand <germain@ebooksfrance.org>
+
+ * css/html4.css: the -around-floats flow mode can only be applied to elements defining a
+ new block formatting context (see CSS2.1 - 9.5).
+ Blockquote and DL don't by any stretch of the mind, so clear this property for those.
+ Also, don't center fieldset.
+
+ * rendering/render_block.cpp (layoutBlock): make flowAroundFloats encompass their own floats
+ (#85984).
+
+2005-02-02 Leo Savernik <l.savernik@aon.at>
+
+ * dom/dom_doc.{cpp,h}: Added Document::addStyleSheet/removeStyleSheet
+ interface methods for programmatically adding/removing style sheets.
+
+ * xml/dom_docimpl.{cpp,h}: Added DocumentImpl::addStyleSheet/
+ removeStyleSheet methods.
+ Added list storing programmatically added style sheets.
+ (updateStyleSelector) Merge programmatical list with effective list
+ of style sheets.
+
+2005-02-01 Germain Garand <germain@ebooksfrance.org>
+
+ clearly separate full blown anonymous blocks (isAnonymousBlock) from
+ pseudo-elements (isPseudoAnonymous). #74595, #92910.
+
+ * rendering/render_block.cpp
+ (setStyle,updateFirstLetter,addChildToFlow,removeChild,close,renderName):
+ Only real anonymous blocks can be manipulated interchangeably => adjust logic.
+ PseudoAnonymous blocks have a null element(), but they keep a relationship to
+ the element they were generated from, that can be gathered from node()
+
+ * rendering/render_container.cpp (updatePseudoChild,insertChildNode,removeLeftoverAnonymousBoxes):
+ ditto.
+
+ * rendering/render_inline.cpp (addChildToFlow,splitFlow): ditto.
+
+ * rendering/render_list.cpp (setStyle,updateMarkerLocation,RenderListMarker):
+ ditto.
+
+ * rendering/render_object.cpp
+ (RenderObject::information): highlight the pseudo-element to originating element relationship in output.
+ (RenderObject::dump): ditto.
+
+ * rendering/render_object.h (requiresLayer): add missing hasOverflowClip condition
+ (isAnonymousBlock): ditto.
+ (isPseudoAnonymous): ditto.
+
+2005-01-25 Germain Garand <germain@ebooksfrance.org>
+
+ * tdehtmlview.cpp (viewportWheelEvent): discard wheel events occuring before the first relayout (avoids blanking the view).
+ Also support Horizontal wheel events (needs qt-copy/patch #61).
+
+2005-01-25 Germain Garand <germain@ebooksfrance.org>
+
+ fix #95704: float double-painting bug. Most of the work done by Charles Samuels.
+
+ * rendering/render_block.h (FloatingObject::FloatingObject): add crossedLayer flag to prevent noPaint from
+ being toggled off once we have crossed a layer during the float propagation process
+
+ * rendering/render_block.cpp (addOverHangingFloats): use/update said flag.
+
+2005-01-19 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * css/*: Parse opacity and outline-offset
+ * rendering/*: Implement outline-offset
+
+2005-01-12 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * css/cssstyleselector.cpp: Match :contains() against innerText on HTMLElements
+
+2005-01-11 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_text.cpp (caretPos): Calculate absolute position
+ beginning from the RenderText, not from the containing block.
+
+2005-01-07 David Faure <faure@kde.org>
+
+ * ecma/kjs_html.cpp: Support for document.body.onload.
+
+2005-01-06 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * tdehtml_part.cpp: Fix selection by selecting the text in the cleaned string rather
+ than in the DOM.
+ * xml/dom_textimpl.{h,cpp}: Add renderString() to return the possibly transformed string.
+
+2004-12-29 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement CSS 2.1 white-space: pre, pre-line and pre-wrap
+
+ * html/htmltokenizer.cpp: Merge white-space related parsing from Webcore
+ * html/htmlparser.cpp: Ditto
+ * rendering/render_text.cpp: Introduce text transformation that cleans excess
+ white-space and linefeeds when style()->whitespace() changes.
+ * rendering/render_style.h: Introduce pre-wrap and pre-line.
+ Add helper functions autoWrap(), preserveLF() and preserveWS()
+ * rendering/bidi.cpp: Replace checks of whiteSpace==PRE/NORMAL with new the
+ more finegrained autoWrap, preserveLF and preserveWS functions.
+ * css/*: Add pre-line and pre-wrap as possible CSS values
+
+2004-12-29 Germain Garand <germain@ebooksfrance.org>
+
+ merge bug fix for suboptimal updating of layer hierarchy
+
+ * rendering/render_container.cpp (appendChildNode/insertChildNode): optimize for common case
+
+ * rendering/render_object.{h,cpp} (addLayers): merge optimization
+
+2004-12-29 Germain Garand <germain@ebooksfrance.org>
+
+ memory allocation fixes
+
+ * tdehtml_factory.cpp: cleanup the global Arena freelist after the last tdehtml part gets unloaded
+
+ * misc/arena.{cpp,h} (InitArenaPool): change arenasize from 4096 to kMax(8192, 2*pagesize).
+ (ArenaAllocate): when a single pool grows over a 256*initial size threshold, switch to fractional allocation
+ so that more resources can be returned to the system afterward.
+ (FreeArenaList): don't link more than FREELIST_MAX Arenas to the freelist
+ (ArenaFinish): reset freelist_count
+
+2004-12-24 Stephan Kulow <coolo@kde.org>
+
+ * css/cssparser.cpp: fixing keyword background-positions that have an implicit center for the
+ other cordinate
+
+2004-12-19 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * xml/dom_nodeimpl.{h,cpp}: Merge createRendererIfNeeded() and friends from WebCore
+ * xml/dom_elementimpl.{h,cpp}: Simplify attach to createRendererIfNeeded
+ * xml/dom_textimpl.{h,cpp}: Don't create unneeded empty text-runs.
+
+2004-12-18 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Fix structural pseudo-classes :empty, :last-*, :only-* and :nth-last-* by introducing a late restyling
+ run when needed.
+
+ * xml/dom_nodeimpl.{h,cpp}: Add new function close() to notify that the close tag have been parsed and no
+ more static children will be added.
+ * xml/dom_elementimpl.{h,cpp}: Add flags restyleChildrenLate, restyleSelfLate and restyleLate. To indicate
+ self, children or self in relation to parent needs restyling at closing time.
+ * xml/xml_tokenizer.cpp: Call close when close-tags are parsed
+ * html/htmlparser.cpp: Call close where closeRenderer was previously called
+ * css/cssstylerenderer.cpp: Set restyleLate flags where necessary
+
+2004-12-13 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Be more IE-compatible in IE-compatible key-event extension
+
+ * ecma/kjs_events.{h,cpp}: Add charCode
+ * dom/dom2_events.{h,cpp}: Glue
+ * xml/dom2_eventsimpl.{h,cpp}: Make keyCode return windows key codes and add charCode.
+
+2004-12-12 Germain Garand <germain@ebooksfrance.org>
+
+ Pragmatic incremental repaints: be accurate on layered objects, conservative on
+ objects in normal flow. Fix performance issues on repeated relayouts (#53114)
+
+ * tdehtmlview.{cpp,h}: add needsFullRepaint flag, mostly similar to WebCore's.
+ (layout): don't repaint the canvas systematically anymore.
+
+ * rendering/bidi.cpp (layoutInlineChildren): schedule a repaint on
+ old rectangle and future rectangle, if marked dirty.
+
+ * rendering/render_block.cpp (layoutBlock/layoutBlockChildren/layoutPositionedObjects): ditto.
+
+ * rendering/render_table.cpp (layout): ditto.
+
+ * rendering/render_box.cpp (calcAbsoluteHorizontal): no more updateLayerPosition() here.
+ Layers positioning now happen in a separate pass.
+
+ * rendering/render_canvas.{cpp,h}
+ (needsFullRepaint): new - used to determine if we need to do incremental repaint at all. Don't waste time if the whole canvas is dirty.
+ (repaintViewRectangle): new - schedule a repaint in absolute coordinates.
+ (deferredRepaint): new - append argument to a list of objects needing a post-layout repaint.
+ (scheduleDeferredRepaints): new - repaint all objects in list described above, at the end of layout.
+
+ * rendering/render_layer.{cpp,h} (markForRepaint): new - schedule a repaint of a layer, calculating its visible rectangle,
+ and optionnally marking it as needing a post-layout repaint.
+ (updateLayerPositions): merged++ from WebCore. Position layers. Repaint layers marked by the above.
+ (calculateClipRects/calculateRects): no more updateLayerPosition call there.
+
+ * rendering/render_object.cpp
+ (setNeedsLayout): when marking for layout, also mark the formatting context for repaint (m_markedForRepaint boolean)
+ (setChildNeedsLayout): merge WebCore guard against multiple dirtying.
+ (setStyle): based on the Style diff, decide whether to dirty only the current formatting context, or also the parent's.
+ (dirtyFormattingContext): new.
+ (repaintDuringLayout): new - schedule a pre/post-layout repaint on the object, if it makes sense.
+
+2004-12-12 Germain Garand <germain@ebooksfrance.org>
+
+ sanitize anchor-jumping code. Merge restoreScrollPosition/gotoAnchor
+ slots to avoid undeterministic calling order and redundant
+ connections(#94783, 3.3.2 regression of #57360).
+
+ * tdehtml_part.cpp (restoreURL/openURL/slotData/restoreState): ditto.
+ (checkCompleted): don't setContentsPos here
+
+ * tdehtml_part.h: remove private gotoAnchor slot
+
+ * tdehtmlpart_p.h: add boolean to record whether we need to restore a
+ stored scroll offset or honour an anchor
+
+2004-12-09 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Add :enabled and :disabled pseudo-classes
+
+ * css/css_base.{h,cpp}: Parse new pseudoclases
+ * css/cssstyleselector.cpp: Implement new selectors
+
+2004-12-08 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge encoding detection from WebCore
+
+ * misc/decoder.{h,cpp}: Detect XML-encoding, comments in headers and other merges
+ * tdehtml_part.cpp: Frames inherits parents encoding as their default
+
+2004-12-08 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Merge :target pseudo-class from WebCore
+
+ * css/cssstyleselector.cpp: Uncomment :target handling
+ * xml/dom_docimpl.{h,cpp}: Add (set)cssTarget.
+ * tdehtml_part.cpp: Call setCssTarget on anchors
+
+2004-12-07 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement/merge CSS2-3 text-shadow property
+
+ * css/*: Merge values and parsing from WebCore
+ * render/render_style.{h,cpp}: Merge CSS3Inherited and ShadowData classes
+ * render/render_text.{h,cpp}: Implement new paintShadow function
+
+2004-12-06 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/bidi.cpp: Layout arabic numbers with a separator correctly.
+
+2004-12-02 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement remaining CSS2 list-style-types and a few CSS3
+
+ * rendering/render_list.cpp: New algorithms for hiragana, katakana,
+ armenian, georgian and decimal-leading-zero.
+ Also fix greek and latin list-styles for larger values.
+ * css/cssvalues.cpp: Parse box, -tdehtml-diamond, -tdehtml-arabic-indic,
+ -tdehtml-persian, -tdehtml-urdu and -tdehtml-upper-greek
+ * rendering/render_style.h: Expand list-style enum
+
+2004-11-30 Germain Garand <germain@ebooksfrance.org>
+
+ * css/cssstyleselector.{cpp,h}: fontSizes array now uses a QValueVector;
+ made "font-size: smaller/bigger" follow the standard font scale
+ when possible.
+
+ * css/html4.css: made <big>/<small> use font-size: bigger/smaller (#82657)
+
+2004-11-29 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * css/cssstyleselector.cpp: Handle :lang selector
+
+2004-11-27 Germain Garand <germain@ebooksfrance.org>
+
+ merge WebCore differences in logic for Auto table layout
+
+ * rendering/table_layout.cpp (calcEffectiveWidth/layout):
+ distribute remaining width starting with fixed rather than percent (#88104).
+
+2004-11-26 Germain Garand <germain@ebooksfrance.org>
+
+ merge zero deep-copy TokenizerString class from WebCore
+
+ * html/htmltokenizer.{cpp,h}
+ * misc/stringit.{cpp,h}
+ * xml/xml_tokenizer.{cpp,h}
+
+2004-11-23 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement the structual pseudo-selectors of CSS3.
+
+ * css/tokenizer.flex: Add nth and NOTFUNCTION tokens.
+ The later because the not-function is unique in its parsing.
+ * css/tokenizer.cpp: Manually merge output from flex :(
+ * css/parser.y: Update parsing of pseudo-functions.
+ Also enables correct parsing of :lang and :contains.
+ * css/css_base.{h,cpp}: Add new pseudoselectors
+ * css/cssstyleselector.cpp: Implement new selectors
+
+2004-11-22 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/bidi.cpp (layoutInlineChildren): for elements with some kind of
+ scrolling overflow and a variable height, include the scrollbar height in
+ calculations to avoid masking content (#89136).
+
+ * rendering/render_block.cpp (layoutBlock/layoutBlockChildren): ditto.
+
+ * rendering/render_box.cpp (contentWidth/contentHeight): subtract scrollbars
+ height/width when applicable.
+
+2004-11-22 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement CSS border on form-widgets
+
+ * css/cssvalues.in: Add -tdehtml-native
+ * css/cssparser.cpp: Accept -tdehtml-native as a border-type
+ * css/cssstyleselector.cpp: BNATIVE and not BNONE is now lowest border-style
+ * css/html4.css: Make -tdehtml-native default border-style for form-widgets
+ * render/render_style.h: Add BNATIVE
+ * render/render_object.cpp: Treat BNATIVE like BNONE
+ * render/render_replaced.cpp: Remove native, and paint CSS border when allowed
+
+2004-11-21 Germain Garand <germain@ebooksfrance.org>
+
+ float and flowAroundFloat fixes.
+
+ * css/html4.css: make fieldset -tdehtml-around-floats (#92979)
+
+ * rendering/render_block.cpp (layoutBlockChildren): cleanup float/flowAroundFloats
+ logic. Merges: add better RTL layouting of fAFs.
+ (lineWidth): guard against negative values
+ (clearFloats): don't copy floats if element defines a new block
+ formatting context (#93511)
+ (markAllDescendantsWithFloatsForLayout): add missing argument to
+ recursive call
+ (getClearDelta): merge
+ (InlineMinMaxIterator::next): exclude positioned elements
+ (calcInlineMinMaxWidth): merge float clearing adjustments
+ (calcBlockMinMaxWidth): ditto
+
+ * rendering/render_box.cpp (calcWidth): use containingBlockWidth
+
+ * rendering/render_object.cpp (isHR): new. Evil but useful for quirkmode (cf. usesLineWidth).
+ (flowAroundFloats): add replaced and overflowClip elements
+ (usesLineWidth): adapt to above.
+
+ * rendering/render_table.cpp (calcWidth): style()->flowAroundFloats => flowAroundFloats()
+
+2004-11-19 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_form.cpp (updateFromElement): restore scrolling position in case of a change
+ in text and do not trigger the update code more often than necessary
+
+2004-11-17 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * render/render_table.{h,cpp}: Improve distribution of excess height
+
+2004-11-17 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * render/render_table.cpp: Respect margins when calculating width to be distributed.
+
+2004-11-16 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_replaced.{cpp,h} (cancelPendingResize): allow
+ canceling of scheduled widget resizes, to avoid flicker when we
+ had to perform temporary layouts.
+
+ * rendering/render_table.cpp (calcRowHeight): displace resetting layout of cells with
+ percent children here and mark those dirty, or we might get zero-height widgets on resize
+ (cf. map24.com)
+ (layout): ditto.
+ (layoutRows): cancel widget resizes from temporary layouts.
+
+2004-11-16 Stephan Kulow <coolo@kde.org>
+
+ * rendering/break_lines.cpp (tdehtml): adding patch by Otto Pattara to support
+ libthai for correct line breaks
+
+2004-11-15 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Fix odd spacing in gmail-composer and zeg-shop.de
+
+ * render/render_box.h: Change auxillary box-size functions to protected
+ * render/render_table.cpp: Calculate percentage heights based on containing box
+ rather than viewport, by merging code with renderBox.
+
+2004-11-09 Germain Garand <germain@ebooksfrance.org>
+
+ fix globeandmail.com famlily of crashes (#65715)
+
+ * rendering/render_box.cpp (createAnonymousBlock): moved from RenderFlow
+ (restructureParentFlow): check soundness of parent's flow structure with regard to
+ the child's new display. Adapted from WebCore.
+ (setStyle): check parent if floats or positioned objects become in-flow
+ and thus affects flow structure.
+
+ * rendering/render_flow.cpp (createAnonymousBlock): moved.
+
+ * rendering/render_inline.cpp (splitInlines): use addChildToFlow
+ rather than appendChildNode
+
+ * rendering/render_line.cpp: display COMPACT cleanups
+
+ * rendering/render_object.cpp: ditto.
+
+2004-11-06 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement CSS3 property box-sizing to match MacIE, Opera and Mozilla
+
+ * css/css*.in: Add new property and primitive values
+ * css/cssparser.cpp: Detect content-box and border-box as primitives
+ * css/cssstyleselector.cpp: Parse box-sizing
+ * render/render_style.h: Add box-sizing to non-inherited values
+ * render/render_box.cpp: Consult box-sizing before adding padding and
+ border to width and height
+
+2004-11-05 Germain Garand <germain@ebooksfrance.org>
+
+ * tdehtml_part.cpp (closeURL/slotData/restoreState): avoid triggering
+ full repaints of the view before the first layout is done.
+
+2004-11-05 Germain Garand <germain@ebooksfrance.com>
+
+ * css/cssstyleselector.cpp (computeFontSizes): add compensated font scale
+ from Todd Fahrner's "Toward a standard font size interval system"
+ article for 12ppem and below (suggested by Bert Bos <bert@w3.org>)
+
+2004-11-04 Stephan Kulow <coolo@kde.org>
+
+ * rendering/bidi.cpp (bidiReorderLine): applying patch by Mitz Pettel
+ to fix neutral types at beginning of context
+
+2004-11-03 Germain Garand <germain@ebooksfrance.com>
+
+ * tdehtmlview.cpp (slotScrollBarMoved): make sure we are layouted before
+ scrolling if we are still loading (#51473)
+
+2004-11-02 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_replaced.cpp (setStyle): set hidden widgets to invisible
+
+ * xml/dom_docimpl.cpp (recalcStyleSelector): avoid invalid casts on XML documents
+
+2004-11-02 Germain Garand <germain@ebooksfrance.com>
+
+ * css/cssstyleselector.cpp (adjustRenderStyle):
+ ignore relative positioning on table sections. CSS 2.1 does not
+ define that, but it is a consensus amongst all major browsers.
+
+2004-11-01 Sandro Giessl <sandro@giessl.com>
+
+ * rendering/render_replaced.cpp (copyWidget): don't fill the
+ background of QFrames. they paint their own background now
+
+2004-10-30 Stephan Kulow <coolo@kde.org>
+
+ * html/html_formimpl.cpp (parseAttribute): ignore height element
+ for input elements that are not image
+
+2004-10-28 Stephan Kulow <coolo@kde.org>
+
+ * html/html_documentimpl.cpp (determineParseMode): adding a fixed list of
+ doctypes to enable quirks mode on (derived from Webcore, but majorly revised)
+ * enable strict CSS parsing also for transitional doctypes
+
+2004-10-27 Germain Garand <germain@ebooksfrance.com>
+
+ make font-sizes CSS2.1 compliant.
+
+ * css/cssstyleselector.cpp (computeFontSizes): use standard ratios
+ from CSS 2.1 15.7.
+ (applyRule): don't apply zoom factor to ems/exs relative values (#91228).
+
+ * css/html4.css: Hx elements - margin ratios are now 1.1/corresponding ratio.
+ Switch to absolute sizes from CSS 2.1 15.7
+
+2004-10-27 Stephan Kulow <coolo@kde.org>
+
+ * css/cssstyleselector.cpp (checkOneSelector): match exact matches case sensitive
+ only in XHTML - HTML attributes are all case insensitive
+
+2004-10-26 Stephan Kulow <coolo@kde.org>
+
+ * html/html_elementimpl.cpp (addCSSProperty): don't add all css properties in
+ lower case but select those those where it matters
+
+2004-10-26 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/bidi.{h,cpp}: Merge bidi-changes from WebCore
+
+2004-10-26 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (urlSelected): Only call recursiveFrameRequest if target is
+ different from _self, _top, _blank and _parent. See tests/frames/target/*.
+
+2004-10-25 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (processObjectRequest): connect to completed(bool) for <embed>
+ too, to avoid a never-ending-spinning-wheel on the following testcase
+ <META HTTP-EQUIV="Refresh" content="10;URL=www.kde.org"><EMBED>
+
+2004-10-25 Stephan Kulow <coolo@kde.org>
+
+ * html/html_elementimpl.cpp (addCSSProperty): add css properties parsed from
+ attributes as lower case
+
+2004-10-25 George Staikos <staikos@kde.org>
+
+ * rendering/render_image.cpp: Pass through the CachedObject so we can
+ use the suggested filename possibly provided by the HTTP headers.
+
+ * tdehtml_ext.cpp: Make use of the suggested filename for images.
+
+2004-10-24 David Faure <faure@kde.org>
+
+ * html/html_formimpl.cpp (value): Fixed m_value vs ATTR_VALUE problem
+ which didn't allow sending mail on gmail.google.com. Testcases:
+ forms/form_setattribute.html, mozilla/dom/dom-html/{hfor009.html,hinp017.html}
+
+2004-10-22 Stephan Kulow <coolo@kde.org>
+
+ * ecma/kjs_window.cpp (tryCall): merging handling of event handlers
+
+ * css/cssparser.cpp (parseValue): implementing CSS 2.1 compliant parsing
+ of background-position (#91572)
+
+2004-10-21 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ Implement limited DHTML capabilities to the layer implementation
+
+ * html/html_miscimpl.{h,cpp}: Extract collection of all layers
+ * dom/html_block.{h,cpp}: Add layer DOM
+ * dom/html_document.{h,cpp}: Add .layers to document DOM
+ * ecma/kjs_html.{h,cpp}: Add layer DHTML and allow layers to be found by ID
+ * ecma/kjs_window.cpp: Allow layers to be found by ID
+
+2004-10-19 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_box.{h,cpp}: Merge min,max-height fixes
+
+2004-10-19 Germain Garand <germain@ebooksfrance.org>
+
+ finish merge of static position for positioned objects
+
+ * css/cssstyleselector.cpp (adjustRenderStyle): remember our original display
+ * rendering/bidi.cpp (appendRun): include positioned objects with static X/Y,
+ now that we use those.
+ (findNextLineBreak): adjust static position
+
+ * rendering/render_block.cpp (layoutBlockChildren): ditto.
+
+ * rendering/render_box.cpp (containingBlockWidth): use usesLineWidth
+ (position): activate static position logic
+ (calcAbsoluteHorizontal): replace static position calculation
+ (calcAbsoluteVertical): ditto.
+
+ * rendering/render_object.cpp (removeChild): fix typo
+ (usesLineWidth): merge usesLineWidth from WebCore
+
+ * rendering/render_style.h (NonInheritedFlags::): originalDisplay member
+ (setBitDefaults): initialize the above
+ (originalDisplay/setOriginalDisplay): accessors
+ (isDisplayReplacedType/isDisplayInlineType/isOriginalDisplayInlineType):
+ helpers
+
+2004-10-18 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * rendering/render_table.cpp: Merge layout fixes from Webcore
+
+2004-10-17 Stephan Kulow <coolo@kde.org>
+
+ * ecma/kjs_dom.cpp: adding patch by Richard Lärkäng to support IE
+ extension insertAdjacentHTML (#33968)
+
+2004-10-16 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ * html/html_formimpl.cpp: Escape otherwise unencodable characters.
+ Matches the behavior of Gecko.
+
+2004-10-15 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_form.cpp (updateFromElement): don't set assume <select>
+ got items when we calculate a height for items (#87466)
+
+ * css/html4.css: changing default horizontal margins for H1-H6 from
+ auto to 0 (#91327)
+
+2004-10-15 Germain Garand <germain@ebooksfrance.org>
+
+ bring z-order to QScrollView
+
+ * html/html_formimpl.cpp (defaultEventHandler): propagate events to
+ QScrollView
+
+ * tdehtmlview.{cpp,h}: QScrollview needs fast repaints. Fix
+ background color of QFrames.
+
+ * rendering/render_form.cpp (createListBox/TextAreaWidget):
+ make those widgets z-ordered as well.
+
+ * rendering/render_replaced.cpp (paintWidget): optimize painting by
+ avoiding unnecessary background repaints and by using a shared
+ paint buffer.
+
+2004-10-15 Germain Garand <germain@ebooksfrance.org>
+
+ display: compact fixes.
+
+ * rendering/bidi.cpp: remove checks for display: compact,
+ not needed anymore.
+
+ * rendering/render_block.cpp (layoutBlockChildren):
+ simpler implementation for compact display: do not insert the
+ compact child within the next block anymore.
+ Solves lot of problems with host blocks having non-inline children.
+
+ * rendering/render_object.{cpp,h} (getVerticalPosition): add
+ ability to compute vertical position with respect to other
+ RenderObjects than parent.
+
+2004-10-14 David Faure <faure@kde.org>
+
+ * html/htmltokenizer.cpp (parseTag): Merged patch by John Sullivan (safari)
+ to refuse skip more <script> tags depending on the value of type and language.
+
+ * html/html_documentimpl.cpp (determineParseMode):
+ When the document is loaded as text/html, even if xhtml doctype, activate case-insensitive
+ ("htmlCompat") lookup of tags and attributes (but not in CSS parser). (#86446)
+
+2004-10-14 Allan Sandfeld Jensen <kde@carewolf.com>
+ * rendering/*.*: WebCore merge/port of layouted->needsLayout
+
+2004-10-11 David Faure <faure@kde.org>
+
+ * xml/dom_nodeimpl.cpp (dispatchGenericEvent): Fixed stopPropagation
+ when called from the target node itself (#90750).
+
+2004-10-11 Harri Porten <porten@kde.org>
+
+ * ecma/*.cpp: return an empty string (instead of null) when
+ querying unset string properties
+
+ * ecma/kjs_html.cpp: use full url for Image.src.
+
+2004-10-08 David Faure <faure@kde.org>
+
+ * ecma/kjs_html.cpp (KJS::HTMLCollection::tryGet):
+ return Undefined instead of Null for out-of-range indices.
+
+2004-10-07 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp
+ (updateFirstLetter): move update of first-letter from addChildToFlow to
+ setStyle/close. Better drilling logic. Use RenderTextFragment to
+ correctly handle text-transform on first-letter(#76078).
+ (addChildToFlow): ditto. fix display: block on pseudo-elements (#90917)
+ (layoutBlockChildren): only clear if floats actually changed our
+ height.
+ * rendering/render_object.h (node): accessor to m_node
+ * rendering/render_text.{cpp,h}: merge RenderTextFragment class
+ * xml/dom_nodeimpl.h (setRenderer): accessor
+
+2004-10-07 Allan Sandfeld Jensen <kde@carewolf.com>
+ * rendering/render_style.h:
+ WebCore merge of paged media attributes (#68930).
+ * rendering/render_block.cpp (paintObject):
+ Break on page-break-before and -after.
+ * rendering/render_canvas.{h,cpp}:
+ Merge bestTruncatedAt from WebCore.
+ * tdehtmlview.cpp (print):
+ Use bestTruncatedAt for detect truncated pages.
+
+2004-10-07 David Faure <faure@kde.org>
+
+ * xml/dom_nodeimpl.cpp (dispatchWindowEvent): Emit load event for frames
+ from there, to avoid bubbling (safari merge)
+
+2004-10-05 Rob Buis <buis@kde.org>
+ * render/render_form.{cpp,h}:
+ Implemented onchange event generating for checkbox and radio buttons (fixes #51765).
+
+2004-10-05 David Faure <faure@kde.org>
+
+ * html/html_baseimpl.cpp (parseAttribute):
+ Set event listener on frame element itself (fixes #72440)
+ * xml/dom_docimpl.cpp (ownerElement): Safari merge.
+ * html/html_documentimpl.cpp (close):
+ Emit onload event for frames (famous gmail bug).
+
+ * ecma/kjs_html.cpp (getValueProperty):
+ Don't return null when innerText or innerHTML is empty.
+
+2004-10-04 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (processObjectRequest):
+ Fixed showing of iframe hidden with display=none (#84332).
+
+2004-09-16 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_inline.{cpp,h} (paintOutline): removed.
+ (paintOutlinePath): Paints an outline by following a path consisting of
+ rectangular line segments.
+ (appendIfNew): Append point if not contained at end.
+ (reduceSpike): Reduce spikes.
+ (reduceSegmentSeparators): Redoce segment separators.
+ (appendPoint): Appends point with reductions.
+ (collectHorizontalBoxCoordinates): Determines points for top-/bottommost line box.
+ (lineBoxesDisjoint): Checks whether two line boxes don't share a common x-range.
+ (collectVerticalBoxCoordinates): Determines points for left/right sides of line boxes.
+ (linkBeginToEnd): Links the last point to the first one, reducing even more.
+ (paintOutlines): Uses new painting outline algorithm.
+ (kSwap): Swaps two variables (candidate for misc?)
+ (bsOrientation): returns whether border side is horizontal/vertical.
+ (newBorderSide): Determines new border side.
+ (paintOutlineSegment): Paints a straight outline segment.
+
+2004-09-11 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (defaultEncoding, encoding, createDecoder):
+ Make default charset latin1 over HTTP, keep default to locale on other protocols.
+
+2004-09-02 Leo Savernik <l.savernik@aon.at>
+
+ * html_formimpl.{cpp,h} (HTMLTextAreaElementImpl::value):
+ Only take text from RenderTextArea when it has been fully initialized.
+ Mark it fully initialized when RenderTextArea has been initialized
+ from the DOM.
+ (HTMLTextAreaElementImpl::setValue): Mark element as initialized after
+ setting.
+ * render_form.cpp (RenderTextArea::setStyle):
+ Block signals on call to QTextEdit::setAlignment. Otherwise, a bogus
+ textChanged signal is emitted.
+
+2004-08-27 Germain Garand <germain@ebooksfrance.org>
+
+ scope: - more accurate completed() signal.
+ - anchor jumps (#57360)
+
+ * tdehtml_part.cpp (openURL): when restoring a previous scroll
+ position on reload, avoid jumping to anchors.
+ (gotoAnchor): keep jumping at least while we are parsing.
+ (gotoAnchor): "top" and "" anchors mean top of document.
+
+ (checkCompleted): entrust the view to emit completed on our behalf
+ after any pending layout/repaint is done.
+
+ * tdehtmlview.{cpp,h}: ditto
+
+ * xml/dom_nodeimpl.cpp (getUpperLeftCorner/getLowerRightCorner):
+ use inlineYPos for text objects (#57360 c.#17).
+
+2004-08-27 Leo Savernik <l.savernik@aon.at>
+
+ * html/html_tableimpl.cpp (HTMLTableCellElementImpl::attach):
+ Fixed explicit setting of border to 0 width.
+
+2004-08-24 Leo Savernik <l.savernik@aon.at>
+
+ * ecma/kjs_html.{cpp,h} (HTMLDocument):
+ Added Javascript-support for HTMLDocument.compatMode.
+
+2004-08-23 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_layer.{cpp,h} (Marquee): Added a stop method for
+ the ECMAScript invokation.
+ Fixed starting and stopping and suspending by properly discriminating
+ against them.
+
+2004-08-19 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_body.cpp (setStyle): only disallow fixed positioning
+ on body, not relative/absolute (#77048, #76982).
+
+ * rendering/render_box.cpp (paintBackgroundExtended): make sure backgrounds paint
+ in the border box and not just in the padding box (WC merge - meyerweb.com/unsorted/bg-position.html).
+
+2004-08-18 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_block.cpp (layoutBlock, layoutBlockChildren,
+ layoutPositionedObject): Ensure that m_overflowWidth/m_overflowHeight
+ get updated properly to include relatively positioned
+ elements, but to exclude the overflow-area of clipped children.
+
+ * rendering/render_box.cpp (repaint): Removed superfluous null ptr check.
+ Use effectiveWidth/Height instead of overflowWidth/Height.
+
+ * rendering/render_canvas.cpp (docHeight): Fixed superfluous vertical
+ scrollbars on clipped children.
+ (docWidth): Fixed superfluous horizontal scrollbars on clipped children.
+
+ * rendering/render_flow.cpp (repaint):
+ Use effectiveWidth/Height instead of overflowWidth/Height.
+
+ * rendering/render_object.h: Added effectiveWidth/Height.
+ Made hasClip and hasOverflowClip const.
+
+2004-08-05 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (layoutBlockChildren): when positionning floats,
+ use the margin tracking variables, and not the prevFlow -there might be
+ self-collapsing blocks in between (#85150).
+ (calcMinMaxWidth): better calculation merged from WebCore. Fixes a few testcases.
+
+ * rendering/render_object.h (collapsedMarginTop/Bottom): don't avoid max(Top|Bottom)Margin,
+ they are virtuals reimplemented for RenderBlock.
+
+ * rendering/render_object.cpp (createObject): do not set the style before
+ the renderer is assigned to a node. Fixes Marquee initial layout
+ (unsorted/RESOLVED-57087-1342.html) failing because of 'element()->renderer() == this' checks.
+
+ * xml/dom_elementimpl.cpp (attach): ditto
+
+2004-08-04 Germain Garand <germain@ebooksfrance.org>
+
+ * tdehtmlview.cpp (resizeEvent): take care, in case we are shrinking,
+ not to pass past the content limits yet. Next layout will calculate
+ if we positively need scrollbars or not (#84798).
+
+ * rendering/render_canvas.cpp (layout): remove scrollbar flickering turnarounds.
+ instead, account for a scrollbar hysteresis level when sizing the content (#61730).
+
+2004-07-30 Jean-Baptiste Mardelle <bj@altern.org>
+ * tdehtmlview.{cpp,h} (displayAccessKeys): When accesskeys are activated,
+ small tooltips appear showing existing accesskeys on the page.
+
+2004-07-28 Stephan Kulow <coolo@kde.org>
+
+ * html/html_miscimpl.cpp (getNamedItem): more investigation on tags returned
+ by name attribute in document.all
+
+2004-07-28 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtmlview.{cpp,h} (KHTMLToolTip::maybeTip): Query <area> elements
+ of image maps.
+ (dispatchMouseEvent): Added parameter innerNonSharedNode.
+ * tdehtml_part.{cpp,h}: Added method nonSharedNodeUnderMouse.
+ * xml/dom_docimpl.cpp (prepareMouseEvent): Initialize
+ innerNonSharedNode in DOM mouse event.
+ * xml/dom_nodeimpl.h: Added innerNonSharedNode to
+ NodeImpl::MouseEvent.
+ * html/html_imageimpl.h: Added cachedRegion() for being able to
+ retrieve the region in KHTMLToolTip.
+
+2004-07-20 Stephan Kulow <coolo@kde.org>
+
+ * css/parser.y: catching imports that come between rules.
+ They have to be ignored (css1/test11.htm)
+
+2004-07-14 Jean-Baptiste Mardelle <bj@altern.org>
+ * tdehtmlview.{cpp,h}: Accesskeys now activated when pressing & releasing
+ the crtl key (#83053).
+
+2004-07-12 Jean-Baptiste Mardelle <bj@altern.org>
+ * html/html_formimpl.{h,cpp}: Make form labels clickable (#59489)
+ * tdehtmlview.cpp (focusNodeWithAccessKey): Make accesskeys work for labels
+
+2004-07-12 Germain Garand <germain@ebooksfrance.org>
+
+ * ecma/kjs_navigator.{h,cpp} (getValueProperty):
+ implement navigator.productSub. Fixes most
+ instances of #68271
+
+2004-07-10 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_layer.cpp (calculateClipRects):
+ absolutely positioned objects must update the overflowClipRect
+ passed to relatively positioned child layers to match the
+ posClipRect in effect (#67665/#72994).
+
+2004-06-30 Tobias Anton <anton@stud.fbi.fh-darmstadt.de>
+ * tdehtmlview.{cpp,h}:
+ integrated keyboard tabbing with mouse scrolling.
+ Hitting tab skips at most one page, but respects
+ the tabindex ordering of the document.
+ If the document has been scrolled by the mouse before,
+ "tab" now selects the first/last element in the visible
+ area of the page.
+
+2004-06-26 Germain Garand <germain@ebooksfrance.org>
+
+ * css/html4.css:
+ - do not set vertical-align on the table: it breaks inline-table's
+ default (baseline). cf.webcore/fast/inline-block/001.html
+ - default all of tbody/tfoot/thead to 'vertical-align: middle'
+ as per specification.
+
+ * rendering/render_object.cpp:
+ (getVerticalPosition): fix inverted logic. cf.unsorted/74399.html
+ (lineHeight/baselinePosition): inline-blocks behaves like replaced elements
+ only after they are layouted.
+
+ * rendering/render_table.h (position): remove empty reimplementation:
+ inline-tables need positioning. cf.webcore/fast/inline-block/001.html
+
+ * rendering/render_box.cpp (calcAbsoluteHorizontal): subtract p/b width
+ when shrinking-to-fit, otherwise it gets accounted for twice.
+
+2004-06-22 Zack Rusin <zack@kde.org>
+
+ * ecma/kjs_events.cpp (JSLazyEventListener): Adding a destructor
+ which is now needed since Niko's eventlistener changes make
+ jseventlistener destructor not remove the listener from
+ jsEventListeners
+
+2004-06-22 Germain Garand <germain@ebooksfrance.org>
+
+ Scope: Inline-blocks inlining. Merge Webcore improvements for
+ Fieldset/Legend
+
+ * css/html4.css: Legend => display: block.
+
+ * html/html_formimpl.{cpp,h} (addChild): remove.
+
+ * rendering/render_block.cpp:
+ (setStyle): do not overwrite inline status
+ (makeChildrenNonInline): change assert
+ (layoutBlock): account for inline-blocks
+ (layoutBlockChildren): ditto
+ (clearFloats): ditto. bail out.
+
+ * rendering/render_box.cpp:
+ (calcWidth): fix logic. cf.css1/test43.htm
+ (calcHeight): fix logic
+
+ * rendering/render_form.cpp:
+ (layoutLegend): merges from WebCore-125
+ (findLegend): ditto
+ (paintBoxDecorations): ditto
+ (setStyle): cf.webcore/fast/forms/007.html
+
+2004-06-22 Germain Garand <germain@ebooksfrance.org>
+
+ Scope: avoid leaking placeholder InlineBoxes. Cleanups.
+
+ * rendering/bidi.cpp (Bidinext): simplified logic. Do not return each
+ InlineFlow twice.
+ (layoutInlineChildren): clear InlineBoxes on relayout.
+
+ * rendering/render_object.{cpp,h}:
+ (deleteInlineBoxes): new virtual method.
+
+ * rendering/render_box.{cpp,h}: added m_placeHolderBox member.
+ (createInlineBox/deleteInlineBoxes): reimplemented.
+
+ * rendering/render_flow.{cpp,h}:
+ (createInlineBox/deleteInlineBoxes): ditto.
+
+ * rendering/render_replaced.cpp (detach): call deleteLineBoxes
+
+ * rendering/render_text.{cpp,h} (deleteInlineBoxes): reimplemented, replacing
+ deleteTextBoxes
+ (~RenderText): no need to clear lineboxes twice.
+
+2004-06-13 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.cpp: (clear) Stopping marquees.
+ * css/cssparser.cpp: (parserValue) Parse overflow: marquee.
+ Inserted CSS3 Properties section.
+ Moved -tdehtml-user-input to CSS3 Properties.
+ Added parsing of -tdehtml-marquee{,-direction,-increment,-style,-repetition,
+ -speed}.
+ * css/cssproperties.{c,h}: Regenerated.
+ * css/cssproperties.in: Added -tdehtml-marquee{,-direction,-increment,
+ -style,-repetition, -speed} keywords.
+ * css/cssstyleselector: (applyRule) Handle overflow: marquee.
+ Handle applying of -tdehtml-marquee{,-direction,-increment,-style,-repetition,
+ -speed}.
+ * css/cssvalues.{c,h}: Regenerated.
+ * css/cssvalues.in: Added marquee, forwards, backwards, ahead, reverse,
+ up, down, slow, fast, infinite, slide, alternate, and unfurl keywords.
+ * css/html4.css: Updated rule to make marquee behave like marquee.
+ * html/html_blockimpl.{cpp,h}: Added class HTMLMarqueeElementImpl.
+ * html/html_elementimpl.cpp: (addCSSLength) Fixed adding numeric lengths
+ without unit.
+ * html/html_parser.cpp: (getElement) Made ID_MARQUEE generate an
+ HTMLMarqueeElement.
+ * htmlattrs.{c,h}: Regenerated.
+ * htmlattrs.in: Added behavior, direction, loop, scrollamount, scrolldelay,
+ truespeed attribute keywords.
+ * rendering/bidi.cpp: (RenderBlock::findNextLineBreak): marquee-related extensions.
+ * rendering/render_block.{cpp,h}: Updated lowestPosition, rightmostPosition, added
+ leftmostPosition.
+ * rendering/render_box.{cpp,h}: Updated lowestPosition, rightmostPosition, added
+ leftmostPosition.
+ (setStyle) Inserted call to styleChanged of layer.
+ (calcWidth) Used containing block's direction when aligning this box.
+ (calcWidthUsing) Used centralized sizesToMaxWidth() method.
+ (calcHorizontalMargins) Margin fix for inline blocks.
+ * rendering/render_flow.{cpp,h}: Updated lowestPosition, rightmostPosition, added
+ leftmostPosition.
+ * rendering/render_layer.{cpp,h}: Added Marquee class which takes care of
+ the shifting operations.
+ Added styleChanged and suspendMarquees methods.
+ (updateLayerPositions) Inserted call to updateMarqueePosition.
+ (scrollToOffset) Took care of marquee.
+ * rendering/render_object.{cpp,h}: Updated lowestPosition, rightmostPosition,
+ added leftmostPosition.
+ Added isHTMLMarquee, sizesToMaxWidth, and isCompact.
+ * rendering/render_style.{cpp,h}: Added CSS3NonInheritedData structure.
+ Added StyleMarqueeData. Added OMARQUEE to EOverflow.
+ Added EMarqueeBehavior, EMarqueeDirection.
+ Added CSS3 Getter Methods section.
+ Moved userInput to CSS3 Getter Methods section.
+ Added marqueeIncrement, marqueeSpeed, marqueeLoopCount,
+ marqueeBehavior, marqueeDirection.
+ (RenderStyle::RenderStyle) Instantiated CSS3NonInheritedData there.
+ Added respective setters to new CSS3 Setters section.
+ * rendering/render_text.{cpp,h}: Removed rightmostPosition.
+ * xml/dom_docimpl.cpp: (createHTMLElement) Made it return a
+ HTMLMarqueeElement for ID_MARQUEE.
+
+2004-06-10 Zack Rusin <zack@kde.org>
+
+ * xml/dom_textimpl.cpp (escapeHTML): Move from dom_elementimpl.cpp,
+ and use it to espace text nodes in here
+ * xml/dom_elementimpl.cpp: propely handle attributes,
+ * dom/dom_doc.cpp (toHTML): deprecate in favor of toString and
+ implement in terms of toString,
+ * dom/html_elementimpl.h (innerHTML): implement in terms of
+ toString,
+ * xml/dom_nodeimpl.{h,cpp}: remove the toHTML and recursive_toHTML
+ methods,
+
+2004-06-09 Zack Rusin <zack@kde.org>
+
+ * xml/dom_nodeimpl.h, xml/dom_xmlimpl.{h,cpp},
+ xml/dom_textimpl.{h,cpp}, xml/dom_elementimpl.{h,cpp},
+ xml/dom_docimpl.{h,cpp}, html/html_elementimpl.{h,cpp},
+ dom/dom_doc.{h,cpp} : Merging in toString method which serializes
+ the DOM tree back to a string
+
+2004-06-09 Zack Rusin <zack@kde.org>
+
+ * xml/xml_tokenizer.{h,cpp}: adding bool isWaitingForScripts()
+ const method to tokenizer interface which should return true if
+ the tokenizer is waiting for scripts to finish. Adding the method
+ to XMLTokenizer,
+ * html/htmltokenizer.{h,cpp}: adding the isWaitingForScripts
+ method,
+ * xml/dom_docimpl.cpp (close): On an explicit document.close()
+ don't destroy the tokenizer if it's still waiting on external
+ scripts
+
+2004-06-09 Zack Rusin <zack@kde.org>
+
+ * ecma/kjs_events.{h,cpp}: made the listener in jseventlistener an
+ object instead of a value and switch its function accordingly,
+ adding JSLazyEventListener which delays evaluation of event
+ handlers,
+ * ecma/kjs_window.{h,cpp}: adding getJSLazyEventListener which
+ creates lazy listeners,
+ * ecma/kjs_dom.cpp (getListener): switched to use lazy listeners,
+ * ecma/kjs_html.cpp (getValueProperty): adding check of whether
+ listener implementation is in place (listener is valid),
+ * ecma/kjs_proxy.cpp (createHTMLEventHandler): switched to use
+ getJSLazyEventListener,
+
+2004-06-08 Zack Rusin <zack@kde.org>
+
+ * html/htmltokenizer.cpp (parseEntity): Fix to make 8-character
+ hexadecimal entities work in tdehtml from Darin Adler. Testcase at
+ http://www.alanwood.net/unicode/deseret.html
+
+2004-06-06 Zack Rusin <zack@kde.org>
+
+ * xml/dom_docimpl.cpp (getId): do html lookup if specified even if not
+ in a html document since elements can be in xhtml the namespace
+
+ * xml/dom_docimpl.h (hasPendingSheets): adding function returning true,
+ if stylesheets are currently loading for document.
+
+ * xml/xml_tokenizer.cpp: Merging table hack for XML parsing from
+ Safari, merging in character changes, but with a fix which we
+ need, delaying attaching of text nodes till parsing finishes (
+ also merged from the Safari team), adding FOUC prevention code.
+
+2004-06-02 Zack Rusin <zack@kde.org>
+
+ * xml/dom_xmlimpl.cpp: Correctly handle stylesheet loading in
+ XML documents (try to avoid FOUC)
+
+ * xml/xml_tokenizer.{h,cpp}: Added pushNode(), popNode() and
+ currenNode() methods. Removed m_currentNode memeber and switched
+ node construction to a stack based ones. Try to attach to the
+ parent of the tag which encloses us if it can't handle children.
+
+2004-05-28 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_object.cpp: (drawBorder) Make use of Mozilla's
+ border-bevel coloring algorithm.
+
+2004-05-14 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_table.cpp: (RenderTableCell::paintBoxDecorations)
+ Make it unconditionally paint background on empty table-cells
+ with empty-cells:hide in quirks mode.
+
+2004-05-13 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/font.cpp: (drawDecoration)
+ rendering/render_line.cpp: (InlineFlowBox::paintDecoration)
+ Increased width of text decoration by one.
+
+2004-05-12 Leo Savernik <l.savernik@aon.at>
+
+ * css/cssstyleselector.cpp: (applyRule) Make borders be at least one
+ pixel wide between 1pt and 0.025pt. This makes konqueror's behaviour
+ more compatible to Mozilla's.
+
+2004-05-09 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/font.cpp: (drawDecoration) Honored line thickness.
+ Used fillRect instead of drawLine.
+
+ * rendering/render_layer.cpp: (paintLayer) Added invokation of
+ PaintActionSelection phase when there is a selection.
+
+ * rendering/render_line.cpp: (InlineFlowBox::paintDecorations)
+ Honored line thickness. Used fillRect instead of drawLine.
+ Actually use it.
+
+ * rendering/render_text.cpp: (paint) Stopped drawing text in PaintActionSelection.
+ Stopped drawing selection in any other phase.
+ Make it draw text-decorations only in quirks mode.
+
+2004-05-09 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_block.cpp: (paint, paintObject, paintFloat)
+ Introduced maximalOutlineSize, PaintActionOutline phase.
+
+ * rendering/render_box.cpp: (setStyle) Updating maximumOutlineSize.
+
+ * rendering/render_canvas.{cpp,h}: Added maximumOutlineSize
+ member, setter, and getter.
+
+ * rendering/render_image.cpp: (paint) Added handling new
+ PaintActionOutline phase.
+
+ * rendering/render_inline.{cpp,h}: Moved paintOutline{s,} from RenderText
+ to RenderInline.
+ (paint) Handled PaintActionOutline phase.
+
+ * rendering/render_layer.cpp: (paintLayer) Added invokation of
+ PaintActionOutline phase.
+
+ * rendering/render_object.{cpp,h}: Added PaintActionOutline phase and
+ maximumOutlineSize.
+
+ * rendering/render_table.cpp: Added code for handling outlines.
+
+ * rendering/render_text.{cpp,h}: (paint) Removed outline painting
+ code from there.
+ Moved paintOutline{s,} to RenderInline.
+
+ * xml/dom_nodeimpl.cpp: (NodeBaseImpl::setFocus) Fixed recursive
+ application of focus to child elements now that outline correctly
+ handles block elements.
+
+2004-05-06 Tobias Anton <anton@stud.fbi.fh-darmstadt.de>
+
+ * html/htmlparser.cpp (class KHTMLParser): use setCurrent() after reset()
+ to avoid a memleak whenever the parser is used on a DocumentFragment.
+
+2004-05-04 Leo Savernik <l.savernik@aon.at>
+
+ * css/cssparser.cpp: (parseValue) Updated order of border values to
+ accomodate border precedence.
+ Made all colors accept transparent.
+
+ * css/cssstyleselector.cpp: (applyRule) Fixed recognition of transparent
+ colors so that BorderValue::isTransparent returns true for border colors.
+
+ * css/cssvalues.in: Updated order of border values to accomodate border
+ precedence.
+
+ * rendering/render_form.cpp: (paintBorderMinusLegend) Honor new border
+ precedence.
+
+ * rendering/render_object.cpp: (drawBorder) Inserted forgotten break.
+ (paintBorder) Make border-color: transparent work like in WebCore.
+ Honor new border precedence.
+
+ * rendering/render_object.h: Introduced PaintActionCollapsedTableBorders.
+
+ * rendering/render_style.h: Updated EBorderStyle to accomodate border
+ precedence.
+ (class BorderValue) Merged nonZero and isTransparent to make border
+ drawing code work.
+ Merged lots of stuff needed for border-collapse.
+ Set initial value of empty-cells to hide (to match NN, Moz, IE behaviour).
+
+ * rendering/render_table.cpp: (RenderTable::RenderTable,
+ RenderTable::setStyle) Merged small adaptations for border-collapse.
+ (RenderTable::paint) Merged border-collapse paint code from WebCore.
+ (class RenderTable) Merged new paintBoxDecorations code.
+ (class RenderTableCell) Merged lots of helper classes from WebCore.
+ (RenderTableSection::paint) Fixed cutting off of borders spilling into
+ neighbour cells.
+ (RenderTableCell::paint) Merged paint code from WebCore.
+
+ * rendering/render_table.h: Added prototypes/member variables.
+
+2004-04-18 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.cpp: (extendSelectionTo): Fixed deselection of whole
+ word/line at line boundaries in ExtendByWord/ExtendByLine mode.
+
+2004-04-18 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.cpp: Merged firstRunAt, lastRunAt from WebCore.
+ (tdehtmlMouse{Press,DoubleClick,Move,Release}Event): Support extending selection
+ by word and by line as mandated by the KDE style guide.
+ (tdehtmlMousePressDoubleClickEvent): Fixed automatic scrolling when mouse
+ moves off the view while selecting.
+ (extendSelection): Make it support extending by line by merging
+ WebCore's startAndEndLineNodesIncludingNode into it.
+ Fixed issue with double word selection when between two words.
+
+ * tdehtmlpart_p.h: added m_initialNode, m_initialOffset and
+ m_extendMode.
+
+ * tdehtmlview.cpp (extendSelection): Initialize all relevant fields for selection.
+
+ * rendering/render_text.h: Merged inlineTextBoxes function, needed by
+ firstRunAt, lastRunAt.
+ (findInlineTextBox): Make it public.
+
+2004-04-15 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_caret{.cpp,_p.h}: Vast changes.
+ Added classes CaretBox, CaretBoxLine, CaretBoxIterator,
+ EditableCaretBoxIterator. Changed every other class.
+
+ * tdehtmlview.[cpp,h}: (class KHTMLView) Adapt to tdehtml_caret* changes.
+ (KHTMLToolTip::maybeTip) Save tooltip position instead of recalculating it.
+
+ * rendering/render_{inline,box}.{cpp,h}: (Render{Box,Inline}::caretPos)
+ Handle outside caret positions.
+
+ * rendering/render_{image,br}.{cpp,h}: Remove superfluous
+ Render{Image,BR}::caretPos.
+
+ * rendering/render_line.h: (InlineBox::maxOffset) Return 0 instead of 1.
+
+ * rendering/render_object.{cpp,h}: (RenderObject::caretPos) Introduce
+ flags to denote outside positions.
+ Add RenderObject::isRenderReplaced.
+
+ * rendering/render_replaced.h: Add RenderReplaced::isRenderReplaced
+ returning true.
+
+ * rendering/render_text.{cpp,h}: (RenderText::caretPos) Handle flags.
+
+ * xml/dom_nodeimpl.{cpp,h}: (NodeImpl::getCaret) Handle DOM Range
+ positions.
+ Remove unused NodeImpl::{prev,next}LeafNode.
+ (NodeImpl::maxOffset) Return child node count instead of 1 for element
+ nodes.
+ (NodeBaseImpl::childNode): Don't crash on out-of-bounds offsets.
+
+2004-04-02 Dirk Mueller <mueller@kde.org>
+
+ * misc/loader.cpp (slotFinished): store suggestedfilename for later.
+ (movieResize): start with the notify. Experimental.
+
+ * rendering/render_layer.cpp (nodeAtPoint): make sure we set
+ the urlelement to the innermost urlelement. otherwise
+ overURL and the actual url followed during click get out of sync.
+
+2004-03-23 Dirk Mueller <mueller@kde.org>
+
+ * tdehtml_part.cpp (checkLinkSecurity): Be stricter.
+
+ * rendering/render_frames.cpp (updateWidget): readd the recursion protection.
+
+2004-03-21 Arend van Beelen jr. <arend@auton.nl>
+ * tdehtml_part.cpp/.h: if text in a link is highlighted, the link now receives
+ focus.
+
+ * tdehtmlview.cpp: made type-ahead find more aggressive by grabbing the keyboard
+ when active, this way it temporarily overrules single-letter shortcuts as seen
+ in KMail. Note it immediately releases the keyboard when it looses focus.
+
+2004-03-20 Arend van Beelen jr. <arend@auton.nl>
+ * tdehtml_part.cpp/.h: finished new searching API.
+
+ * tdehtmlview.cpp/.h: implemented type-ahead find (#51259).
+
+2004-03-21 Dirk Mueller <mueller@kde.org>
+
+ * html/html_formimpl.cpp (encoding): fix submission of forms
+ without file upload (#77382).
+
+ * css/css_renderstyledeclarationimpl.cpp (getPropertyCSSValue): fix crash (#77324).
+
+2004-03-20 Dirk Mueller <mueller@kde.org>
+
+ * xml/dom_docimpl.cpp (processHttpEquiv): improve refresh handling for negative and
+ slightly malformed delays (#78049)
+
+2004-03-18 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp, xml/dom_docimpl.cpp: accesskey attribute support
+
+2004-03-03 Dirk Mueller <mueller@kde.org>
+
+ * html/htmlparser.cpp (getElement): try to avoid nesting <nobr> and <wbr>,
+ but don't forbit it.
+
+2004-03-01 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_text.cpp (calcMinMaxWidth): some more hacks for white-space !=
+ normal.
+
+ * rendering/render_object.cpp (drawBorder): use drawPixel directly.
+ turns out to be more reliable and equally fast (#62296).
+
+2004-02-29 Dirk Mueller <mueller@kde.org>
+
+ * html/html_documentimpl.cpp (determineParseMode): treat xhtml transitional
+ that way (#76449).
+
+ * rendering/bidi.cpp (findNextLineBreak): make sure we move
+ replaced elements, that don't fit on a line below the floats (#74609).
+
+ * rendering/render_replaced.cpp (calcMinMaxWidth): respect
+ padding and borders (#65788).
+
+ * rendering/render_form.h (RenderFormElement): make sure we never
+ end up getting a border or padding for form elements.
+
+ * rendering/render_frames.cpp (partLoadingErrorNotify): don't trigger
+ slotPartLoadingErrorNotify twice.
+
+ (slotPartLoadingErrorNotify): avoid KMessageBox deletion race.
+
+ * misc/loader_jpeg.cpp: fix incredibly rare lockup in jpeg decoder.
+
+2004-02-28 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (layoutBlockChildren):
+ - displace the check for if we need to relayout our childs
+ because of a float. It was outside of loop (#71445)
+ - remove check for floatBottom() > m_y has it seems outdated.
+
+2004-02-25 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_text.h (class InlineTextBox): rename width(int)
+ to widthFromStart(int), since it otherwise clashes with upcoming
+ Safari merges.
+
+ * rendering/render_image.cpp (notifyFinished): forward the
+ notifyFinished call to the inherited class.
+
+ * rendering/render_inline.h (class RenderInline):
+ constructor/destructor cleanup.
+
+ * misc/htmlattrs.h: don't export getAttrName symbol.
+
+ * rendering/render_object.h (class RenderObject): move background
+ repaint handling over here, since TableSections don't inherit RenderBox,
+ but still have a background.
+
+ * tdehtml_settings.cc (init)/html4.css: MediumFontSize up to 12. Form elements
+ get font-size: small instead.
+
+2004-02-24 Dirk Mueller <mueller@kde.org>
+
+ * ecma/xmlhttprequest.h/cpp: Implement asynchronous interface
+ enough to pass the tests on http://www.mozilla.org/xmlextras/tests.html
+
+ * xml/dom2_eventsimpl.h (EventImpl): rename KHTML_KEYUP/DOWN_EVENT
+ to KEYUP/DOWN_EVENT. Add events needed for XMLHttpRequest.
+
+ * rendering/render_object.h (class RenderObject): introduce a PaintInfo
+ struct that contains the information necessary for all those paint..() methods.
+ Requires much less parameters to pass and is therefore faster. While being
+ at it, eliminate the unnecessary virtual method paintObject.
+
+2004-02-23 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_inline.cpp: check if the containingBlock is displayed
+ as block before using it as continuation (#73573)
+
+2004-02-22 Frerich Raabe <raabe@kde.org>
+
+ * tdehtml_part.cpp/.h (openURL): In case the call is a reload, do a stat
+ on the user-defined stylesheet and reload it in case it changed in
+ the meanwhile (#39962).
+ * tdehtmlpart_p.h (class KHTMLPartPrivate): Added
+ m_userStyleSheetLastModified variable which keeps track of the
+ mtime of the user-defined sheet.
+
+2004-02-20 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/bidi.cpp (operator ++): skip empty RenderText.
+ Remove unused forcedMinWidth cruft.
+
+ * rendering/render_block.cpp (addChildToFlow): keep the refcount
+ high for first-letter affected text while we manipulate it.
+
+ * rendering/render_text.cpp: remove unused forcedMinWidth cruft.
+
+2004-02-20 Frerich Raabe <raabe@kde.org>
+
+ * misc/loader.cpp (DOCLOADER_SECCHECK): Adjusted the macro so that it
+ takes a bool parameter which indicates whether it should check for
+ invalid redirections.
+ (requestImage, requestScript): Use DOCLOADER_SECCHECK(true) now
+ * misc/loader.cpp/.h (requestStyleSheet): Added parameter which tells
+ whether the given URL references the user-defined stylesheet. If so,
+ use DOCLOADER_SECCHECK(false) to disable the check for invalid
+ redirections (it's not useful for the user-defined URL).
+ * tdehtml_part.cpp (PartStyleSheetLoader ctor): pass true to
+ DocLoader::requestStyleSheet to indicate that the user-stylesheet is
+ loaded. Fixes seemingly ignored user-defined stylesheet. (#69697)
+
+2004-02-17 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (addChildToFlow): first-letter:
+ better fix for pure punctuation/single letter text childs.
+ Fixes an invalid reference crash (#70546).
+
+2004-02-16 Germain Garand <germain@ebooksfrance.org>
+
+ * css/cssstyleselector.cpp (styleForElement): pseudo-elements
+ use their subject's style as parentStyle -e.g: 'inherit' value.
+ (adjustRenderStyle): mutate pseudo style display to block if
+ needed (floating or ps. content) as allowed by recent CSS2.1
+ draft.
+
+2004-02-16 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (setStyle): skip pseudo
+ styles when updating anonymous blocks'style (#73978).
+ (addChildToFlow):don't crash when installing
+ first-letter in anonymous blocks or when remaining
+ content is empty.
+
+ * rendering/render_container.cpp (updatePseudoChild):
+ always regenerate :before/:after content holding
+ :first-letter.
+
+ * rendering/render_style.cpp (addPseudoStyle): don't use
+ RenderStyle's copy constructor for pseudo-elements.
+
+2004-02-16 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_container.cpp (updatePseudoChild): merge more
+ code for content generated elements
+
+2004-02-15 Zack Rusin <zack@kde.org>
+
+ * xml/dom2_viewsimpl.cpp (getComputedStyle): implementing
+ 26311
+ * css/css_renderstyledeclarationimpl : implementing
+ CSSStyleDeclarationImpl which maps the properties
+ to the rendering tree
+ * css/css_valueimpl.h: changing some methods to virtual
+ in order to overload them in RenderStyleDeclarationImpl
+
+2004-02-15 Dirk Mueller <mueller@kde.org>
+
+ * css/css_base.cpp (specificity): fix detection of the *
+ selector (#73214).
+
+2004-02-13 Zack Rusin <zack@kde.org>
+
+ * xml/xml_tokenizer (XMLIncrementalSource): implementing
+ incremental XML parsing
+
+ * xml/dom_nodeimpl.h : removing superfluous semi-colons
+
+2004-02-11 Germain Garand <germain@ebooksfrance.org>
+
+ Activate merged alternate code path for inline boxes
+ construction/painting. Whitespace count consistency.
+
+ * rendering/bidi.cpp: merge computeHorizontalPositionsForLine
+ to get properly constructed InlineFlowBoxes.
+ (Bidinext): merge skipInline bool to avoid leak.
+ (RenderBlock::bidiReorderLine): handle whitespace count through
+ category separator_Space
+ (RenderBlock::findNextLineBreak): account for empty InlineFlow
+
+ * rendering/font.cpp (drawText, width): whitespace handling
+
+ * rendering/render_box.cpp (position): partial merge
+
+ * rendering/render_line.cpp (placeBoxesVertically):
+ - line-height on block level means minimum line-height for children.
+ - Don't enlarge boxes to fit font, only shrink (CSS2:10.8.1)
+ - Add font's half-leading to top and bottom to avoid nodeAtPoint gaps.
+ Use fm.height(): WebCore's QFontMetrics includes the baseline in descent
+
+ * rendering/render_object.cpp (offsetLeft/offsetTop): adjust
+ (hasStaticX/hasStaticY): merged non-virtual methods
+
+ * rendering/render_replaced.cpp (position): do not add margin anymore
+
+ * rendering/render_text.cpp: whitespace handling. No more p/b/m.
+
+2004-02-10 Dirk Mueller <mueller@kde.org>
+
+ * implement support for pageX/pageY. fix layerX/layerY, which was horrible broken
+ due to its (wrong) assumption that clientX is the same as pageX (#74718), (#70290).
+
+ * dom/dom2_events.cpp (pageX/Y): add bindings.
+
+ * html/htmlparser.cpp (insertNode): argh. regression fix (http://www.cygwin.com) (#74329).
+
+2004-02-09 David Faure <faure@kde.org>
+
+ * ecma/kjs_events.h (clear): set listener object to Null(), not to an invalid Object(),
+ which will crash when the listener is stored in another frame (#61467). Maybe it would be better
+ to really remove the event listener in this case, but this is hard to do efficiently.
+
+2004-02-09 Stephan Kulow <coolo@kde.org>
+
+ * css/html4.css: use text-align: left for all input elements
+
+2004-02-09 David Faure <faure@kde.org>
+
+ * ecma/kjs_html.cpp (getValueProperty): s/getString/String/ for meta attributes,
+ fixes http://www.accorhotels.com/fr/fidelisation/travelplus/tp_pros_adh_form.shtml
+
+2004-02-07 Harri Porten <porten@kde.org>
+
+ * rendering/render_layer.cpp (sortByZOrder): compile fix for non-gcc
+ compilers
+
+2004-02-04 Zack Rusin <zack@kde.org>
+
+ * dom/dom2_traversal : Making NodeFilter( NodeFilterImpl* )
+ constructor public. Making setFilter method take arg by
+ reference
+ * dom/dom_doc.cpp (createTreeWalker): implementing the
+ method
+ * xml/dom2_traversalimpl : Implementing TreeWalkerImpl
+ * xml/dom_docimpl (createTreeWalker): Implementing the
+ method
+
+2004-02-04 Stephan Kulow <coolo@kde.org>
+
+ * html/html_tableimpl.cpp (insertRow): append to tbody if
+ there is no tfood for insertRow(numRows) (#74125)
+
+2004-01-29 Germain Garand <germain@ebooksfrance.org>
+
+ * xml/dom_elementimpl.cpp (name): return attribute names in lowercase
+ in compatibility mode. Solves contradiction between DOM L2/L3. Erratum
+ to DOM L2 is pending, thanks to David Faure.
+
+2004-01-29 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp (get): update frame sizes before returning value for
+ innerWidth/innerHeight, in case the window was just resized (#73528, regtest ecma/window.js)
+
+2004-01-29 Dirk Mueller <mueller@kde.org>
+
+ * html/html_inlineimpl.cpp (parseAttribute): restore KDE 3.1 behavior
+ of <font size=-1> (#73500).
+
+2004-01-26 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp (get/hasProperty): Reduce window.<name> to
+ forms, images and applets, like document.<name> (#71363 comment #5)
+ by sharing NamedTagLengthDeterminer with kjs_html.cpp
+
+2004-01-26 Dirk Mueller <mueller@kde.org>
+
+ * html/html_inlineimpl.cpp (defaultEventHandler): use content, not
+ viewport coordinates for server side image maps (#59701).
+
+ * rendering/bidi.cpp (computeVerticalPositionsForLine): update
+ overflowWidth, otherwise a lot of things go wrong (#59701).
+
+ * misc/loader.cpp (data): correctly emit notifyFinished(), otherwise our
+ state machine goes out of sync.
+
+ * rendering/render_image.cpp: avoid shoot-out effect when neither oimage nor
+ image are fully loaded. do a repaint when the new image finished loading, so
+ that it actually updates. avoid reloading images on news.google.com on hover.
+
+ * tdehtmlview.cpp (scheduleRepaint): make scheduling not starvating repaints.
+ Fix repainting logic to optimize for reduced X server load and minimum CPU
+ usage in traversing the render tree (#72575).
+
+2004-01-25 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_object (offsetLeft/offsetTop): fix Heirmenus which expect to get the
+ <body> offset when the offsetParent is the <body> itself.
+
+ * misc/loader.cpp (class ImageSource): by default, we're rewindable.
+
+ * rendering/render_block.cpp (positionNewFloats): when somebody says
+ clear: both;, he usually means it (#68068).
+
+ * html/html_objectimpl.cpp (renderAlternative): give the alternative rendering
+ some time to avoid ugly deletion races.
+
+ * rendering/render_canvas.cpp (layout): don't recurse when printing (#72775).
+
+ * rendering/render_image.cpp (setPixmap): handle cases when
+ we're not inserted in the tree yet, but the image is already loaded
+ (this happens when the memory cache actually works) (#73311).
+
+2004-01-23 Lubos Lunak <l.lunak@kde.org>
+
+ * html_inlineimpl.cpp (defaultEventHandler): make HTMLAnchorElementImpl
+ react also on DOMActivate event
+
+2004-01-23 David Faure <faure@kde.org>
+
+ * html/html_tableimpl.cpp (insertRow): Fix for DOMTS-L2-HTML test
+ HTMLTableElement39.html: insertRow(-1) appends to last section in
+ document order, not to TFOOT.
+
+ * xml/dom_docimpl.cpp (hasFeature): Updated to current state.
+ (createEvent): Allow to create events with eventType="Events"
+
+2004-01-22 David Faure <faure@kde.org>
+
+ * xml/dom_nodeimpl.cpp (GenericRONamedNodeMapImpl): Implementation of
+ node map for entities and notations, required by some DOMTS Core 1 tests.
+
+2004-01-22 Waldo Bastian <bastian@kde.org>
+
+ * html/htmlparser.cpp (class HTMLStackElem): ref and unref the nodes to avoid them beeing removed below us (#73112)
+
+2004-01-22 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp: make Ctrl only temporary suspend Shift+Down scrolling
+
+2004-01-22 David Faure <faure@kde.org>
+
+ * xml/dom_nodeimpl.cpp (setNodeValue): Don't throw NO_MODIFICATION_ALLOWED_ERR from
+ there, DOMTS-Core-Level1's hc_nodevalue03 says createEntityReference().setNodeValue()
+ should simply do nothing.
+
+ * dom/dom_element.cpp (removeAttributeNode): Fixed logic for NOT_FOUND_ERR.
+ (setAttributeNode): removed tests for WRONG_DOCUMENT_ERR and
+ INUSE_ATTRIBUTE_ERR, the latter being incorrect and both being already
+ done by setNamedItem
+
+ * xml/dom_elementimpl.cpp (setNamedItem): if attribute exists already,
+ return it, to fix DOMTS-Core-level1 test hc_elementreplaceattributewithself
+
+2004-01-21 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.cpp (checkCompleted): do not explicitly set focus to
+ the document if m_focusNodeNumber is not set (fixes dict.leo.org)
+
+2004-01-21 Stephan Kulow <coolo@kde.org>
+
+ * html/html_formimpl.h: handle malformed forms different than
+ wellformed
+
+2004-01-21 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_block.cpp (layoutBlockChildren): use maxTopMargin
+ again, for correct margin-top determination (#67527)
+
+2004-01-20 Dirk Mueller <mueller@kde.org>
+
+ * css/cssstyleselector.cpp (applyRule): Implement handling of
+ empty-cells.
+
+ * css/cssstyleselector.cpp (applyRule): remove superfluous setZIndex(0)
+ after setHasAutoZIndex, which breaks auto.
+
+2004-01-19 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_object.cpp (getVerticalPosition): improve
+ logic (#65121).
+
+2004-01-19 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_style.h: providing an initial property
+ function for every css property and using it in macros
+ from cssselector.cpp to unify the handling of short hand
+ properties (based on safari patch)
+
+ * css/cssstyleselector.cpp (parseValue): unify handling
+ of inherited css properties (based on safari patch)
+
+2004-01-18 Dirk Mueller <mueller@kde.org>
+
+ * tdehtmlpart_p.h (class KHTMLPartPrivate): experimental:
+ copy encoding information from parent frame. helps on
+ http://www.pfl.ru/ when manually setting the correct encoding.
+
+ * rendering/render_container.cpp (addChild): make sure
+ that a RenderTableCol object is correctly nested inside
+ a table (#59766).
+
+ * xml/dom_elementimpl.cpp (recalcStyle): fix tree corruption
+ when recalcStyle() happens to be invoked in the wrong moment.
+
+ * html/html_baseimpl.cpp (setLocation): fix KURL() casting issue.
+
+2004-01-16 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_image.cpp: remove some asserts that
+ noone needs anyway (#72739).
+
+2004-01-16 Stephan Kulow <coolo@kde.org>
+
+ * html/htmltokenizer.cpp: fixing <pre> parsing (#58584)
+
+2004-01-15 Dirk Mueller <mueller@kde.org>
+
+ * misc/loader.cpp (ref): ok, there are cases where an image
+ gets refed twice from the same client. *sigh*.
+
+2004-01-15 Lars Knoll <knoll@kde.org>
+
+ * rendering/render_table.cpp: set overflowWidth to width
+ when layouting (#72420)
+ * xml/dom2_eventsimpl.cpp rendering/render_block.cpp
+ nodeAtPoint() should always use contents coordinates.
+
+2004-01-14 Dirk Mueller <mueller@kde.org>
+
+ * misc/loader.cpp: Fix uncachable image leak (#72197).
+
+2004-01-13 Dirk Mueller <mueller@kde.org>
+
+ * css/css_ruleimpl.cpp (CSSMediaRuleImpl): set parent to 0
+ to avoid leak (#70731).
+
+2004-01-13 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_canvas.cpp (layout):
+ force scrollbar visibility status while layouting
+ to avoid endless cycles (#69613)
+
+2004-01-13 Dirk Mueller <mueller@kde.org>
+
+ * ecma/kjs_events.cpp (JSEventListener): store them in a dictionary,
+ not a linked list.
+
+ * css/parser.y: fix rect() parsing problem (#72458).
+
+2004-01-12 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_block.cpp (left/rightRelOffset): recursion protection
+ (#70608).
+
+ * rendering/render_image.cpp (updateFromElement): add tracking of
+ an oldimage, to avoid a "shoot out" effect on hovering expired images.
+
+2004-01-11 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_text.cpp (paintBoxDecorations):
+ make background images on inlines obbey the full CSS
+ spec (#59600)
+
+ * rendering/render_text.h (paintBoxDecorations): changed prototype
+
+ * rendering/render_line.cpp (paintDecorations): disable for now.
+
+2004-01-11 Dirk Mueller <mueller@kde.org>
+
+ * html/htmlparser.cpp (insertNode): fix <p><dl> handling (#68167).
+
+ * css/css_base.cpp (extractPseudoType): make it case-insensitive (#72159).
+
+2004-01-11 Germain Garand <germain@ebooksfrance.org>
+
+ border/padding/margin issues on inlines (#68394)
+
+ * rendering/bidi.cpp (computeVerticalPositionsForLine):
+ add the correct width offset for text objects
+
+ * rendering/render_line.cpp (paintBackgroundAndBorder):
+ guard against invalid width values
+
+ * rendering/render_text.cpp (paintDecoration):
+ revert revision 1.224, avoid resurecting #50683
+ by matching the conditionals of RenderText::position
+ (RenderText::nodeAtPoint): revert part of r1.234,
+ avoid #69345 by commenting incompatible merge.
+ (RenderText::width): add padding/border/margin
+
+2004-01-10 Dirk Mueller <mueller@kde.org>
+
+ * css/html4.css: fix default font/fontsize of input,select and textarea
+ (#67851).
+
+ * misc/loader_jpeg.cpp (decode): try hard not to shoot
+ down the machine with large images
+ (try http://www.parisc-linux.org/~willy/kde/graph.jpg)
+
+ * rendering/render_image.cpp (layout): ugh, major stupidity. don't rescale large
+ images if nobody explicitely asked for it. makes loading of very large images
+ quite a bit faster.
+
+ * rendering/render_image.cpp/.h: Reduce X-server pressure with large images (#39693).
+
+ * misc/loader_jpeg.cpp: Upon suggestion from Maksim, implement decoding of
+ nonprogressive jpegs in non-buffered-image mode. This massively reduces memory
+ footprint and slightly improves performance.
+
+2004-01-09 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_replaced.cpp (eventFilter): readd the wheel event handling
+ which allows scrolling of the page again. Thanks a lot for just removing it. (#45180)
+
+
+2004-01-02 Dirk Mueller <mueller@kde.org>
+
+ * html/htmltokenizer.cpp (notifyFinished): fix null pointer dereference
+ in rare cases.
+
+ * css/cssstyleselector.cpp (reparseConfiguration): implement.
+
+ * tdehtml_part.cpp (reparseConfiguration): call CSSStyleSelector::reparseConfiguration
+ instead of ::clear(). much less crashy. (#68141)
+
+2003-12-27 Simon Perreault <nomis80@nomis80.org>
+
+ * tdehtml_part.cpp: Remove unused zoom actions. Assign CTRL + Key_Plus to
+ zooming in and CTRL + Key_Minus to zooming out.
+
+2003-12-27 Luis Pedro Coelho <luis@luispedro.org>
+
+ * misc/loader.cpp : Discard items from cache if they have the wrong type (#68181)
+
+2003-12-20 Koos Vriezen <koos.vriezen@xs4all.nl>
+
+ * html_objectimpl.cpp (attach): Check KImageIO::typeForMime first if RenderImage
+ supports the image format
+
+2003-12-11 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_image.cpp (updateFromElement): set the alt text before doing anything
+ else, because it might trigger a setting of the error pixmap and then we don't know the
+ alt text to draw and get wrong sizes
+
+2003-12-10 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_replaced.cpp (updateFromElement): don't use setEraseColor for __tdehtml
+ widgets as it changes the background mode and induces flicker (#69130)
+ (copyWidget): retrieve background color from the widget's palette.
+
+2003-12-10 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_list.cpp: fix toLetter, based on Safari patch.
+
+2003-12-09 Dirk Mueller <mueller@kde.org>
+
+ * html/html_formimpl.cpp (submit): don't ask over and over again the same question.
+
+2003-12-08 Zack Rusin <zack@kde.org>
+
+ * tdehtmlview.*, html/html_formimpl.cpp (submit): Fixing 67179 -
+ Possibility to avoid saving form data for certain sites.
+
+2003-12-05 David Faure <faure@kde.org>
+
+ Clean up "default handling" of events. Fixes recent regressions like
+ "arrow keys in lineedit make the scrollview scroll".
+ * xml/dom_nodeimpl.*: Removed bool return value from most dispatch*Event methods,
+ documented the two that still return a bool. The meat of the change is
+ that dispatchKeyEvent returns defaultHandled || defaultPrevented.
+ * dom/dom_node.cpp (dispatchEvent): Return !defaultPrevented as mandated by
+ the DOM, now that NodeImpl doesn't do it anymore.
+ * rendering/render_replaced.cpp (eventFilter): Adapted to new logic
+ * tdehtmlview.cpp (dispatchKeyEventHelper): Adapted to new logic
+
+2003-12-05 Stephan Kulow <coolo@kde.org>
+
+ * css/cssparser.cpp (parseValue): Do not accept negative values for padding (#59557)
+
+2003-12-05 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp, xml/dom2_eventsimpl.*, xml/dom_nodeimpl.*, rendering/render_replaced.cpp :
+ fix mapping between Qt and DOM key events
+
+2003-12-05 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_object.cpp (nodeAtPoint): don't offset
+ relatively positioned objects coordinates. They already are (#68716/#60453)
+
+ * rendering/render_text.cpp (nodeAtPoint): no need to include borders and padding
+ in the matching region anymore (#69345)
+
+2003-12-05 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_box.cpp (paintRootBoxDecorations): use the full canvas's height
+ when painting the root's background (#55065)
+
+2003-12-03 Stephan Kulow <coolo@kde.org>
+
+ * css/html4.css: define default text-alignments for input fields to avoid
+ problems with inherited attributes
+
+2003-12-02 Stephan Kulow <coolo@kde.org>
+
+ * html/htmltokenizer.cpp: do not discard any line feed from parsing textareas
+
+2003-11-29 Dirk Mueller <mueller@kde.org>
+
+ * css/cssstyleselector.cpp: add indigo/crimson colorhandling as it is not in X11's rgb
+ names list.
+
+ * misc/loader.cpp (CachedCSSStyleSheet/CachedScript::data): add some utf8/utf16 encoding
+ handling. Workaround Qt bugs (#69115). Initial investigation and patch by Harri.
+
+2003-11-29 Stephan Kulow <coolo@kde.org>
+
+ * html/html_elementimpl.cpp (addHTMLAlignment): readding floating for input type="image"
+
+ * rendering/render_form.cpp (setStyle): respect text-align style on input elements
+ (#65610)
+
+ * html/html_formimpl.cpp (HTMLInputElementImpl): don't make input elements
+ floating, but only care for the text alignment
+
+2003-11-28 Harri Porten <porten@kde.org>
+
+ * css/css_valueimpl.cpp (setProperty): remove superfluous
+ removeProperty() call. It will be done later in CSSParser. After
+ after the value has been recognized as valid.
+
+2003-11-28 Germain Garand <germain@ebooksfrance.org>
+
+ * html/html_headimpl.cpp (class HTMLLinkElementImpl): grant to alternate sheets
+ enabled via script the same status as preferred sheets. Restore proper tracking
+ of pending stylesheets.(#67453/#68504)
+
+ * html/html_headimpl.h (HTMLLinkElementImpl::setDisabled)
+
+ * xml/dom_docimpl.cpp (recalcStyleSelector): don't remove sheets linked from
+ DOM-disabled link elements from the list of available alternate stylesheets.
+ Re-enabling them manually is a valid option.
+
+2003-11-26 Lubos Lunak <l.lunak@kde.org>
+
+ * tdehtmlview.cpp, xml/dom2_eventsimpl.cpp : generate correctly keydown,keypress and keyup events
+
+2003-11-26 Dirk Mueller <mueller@kde.org>
+
+ * html/htmlparser.cpp (parseToken): ignore flat on <select>. maybe
+ we should only do this in compat mode though (#69017).
+
+2003-11-25 Dirk Mueller <mueller@kde.org>
+
+ * html/html_formimpl.cpp (defaultEventHandler): ignore stale keyup events
+ on space too.
+
+ * css/html4.css: Set quirky margins on elements that need it (#66490).
+
+2003-11-25 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_container.cpp (updatePseudoChild): fix handling of
+ images in :content (#67373)
+
+ * html/html_baseimpl.cpp (parseAttribute): fix parsing of body attributes (safari merge)
+
+ * rendering/render_box.cpp (calcAbsoluteVertical): basically reverting commit 1.218
+ for height calculation. It broke floating images (#67839)
+
+2003-11-25 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp: Implement hasProperty and get for frames by number in Window,
+ to fix window[0] and parent[1] etc. (#56983)
+
+2003-11-25 Germain Garand <germain@ebooksfrance.org>
+
+ * tdehtml_part.cpp (checkCompleted): prepend "Automatic Detection" entry to
+ "Use Stylesheet" menu.
+ (slotUseStylesheet): set m_sheetUsed to null string if autodetect is on.
+ Fixes #54335.
+
+ * xml/dom_docimpl.cpp (recalcStyleSelector): if the previous sheet is sticky but
+ still missing when we've already got <body>, choose the document's best
+ candidate until parsing ends. Avoids ending with no decision (#63348).
+
+2003-11-24 Dirk Mueller <mueller@kde.org>
+
+ * html/html_formimpl.cpp (defaultEventHandler): ignore stale keyup events.
+ Only react when we saw a matching keydown before.
+
+2003-11-24 David Faure <faure@kde.org>
+
+ * html/htmlparser.cpp (popInlineBlocks): Fixed infinite loop due to
+ popOneBlock returning immediately if blockStack==0. #68034.
+
+ * rendering/bidi.cpp: Fixed infinite loop with <nobr> due to findNextLineBreak
+ going back (wrong variable used). #66867, #68598, #59230 and their duplicates.
+
+2003-11-24 Stephan Kulow <coolo@kde.org>
+
+ * css/cssparser.cpp (parseFontFamily): handle invalid font families like
+ font-family: ms sans serif, utopia
+ * css/css_valueimpl.cpp (FontFamilyValueImpl): merging safari code to handle
+ invalid font families. Replacing buggy font maching by substring search by
+ simply ripping out "MS" and searching for similiar fonts
+
+2003-11-24 David Faure <faure@kde.org>
+
+ * html/htmlparser.cpp (getElement, processCloseTag): Allow only one
+ non-empty <title> tag, discard any following <title> tag. This matches
+ both IE and Mozilla. Testcases tdehtmltests/regression/tests/ecma/title*
+
+ * html/html_headimpl.cpp (childrenChanged): Set title immediately, like
+ other browsers do.
+
+2003-11-23 Germain Garand <germain@ebooksfrance.org>
+
+ * html/html_imageimpl.cpp (attach): don't create a renderer if our parent doesn't
+ allow childs. e.g: a RenderPartObject (#66793)
+
+2003-11-23 Stephan Kulow <coolo@kde.org>
+
+ * css/cssstyleselector.cpp (applyRule): fixing my fix for #60556, which
+ introduced quite some regressions (thanks to Paul Sprakes for working
+ that out with me)
+
+2003-11-22 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_line.cpp (paintDecorations): avoid underlining elements that
+ have no dimension in itself (#68728)
+
+2003-11-22 Koos Vriezen <koos.vriezen@xs4all.nl>
+
+ * html_miscimpl.cpp (HTMLCollectionImpl): Make
+ window.xxx == document.xxx for APPLET/OBJECT/EMBED elements, using
+ ID or NAME attributes, behave alike
+
+2003-11-22 Germain Garand <germain@ebooksfrance.org>
+
+ * dom/css_value.cpp (getPropertyPriority): const version was declared
+ but not implemented
+
+ * rendering/font.cpp (drawText): do not use DirWS to count spaces
+ when justifying, it won't count &nbsp;'s (#65903)
+
+ * rendering/render_text.cpp (class InlineTextBox): ditto.
+
+2003-11-19 Dirk Mueller <mueller@kde.org>
+
+ * html/html_baseimpl.cpp (attach): respect display: NONE on <frame>, since
+ it is used to indicate the FOUC prevention code path now.
+
+ * css/cssparser.cpp (parseColor): remove use of invalidColor. use a boolean
+ return instead. invalidColor was confusing as it was actually a valid color.
+ Also add rgba() parsing.
+
+ * css/cssstyleselector.cpp (adjustRenderStyle): add check to avoid that
+ <FRAME> gets a display != BLOCK assigned (#63640).
+
+2003-11-18 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_html.cpp: limit collection length to >= 0 (Maciej)
+
+2003-11-18 David Faure <faure@kde.org>
+
+ * css/css_valueimpl.* (cssText): cssText implementation from Maciej Stachowiak.
+
+2003-11-17 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp (processObjectRequest):
+ Stop the spinning wheel on <frame src="">.
+ Testcase: webcore's fast/frames/empty-frame-src.html
+
+2003-11-17 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_*.cpp: changing the output of dump to
+ get a more comprehensive renderer tree output - as inspired
+ by Safari's kwqDebugTree. This allows for a change in
+ test_regression to check layouts
+
+2003-11-15 Zack Rusin <zack@kde.org>
+
+ * rendering/render_box.cpp (calcHeight): correctly compute the
+ height for relatively positioned object with percentage based
+ dimensions - pretty much a merge from safari (#53902)
+
+2003-11-14 Germain Garand <germain@ebooksfrance.org>
+
+ fix "overflow: scroll" layout/painting issues
+
+ * rendering/render_box.cpp (getOverflowClipRect): substract
+ scrollbars width/height if any. Merged from WebCore.
+
+ * rendering/render_layer.cpp (horizontalScrollbarHeight,
+ verticalScrollbarWidth): use pixelMetric instead of width()/height().
+
+2003-11-13 Zack Rusin <zack@kde.org>
+
+ * rendering/render_box.cpp (calcAbsoluteVertical): fix the
+ computation of the height for the percentage positioned elements
+ contained in the root
+
+2003-11-11 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_style.h (StyleBoxData>): fix SunProCC
+ compatibility problem.
+
+ * xml/dom_elementimpl.cpp (attach): don't attach a renderobject
+ to a parent that does not support childs (childAllowed()).
+ * html/html_objectimpl.cpp (attach): check for childAllowed().
+ * xml/dom_textimpl.cpp (attach): check for childAllowed().
+
+ * misc/loader.cpp (CachedCSSStyleSheet): add "*/*;q=0.1" to the
+ accept header (#67803).
+
+2003-11-10 David Faure <faure@kde.org>
+
+ * tdehtml_part.cpp: Ask the user "open or save?" before embedding a
+ non-usual mimetype into a frame (e.g. ZIP files or PS files).
+ (html and images are the 'usual' exceptions)
+ Includes a dontshowagain checkbox, so this shouldn't be too annoying.
+
+2003-11-07 Stephan Kulow <coolo@kde.org>
+
+ * css/cssparser.cpp (parseValue): set the background-* properties
+ to their initial value before expanding (#64743)
+
+2003-11-07 Dirk Mueller <mueller@kde.org>
+
+ * css/css_valueimpl.cpp (cssText): wrap uri's into url().
+ Stephan Kulow noted that other browsers do that.
+
+ * rendering/render_list.h (class RenderListItem): another
+ SunCC incompatibility fixed. Only applies to HEAD (*phew*).
+
+2003-11-05 Germain Garand <germain@ebooksfrance.org>
+
+ Refinement of namespace handling for Attributes,
+ following David's patch of 2003-10-25.
+
+ * xml/dom_elementimpl.cpp: get rid of the m_localName string member
+ for Attributes.
+ (AttrImpl::cloneNode): fix wrong argument order in ctor call
+
+ * xml/dom_docimpl.cpp (getId/getName): fix problems introduced by the
+ switch to an Id of zero for both global and XHTML Namespace. Zero is
+ also what a failed QDict lookup returns...
+
+2003-11-05 Dirk Mueller <mueller@kde.org>
+
+ * html/htmltokenizer.cpp (parseEntity): fix annoying entity parsing problem
+ that caused stale ';''s popping up everywhere.
+
+2003-11-04 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.{cpp,h} (selection): Added new overloaded function to
+ return selection boundaries.
+
+2003-11-04 Dirk Mueller <mueller@kde.org>
+
+ * html/html_baseimpl.cpp (attach): fix assertion failure thanks
+ to the FOUC patch.
+
+2003-11-04 David Faure <faure@kde.org>
+
+ * html/html_documentimpl.cpp (close): Ensure setTitle is called
+ at least once, with an empty string if there's no title tag.
+
+ * xml/dom_docimpl.cpp (setTitle): Skip equality test if passing an
+ empty title, since m_title is initially empty.
+
+2003-11-03 Dirk Mueller <mueller@kde.org>
+
+ * misc/loader.cpp (buildAcceptHeader): add */* to Accept-Header
+ for image requests with low priority to fix www.tweakers.net (#53515).
+
+ * css/parser.y: lowercase the media we get via CSS stylesheets.
+ Its true that the media is case insensitive in CSS, but it is
+ case sensitive in HTML, and as we don't want to do the code twice
+ we cheat a little here.
+
+ Also change media parsing logic for @import to handle
+ http://www.hixie.ch/tests/evil/css/import/extra/importexoticmedia.html
+ correctly (idea by Stephan Kulow).
+
+ * html/html_formimpl.cpp (defaultEventHandler): react on space too
+ (#64200).
+
+ * dom/html_base.cpp (src): return the completeURL.
+
+ * html/html_formimpl.cpp: remove the addCSSProperty calls and put
+ them in the default stylesheet. the original reasons for them in that
+ place is no longer valid since we implemented the CSS 2.1 selector rules.
+
+
+2003-11-02 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_form.cpp (setStyle): check for direction (#57626)
+ on RenderLineEdit and RenderTextArea.
+
+ * tdehtmlview.cpp (viewportWheelEvent): toggle Font zooming orientation (#61862).
+
+ * rendering/render_box.cpp (paintBackgroundExtended): implement. needed
+ for inline elements background drawing somewhen.
+
+ * rendering/render_object.cpp (nodeAtPoint): merge from Safari. Still
+ does not work, but at least its the same now.
+ (lineHeight): handle replaced elements here. They don't necessarily
+ inherit RenderReplaced anymore.
+ (baselinePosition): handle replaced elements.
+
+ * rendering/render_replaced.cpp: remove baselinePosition/lineHeight. its in
+ RenderObject now.
+
+ * rendering/render_block.cpp (isSelfCollapsingBlock): collapse away trailing whitespace
+ at the end of the block.
+ (setStyle): set "isReplaced" for display: inline-block.
+ (addChildToFlow): Make sure we don't append things after :after generated content.
+ (calcInlineMinMaxWidth): respect text-indent (taken from WebCore 106).
+
+2003-11-02 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_form.cpp (updateFromElement): invalidate the size hint
+ of comboboxes as they are cached in QComboBox (#64229)
+
+2003-11-01 Dirk Mueller <mueller@kde.org>
+
+ * css/cssstyleselector.cpp (applyRule): handle clear: none (#57676)
+
+2003-10-31 David Faure <faure@kde.org>
+
+ * html/html_inlineimpl.cpp (defaultEventHandler): Another wrong use of detail()
+ instead of the new isDoubleClick(), which made it impossible to click on the
+ same link twice without moving the mouse (#58241).
+
+2003-10-30 Dirk Mueller <mueller@kde.org>
+
+ * xml/dom_docimpl.cpp (open): do a full detach()/attach(),
+ otherwise we're corrupting the rendertree (#66590).
+
+2003-10-29 Stephan Kulow <coolo@kde.org>
+
+ * html/htmltokenizer.cpp (processListing): fixing textarea regression
+
+2003-10-29 David Faure <faure@kde.org>
+
+ * ecma/kjs_dom.cpp: Patch from Darin Adler to implement Node.item.
+
+2003-10-29 Leo Savernik <l.savernik@aon.at>
+
+ * tdehtml_part.cpp (tdehtmlMousePressEvent): Fixed occasional selection
+ of image on which a drag had been initiated.
+
+2003-10-29 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp (Window::openWindow): patch from Maciej to allow
+ floats in window.open properties (e.g. small window at saabusa.com)
+
+2003-10-28 David Faure <faure@kde.org>
+
+ * tdehtmlview.cpp (viewportMouseDoubleClickEvent): Set bool in MouseEventImpl
+ when handling a double click. The DOM API only has "number of clicks at the
+ same place" notion, but not whether they happened quick or over a long time.
+ Added support for small mouse movement when double-clicking, like in mousePressEvent.
+
+ * xml/dom2_eventsimpl.*: Added m_isDoubleClick bool for the reason above.
+
+ * xml/dom_nodeimpl.cpp (handleLocalEvents): Use new MouseEventImpl::isDoubleClick()
+ to differenciate between click and dblclick. Lars used the QMouseEvent type,
+ but when the event comes from JS - initMouseEvent+dispatchEvent, there's
+ no QMouseEvent - which broke test_regression.
+
+2003-10-28 Stephan Kulow <coolo@kde.org>
+
+ * tdehtml_part.cpp (reparseConfiguration): clear the style selector
+
+2003-10-28 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_replaced.cpp (checkSelectionPoint):
+ Readded RenderReplaced::checkSelectionPoint to fix disrupted selection
+ of sole inline images within block elements (<p><img ...></p>).
+ Also fixes caret placement issues.
+
+2003-10-28 David Faure <faure@kde.org>
+
+ * ecma/kjs_window.cpp (goURL): Compare the URLs without the ref, fixes
+ wrong reload when opening a tree-like structure (#54358).
+
+ * ecma/kjs_html.cpp (getValueProperty): (#54929)
+ Fixes for HTMLAnchorElement properties, return empty strings instead
+ of null, and let "text" return plain text instead of HTML.
+
+ * html/html_elementimpl.cpp (innerText): Fix for empty elements.
+
+2003-10-27 David Faure <faure@kde.org>
+
+ * tdehtmlview.cpp (dispatchKeyEvent): Generate keypress, keydown and keyup
+ events for the document if no node has the focus. Factorized code in
+ a new method, dispatchKeyEvent. Cleaned up old unused variables d->lastKeyNode
+ and d->lastKeyPress. #42918 and #43072, google keys.
+
+ * xml/dom_elementimpl.h (checkQualifiedName): Added bool nameCanBeEmpty,
+ and fixed again: DOM3 now says a null qualifiedName is allowed in createDocument.
+ * xml/dom_docimpl.cpp (createDocument): Pass nameCanBeEmpty=true, to
+ allow the commonly found implementation.createDocument("","",null); (#61650)
+
+ * html/html_elementimpl.cpp (HTMLElementImpl): Fixed wrong m_htmlCompat
+ value when parsing HTML in HTML-compat mode, get it from the doc's setting.
+ * xml/dom_docimpl.cpp (createElementNS): Always set m_htmlCompat, now that
+ the HTMLElementImpl constructor sets it too.
+
+ * xml/dom_nodeimpl.cpp (handleLocalEvents): fixed crash when a mouse event
+ is dispatched via the DOM API, with initMouseEvent, dispatchEvent.
+
+2003-10-26 David Faure <faure@kde.org>
+
+ * xml/dom_docimpl.cpp (getId): added bool lookupHTML, set to true in most
+ places, to fix e.g. css selector broken by my previous change, and set
+ to false from createElementNS to still skip the lookup for HTML tags.
+
+2003-10-25 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_form.h (class RenderFileButton): use KURLRequester
+ instead of just doing the stuff on our own in a worse way (#62328).
+ Also provides completion, yay! :)
+
+ right now <input type=file> has severe rendering errors which I blame
+ on the widget painting code from Lars.
+
+2003-10-25 David Faure <faure@kde.org>
+
+ Make use of the ID scheme much more for elements, getting rid of
+ m_localName and m_tagName strings in XMLElementImpl.
+
+ * misc/maketags: switched to lowercase; uppercase is the html-compat case only.
+ * html/html_elementimpl.cpp(tagName,localName): lookup name from id, with proper
+ handling of m_htmlCompat vs xhtml difference.
+ * html/html_elementimpl.h: removed m_xhtml bool, becomes bitfield in NodeImpl instead,
+ since XML elements can be in "HTML compat" mode too (uppercased).
+ * xml/dom_docimpl.cpp (DocumentImpl): XML namespace is id 0 again
+ * xml/dom_docimpl.cpp (createElementNS): check for exceptions when
+ setting the prefix; set HTML compat mode in the element if necessary.
+ Only look for the ID if it's an XML element - if not, createHTMLElement did it.
+ * xml/dom_docimpl.cpp (getId): Do not apply the html-compat case hacks
+ when looking up elements. This is done by createElement[NS] now. Left
+ the code for the attribute lookup only.
+ * xml/dom_elementimpl.cpp (XMLElementImpl::XMLElementImpl): ctor only needs id and prefix.
+ Removed m_tagName and m_localName member vars in all methods, used id lookups instead.
+ * xml/dom_elementimpl.cpp (cloneNode): fixed namespace being lost. Factorized
+ common code with HTMLElementImpl in finishCloneNode.
+ * xml/dom_nodeimpl.*: added m_htmlCompat bool in bitfield. Only makes
+ sense for elements currently, but would take more memory in ElementImpl.
+
+ * xml/dom_docimpl.cpp (DOMImplementationImpl::createDocument):
+ DOM3 now says a null qualifiedName is allowed in createDocument.
+
+2003-10-24 Dirk Mueller <mueller@kde.org>
+
+ * css/html4.css (marquee): don't set display: none, it might
+ contain useful text (its used on ebay.com for every second article).
+
+ * html/html_formimpl.cpp/h: revert this commit:
+ * remove lot's of addCSSProperty calls and moved the
+ definitions to the default style sheet. This made
+ it possible to remove quite some code in html_formimpl.cpp
+
+ * rendering/render_form.cpp (updateFromElement): Fix coolo's commit (#61347)
+
+2003-10-24 Germain Garand <germain@ebooksfrance.org>
+ * General scope of the change:
+ - bring back the NodeImpl_NSMask bits in id() for Attributes and XMLElements
+ => the cssselector need that to support CSS namespaces in an efficient way.
+ => fixes CSS selection for XML documents
+ - change Nodeimpl::Id registration mechanism:
+ We tried to solve the DOM1/DOM2 NS methods compatibility problems
+ by registering the qualifiedName. However, this is doomed to fail in other
+ places that relies on Ids because prefixes aren't encoded in the Ids and
+ are irrelevant for NS nodes identification.
+ Instead, use registered aliases (see DocumentImpl::getId) to solve
+ compatibility issues while maintaining a sound Id system.
+
+ * css/cssstyleselector.cpp: change getId calls
+
+ * css/parser.y: ditto
+
+ * dom/dom_doc.cpp: change getId/implementation method calls
+ (DOM::Document::createElement): check DOM exceptions
+ (DOM::Document::createElementNS): ditto
+ (DOM::Document::createAttribute): ditto
+ (DOM::Document::createAttributeNS): ditto
+ (DOM::Document::createDocumentFragment): ditto
+
+ * dom/dom_element.cpp: change getId/implementation method calls
+
+ * dom/dom_node.cpp: ditto
+
+ * html/html_documentimpl.cpp:
+ (HTMLDocumentImpl::createElement): check DOM exceptions
+
+ * html/html_documentimpl.h: ditto
+
+ * html/html_elementimpl.cpp: use m_xhtml bool flag to distinguish HTML/XHTML elements
+
+ * html/html_elementimpl.h:
+ (DOM::HTMLElementImpl::HTMLElementImpl): init m_xhtml
+ (DOM::HTMLElementImpl::setXHtmlElement): set/retrieve m_xhtml (non-virtual)
+ (DOM::HTMLElementImpl::isXHtmlElement): ditto
+
+ * html/htmlparser.cpp: change getValue/setValue syntax
+
+ * html/htmltokenizer.h: change getId calls
+
+ * rendering/render_frames.cpp: ditto
+
+ * xml/dom_docimpl.cpp: IdNameMapping is now a struct holding QDicts. getId dynamically choses
+ the struct to be used based on it's first argument (ElementId, AttributeId, NamespaceId)
+ (DOMImplementationImpl::createDocument): factor qualifiedName checking code
+ (DocumentImpl::createAttribute): New. Mirrors DOM.
+ (DocumentImpl::createAttributeNS): ditto
+ (DocumentImpl::createElementNS): check exceptions in qualifiedName
+
+ * xml/dom_docimpl.h: IdNameMapping change
+
+ * xml/dom_elementimpl.h:
+ * xml/dom_elementimpl.cpp:
+ (AttrImpl::AttrImpl): no more m_namespaceURI, now dynamically retrieved with getName(NamespaceId...)
+ (AttrImpl::nodeName): now built from prefix + localName
+ (ElementImpl::setAttributeNS): check exceptions on qualifiedName
+ (XMLElementImpl::XMLElementImpl): no more m_namespaceURI, now dynamically retrieved with getName(NamespaceId...)
+ restore m_id (as in 3_1_BRANCH) for correct CSS selection on XML Elements
+
+ * xml/dom_elementimpl.h:
+ (DOM::checkQualifiedName): inline DOM helper, factoring qualifiedName exception checkings
+ (DOM::splitPrefixLocalName): inline DOM helper, avoids scanning qualifiedName multiple times
+
+ * xml/dom_nodeimpl.h:
+ (DOM::NodeImpl::): enum IdType for (ElementId, AttributeId, NamespaceId)
+
+ * xml/xml_tokenizer.cpp:
+ (XMLHandler::startElement): use the qualifiedName instead of the localName
+ in order to know the prefix if any.
+
+2003-10-24 Stephan Kulow <coolo@kde.org>
+
+ * rendering/render_form.cpp (updateFromElement): support disabled attribute
+ select option (#61347)
+
+2003-10-24 Lars Knoll <knoll@kde.org>
+ * Make the <button> element work correctly
+ * remove lot's of addCSSProperty calls and moved the
+ definitions to the default style sheet. This made
+ it possible to remove quite some code in html_formimpl.cpp
+
+2003-10-24 Lars Knoll <knoll@kde.org>
+ * A few more small fixes to Html event handlers. We can unfortunately not
+ easily get the events for <select> and <textarea> correct, as they use
+ either modality or QScrollView (but doesn't work in 3.1.x neither).
+
+2003-10-24 Lars Knoll <knoll@kde.org>
+ * Hopefully fixed most repainting problems.
+
+2003-10-24 Lars Knoll <knoll@kde.org>
+ * Fix most of the form related regressions introduced by my
+ changes earlier on. onfoo event handlers are now fired in a
+ way that is mostly compatible to IE for <input type=xxx>.
+ Other form elements might still need some work.
+
+2003-10-23 Lars Knoll <knoll@kde.org>
+ * Fix nodeAtPoint for elements that have no child (makes links on images
+ work again)
+ * Fix null pointer dereferencing in RenderLayer::updateHoverActiveState
+
+2003-10-23 Stephan Kulow <coolo@kde.org>
+
+ * html/htmltokenizer.cpp (processListing): do not discard all white space
+ in textareas (#62076)
+
+ * css/cssstyleselector.cpp (applyRule): if the first font isn't found,
+ continue looking (#60556)
+
+2003-10-22 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_box.cpp (calcAbsoluteHorizontal): fixed containing block
+ height calculation for position:fixed.
+ (paintBackground): fix negative backgroundx/y positioning. fix
+ background-attachment: fixed (http://placenamehere.com/safari/fixedbgtest.html)
+ avoid division by zero. fix table background positioning (#49336).
+ http://c133.org/testcase1.html, http://c133.org/testcase2.html,
+ http://c133.org/testcase3.html
+
+ * misc/loader.cpp (pixmap_size/valid_rect): return useful values for the error image
+ to avoid that its shown as null pixmap (#42233).
+
+2003-10-21 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_list.cpp (calcListValue): skip anonymous block while searching
+ for the <ol> block. Thanks to the Maksim regression testengine.
+
+ * rendering/render_object.cpp (setOverhangingContents): refine assert to avoid
+ crash on bananalotto.com. Adjust to changed containingBlock() behavior.
+
+ * html/html_listimpl.cpp (attach): fix thinko. Revert Safari merge which
+ broke <ul><p><li>. Thanks to Maksim for noticing.
+
+ * rendering/render_list.cpp (calcListValue): handle <ul><p><li> again.
+
+ * rendering/render_box.cpp (repaint): revert commit which introduced another
+ 4 bytes overhead. No need to waste memory here.
+
+ * rendering/render_object.cpp (setStyle): schedule repaint on old object
+ when the new outline is going to be thinner.
+
+ * rendering/render_form.cpp (RenderCustomButton): Remove.
+
+ * rendering/render_replaced.cpp (RenderReplaced::checkSelectionPoint): Remove.
+ RenderObject/RenderBox'es implementation *must* work. No need to add useless code.
+
+ * rendering/render_replaced.cpp (RenderReplacedBlock): Remove.
+
+ * html/html_formimpl.cpp (HTMLButtonElement::attach): Remove.
+
+ * rendering/render_box.cpp (calcWidth): implement CSS min-width/max-width
+ support (#12994).
+
+ * rendering/render_block.cpp (renderName): don't crash when style() is 0L.
+
+ * rendering/render_object.h (class RenderObject): remove isRunIn() / isCompact().
+ We can use style()->display() here, and it is inconsistent with the other is*
+ members which usually do not access style() (that can be 0L).
+
+ * rendering/render_object.cpp (createObject): create RenderBlock for INLINE_BLOCK.
+
+ * css/html4.css (BUTTON/LEGEND): set display: inline-block.
+
+ * css/cssstyleselector.cpp (styleForElement): handle COMPACT/RUN_IN/INLINE_BLOCK
+ (applyRule): handle INLINE_BLOCK.
+
+ * css/makeprop: don't export getPropertyName. declare it.
+
+ * xml/dom_nodeimpl.cpp (replaceChild/appendChild/removeChild):
+ Reverting patch which invalidated layout on child when it was attached.
+
+2003-10-20 Lars Knoll <knoll@kde.org>
+
+ * fix most issues with the layering code by
+ merging and adapting safaris implementation
+ * fix a bug in RenderBox::calcAbsoluteVertical(), that probably
+ has destroyed a lot of layouts.
+ * don't add the scroll offset in RenderBox::paintBoxDecorations()
+
+2003-10-20 Dirk Mueller <mueller@kde.org>
+
+ * css/html4.css (UL,MENU,DIR,OL): don't set flow-around-floats (#53429).
+
+2003-10-20 David Faure <faure@kde.org>
+
+ * xml/dom_docimpl.cpp (defaultEventHandler): set current target to 0 for window events.
+ * ecma/kjs_events.cpp (handleEvent): Window events like window.onload window.onresize etc.
+ must have 'this' set to the window (not to the document).
+
+2003-10-20 Dirk Mueller <mueller@kde.org>
+
+ * rendering/render_form.cpp (layout): set IE-CSS-extension style palette
+ on <textarea> scrollbars (#56532).
+
+ * rendering/render_layer.cpp (showScrollbar): set IE-CSS-extension styled
+ palette on the overflow=scroll/auto scrollbars.
+
+ * rendering/render_frames.cpp (close): reorder. updateWidget() might
+ delete this.
+
+ * html/html_formimpl.cpp (value): return the DOM "defaultValue" when we have
+ no renderer.
+ (encoding): submit textarea even if display=none (#49829)
+
+ * ecma/kjs_dom.cpp (getValueProperty): add bindings to clientWidth/Height,
+ scrollWidth/height,offsetTop/left,offsetWidth/Height,offsetParent.
+ (getValueProperty): don't map body to canvas (#59676).
+
+ * split up borderSpacing into a horizontal and vertical border spacing so that
+ tables can have assymmetric spacing.
+
+ * html/htmlparser.cpp (insertNode): don't set css list position on stray <li>
+ elements. its an inherited attribute, and might mess up rendering of nested
+ <ul>/<ol> constructs.
+
+ * rendering/render_list.cpp: ListItems are no longer floats.
+
+2003-10-19 Dirk Mueller <mueller@kde.org>
+
+ * html/html_headimpl.cpp (childrenChanged): make sure that we respect the media
+ attribute of <style> (#47786).
+
+2003-10-19 Harri Porten <porten@kde.org>
+
+ * html/html_documentimpl.cpp (setCookie): use latin1 encoding to
+ have a 1:1 translation of the lowest Unicode row.
+
+2003-10-19 Dirk Mueller <mueller@kde.org>
+
+ * html/htmltokenizer.cpp (parseEntity): when entity is terminated and result
+ is not-ascii, require ending ';'. tdehtmltests/html/parser/obscure_entity_tokenizing.html
+
+2003-10-18 Dirk Mueller <mueller@kde.org>
+
+ * css/cssstyleselector.cpp (checkOneSelector): fix selector list matching
+ when substrings match in a word. we have to test if we matched a complete word,
+ otherwise its not a match.
+
+ * html/htmltokenizer.cpp (parseEntity): don't do the magic-unterminated-entities-IE-hack
+ when inside a tag. fixes <a href="/foo.html&section=2">
+
+ * html/htmlparser.cpp (insertNode): fix typo (#66200).
+
+ * rendering/render_table.cpp (seekCell): make static. check for out of bounds.
+ * rendering/render_table.cpp (RenderTableSection::checkSelectionPoint): fix
+ brain damage (#66198).
+
+2003-10-14 David Faure <faure@kde.org>
+
+ * misc/htmltags.in, html/htmlparser.cpp, html/dtd.cpp: added very basic
+ support for <ilayer>, much like <layer>, as a generic block element.
+ Fixes sites looking for such elements by ID, like www.sp ort1.de's diashow.
+
+2003-10-14 Wilco Greven <greven@kde.org>
+ * ecma/kjs_window.cpp (tryCall): Scroll should do the same as
+ ScrollTo, not ScrollBy. #63301
+
+2003-10-14 David Faure <faure@kde.org>
+
+ * xml/dom_nodeimpl.cpp (handleLocalEvents): Fixed infinite loop in
+ NodeImpl::handleLocalEvents due to braindead QPtrList behavior. #61623.
+
+2003-10-10 Harri Porten <porten@kde.org>
+
+ * ecma/kjs_html.cpp: title and alt attributes should never be null
+
+ * ecma/kjs_html.cpp (toString): make use of alt attribute if set
+
+2003-10-09 Dirk Mueller <mueller@kde.org>
+
+ * ecma/kjs_dom.cpp (putValueProperty): don't scroll layer when there is is nothing
+ to scroll. (David Hyatt)
+
+ * rendering/render_object.cpp (scrollHeight): return overflowHeight() not contentHeight()
+ by default. (David Hyatt)
+
+ * rendering/render_object.cpp (scrollWidth): return overflowWidth() not contentWidth()
+ by default. (David Hyatt)
+
+ * html/htmltokenizer.cpp (parseEntity): Improve tokenizing of unterminated
+ entities.
+
+2003-10-09 Leo Savernik <l.savernik@aon.at>
+
+ * rendering/render_object.{cpp,h} (getTextDecorationColors),
+ rendering/render_text.{cpp,h} (InlineTextBox::paintDecoration, RenderText::paintObject),
+ rendering/render_style.{cpp,h},
+ css/cssstyleselector.cpp (styleForElement):
+ fixed text-decoration issues by merging RenderObject::getTextDecorationColor
+ from Safari, changed CSSStyleSelector appropriately
+
+ * rendering/render_text.{cpp,h} (InlineTextBox::paintDecoration),
+ rendering/font.{cpp,h} (drawText, drawDecoration):
+ fixed drawing of text decoration within selected text
+
+ * rendering/render_text.cpp (paintObject),
+ rendering/font.{cpp,h} (drawText):
+ fixed overspilling of selection with unusual line-height configurations
+
+2003-10-07 Germain Garand <germain@ebooksfrance.org>
+
+ * tdehtmlview.cpp (viewportMouseReleaseEvent/viewportMouseMoveEvent): forward
+ meaningful peripheral mouse events to focused widget to restore correct
+ mouse handling in proxied widgets. #65216 (selection part)
+
+ * rendering/render_replaced.cpp (handleEvent):
+ map MOUSEOUT/MOUSEOVER DOM events to Enter/Leave events. Honours stacking
+ while mouse buttons are pressed.
+
+ * html/html_formimpl.cpp (defaultEventHandler): forward MOUSEOUT/MOUSEOVER
+ to handleEvent
+
+2003-10-06 Daniel Molkentin <molkentin@kde.org>
+
+ * ecma/kjs_window.cpp: added window.open targets _self and replace
+
+2003-10-06 David Faure <faure@kde.org>
+
+ * ecma/kjs_html.cpp: Fixed crash due to onload=null in the onload event
+ handler (#57195).
+
+2003-10-06 Dirk Mueller <mueller@kde.org>
+
+ * tdehtml_part.cpp (jScript): remove broken #ifdef'ery.
+ (popupMenu): add a QGuardedPtr to detect the case when we're destructed
+ before the popup menu is closed. avoid accessing any "this" then.
+ #43389
+
+ * tdehtmlview.cpp (viewportMousePressEvent): reorder afaik unrelated code
+ to make the one call entering a local event loop the last, so that we can
+ cleanly exit when it the view is already deleted.
+
+ * tdehtml_ext.cpp (KHTMLPopupGUIClient): pass QObject parent
+
+2003-10-05 Dirk Mueller <mueller@kde.org>
+
+ * ecma/kjs_css.cpp (tryPut): Fix CSSValue refcounting error causing major
+ memory leak.
+
+ * dom/css_value.cpp/h (class CSSStyleDeclaration): make accessors const. Add
+ binary compatibility wrappers.
+
+2003-10-04 Germain Garand <germain@ebooksfrance.org>
+
+ * rendering/render_replaced.cpp (baselinePosition): use setPos to adjust
+ layer position if needed. Fix relatively positioned widgets not being painted.
+
+2003-10-04 Dirk Mueller <mueller@kde.org>
+
+ * html/htmlparser.h (class KHTMLParser): keep "current" NodeImpl referenced
+ to avoid ugly crashes when DHTML deletes the node while we're still parsing.
+ #57020, testcase alja.html
+
+
+2003-10-04 Dirk Mueller <mueller@kde.org>
+
+ * tdehtml_settings.cc (init): change default for JS debugger to off.
+
+ * html/html_elementimpl.cpp (createContextualFragment): Fix memory
+ leaks. Adjust code style. Adjust return to avoid dangling return leaks.
+
+ * xml/dom2_rangeimpl.cpp (createContextualFragment): adjust return type.
+
+ * html/html_elementimpl.h (class HTMLElementImpl): adjust return type.
+
+ * dom/dom2_range.cpp (createContextualFragment): Adjust to DocumentFragment
+ return type.
+
+
diff --git a/tdehtml/DESIGN.html b/tdehtml/DESIGN.html
new file mode 100644
index 000000000..861825141
--- /dev/null
+++ b/tdehtml/DESIGN.html
@@ -0,0 +1,346 @@
+<html>
+<head>
+<title>Internal design of tdehtml</title>
+<style>
+dt { font-weight: bold; }
+</style>
+<body bgcolor=white>
+<h1>Internal design of tdehtml</h1>
+
+<p>
+This document tries to give a short overview about the internal design of the tdehtml
+library. I've written this, because the lib has gotten quite big, and it is hard at first to find your
+way in the source code. This doesn't mean that you'll understand tdehtml after reading this
+document, but it'll hopefully make it easier for you to read the source code.
+</p>
+<p>
+The library is build up out of several different parts. Basically, when you use the lib, you
+create an instance of a KHTMLPart, and feed data to it. That's more or less all you need to
+know if you want to use tdehtml for another application. If you want to start hacking tdehtml,
+here's a sketch of the objects that will get constructed, when eg. running testtdehtml with
+a url argument.
+</p>
+<p>
+In the following I'll assume that you're familiar with all the buzzwords used in current web
+techology. In case you aren't here's a more or less complete list of references:
+</p>
+<blockquote>
+<p>
+<b>Document Object model (DOM):</b><br>
+<a href="http://www.w3.org/DOM/">DOM Level1 and 2</a><br>
+We support DOM Level2 except for the events model at the moment.
+</p>
+<p>
+<b>HTML:</b><br>
+<a href="http://www.w3.org/TR/html4/">HTML4 specs</a><br>
+<a href="http://www.w3.org/TR/xhtml1/">xhtml specs</a><br>
+We support almost all of HTML4 and xhtml.
+</p>
+<p>
+<b>Cascading style sheets (CSS):</b><br>
+<a href="http://www.w3.org/TR/REC-CSS2/">CSS2 specs</a><br>
+We support almost all of CSS1, and most parts of CSS2.
+</p>
+<p>
+<b>Javascript:</b><br>
+<a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/objects.asp">Microsoft javascript bindings</a><br>
+<a href="http://docs.sun.com/source/816-6408-10/index.html">Netscape javascript reference</a><br>
+Netscapes javascript bindings are outdated. We shouldn't follow them. Let's focus on getting the bindings
+compatible to IE.
+<a href="http://mozilla.org/docs/dom/domref/">Mozilla JS/DOM reference</a>
+</p>
+</blockquote>
+
+<p>
+<a href="tdehtml_part.h">KHTMLPart</a> creates one instance of a
+<a href="tdehtmlview.h">KHTMLView</a> (derived from TQScrollView),
+the widget showing the whole thing. At the same time a DOM tree
+is built up from the HTML or XML found in the specified file.
+<p>
+Let me describe this with an example.
+<p>
+tdehtml makes use of the document object model (DOM) for storing the document
+in a tree like structure. Imagine some html like
+<pre>
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;style&gt;
+ h1: { color: red; }
+ &lt;/style&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;H1&gt;
+ some red text
+ &lt;/h1&gt;
+ more text
+ &lt;p&gt;
+ a paragraph with an
+ &lt;img src="foo.png"&gt;
+ embedded image.
+ &lt;/p&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre>
+In the following I'll show how this input will be processed step by step to generate the visible output
+you will finally see on your screen. I'm describing the things as if they happen one after the other,
+to make the principle more clear. In reality, to get visible output on the screen as soon as possible,
+all these things (from tokenization to the build up and layouting of the rendering tree) happen
+more or less in parallel.
+
+<h2>Tokenizer and parser</h2>
+<p>
+The first thing that happens when you start parsing a new document is that a
+DocumentImpl* (for XML documents) or an HTMLDocumentImpl* object will get
+created by the Part (in tdehtml_part.cpp::begin()). A Tokenizer*
+object is created as soon as DocumentImpl::open() is called by the part, also
+in begin() (can be either an XMLTokenizer or an HTMLTokenizer).
+<p>
+The XMLTokenizer uses the QXML classes in Qt to parse the document, and it's SAX interface
+to parse the stuff into tdehtmls DOM.
+<p>
+For HTML, the tokenizer is located in tdehtmltokenizer.cpp. The tokenizer uses the contents
+of a HTML-file as input and breaks this contents up in a linked list of
+tokens. The tokenizer recognizes HTML-entities and HTML-tags. Text between
+begin- and end-tags is handled distinctly for several tags. The distinctions
+are in the way how spaces, linefeeds, HTML-entities and other tags are
+handled.
+<p>
+The tokenizer is completely state-driven on a character by character basis.
+All text passed over to the tokenizer is directly tokenized. A complete
+HTML-file can be passed to the tokenizer as a whole, character by character
+(not very efficient) or in blocks of any (variable) size.
+<p>
+The HTMLTokenizer creates an HTMLParser which
+interprets the stream of tokens provided by the tokenizer
+and constructs the tree of Nodes representing the document according
+to the Document Object Model.
+<p>
+
+<h2>The DOM in tdehtml</h2>
+<p>
+Parsing the document given above gives the following DOM tree:
+
+<pre>
+HTMLDocumentElement
+ |--> HTMLHeadElement
+ | \--> HTMLStyleElement
+ | \--> CSSStyleSheet
+ \--> HTMLBodyElement
+ |--> HTMLHeadingElement
+ | \--> Text
+ |--> Text
+ \--> HTMLParagraphElement
+ |--> Text
+ |--> HTMLImageElement
+ \--> Text
+</pre>
+<p>
+Actually, the classes mentioned above are the interfaces for accessing the
+DOM. The actual data is stored in *Impl classes, providing the implementation
+for all of the above mentioned elements. So internally we have a tree
+looking like:
+<pre>
+HTMLDocumentElementImpl*
+ |--> HTMLHeadElementImpl*
+ | \--> HTMLStyleElementImpl*
+ | \--> CSSStyleSheetImpl*
+ \--> HTMLBodyElementImpl*
+ |--> HTMLHeadingElementImpl*
+ | \--> TextImpl*
+ |--> TextImpl*
+ \--> HTMLParagraphElementImpl*
+ |--> TextImpl*
+ |--> HTMLImageElementImpl*
+ \--> TextImpl*
+</pre>
+<p>
+We use a refcounting scheme to assure that all the objects get deleted, in
+case the root element gets deleted (as long as there's no interface class
+holding a pointer to the Implementation).
+<p>
+The interface classes (the ones without the Impl) are defined in the <code>dom/</code>
+subdirectory, and are not used by tdehtml itself at all. The only place they are used are in the
+javascript bindings, which uses them to access the DOM tree. The big advantage of having this
+separation between interface classes and imlementation classes, is that we can have several
+interface objects pointing to the same implementation. This implements the requirement of
+explicit sharing of the DOM specs.
+<p>
+Another advantage is, that (as the implementation classes are not exported) it gives us a lot
+more freedom to make changes in the implementation without breaking binary compatibility.
+<p>
+You will find almost a one to one correspondence between the interface classes and the implementation
+classes. In the implementation classes we have added a few more intermediate classes, that can
+not be seen from the outside for various reasons (make implementation of shared features easier
+or to reduce memory consumption).
+<p>
+In C++, you can access the whole DOM tree from outside KHTML by using the interface classes.
+For a description see the <a href="http://developer.kde.org/documentation/library/kdeqt/trinityarch/tdehtml/index.html">introduction to tdehtml</a> on <a href="http://developer.kde.org/">developer.kde.org</a>.
+
+One thing that has been omitted in the discussion above is the style sheet defined inside the
+<code>&lt;style&gt;</code> element (as an example of a style sheet) and the image element
+(as an example of an external resource that needs to be loaded). This will be done in the following
+two sections.
+
+<h2>CSS</h2> The contents of the <code>&lt;style&gt;</code> element (in this
+case the <code>h1 { color: red; }</code> rule) will get passed to the
+<a href="html/html_headimpl.h">HTMLStyleElementImpl object</a>. This object creates an
+<a href="css/cssstylesheetimpl.h">CSSStyleSheetImpl object</a> and passes the
+data to it. The <a href="css/cssparser.h">CSS parser</a> will take
+the data, and parse it into a DOM structure for CSS (similar to the one for
+HTML, see also the DOM level 2 specs). This will be later on used to define the
+look of the HTML elements in the DOM tree.
+<p>
+Actually "later on" is relative, as we will see later, that this happens partly in parallel to
+the build up of the DOM tree.
+
+<h2>Loading external objects</h2>
+<p>
+Some HTML elements (as <code>&lt;img&gt;, &lt;link&gt;, &lt;object&gt;, etc.</code>) contain
+references to external objects, that have to be loaded. This is done by the
+Loader and related classes (misc/loader.*). Objects that might need to load external objects
+inherit from <a href="misc/loader_client.h">CachedObjectClient</a>, and can ask
+the <a href="misc/loader.h">loader</a> (that also acts as a memory cache) to
+download the object they need for them from the web.
+<p>
+Once the <a href="misc/loader.h">loader</a> has the requested object ready, it will notify the
+<a href="misc/loader_client.h">CachedObjectClient</a> of this, and the client can
+then process the received data.
+
+<h2>Making it visible</h2>
+
+Now once we have the DOM tree, and the associated style sheets and external objects, how
+do we get the stuff actually displayed on the screen?
+<p>
+For this we have a rendering engine, that is completely based on CSS. The first
+thing that is done is to collect all style sheets that apply to the document
+and create a nice list of style rules that need to be applied to the
+elements. This is done in the <a href="css/cssstyleselector.h">CSSStyleSelector</a> class.
+It takes the <a href="css/html4.css">default HTML style sheet</a> (defined in css/html4.css),
+an optional user defined style sheet, and all style sheets from the document,
+and combines them to a nice list of parsed style rules (optimised for fast
+lookup). The exact rules of how these style sheets should get applied to HTML
+or XML documents can be found in the CSS2 specs.
+<p>
+Once we have this list, we can get a <a
+href="rendering/render_style.h">RenderStyle object</a>
+for every DOM element from the <a
+href="css/cssstyleselector.h">CSSStyleSelector</a> by calling
+"styleForElement(DOM::ElementImpl *)".
+The style object describes in a compact form all the
+<a href="css/css_properties.in">CSS properties</a>
+that should get applied to the Node.
+<p>
+After that, a rendering tree gets built up. Using the style object, the
+<a href="xml/dom_nodeimpl.h">DOM Node</a> creates an appropriate render object
+(all these are defined in the rendering subdirectory) and adds it to the
+rendering tree. This will give another tree like structure, that resembles in
+it's general structure the DOM tree, but might have some significant
+differences too. First of all, so called
+ <a href="http://www.w3.org/TR/REC-CSS2/visuren.html#anonymous-block-level">anonymous boxes</a> - (see
+ <a href="http://www.w3.org/TR/REC-CSS2/">CSS specs</a>) that
+have no DOM counterpart might get inserted into the rendering tree to satisfy
+DOM requirements. Second, the display property of the style affects which type
+of rendering object is chosen to represent the current DOM object.
+
+<p>
+In the above example we would get the following rendering tree:
+<pre>
+RenderRoot*
+ \--> RenderBody*
+ |--> RenderFlow* (&lt;H1&gt;)
+ | \--> RenderText* ("some red text")
+ |--> RenderFlow* (anonymous box)
+ | \--> RenderText* ("more text")
+ \--> RenderFlow* (&lt;P&gt;)
+ |--> RenderText* ("a paragraph with an")
+ |--> RenderImage*
+ \--> RenderText* ("embedded image.")
+</pre>
+
+<p>
+A call to of <a href="rendering/render_root.cpp">layout()</a> on the
+<a href="rendering/render_root.h">RenderRoot </a> (the root of the rendering tree)
+object causes the rendering tree to layout itself into the available space
+(width) given by the the KHTMLView. After that, the drawContents() method of
+KHTMLView can call RenderRoot->print() with appropriate parameters to actually
+paint the document. This is not 100% correct, when parsing incrementally, but
+is exactly what happens when you resize the document.
+
+
+As you can see, the conversion to the rendering tree removed the head part of
+the HTML code, and inserted an anonymous render object around the string "more
+text". For an explanation why this is done, see the CSS specs.
+<p>
+
+<h2>Directory structure</h2>
+
+A short explanation of the subdirectories in tdehtml.
+<dl>
+<dt><a href="css/">css:</a>
+<dd>Contains all the stuff relevant to the CSS part of DOM Level2 (implementation classes only),
+the <a href="css/cssparser.h">CSS parser</a>, and the stuff to create
+RenderStyle object out of Nodes and the CSS style sheets.
+<dt><a href="dom/">dom: </a>
+<dd>Contains the external DOM API (the DOM interface classes) for all of the DOM
+<dt><a href="ecma/">ecma:</a>
+<dd>The javascript bindings to the DOM and tdehtml.
+<dt><a href="html/">html:</a>
+<dd>The html subpart of the DOM (implementation only), the HTML tokenizer and parser and a class
+that defines the DTD to use for HTML (used mainly in the parser).
+<dt><a href="java/">java:</a>
+<dd>Java related stuff.
+<dt><a href="misc/">misc:</a>
+<dd>Some misc stuff needed in tdehtml. Contains the image loader, some misc definitions and the
+decoder class that converts the incoming stream to unicode.
+<dt><a href="rendering">rendering:</a>
+<dd>Everything thats related to bringing a DOM tree with CSS declarations to the screen. Contains
+the definition of the objects used in the rendering tree, the layouting code, and the RenderStyle objects.
+<dt><a href="xml/">xml:</a>
+<dd>The XML part of the DOM implementation, the xml tokenizer.
+</dl>
+
+<h2>Exception handling</h2>
+To save on library size, C++-exceptions are only enabled in the dom/ subdirectory,
+since exceptions are mandated by the DOM API. In the rest of KHTML's code,
+we pass an error flag (usually called "exceptionCode"), and the class that
+is part of dom/* checks for this flag and throws the exception.
+
+<h2>Final words...</h2>
+<p>
+All the above is to give you a quick introduction into the way tdehtml brings an HTML/XML file to the screen.
+It is by no way complete or even 100% correct. I left out many problems, I will perhaps add either on request
+or when I find some time to do so. Let me name some of the missing things:
+<ul>
+<li>The decoder to convert the incoming stream to Unicode
+<li>interaction with konqueror/applications
+<li>javascript
+<li>dynamic reflow and how to use the DOM to manipulate tdehtmls visual output
+<li>mouse/event handling
+<li>real interactions when parsing incrementally
+<li>java
+</ul>
+
+Still I hope that this short introduction will make it easier for you to get a first hold of tdehtml and the way it works.
+<p>
+Now before I finish let me add a small <b>warning</b> and <b>advice</b> to all of you who plan hacking tdehtml themselves:
+<p>
+tdehtml is by now a quite big library and it takes some time to understand how it works. Don't let yourself get frustrated
+if you don't immediately understand how it works. On the other hand, it is by now one of the libraries that
+get used a lot, that probably has the biggest number of remaining bugs (even though it's sometimes hard to
+know if some behavior is really a bug).
+<blockquote>
+Some parts of it's code are however <b>extremely touchy</b> (especially the layouting algorithms),
+and making changes there (that might fix a bug on one web page) might introduce severe bugs.
+All the people developing tdehtml have already spend huge amounts of time searching for such bugs,
+that only showed up on some web pages, and thus were found only a week after the change that
+introduced the bug was made. This can be very frustrating for us, and we'd appreciate if people
+that are not completely familiar with tdehtml post changes touching these critical regions to kfm-devel
+for review before applying them.
+</blockquote>
+
+<div style="margin-top: 2em; font-size: large;">
+And now have fun hacking tdehtml.
+<div style="margin-left: 10em; margin-bottom: 1em;">Lars</div>
+</div>
+</body>
+</html>
diff --git a/tdehtml/Mainpage.dox b/tdehtml/Mainpage.dox
new file mode 100644
index 000000000..84ebfedb1
--- /dev/null
+++ b/tdehtml/Mainpage.dox
@@ -0,0 +1,46 @@
+/** @mainpage Trinity HTML Parser and Widget
+
+If you want a fully-fledged HTML browser widget in your application,
+you can use KHTMLPart to do so.
+
+@code
+KUrl url = "http://www.trinitydesktop.org";
+KHTMLPart *w = new KHTMLPart();
+w->openUrl(url);
+w->view()->resize(500, 400);
+w->show();
+@endcode
+
+For more information, see the documentation for KHTMLPart.
+
+Note that using KHTMLPart may introduce security vulnerabilities
+and unnecessary bloat to your application. Qt's text widgets are
+rich-text capable, and will interpret a limited subset of HTML.
+
+@authors
+Torben Weis \<weis@stud.uni-frankfurt.de\><br>
+Josip A. Gracin \<grac@fly.cc.fer.hr\><br>
+Martin Jones \<mjones@kde.org\><br>
+Waldo Bastian \<bastian@kde.org\><br>
+Lars Knoll \<knoll@kde.org\><br>
+Antti Koivisto \<koivisto@iki.fi\><br>
+Dirk Mueller \<mueller@kde.org\><br>
+Peter Kelly \<pmk@post.com\><br>
+George Staikos \<staikos@kde.org\><br>
+Allan Sandfeld Jensen \<kde@carewolf.com\><br>
+Germain Garand \<germain@ebooksfrance.org\><br>
+Maksim Orlovich \<maksim@kde.org\><br>
+KHTML has also heavily benefited from the work of Apple Computer, Inc.
+@maintainers
+Allan Sandfeld Jensen <br>
+Germain Garand<br>
+Maksim Orlovich
+
+@licenses
+@lgpl
+
+*/
+// DOXYGEN_REFERENCES = tdecore tdeui kio tdeparts kjs
+// DOXYGEN_EXCLUDE = test*.* html rendering xml misc ecma css imload pics test
+// DOXYGEN_SET_PROJECT_NAME = KHTML
+// vim:ts=4:sw=4:expandtab:filetype=doxygen
diff --git a/tdehtml/Makefile.am b/tdehtml/Makefile.am
new file mode 100644
index 000000000..3c9cb05c5
--- /dev/null
+++ b/tdehtml/Makefile.am
@@ -0,0 +1,133 @@
+# 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)
+
+if DOJAVA
+JAVA_SUBDIR=java
+LIBKJAVA=
+endif
+
+SUBDIRS = misc dom css xml html rendering pics $(JAVA_SUBDIR) ecma . tdemultipart
+
+CLEANFILES = dummy.cpp
+
+lib_LTLIBRARIES = libtdehtml.la
+kde_module_LTLIBRARIES = libtdehtmlpart.la tdehtmlimagepart.la
+
+libtdehtml_la_SOURCES = kjserrordlg.ui tdehtmlview.cpp tdehtml_part.cpp tdehtml_run.cpp\
+ tdehtml_factory.cpp tdehtml_settings.cc tdehtml_events.cpp \
+ tdehtml_ext.cpp tdehtml_pagecache.cpp tdehtml_iface.skel \
+ tdehtml_iface.cc tdehtml_printsettings.cpp htmlpageinfo.ui \
+ tdehtmlimage.cpp
+
+libtdehtml_la_METASOURCES = AUTO
+
+include_HEADERS = tdehtmlview.h tdehtml_part.h tdehtml_events.h tdehtml_settings.h tdehtmldefaults.h
+
+noinst_HEADERS = design.h testtdehtml.h test_regression.h tdehtml_ext.h \
+ tdehtml_pagecache.h tdehtmlimage.h tdehtmlpart_p.h tdehtml_printsettings.h \
+ kjserrordlg.ui.h
+
+if include_VERSION_SCRIPT
+VSCRIPT = -Wl,--version-script=$(srcdir)/libtdehtml.map
+endif
+
+libtdehtml_la_LDFLAGS = -version-info 6:0:2 -no-undefined $(VSCRIPT) $(all_libraries)
+libtdehtml_la_LIBADD = ./xml/libtdehtmlxml.la ./html/libtdehtmlhtml.la \
+ ./rendering/libtdehtmlrender.la ./css/libtdehtmlcss.la \
+ ./misc/libtdehtmlmisc.la ecma/libkjs_html.la ./dom/libtdehtmldom.la $(LIBKJAVA) \
+ $(LIB_KPARTS) \
+ $(LIBTHAI) \
+ $(top_builddir)/tdeprint/libtdeprint.la \
+ $(top_builddir)/tdeutils/libtdeutils.la \
+ $(top_builddir)/tdewallet/client/libtdewalletclient.la $(top_builddir)/kjs/libkjs.la $(LIB_TDEUI) $(LIB_QT) $(LIB_TDECORE) $(LIB_KFILE) $(top_builddir)/dcop/libDCOP.la $(LIBJPEG) $(LIB_X11)
+
+# init_libtdehtml is in libtdehtml.so; init_libtdehtmlpart needs to be in the part
+dummy.cpp: $(srcdir)/Makefile.am
+ echo '#include <tdelibs_export.h>' > $@
+ echo 'extern "C" KDE_EXPORT void* init_libtdehtml();' >> $@
+ echo 'extern "C" KDE_EXPORT void* init_libtdehtmlpart() { return init_libtdehtml(); } ' >> $@
+
+libtdehtmlpart_la_SOURCES = dummy.cpp
+libtdehtmlpart_la_LDFLAGS = -no-undefined -module $(KDE_PLUGIN) $(all_libraries)
+libtdehtmlpart_la_LIBADD = libtdehtml.la $(LIB_QT)
+
+# init_tdehtmlimagefactory is in libtdehtml.so; init_tdehtmlimagepart needs to be in the part
+imgdummy.cpp: $(srcdir)/Makefile.am
+ echo '#include <tdelibs_export.h>' > $@
+ echo 'extern "C" KDE_EXPORT void* init_tdehtmlimagefactory();' >> $@
+ echo 'extern "C" KDE_EXPORT void* init_tdehtmlimagepart() { return init_tdehtmlimagefactory(); } ' >> $@
+
+tdehtmlimagepart_la_SOURCES = imgdummy.cpp
+tdehtmlimagepart_la_LDFLAGS = -no-undefined -module $(KDE_PLUGIN) $(all_libraries)
+tdehtmlimagepart_la_LIBADD = libtdehtml.la $(LIB_QT)
+
+INCLUDES = -I$(top_srcdir)/kjs -I$(top_builddir)/kjs -I$(top_srcdir)/kimgio \
+ -I$(srcdir)/java -I$(top_srcdir)/dcop -I$(srcdir)/misc \
+ -I$(srcdir)/dom -I$(srcdir)/xml -I$(srcdir)/html -I$(srcdir)/css \
+ -I$(top_srcdir)/libltdl \
+ -I$(top_srcdir)/kio/kssl -I$(top_builddir)/kio/kssl \
+ -I$(top_srcdir)/tdeprint \
+ -I$(top_srcdir)/interfaces \
+ -I$(top_srcdir)/interfaces/kregexpeditor \
+ -I$(top_srcdir)/tdewallet/client \
+ -I$(top_srcdir)/tdeutils \
+ -I$(top_srcdir) $(all_includes)
+
+servicedir = $(kde_servicesdir)
+service_DATA = tdehtml.desktop tdehtmlimage.desktop
+
+rcdir = $(kde_datadir)/tdehtml
+rc_DATA = tdehtml.rc tdehtml_browser.rc tdehtml_popupmenu.rc
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) tdecore \
+ $(include_HEADERS) -lqt
+
+EXTRA_DIST = CHANGES DESIGN README.HTMLWidget README.tags
+
+parser:
+ cd $(srcdir) && \
+ perl scripts/makeattrs && \
+ bash scripts/maketags && \
+ bash scripts/makeprop
+
+## test program
+check_PROGRAMS = testtdehtml
+EXTRA_PROGRAMS = testtdehtml_static testregression
+testtdehtml_SOURCES = testtdehtml.cpp domtreeview.cpp
+testtdehtml_LDADD = libtdehtml.la
+testtdehtml_static_SOURCES = testtdehtml.cpp domtreeview.cpp
+testtdehtml_static_LDADD = libtdehtml.la
+testtdehtml_static_LDFLAGS = -static
+testregression_SOURCES = test_regression.cpp test_regression_fontoverload.cpp
+testregression_LDADD = libtdehtml.la
+
+DOXYGEN_REFERENCES = tdecore tdeui kio tdefx tdeparts
+DOXYGEN_EXCLUDE = test*.* css ecma html java tdemultipart misc pics rendering test xml
+
+include ../admin/Doxyfile.am
+
+.PHONY: parser
+
diff --git a/tdehtml/README.HTMLWidget b/tdehtml/README.HTMLWidget
new file mode 100644
index 000000000..2a8900ee2
--- /dev/null
+++ b/tdehtml/README.HTMLWidget
@@ -0,0 +1,66 @@
+KDE HTML Widget
+===============
+
+Developers
+----------
+
+The first version was written by
+
+Torben Weis <weis@stud.uni-frankfurt.de>
+
+It was extended by
+
+Josip A. Gracin <grac@fly.cc.fer.hr>,
+Martin Jones <mjones@kde.org>,
+Waldo Bastian <bastian@kde.org>
+Lars Knoll <knoll@kde.org>
+Antti Koivisto <koivisto@iki.fi>
+Dirk Mueller <mueller@kde.org>
+Peter Kelly <pmk@post.com>
+
+It is currently primarily maintained and developed by
+Lars Knoll, Dirk Mueller and Antti Koivisto.
+
+
+Revision History
+----------------
+
+This library is called libtdehtml.
+This library used to be called libtdehtmlw. With the release of KDE 1.1 a
+source incompatible version called libtdehtml has been created.
+libtdehtmlw will not be maintained any more, all application writers are
+urgently requested to make use of the new libtdehtml library.
+
+
+Starting Point
+--------------
+
+You can add the widget to your program by doing something like:
+
+#include <tdehtml.h>
+
+ .
+ .
+ .
+
+ KHTMLWidget *view = new KHTMLWidget( parent, "Name" );
+ view->show();
+
+ view->begin( "file:/tmp/test.html" );
+ view->parse();
+ view->write( "<HTML><TITLE>...." );
+ view->write( "..." );
+ .
+ .
+ .
+ view->write( "</HTML>" );
+ view->end();
+
+
+After doing this, control must be returned to the event loop as the HTML
+is parsed in the background using a Qt timer.
+
+For more information see the full documentation in JavaDoc format included
+in the header files.
+
+
diff --git a/tdehtml/SAFARI_MERGE b/tdehtml/SAFARI_MERGE
new file mode 100644
index 000000000..427c3d1c8
--- /dev/null
+++ b/tdehtml/SAFARI_MERGE
@@ -0,0 +1,161 @@
+
+This is a short document with the progress of patches in the Safari codebase
+being merged into tdehtml.
+
+its ordered by directory and by files. Add here the parts that cannot be
+immediately merged and need further negotiation.
+
+Its recommended to add a //FIXME_SAFARI comment to places which need merging
+in the tdehtml sourcecode.
+
+===========================================================================
+# css
+===========================================================================
+
+- the font changes (except for the konq-body property) are still not merged.
+ They are partly not easily portable and I don't understand some parts of them.
+ a small part is merged but still unused (separate font sizes for fixed fonts)
+
+- The Apple specific parts with their DPI settings.
+
+- most of the html4.css changes are not in. I have already added the
+ @konq-quirks part
+
+===========================================================================
+# dom
+===========================================================================
+
+- dom_doc.cpp / .h: preferred Stylesheet stuff. how does this correlate
+ to the changes in css_stylesheet.h / cpp ? <- It's independent (lars).
+ requires merging of the impl in xml/html first
+
+- css_stylesheet.cpp / .h addition of preferredStyleSheet et all, but
+ appears to be unused
+
+- weird change in dom_doc.cpp: doctype()
+
+- dom_string.h: removal of virtual destructor can't be merged, BIC.
+ doesn't make sense anyway, as one might want to inherit from it.
+ if it is a speed problem more stuff has to be handled with DOMStringImpl*
+
+- html_document.cpp / .h setPolicyBaseURL for cookie handling. euhm?
+
+===========================================================================
+# ecma
+===========================================================================
+
+TODO:
+- ScriptInterpreter domObjectsPerDocument + getDOMDocumentNode
+
+To investigate:
+- kjs_navigator (PluginBase refcount ; ProductSub)
+ hmm, why is e.g. the ref/deref stuff in APPLE_CHANGES?
+- scope changes (kjs_events.cpp, DOMNode::pushEventHandlerScope)
+- Image object: DOM::Document doc -> QGuardedPtr<DOM::DocumentImpl> doc;
+ (why? Or rather: should this also be done in all other domobject-wrappers?)
+- window.scroll == scrollto or scrollby ??
+- ScheduledAction: ObjectImp -> Object. Sounds good - why did we have an imp? refcount problem?
+
+Needs other stuff before it can be applied:
+- Identifier change (needs kjs2) (includes lengthPropertyName change)
+
+===========================================================================
+# html
+===========================================================================
+
+- dtd.cpp: changes regareding ID_TEXT, ID_FORM, A and FONT left out
+
+- html_formimpl.cpp/.h: many changes skipped. will need to integrate the
+ "activate first submit" button part.
+
+- html_headimpl.cpp: changes for FOUC in external style loading
+
+- html_image/html_form: name / id lookup cache skipped. want to do that
+ for all elements.
+
+- html_miscimpl.cpp: case insensitive name / id matching
+
+- html_parser: reapplying of dropped attributes. reported to be obsolete
+
+===========================================================================
+# misc
+===========================================================================
+
+- decoder.cpp/.h: changes in APPLE_CHANGES #ifdef that make decoder
+ being a null wrapper just using unicode directly instead of working
+ on charset specific 8bit data.
+
+- htmltags.in: removal of <-konqblock>, not sure if that should ever
+ be merged.
+
+===========================================================================
+# rendering
+===========================================================================
+
+done so far:
+
+- RenderArena support. Usage of the arena is disabled for now. Needs
+ testing before I'll enable it.
+
+- renamed print methods to paint
+
+- RendeLayer code is used. Needs to be updated to apples latest version.
+
+- Handling of block within inlines via continuations is done.
+
+changes that need to be merged:
+
+- bidi.h/cpp: lot's of changes to white space handling and others.
+ probably needs the merge of the tokenizer.
+
+- font.cpp/h: some apple specific changes. Addition of a genericFamily enum,
+ IMO to speed up style stuff. Should IMO be separated out into a font_mac.cpp
+ and font_x11.cpp
+
+- repaint has gotten a bool immediate
+
+- render_applet.cpp: small #ifdef APPLE changes
+
+- render_box.cpp:
+ paintBackground has some fixes for background position in
+ table cells and repeat handling. Need to examine in detail
+
+ calcWidth has some code for min and max width constraints
+ calcHeight has a hack for "height: 100%". Not sure I understand it.
+
+- render_container:
+ some hack to avoid an infinite recursion on one of the evil tests.
+ Since I fixed anonymous table insertion, I doubt it is still needed. Needs testing.
+
+....
+
+
+===========================================================================
+# xml
+===========================================================================
+
+- dom2_eventsimpl.cpp: computeLayerPos, requires mering of rendering/
+
+- dom2_rangeimpl.cpp: crateContextualFragmet.. merging needed
+
+- dom_docimpl.cpp:
+ renderArena support.. merging needed.
+ lowercase attribute names.. requires confirmation
+ preferred style sheet / delay recalcing style selector till
+ all external stylesheets are loaded.
+
+- dom_nodeimpl.cpp: rendererNeedsClose. I don't fully understand this
+ seems to be only required for the avoid-unstyled-elements-flicker
+ restoreState -> QStringList change. will merge.
+ setLayouted(false) calls in attach(). this should imho be handled
+ in the rendering tree. needs feedback.
+
+- dom_nodeimpl.cpp / .h: setMalformed() hack.
+ isInline() fixes.
+ previous/nextrenderer addition
+
+- dom_stringimpl.cpp: toLengthArray alternative implementation not merged
+
+- dom_textimpl.cpp: setNodeValue: whitespace nuking needs merged!!
+
+- xml_tokenizer.cpp/.h: completely skipped. unfinished work.
diff --git a/tdehtml/TODO b/tdehtml/TODO
new file mode 100644
index 000000000..d22e3f83d
--- /dev/null
+++ b/tdehtml/TODO
@@ -0,0 +1,60 @@
+Here's what's still missing (without order):
+
+Rendering:
+ * text-align: Justify missing
+ * allow font elements in a block level context.
+
+StyleSheets:
+ * @ rules in sheets
+ * lots of properties
+ * delete the old cssproperties in a style attribute in case
+ the style attribute changes.
+ * border shorthand properties. Unspecified properties get their default
+ values. border-width: medium; border-color: undefined (== text color)
+
+DOM:
+ * some functions in the Impl classes
+ * fix the set/retrieve functions, which use boolean values
+ -->> mostly done, still need to fix parseAttribute() calls
+ * DOM level 2
+ * DOM stylesheets, changes need to trigger the appropriate changes
+ in the rendering tree
+ * Implementation of NamedAttrMapImpl and Attributes in DOMElementImpl
+ is ugly. MOve aatributes to the elementImpl and make the namedNodeMap
+ point to an element. Think of creating AttrImpl's directly in
+ tdehtmltoken.cpp
+
+XML:
+ * lots of stuff in the Impl classes
+ * parsing
+ * entities
+ * style sheet processing instructions
+ * proper mimetype detection
+
+misc:
+ * <font size=+3> works as size=+1
+
+Java:
+ * support for the object element
+ --> mostly done
+ * Java <--> HTMLWidget communication
+ * turn kjava into a kpart
+
+Attributes:
+ * check for unimplemented attributes
+
+Memory usage:
+ * use bitfields for lots of things (especially in the
+ DOM/CSS/rendering stuff)
+ * try to make better use of shared objects, especially in the
+ RenderStyle
+ * check for leaks
+ * there's a mem leak with the style objects of anonymous
+ boxes (and ListMarkers).
+
+Other:
+ * there's a bug on correctly retrieving <textarea> text.
+ see test/forms.html and compare it with the way all other
+ browsers handle that code
+ * paste should be enabled (and implemented) if there's pasteable clipboard
+ content and a form element has the focus
diff --git a/tdehtml/configure.in.in b/tdehtml/configure.in.in
new file mode 100644
index 000000000..b85dd8474
--- /dev/null
+++ b/tdehtml/configure.in.in
@@ -0,0 +1,57 @@
+AM_CONDITIONAL(DOJAVA, test "x$kde_use_qt_emb" != "xyes")
+
+AC_DEFUN([KDE_CHECK_LIBTHAI],
+[
+AC_MSG_CHECKING([if libthai should be compiled in])
+ AC_ARG_WITH(libthai,
+ AC_HELP_STRING(
+ [--with-libthai=yes],
+ [add Thai-language support from libthai library [default=no]]
+ ),
+ [ ac_libthai=$withval],
+ [ ac_libthai=no ]
+ )
+
+if test "$ac_libthai" != "no"; then
+ AC_CACHE_VAL(kde_link_libthai,
+ [
+ kde_ldflags_safe="$LDFLAGS"
+ kde_libs_safe="$LIBS"
+
+ LDFLAGS="$LDFLAGS $USER_LDFLAGS"
+ LIBS="-lthai"
+
+ AC_TRY_LINK([
+ #include <thai/thailib.h>
+ #include <thai/thbrk.h>
+ ],
+ [
+ thchar_t c = 'C';
+ int pos[1];
+ size_t n = 12;
+ (void)th_brk(&c, pos, n);
+ ],
+ kde_link_libthai=yes,
+ kde_link_libthai=no
+ )
+
+ LDFLAGS=$kde_ldflags_safe
+ LIBS=$kde_libs_safe
+ ])
+
+ LIBTHAI=""
+ if test "$kde_link_libthai" = "no"; then
+ AC_MSG_ERROR([Can't find libthai.])
+ else
+ AC_DEFINE(HAVE_LIBTHAI, 1,
+ [Defined if you have libthai and want to have it compiled in])
+ LIBTHAI="-lthai"
+ fi
+ AC_SUBST(LIBTHAI)
+fi
+AC_MSG_RESULT($ac_libthai)
+])
+
+KDE_CHECK_LIBTHAI
+
+KDE_CHECK_HEADERS(valgrind/memcheck.h)
diff --git a/tdehtml/css/CMakeLists.txt b/tdehtml/css/CMakeLists.txt
new file mode 100644
index 000000000..4d0b52df1
--- /dev/null
+++ b/tdehtml/css/CMakeLists.txt
@@ -0,0 +1,47 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/tdewallet/client
+ ${CMAKE_SOURCE_DIR}/tdeutils
+)
+
+
+##### other data ################################
+
+install( FILES html4.css quirks.css DESTINATION ${DATA_INSTALL_DIR}/tdehtml/css )
+
+
+##### tdehtmlcss (static) #########################
+
+set( target tdehtmlcss )
+
+set( ${target}_SRCS
+ css_stylesheetimpl.cpp css_ruleimpl.cpp css_valueimpl.cpp
+ css_base.cpp cssparser.cpp cssstyleselector.cpp
+ csshelper.cpp parser.cpp css_renderstyledeclarationimpl.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
+
diff --git a/tdehtml/css/Makefile.am b/tdehtml/css/Makefile.am
new file mode 100644
index 000000000..6c43675ed
--- /dev/null
+++ b/tdehtml/css/Makefile.am
@@ -0,0 +1,60 @@
+# 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)
+
+YACC=bison
+
+noinst_LTLIBRARIES = libtdehtmlcss.la
+libtdehtmlcss_la_SOURCES = \
+ css_stylesheetimpl.cpp css_ruleimpl.cpp css_valueimpl.cpp css_base.cpp \
+ cssparser.cpp cssstyleselector.cpp csshelper.cpp parser.cpp \
+ css_renderstyledeclarationimpl.cpp
+
+#libtdehtmlcss_la_LDFLAGS = -no-undefined
+libtdehtmlcss_la_METASOURCES = AUTO
+
+noinst_HEADERS = \
+ css_extensionsimpl.h css_stylesheetimpl.h cssparser.h \
+ css_ruleimpl.h css_valueimpl.h css_base.h \
+ cssstyleselector.h csshelper.h parser.h \
+ css_renderstyledeclarationimpl.h
+
+INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/kio -I$(top_srcdir)/dcop \
+ -I$(top_srcdir)/tdehtml -I$(top_srcdir)/libltdl -I$(top_srcdir) \
+ -I$(top_srcdir)/tdewallet/client -I$(top_srcdir)/tdeutils \
+ $(all_includes)
+
+cssdir = $(kde_datadir)/tdehtml/css
+css_DATA = html4.css quirks.css
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+EXTRA_DIST = parser.y
+
+parser: $(srcdir)/parser.y
+ cd $(srcdir); \
+ $(YACC) -v -d -p cssyy parser.y && mv parser.tab.c parser.cpp; \
+ if test -f parser.tab.h; then \
+ if cmp -s parser.tab.h parser.h; then rm -f parser.tab.h; \
+ else mv parser.tab.h parser.h; fi \
+ else :; fi
+
+.PHONY: parser
+
diff --git a/tdehtml/css/css_base.cpp b/tdehtml/css/css_base.cpp
new file mode 100644
index 000000000..a4dda95a0
--- /dev/null
+++ b/tdehtml/css/css_base.cpp
@@ -0,0 +1,419 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * 1999 Waldo Bastian (bastian@kde.org)
+ * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
+ * 2001-2003 Dirk Mueller (mueller@kde.org)
+ * 2002 Apple Computer, Inc.
+ * 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 CSS_DEBUG
+
+#include <assert.h>
+#include <kdebug.h>
+
+#include "css_base.h"
+
+#ifdef CSS_DEBUG
+#include "cssproperties.h"
+#endif
+
+#include "css_stylesheetimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmlhashes.h"
+#include "css_valueimpl.h"
+using namespace DOM;
+
+void StyleBaseImpl::checkLoaded() const
+{
+ if(m_parent) m_parent->checkLoaded();
+}
+
+StyleSheetImpl* StyleBaseImpl::stylesheet()
+{
+ StyleBaseImpl* b = this;
+ while(b && !b->isStyleSheet())
+ b = b->m_parent;
+ return static_cast<StyleSheetImpl *>(b);
+}
+
+KURL StyleBaseImpl::baseURL()
+{
+ // try to find the style sheet. If found look for its url.
+ // If it has none, look for the parentsheet, or the parentNode and
+ // try to find out about their url
+
+ StyleSheetImpl *sheet = stylesheet();
+
+ if(!sheet) return KURL();
+
+ if(!sheet->href().isNull())
+ return KURL( sheet->href().string() );
+
+ // find parent
+ if(sheet->parent()) return sheet->parent()->baseURL();
+
+ if(!sheet->ownerNode()) return KURL();
+
+ return sheet->ownerNode()->getDocument()->baseURL();
+}
+
+void StyleBaseImpl::setParsedValue(int propId, const CSSValueImpl *parsedValue,
+ bool important, bool nonCSSHint, TQPtrList<CSSProperty> *propList)
+{
+ TQPtrListIterator<CSSProperty> propIt(*propList);
+ propIt.toLast(); // just remove the top one - not sure what should happen if we have multiple instances of the property
+ while (propIt.current() &&
+ ( propIt.current()->m_id != propId || propIt.current()->nonCSSHint != nonCSSHint ||
+ propIt.current()->m_important != important) )
+ --propIt;
+ if (propIt.current())
+ propList->removeRef(propIt.current());
+
+ CSSProperty *prop = new CSSProperty();
+ prop->m_id = propId;
+ prop->setValue((CSSValueImpl *) parsedValue);
+ prop->m_important = important;
+ prop->nonCSSHint = nonCSSHint;
+
+ propList->append(prop);
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "added property: " << getPropertyName(propId).string()
+ // non implemented yet << ", value: " << parsedValue->cssText().string()
+ << " important: " << prop->m_important
+ << " nonCSS: " << prop->nonCSSHint << endl;
+#endif
+}
+
+// ------------------------------------------------------------------------------
+
+StyleListImpl::~StyleListImpl()
+{
+ StyleBaseImpl *n;
+
+ if(!m_lstChildren) return;
+
+ for( n = m_lstChildren->first(); n != 0; n = m_lstChildren->next() )
+ {
+ n->setParent(0);
+ if( !n->refCount() ) delete n;
+ }
+ delete m_lstChildren;
+}
+
+// --------------------------------------------------------------------------------
+
+void CSSSelector::print(void)
+{
+ kdDebug( 6080 ) << "[Selector: tag = " << TQString::number(tag,16) << ", attr = \"" << attr << "\", match = \"" << match
+ << "\" value = \"" << value.string().latin1() << "\" relation = " << (int)relation
+ << "]" << endl;
+ if ( tagHistory )
+ tagHistory->print();
+ kdDebug( 6080 ) << " specificity = " << specificity() << endl;
+}
+
+unsigned int CSSSelector::specificity() const
+{
+ if ( nonCSSHint )
+ return 0;
+
+ int s = ((localNamePart(tag) == anyLocalName) ? 0 : 1);
+ switch(match)
+ {
+ case Id:
+ s += 0x10000;
+ break;
+ case Exact:
+ case Set:
+ case List:
+ case Class:
+ case Hyphen:
+ case PseudoClass:
+ case PseudoElement:
+ case Contain:
+ case Begin:
+ case End:
+ s += 0x100;
+ case None:
+ break;
+ }
+ if(tagHistory)
+ s += tagHistory->specificity();
+ // make sure it doesn't overflow
+ return s & 0xffffff;
+}
+
+void CSSSelector::extractPseudoType() const
+{
+ if (match != PseudoClass && match != PseudoElement)
+ return;
+ _pseudoType = PseudoOther;
+ bool element = false;
+ bool compat = false;
+ if (!value.isEmpty()) {
+ value = value.lower();
+ switch (value[0]) {
+ case '-':
+ if (value == "-tdehtml-replaced")
+ _pseudoType = PseudoReplaced;
+ else
+ if (value == "-tdehtml-marker")
+ _pseudoType = PseudoMarker;
+ element = true;
+ break;
+ case 'a':
+ if (value == "active")
+ _pseudoType = PseudoActive;
+ else if (value == "after") {
+ _pseudoType = PseudoAfter;
+ element = compat = true;
+ }
+ break;
+ case 'b':
+ if (value == "before") {
+ _pseudoType = PseudoBefore;
+ element = compat = true;
+ }
+ break;
+ case 'c':
+ if (value == "checked")
+ _pseudoType = PseudoChecked;
+ else if (value == "contains(")
+ _pseudoType = PseudoContains;
+ break;
+ case 'd':
+ if (value == "disabled")
+ _pseudoType = PseudoDisabled;
+ break;
+ case 'e':
+ if (value == "empty")
+ _pseudoType = PseudoEmpty;
+ else if (value == "enabled")
+ _pseudoType = PseudoEnabled;
+ break;
+ case 'f':
+ if (value == "first-child")
+ _pseudoType = PseudoFirstChild;
+ else if (value == "first-letter") {
+ _pseudoType = PseudoFirstLetter;
+ element = compat = true;
+ }
+ else if (value == "first-line") {
+ _pseudoType = PseudoFirstLine;
+ element = compat = true;
+ }
+ else if (value == "first-of-type")
+ _pseudoType = PseudoFirstOfType;
+ else if (value == "focus")
+ _pseudoType = PseudoFocus;
+ break;
+ case 'h':
+ if (value == "hover")
+ _pseudoType = PseudoHover;
+ break;
+ case 'i':
+ if (value == "indeterminate")
+ _pseudoType = PseudoIndeterminate;
+ break;
+ case 'l':
+ if (value == "link")
+ _pseudoType = PseudoLink;
+ else if (value == "lang(")
+ _pseudoType = PseudoLang;
+ else if (value == "last-child")
+ _pseudoType = PseudoLastChild;
+ else if (value == "last-of-type")
+ _pseudoType = PseudoLastOfType;
+ break;
+ case 'n':
+ if (value == "not(")
+ _pseudoType = PseudoNot;
+ else if (value == "nth-child(")
+ _pseudoType = PseudoNthChild;
+ else if (value == "nth-last-child(")
+ _pseudoType = PseudoNthLastChild;
+ else if (value == "nth-of-type(")
+ _pseudoType = PseudoNthOfType;
+ else if (value == "nth-last-of-type(")
+ _pseudoType = PseudoNthLastOfType;
+ break;
+ case 'o':
+ if (value == "only-child")
+ _pseudoType = PseudoOnlyChild;
+ else if (value == "only-of-type")
+ _pseudoType = PseudoOnlyOfType;
+ break;
+ case 'r':
+ if (value == "root")
+ _pseudoType = PseudoRoot;
+ break;
+ case 's':
+ if (value == "selection") {
+ _pseudoType = PseudoSelection;
+ element = true;
+ }
+ break;
+ case 't':
+ if (value == "target")
+ _pseudoType = PseudoTarget;
+ break;
+ case 'v':
+ if (value == "visited")
+ _pseudoType = PseudoVisited;
+ break;
+ }
+ }
+ if (match == PseudoClass && element)
+ if (!compat) _pseudoType = PseudoOther;
+ else match = PseudoElement;
+ else
+ if (match == PseudoElement && !element)
+ _pseudoType = PseudoOther;
+}
+
+
+bool CSSSelector::operator == ( const CSSSelector &other ) const
+{
+ const CSSSelector *sel1 = this;
+ const CSSSelector *sel2 = &other;
+
+ while ( sel1 && sel2 ) {
+ //assert(sel1->_pseudoType != PseudoNotParsed);
+ //assert(sel2->_pseudoType != PseudoNotParsed);
+ if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
+ sel1->relation != sel2->relation || sel1->match != sel2->match ||
+ sel1->nonCSSHint != sel2->nonCSSHint ||
+ sel1->value != sel2->value ||
+ sel1->pseudoType() != sel2->pseudoType() ||
+ sel1->string_arg != sel2->string_arg)
+ return false;
+ sel1 = sel1->tagHistory;
+ sel2 = sel2->tagHistory;
+ }
+ if ( sel1 || sel2 )
+ return false;
+ return true;
+}
+
+DOMString CSSSelector::selectorText() const
+{
+ // FIXME: Support namespaces when dumping the selector text. This requires preserving
+ // the original namespace prefix used. Ugh. -dwh
+ DOMString str;
+ const CSSSelector* cs = this;
+ TQ_UINT16 tag = localNamePart(cs->tag);
+ if (tag == anyLocalName && cs->match == CSSSelector::None)
+ str = "*";
+ else if (tag != anyLocalName)
+ str = getTagName( cs->tag );
+
+ const CSSSelector* op = 0;
+ while (true) {
+ if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Id )
+ {
+ str += "#";
+ str += cs->value;
+ }
+ else if ( cs->match == CSSSelector::Class )
+ {
+ str += ".";
+ str += cs->value;
+ }
+ else if ( cs->match == CSSSelector::PseudoClass )
+ {
+ str += ":";
+ str += cs->value;
+ if (!cs->string_arg.isEmpty()) { // e.g :nth-child(...)
+ str += cs->string_arg;
+ str += ")";
+ } else if (cs->simpleSelector && !op) { // :not(...)
+ op = cs;
+ cs = cs->simpleSelector;
+ continue;
+ }
+ }
+ else if ( cs->match == CSSSelector::PseudoElement )
+ {
+ str += "::";
+ str += cs->value;
+ }
+ // optional attribute
+ else if ( cs->attr ) {
+ DOMString attrName = getAttrName( cs->attr );
+ str += "[";
+ str += attrName;
+ switch (cs->match) {
+ case CSSSelector::Exact:
+ str += "=";
+ break;
+ case CSSSelector::Set:
+ break;
+ case CSSSelector::List:
+ str += "~=";
+ break;
+ case CSSSelector::Hyphen:
+ str += "|=";
+ break;
+ case CSSSelector::Begin:
+ str += "^=";
+ break;
+ case CSSSelector::End:
+ str += "$=";
+ break;
+ case CSSSelector::Contain:
+ str += "*=";
+ break;
+ default:
+ kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl;
+ }
+ if (cs->match != CSSSelector::Set) {
+ str += "\"";
+ str += cs->value;
+ str += "\"";
+ }
+ str += "]";
+ }
+ if (op && !cs->tagHistory) {
+ cs=op;
+ op=0;
+ str += ")";
+ }
+
+ if ((cs->relation != CSSSelector::SubSelector && !op) || !cs->tagHistory)
+ break;
+ cs = cs->tagHistory;
+ }
+
+ if ( cs->tagHistory ) {
+ DOMString tagHistoryText = cs->tagHistory->selectorText();
+ if ( cs->relation == DirectAdjacent )
+ str = tagHistoryText + " + " + str;
+ else if ( cs->relation == IndirectAdjacent )
+ str = tagHistoryText + " ~ " + str;
+ else if ( cs->relation == Child )
+ str = tagHistoryText + " > " + str;
+ else // Descendant
+ str = tagHistoryText + " " + str;
+ }
+ return str;
+}
+
+// ----------------------------------------------------------------------------
diff --git a/tdehtml/css/css_base.h b/tdehtml/css/css_base.h
new file mode 100644
index 000000000..d2ab4f63f
--- /dev/null
+++ b/tdehtml/css/css_base.h
@@ -0,0 +1,271 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * 1999 Waldo Bastian (bastian@kde.org)
+ * 2002 Apple Computer, Inc.
+ * 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.
+ *
+ */
+#ifndef _CSS_BASE_H
+#define _CSS_BASE_H
+
+#include "dom/dom_string.h"
+#include "dom/dom_misc.h"
+#include "xml/dom_nodeimpl.h"
+#include "misc/shared.h"
+#include <kdemacros.h>
+#include <tqdatetime.h>
+#include <tqptrlist.h>
+
+namespace DOM {
+
+ class StyleSheetImpl;
+ class MediaList;
+
+ class CSSSelector;
+ class CSSProperty;
+ class CSSValueImpl;
+ class CSSPrimitiveValueImpl;
+ class CSSStyleDeclarationImpl;
+ class CSSRuleImpl;
+ class CSSStyleRuleImpl;
+
+ class DocumentImpl;
+
+ struct CSSNamespace {
+ DOMString m_prefix;
+ DOMString m_uri;
+ CSSNamespace* m_parent;
+
+ CSSNamespace(const DOMString& p, const DOMString& u, CSSNamespace* parent)
+ :m_prefix(p), m_uri(u), m_parent(parent) {}
+ ~CSSNamespace() { delete m_parent; }
+
+ const DOMString& uri() { return m_uri; }
+ const DOMString& prefix() { return m_prefix; }
+
+ CSSNamespace* namespaceForPrefix(const DOMString& prefix) {
+ if (prefix == m_prefix)
+ return this;
+ if (m_parent)
+ return m_parent->namespaceForPrefix(prefix);
+ return 0;
+ }
+ };
+
+// this class represents a selector for a StyleRule
+ class CSSSelector
+ {
+ public:
+ CSSSelector()
+ : tagHistory(0), simpleSelector(0), attr(0), tag(anyQName), relation( Descendant ),
+ match( None ), nonCSSHint( false ), pseudoId( 0 ), _pseudoType(PseudoNotParsed)
+ {}
+
+ ~CSSSelector() {
+ delete tagHistory;
+ delete simpleSelector;
+ }
+
+ /**
+ * Print debug output for this selector
+ */
+ void print();
+
+ /**
+ * Re-create selector text from selector's data
+ */
+ DOMString selectorText() const;
+
+ // checks if the 2 selectors (including sub selectors) agree.
+ bool operator == ( const CSSSelector &other ) const;
+
+ // tag == -1 means apply to all elements (Selector = *)
+
+ unsigned int specificity() const;
+
+ /* how the attribute value has to match.... Default is Exact */
+ enum Match
+ {
+ None = 0,
+ Id,
+ Exact,
+ Set,
+ Class,
+ List,
+ Hyphen,
+ PseudoClass,
+ PseudoElement,
+ Contain, // css3: E[foo*="bar"]
+ Begin, // css3: E[foo^="bar"]
+ End // css3: E[foo$="bar"]
+ };
+
+ enum Relation
+ {
+ Descendant = 0,
+ Child,
+ DirectAdjacent,
+ IndirectAdjacent,
+ SubSelector
+ };
+
+ enum PseudoType
+ {
+ PseudoNotParsed = 0,
+ PseudoOther,
+ PseudoEmpty,
+ PseudoFirstChild,
+ PseudoLastChild,
+ PseudoNthChild,
+ PseudoNthLastChild,
+ PseudoOnlyChild,
+ PseudoFirstOfType,
+ PseudoLastOfType,
+ PseudoNthOfType,
+ PseudoNthLastOfType,
+ PseudoOnlyOfType,
+ PseudoLink,
+ PseudoVisited,
+ PseudoHover,
+ PseudoFocus,
+ PseudoActive,
+ PseudoTarget,
+ PseudoLang,
+ PseudoNot,
+ PseudoContains,
+ PseudoRoot,
+ PseudoEnabled,
+ PseudoDisabled,
+ PseudoChecked,
+ PseudoIndeterminate,
+// pseudo-elements:
+ // inherited:
+ PseudoFirstLine,
+ PseudoFirstLetter,
+ PseudoSelection,
+ // generated:
+ PseudoBefore,
+ PseudoAfter,
+ PseudoMarker,
+ PseudoReplaced
+ };
+
+ PseudoType pseudoType() const {
+ if (_pseudoType == PseudoNotParsed)
+ extractPseudoType();
+ return _pseudoType;
+ }
+
+ mutable DOM::DOMString value;
+ CSSSelector *tagHistory;
+ CSSSelector* simpleSelector; // Used by :not
+ DOM::DOMString string_arg; // Used by :contains, :lang and :nth-*
+ DOM::NodeImpl::Id attr;
+ DOM::NodeImpl::Id tag;
+
+ Relation relation : 3;
+ mutable Match match : 4;
+ bool nonCSSHint : 1;
+ unsigned int pseudoId : 4;
+ mutable PseudoType _pseudoType : 6;
+
+ private:
+ void extractPseudoType() const;
+ };
+
+ // a style class which has a parent (almost all have)
+ class StyleBaseImpl : public tdehtml::TreeShared<StyleBaseImpl>
+ {
+ public:
+ StyleBaseImpl() { m_parent = 0; hasInlinedDecl = false; strictParsing = true; multiLength = false; }
+ StyleBaseImpl(StyleBaseImpl *p) {
+ m_parent = p; hasInlinedDecl = false;
+ strictParsing = (m_parent ? m_parent->useStrictParsing() : true);
+ multiLength = false;
+ }
+
+ virtual ~StyleBaseImpl() {}
+
+ // returns the url of the style sheet this object belongs to
+ // not const
+ KURL baseURL();
+
+ virtual bool isStyleSheet() const { return false; }
+ virtual bool isCSSStyleSheet() const { return false; }
+ virtual bool isStyleSheetList() const { return false; }
+ virtual bool isMediaList() const { return false; }
+ virtual bool isRuleList() const { return false; }
+ virtual bool isRule() const { return false; }
+ virtual bool isStyleRule() const { return false; }
+ virtual bool isCharetRule() const { return false; }
+ virtual bool isImportRule() const { return false; }
+ virtual bool isMediaRule() const { return false; }
+ virtual bool isFontFaceRule() const { return false; }
+ virtual bool isPageRule() const { return false; }
+ virtual bool isUnknownRule() const { return false; }
+ virtual bool isStyleDeclaration() const { return false; }
+ virtual bool isValue() const { return false; }
+ virtual bool isPrimitiveValue() const { return false; }
+ virtual bool isValueList() const { return false; }
+ virtual bool isValueCustom() const { return false; }
+
+ void setParent(StyleBaseImpl *parent) { m_parent = parent; }
+
+ static void setParsedValue(int propId, const CSSValueImpl *parsedValue,
+ bool important, bool nonCSSHint, TQPtrList<CSSProperty> *propList);
+
+ virtual bool parseString(const DOMString &/*cssString*/, bool = false) { return false; }
+
+ virtual void checkLoaded() const;
+
+ void setStrictParsing( bool b ) { strictParsing = b; }
+ bool useStrictParsing() const { return strictParsing; }
+
+ // not const
+ StyleSheetImpl* stylesheet();
+
+ protected:
+ bool hasInlinedDecl : 1;
+ bool strictParsing : 1;
+ bool multiLength : 1;
+ };
+
+ // a style class which has a list of children (StyleSheets for example)
+ class StyleListImpl : public StyleBaseImpl
+ {
+ public:
+ StyleListImpl() : StyleBaseImpl() { m_lstChildren = 0; }
+ StyleListImpl(StyleBaseImpl *parent) : StyleBaseImpl(parent) { m_lstChildren = 0; }
+ virtual ~StyleListImpl();
+
+ unsigned long length() const { return m_lstChildren->count(); }
+ StyleBaseImpl *item(unsigned long num) const { return m_lstChildren->at(num); }
+
+ void append(StyleBaseImpl *item) { m_lstChildren->append(item); }
+
+ protected:
+ TQPtrList<StyleBaseImpl> *m_lstChildren;
+ };
+
+ KDE_NO_EXPORT int getPropertyID(const char *tagStr, int len);
+
+}
+
+#endif
diff --git a/tdehtml/css/css_extensionsimpl.cpp b/tdehtml/css/css_extensionsimpl.cpp
new file mode 100644
index 000000000..e0e17e207
--- /dev/null
+++ b/tdehtml/css/css_extensionsimpl.cpp
@@ -0,0 +1,366 @@
+/**
+ * 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 "DOMException.h"
+#include "DOMString.h"
+
+#include "CSS2AzimuthImpl.h"
+using namespace DOM;
+
+CSS2AzimuthImpl::CSS2AzimuthImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2AzimuthImpl::~CSS2AzimuthImpl()
+{
+}
+
+unsigned short CSS2AzimuthImpl::azimuthType() const
+{
+}
+
+DOMString CSS2AzimuthImpl::identifier() const
+{
+}
+
+bool CSS2AzimuthImpl::behind() const
+{
+}
+
+void CSS2AzimuthImpl::setAngleValue( const unsigned short &unitType, const float &floatValue )
+{
+}
+
+float CSS2AzimuthImpl::getAngleValue( const unsigned short &unitType )
+{
+}
+
+void CSS2AzimuthImpl::setIdentifier( const DOMString &identifier, const bool &behind )
+{
+}
+
+
+
+
+
+#include "CSS2BackgroundPositionImpl.h"
+CSS2BackgroundPositionImpl::CSS2BackgroundPositionImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2BackgroundPositionImpl::~CSS2BackgroundPositionImpl()
+{
+}
+
+unsigned short CSS2BackgroundPositionImpl::horizontalType() const
+{
+}
+
+unsigned short CSS2BackgroundPositionImpl::verticalType() const
+{
+}
+
+DOMString CSS2BackgroundPositionImpl::horizontalIdentifier() const
+{
+}
+
+DOMString CSS2BackgroundPositionImpl::verticalIdentifier() const
+{
+}
+
+float CSS2BackgroundPositionImpl::getHorizontalPosition( const float &horizontalType )
+{
+}
+
+float CSS2BackgroundPositionImpl::getVerticalPosition( const float &verticalType )
+{
+}
+
+void CSS2BackgroundPositionImpl::setHorizontalPosition( const unsigned short &horizontalType, const float &value )
+{
+}
+
+void CSS2BackgroundPositionImpl::setVerticalPosition( const unsigned short &verticalType, const float &value )
+{
+}
+
+void CSS2BackgroundPositionImpl::setPositionIdentifier( const DOMString &horizontalIdentifier, const DOMString &verticalIdentifier )
+{
+}
+
+
+
+
+
+#include "CSS2BorderSpacingImpl.h"
+CSS2BorderSpacingImpl::CSS2BorderSpacingImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2BorderSpacingImpl::~CSS2BorderSpacingImpl()
+{
+}
+
+unsigned short CSS2BorderSpacingImpl::horizontalType() const
+{
+}
+
+unsigned short CSS2BorderSpacingImpl::verticalType() const
+{
+}
+
+float CSS2BorderSpacingImpl::getHorizontalSpacing( const float &horizontalType )
+{
+}
+
+float CSS2BorderSpacingImpl::getVerticalSpacing( const float &verticalType )
+{
+}
+
+void CSS2BorderSpacingImpl::setHorizontalSpacing( const unsigned short &horizontalType, const float &value )
+{
+}
+
+void CSS2BorderSpacingImpl::setVerticalSpacing( const unsigned short &verticalType, const float &value )
+{
+}
+
+void CSS2BorderSpacingImpl::setInherit()
+{
+}
+
+
+
+
+
+#include "CSS2CounterIncrementImpl.h"
+CSS2CounterIncrementImpl::CSS2CounterIncrementImpl(DocumentImpl *doc)
+{
+}
+
+CSS2CounterIncrementImpl::~CSS2CounterIncrementImpl()
+{
+}
+
+short CSS2CounterIncrementImpl::increment() const
+{
+}
+
+void CSS2CounterIncrementImpl::setIncrement( const short & )
+{
+}
+
+
+
+
+
+#include "CSS2CounterResetImpl.h"
+CSS2CounterResetImpl::CSS2CounterResetImpl(DocumentImpl *doc)
+{
+}
+
+CSS2CounterResetImpl::~CSS2CounterResetImpl()
+{
+}
+
+short CSS2CounterResetImpl::reset() const
+{
+}
+
+void CSS2CounterResetImpl::setReset( const short & )
+{
+}
+
+
+
+
+#include "CSSValueList.h"
+#include "CSS2CursorImpl.h"
+CSS2CursorImpl::CSS2CursorImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2CursorImpl::~CSS2CursorImpl()
+{
+}
+
+unsigned short CSS2CursorImpl::cursorType() const
+{
+}
+
+void CSS2CursorImpl::setCursorType( const unsigned short & )
+{
+}
+
+CSSValueList CSS2CursorImpl::uris() const
+{
+}
+
+#include "CSS2FontFaceSrcImpl.h"
+CSS2FontFaceSrcImpl::CSS2FontFaceSrcImpl(DocumentImpl *doc)
+{
+}
+
+CSS2FontFaceSrcImpl::~CSS2FontFaceSrcImpl()
+{
+}
+
+CSSValueList CSS2FontFaceSrcImpl::format() const
+{
+}
+
+
+
+
+#include "CSS2FontFaceWidthsImpl.h"
+CSS2FontFaceWidthsImpl::CSS2FontFaceWidthsImpl(DocumentImpl *doc)
+{
+}
+
+CSS2FontFaceWidthsImpl::~CSS2FontFaceWidthsImpl()
+{
+}
+
+CSSValueList CSS2FontFaceWidthsImpl::numbers() const
+{
+}
+
+
+
+
+#include "CSS2PageSizeImpl.h"
+CSS2PageSizeImpl::CSS2PageSizeImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2PageSizeImpl::~CSS2PageSizeImpl()
+{
+}
+
+unsigned short CSS2PageSizeImpl::widthType() const
+{
+}
+
+unsigned short CSS2PageSizeImpl::heightType() const
+{
+}
+
+DOMString CSS2PageSizeImpl::identifier() const
+{
+}
+
+float CSS2PageSizeImpl::getWidth( const float &widthType )
+{
+}
+
+float CSS2PageSizeImpl::getHeightSize( const float &heightType )
+{
+}
+
+void CSS2PageSizeImpl::setWidthSize( const unsigned short &widthType, const float &value )
+{
+}
+
+void CSS2PageSizeImpl::setHeightSize( const unsigned short &heightType, const float &value )
+{
+}
+
+void CSS2PageSizeImpl::setIdentifier( const DOMString &identifier )
+{
+}
+
+
+
+
+#include "CSS2PlayDuringImpl.h"
+CSS2PlayDuringImpl::CSS2PlayDuringImpl(DocumentImpl *doc) : CSSValueImpl(doc)
+{
+}
+
+CSS2PlayDuringImpl::~CSS2PlayDuringImpl()
+{
+}
+
+unsigned short CSS2PlayDuringImpl::playDuringType() const
+{
+}
+
+bool CSS2PlayDuringImpl::mix() const
+{
+}
+
+void CSS2PlayDuringImpl::setMix( const bool & )
+{
+}
+
+bool CSS2PlayDuringImpl::repeat() const
+{
+}
+
+void CSS2PlayDuringImpl::setRepeat( const bool & )
+{
+}
+
+
+
+
+
+#include "CSS2PropertiesImpl.h"
+CSS2PropertiesImpl::CSS2PropertiesImpl(DocumentImpl *doc)
+{
+}
+
+CSS2PropertiesImpl::~CSS2PropertiesImpl()
+{
+}
+
+
+
+
+#include "CSSValue.h"
+
+#include "CSS2TextShadowImpl.h"
+CSS2TextShadowImpl::CSS2TextShadowImpl(DocumentImpl *doc)
+{
+}
+
+CSS2TextShadowImpl::~CSS2TextShadowImpl()
+{
+}
+
+CSSValue CSS2TextShadowImpl::color() const
+{
+}
+
+CSSValue CSS2TextShadowImpl::horizontal() const
+{
+}
+
+CSSValue CSS2TextShadowImpl::vertical() const
+{
+}
+
+CSSValue CSS2TextShadowImpl::blur() const
+{
+}
+
+
+
diff --git a/tdehtml/css/css_extensionsimpl.h b/tdehtml/css/css_extensionsimpl.h
new file mode 100644
index 000000000..dba74e217
--- /dev/null
+++ b/tdehtml/css/css_extensionsimpl.h
@@ -0,0 +1,205 @@
+/*
+ * 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 _CSS_css_extensionsimpl_h_
+#define _CSS_css_extensionsimpl_h_
+
+#include "css_valueimpl.h"
+#include "dom_string.h"
+
+namespace DOM {
+
+class CSS2AzimuthImpl : public CSSValueImpl
+{
+public:
+ CSS2AzimuthImpl(DocumentImpl *doc);
+
+ ~CSS2AzimuthImpl();
+
+ unsigned short azimuthType() const;
+ DOM::DOMString identifier() const;
+ bool behind() const;
+ void setAngleValue ( const unsigned short &unitType, const float &floatValue );
+ float getAngleValue ( const unsigned short &unitType );
+ void setIdentifier ( const DOM::DOMString &identifier, const bool &behind );
+};
+
+
+class DOM::DOMString;
+
+class CSS2BackgroundPositionImpl : public CSSValueImpl
+{
+public:
+ CSS2BackgroundPositionImpl(DocumentImpl *doc);
+
+ ~CSS2BackgroundPositionImpl();
+
+ unsigned short horizontalType() const;
+ unsigned short verticalType() const;
+ DOM::DOMString horizontalIdentifier() const;
+ DOM::DOMString verticalIdentifier() const;
+ float getHorizontalPosition ( const float &horizontalType );
+ float getVerticalPosition ( const float &verticalType );
+ void setHorizontalPosition ( const unsigned short &horizontalType, const float &value );
+ void setVerticalPosition ( const unsigned short &verticalType, const float &value );
+ void setPositionIdentifier ( const DOM::DOMString &horizontalIdentifier, const DOM::DOMString &verticalIdentifier );
+};
+
+
+
+class CSS2BorderSpacingImpl : public CSSValueImpl
+{
+public:
+ CSS2BorderSpacingImpl(DocumentImpl *doc);
+
+ ~CSS2BorderSpacingImpl();
+
+ unsigned short horizontalType() const;
+ unsigned short verticalType() const;
+ float getHorizontalSpacing ( const float &horizontalType );
+ float getVerticalSpacing ( const float &verticalType );
+ void setHorizontalSpacing ( const unsigned short &horizontalType, const float &value );
+ void setVerticalSpacing ( const unsigned short &verticalType, const float &value );
+ void setInherit();
+};
+
+
+class CSS2CounterIncrementImpl
+{
+public:
+ CSS2CounterIncrementImpl(DocumentImpl *doc);
+
+ ~CSS2CounterIncrementImpl();
+
+ short increment() const;
+ void setIncrement( const short & );
+};
+
+
+class CSS2CounterResetImpl
+{
+public:
+ CSS2CounterResetImpl(DocumentImpl *doc);
+
+ ~CSS2CounterResetImpl();
+
+ short reset() const;
+ void setReset( const short & );
+};
+
+
+class CSS2CursorImpl : public CSSValueImpl
+{
+public:
+ CSS2CursorImpl(DocumentImpl *doc);
+
+ ~CSS2CursorImpl();
+
+ unsigned short cursorType() const;
+ void setCursorType( const unsigned short & );
+
+ CSSValueList uris() const;
+};
+
+
+class CSS2FontFaceSrcImpl
+{
+public:
+ CSS2FontFaceSrcImpl(DocumentImpl *doc);
+
+ ~CSS2FontFaceSrcImpl();
+
+ CSSValueList format() const;
+};
+
+
+class CSS2FontFaceWidthsImpl
+{
+public:
+ CSS2FontFaceWidthsImpl(DocumentImpl *doc);
+
+ ~CSS2FontFaceWidthsImpl();
+
+ CSSValueList numbers() const;
+};
+
+
+class CSS2PageSizeImpl : public CSSValueImpl
+{
+public:
+ CSS2PageSizeImpl(DocumentImpl *doc);
+
+ ~CSS2PageSizeImpl();
+
+ unsigned short widthType() const;
+ unsigned short heightType() const;
+ DOM::DOMString identifier() const;
+ float getWidth ( const float &widthType );
+ float getHeightSize ( const float &heightType );
+ void setWidthSize ( const unsigned short &widthType, const float &value );
+ void setHeightSize ( const unsigned short &heightType, const float &value );
+ void setIdentifier ( const DOM::DOMString &identifier );
+};
+
+
+class CSS2PlayDuringImpl : public CSSValueImpl
+{
+public:
+ CSS2PlayDuringImpl(DocumentImpl *doc);
+
+ ~CSS2PlayDuringImpl();
+
+ unsigned short playDuringType() const;
+ bool mix() const;
+
+ void setMix( const bool & );
+ bool repeat() const;
+
+ void setRepeat( const bool & );
+};
+
+
+class CSS2PropertiesImpl
+{
+public:
+ CSS2PropertiesImpl(DocumentImpl *doc);
+
+ ~CSS2PropertiesImpl();
+};
+
+
+class CSS2TextShadowImpl
+{
+public:
+ CSS2TextShadowImpl(DocumentImpl *doc);
+
+ ~CSS2TextShadowImpl();
+
+ CSSValue color() const;
+ CSSValue horizontal() const;
+ CSSValue vertical() const;
+ CSSValue blur() const;
+};
+
+
+}; // namespace
+
+#endif
diff --git a/tdehtml/css/css_renderstyledeclarationimpl.cpp b/tdehtml/css/css_renderstyledeclarationimpl.cpp
new file mode 100644
index 000000000..95c1c95d9
--- /dev/null
+++ b/tdehtml/css/css_renderstyledeclarationimpl.cpp
@@ -0,0 +1,1147 @@
+/**
+ * css_renderstyledeclarationimpl.cpp
+ *
+ * Copyright (C) 2004 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2004,2005 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include "css_renderstyledeclarationimpl.h"
+
+#include "rendering/render_style.h"
+#include "rendering/render_object.h"
+
+#include "cssproperties.h"
+#include "cssvalues.h"
+
+using namespace DOM;
+using namespace tdehtml;
+
+// List of all properties we know how to compute, omitting shorthands.
+static const int computedProperties[] = {
+ CSS_PROP_BACKGROUND_COLOR,
+ CSS_PROP_BACKGROUND_IMAGE,
+ CSS_PROP_BACKGROUND_REPEAT,
+ CSS_PROP_BACKGROUND_ATTACHMENT,
+ CSS_PROP_BACKGROUND_POSITION,
+ CSS_PROP_BACKGROUND_POSITION_X,
+ CSS_PROP_BACKGROUND_POSITION_Y,
+ CSS_PROP_BORDER_COLLAPSE,
+ CSS_PROP_BORDER_SPACING,
+ CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING,
+ CSS_PROP__KHTML_BORDER_VERTICAL_SPACING,
+ CSS_PROP_BORDER_TOP_COLOR,
+ CSS_PROP_BORDER_RIGHT_COLOR,
+ CSS_PROP_BORDER_BOTTOM_COLOR,
+ CSS_PROP_BORDER_LEFT_COLOR,
+ CSS_PROP_BORDER_TOP_STYLE,
+ CSS_PROP_BORDER_RIGHT_STYLE,
+ CSS_PROP_BORDER_BOTTOM_STYLE,
+ CSS_PROP_BORDER_LEFT_STYLE,
+ CSS_PROP_BORDER_TOP_WIDTH,
+ CSS_PROP_BORDER_RIGHT_WIDTH,
+ CSS_PROP_BORDER_BOTTOM_WIDTH,
+ CSS_PROP_BORDER_LEFT_WIDTH,
+ CSS_PROP_BOTTOM,
+ CSS_PROP_CAPTION_SIDE,
+ CSS_PROP_CLEAR,
+ CSS_PROP_COLOR,
+ CSS_PROP_CURSOR,
+ CSS_PROP_DIRECTION,
+ CSS_PROP_DISPLAY,
+ CSS_PROP_EMPTY_CELLS,
+ CSS_PROP_FLOAT,
+ CSS_PROP_FONT_FAMILY,
+ CSS_PROP_FONT_SIZE,
+ CSS_PROP_FONT_STYLE,
+ CSS_PROP_FONT_VARIANT,
+ CSS_PROP_FONT_WEIGHT,
+ CSS_PROP_HEIGHT,
+ CSS_PROP_LEFT,
+ CSS_PROP_LETTER_SPACING,
+ CSS_PROP_LINE_HEIGHT,
+ CSS_PROP_LIST_STYLE_IMAGE,
+ CSS_PROP_LIST_STYLE_POSITION,
+ CSS_PROP_LIST_STYLE_TYPE,
+ CSS_PROP_MARGIN_TOP,
+ CSS_PROP_MARGIN_RIGHT,
+ CSS_PROP_MARGIN_BOTTOM,
+ CSS_PROP_MARGIN_LEFT,
+ CSS_PROP__KHTML_MARQUEE_DIRECTION,
+ CSS_PROP__KHTML_MARQUEE_INCREMENT,
+ CSS_PROP__KHTML_MARQUEE_REPETITION,
+ CSS_PROP__KHTML_MARQUEE_STYLE,
+ CSS_PROP_MAX_HEIGHT,
+ CSS_PROP_MAX_WIDTH,
+ CSS_PROP_MIN_HEIGHT,
+ CSS_PROP_MIN_WIDTH,
+ CSS_PROP_OPACITY,
+ CSS_PROP_ORPHANS,
+ CSS_PROP_OUTLINE_STYLE,
+ CSS_PROP_OVERFLOW,
+ CSS_PROP_OVERFLOW_X,
+ CSS_PROP_OVERFLOW_Y,
+ CSS_PROP_PADDING_TOP,
+ CSS_PROP_PADDING_RIGHT,
+ CSS_PROP_PADDING_BOTTOM,
+ CSS_PROP_PADDING_LEFT,
+ CSS_PROP_PAGE_BREAK_AFTER,
+ CSS_PROP_PAGE_BREAK_BEFORE,
+ CSS_PROP_PAGE_BREAK_INSIDE,
+ CSS_PROP_POSITION,
+ CSS_PROP_RIGHT,
+ CSS_PROP_TABLE_LAYOUT,
+ CSS_PROP_TEXT_ALIGN,
+ CSS_PROP_TEXT_DECORATION,
+ CSS_PROP_TEXT_INDENT,
+ CSS_PROP_TEXT_SHADOW,
+ CSS_PROP_TEXT_TRANSFORM,
+ CSS_PROP_TOP,
+ CSS_PROP_UNICODE_BIDI,
+ CSS_PROP_VERTICAL_ALIGN,
+ CSS_PROP_VISIBILITY,
+ CSS_PROP_WHITE_SPACE,
+ CSS_PROP_WIDOWS,
+ CSS_PROP_WIDTH,
+ CSS_PROP_WORD_SPACING,
+ CSS_PROP_Z_INDEX,
+};
+
+const unsigned numComputedProperties = sizeof(computedProperties) / sizeof(computedProperties[0]);
+
+
+static CSSValueImpl *valueForLength(const Length &length, int max)
+{
+ if (length.isPercent()) {
+ return new CSSPrimitiveValueImpl(length.value(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ else {
+ return new CSSPrimitiveValueImpl(length.minWidth(max), CSSPrimitiveValue::CSS_PX);
+ }
+}
+
+static CSSValueImpl *valueForBorderStyle(EBorderStyle style)
+{
+ switch (style) {
+ case tdehtml::BNATIVE:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_NATIVE);
+ case tdehtml::BNONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case tdehtml::BHIDDEN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN);
+ case tdehtml::INSET:
+ return new CSSPrimitiveValueImpl(CSS_VAL_INSET);
+ case tdehtml::GROOVE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_GROOVE);
+ case tdehtml::RIDGE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIDGE);
+ case tdehtml::OUTSET:
+ return new CSSPrimitiveValueImpl(CSS_VAL_OUTSET);
+ case tdehtml::DOTTED:
+ return new CSSPrimitiveValueImpl(CSS_VAL_DOTTED);
+ case tdehtml::DASHED:
+ return new CSSPrimitiveValueImpl(CSS_VAL_DASHED);
+ case tdehtml::SOLID:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SOLID);
+ case tdehtml::DOUBLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_DOUBLE);
+ }
+ Q_ASSERT( 0 );
+ return 0;
+}
+
+static CSSValueImpl *valueForTextAlign(ETextAlign align)
+{
+ switch (align) {
+ case tdehtml::TAAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case tdehtml::LEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case tdehtml::RIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ case tdehtml::CENTER:
+ return new CSSPrimitiveValueImpl(CSS_VAL_CENTER);
+ case tdehtml::JUSTIFY:
+ return new CSSPrimitiveValueImpl(CSS_VAL_JUSTIFY);
+ case tdehtml::KHTML_LEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_LEFT);
+ case tdehtml::KHTML_RIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_RIGHT);
+ case tdehtml::KHTML_CENTER:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_CENTER);
+ }
+ Q_ASSERT( 0 );
+ return 0;
+}
+
+DOMString tdehtml::stringForListStyleType(EListStyleType type)
+{
+ switch (type) {
+ case tdehtml::LDISC:
+ return "disc";
+ case tdehtml::LCIRCLE:
+ return "circle";
+ case tdehtml::LSQUARE:
+ return "square";
+ case tdehtml::LBOX:
+ return "box";
+ case tdehtml::LDIAMOND:
+ return "-tdehtml-diamond";
+ case tdehtml::LDECIMAL:
+ return "decimal";
+ case tdehtml::DECIMAL_LEADING_ZERO:
+ return "decimal-leading-zero";
+ case tdehtml::ARABIC_INDIC:
+ return "-tdehtml-arabic-indic";
+ case tdehtml::LAO:
+ return "-tdehtml-lao";
+ case tdehtml::PERSIAN:
+ return "-tdehtml-persian";
+ case tdehtml::URDU:
+ return "-tdehtml-urdu";
+ case tdehtml::THAI:
+ return "-tdehtml-thai";
+ case tdehtml::TIBETAN:
+ return "-tdehtml-tibetan";
+ case tdehtml::LOWER_ROMAN:
+ return "lower-roman";
+ case tdehtml::UPPER_ROMAN:
+ return "upper-roman";
+ case tdehtml::HEBREW:
+ return "hebrew";
+ case tdehtml::ARMENIAN:
+ return "armenian";
+ case tdehtml::GEORGIAN:
+ return "georgian";
+ case tdehtml::CJK_IDEOGRAPHIC:
+ return "cjk-ideographic";
+ case tdehtml::JAPANESE_FORMAL:
+ return "-tdehtml-japanese-formal";
+ case tdehtml::JAPANESE_INFORMAL:
+ return "-tdehtml-japanese-informal";
+ case tdehtml::SIMP_CHINESE_FORMAL:
+ return "-tdehtml-simp-chinese-formal";
+ case tdehtml::SIMP_CHINESE_INFORMAL:
+ return "-tdehtml-simp-chinese-informal";
+ case tdehtml::TRAD_CHINESE_FORMAL:
+ return "-tdehtml-trad-chinese-formal";
+ case tdehtml::TRAD_CHINESE_INFORMAL:
+ return "-tdehtml-trad-chinese-informal";
+ case tdehtml::LOWER_GREEK:
+ return "lower-greek";
+ case tdehtml::UPPER_GREEK:
+ return "-tdehtml-upper-greek";
+ case tdehtml::LOWER_ALPHA:
+ return "lower-alpha";
+ case tdehtml::UPPER_ALPHA:
+ return "upper-alpha";
+ case tdehtml::LOWER_LATIN:
+ return "lower-latin";
+ case tdehtml::UPPER_LATIN:
+ return "upper-latin";
+ case tdehtml::HIRAGANA:
+ return "hiragana";
+ case tdehtml::KATAKANA:
+ return "katakana";
+ case tdehtml::HIRAGANA_IROHA:
+ return "hiragana-iroha";
+ case tdehtml::KATAKANA_IROHA:
+ return "katakana_iroha";
+ case tdehtml::LNONE:
+ return "none";
+ }
+ Q_ASSERT( 0 );
+ return "";
+}
+
+static CSSPrimitiveValueImpl* valueForColor(TQColor color)
+{
+ if (color.isValid())
+ return new CSSPrimitiveValueImpl(color.rgb());//### KDE4: use rgba!
+ else
+ return new CSSPrimitiveValueImpl(tdehtml::transparentColor);
+}
+
+static CSSValueImpl* valueForShadow(const ShadowData *shadow)
+{
+ if (!shadow)
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ CSSValueListImpl *list = new CSSValueListImpl;
+ for (const ShadowData *s = shadow; s; s = s->next) {
+ CSSPrimitiveValueImpl *x = new CSSPrimitiveValueImpl(s->x, CSSPrimitiveValue::CSS_PX);
+ CSSPrimitiveValueImpl *y = new CSSPrimitiveValueImpl(s->y, CSSPrimitiveValue::CSS_PX);
+ CSSPrimitiveValueImpl *blur = new CSSPrimitiveValueImpl(s->blur, CSSPrimitiveValue::CSS_PX);
+ CSSPrimitiveValueImpl *color = valueForColor(s->color);
+ list->append(new ShadowValueImpl(x, y, blur, color));
+ }
+ return list;
+}
+
+static CSSValueImpl *getPositionOffsetValue(RenderObject *renderer, int propertyID)
+{
+ if (!renderer)
+ return 0;
+
+ RenderStyle *style = renderer->style();
+ if (!style)
+ return 0;
+
+ Length l;
+ switch (propertyID) {
+ case CSS_PROP_LEFT:
+ l = style->left();
+ break;
+ case CSS_PROP_RIGHT:
+ l = style->right();
+ break;
+ case CSS_PROP_TOP:
+ l = style->top();
+ break;
+ case CSS_PROP_BOTTOM:
+ l = style->bottom();
+ break;
+ default:
+ return 0;
+ }
+
+ if (renderer->isPositioned())
+ return valueForLength(l, renderer->contentWidth());
+
+ if (renderer->isRelPositioned())
+ // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
+ // In other words if left is auto and right is not auto, then left's computed value is negative right.
+ // So we should get the opposite length unit and see if it is auto.
+ return valueForLength(l, renderer->contentWidth());
+
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ }
+
+RenderStyleDeclarationImpl::RenderStyleDeclarationImpl( DOM::NodeImpl *node )
+ : CSSStyleDeclarationImpl(0), m_node(node)
+{
+ //kdDebug() << "Render Style Declaration created" << endl;
+}
+
+RenderStyleDeclarationImpl::~RenderStyleDeclarationImpl()
+{
+ //kdDebug() << "Render Style Declaration destroyed" << endl;
+}
+
+DOM::DOMString RenderStyleDeclarationImpl::cssText() const
+{
+ DOMString result;
+
+ for (unsigned i = 0; i < numComputedProperties; i++) {
+ if (i != 0)
+ result += " ";
+ result += getPropertyName(computedProperties[i]);
+ result += ": ";
+ result += getPropertyValue(computedProperties[i]);
+ result += ";";
+ }
+
+ return result;
+}
+
+void RenderStyleDeclarationImpl::setCssText( DOM::DOMString )
+{
+ // ### report that this sucka is read only
+}
+
+CSSValueImpl *RenderStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const
+{
+ NodeImpl *node = m_node.get();
+ if (!node)
+ return 0;
+
+ // Make sure our layout is up to date before we allow a query on these attributes.
+ DocumentImpl* docimpl = node->getDocument();
+ if (docimpl) {
+ docimpl->updateLayout();
+ }
+
+ RenderObject *renderer = m_node->renderer();
+ if (!renderer)
+ return 0;
+ RenderStyle *style = renderer->style();
+ if (!style)
+ return 0;
+
+ switch(propertyID)
+ {
+ case CSS_PROP_BACKGROUND_COLOR:
+ return valueForColor(style->backgroundColor());
+ case CSS_PROP_BACKGROUND_IMAGE:
+ if (style->backgroundImage())
+ return new CSSPrimitiveValueImpl(style->backgroundImage()->url(),
+ CSSPrimitiveValue::CSS_URI);
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case CSS_PROP_BACKGROUND_REPEAT:
+ switch (style->backgroundRepeat()) {
+ case tdehtml::REPEAT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT);
+ case tdehtml::REPEAT_X:
+ return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_X);
+ case tdehtml::REPEAT_Y:
+ return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_Y);
+ case tdehtml::NO_REPEAT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NO_REPEAT);
+ default:
+ Q_ASSERT( 0 );
+ }
+ case CSS_PROP_BACKGROUND_ATTACHMENT:
+ if (style->backgroundAttachment())
+ return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_FIXED);
+ case CSS_PROP_BACKGROUND_POSITION:
+ {
+ DOMString string;
+ Length length(style->backgroundXPosition());
+ if (length.isPercent())
+ string = TQString::number(length.value()) + "%";
+ else
+ string = TQString::number(length.minWidth(renderer->contentWidth()));
+ string += " ";
+ length = style->backgroundYPosition();
+ if (length.isPercent())
+ string += TQString::number(length.value()) + "%";
+ else
+ string += TQString::number(length.minWidth(renderer->contentWidth()));
+ return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING);
+ }
+ case CSS_PROP_BACKGROUND_POSITION_X:
+ return valueForLength(style->backgroundXPosition(), renderer->contentWidth());
+ case CSS_PROP_BACKGROUND_POSITION_Y:
+ return valueForLength(style->backgroundYPosition(), renderer->contentHeight());
+ case CSS_PROP_BORDER_COLLAPSE:
+ if (style->borderCollapse())
+ return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_SEPARATE);
+ case CSS_PROP_BORDER_SPACING:
+ {
+ TQString string(TQString::number(style->borderHorizontalSpacing()) +
+ "px " +
+ TQString::number(style->borderVerticalSpacing()) +
+ "px");
+ return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING);
+ }
+ case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING:
+ return new CSSPrimitiveValueImpl(style->borderHorizontalSpacing(),
+ CSSPrimitiveValue::CSS_PX);
+ case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING:
+ return new CSSPrimitiveValueImpl(style->borderVerticalSpacing(),
+ CSSPrimitiveValue::CSS_PX);
+ case CSS_PROP_BORDER_TOP_COLOR:
+ return valueForColor(style->borderTopColor());
+ case CSS_PROP_BORDER_RIGHT_COLOR:
+ return valueForColor(style->borderRightColor());
+ case CSS_PROP_BORDER_BOTTOM_COLOR:
+ return valueForColor(style->borderBottomColor());
+ case CSS_PROP_BORDER_LEFT_COLOR:
+ return valueForColor(style->borderLeftColor());
+ case CSS_PROP_BORDER_TOP_STYLE:
+ return valueForBorderStyle(style->borderTopStyle());
+ case CSS_PROP_BORDER_RIGHT_STYLE:
+ return valueForBorderStyle(style->borderRightStyle());
+ case CSS_PROP_BORDER_BOTTOM_STYLE:
+ return valueForBorderStyle(style->borderBottomStyle());
+ case CSS_PROP_BORDER_LEFT_STYLE:
+ return valueForBorderStyle(style->borderLeftStyle());
+ case CSS_PROP_BORDER_TOP_WIDTH:
+ return new CSSPrimitiveValueImpl( style->borderTopWidth(), CSSPrimitiveValue::CSS_PX );
+ case CSS_PROP_BORDER_RIGHT_WIDTH:
+ return new CSSPrimitiveValueImpl( style->borderRightWidth(), CSSPrimitiveValue::CSS_PX );
+ case CSS_PROP_BORDER_BOTTOM_WIDTH:
+ return new CSSPrimitiveValueImpl( style->borderBottomWidth(), CSSPrimitiveValue::CSS_PX );
+ case CSS_PROP_BORDER_LEFT_WIDTH:
+ return new CSSPrimitiveValueImpl( style->borderLeftWidth(), CSSPrimitiveValue::CSS_PX );
+ case CSS_PROP_BOTTOM:
+ return getPositionOffsetValue(renderer, CSS_PROP_BOTTOM);
+ case CSS_PROP_CAPTION_SIDE:
+ switch (style->captionSide()) {
+ case CAPLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case CAPRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ case CAPTOP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TOP);
+ case CAPBOTTOM:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_CLEAR:
+ switch (style->clear()) {
+ case CNONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case CLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case CRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ case CBOTH:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BOTH);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_CLIP:
+ break;
+ case CSS_PROP_COLOR:
+ return valueForColor(style->color());
+ case CSS_PROP_CONTENT:
+ break;
+ case CSS_PROP_COUNTER_INCREMENT:
+ break;
+ case CSS_PROP_COUNTER_RESET:
+ break;
+ case CSS_PROP_CURSOR:
+ switch (style->cursor()) {
+ case CURSOR_AUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case CURSOR_CROSS:
+ return new CSSPrimitiveValueImpl(CSS_VAL_CROSSHAIR);
+ case CURSOR_DEFAULT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_DEFAULT);
+ case CURSOR_POINTER:
+ return new CSSPrimitiveValueImpl(CSS_VAL_POINTER);
+ case CURSOR_MOVE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_MOVE);
+ case CURSOR_PROGRESS:
+ return new CSSPrimitiveValueImpl(CSS_VAL_PROGRESS);
+ case CURSOR_E_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_E_RESIZE);
+ case CURSOR_NE_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NE_RESIZE);
+ case CURSOR_NW_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NW_RESIZE);
+ case CURSOR_N_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_N_RESIZE);
+ case CURSOR_SE_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SE_RESIZE);
+ case CURSOR_SW_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SW_RESIZE);
+ case CURSOR_S_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_S_RESIZE);
+ case CURSOR_W_RESIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_W_RESIZE);
+ case CURSOR_TEXT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TEXT);
+ case CURSOR_WAIT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_WAIT);
+ case CURSOR_HELP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_HELP);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_DIRECTION:
+ switch (style->direction()) {
+ case LTR:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LTR);
+ case RTL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RTL);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_DISPLAY:
+ switch (style->display()) {
+ case INLINE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_INLINE);
+ case BLOCK:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BLOCK);
+ case LIST_ITEM:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LIST_ITEM);
+ case RUN_IN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RUN_IN);
+ case COMPACT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_COMPACT);
+ case INLINE_BLOCK:
+ return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_BLOCK);
+ case TABLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE);
+ case INLINE_TABLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_TABLE);
+ case TABLE_ROW_GROUP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW_GROUP);
+ case TABLE_HEADER_GROUP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_HEADER_GROUP);
+ case TABLE_FOOTER_GROUP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_FOOTER_GROUP);
+ case TABLE_ROW:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW);
+ case TABLE_COLUMN_GROUP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN_GROUP);
+ case TABLE_COLUMN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN);
+ case TABLE_CELL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CELL);
+ case TABLE_CAPTION:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CAPTION);
+ case NONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ }
+ Q_ASSERT( 0 );
+ break;
+ case CSS_PROP_EMPTY_CELLS:
+ switch (style->emptyCells()) {
+ case SHOW:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SHOW);
+ case HIDE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_HIDE);
+ }
+ Q_ASSERT( 0 );
+ break;
+ case CSS_PROP_FLOAT:
+ {
+ switch (style->floating()) {
+ case FNONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case FLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case FRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ case FLEFT_ALIGN:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_LEFT);
+ case FRIGHT_ALIGN:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_RIGHT);
+ }
+ }
+ case CSS_PROP_FONT_FAMILY:
+ {
+ FontDef def = style->htmlFont().getFontDef();
+ return new CSSPrimitiveValueImpl(def.family, CSSPrimitiveValue::CSS_STRING);
+ }
+ case CSS_PROP_FONT_SIZE:
+ {
+ FontDef def = style->htmlFont().getFontDef();
+ return new CSSPrimitiveValueImpl(def.size, CSSPrimitiveValue::CSS_PX);
+ }
+ case CSS_PROP_FONT_STYLE:
+ {
+ // FIXME: handle oblique
+ FontDef def = style->htmlFont().getFontDef();
+ if (def.italic)
+ return new CSSPrimitiveValueImpl(CSS_VAL_ITALIC);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ }
+ case CSS_PROP_FONT_VARIANT:
+ {
+ FontDef def = style->htmlFont().getFontDef();
+ if (def.smallCaps)
+ return new CSSPrimitiveValueImpl(CSS_VAL_SMALL_CAPS);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ }
+ case CSS_PROP_FONT_WEIGHT:
+ {
+ // FIXME: this does not reflect the full range of weights
+ // that can be expressed with CSS
+ FontDef def = style->htmlFont().getFontDef();
+ if (def.weight == TQFont::Bold)
+ return new CSSPrimitiveValueImpl(CSS_VAL_BOLD);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ }
+ case CSS_PROP_HEIGHT:
+ return new CSSPrimitiveValueImpl(renderer->contentHeight(), CSSPrimitiveValue::CSS_PX);
+ case CSS_PROP_LEFT:
+ return getPositionOffsetValue(renderer, CSS_PROP_LEFT);
+ case CSS_PROP_LETTER_SPACING:
+ if (style->letterSpacing() == 0)
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ return new CSSPrimitiveValueImpl(style->letterSpacing(), CSSPrimitiveValue::CSS_PX);
+ case CSS_PROP_LINE_HEIGHT:
+ {
+ // Note: internally a specified <number> value gets encoded as a percentage,
+ // so the isPercent() case corresponds to the <number> case;
+ // values < 0 are used to mark "normal"; and specified %%
+ // get computed down to px by the time they get to RenderStyle
+ // already
+ Length length(style->lineHeight());
+ if (length.value() < 0)
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ if (length.isPercent()) {
+ //XXX: merge from webcore the computedStyle/specifiedStyle distinction in rendering/font.h
+ float computedSize = style->htmlFont().getFontDef().size;
+ return new CSSPrimitiveValueImpl((int)(length.value() * computedSize) / 100, CSSPrimitiveValue::CSS_PX);
+ }
+ else {
+ return new CSSPrimitiveValueImpl(length.value(), CSSPrimitiveValue::CSS_PX);
+ }
+ }
+ case CSS_PROP_LIST_STYLE_IMAGE:
+ if (style->listStyleImage())
+ return new CSSPrimitiveValueImpl(style->listStyleImage()->url(), CSSPrimitiveValue::CSS_URI);
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case CSS_PROP_LIST_STYLE_POSITION:
+ switch (style->listStylePosition()) {
+ case OUTSIDE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_OUTSIDE);
+ case INSIDE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_INSIDE);
+ }
+ Q_ASSERT( 0 );
+ break;
+ case CSS_PROP_LIST_STYLE_TYPE:
+ return new CSSPrimitiveValueImpl(stringForListStyleType(style->listStyleType()), CSSPrimitiveValue::CSS_STRING);
+ case CSS_PROP_MARGIN_TOP:
+ return valueForLength(style->marginTop(), renderer->contentHeight());
+ case CSS_PROP_MARGIN_RIGHT:
+ return valueForLength(style->marginRight(), renderer->contentWidth());
+ case CSS_PROP_MARGIN_BOTTOM:
+ return valueForLength(style->marginBottom(), renderer->contentHeight());
+ case CSS_PROP_MARGIN_LEFT:
+ return valueForLength(style->marginLeft(), renderer->contentWidth());
+ case CSS_PROP__KHTML_MARQUEE:
+ // FIXME: unimplemented
+ break;
+ case CSS_PROP__KHTML_MARQUEE_DIRECTION:
+ switch (style->marqueeDirection()) {
+ case MFORWARD:
+ return new CSSPrimitiveValueImpl(CSS_VAL_FORWARDS);
+ case MBACKWARD:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BACKWARDS);
+ case MAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case MUP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_UP);
+ case MDOWN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_DOWN);
+ case MLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case MRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ }
+ Q_ASSERT(0);
+ return 0;
+ case CSS_PROP__KHTML_MARQUEE_INCREMENT:
+ return valueForLength(style->marqueeIncrement(), renderer->contentWidth());
+ case CSS_PROP__KHTML_MARQUEE_REPETITION:
+ if (style->marqueeLoopCount() < 0)
+ return new CSSPrimitiveValueImpl(CSS_VAL_INFINITE);
+ return new CSSPrimitiveValueImpl(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSS_PROP__KHTML_MARQUEE_SPEED:
+ // FIXME: unimplemented
+ break;
+ case CSS_PROP__KHTML_MARQUEE_STYLE:
+ switch (style->marqueeBehavior()) {
+ case MNONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ case MSCROLL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL);
+ case MSLIDE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SLIDE);
+ case MALTERNATE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_ALTERNATE);
+ case MUNFURL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_UNFURL);
+ }
+ Q_ASSERT(0);
+ return 0;
+ case CSS_PROP_MAX_HEIGHT:
+ return new CSSPrimitiveValueImpl( renderer->availableHeight(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_MAX_WIDTH:
+ return new CSSPrimitiveValueImpl( renderer->maxWidth(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_MIN_HEIGHT:
+ return new CSSPrimitiveValueImpl( renderer->contentHeight(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_MIN_WIDTH:
+ return new CSSPrimitiveValueImpl( renderer->minWidth(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_OPACITY:
+ return new CSSPrimitiveValueImpl(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSS_PROP_ORPHANS:
+ return new CSSPrimitiveValueImpl(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSS_PROP_OUTLINE_COLOR:
+ break;
+ case CSS_PROP_OUTLINE_OFFSET:
+ break;
+ case CSS_PROP_OUTLINE_STYLE:
+ if (style->outlineStyleIsAuto())
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ return valueForBorderStyle(style->outlineStyle());
+ case CSS_PROP_OUTLINE_WIDTH:
+ break;
+ case CSS_PROP_OVERFLOW:
+ case CSS_PROP_OVERFLOW_X:
+ case CSS_PROP_OVERFLOW_Y: {
+ EOverflow overflow;
+ switch (propertyID) {
+ case CSS_PROP_OVERFLOW_X:
+ overflow = style->overflowX();
+ break;
+ case CSS_PROP_OVERFLOW_Y:
+ overflow = style->overflowY();
+ break;
+ default:
+ overflow = kMax(style->overflowX(), style->overflowY());
+ }
+ switch (overflow) {
+ case OVISIBLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE);
+ case OHIDDEN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN);
+ case OSCROLL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL);
+ case OAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case OMARQUEE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_MARQUEE);
+ }
+ Q_ASSERT(0);
+ return 0;
+ }
+ case CSS_PROP_PADDING_TOP:
+ return valueForLength(style->paddingTop(), renderer->contentHeight());
+ case CSS_PROP_PADDING_RIGHT:
+ return valueForLength(style->paddingRight(), renderer->contentWidth());
+ case CSS_PROP_PADDING_BOTTOM:
+ return valueForLength(style->paddingBottom(), renderer->contentHeight());
+ case CSS_PROP_PADDING_LEFT:
+ return valueForLength(style->paddingLeft(), renderer->contentWidth());
+ case CSS_PROP_PAGE_BREAK_AFTER:
+ switch (style->pageBreakAfter()) {
+ case PBAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case PBALWAYS:
+ return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS);
+ case PBAVOID:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AVOID);
+ case PBLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case PBRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_PAGE_BREAK_BEFORE:
+ switch (style->pageBreakBefore()) {
+ case PBAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case PBALWAYS:
+ return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS);
+ case PBAVOID:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AVOID);
+ case PBLEFT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LEFT);
+ case PBRIGHT:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_PAGE_BREAK_INSIDE:
+ if (style->pageBreakInside())
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ else
+ return new CSSPrimitiveValueImpl(CSS_VAL_AVOID);
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_POSITION:
+ switch (style->position()) {
+ case STATIC:
+ return new CSSPrimitiveValueImpl(CSS_VAL_STATIC);
+ case RELATIVE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_RELATIVE);
+ case ABSOLUTE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_ABSOLUTE);
+ case FIXED:
+ return new CSSPrimitiveValueImpl(CSS_VAL_FIXED);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_QUOTES:
+ break;
+ case CSS_PROP_RIGHT:
+ return getPositionOffsetValue(renderer, CSS_PROP_RIGHT);
+ case CSS_PROP_SIZE:
+ break;
+ case CSS_PROP_TABLE_LAYOUT:
+ switch (style->tableLayout()) {
+ case TAUTO:
+ return new CSSPrimitiveValueImpl(CSS_VAL_AUTO);
+ case TFIXED:
+ return new CSSPrimitiveValueImpl(CSS_VAL_FIXED);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_TEXT_ALIGN:
+ return valueForTextAlign(style->textAlign());
+ case CSS_PROP_TEXT_DECORATION:
+ {
+ TQString string;
+ if (style->textDecoration() & tdehtml::UNDERLINE)
+ string += "underline";
+ if (style->textDecoration() & tdehtml::OVERLINE) {
+ if (string.length() > 0)
+ string += " ";
+ string += "overline";
+ }
+ if (style->textDecoration() & tdehtml::LINE_THROUGH) {
+ if (string.length() > 0)
+ string += " ";
+ string += "line-through";
+ }
+ if (style->textDecoration() & tdehtml::BLINK) {
+ if (string.length() > 0)
+ string += " ";
+ string += "blink";
+ }
+ if (string.length() == 0)
+ string = "none";
+ return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING);
+ }
+ case CSS_PROP_TEXT_INDENT:
+ return valueForLength(style->textIndent(), renderer->contentWidth());
+ case CSS_PROP_TEXT_SHADOW:
+ return valueForShadow(style->textShadow());
+ case CSS_PROP_TEXT_TRANSFORM:
+ switch (style->textTransform()) {
+ case CAPITALIZE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_CAPITALIZE);
+ case UPPERCASE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_UPPERCASE);
+ case LOWERCASE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_LOWERCASE);
+ case TTNONE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NONE);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_TOP:
+ return getPositionOffsetValue(renderer, CSS_PROP_TOP);
+ case CSS_PROP_UNICODE_BIDI:
+ switch (style->unicodeBidi()) {
+ case UBNormal:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ case Embed:
+ return new CSSPrimitiveValueImpl(CSS_VAL_EMBED);
+ case Override:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BIDI_OVERRIDE);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_VERTICAL_ALIGN:
+ {
+ switch (style->verticalAlign()) {
+ case BASELINE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BASELINE);
+ case MIDDLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_MIDDLE);
+ case SUB:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SUB);
+ case SUPER:
+ return new CSSPrimitiveValueImpl(CSS_VAL_SUPER);
+ case TEXT_TOP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_TOP);
+ case TEXT_BOTTOM:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_BOTTOM);
+ case TOP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_TOP);
+ case BOTTOM:
+ return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM);
+ case BASELINE_MIDDLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_BASELINE_MIDDLE);
+ case LENGTH:
+ return valueForLength(style->verticalAlignLength(), renderer->contentWidth());
+ }
+ Q_ASSERT(0);
+ break;
+ }
+ case CSS_PROP_VISIBILITY:
+ switch (style->visibility()) {
+ case tdehtml::VISIBLE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE);
+ case tdehtml::HIDDEN:
+ return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN);
+ case tdehtml::COLLAPSE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE);
+ }
+ Q_ASSERT(0);
+ break;
+ case CSS_PROP_WHITE_SPACE:
+ {
+ switch (style->whiteSpace()) {
+ case NORMAL:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ case PRE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_PRE);
+ case PRE_WRAP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_PRE_WRAP);
+ case PRE_LINE:
+ return new CSSPrimitiveValueImpl(CSS_VAL_PRE_LINE);
+ case NOWRAP:
+ return new CSSPrimitiveValueImpl(CSS_VAL_NOWRAP);
+ case KHTML_NOWRAP:
+ return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_NOWRAP);
+ }
+ Q_ASSERT(0);
+ break;
+ }
+ case CSS_PROP_WIDOWS:
+ return new CSSPrimitiveValueImpl(style->widows(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSS_PROP_WIDTH:
+ return new CSSPrimitiveValueImpl( renderer->contentWidth(),
+ CSSPrimitiveValue::CSS_PX );
+ case CSS_PROP_WORD_SPACING:
+ return new CSSPrimitiveValueImpl(style->wordSpacing(), CSSPrimitiveValue::CSS_PX);
+ case CSS_PROP_Z_INDEX:
+ if (style->hasAutoZIndex())
+ return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL);
+ return new CSSPrimitiveValueImpl(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSS_PROP_BACKGROUND:
+ break;
+ case CSS_PROP_BORDER:
+ break;
+ case CSS_PROP_BORDER_COLOR:
+ break;
+ case CSS_PROP_BORDER_STYLE:
+ break;
+ case CSS_PROP_BORDER_TOP:
+ return new CSSPrimitiveValueImpl( renderer->borderTop(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_BORDER_RIGHT:
+ return new CSSPrimitiveValueImpl( renderer->borderRight(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_BORDER_BOTTOM:
+ return new CSSPrimitiveValueImpl( renderer->borderBottom(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_BORDER_LEFT:
+ return new CSSPrimitiveValueImpl( renderer->borderLeft(),
+ CSSPrimitiveValue::CSS_PX );
+ break;
+ case CSS_PROP_BORDER_WIDTH:
+ break;
+ case CSS_PROP_FONT:
+ break;
+ case CSS_PROP_LIST_STYLE:
+ break;
+ case CSS_PROP_MARGIN:
+ break;
+ case CSS_PROP_OUTLINE:
+ break;
+ case CSS_PROP_PADDING:
+ break;
+ case CSS_PROP_SCROLLBAR_BASE_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_FACE_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_TRACK_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_ARROW_COLOR:
+ break;
+ case CSS_PROP__KHTML_FLOW_MODE:
+ break;
+ case CSS_PROP__KHTML_USER_INPUT:
+ break;
+ default:
+ Q_ASSERT( 0 );
+ break;
+ }
+ return 0;
+}
+
+DOMString RenderStyleDeclarationImpl::getPropertyValue( int propertyID ) const
+{
+ CSSValueImpl* value = getPropertyCSSValue(propertyID);
+ if (value) {
+ DOMString val = value->cssText();
+ delete value;
+ return val;
+ }
+ return "";
+}
+
+bool RenderStyleDeclarationImpl::getPropertyPriority( int ) const
+{
+ // All computed styles have a priority of false (not "important").
+ return false;
+}
+
+DOM::DOMString RenderStyleDeclarationImpl::removeProperty( int, bool )
+{
+ // ### emit error since we're read-only
+ return DOMString();
+}
+
+bool RenderStyleDeclarationImpl::setProperty ( int, const DOM::DOMString&, bool,
+ bool )
+{
+ // ### emit error since we're read-only
+ return false;
+}
+
+void RenderStyleDeclarationImpl::setProperty ( int, int, bool,
+ bool )
+{
+ // ### emit error since we're read-only
+}
+
+void RenderStyleDeclarationImpl::setLengthProperty( int, const DOM::DOMString&, bool,
+ bool, bool )
+{
+ // ### emit error since we're read-only
+}
+
+void RenderStyleDeclarationImpl::setProperty( const DOMString& )
+{
+ // ### emit error since we're read-only
+}
+
+unsigned long RenderStyleDeclarationImpl::length() const
+{
+ return numComputedProperties;
+}
+
+DOM::DOMString RenderStyleDeclarationImpl::item( unsigned long i ) const
+{
+ if (i >= numComputedProperties)
+ return DOMString();
+
+ return getPropertyName(computedProperties[i]);
+}
+
+CSSProperty RenderStyleDeclarationImpl::property( int id ) const
+{
+ CSSProperty prop;
+ prop.m_id = id;
+ prop.m_important = false;
+ prop.nonCSSHint = false;
+
+ CSSValueImpl* v = getPropertyCSSValue( id );
+ if ( !v )
+ v = new CSSPrimitiveValueImpl;
+ prop.setValue( v );
+ return prop;
+}
+
diff --git a/tdehtml/css/css_renderstyledeclarationimpl.h b/tdehtml/css/css_renderstyledeclarationimpl.h
new file mode 100644
index 000000000..a751ceda1
--- /dev/null
+++ b/tdehtml/css/css_renderstyledeclarationimpl.h
@@ -0,0 +1,75 @@
+/*
+ * css_renderstyleimpl.h
+ *
+ * Copyright (C) 2004 Zack Rusin <zack@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef CSS_RENDERSTYLEIMPL_H
+#define CSS_RENDERSTYLEIMPL_H
+
+#include "css/css_valueimpl.h"
+#include "dom/dom_string.h"
+#include "rendering/render_style.h"
+
+
+namespace DOM {
+ class NodeImpl;
+}
+
+namespace tdehtml {
+
+class RenderObject;
+
+
+// Used by DOM::Counter::listStyle()
+DOM::DOMString stringForListStyleType(tdehtml::EListStyleType type);
+
+class RenderStyleDeclarationImpl : public DOM::CSSStyleDeclarationImpl
+{
+public:
+ RenderStyleDeclarationImpl( DOM::NodeImpl *node );
+ virtual ~RenderStyleDeclarationImpl();
+
+ DOM::DOMString cssText() const;
+ void setCssText( DOM::DOMString str );
+
+ DOM::CSSValueImpl *getPropertyCSSValue( int propertyID ) const;
+ DOM::DOMString getPropertyValue( int propertyID ) const;
+ bool getPropertyPriority( int propertyID ) const;
+ unsigned long length() const;
+
+ DOM::DOMString removeProperty( int propertyID, bool NonCSSHints = false );
+ bool setProperty ( int propertyId, const DOM::DOMString &value, bool important = false,
+ bool nonCSSHint = false);
+ void setProperty ( int propertyId, int value, bool important = false, bool nonCSSHint = false);
+ void setLengthProperty(int id, const DOM::DOMString &value, bool important,
+ bool nonCSSHint = true, bool multiLength = false);
+
+ void setProperty ( const DOM::DOMString &propertyString);
+ DOM::DOMString item ( unsigned long index ) const;
+
+protected:
+ DOM::CSSProperty property( int id ) const;
+
+protected:
+ SharedPtr<DOM::NodeImpl> m_node;
+};
+
+
+}
+
+#endif
diff --git a/tdehtml/css/css_ruleimpl.cpp b/tdehtml/css/css_ruleimpl.cpp
new file mode 100644
index 000000000..0edd3a511
--- /dev/null
+++ b/tdehtml/css/css_ruleimpl.cpp
@@ -0,0 +1,391 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-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.
+ */
+#include "dom/css_rule.h"
+#include "dom/css_stylesheet.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_string.h"
+
+#include "css/css_stylesheetimpl.h"
+#include "css/css_valueimpl.h"
+#include "css/cssparser.h"
+#include "css/css_ruleimpl.h"
+
+#include "misc/loader.h"
+#include "misc/htmltags.h"
+#include "misc/htmlattrs.h"
+#include "xml/dom_docimpl.h"
+
+using namespace DOM;
+
+#include <kdebug.h>
+
+CSSStyleSheetImpl *CSSRuleImpl::parentStyleSheet() const
+{
+ return ( m_parent && m_parent->isCSSStyleSheet() ) ?
+ static_cast<CSSStyleSheetImpl *>(m_parent) : 0;
+}
+
+CSSRuleImpl *CSSRuleImpl::parentRule() const
+{
+ return ( m_parent && m_parent->isRule() ) ?
+ static_cast<CSSRuleImpl *>(m_parent) : 0;
+}
+
+DOM::DOMString CSSRuleImpl::cssText() const
+{
+ // ###
+ return DOMString();
+}
+
+void CSSRuleImpl::setCssText(DOM::DOMString /*str*/)
+{
+ // ###
+}
+
+// ---------------------------------------------------------------------------
+
+CSSFontFaceRuleImpl::CSSFontFaceRuleImpl(StyleBaseImpl *parent)
+ : CSSRuleImpl(parent)
+{
+ m_type = CSSRule::FONT_FACE_RULE;
+ m_style = 0;
+}
+
+CSSFontFaceRuleImpl::~CSSFontFaceRuleImpl()
+{
+ if(m_style) m_style->deref();
+}
+
+// --------------------------------------------------------------------------
+
+CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl *parent,
+ const DOM::DOMString &href,
+ MediaListImpl *media )
+ : CSSRuleImpl(parent)
+{
+ m_type = CSSRule::IMPORT_RULE;
+
+ m_lstMedia = media;
+ if ( !m_lstMedia )
+ m_lstMedia = new MediaListImpl( this, DOMString() );
+ m_lstMedia->setParent( this );
+ m_lstMedia->ref();
+
+ m_strHref = href;
+ m_styleSheet = 0;
+
+ m_cachedSheet = 0;
+
+ init();
+}
+CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl *parent,
+ const DOM::DOMString &href,
+ const DOM::DOMString &media )
+ : CSSRuleImpl(parent)
+{
+ m_type = CSSRule::IMPORT_RULE;
+
+ m_lstMedia = new MediaListImpl( this, media );
+ m_lstMedia->ref();
+
+ m_strHref = href;
+ m_styleSheet = 0;
+
+ m_cachedSheet = 0;
+
+ init();
+}
+
+CSSImportRuleImpl::~CSSImportRuleImpl()
+{
+ if( m_lstMedia ) {
+ m_lstMedia->setParent( 0 );
+ m_lstMedia->deref();
+ }
+ if(m_styleSheet) {
+ m_styleSheet->setParent(0);
+ m_styleSheet->deref();
+ }
+
+ if(m_cachedSheet) m_cachedSheet->deref(this);
+}
+
+void CSSImportRuleImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset)
+{
+ if ( m_styleSheet ) {
+ m_styleSheet->setParent(0);
+ m_styleSheet->deref();
+ }
+ m_styleSheet = new CSSStyleSheetImpl(this, url);
+ m_styleSheet->setCharset(charset);
+ m_styleSheet->ref();
+
+ CSSStyleSheetImpl *parent = parentStyleSheet();
+ m_styleSheet->parseString( sheet, parent ? parent->useStrictParsing() : true );
+ m_loading = false;
+ m_done = true;
+
+ checkLoaded();
+}
+
+void CSSImportRuleImpl::error(int /*err*/, const TQString &/*text*/)
+{
+ if ( m_styleSheet ) {
+ m_styleSheet->setParent(0);
+ m_styleSheet->deref();
+ }
+ m_styleSheet = 0;
+
+ m_loading = false;
+ m_done = true;
+
+ checkLoaded();
+}
+
+bool CSSImportRuleImpl::isLoading()
+{
+ return ( m_loading || (m_styleSheet && m_styleSheet->isLoading()) );
+}
+
+void CSSImportRuleImpl::init()
+{
+ m_loading = 0;
+ m_done = false;
+ tdehtml::DocLoader *docLoader = 0;
+ StyleBaseImpl *root = this;
+ StyleBaseImpl *parent;
+ while ( ( parent = root->parent()) )
+ root = parent;
+ if (root->isCSSStyleSheet())
+ docLoader = static_cast<CSSStyleSheetImpl*>(root)->docLoader();
+
+ DOMString absHref = m_strHref;
+ CSSStyleSheetImpl *parentSheet = parentStyleSheet();
+ if (!parentSheet->href().isNull()) {
+ // use parent styleheet's URL as the base URL
+ absHref = KURL(KURL( parentSheet->href().string() ),m_strHref.string()).url();
+ }
+/*
+ else {
+ // use documents's URL as the base URL
+ DocumentImpl *doc = static_cast<CSSStyleSheetImpl*>(root)->doc();
+ absHref = KURL(doc->URL(),m_strHref.string()).url();
+ }
+*/
+ // Check for a cycle in our import chain. If we encounter a stylesheet
+ // in our parent chain with the same URL, then just bail.
+ for ( parent = static_cast<StyleBaseImpl*>( this )->parent();
+ parent;
+ parent = parent->parent() )
+ if ( absHref == parent->baseURL().url() )
+ return;
+
+ m_cachedSheet = docLoader->requestStyleSheet(absHref, parentStyleSheet()->charset().string());
+
+ if (m_cachedSheet)
+ {
+ m_cachedSheet->ref(this);
+
+ // If the imported sheet is in the cache, then setStyleSheet gets called,
+ // and the sheet even gets parsed (via parseString). In this case we have
+ // loaded (even if our subresources haven't), so if we have stylesheet after
+ // checking the cache, then we've clearly loaded. -dwh
+ // This can also happen when error() is called from within ref(). In either case,
+ // m_done is set to true.
+ if (!m_done)
+ m_loading = true;
+ }
+}
+
+// --------------------------------------------------------------------------
+CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl *parent, MediaListImpl *mediaList, CSSRuleListImpl *ruleList )
+ : CSSRuleImpl( parent )
+{
+ m_type = CSSRule::MEDIA_RULE;
+ m_lstMedia = mediaList;
+ m_lstMedia->ref();
+ m_lstCSSRules = ruleList;
+ m_lstCSSRules->ref();
+}
+
+CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent)
+ : CSSRuleImpl( parent )
+{
+ m_type = CSSRule::MEDIA_RULE;
+ m_lstMedia = 0;
+ m_lstCSSRules = new CSSRuleListImpl();
+ m_lstCSSRules->ref();
+}
+
+CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl *parent, const DOM::DOMString &media )
+: CSSRuleImpl( parent )
+{
+ m_type = CSSRule::MEDIA_RULE;
+ m_lstMedia = new MediaListImpl( this, media );
+ m_lstMedia->ref();
+ m_lstCSSRules = new CSSRuleListImpl();
+ m_lstCSSRules->ref();
+}
+
+CSSMediaRuleImpl::~CSSMediaRuleImpl()
+{
+ if( m_lstMedia ) {
+ m_lstMedia->setParent( 0 );
+ m_lstMedia->deref();
+ }
+ for ( unsigned int i = 0; i < m_lstCSSRules->length(); ++i )
+ m_lstCSSRules->item( i )->setParent( 0 );
+ m_lstCSSRules->deref();
+}
+
+unsigned long CSSMediaRuleImpl::append( CSSRuleImpl *rule )
+{
+ return rule ? m_lstCSSRules->insertRule( rule, m_lstCSSRules->length() ) : 0;
+}
+
+unsigned long CSSMediaRuleImpl::insertRule( const DOMString &rule,
+ unsigned long index )
+{
+ CSSParser p( strictParsing );
+ CSSRuleImpl *newRule = p.parseRule( parentStyleSheet(), rule );
+
+ return newRule ? m_lstCSSRules->insertRule( newRule, index ) : 0;
+}
+
+CSSRuleListImpl::~CSSRuleListImpl()
+{
+ CSSRuleImpl* rule;
+ while ( !m_lstCSSRules.isEmpty() && ( rule = m_lstCSSRules.take( 0 ) ) )
+ rule->deref();
+}
+
+// ---------------------------------------------------------------------------
+
+CSSPageRuleImpl::CSSPageRuleImpl(StyleBaseImpl *parent)
+ : CSSRuleImpl(parent)
+{
+ m_type = CSSRule::PAGE_RULE;
+ m_style = 0;
+}
+
+CSSPageRuleImpl::~CSSPageRuleImpl()
+{
+ if(m_style) m_style->deref();
+}
+
+DOM::DOMString CSSPageRuleImpl::selectorText() const
+{
+ // ###
+ return DOMString();
+}
+
+void CSSPageRuleImpl::setSelectorText(DOM::DOMString /*str*/)
+{
+ // ###
+}
+
+// --------------------------------------------------------------------------
+
+CSSStyleRuleImpl::CSSStyleRuleImpl(StyleBaseImpl *parent)
+ : CSSRuleImpl(parent)
+{
+ m_type = CSSRule::STYLE_RULE;
+ m_style = 0;
+ m_selector = 0;
+}
+
+CSSStyleRuleImpl::~CSSStyleRuleImpl()
+{
+ if(m_style) {
+ m_style->setParent( 0 );
+ m_style->deref();
+ }
+ delete m_selector;
+}
+
+DOM::DOMString CSSStyleRuleImpl::selectorText() const
+{
+ if (m_selector) {
+ DOMString str;
+ for (CSSSelector *s = m_selector->first(); s; s = m_selector->next()) {
+ if (s != m_selector->getFirst())
+ str += ", ";
+ str += s->selectorText();
+ }
+ return str;
+ }
+ return DOMString();
+}
+
+void CSSStyleRuleImpl::setSelectorText(DOM::DOMString /*str*/)
+{
+ // ###
+}
+
+bool CSSStyleRuleImpl::parseString( const DOMString &/*string*/, bool )
+{
+ // ###
+ return false;
+}
+
+void CSSStyleRuleImpl::setDeclaration( CSSStyleDeclarationImpl *style)
+{
+ if ( m_style != style ) {
+ if(m_style) m_style->deref();
+ m_style = style;
+ if(m_style) m_style->ref();
+ }
+}
+
+void CSSStyleRuleImpl::setNonCSSHints()
+{
+ CSSSelector *s = m_selector->first();
+ while ( s ) {
+ s->nonCSSHint = true;
+ s = m_selector->next();
+ }
+}
+
+void CSSRuleListImpl::deleteRule ( unsigned long index )
+{
+ CSSRuleImpl *rule = m_lstCSSRules.take( index );
+ if( rule )
+ rule->deref();
+ else {
+ // ### Throw INDEX_SIZE_ERR exception here (TODO)
+ }
+}
+
+unsigned long CSSRuleListImpl::insertRule( CSSRuleImpl *rule,
+ unsigned long index )
+{
+ if( rule && m_lstCSSRules.insert( index, rule ) )
+ {
+ rule->ref();
+ return index;
+ }
+
+ // ### Should throw INDEX_SIZE_ERR exception instead! (TODO)
+ return 0;
+}
+
diff --git a/tdehtml/css/css_ruleimpl.h b/tdehtml/css/css_ruleimpl.h
new file mode 100644
index 000000000..63d0f96a1
--- /dev/null
+++ b/tdehtml/css/css_ruleimpl.h
@@ -0,0 +1,237 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-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.
+ *
+ */
+#ifndef _CSS_css_ruleimpl_h_
+#define _CSS_css_ruleimpl_h_
+
+#include "dom/dom_string.h"
+#include "dom/css_rule.h"
+#include "css/css_base.h"
+#include "misc/loader_client.h"
+#include "misc/shared.h"
+
+namespace tdehtml {
+ class CachedCSSStyleSheet;
+}
+
+namespace DOM {
+
+class CSSRule;
+class CSSStyleSheet;
+class CSSStyleSheetImpl;
+class CSSStyleDeclarationImpl;
+class MediaListImpl;
+
+class CSSRuleImpl : public StyleBaseImpl
+{
+public:
+ CSSRuleImpl(StyleBaseImpl *parent)
+ : StyleBaseImpl(parent), m_type(CSSRule::UNKNOWN_RULE) {}
+
+ virtual bool isRule() const { return true; }
+ unsigned short type() const { return m_type; }
+
+ CSSStyleSheetImpl *parentStyleSheet() const;
+ CSSRuleImpl *parentRule() const;
+
+ DOM::DOMString cssText() const;
+ void setCssText(DOM::DOMString str);
+ virtual void init() {}
+
+protected:
+ CSSRule::RuleType m_type;
+};
+
+
+class CSSCharsetRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSCharsetRuleImpl(StyleBaseImpl *parent)
+ : CSSRuleImpl(parent) { m_type = CSSRule::CHARSET_RULE; }
+
+ virtual bool isCharsetRule() const { return true; }
+
+ DOMString encoding() const { return m_encoding; }
+ void setEncoding(DOMString _encoding) { m_encoding = _encoding; }
+
+protected:
+ DOMString m_encoding;
+};
+
+
+class CSSFontFaceRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSFontFaceRuleImpl(StyleBaseImpl *parent);
+
+ virtual ~CSSFontFaceRuleImpl();
+
+ CSSStyleDeclarationImpl *style() const { return m_style; }
+
+ virtual bool isFontFaceRule() const { return true; }
+
+protected:
+ CSSStyleDeclarationImpl *m_style;
+};
+
+
+class CSSImportRuleImpl : public tdehtml::CachedObjectClient, public CSSRuleImpl
+{
+public:
+ CSSImportRuleImpl( StyleBaseImpl *parent, const DOM::DOMString &href,
+ const DOM::DOMString &media );
+ CSSImportRuleImpl( StyleBaseImpl *parent, const DOM::DOMString &href,
+ MediaListImpl *media );
+
+ virtual ~CSSImportRuleImpl();
+
+ DOM::DOMString href() const { return m_strHref; }
+ MediaListImpl *media() const { return m_lstMedia; }
+ CSSStyleSheetImpl *styleSheet() const { return m_styleSheet; }
+
+ virtual bool isImportRule() const { return true; }
+
+ // from CachedObjectClient
+ virtual void setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset);
+ virtual void error(int err, const TQString &text);
+
+ bool isLoading();
+ virtual void init();
+
+protected:
+ DOMString m_strHref;
+ MediaListImpl *m_lstMedia;
+ CSSStyleSheetImpl *m_styleSheet;
+ tdehtml::CachedCSSStyleSheet *m_cachedSheet;
+ bool m_loading;
+ bool m_done;
+};
+
+class MediaList;
+
+class CSSRuleListImpl : public tdehtml::Shared<CSSRuleListImpl>
+{
+public:
+ CSSRuleListImpl() {}
+
+ ~CSSRuleListImpl();
+
+ unsigned long length() const { return m_lstCSSRules.count(); }
+ CSSRuleImpl *item ( unsigned long index ) { return m_lstCSSRules.at( index ); }
+
+
+ /* not part of the DOM */
+ unsigned long insertRule ( CSSRuleImpl *rule, unsigned long index );
+ void deleteRule ( unsigned long index );
+
+ void append( CSSRuleImpl *rule ) { m_lstCSSRules.append( rule ); }
+protected:
+ TQPtrList<CSSRuleImpl> m_lstCSSRules;
+};
+
+class CSSMediaRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSMediaRuleImpl( StyleBaseImpl *parent );
+ CSSMediaRuleImpl( StyleBaseImpl *parent, const DOM::DOMString &media );
+ CSSMediaRuleImpl( StyleBaseImpl *parent, MediaListImpl *mediaList, CSSRuleListImpl *ruleList );
+
+ virtual ~CSSMediaRuleImpl();
+
+ MediaListImpl *media() const { return m_lstMedia; }
+ CSSRuleListImpl *cssRules() { return m_lstCSSRules; }
+
+ unsigned long insertRule ( const DOM::DOMString &rule, unsigned long index );
+ void deleteRule ( unsigned long index ) { m_lstCSSRules->deleteRule( index ); }
+
+ virtual bool isMediaRule() const { return true; }
+
+ /* Not part of the DOM */
+ unsigned long append( CSSRuleImpl *rule );
+protected:
+ MediaListImpl *m_lstMedia;
+ CSSRuleListImpl *m_lstCSSRules;
+};
+
+
+class CSSPageRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSPageRuleImpl(StyleBaseImpl *parent);
+
+ virtual ~CSSPageRuleImpl();
+
+ CSSStyleDeclarationImpl *style() const { return m_style; }
+
+ virtual bool isPageRule() const { return true; }
+
+ DOM::DOMString selectorText() const;
+ void setSelectorText(DOM::DOMString str);
+
+protected:
+ CSSStyleDeclarationImpl *m_style;
+};
+
+
+class CSSStyleRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSStyleRuleImpl(StyleBaseImpl *parent);
+
+ virtual ~CSSStyleRuleImpl();
+
+ CSSStyleDeclarationImpl *style() const { return m_style; }
+
+ virtual bool isStyleRule() const { return true; }
+
+ DOM::DOMString selectorText() const;
+ void setSelectorText(DOM::DOMString str);
+
+ virtual bool parseString( const DOMString &string, bool = false );
+
+ void setSelector( TQPtrList<CSSSelector> *selector) { m_selector = selector; }
+ void setDeclaration( CSSStyleDeclarationImpl *style);
+
+ TQPtrList<CSSSelector> *selector() { return m_selector; }
+ CSSStyleDeclarationImpl *declaration() { return m_style; }
+
+ void setNonCSSHints();
+
+protected:
+ CSSStyleDeclarationImpl *m_style;
+ TQPtrList<CSSSelector> *m_selector;
+};
+
+
+class CSSUnknownRuleImpl : public CSSRuleImpl
+{
+public:
+ CSSUnknownRuleImpl(StyleBaseImpl *parent) : CSSRuleImpl(parent) {}
+
+ virtual bool isUnknownRule() const { return true; }
+};
+
+
+} // namespace
+
+#endif
diff --git a/tdehtml/css/css_stylesheetimpl.cpp b/tdehtml/css/css_stylesheetimpl.cpp
new file mode 100644
index 000000000..40fa0dc0c
--- /dev/null
+++ b/tdehtml/css/css_stylesheetimpl.cpp
@@ -0,0 +1,436 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2004 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 CSS_STYLESHEET_DEBUG
+
+#include "dom/dom_string.h"
+#include "dom/dom_exception.h"
+#include "dom/css_stylesheet.h"
+#include "dom/css_rule.h"
+
+#include "css/css_ruleimpl.h"
+#include "css/css_valueimpl.h"
+#include "css/cssparser.h"
+#include "css/css_stylesheetimpl.h"
+
+#include "xml/dom_nodeimpl.h"
+#include "html/html_documentimpl.h"
+#include "misc/loader.h"
+
+#include <kdebug.h>
+
+using namespace DOM;
+using namespace tdehtml;
+// --------------------------------------------------------------------------------
+
+StyleSheetImpl::StyleSheetImpl(StyleSheetImpl *parentSheet, DOMString href)
+ : StyleListImpl(parentSheet)
+{
+ m_disabled = false;
+ m_media = 0;
+ m_parentNode = 0;
+ m_strHref = href;
+}
+
+
+StyleSheetImpl::StyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href)
+ : StyleListImpl()
+{
+ m_parentNode = parentNode;
+ m_disabled = false;
+ m_media = 0;
+ m_strHref = href;
+}
+
+StyleSheetImpl::StyleSheetImpl(StyleBaseImpl *owner, DOMString href)
+ : StyleListImpl(owner)
+{
+ m_disabled = false;
+ m_media = 0;
+ m_parentNode = 0;
+ m_strHref = href;
+}
+
+StyleSheetImpl::~StyleSheetImpl()
+{
+ if(m_media) {
+ m_media->setParent( 0 );
+ m_media->deref();
+ }
+}
+
+StyleSheetImpl *StyleSheetImpl::parentStyleSheet() const
+{
+ if( !m_parent ) return 0;
+ if( m_parent->isStyleSheet() ) return static_cast<StyleSheetImpl *>(m_parent);
+ if( m_parent->isRule() ) return m_parent->stylesheet();
+ return 0;
+}
+
+void StyleSheetImpl::setMedia( MediaListImpl *media )
+{
+ if( media )
+ media->ref();
+ if( m_media )
+ m_media->deref();
+ m_media = media;
+}
+
+void StyleSheetImpl::setDisabled( bool disabled )
+{
+ bool updateStyle = isCSSStyleSheet() && m_parentNode && disabled != m_disabled;
+ m_disabled = disabled;
+ if (updateStyle)
+ m_parentNode->getDocument()->updateStyleSelector();
+}
+
+// -----------------------------------------------------------------------
+
+
+CSSStyleSheetImpl::CSSStyleSheetImpl(CSSStyleSheetImpl *parentSheet, DOMString href)
+ : StyleSheetImpl(parentSheet, href)
+{
+ m_lstChildren = new TQPtrList<StyleBaseImpl>;
+ m_doc = parentSheet ? parentSheet->doc() : 0;
+ m_implicit = false;
+ m_namespaces = 0;
+ m_defaultNamespace = anyNamespace;
+}
+
+CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href, bool _implicit)
+ : StyleSheetImpl(parentNode, href)
+{
+ m_lstChildren = new TQPtrList<StyleBaseImpl>;
+ m_doc = parentNode->getDocument();
+ m_implicit = _implicit;
+ m_namespaces = 0;
+ m_defaultNamespace = anyNamespace;
+}
+
+CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, DOMString href)
+ : StyleSheetImpl(ownerRule, href)
+{
+ m_lstChildren = new TQPtrList<StyleBaseImpl>;
+ m_doc = static_cast<CSSStyleSheetImpl*>(ownerRule->stylesheet())->doc();
+ m_implicit = false;
+ m_namespaces = 0;
+ m_defaultNamespace = anyNamespace;
+}
+
+CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, CSSStyleSheetImpl *orig)
+ : StyleSheetImpl(parentNode, orig->m_strHref)
+{
+ m_lstChildren = new TQPtrList<StyleBaseImpl>;
+ StyleBaseImpl *rule;
+ for ( rule = orig->m_lstChildren->first(); rule != 0; rule = orig->m_lstChildren->next() )
+ {
+ m_lstChildren->append(rule);
+ rule->setParent(this);
+ }
+ m_doc = parentNode->getDocument();
+ m_implicit = false;
+ m_namespaces = 0;
+ m_defaultNamespace = anyNamespace;
+}
+
+CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, CSSStyleSheetImpl *orig)
+ : StyleSheetImpl(ownerRule, orig->m_strHref)
+{
+ // m_lstChildren is deleted in StyleListImpl
+ m_lstChildren = new TQPtrList<StyleBaseImpl>;
+ StyleBaseImpl *rule;
+ for ( rule = orig->m_lstChildren->first(); rule != 0; rule = orig->m_lstChildren->next() )
+ {
+ m_lstChildren->append(rule);
+ rule->setParent(this);
+ }
+ m_doc = static_cast<CSSStyleSheetImpl*>(ownerRule->stylesheet())->doc();
+ m_implicit = false;
+ m_namespaces = 0;
+ m_defaultNamespace = anyNamespace;
+}
+
+CSSRuleImpl *CSSStyleSheetImpl::ownerRule() const
+{
+ if( !m_parent ) return 0;
+ if( m_parent->isRule() ) return static_cast<CSSRuleImpl *>(m_parent);
+ return 0;
+}
+
+unsigned long CSSStyleSheetImpl::insertRule( const DOMString &rule, unsigned long index, int &exceptioncode )
+{
+ exceptioncode = 0;
+ if(index > m_lstChildren->count()) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ return 0;
+ }
+ CSSParser p( strictParsing );
+ CSSRuleImpl *r = p.parseRule( this, rule );
+
+ if(!r) {
+ exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
+ return 0;
+ }
+ // ###
+ // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an
+ //@import rule is inserted after a standard rule set or other at-rule.
+ m_lstChildren->insert(index, r);
+ if (m_doc)
+ m_doc->updateStyleSelector(true /*shallow*/);
+ return index;
+}
+
+CSSRuleList CSSStyleSheetImpl::cssRules()
+{
+ return this;
+}
+
+void CSSStyleSheetImpl::deleteRule( unsigned long index, int &exceptioncode )
+{
+ exceptioncode = 0;
+ StyleBaseImpl *b = m_lstChildren->take(index);
+ if(!b) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ return;
+ }
+ // TreeShared requires delete not deref when removed from tree
+ b->setParent(0);
+ if( !b->refCount() ) delete b;
+ if (m_doc)
+ m_doc->updateStyleSelector(true /*shallow*/);
+}
+
+void CSSStyleSheetImpl::addNamespace(CSSParser* p, const DOM::DOMString& prefix, const DOM::DOMString& uri)
+{
+ int exceptioncode = 0;
+ if (uri.isEmpty())
+ return;
+
+ m_namespaces = new CSSNamespace(prefix, uri, m_namespaces);
+
+ if (prefix.isEmpty()) {
+ Q_ASSERT(m_doc != 0);
+
+ m_defaultNamespace = m_doc->getId(NodeImpl::NamespaceId, uri.implementation(), false, false, &exceptioncode);
+ }
+}
+
+void CSSStyleSheetImpl::determineNamespace(TQ_UINT32& id, const DOM::DOMString& prefix)
+{
+ // If the stylesheet has no namespaces we can just return. There won't be any need to ever check
+ // namespace values in selectors.
+ if (!m_namespaces)
+ return;
+
+ if (prefix.isEmpty())
+ id = makeId(emptyNamespace, localNamePart(id)); // No namespace. If an element/attribute has a namespace, we won't match it.
+ else if (prefix == "*")
+ id = makeId(anyNamespace, localNamePart(id)); // We'll match any namespace.
+ else {
+ int exceptioncode = 0;
+ CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix);
+ if (ns) {
+ Q_ASSERT(m_doc != 0);
+
+ // Look up the id for this namespace URI.
+ TQ_UINT16 nsid = m_doc->getId(NodeImpl::NamespaceId, 0, 0, ns->uri().implementation(), false, false, &exceptioncode);
+ id = makeId(nsid, localNamePart(id));
+ }
+ }
+}
+
+bool CSSStyleSheetImpl::parseString(const DOMString &string, bool strict)
+{
+#ifdef CSS_STYLESHEET_DEBUG
+ kdDebug( 6080 ) << "parsing sheet, len=" << string.length() << ", sheet is " << string.string() << endl;
+#endif
+
+ strictParsing = strict;
+ CSSParser p( strict );
+ p.parseSheet( this, string );
+ return true;
+}
+
+bool CSSStyleSheetImpl::isLoading() const
+{
+ StyleBaseImpl *rule;
+ for ( rule = m_lstChildren->first(); rule != 0; rule = m_lstChildren->next() )
+ {
+ if(rule->isImportRule())
+ {
+ CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(rule);
+#ifdef CSS_STYLESHEET_DEBUG
+ kdDebug( 6080 ) << "found import" << endl;
+#endif
+ if(import->isLoading())
+ {
+#ifdef CSS_STYLESHEET_DEBUG
+ kdDebug( 6080 ) << "--> not loaded" << endl;
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void CSSStyleSheetImpl::checkLoaded() const
+{
+ if(isLoading()) return;
+ if(m_parent) m_parent->checkLoaded();
+ if(m_parentNode) m_parentNode->sheetLoaded();
+}
+
+void CSSStyleSheetImpl::setNonCSSHints()
+{
+ StyleBaseImpl *rule = m_lstChildren->first();
+ while(rule) {
+ if(rule->isStyleRule()) {
+ static_cast<CSSStyleRuleImpl *>(rule)->setNonCSSHints();
+ }
+ rule = m_lstChildren->next();
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+StyleSheetListImpl::~StyleSheetListImpl()
+{
+ for ( TQPtrListIterator<StyleSheetImpl> it ( styleSheets ); it.current(); ++it )
+ it.current()->deref();
+}
+
+void StyleSheetListImpl::add( StyleSheetImpl* s )
+{
+ if ( !styleSheets.containsRef( s ) ) {
+ s->ref();
+ styleSheets.append( s );
+ }
+}
+
+void StyleSheetListImpl::remove( StyleSheetImpl* s )
+{
+ if ( styleSheets.removeRef( s ) )
+ s->deref();
+}
+
+unsigned long StyleSheetListImpl::length() const
+{
+ // hack so implicit BODY stylesheets don't get counted here
+ unsigned long l = 0;
+ TQPtrListIterator<StyleSheetImpl> it(styleSheets);
+ for (; it.current(); ++it) {
+ if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit())
+ ++l;
+ }
+ return l;
+}
+
+StyleSheetImpl *StyleSheetListImpl::item ( unsigned long index )
+{
+ unsigned long l = 0;
+ TQPtrListIterator<StyleSheetImpl> it(styleSheets);
+ for (; it.current(); ++it) {
+ if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit()) {
+ if (l == index)
+ return it.current();
+ ++l;
+ }
+ }
+ return 0;
+}
+
+// --------------------------------------------------------------------------------------------
+
+MediaListImpl::MediaListImpl( CSSStyleSheetImpl *parentSheet,
+ const DOMString &media )
+ : StyleBaseImpl( parentSheet )
+{
+ setMediaText( media );
+}
+
+MediaListImpl::MediaListImpl( CSSRuleImpl *parentRule, const DOMString &media )
+ : StyleBaseImpl(parentRule)
+{
+ setMediaText( media );
+}
+
+bool MediaListImpl::contains( const DOMString &medium ) const
+{
+ return m_lstMedia.empty() || m_lstMedia.contains( medium ) ||
+ m_lstMedia.contains( "all" );
+}
+
+CSSStyleSheetImpl *MediaListImpl::parentStyleSheet() const
+{
+ if( m_parent->isCSSStyleSheet() ) return static_cast<CSSStyleSheetImpl *>(m_parent);
+ return 0;
+}
+
+CSSRuleImpl *MediaListImpl::parentRule() const
+{
+ if( m_parent->isRule() ) return static_cast<CSSRuleImpl *>(m_parent);
+ return 0;
+}
+
+void MediaListImpl::deleteMedium( const DOMString &oldMedium )
+{
+ const TQValueList<DOMString>::Iterator itEnd = m_lstMedia.end();
+
+ for ( TQValueList<DOMString>::Iterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
+ if( (*it) == oldMedium ) {
+ m_lstMedia.remove( it );
+ return;
+ }
+ }
+}
+
+DOM::DOMString MediaListImpl::mediaText() const
+{
+ DOMString text;
+ const TQValueList<DOMString>::ConstIterator itEnd = m_lstMedia.end();
+
+ for ( TQValueList<DOMString>::ConstIterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
+ text += *it;
+ text += ", ";
+ }
+ return text;
+}
+
+void MediaListImpl::setMediaText(const DOM::DOMString &value)
+{
+ m_lstMedia.clear();
+ const TQString val = value.string();
+ const TQStringList list = TQStringList::split( ',', val );
+
+ const TQStringList::ConstIterator itEnd = list.end();
+
+ for ( TQStringList::ConstIterator it = list.begin(); it != itEnd; ++it )
+ {
+ const DOMString medium = (*it).stripWhiteSpace();
+ if( !medium.isEmpty() )
+ m_lstMedia.append( medium );
+ }
+}
diff --git a/tdehtml/css/css_stylesheetimpl.h b/tdehtml/css/css_stylesheetimpl.h
new file mode 100644
index 000000000..8b59003ed
--- /dev/null
+++ b/tdehtml/css/css_stylesheetimpl.h
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2004 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 _CSS_css_stylesheetimpl_h_
+#define _CSS_css_stylesheetimpl_h_
+
+#include <tqvaluelist.h>
+#include <tqptrlist.h>
+
+#include "dom/dom_string.h"
+#include "css/css_base.h"
+#include "misc/loader_client.h"
+#include "xml/dom_docimpl.h"
+
+namespace tdehtml {
+ class CachedCSSStyleSheet;
+ class DocLoader;
+}
+
+namespace DOM {
+
+class StyleSheet;
+class CSSStyleSheet;
+class CSSParser;
+class MediaListImpl;
+class CSSRuleImpl;
+class CSSRuleList;
+class CSSStyleRuleImpl;
+class CSSValueImpl;
+class NodeImpl;
+class DocumentImpl;
+
+class StyleSheetImpl : public StyleListImpl
+{
+public:
+ StyleSheetImpl(DOM::NodeImpl *ownerNode, DOM::DOMString href = DOMString());
+ StyleSheetImpl(StyleSheetImpl *parentSheet, DOM::DOMString href = DOMString());
+ StyleSheetImpl(StyleBaseImpl *owner, DOM::DOMString href = DOMString());
+ StyleSheetImpl(tdehtml::CachedCSSStyleSheet *cached, DOM::DOMString href = DOMString());
+ virtual ~StyleSheetImpl();
+
+ virtual bool isStyleSheet() const { return true; }
+
+ virtual DOM::DOMString type() const { return DOMString(); }
+
+ bool disabled() const { return m_disabled; }
+ void setDisabled( bool disabled );
+ DOM::NodeImpl *ownerNode() const { return m_parentNode; }
+ StyleSheetImpl *parentStyleSheet() const;
+ DOM::DOMString href() const { return m_strHref; }
+ DOM::DOMString title() const { return m_strTitle; }
+ MediaListImpl *media() const { return m_media; }
+ void setMedia( MediaListImpl *media );
+
+protected:
+ DOM::NodeImpl *m_parentNode;
+ DOM::DOMString m_strHref;
+ DOM::DOMString m_strTitle;
+ MediaListImpl *m_media;
+ bool m_disabled;
+};
+
+class CSSStyleSheetImpl : public StyleSheetImpl
+{
+public:
+ CSSStyleSheetImpl(DOM::NodeImpl *parentNode, DOM::DOMString href = DOMString(), bool _implicit = false);
+ CSSStyleSheetImpl(CSSStyleSheetImpl *parentSheet, DOM::DOMString href = DOMString());
+ CSSStyleSheetImpl(CSSRuleImpl *ownerRule, DOM::DOMString href = DOMString());
+ // clone from a cached version of the sheet
+ CSSStyleSheetImpl(DOM::NodeImpl *parentNode, CSSStyleSheetImpl *orig);
+ CSSStyleSheetImpl(CSSRuleImpl *ownerRule, CSSStyleSheetImpl *orig);
+
+ ~CSSStyleSheetImpl() { delete m_namespaces; }
+
+ virtual bool isCSSStyleSheet() const { return true; }
+
+ virtual DOM::DOMString type() const { return "text/css"; }
+
+ CSSRuleImpl *ownerRule() const;
+ CSSRuleList cssRules();
+ unsigned long insertRule ( const DOM::DOMString &rule, unsigned long index, int &exceptioncode );
+ void deleteRule ( unsigned long index, int &exceptioncode );
+
+ void addNamespace(CSSParser* p, const DOM::DOMString& prefix, const DOM::DOMString& uri);
+ void determineNamespace(TQ_UINT32& id, const DOM::DOMString& prefix);
+ TQ_UINT32 defaultNamespace() { return m_defaultNamespace; };
+
+ void setCharset(const DOMString &charset) { m_charset = charset; }
+ const DOMString& charset() const { return m_charset; }
+
+ virtual bool parseString( const DOMString &string, bool strict = true );
+
+ bool isLoading() const;
+ void setNonCSSHints();
+
+ virtual void checkLoaded() const;
+
+ // ### remove? (clients should use sheet->doc()->docLoader())
+ tdehtml::DocLoader *docLoader() const
+ { return m_doc ? m_doc->docLoader() : 0; }
+
+ DocumentImpl *doc() const { return m_doc; }
+ bool implicit() const { return m_implicit; }
+protected:
+ DocumentImpl *m_doc;
+ bool m_implicit;
+ TQ_UINT32 m_defaultNamespace;
+ CSSNamespace* m_namespaces;
+ DOMString m_charset;
+};
+
+// ----------------------------------------------------------------------------
+
+class StyleSheetListImpl : public tdehtml::Shared<StyleSheetListImpl>
+{
+public:
+ StyleSheetListImpl() {}
+ ~StyleSheetListImpl();
+
+ // the following two ignore implicit stylesheets
+ unsigned long length() const;
+ StyleSheetImpl *item ( unsigned long index );
+
+ void add(StyleSheetImpl* s);
+ void remove(StyleSheetImpl* s);
+
+ TQPtrList<StyleSheetImpl> styleSheets;
+};
+
+// ----------------------------------------------------------------------------
+
+class MediaListImpl : public StyleBaseImpl
+{
+public:
+ MediaListImpl()
+ : StyleBaseImpl( 0 ) {}
+ MediaListImpl( CSSStyleSheetImpl *parentSheet )
+ : StyleBaseImpl(parentSheet) {}
+ MediaListImpl( CSSStyleSheetImpl *parentSheet,
+ const DOM::DOMString &media );
+ MediaListImpl( CSSRuleImpl *parentRule, const DOM::DOMString &media );
+
+ virtual bool isMediaList() const { return true; }
+
+ CSSStyleSheetImpl *parentStyleSheet() const;
+ CSSRuleImpl *parentRule() const;
+ unsigned long length() const { return m_lstMedia.count(); }
+ DOM::DOMString item ( unsigned long index ) const { return m_lstMedia[index]; }
+ void deleteMedium ( const DOM::DOMString &oldMedium );
+ void appendMedium ( const DOM::DOMString &newMedium ) { m_lstMedia.append(newMedium); }
+
+ DOM::DOMString mediaText() const;
+ void setMediaText(const DOM::DOMString &value);
+
+ /**
+ * Check if the list contains either the requested medium, or the
+ * catch-all "all" media type. Returns true when found, false otherwise.
+ * Since not specifying media types should be treated as "all" according
+ * to DOM specs, an empty list always returns true.
+ *
+ * _NOT_ part of the DOM!
+ */
+ bool contains( const DOM::DOMString &medium ) const;
+
+protected:
+ TQValueList<DOM::DOMString> m_lstMedia;
+};
+
+
+} // namespace
+
+#endif
+
diff --git a/tdehtml/css/css_valueimpl.cpp b/tdehtml/css/css_valueimpl.cpp
new file mode 100644
index 000000000..0da65c4b6
--- /dev/null
+++ b/tdehtml/css/css_valueimpl.cpp
@@ -0,0 +1,1073 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * (C) 2005 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.
+ */
+
+#include "dom/css_value.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_string.h"
+
+#include "css/css_valueimpl.h"
+#include "css/css_ruleimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/cssparser.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+
+#include "xml/dom_stringimpl.h"
+#include "xml/dom_docimpl.h"
+
+#include "misc/loader.h"
+
+#include "rendering/font.h"
+#include "rendering/render_style.h"
+
+#include <kdebug.h>
+#include <tqregexp.h>
+#include <tqpaintdevice.h>
+#include <tqpaintdevicemetrics.h>
+
+// Hack for debugging purposes
+extern DOM::DOMString getPropertyName(unsigned short id);
+
+using tdehtml::FontDef;
+
+using namespace DOM;
+
+// Quotes the string if it needs quoting.
+static DOMString quoteStringIfNeeded(const DOMString &string)
+{
+ // FIXME: Also need to transform control characters into \ sequences.
+ TQString s = string.string();
+ s.replace('\\', "\\\\");
+ s.replace('\'', "\\'");
+ return '\'' + s + '\'';
+}
+
+
+CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent)
+ : StyleBaseImpl(parent)
+{
+ m_lstValues = 0;
+ m_node = 0;
+}
+
+CSSStyleDeclarationImpl::CSSStyleDeclarationImpl(CSSRuleImpl *parent, TQPtrList<CSSProperty> *lstValues)
+ : StyleBaseImpl(parent)
+{
+ m_lstValues = lstValues;
+ m_node = 0;
+}
+
+CSSStyleDeclarationImpl& CSSStyleDeclarationImpl::operator= (const CSSStyleDeclarationImpl& o)
+{
+ // don't attach it to the same node, just leave the current m_node value
+ delete m_lstValues;
+ m_lstValues = 0;
+ if (o.m_lstValues) {
+ m_lstValues = new TQPtrList<CSSProperty>;
+ m_lstValues->setAutoDelete( true );
+
+ TQPtrListIterator<CSSProperty> lstValuesIt(*o.m_lstValues);
+ for (lstValuesIt.toFirst(); lstValuesIt.current(); ++lstValuesIt)
+ m_lstValues->append(new CSSProperty(*lstValuesIt.current()));
+ }
+
+ return *this;
+}
+
+CSSStyleDeclarationImpl::~CSSStyleDeclarationImpl()
+{
+ delete m_lstValues;
+ // we don't use refcounting for m_node, to avoid cyclic references (see ElementImpl)
+}
+
+DOMString CSSStyleDeclarationImpl::getPropertyValue( int propertyID ) const
+{
+ if(!m_lstValues) return DOMString();
+ CSSValueImpl* value = getPropertyCSSValue( propertyID );
+ if ( value )
+ return value->cssText();
+
+ // Shorthand and 4-values properties
+ switch ( propertyID ) {
+ case CSS_PROP_BACKGROUND_POSITION:
+ {
+ // ## Is this correct? The code in cssparser.cpp is confusing
+ const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X,
+ CSS_PROP_BACKGROUND_POSITION_Y };
+ return getShortHandValue( properties, 2 );
+ }
+ case CSS_PROP_BACKGROUND:
+ {
+ const int properties[5] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
+ CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION,
+ CSS_PROP_BACKGROUND_COLOR };
+ return getShortHandValue( properties, 5 );
+ }
+ case CSS_PROP_BORDER:
+ {
+ const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
+ CSS_PROP_BORDER_COLOR };
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_BORDER_TOP:
+ {
+ const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
+ CSS_PROP_BORDER_TOP_COLOR};
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_BORDER_RIGHT:
+ {
+ const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
+ CSS_PROP_BORDER_RIGHT_COLOR};
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_BORDER_BOTTOM:
+ {
+ const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
+ CSS_PROP_BORDER_BOTTOM_COLOR};
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_BORDER_LEFT:
+ {
+ const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
+ CSS_PROP_BORDER_LEFT_COLOR};
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_OUTLINE:
+ {
+ const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
+ CSS_PROP_OUTLINE_COLOR };
+ return getShortHandValue( properties, 3 );
+ }
+ case CSS_PROP_BORDER_COLOR:
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
+ CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
+ return get4Values( properties );
+ }
+ case CSS_PROP_BORDER_WIDTH:
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
+ CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
+ return get4Values( properties );
+ }
+ case CSS_PROP_BORDER_STYLE:
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
+ CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
+ return get4Values( properties );
+ }
+ case CSS_PROP_MARGIN:
+ {
+ const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
+ CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
+ return get4Values( properties );
+ }
+ case CSS_PROP_PADDING:
+ {
+ const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
+ CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
+ return get4Values( properties );
+ }
+ case CSS_PROP_LIST_STYLE:
+ {
+ const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
+ CSS_PROP_LIST_STYLE_IMAGE };
+ return getShortHandValue( properties, 3 );
+ }
+ }
+ //kdDebug() << k_funcinfo << "property not found:" << propertyID << endl;
+ return DOMString();
+}
+
+DOMString CSSStyleDeclarationImpl::get4Values( const int* properties ) const
+{
+ DOMString res;
+ for ( int i = 0 ; i < 4 ; ++i ) {
+ CSSValueImpl* value = getPropertyCSSValue( properties[i] );
+ if ( !value ) { // apparently all 4 properties must be specified.
+ return DOMString();
+ }
+ if ( i > 0 )
+ res += " ";
+ res += value->cssText();
+ }
+ return res;
+}
+
+DOMString CSSStyleDeclarationImpl::getShortHandValue( const int* properties, int number ) const
+{
+ DOMString res;
+ for ( int i = 0 ; i < number ; ++i ) {
+ CSSValueImpl* value = getPropertyCSSValue( properties[i] );
+ if ( value ) { // TODO provide default value if !value
+ if ( !res.isNull() )
+ res += " ";
+ res += value->cssText();
+ }
+ }
+ return res;
+}
+
+ CSSValueImpl *CSSStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const
+{
+ if(!m_lstValues) return 0;
+
+ TQPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
+ CSSProperty *current;
+ for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt )
+ if (current->m_id == propertyID && !current->nonCSSHint)
+ return current->value();
+ return 0;
+}
+
+DOMString CSSStyleDeclarationImpl::removeProperty( int propertyID, bool NonCSSHint )
+{
+ if(!m_lstValues) return DOMString();
+ DOMString value;
+
+ TQPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
+ CSSProperty *current;
+ for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt ) {
+ if (current->m_id == propertyID && NonCSSHint == current->nonCSSHint) {
+ value = current->value()->cssText();
+ m_lstValues->removeRef(current);
+ setChanged();
+ break;
+ }
+ }
+
+ return value;
+}
+
+void CSSStyleDeclarationImpl::setChanged()
+{
+ if (m_node) {
+ m_node->setChanged();
+ return;
+ }
+
+ // ### quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk)
+ for (StyleBaseImpl* stylesheet = this; stylesheet; stylesheet = stylesheet->parent())
+ if (stylesheet->isCSSStyleSheet()) {
+ static_cast<CSSStyleSheetImpl*>(stylesheet)->doc()->updateStyleSelector();
+ break;
+ }
+}
+
+void CSSStyleDeclarationImpl::removeCSSHints()
+{
+ if (!m_lstValues)
+ return;
+
+ for (int i = (int)m_lstValues->count()-1; i >= 0; i--) {
+ if (!m_lstValues->at(i)->nonCSSHint)
+ m_lstValues->remove(i);
+ }
+}
+
+bool CSSStyleDeclarationImpl::getPropertyPriority( int propertyID ) const
+{
+ if ( m_lstValues) {
+ TQPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
+ CSSProperty *current;
+ for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
+ if( propertyID == current->m_id )
+ return current->m_important;
+ }
+ }
+ return false;
+}
+
+bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool nonCSSHint)
+{
+ if(!m_lstValues) {
+ m_lstValues = new TQPtrList<CSSProperty>;
+ m_lstValues->setAutoDelete(true);
+ }
+
+ CSSParser parser( strictParsing );
+ bool success = parser.parseValue( this, id, value, important, nonCSSHint );
+ if(!success)
+ kdDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string()
+ << "] value: [" << value.string() << "]"<< endl;
+ else
+ setChanged();
+ return success;
+}
+
+void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool nonCSSHint)
+{
+ if(!m_lstValues) {
+ m_lstValues = new TQPtrList<CSSProperty>;
+ m_lstValues->setAutoDelete(true);
+ }
+ removeProperty(id, nonCSSHint );
+
+ CSSValueImpl * cssValue = new CSSPrimitiveValueImpl(value);
+ setParsedValue(id, cssValue, important, nonCSSHint, m_lstValues);
+ setChanged();
+}
+
+void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint, bool _multiLength )
+{
+ bool parseMode = strictParsing;
+ strictParsing = false;
+ multiLength = _multiLength;
+ setProperty( id, value, important, nonCSSHint);
+ strictParsing = parseMode;
+ multiLength = false;
+}
+
+void CSSStyleDeclarationImpl::setProperty ( const DOMString &propertyString)
+{
+ if(!m_lstValues) {
+ m_lstValues = new TQPtrList<CSSProperty>;
+ m_lstValues->setAutoDelete( true );
+ }
+
+ CSSParser parser( strictParsing );
+ parser.parseDeclaration( this, propertyString, false );
+ setChanged();
+}
+
+unsigned long CSSStyleDeclarationImpl::length() const
+{
+ return m_lstValues ? m_lstValues->count() : 0;
+}
+
+DOMString CSSStyleDeclarationImpl::item( unsigned long index ) const
+{
+ if(m_lstValues && index < m_lstValues->count() && m_lstValues->at(index))
+ return getPropertyName(m_lstValues->at(index)->m_id);
+ return DOMString();
+}
+
+CSSRuleImpl *CSSStyleDeclarationImpl::parentRule() const
+{
+ return (m_parent && m_parent->isRule() ) ?
+ static_cast<CSSRuleImpl *>(m_parent) : 0;
+}
+
+DOM::DOMString CSSStyleDeclarationImpl::cssText() const
+{
+ DOMString result;
+
+ if ( m_lstValues) {
+ TQPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
+ CSSProperty *current;
+ for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
+ result += current->cssText();
+ }
+ }
+
+ return result;
+}
+
+void CSSStyleDeclarationImpl::setCssText(DOM::DOMString text)
+{
+ if (m_lstValues) {
+ m_lstValues->clear();
+ } else {
+ m_lstValues = new TQPtrList<CSSProperty>;
+ m_lstValues->setAutoDelete( true );
+ }
+
+ CSSParser parser( strictParsing );
+ parser.parseDeclaration( this, text, false );
+ setChanged();
+}
+
+bool CSSStyleDeclarationImpl::parseString( const DOMString &/*string*/, bool )
+{
+ kdDebug() << "WARNING: CSSStyleDeclarationImpl::parseString, unimplemented, was called" << endl;
+ return false;
+ // ###
+}
+
+
+// --------------------------------------------------------------------------------------
+
+unsigned short CSSInheritedValueImpl::cssValueType() const
+{
+ return CSSValue::CSS_INHERIT;
+}
+
+DOM::DOMString CSSInheritedValueImpl::cssText() const
+{
+ return DOMString("inherit");
+}
+
+unsigned short CSSInitialValueImpl::cssValueType() const
+{
+ return CSSValue::CSS_INITIAL;
+}
+
+DOM::DOMString CSSInitialValueImpl::cssText() const
+{
+ return DOMString("initial");
+}
+
+// ----------------------------------------------------------------------------------------
+
+CSSValueListImpl::~CSSValueListImpl()
+{
+ CSSValueImpl *val = m_values.first();
+ while( val ) {
+ val->deref();
+ val = m_values.next();
+ }
+}
+
+unsigned short CSSValueListImpl::cssValueType() const
+{
+ return CSSValue::CSS_VALUE_LIST;
+}
+
+void CSSValueListImpl::append(CSSValueImpl *val)
+{
+ m_values.append(val);
+ val->ref();
+}
+
+DOM::DOMString CSSValueListImpl::cssText() const
+{
+ DOMString result = "";
+
+ for (TQPtrListIterator<CSSValueImpl> iterator(m_values); iterator.current(); ++iterator) {
+ result += iterator.current()->cssText();
+ }
+
+ return result;
+}
+
+// -------------------------------------------------------------------------------------
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl()
+ : CSSValueImpl()
+{
+ m_type = 0;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(int ident)
+ : CSSValueImpl()
+{
+ m_value.ident = ident;
+ m_type = CSSPrimitiveValue::CSS_IDENT;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type)
+{
+ m_value.num = num;
+ m_type = type;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type)
+{
+ m_value.string = str.implementation();
+ if(m_value.string) m_value.string->ref();
+ m_type = type;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(CounterImpl *c)
+{
+ m_value.counter = c;
+ if (m_value.counter)
+ m_value.counter->ref();
+ m_type = CSSPrimitiveValue::CSS_COUNTER;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl( RectImpl *r)
+{
+ m_value.rect = r;
+ if (m_value.rect)
+ m_value.rect->ref();
+ m_type = CSSPrimitiveValue::CSS_RECT;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(QRgb color)
+{
+ m_value.rgbcolor = color;
+ m_type = CSSPrimitiveValue::CSS_RGBCOLOR;
+}
+
+CSSPrimitiveValueImpl::CSSPrimitiveValueImpl(PairImpl *p)
+{
+ m_value.pair = p;
+ if (m_value.pair)
+ m_value.pair->ref();
+ m_type = CSSPrimitiveValue::CSS_PAIR;
+}
+
+
+CSSPrimitiveValueImpl::~CSSPrimitiveValueImpl()
+{
+ cleanup();
+}
+
+void CSSPrimitiveValueImpl::cleanup()
+{
+ switch(m_type) {
+ case CSSPrimitiveValue::CSS_STRING:
+ case CSSPrimitiveValue::CSS_URI:
+ case CSSPrimitiveValue::CSS_ATTR:
+ if(m_value.string) m_value.string->deref();
+ break;
+ case CSSPrimitiveValue::CSS_COUNTER:
+ m_value.counter->deref();
+ break;
+ case CSSPrimitiveValue::CSS_RECT:
+ m_value.rect->deref();
+ break;
+ case CSSPrimitiveValue::CSS_PAIR:
+ m_value.pair->deref();
+ break;
+ default:
+ break;
+ }
+
+ m_type = 0;
+}
+
+int CSSPrimitiveValueImpl::computeLength( tdehtml::RenderStyle *style, TQPaintDeviceMetrics *devMetrics )
+{
+ double result = computeLengthFloat( style, devMetrics );
+ // This conversion is imprecise, often resulting in values of, e.g., 44.99998. We
+ // need to go ahead and round if we're really close to the next integer value.
+ int intResult = (int)(result + (result < 0 ? -0.01 : +0.01));
+ return intResult;
+}
+
+double CSSPrimitiveValueImpl::computeLengthFloat( tdehtml::RenderStyle *style, TQPaintDeviceMetrics *devMetrics )
+{
+ unsigned short type = primitiveType();
+
+ double dpiY = 72.; // fallback
+ if ( devMetrics )
+ dpiY = devMetrics->logicalDpiY();
+ if ( !tdehtml::printpainter && dpiY < 96 )
+ dpiY = 96.;
+
+ double factor = 1.;
+ switch(type)
+ {
+ case CSSPrimitiveValue::CSS_EMS:
+ factor = style->font().pixelSize();
+ break;
+ case CSSPrimitiveValue::CSS_EXS:
+ {
+ TQFontMetrics fm = style->fontMetrics();
+#ifdef APPLE_CHANGES
+ factor = fm.xHeight();
+#else
+ TQRect b = fm.boundingRect('x');
+ factor = b.height();
+#endif
+ break;
+ }
+ case CSSPrimitiveValue::CSS_PX:
+ break;
+ case CSSPrimitiveValue::CSS_CM:
+ factor = dpiY/2.54; //72dpi/(2.54 cm/in)
+ break;
+ case CSSPrimitiveValue::CSS_MM:
+ factor = dpiY/25.4;
+ break;
+ case CSSPrimitiveValue::CSS_IN:
+ factor = dpiY;
+ break;
+ case CSSPrimitiveValue::CSS_PT:
+ factor = dpiY/72.;
+ break;
+ case CSSPrimitiveValue::CSS_PC:
+ // 1 pc == 12 pt
+ factor = dpiY*12./72.;
+ break;
+ default:
+ return -1;
+ }
+
+ return floatValue(type)*factor;
+}
+
+void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode )
+{
+ exceptioncode = 0;
+ cleanup();
+ // ### check if property supports this type
+ if(m_type > CSSPrimitiveValue::CSS_DIMENSION) {
+ exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
+ return;
+ }
+ //if(m_type > CSSPrimitiveValue::CSS_DIMENSION) throw DOMException(DOMException::INVALID_ACCESS_ERR);
+ m_value.num = floatValue;
+ m_type = unitType;
+}
+
+void CSSPrimitiveValueImpl::setStringValue( unsigned short stringType, const DOMString &stringValue, int &exceptioncode )
+{
+ exceptioncode = 0;
+ cleanup();
+ //if(m_type < CSSPrimitiveValue::CSS_STRING) throw DOMException(DOMException::INVALID_ACCESS_ERR);
+ //if(m_type > CSSPrimitiveValue::CSS_ATTR) throw DOMException(DOMException::INVALID_ACCESS_ERR);
+ if(m_type < CSSPrimitiveValue::CSS_STRING || m_type > CSSPrimitiveValue::CSS_ATTR) {
+ exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
+ return;
+ }
+ if(stringType != CSSPrimitiveValue::CSS_IDENT)
+ {
+ m_value.string = stringValue.implementation();
+ m_value.string->ref();
+ m_type = stringType;
+ }
+ // ### parse ident
+}
+
+unsigned short CSSPrimitiveValueImpl::cssValueType() const
+{
+ return CSSValue::CSS_PRIMITIVE_VALUE;
+}
+
+bool CSSPrimitiveValueImpl::parseString( const DOMString &/*string*/, bool )
+{
+ // ###
+ kdDebug() << "WARNING: CSSPrimitiveValueImpl::parseString, unimplemented, was called" << endl;
+ return false;
+}
+
+int CSSPrimitiveValueImpl::getIdent()
+{
+ if(m_type != CSSPrimitiveValue::CSS_IDENT) return 0;
+ return m_value.ident;
+}
+
+DOM::DOMString CSSPrimitiveValueImpl::cssText() const
+{
+ // ### return the original value instead of a generated one (e.g. color
+ // name if it was specified) - check what spec says about this
+ DOMString text;
+ switch ( m_type ) {
+ case CSSPrimitiveValue::CSS_UNKNOWN:
+ // ###
+ break;
+ case CSSPrimitiveValue::CSS_NUMBER:
+ text = DOMString(TQString::number( (int)m_value.num ));
+ break;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ text = DOMString(TQString::number( m_value.num ) + "%");
+ break;
+ case CSSPrimitiveValue::CSS_EMS:
+ text = DOMString(TQString::number( m_value.num ) + "em");
+ break;
+ case CSSPrimitiveValue::CSS_EXS:
+ text = DOMString(TQString::number( m_value.num ) + "ex");
+ break;
+ case CSSPrimitiveValue::CSS_PX:
+ text = DOMString(TQString::number( m_value.num ) + "px");
+ break;
+ case CSSPrimitiveValue::CSS_CM:
+ text = DOMString(TQString::number( m_value.num ) + "cm");
+ break;
+ case CSSPrimitiveValue::CSS_MM:
+ text = DOMString(TQString::number( m_value.num ) + "mm");
+ break;
+ case CSSPrimitiveValue::CSS_IN:
+ text = DOMString(TQString::number( m_value.num ) + "in");
+ break;
+ case CSSPrimitiveValue::CSS_PT:
+ text = DOMString(TQString::number( m_value.num ) + "pt");
+ break;
+ case CSSPrimitiveValue::CSS_PC:
+ text = DOMString(TQString::number( m_value.num ) + "pc");
+ break;
+ case CSSPrimitiveValue::CSS_DEG:
+ text = DOMString(TQString::number( m_value.num ) + "deg");
+ break;
+ case CSSPrimitiveValue::CSS_RAD:
+ text = DOMString(TQString::number( m_value.num ) + "rad");
+ break;
+ case CSSPrimitiveValue::CSS_GRAD:
+ text = DOMString(TQString::number( m_value.num ) + "grad");
+ break;
+ case CSSPrimitiveValue::CSS_MS:
+ text = DOMString(TQString::number( m_value.num ) + "ms");
+ break;
+ case CSSPrimitiveValue::CSS_S:
+ text = DOMString(TQString::number( m_value.num ) + "s");
+ break;
+ case CSSPrimitiveValue::CSS_HZ:
+ text = DOMString(TQString::number( m_value.num ) + "hz");
+ break;
+ case CSSPrimitiveValue::CSS_KHZ:
+ text = DOMString(TQString::number( m_value.num ) + "khz");
+ break;
+ case CSSPrimitiveValue::CSS_DIMENSION:
+ // ###
+ break;
+ case CSSPrimitiveValue::CSS_STRING:
+ text = quoteStringIfNeeded(m_value.string);
+ break;
+ case CSSPrimitiveValue::CSS_URI:
+ text = "url(";
+ text += DOMString( m_value.string );
+ text += ")";
+ break;
+ case CSSPrimitiveValue::CSS_IDENT:
+ text = getValueName(m_value.ident);
+ break;
+ case CSSPrimitiveValue::CSS_ATTR:
+ text = "attr(";
+ text += DOMString( m_value.string );
+ text += ")";
+ break;
+ case CSSPrimitiveValue::CSS_COUNTER:
+ text = "counter(";
+ text += m_value.counter->m_identifier;
+ text += ")";
+ // ### add list-style and separator
+ break;
+ case CSSPrimitiveValue::CSS_RECT:
+ {
+ RectImpl* rectVal = getRectValue();
+ text = "rect(";
+ text += rectVal->top()->cssText() + " ";
+ text += rectVal->right()->cssText() + " ";
+ text += rectVal->bottom()->cssText() + " ";
+ text += rectVal->left()->cssText() + ")";
+ break;
+ }
+ case CSSPrimitiveValue::CSS_RGBCOLOR:
+ if (tqAlpha(m_value.rgbcolor) != 0xFF) {
+ if (m_value.rgbcolor == tdehtml::transparentColor)
+ text = "transparent";
+ else
+ text = "rgba(" + TQString::number(tqRed (m_value.rgbcolor)) + ","
+ + TQString::number(tqBlue (m_value.rgbcolor)) + ","
+ + TQString::number(tqGreen(m_value.rgbcolor)) + ","
+ + TQString::number(tqAlpha(m_value.rgbcolor)/255.0) + ")";
+ } else {
+ text = TQString(TQColor(m_value.rgbcolor).name());
+ }
+ break;
+ case CSSPrimitiveValue::CSS_PAIR:
+ text = m_value.pair->first()->cssText();
+ text += " ";
+ text += m_value.pair->second()->cssText();
+ break;
+ default:
+ break;
+ }
+ return text;
+}
+
+// -----------------------------------------------------------------
+
+RectImpl::RectImpl()
+{
+ m_top = 0;
+ m_right = 0;
+ m_bottom = 0;
+ m_left = 0;
+}
+
+RectImpl::~RectImpl()
+{
+ if (m_top) m_top->deref();
+ if (m_right) m_right->deref();
+ if (m_bottom) m_bottom->deref();
+ if (m_left) m_left->deref();
+}
+
+void RectImpl::setTop( CSSPrimitiveValueImpl *top )
+{
+ if( top ) top->ref();
+ if ( m_top ) m_top->deref();
+ m_top = top;
+}
+
+void RectImpl::setRight( CSSPrimitiveValueImpl *right )
+{
+ if( right ) right->ref();
+ if ( m_right ) m_right->deref();
+ m_right = right;
+}
+
+void RectImpl::setBottom( CSSPrimitiveValueImpl *bottom )
+{
+ if( bottom ) bottom->ref();
+ if ( m_bottom ) m_bottom->deref();
+ m_bottom = bottom;
+}
+
+void RectImpl::setLeft( CSSPrimitiveValueImpl *left )
+{
+ if( left ) left->ref();
+ if ( m_left ) m_left->deref();
+ m_left = left;
+}
+
+// -----------------------------------------------------------------
+
+PairImpl::~PairImpl()
+{
+ if (m_first) m_first->deref(); if (m_second) m_second->deref();
+}
+
+void PairImpl::setFirst(CSSPrimitiveValueImpl* first)
+{
+ if (first == m_first) return;
+ if (m_first) m_first->deref();
+ m_first = first;
+ if (m_first) m_first->ref();
+}
+
+void PairImpl::setSecond(CSSPrimitiveValueImpl* second)
+{
+ if (second == m_second) return;
+ if (m_second) m_second->deref();
+ m_second = second;
+ if (m_second) m_second->ref();
+}
+
+// -----------------------------------------------------------------
+
+CSSImageValueImpl::CSSImageValueImpl(const DOMString &url, const StyleBaseImpl* style)
+ : CSSPrimitiveValueImpl(url, CSSPrimitiveValue::CSS_URI)
+{
+ tdehtml::DocLoader *docLoader = 0;
+ const StyleBaseImpl *root = style;
+ while (root->parent())
+ root = root->parent();
+ if (root->isCSSStyleSheet())
+ docLoader = static_cast<const CSSStyleSheetImpl*>(root)->docLoader();
+
+ m_image = docLoader->requestImage(url);
+ if(m_image) m_image->ref(this);
+}
+
+CSSImageValueImpl::CSSImageValueImpl()
+ : CSSPrimitiveValueImpl(CSS_VAL_NONE)
+{
+ m_image = 0;
+}
+
+CSSImageValueImpl::~CSSImageValueImpl()
+{
+ if(m_image) m_image->deref(this);
+}
+
+// ------------------------------------------------------------------------
+
+FontFamilyValueImpl::FontFamilyValueImpl( const TQString &string)
+: CSSPrimitiveValueImpl( DOMString(string), CSSPrimitiveValue::CSS_STRING)
+{
+ static const TQRegExp parenReg(" \\(.*\\)$");
+ static const TQRegExp braceReg(" \\[.*\\]$");
+
+ parsedFontName = string;
+ // a language tag is often added in braces at the end. Remove it.
+ parsedFontName.replace(parenReg, TQString());
+ // remove [Xft] qualifiers
+ parsedFontName.replace(braceReg, TQString());
+
+#ifndef APPLE_CHANGES
+ const TQString &available = KHTMLSettings::availableFamilies();
+
+ parsedFontName = parsedFontName.lower();
+ // kdDebug(0) << "searching for face '" << parsedFontName << "'" << endl;
+
+ int pos = available.find( ',' + parsedFontName + ',', 0, false );
+ if ( pos == -1 ) {
+ // many pages add extra MSs to make sure it's windows only ;(
+ if ( parsedFontName.startsWith( "ms " ) )
+ parsedFontName = parsedFontName.mid( 3 );
+ if ( parsedFontName.endsWith( " ms" ) )
+ parsedFontName.truncate( parsedFontName.length() - 3 );
+ pos = available.find( ",ms " + parsedFontName + ',', 0, false );
+ if ( pos == -1 )
+ pos = available.find( ',' + parsedFontName + " ms,", 0, false );
+ }
+
+ if ( pos != -1 ) {
+ ++pos;
+ int p = available.find(',', pos);
+ assert( p != -1 ); // available is supposed to start and end with ,
+ parsedFontName = available.mid( pos, p - pos);
+ // kdDebug(0) << "going for '" << parsedFontName << "'" << endl;
+ } else
+ parsedFontName = TQString::null;
+
+#endif // !APPLE_CHANGES
+}
+
+FontValueImpl::FontValueImpl()
+ : style(0), variant(0), weight(0), size(0), lineHeight(0), family(0)
+{
+}
+
+FontValueImpl::~FontValueImpl()
+{
+ delete style;
+ delete variant;
+ delete weight;
+ delete size;
+ delete lineHeight;
+ delete family;
+}
+
+DOMString FontValueImpl::cssText() const
+{
+ // font variant weight size / line-height family
+
+ DOMString result("");
+
+ if (style) {
+ result += style->cssText();
+ }
+ if (variant) {
+ if (result.length() > 0) {
+ result += " ";
+ }
+ result += variant->cssText();
+ }
+ if (weight) {
+ if (result.length() > 0) {
+ result += " ";
+ }
+ result += weight->cssText();
+ }
+ if (size) {
+ if (result.length() > 0) {
+ result += " ";
+ }
+ result += size->cssText();
+ }
+ if (lineHeight) {
+ if (!size) {
+ result += " ";
+ }
+ result += "/";
+ result += lineHeight->cssText();
+ }
+ if (family) {
+ if (result.length() > 0) {
+ result += " ";
+ }
+ result += family->cssText();
+ }
+
+ return result;
+}
+
+QuotesValueImpl::QuotesValueImpl()
+ : levels(0)
+{
+}
+
+DOMString QuotesValueImpl::cssText() const
+{
+ return "\"" + data.join("\" \"") + "\"";
+}
+
+void QuotesValueImpl::addLevel(const TQString& open, const TQString& close)
+{
+ data.append(open);
+ data.append(close);
+ levels++;
+}
+
+TQString QuotesValueImpl::openQuote(int level) const
+{
+ if (levels == 0) return "";
+ level--; // increments are calculated before openQuote is called
+// kdDebug( 6080 ) << "Open quote level:" << level << endl;
+ if (level < 0) level = 0;
+ else
+ if (level >= (int) levels) level = (int) (levels-1);
+ return data[level*2];
+}
+
+TQString QuotesValueImpl::closeQuote(int level) const
+{
+ if (levels == 0) return "";
+// kdDebug( 6080 ) << "Close quote level:" << level << endl;
+ if (level < 0) level = 0;
+ else
+ if (level >= (int) levels) level = (int) (levels-1);
+ return data[level*2+1];
+}
+
+// Used for text-shadow and box-shadow
+ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y,
+ CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color)
+ :x(_x), y(_y), blur(_blur), color(_color)
+{}
+
+ShadowValueImpl::~ShadowValueImpl()
+{
+ delete x;
+ delete y;
+ delete blur;
+ delete color;
+}
+
+DOMString ShadowValueImpl::cssText() const
+{
+ DOMString text("");
+ if (color) {
+ text += color->cssText();
+ }
+ if (x) {
+ if (text.length() > 0) {
+ text += " ";
+ }
+ text += x->cssText();
+ }
+ if (y) {
+ if (text.length() > 0) {
+ text += " ";
+ }
+ text += y->cssText();
+ }
+ if (blur) {
+ if (text.length() > 0) {
+ text += " ";
+ }
+ text += blur->cssText();
+ }
+
+ return text;
+}
+
+DOMString CounterActImpl::cssText() const
+{
+ DOMString text(m_counter);
+ text += DOMString(TQString::number(m_value));
+
+ return text;
+}
+
+DOMString CSSProperty::cssText() const
+{
+ return getPropertyName(m_id) + DOMString(": ") + m_value->cssText() + (m_important ? DOMString(" !important") : DOMString()) + DOMString("; ");
+}
diff --git a/tdehtml/css/css_valueimpl.h b/tdehtml/css/css_valueimpl.h
new file mode 100644
index 000000000..9a6203c86
--- /dev/null
+++ b/tdehtml/css/css_valueimpl.h
@@ -0,0 +1,461 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * (C) 2005 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.
+ *
+ */
+#ifndef _CSS_css_valueimpl_h_
+#define _CSS_css_valueimpl_h_
+
+#include "dom/css_value.h"
+#include "dom/dom_string.h"
+#include "css/css_base.h"
+#include "misc/loader_client.h"
+#include "misc/shared.h"
+
+#include <tqintdict.h>
+
+namespace tdehtml {
+ class RenderStyle;
+ class CachedImage;
+}
+
+
+namespace DOM {
+
+class CSSRuleImpl;
+class CSSValueImpl;
+class NodeImpl;
+class CounterImpl;
+class PairImpl;
+
+
+class CSSStyleDeclarationImpl : public StyleBaseImpl
+{
+public:
+ CSSStyleDeclarationImpl(CSSRuleImpl *parentRule);
+ CSSStyleDeclarationImpl(CSSRuleImpl *parentRule, TQPtrList<CSSProperty> *lstValues);
+ virtual ~CSSStyleDeclarationImpl();
+
+ CSSStyleDeclarationImpl& operator=( const CSSStyleDeclarationImpl&);
+
+ virtual unsigned long length() const;
+ CSSRuleImpl *parentRule() const;
+ virtual DOM::DOMString removeProperty( int propertyID, bool NonCSSHints = false );
+ virtual bool setProperty ( int propertyId, const DOM::DOMString &value, bool important = false, bool nonCSSHint = false);
+ virtual void setProperty ( int propertyId, int value, bool important = false, bool nonCSSHint = false);
+ // this treats integers as pixels!
+ // needed for conversion of html attributes
+ virtual void setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint = true, bool multiLength = false);
+
+ // add a whole, unparsed property
+ virtual void setProperty ( const DOMString &propertyString);
+ virtual DOM::DOMString item ( unsigned long index ) const;
+
+ DOM::DOMString cssText() const;
+ void setCssText(DOM::DOMString str);
+
+ virtual bool isStyleDeclaration() const { return true; }
+ virtual bool parseString( const DOMString &string, bool = false );
+
+ virtual CSSValueImpl *getPropertyCSSValue( int propertyID ) const;
+ virtual DOMString getPropertyValue( int propertyID ) const;
+ virtual bool getPropertyPriority( int propertyID ) const;
+
+ TQPtrList<CSSProperty> *values() const { return m_lstValues; }
+ void setNode(NodeImpl *_node) { m_node = _node; }
+
+ void setChanged();
+
+ void removeCSSHints();
+
+protected:
+ DOMString getShortHandValue( const int* properties, int number ) const;
+ DOMString get4Values( const int* properties ) const;
+
+ TQPtrList<CSSProperty> *m_lstValues;
+ NodeImpl *m_node;
+
+private:
+ // currently not needed - make sure its not used
+ CSSStyleDeclarationImpl(const CSSStyleDeclarationImpl& o);
+};
+
+class CSSValueImpl : public StyleBaseImpl
+{
+public:
+ CSSValueImpl() : StyleBaseImpl() {}
+
+ virtual unsigned short cssValueType() const = 0;
+
+ virtual DOM::DOMString cssText() const = 0;
+
+ virtual bool isValue() const { return true; }
+ virtual bool isFontValue() const { return false; }
+};
+
+class CSSInheritedValueImpl : public CSSValueImpl
+{
+public:
+ CSSInheritedValueImpl() : CSSValueImpl() {}
+ virtual ~CSSInheritedValueImpl() {}
+
+ virtual unsigned short cssValueType() const;
+ virtual DOM::DOMString cssText() const;
+};
+
+class CSSInitialValueImpl : public CSSValueImpl
+{
+public:
+ virtual unsigned short cssValueType() const;
+ virtual DOM::DOMString cssText() const;
+};
+
+class CSSValueListImpl : public CSSValueImpl
+{
+public:
+ CSSValueListImpl() : CSSValueImpl() {}
+
+ virtual ~CSSValueListImpl();
+
+ unsigned long length() const { return m_values.count(); }
+ CSSValueImpl *item ( unsigned long index ) { return m_values.at(index); }
+
+ virtual bool isValueList() const { return true; }
+
+ virtual unsigned short cssValueType() const;
+
+ void append(CSSValueImpl *val);
+ virtual DOM::DOMString cssText() const;
+
+protected:
+ TQPtrList<CSSValueImpl> m_values;
+};
+
+
+class Counter;
+class RGBColor;
+class Rect;
+
+class CSSPrimitiveValueImpl : public CSSValueImpl
+{
+public:
+ CSSPrimitiveValueImpl();
+ CSSPrimitiveValueImpl(int ident);
+ CSSPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type);
+ CSSPrimitiveValueImpl(const DOMString &str, CSSPrimitiveValue::UnitTypes type);
+ CSSPrimitiveValueImpl(CounterImpl *c);
+ CSSPrimitiveValueImpl( RectImpl *r);
+ CSSPrimitiveValueImpl(QRgb color);
+ CSSPrimitiveValueImpl(PairImpl *p);
+
+ virtual ~CSSPrimitiveValueImpl();
+
+ void cleanup();
+
+ unsigned short primitiveType() const { return m_type; }
+
+ /*
+ * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get
+ * the fontinfo in case val is defined in em or ex.
+ *
+ * The metrics have to be a bit different for screen and printer output.
+ * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi
+ *
+ * this is screen/printer dependent, so we probably need a config option for this,
+ * and some tool to calibrate.
+ */
+ int computeLength( tdehtml::RenderStyle *style, TQPaintDeviceMetrics *devMetrics );
+
+ double computeLengthFloat( tdehtml::RenderStyle *style, TQPaintDeviceMetrics *devMetrics );
+
+ // use with care!!!
+ void setPrimitiveType(unsigned short type) { m_type = type; }
+ void setFloatValue ( unsigned short unitType, double floatValue, int &exceptioncode );
+ double floatValue ( unsigned short/* unitType */) const { return m_value.num; }
+
+ void setStringValue ( unsigned short stringType, const DOM::DOMString &stringValue, int &exceptioncode );
+ DOM::DOMStringImpl *getStringValue () const {
+ return ( ( m_type < CSSPrimitiveValue::CSS_STRING ||
+ m_type > CSSPrimitiveValue::CSS_ATTR ||
+ m_type == CSSPrimitiveValue::CSS_IDENT ) ? // fix IDENT
+ 0 : m_value.string );
+ }
+ CounterImpl *getCounterValue () const {
+ return ( m_type != CSSPrimitiveValue::CSS_COUNTER ? 0 : m_value.counter );
+ }
+
+ RectImpl *getRectValue () const {
+ return ( m_type != CSSPrimitiveValue::CSS_RECT ? 0 : m_value.rect );
+ }
+
+ QRgb getRGBColorValue () const {
+ return ( m_type != CSSPrimitiveValue::CSS_RGBCOLOR ? 0 : m_value.rgbcolor );
+ }
+
+ PairImpl* getPairValue() const {
+ return (m_type != CSSPrimitiveValue::CSS_PAIR ? 0 : m_value.pair);
+ }
+
+ virtual bool isPrimitiveValue() const { return true; }
+ virtual unsigned short cssValueType() const;
+
+ int getIdent();
+
+ virtual bool parseString( const DOMString &string, bool = false);
+ virtual DOM::DOMString cssText() const;
+
+ virtual bool isQuirkValue() const { return false; }
+
+protected:
+ int m_type;
+ union {
+ int ident;
+ double num;
+ DOM::DOMStringImpl *string;
+ CounterImpl *counter;
+ RectImpl *rect;
+ QRgb rgbcolor;
+ PairImpl* pair;
+ } m_value;
+};
+
+// This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE.
+// The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em
+// in a stylesheet. When the quirky value is used, if you're in quirks mode, the margin will
+// collapse away inside a table cell.
+class CSSQuirkPrimitiveValueImpl : public CSSPrimitiveValueImpl
+{
+public:
+ CSSQuirkPrimitiveValueImpl(double num, CSSPrimitiveValue::UnitTypes type)
+ :CSSPrimitiveValueImpl(num, type) {}
+
+ virtual ~CSSQuirkPrimitiveValueImpl() {}
+
+ virtual bool isQuirkValue() const { return true; }
+};
+
+class CounterImpl : public tdehtml::Shared<CounterImpl> {
+public:
+ CounterImpl() : m_listStyle(0) { }
+ DOMString identifier() const { return m_identifier; }
+ unsigned int listStyle() const { return m_listStyle; }
+ DOMString separator() const { return m_separator; }
+
+ DOMString m_identifier;
+ unsigned int m_listStyle;
+ DOMString m_separator;
+};
+
+class RectImpl : public tdehtml::Shared<RectImpl> {
+public:
+ RectImpl();
+ ~RectImpl();
+
+ CSSPrimitiveValueImpl *top() const { return m_top; }
+ CSSPrimitiveValueImpl *right() const { return m_right; }
+ CSSPrimitiveValueImpl *bottom() const { return m_bottom; }
+ CSSPrimitiveValueImpl *left() const { return m_left; }
+
+ void setTop( CSSPrimitiveValueImpl *top );
+ void setRight( CSSPrimitiveValueImpl *right );
+ void setBottom( CSSPrimitiveValueImpl *bottom );
+ void setLeft( CSSPrimitiveValueImpl *left );
+protected:
+ CSSPrimitiveValueImpl *m_top;
+ CSSPrimitiveValueImpl *m_right;
+ CSSPrimitiveValueImpl *m_bottom;
+ CSSPrimitiveValueImpl *m_left;
+};
+
+// A primitive value representing a pair. This is useful for properties like border-radius, background-size/position,
+// and border-spacing (all of which are space-separated sets of two values). At the moment we are only using it for
+// border-radius and background-size, but (FIXME) border-spacing and background-position could be converted over to use
+// it (eliminating some extra -webkit- internal properties).
+class PairImpl : public tdehtml::Shared<PairImpl> {
+public:
+ PairImpl() : m_first(0), m_second(0) { }
+ PairImpl(CSSPrimitiveValueImpl* first, CSSPrimitiveValueImpl* second)
+ : m_first(first), m_second(second) { if (first) first->ref(); if (second) second->ref(); }
+ virtual ~PairImpl();
+
+ CSSPrimitiveValueImpl* first() const { return m_first; }
+ CSSPrimitiveValueImpl* second() const { return m_second; }
+
+ void setFirst(CSSPrimitiveValueImpl* first);
+ void setSecond(CSSPrimitiveValueImpl* second);
+
+protected:
+ CSSPrimitiveValueImpl* m_first;
+ CSSPrimitiveValueImpl* m_second;
+};
+
+
+class CSSImageValueImpl : public CSSPrimitiveValueImpl, public tdehtml::CachedObjectClient
+{
+public:
+ CSSImageValueImpl(const DOMString &url, const StyleBaseImpl *style);
+ CSSImageValueImpl();
+ virtual ~CSSImageValueImpl();
+
+ tdehtml::CachedImage *image() { return m_image; }
+protected:
+ tdehtml::CachedImage *m_image;
+};
+
+class FontFamilyValueImpl : public CSSPrimitiveValueImpl
+{
+public:
+ FontFamilyValueImpl( const TQString &string);
+ const TQString &fontName() const { return parsedFontName; }
+ int genericFamilyType() const { return _genericFamilyType; }
+protected:
+ TQString parsedFontName;
+private:
+ int _genericFamilyType;
+};
+
+class FontValueImpl : public CSSValueImpl
+{
+public:
+ FontValueImpl();
+ virtual ~FontValueImpl();
+
+ virtual unsigned short cssValueType() const { return CSSValue::CSS_CUSTOM; }
+
+ virtual DOM::DOMString cssText() const;
+
+ virtual bool isFontValue() const { return true; }
+
+ CSSPrimitiveValueImpl *style;
+ CSSPrimitiveValueImpl *variant;
+ CSSPrimitiveValueImpl *weight;
+ CSSPrimitiveValueImpl *size;
+ CSSPrimitiveValueImpl *lineHeight;
+ CSSValueListImpl *family;
+};
+
+// Used for quotes
+class QuotesValueImpl : public CSSValueImpl
+{
+public:
+ QuotesValueImpl();
+// virtual ~QuotesValueImpl();
+
+ virtual unsigned short cssValueType() const { return CSSValue::CSS_CUSTOM; }
+ virtual DOM::DOMString cssText() const;
+
+ void addLevel(const TQString& open, const TQString& close);
+ TQString openQuote(int level) const;
+ TQString closeQuote(int level) const;
+
+ unsigned int levels;
+ TQStringList data;
+};
+
+// Used for text-shadow and box-shadow
+class ShadowValueImpl : public CSSValueImpl
+{
+public:
+ ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y,
+ CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color);
+ virtual ~ShadowValueImpl();
+
+ virtual unsigned short cssValueType() const { return CSSValue::CSS_CUSTOM; }
+
+ virtual DOM::DOMString cssText() const;
+
+ CSSPrimitiveValueImpl* x;
+ CSSPrimitiveValueImpl* y;
+ CSSPrimitiveValueImpl* blur;
+ CSSPrimitiveValueImpl* color;
+};
+
+// Used for counter-reset and counter-increment
+class CounterActImpl : public CSSValueImpl {
+ public:
+ CounterActImpl(const DOMString &c, short v) : m_counter(c), m_value(v) { }
+ virtual ~CounterActImpl() {};
+
+ virtual unsigned short cssValueType() const { return CSSValue::CSS_CUSTOM; }
+ virtual DOM::DOMString cssText() const;
+
+ const DOMString& counter() const { return m_counter; }
+ short value() const { return m_value; }
+ void setValue( const short v ) { m_value = v; }
+
+ DOM::DOMString m_counter;
+ short m_value;
+};
+
+
+// ------------------------------------------------------------------------------
+
+// another helper class
+class CSSProperty
+{
+public:
+ CSSProperty()
+ {
+ m_id = -1;
+ m_important = false;
+ nonCSSHint = false;
+ m_value = 0;
+ }
+ CSSProperty(const CSSProperty& o)
+ {
+ m_id = o.m_id;
+ m_important = o.m_important;
+ nonCSSHint = o.nonCSSHint;
+ m_value = o.m_value;
+ if (m_value) m_value->ref();
+ }
+ ~CSSProperty() {
+ if(m_value) m_value->deref();
+ }
+
+ void setValue(CSSValueImpl *val) {
+ if ( val != m_value ) {
+ if(m_value) m_value->deref();
+ m_value = val;
+ if(m_value) m_value->ref();
+ }
+ }
+
+ int id() const { return m_id; }
+
+ bool isImportant() const { return m_important; }
+
+ CSSValueImpl *value() const { return m_value; }
+
+ DOM::DOMString cssText() const;
+
+ // make sure the following fits in 4 bytes.
+ signed int m_id : 29;
+ bool m_important : 1;
+ bool nonCSSHint : 1;
+protected:
+ CSSValueImpl *m_value;
+};
+
+
+} // namespace
+
+#endif
diff --git a/tdehtml/css/csshelper.cpp b/tdehtml/css/csshelper.cpp
new file mode 100644
index 000000000..02b5b3d39
--- /dev/null
+++ b/tdehtml/css/csshelper.cpp
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (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 "csshelper.h"
+
+#include <tqfontmetrics.h>
+#include <tqfontinfo.h>
+#include <tqpaintdevice.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqfontdatabase.h>
+
+#include <kcharsets.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include "rendering/render_style.h"
+#include "css_valueimpl.h"
+#include "dom/css_value.h"
+#include "misc/helper.h"
+#include "xml/dom_stringimpl.h"
+#include "tdehtml_settings.h"
+
+using namespace DOM;
+using namespace tdehtml;
+
+
+DOMString tdehtml::parseURL(const DOMString &url)
+{
+ DOMStringImpl* i = url.implementation();
+ if(!i) return DOMString();
+
+ int o = 0;
+ int l = i->l;
+ while(o < l && (i->s[o] <= TQChar(' '))) { o++; l--; }
+ while(l > 0 && (i->s[o+l-1] <= TQChar(' '))) l--;
+
+ if(l >= 5 &&
+ (i->s[o].lower() == 'u') &&
+ (i->s[o+1].lower() == 'r') &&
+ (i->s[o+2].lower() == 'l') &&
+ i->s[o+3].latin1() == '(' &&
+ i->s[o+l-1].latin1() == ')') {
+ o += 4;
+ l -= 5;
+ }
+
+ while(o < l && (i->s[o] <= TQChar(' '))) { o++; l--; }
+ while(l > 0 && (i->s[o+l-1] <= TQChar(' '))) l--;
+
+ if(l >= 2 && i->s[o] == i->s[o+l-1] &&
+ (i->s[o].latin1() == '\'' || i->s[o].latin1() == '\"')) {
+ o++;
+ l -= 2;
+ }
+
+ while(o < l && (i->s[o] <= TQChar(' '))) { o++; l--; }
+ while(l > 0 && (i->s[o+l-1] <= TQChar(' '))) l--;
+
+ DOMStringImpl* j = new DOMStringImpl(i->s+o,l);
+
+ int nl = 0;
+ for(int k = o; k < o+l; k++)
+ if(i->s[k].unicode() > '\r')
+ j->s[nl++] = i->s[k];
+
+ j->l = nl;
+
+ return j;
+}
diff --git a/tdehtml/css/csshelper.h b/tdehtml/css/csshelper.h
new file mode 100644
index 000000000..772a9eba1
--- /dev/null
+++ b/tdehtml/css/csshelper.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (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 css_helper_h
+#define css_helper_h
+
+#include <tqcolor.h>
+#include <tqfont.h>
+
+#include "dom/dom_string.h"
+
+class TQPaintDeviceMetrics;
+class KHTMLSettings;
+
+namespace DOM
+{
+ class CSSPrimitiveValueImpl;
+}
+
+namespace tdehtml
+{
+ class RenderStyle;
+
+ /*
+ * mostly just removes the url("...") brace
+ */
+ DOM::DOMString parseURL(const DOM::DOMString &url);
+
+}
+
+
+
+#endif
diff --git a/tdehtml/css/cssparser.cpp b/tdehtml/css/cssparser.cpp
new file mode 100644
index 000000000..b994ad773
--- /dev/null
+++ b/tdehtml/css/cssparser.cpp
@@ -0,0 +1,2614 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (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.
+ */
+
+// #define CSS_DEBUG
+// #define TOKEN_DEBUG
+#define YYDEBUG 0
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kurl.h>
+
+#include "cssparser.h"
+#include "css_valueimpl.h"
+#include "css_ruleimpl.h"
+#include "css_stylesheetimpl.h"
+#include "cssproperties.h"
+#include "cssvalues.h"
+#include "misc/helper.h"
+#include "csshelper.h"
+using namespace DOM;
+
+#include <stdlib.h>
+#include <assert.h>
+
+// used to promote background: left to left center
+#define BACKGROUND_SKIP_CENTER( num ) \
+ if ( !pos_ok[ num ] && expected != 1 ) { \
+ pos_ok[num] = true; \
+ pos[num] = 0; \
+ skip_next = false; \
+ }
+
+ValueList::~ValueList()
+{
+ unsigned numValues = m_values.size();
+ for (unsigned i = 0; i < numValues; i++)
+ if (m_values[i].unit == Value::Function)
+ delete m_values[i].function;
+}
+
+namespace {
+ class ShorthandScope {
+ public:
+ ShorthandScope(CSSParser* parser, int propId) : m_parser(parser)
+ {
+ if (!(m_parser->m_inParseShorthand++))
+ m_parser->m_currentShorthand = propId;
+ }
+ ~ShorthandScope()
+ {
+ if (!(--m_parser->m_inParseShorthand))
+ m_parser->m_currentShorthand = 0;
+ }
+
+ private:
+ CSSParser* m_parser;
+ };
+}
+
+using namespace DOM;
+
+#if YYDEBUG > 0
+extern int cssyydebug;
+#endif
+
+extern int cssyyparse( void * parser );
+
+CSSParser *CSSParser::currentParser = 0;
+
+CSSParser::CSSParser( bool strictParsing )
+{
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "CSSParser::CSSParser this=" << this << endl;
+#endif
+ strict = strictParsing;
+
+ parsedProperties = (CSSProperty **) malloc( 32 * sizeof( CSSProperty * ) );
+ numParsedProperties = 0;
+ maxParsedProperties = 32;
+
+ data = 0;
+ valueList = 0;
+ rule = 0;
+ id = 0;
+ important = false;
+ nonCSSHint = false;
+
+ m_inParseShorthand = 0;
+ m_currentShorthand = 0;
+ m_implicitShorthand = false;
+
+ yy_start = 1;
+
+#if YYDEBUG > 0
+ cssyydebug = 1;
+#endif
+
+}
+
+CSSParser::~CSSParser()
+{
+ if ( numParsedProperties )
+ clearProperties();
+ free( parsedProperties );
+
+ delete valueList;
+
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "CSSParser::~CSSParser this=" << this << endl;
+#endif
+
+ free( data );
+
+}
+
+unsigned int CSSParser::defaultNamespace()
+{
+ if (styleElement && styleElement->isCSSStyleSheet())
+ return static_cast<CSSStyleSheetImpl*>(styleElement)->defaultNamespace();
+ else
+ return anyNamespace;
+}
+
+void CSSParser::runParser(int length)
+{
+ data[length-1] = 0;
+ data[length-2] = 0;
+ data[length-3] = ' ';
+
+ yyTok = -1;
+ block_nesting = 0;
+ yy_hold_char = 0;
+ yyleng = 0;
+ yytext = yy_c_buf_p = data;
+ yy_hold_char = *yy_c_buf_p;
+
+ CSSParser *old = currentParser;
+ currentParser = this;
+ cssyyparse( this );
+ currentParser = old;
+}
+
+void CSSParser::parseSheet( CSSStyleSheetImpl *sheet, const DOMString &string )
+{
+ styleElement = sheet;
+
+ int length = string.length() + 3;
+ data = (unsigned short *)malloc( length *sizeof( unsigned short ) );
+ memcpy( data, string.unicode(), string.length()*sizeof( unsigned short) );
+
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << ">>>>>>> start parsing style sheet" << endl;
+#endif
+ runParser(length);
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "<<<<<<< done parsing style sheet" << endl;
+#endif
+
+ delete rule;
+ rule = 0;
+}
+
+CSSRuleImpl *CSSParser::parseRule( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string )
+{
+ styleElement = sheet;
+
+ const char tdehtml_rule[] = "@-tdehtml-rule{";
+ int length = string.length() + 4 + strlen(tdehtml_rule);
+ assert( !data );
+ data = (unsigned short *)malloc( length *sizeof( unsigned short ) );
+ for ( unsigned int i = 0; i < strlen(tdehtml_rule); i++ )
+ data[i] = tdehtml_rule[i];
+ memcpy( data + strlen( tdehtml_rule ), string.unicode(), string.length()*sizeof( unsigned short) );
+ // tqDebug("parse string = '%s'", TQConstString( (const TQChar *)data, length ).string().latin1() );
+ data[length-4] = '}';
+
+ runParser(length);
+
+ CSSRuleImpl *result = rule;
+ rule = 0;
+
+ return result;
+}
+
+bool CSSParser::parseValue( DOM::CSSStyleDeclarationImpl *declaration, int _id, const DOM::DOMString &string,
+ bool _important, bool _nonCSSHint )
+{
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "CSSParser::parseValue: id=" << _id << " important=" << _important
+ << " nonCSSHint=" << _nonCSSHint << " value='" << string.string() << "'" << endl;
+#endif
+
+ styleElement = declaration->stylesheet();
+
+ const char tdehtml_value[] = "@-tdehtml-value{";
+ int length = string.length() + 4 + strlen(tdehtml_value);
+ assert( !data );
+ data = (unsigned short *)malloc( length *sizeof( unsigned short ) );
+ for ( unsigned int i = 0; i < strlen(tdehtml_value); i++ )
+ data[i] = tdehtml_value[i];
+ memcpy( data + strlen( tdehtml_value ), string.unicode(), string.length()*sizeof( unsigned short) );
+ data[length-4] = '}';
+ // tqDebug("parse string = '%s'", TQConstString( (const TQChar *)data, length ).string().latin1() );
+
+ id = _id;
+ important = _important;
+ nonCSSHint = _nonCSSHint;
+
+ runParser(length);
+
+ delete rule;
+ rule = 0;
+
+ bool ok = false;
+ if ( numParsedProperties ) {
+ ok = true;
+ for ( int i = 0; i < numParsedProperties; i++ ) {
+ declaration->removeProperty(parsedProperties[i]->m_id, nonCSSHint);
+ declaration->values()->append( parsedProperties[i] );
+ }
+ numParsedProperties = 0;
+ }
+
+ return ok;
+}
+
+bool CSSParser::parseDeclaration( DOM::CSSStyleDeclarationImpl *declaration, const DOM::DOMString &string,
+ bool _nonCSSHint )
+{
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "CSSParser::parseDeclaration: nonCSSHint=" << nonCSSHint
+ << " value='" << string.string() << "'" << endl;
+#endif
+
+ styleElement = declaration->stylesheet();
+
+ const char tdehtml_decls[] = "@-tdehtml-decls{";
+ int length = string.length() + 4 + strlen(tdehtml_decls);
+ assert( !data );
+ data = (unsigned short *)malloc( length *sizeof( unsigned short ) );
+ for ( unsigned int i = 0; i < strlen(tdehtml_decls); i++ )
+ data[i] = tdehtml_decls[i];
+ memcpy( data + strlen( tdehtml_decls ), string.unicode(), string.length()*sizeof( unsigned short) );
+ data[length-4] = '}';
+
+ nonCSSHint = _nonCSSHint;
+
+ runParser(length);
+
+ delete rule;
+ rule = 0;
+
+ bool ok = false;
+ if ( numParsedProperties ) {
+ ok = true;
+ for ( int i = 0; i < numParsedProperties; i++ ) {
+ declaration->removeProperty(parsedProperties[i]->m_id, false);
+ declaration->values()->append( parsedProperties[i] );
+ }
+ numParsedProperties = 0;
+ }
+
+ return ok;
+}
+
+void CSSParser::addProperty( int propId, CSSValueImpl *value, bool important )
+{
+ CSSProperty *prop = new CSSProperty;
+ prop->m_id = propId;
+ prop->setValue( value );
+ prop->m_important = important;
+ prop->nonCSSHint = nonCSSHint;
+
+ if ( numParsedProperties >= maxParsedProperties ) {
+ maxParsedProperties += 32;
+ parsedProperties = (CSSProperty **) realloc( parsedProperties,
+ maxParsedProperties*sizeof( CSSProperty * ) );
+ }
+ parsedProperties[numParsedProperties++] = prop;
+}
+
+CSSStyleDeclarationImpl *CSSParser::createStyleDeclaration( CSSStyleRuleImpl *rule )
+{
+ TQPtrList<CSSProperty> *propList = new TQPtrList<CSSProperty>;
+ propList->setAutoDelete( true );
+ for ( int i = 0; i < numParsedProperties; i++ )
+ propList->append( parsedProperties[i] );
+
+ numParsedProperties = 0;
+ return new CSSStyleDeclarationImpl(rule, propList);
+}
+
+void CSSParser::clearProperties()
+{
+ for ( int i = 0; i < numParsedProperties; i++ )
+ delete parsedProperties[i];
+ numParsedProperties = 0;
+}
+
+DOM::DocumentImpl *CSSParser::document() const
+{
+ const StyleBaseImpl* root = styleElement;
+ DocumentImpl *doc = 0;
+ while (root->parent())
+ root = root->parent();
+ if (root->isCSSStyleSheet())
+ doc = static_cast<const CSSStyleSheetImpl*>(root)->doc();
+ return doc;
+}
+
+
+// defines units allowed for a certain property, used in parseUnit
+enum Units
+{
+ FUnknown = 0x0000,
+ FInteger = 0x0001,
+ FNumber = 0x0002, // Real Numbers
+ FPercent = 0x0004,
+ FLength = 0x0008,
+ FAngle = 0x0010,
+ FTime = 0x0020,
+ FFrequency = 0x0040,
+ FRelative = 0x0100,
+ FNonNeg = 0x0200
+};
+
+static bool validUnit( Value *value, int unitflags, bool strict )
+{
+ if ( unitflags & FNonNeg && value->fValue < 0 )
+ return false;
+
+ bool b = false;
+ switch( value->unit ) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ b = (unitflags & FNumber);
+ if ( !b && ( (unitflags & FLength) && (value->fValue == 0 || !strict ) ) ) {
+ value->unit = CSSPrimitiveValue::CSS_PX;
+ b = true;
+ }
+ if (!b && (unitflags & FInteger) && value->isInt)
+ b = true;
+ break;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ b = (unitflags & FPercent);
+ break;
+ case Value::Q_EMS:
+ case CSSPrimitiveValue::CSS_EMS:
+ case CSSPrimitiveValue::CSS_EXS:
+ case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_CM:
+ case CSSPrimitiveValue::CSS_MM:
+ case CSSPrimitiveValue::CSS_IN:
+ case CSSPrimitiveValue::CSS_PT:
+ case CSSPrimitiveValue::CSS_PC:
+ b = (unitflags & FLength);
+ break;
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_S:
+ b = (unitflags & FTime);
+ break;
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_RAD:
+ case CSSPrimitiveValue::CSS_GRAD:
+ case CSSPrimitiveValue::CSS_HZ:
+ case CSSPrimitiveValue::CSS_KHZ:
+ case CSSPrimitiveValue::CSS_DIMENSION:
+ default:
+ break;
+ }
+ return b;
+}
+
+bool CSSParser::parseValue( int propId, bool important )
+{
+ if ( !valueList ) return false;
+
+ Value *value = valueList->current();
+
+ if ( !value )
+ return false;
+
+ int id = value->id;
+
+ int num = inShorthand() ? 1 : valueList->size();
+
+ if ( id == CSS_VAL_INHERIT ) {
+ if (num != 1)
+ return false;
+ addProperty( propId, new CSSInheritedValueImpl(), important );
+ return true;
+ } else if (id == CSS_VAL_INITIAL ) {
+ if (num != 1)
+ return false;
+ addProperty(propId, new CSSInitialValueImpl(), important);
+ return true;
+ }
+
+ bool valid_primitive = false;
+ CSSValueImpl *parsedValue = 0;
+
+ switch(propId) {
+ /* The comment to the left defines all valid value of this properties as defined
+ * in CSS 2, Appendix F. Property index
+ */
+
+ /* All the CSS properties are not supported by the renderer at the moment.
+ * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
+ * (see parseAuralValues). As we don't support them at all this seems reasonable.
+ */
+
+ case CSS_PROP_SIZE: // <length>{1,2} | auto | portrait | landscape | inherit
+// case CSS_PROP_PAGE: // <identifier> | auto // ### CHECK
+ // ### To be done
+ if (id)
+ valid_primitive = true;
+ break;
+ case CSS_PROP_UNICODE_BIDI: // normal | embed | bidi-override | inherit
+ if ( id == CSS_VAL_NORMAL ||
+ id == CSS_VAL_EMBED ||
+ id == CSS_VAL_BIDI_OVERRIDE )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_POSITION: // static | relative | absolute | fixed | inherit
+ if ( id == CSS_VAL_STATIC ||
+ id == CSS_VAL_RELATIVE ||
+ id == CSS_VAL_ABSOLUTE ||
+ id == CSS_VAL_FIXED )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_PAGE_BREAK_AFTER: // auto | always | avoid | left | right | inherit
+ case CSS_PROP_PAGE_BREAK_BEFORE: // auto | always | avoid | left | right | inherit
+ if ( id == CSS_VAL_AUTO ||
+ id == CSS_VAL_ALWAYS ||
+ id == CSS_VAL_AVOID ||
+ id == CSS_VAL_LEFT ||
+ id == CSS_VAL_RIGHT )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_PAGE_BREAK_INSIDE: // avoid | auto | inherit
+ if ( id == CSS_VAL_AUTO ||
+ id == CSS_VAL_AVOID )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_EMPTY_CELLS: // show | hide | inherit
+ if ( id == CSS_VAL_SHOW ||
+ id == CSS_VAL_HIDE )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_QUOTES: // [<string> <string>]+ | none | inherit
+ if (id == CSS_VAL_NONE) {
+ valid_primitive = true;
+ } else {
+ QuotesValueImpl *quotes = new QuotesValueImpl;
+ bool is_valid = true;
+ TQString open, close;
+ Value *val=valueList->current();
+ while (val) {
+ if (val->unit == CSSPrimitiveValue::CSS_STRING)
+ open = qString(val->string);
+ else {
+ is_valid = false;
+ break;
+ }
+ valueList->next();
+ val=valueList->current();
+ if (val && val->unit == CSSPrimitiveValue::CSS_STRING)
+ close = qString(val->string);
+ else {
+ is_valid = false;
+ break;
+ }
+ quotes->addLevel(open, close);
+ valueList->next();
+ val=valueList->current();
+ }
+ if (is_valid)
+ parsedValue = quotes;
+ else
+ delete quotes;
+ }
+ break;
+
+ case CSS_PROP_CONTENT: // normal | none | inherit |
+ // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+
+ if ( id == CSS_VAL_NORMAL || id == CSS_VAL_NONE)
+ valid_primitive = true;
+ else
+ return parseContent( propId, important );
+ break;
+
+ case CSS_PROP_WHITE_SPACE: // normal | pre | nowrap | pre-wrap | pre-line | inherit
+ if ( id == CSS_VAL_NORMAL ||
+ id == CSS_VAL_PRE ||
+ id == CSS_VAL_PRE_WRAP ||
+ id == CSS_VAL_PRE_LINE ||
+ id == CSS_VAL_NOWRAP )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_CLIP: // <shape> | auto | inherit
+ if ( id == CSS_VAL_AUTO )
+ valid_primitive = true;
+ else if ( value->unit == Value::Function )
+ return parseShape( propId, important );
+ break;
+
+ /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
+ * correctly and allows optimization in tdehtml::applyRule(..)
+ */
+ case CSS_PROP_CAPTION_SIDE: // top | bottom | left | right | inherit
+ // Left and right were deprecated in CSS 2.1 and never supported by KHTML
+ if ( /* id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || */
+ id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_BORDER_COLLAPSE: // collapse | separate | inherit
+ if ( id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_VISIBILITY: // visible | hidden | collapse | inherit
+ if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_COLLAPSE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_OVERFLOW: // visible | hidden | scroll | auto | marquee | inherit
+ case CSS_PROP_OVERFLOW_X:
+ case CSS_PROP_OVERFLOW_Y:
+ if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_SCROLL || id == CSS_VAL_AUTO ||
+ id == CSS_VAL_MARQUEE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_LIST_STYLE_POSITION: // inside | outside | inherit
+ if ( id == CSS_VAL_INSIDE || id == CSS_VAL_OUTSIDE )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_LIST_STYLE_TYPE:
+ // disc | circle | square | decimal | decimal-leading-zero | lower-roman |
+ // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha |
+ // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana |
+ // katakana | hiragana-iroha | katakana-iroha | none | inherit
+ if ((id >= CSS_VAL_DISC && id <= CSS_VAL__KHTML_CLOSE_QUOTE) || id == CSS_VAL_NONE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_DISPLAY:
+ // inline | block | list-item | run-in | inline-block | -tdehtml-ruler | table |
+ // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
+ // table-column-group | table-column | table-cell | table-caption | none | inherit
+ if ((id >= CSS_VAL_INLINE && id <= CSS_VAL_TABLE_CAPTION) || id == CSS_VAL_NONE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_DIRECTION: // ltr | rtl | inherit
+ if ( id == CSS_VAL_LTR || id == CSS_VAL_RTL )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_TEXT_TRANSFORM: // capitalize | uppercase | lowercase | none | inherit
+ if ((id >= CSS_VAL_CAPITALIZE && id <= CSS_VAL_LOWERCASE) || id == CSS_VAL_NONE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_FLOAT: // left | right | none | tdehtml_left | tdehtml_right | inherit + center for buggy CSS
+ if ( id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL__KHTML_LEFT ||
+ id == CSS_VAL__KHTML_RIGHT ||id == CSS_VAL_NONE || id == CSS_VAL_CENTER)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_CLEAR: // none | left | right | both | inherit
+ if ( id == CSS_VAL_NONE || id == CSS_VAL_LEFT ||
+ id == CSS_VAL_RIGHT|| id == CSS_VAL_BOTH)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_TEXT_ALIGN:
+ // left | right | center | justify | tdehtml_left | tdehtml_right | tdehtml_center | <string> | inherit
+ if ( ( id >= CSS_VAL__KHTML_AUTO && id <= CSS_VAL__KHTML_CENTER ) ||
+ value->unit == CSSPrimitiveValue::CSS_STRING )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_OUTLINE_STYLE: // <border-style> | inherit
+ case CSS_PROP_BORDER_TOP_STYLE: //// <border-style> | inherit
+ case CSS_PROP_BORDER_RIGHT_STYLE: // Defined as: none | hidden | dotted | dashed |
+ case CSS_PROP_BORDER_BOTTOM_STYLE: // solid | double | groove | ridge | inset | outset | -tdehtml-native
+ case CSS_PROP_BORDER_LEFT_STYLE: ////
+ if (id >= CSS_VAL__KHTML_NATIVE && id <= CSS_VAL_DOUBLE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_FONT_WEIGHT: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 |
+ // 500 | 600 | 700 | 800 | 900 | inherit
+ if (id >= CSS_VAL_NORMAL && id <= CSS_VAL_900) {
+ // Allready correct id
+ valid_primitive = true;
+ } else if ( validUnit( value, FInteger|FNonNeg, false ) ) {
+ int weight = (int)value->fValue;
+ if ( (weight % 100) )
+ break;
+ weight /= 100;
+ if ( weight >= 1 && weight <= 9 ) {
+ id = CSS_VAL_100 + weight - 1;
+ valid_primitive = true;
+ }
+ }
+ break;
+
+ case CSS_PROP_BORDER_SPACING:
+ {
+ const int properties[2] = { CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING,
+ CSS_PROP__KHTML_BORDER_VERTICAL_SPACING };
+ if (num == 1) {
+ ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
+ if (!parseValue(properties[0], important)) return false;
+ CSSValueImpl* value = parsedProperties[numParsedProperties-1]->value();
+ addProperty(properties[1], value, important);
+ return true;
+ }
+ else if (num == 2) {
+ ShorthandScope scope(this, CSS_PROP_BORDER_SPACING);
+ if (!parseValue(properties[0], important)) return false;
+ if (!parseValue(properties[1], important)) return false;
+ return true;
+ }
+ return false;
+ }
+ case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING:
+ case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING:
+ valid_primitive = validUnit(value, FLength|FNonNeg, strict&(!nonCSSHint));
+ break;
+
+ case CSS_PROP_SCROLLBAR_FACE_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_SHADOW_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_TRACK_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_ARROW_COLOR: // IE5.5
+ case CSS_PROP_SCROLLBAR_BASE_COLOR: // IE5.5
+ if ( strict )
+ break;
+ /* nobreak */
+ case CSS_PROP_OUTLINE_COLOR: // <color> | invert | inherit
+ // outline has "invert" as additional keyword.
+ if ( propId == CSS_PROP_OUTLINE_COLOR && id == CSS_VAL_INVERT ) {
+ valid_primitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSS_PROP_BACKGROUND_COLOR: // <color> | inherit
+ case CSS_PROP_BORDER_TOP_COLOR: // <color> | inherit
+ case CSS_PROP_BORDER_RIGHT_COLOR: // <color> | inherit
+ case CSS_PROP_BORDER_BOTTOM_COLOR: // <color> | inherit
+ case CSS_PROP_BORDER_LEFT_COLOR: // <color> | inherit
+ case CSS_PROP_COLOR: // <color> | inherit
+ if ( id == CSS_VAL__KHTML_TEXT || id == CSS_VAL_MENU ||
+ (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT ) ||
+ id == CSS_VAL_TRANSPARENT ||
+ (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && (nonCSSHint|!strict) ) ) {
+ valid_primitive = true;
+ } else {
+ parsedValue = parseColor();
+ if ( parsedValue )
+ valueList->next();
+ }
+ break;
+
+ case CSS_PROP_CURSOR:
+ // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
+ // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | text |
+ // wait | help ] ] | inherit
+ // MSIE 5 compatibility :/
+ if ( !strict && id == CSS_VAL_HAND ) {
+ id = CSS_VAL_POINTER;
+ valid_primitive = true;
+ } else if ( id >= CSS_VAL_AUTO && id <= CSS_VAL_HELP )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_BACKGROUND_ATTACHMENT:
+ case CSS_PROP__KHTML_BACKGROUND_CLIP:
+ case CSS_PROP_BACKGROUND_IMAGE:
+ case CSS_PROP__KHTML_BACKGROUND_ORIGIN:
+ case CSS_PROP_BACKGROUND_POSITION:
+ case CSS_PROP_BACKGROUND_POSITION_X:
+ case CSS_PROP_BACKGROUND_POSITION_Y:
+ case CSS_PROP__KHTML_BACKGROUND_SIZE:
+ case CSS_PROP_BACKGROUND_REPEAT: {
+ CSSValueImpl *val1 = 0, *val2 = 0;
+ int propId1, propId2;
+ if (parseBackgroundProperty(propId, propId1, propId2, val1, val2)) {
+ addProperty(propId1, val1, important);
+ if (val2)
+ addProperty(propId2, val2, important);
+ return true;
+ }
+ return false;
+ }
+ case CSS_PROP_LIST_STYLE_IMAGE: // <uri> | none | inherit
+ if (id == CSS_VAL_NONE) {
+ parsedValue = new CSSImageValueImpl();
+ valueList->next();
+ }
+ else if (value->unit == CSSPrimitiveValue::CSS_URI ) {
+ // ### allow string in non strict mode?
+ DOMString uri = tdehtml::parseURL( domString( value->string ) );
+ if (!uri.isEmpty()) {
+ parsedValue = new CSSImageValueImpl(
+ DOMString(KURL( styleElement->baseURL(), uri.string()).url()),
+ styleElement );
+ valueList->next();
+ }
+ }
+ break;
+
+ case CSS_PROP_OUTLINE_WIDTH: // <border-width> | inherit
+ case CSS_PROP_BORDER_TOP_WIDTH: //// <border-width> | inherit
+ case CSS_PROP_BORDER_RIGHT_WIDTH: // Which is defined as
+ case CSS_PROP_BORDER_BOTTOM_WIDTH: // thin | medium | thick | <length>
+ case CSS_PROP_BORDER_LEFT_WIDTH: ////
+ if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
+ valid_primitive = true;
+ else
+ valid_primitive = ( validUnit( value, FLength, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_LETTER_SPACING: // normal | <length> | inherit
+ case CSS_PROP_WORD_SPACING: // normal | <length> | inherit
+ if ( id == CSS_VAL_NORMAL )
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit( value, FLength, strict&(!nonCSSHint) );
+ break;
+
+ case CSS_PROP_TEXT_INDENT: // <length> | <percentage> | inherit
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_PADDING_TOP: // <length> | <percentage> | inherit
+ case CSS_PROP_PADDING_RIGHT: // <padding-width> | inherit
+ case CSS_PROP_PADDING_BOTTOM: // Which is defined as
+ case CSS_PROP_PADDING_LEFT: // <length> | <percentage>
+ case CSS_PROP__KHTML_PADDING_START:
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_MAX_HEIGHT: // <length> | <percentage> | none | inherit
+ case CSS_PROP_MAX_WIDTH: // <length> | <percentage> | none | inherit
+ if ( id == CSS_VAL_NONE ) {
+ valid_primitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSS_PROP_MIN_HEIGHT: // <length> | <percentage> | inherit
+ case CSS_PROP_MIN_WIDTH: // <length> | <percentage> | inherit
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_FONT_SIZE:
+ // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
+ if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER)
+ valid_primitive = true;
+ else
+ valid_primitive = ( validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_FONT_STYLE: // normal | italic | oblique | inherit
+ if ( id == CSS_VAL_NORMAL || id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_FONT_VARIANT: // normal | small-caps | inherit
+ if ( id == CSS_VAL_NORMAL || id == CSS_VAL_SMALL_CAPS)
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP_VERTICAL_ALIGN:
+ // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
+ // <percentage> | <length> | inherit
+
+ if ( id >= CSS_VAL_BASELINE && id <= CSS_VAL__KHTML_BASELINE_MIDDLE )
+ valid_primitive = true;
+ else
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_HEIGHT: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_WIDTH: // <length> | <percentage> | auto | inherit
+ if ( id == CSS_VAL_AUTO )
+ valid_primitive = true;
+ else
+ // ### handle multilength case where we allow relative units
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_BOTTOM: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_LEFT: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_RIGHT: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_TOP: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_MARGIN_TOP: //// <margin-width> | inherit
+ case CSS_PROP_MARGIN_RIGHT: // Which is defined as
+ case CSS_PROP_MARGIN_BOTTOM: // <length> | <percentage> | auto | inherit
+ case CSS_PROP_MARGIN_LEFT: ////
+ case CSS_PROP__KHTML_MARGIN_START:
+ if ( id == CSS_VAL_AUTO )
+ valid_primitive = true;
+ else
+ valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+ break;
+
+ case CSS_PROP_Z_INDEX: // auto | <integer> | inherit
+ // tqDebug("parsing z-index: id=%d, fValue=%f", id, value->fValue );
+ if ( id == CSS_VAL_AUTO ) {
+ valid_primitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSS_PROP_ORPHANS: // <integer> | inherit
+ case CSS_PROP_WIDOWS: // <integer> | inherit
+ // ### not supported later on
+ valid_primitive = ( !id && validUnit( value, FInteger, false ) );
+ break;
+
+ case CSS_PROP_LINE_HEIGHT: // normal | <number> | <length> | <percentage> | inherit
+ if ( id == CSS_VAL_NORMAL )
+ valid_primitive = true;
+ else
+ valid_primitive = ( !id && validUnit( value, FNumber|FLength|FPercent, strict&(!nonCSSHint) ) );
+ break;
+ case CSS_PROP_COUNTER_INCREMENT: // [ <identifier> <integer>? ]+ | none | inherit
+ if ( id == CSS_VAL_NONE )
+ valid_primitive = true;
+ else
+ return parseCounter(propId, true, important);
+ break;
+ case CSS_PROP_COUNTER_RESET: // [ <identifier> <integer>? ]+ | none | inherit
+ if ( id == CSS_VAL_NONE )
+ valid_primitive = true;
+ else
+ return parseCounter(propId, false, important);
+ break;
+
+ case CSS_PROP_FONT_FAMILY:
+ // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
+ {
+ parsedValue = parseFontFamily();
+ break;
+ }
+
+ case CSS_PROP_TEXT_DECORATION:
+ // none | [ underline || overline || line-through || blink ] | inherit
+ if (id == CSS_VAL_NONE) {
+ valid_primitive = true;
+ } else {
+ CSSValueListImpl *list = new CSSValueListImpl;
+ bool is_valid = true;
+ while( is_valid && value ) {
+ switch ( value->id ) {
+ case CSS_VAL_BLINK:
+ break;
+ case CSS_VAL_UNDERLINE:
+ case CSS_VAL_OVERLINE:
+ case CSS_VAL_LINE_THROUGH:
+ list->append( new CSSPrimitiveValueImpl( value->id ) );
+ break;
+ default:
+ is_valid = false;
+ }
+ value = valueList->next();
+ }
+ //kdDebug( 6080 ) << "got " << list->length() << "d decorations" << endl;
+ if(list->length() && is_valid) {
+ parsedValue = list;
+ valueList->next();
+ } else {
+ delete list;
+ }
+ }
+ break;
+
+ case CSS_PROP_TABLE_LAYOUT: // auto | fixed | inherit
+ if ( id == CSS_VAL_AUTO || id == CSS_VAL_FIXED )
+ valid_primitive = true;
+ break;
+
+ case CSS_PROP__KHTML_FLOW_MODE:
+ if ( id == CSS_VAL__KHTML_NORMAL || id == CSS_VAL__KHTML_AROUND_FLOATS )
+ valid_primitive = true;
+ break;
+
+ /* CSS3 properties */
+ case CSS_PROP_BOX_SIZING: // border-box | content-box | inherit
+ if ( id == CSS_VAL_BORDER_BOX || id == CSS_VAL_CONTENT_BOX )
+ valid_primitive = true;
+ break;
+ case CSS_PROP_OUTLINE_OFFSET:
+ valid_primitive = validUnit(value, FLength, strict);
+ break;
+ case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
+ if (id == CSS_VAL_NONE)
+ valid_primitive = true;
+ else
+ return parseShadow(propId, important);
+ break;
+ case CSS_PROP_OPACITY:
+ valid_primitive = validUnit(value, FNumber, strict);
+ break;
+ case CSS_PROP__KHTML_USER_INPUT: // none | enabled | disabled | inherit
+ if ( id == CSS_VAL_NONE || id == CSS_VAL_ENABLED || id == CSS_VAL_DISABLED )
+ valid_primitive = true;
+// kdDebug(6080) << "CSS_PROP__KHTML_USER_INPUT: " << valid_primitive << endl;
+ break;
+ case CSS_PROP__KHTML_MARQUEE: {
+ const int properties[5] = { CSS_PROP__KHTML_MARQUEE_DIRECTION, CSS_PROP__KHTML_MARQUEE_INCREMENT,
+ CSS_PROP__KHTML_MARQUEE_REPETITION,
+ CSS_PROP__KHTML_MARQUEE_STYLE, CSS_PROP__KHTML_MARQUEE_SPEED };
+ return parseShortHand(propId, properties, 5, important);
+ }
+ case CSS_PROP__KHTML_MARQUEE_DIRECTION:
+ if (id == CSS_VAL_FORWARDS || id == CSS_VAL_BACKWARDS || id == CSS_VAL_AHEAD ||
+ id == CSS_VAL_REVERSE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL_DOWN ||
+ id == CSS_VAL_UP || id == CSS_VAL_AUTO)
+ valid_primitive = true;
+ break;
+ case CSS_PROP__KHTML_MARQUEE_INCREMENT:
+ if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM)
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit(value, FLength|FPercent, strict&(!nonCSSHint));
+ break;
+ case CSS_PROP__KHTML_MARQUEE_STYLE:
+ if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE ||
+ id == CSS_VAL_UNFURL)
+ valid_primitive = true;
+ break;
+ case CSS_PROP__KHTML_MARQUEE_REPETITION:
+ if (id == CSS_VAL_INFINITE)
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit(value, FInteger|FNonNeg, strict&(!nonCSSHint));
+ break;
+ case CSS_PROP__KHTML_MARQUEE_SPEED:
+ if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST)
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict&(!nonCSSHint));
+ break;
+ case CSS_PROP_TEXT_OVERFLOW: // clip | ellipsis
+ if (id == CSS_VAL_CLIP || id == CSS_VAL_ELLIPSIS)
+ valid_primitive = true;
+ break;
+ // End of CSS3 properties
+
+ /* shorthand properties */
+ case CSS_PROP_BACKGROUND:
+ // ['background-color' || 'background-image' ||'background-repeat' ||
+ // 'background-attachment' || 'background-position'] | inherit
+ return parseBackgroundShorthand(important);
+ case CSS_PROP_BORDER:
+ // [ 'border-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
+ CSS_PROP_BORDER_COLOR };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_BORDER_TOP:
+ // [ 'border-top-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
+ CSS_PROP_BORDER_TOP_COLOR};
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_BORDER_RIGHT:
+ // [ 'border-right-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
+ CSS_PROP_BORDER_RIGHT_COLOR };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_BORDER_BOTTOM:
+ // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
+ CSS_PROP_BORDER_BOTTOM_COLOR };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_BORDER_LEFT:
+ // [ 'border-left-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
+ CSS_PROP_BORDER_LEFT_COLOR };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_OUTLINE:
+ // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
+ {
+ const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
+ CSS_PROP_OUTLINE_COLOR };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_BORDER_COLOR:
+ // <color>{1,4} | inherit
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
+ CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
+ return parse4Values(propId, properties, important);
+ }
+ case CSS_PROP_BORDER_WIDTH:
+ // <border-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
+ CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
+ return parse4Values(propId, properties, important);
+ }
+ case CSS_PROP_BORDER_STYLE:
+ // <border-style>{1,4} | inherit
+ {
+ const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
+ CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
+ return parse4Values(propId, properties, important);
+ }
+ case CSS_PROP_MARGIN:
+ // <margin-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
+ CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
+ return parse4Values(propId, properties, important);
+ }
+ case CSS_PROP_PADDING:
+ // <padding-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
+ CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
+ return parse4Values(propId, properties, important);
+ }
+ case CSS_PROP_FONT:
+ // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
+ // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
+ if ( id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR )
+ valid_primitive = true;
+ else
+ return parseFont(important);
+
+ case CSS_PROP_LIST_STYLE:
+ {
+ const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
+ CSS_PROP_LIST_STYLE_IMAGE };
+ return parseShortHand(propId, properties, 3, important);
+ }
+ case CSS_PROP_WORD_WRAP:
+ {
+ // normal | break-word
+ if ( id == CSS_VAL_NORMAL || id == CSS_VAL_BREAK_WORD )
+ valid_primitive = true;
+ break;
+ }
+ default:
+// #ifdef CSS_DEBUG
+// kdDebug( 6080 ) << "illegal or CSS2 Aural property: " << val << endl;
+// #endif
+ break;
+ }
+
+ if ( valid_primitive ) {
+
+ if ( id != 0 ) {
+ parsedValue = new CSSPrimitiveValueImpl( id );
+ } else if ( value->unit == CSSPrimitiveValue::CSS_STRING )
+ parsedValue = new CSSPrimitiveValueImpl( domString( value->string ),
+ (CSSPrimitiveValue::UnitTypes) value->unit );
+ else if ( value->unit >= CSSPrimitiveValue::CSS_NUMBER &&
+ value->unit <= CSSPrimitiveValue::CSS_KHZ ) {
+ parsedValue = new CSSPrimitiveValueImpl( value->fValue,
+ (CSSPrimitiveValue::UnitTypes) value->unit );
+ } else if ( value->unit >= Value::Q_EMS ) {
+ parsedValue = new CSSQuirkPrimitiveValueImpl( value->fValue, CSSPrimitiveValue::CSS_EMS );
+ }
+ valueList->next();
+ }
+ if ( parsedValue ) {
+ if (!valueList->current() || inShorthand()) {
+ addProperty( propId, parsedValue, important );
+ return true;
+ }
+ delete parsedValue;
+ }
+ return false;
+}
+
+void CSSParser::addBackgroundValue(CSSValueImpl*& lval, CSSValueImpl* rval)
+{
+ if (lval) {
+ if (lval->isValueList())
+ static_cast<CSSValueListImpl*>(lval)->append(rval);
+ else {
+ CSSValueImpl* oldVal = lval;
+ CSSValueListImpl* list = new CSSValueListImpl();
+ lval = list;
+ list->append(oldVal);
+ list->append(rval);
+ }
+ }
+ else
+ lval = rval;
+}
+
+bool CSSParser::parseBackgroundShorthand(bool important)
+{
+ // Position must come before color in this array because a plain old "0" is a legal color
+ // in quirks mode but it's usually the X coordinate of a position.
+ // FIXME: Add CSS_PROP__KHTML_BACKGROUND_SIZE to the shorthand.
+ const int numProperties = 7;
+ const int properties[numProperties] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
+ CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP__KHTML_BACKGROUND_CLIP,
+ CSS_PROP__KHTML_BACKGROUND_ORIGIN, CSS_PROP_BACKGROUND_COLOR };
+
+ ShorthandScope scope(this, CSS_PROP_BACKGROUND);
+
+ bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
+ CSSValueImpl* values[numProperties] = { 0 }; // compiler will repeat 0 as necessary
+ CSSValueImpl* positionYValue = 0;
+ int i;
+
+ while (valueList->current()) {
+ Value* val = valueList->current();
+ if (val->unit == Value::Operator && val->iValue == ',') {
+ // We hit the end. Fill in all remaining values with the initial value.
+ valueList->next();
+ for (i = 0; i < numProperties; ++i) {
+ if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i])
+ // Color is not allowed except as the last item in a list. Reject the entire
+ // property.
+ goto fail;
+
+ if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) {
+ addBackgroundValue(values[i], new CSSInitialValueImpl());
+ if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
+ addBackgroundValue(positionYValue, new CSSInitialValueImpl());
+ }
+ parsedProperty[i] = false;
+ }
+ if (!valueList->current())
+ break;
+ }
+
+ bool found = false;
+ for (i = 0; !found && i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ CSSValueImpl *val1 = 0, *val2 = 0;
+ int propId1, propId2;
+ if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) {
+ parsedProperty[i] = found = true;
+ addBackgroundValue(values[i], val1);
+ if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
+ addBackgroundValue(positionYValue, val2);
+ }
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ goto fail;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ addBackgroundValue(values[i], new CSSInitialValueImpl());
+ if (properties[i] == CSS_PROP_BACKGROUND_POSITION)
+ addBackgroundValue(positionYValue, new CSSInitialValueImpl());
+ }
+ }
+
+ // Now add all of the properties we found.
+ for (i = 0; i < numProperties; i++) {
+ if (properties[i] == CSS_PROP_BACKGROUND_POSITION) {
+ addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i], important);
+ addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue, important);
+ }
+ else
+ addProperty(properties[i], values[i], important);
+ }
+
+ return true;
+
+fail:
+ for (int k = 0; k < numProperties; k++)
+ delete values[k];
+ delete positionYValue;
+ return false;
+}
+
+bool CSSParser::parseShortHand(int propId, const int *properties, int numProperties, bool important )
+{
+ /* We try to match as many properties as possible
+ * We setup an array of booleans to mark which property has been found,
+ * and we try to search for properties until it makes no longer any sense
+ */
+ ShorthandScope scope(this, propId);
+
+ bool found = false;
+ bool fnd[6]; //Trust me ;)
+ for( int i = 0; i < numProperties; i++ )
+ fnd[i] = false;
+
+ while ( valueList->current() ) {
+ found = false;
+ for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
+ if (!fnd[propIndex]) {
+ if ( parseValue( properties[propIndex], important ) ) {
+ fnd[propIndex] = found = true;
+ }
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ return false;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ m_implicitShorthand = true;
+ for (int i = 0; i < numProperties; ++i) {
+ if (!fnd[i])
+ addProperty(properties[i], new CSSInitialValueImpl(), important);
+ }
+ m_implicitShorthand = false;
+
+ return true;
+}
+
+bool CSSParser::parse4Values(int propId, const int *properties, bool important )
+{
+ /* From the CSS 2 specs, 8.3
+ * If there is only one value, it applies to all sides. If there are two values, the top and
+ * bottom margins are set to the first value and the right and left margins are set to the second.
+ * If there are three values, the top is set to the first value, the left and right are set to the
+ * second, and the bottom is set to the third. If there are four values, they apply to the top,
+ * right, bottom, and left, respectively.
+ */
+
+ int num = inShorthand() ? 1 : valueList->size();
+ //tqDebug("parse4Values: num=%d %d", num, valueList->numValues );
+
+ ShorthandScope scope(this, propId);
+
+ // the order is top, right, bottom, left
+ switch (num) {
+ case 1: {
+ if (!parseValue(properties[0], important))
+ return false;
+ CSSValueImpl *value = parsedProperties[numParsedProperties-1]->value();
+ m_implicitShorthand = true;
+ addProperty(properties[1], value, important);
+ addProperty(properties[2], value, important);
+ addProperty(properties[3], value, important);
+ m_implicitShorthand = false;
+ break;
+ }
+ case 2: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
+ return false;
+ CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
+ m_implicitShorthand = true;
+ addProperty(properties[2], value, important);
+ value = parsedProperties[numParsedProperties-2]->value();
+ addProperty(properties[3], value, important);
+ m_implicitShorthand = false;
+ break;
+ }
+ case 3: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
+ return false;
+ CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value();
+ m_implicitShorthand = true;
+ addProperty(properties[3], value, important);
+ m_implicitShorthand = false;
+ break;
+ }
+ case 4: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
+ !parseValue(properties[2], important) || !parseValue(properties[3], important))
+ return false;
+ break;
+ }
+ default: {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
+// in CSS 2.1 this got somewhat reduced:
+// [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
+bool CSSParser::parseContent( int propId, bool important )
+{
+ CSSValueListImpl* values = new CSSValueListImpl();
+
+ bool isValid = true;
+ Value *val;
+ CSSValueImpl *parsedValue = 0;
+ while ( (val = valueList->current()) ) {
+ parsedValue = 0;
+ if ( val->unit == CSSPrimitiveValue::CSS_URI ) {
+ // url
+ DOMString value = tdehtml::parseURL(domString(val->string));
+ parsedValue = new CSSImageValueImpl(
+ DOMString(KURL( styleElement->baseURL(), value.string()).url() ), styleElement );
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "content, url=" << value.string() << " base=" << styleElement->baseURL().url( ) << endl;
+#endif
+ } else if ( val->unit == Value::Function ) {
+ // attr( X ) | counter( X [,Y] ) | counters( X, Y, [,Z] )
+ ValueList *args = val->function->args;
+ TQString fname = qString( val->function->name ).lower();
+ if (!args) return false;
+ if (fname == "attr(") {
+ if ( args->size() != 1)
+ return false;
+ Value *a = args->current();
+ if (a->unit != CSSPrimitiveValue::CSS_IDENT) {
+ isValid=false;
+ break;
+ }
+ if (qString(a->string)[0] == '-') {
+ isValid=false;
+ break;
+ }
+ parsedValue = new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR);
+ }
+ else
+ if (fname == "counter(") {
+ parsedValue = parseCounterContent(args, false);
+ if (!parsedValue) return false;
+ } else
+ if (fname == "counters(") {
+ parsedValue = parseCounterContent(args, true);
+ if (!parsedValue) return false;
+ }
+ else
+ return false;
+
+ } else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) {
+ // open-quote | close-quote | no-open-quote | no-close-quote
+ if ( val->id == CSS_VAL_OPEN_QUOTE ||
+ val->id == CSS_VAL_CLOSE_QUOTE ||
+ val->id == CSS_VAL_NO_OPEN_QUOTE ||
+ val->id == CSS_VAL_NO_CLOSE_QUOTE ) {
+ parsedValue = new CSSPrimitiveValueImpl(val->id);
+ }
+ } else if ( val->unit == CSSPrimitiveValue::CSS_STRING ) {
+ parsedValue = new CSSPrimitiveValueImpl(domString(val->string), CSSPrimitiveValue::CSS_STRING);
+ }
+
+ if (parsedValue)
+ values->append(parsedValue);
+ else {
+ isValid = false;
+ break;
+ }
+ valueList->next();
+ }
+ if ( isValid && values->length() ) {
+ addProperty( propId, values, important );
+ valueList->next();
+ return true;
+ }
+
+ delete values; // also frees any content by deref
+ return false;
+}
+
+CSSValueImpl* CSSParser::parseCounterContent(ValueList *args, bool counters)
+{
+ if (counters || (args->size() != 1 && args->size() != 3))
+ if (!counters || (args->size() != 3 && args->size() != 5))
+ return 0;
+
+ CounterImpl *counter = new CounterImpl;
+ Value *i = args->current();
+ if (i->unit != CSSPrimitiveValue::CSS_IDENT) goto invalid;
+ if (qString(i->string)[0] == '-') goto invalid;
+ counter->m_identifier = domString(i->string);
+ if (counters) {
+ i = args->next();
+ if (i->unit != Value::Operator || i->iValue != ',') goto invalid;
+ i = args->next();
+ if (i->unit != CSSPrimitiveValue::CSS_STRING) goto invalid;
+ counter->m_separator = domString(i->string);
+ }
+ counter->m_listStyle = CSS_VAL_DECIMAL - CSS_VAL_DISC;
+ i = args->next();
+ if (i) {
+ if (i->unit != Value::Operator || i->iValue != ',') goto invalid;
+ i = args->next();
+ if (i->unit != CSSPrimitiveValue::CSS_IDENT) goto invalid;
+ if (i->id < CSS_VAL_DISC || i->id > CSS_VAL__KHTML_CLOSE_QUOTE) goto invalid;
+ counter->m_listStyle = i->id - CSS_VAL_DISC;
+ }
+ return new CSSPrimitiveValueImpl(counter);
+invalid:
+ delete counter;
+ return 0;
+}
+
+CSSValueImpl* CSSParser::parseBackgroundColor()
+{
+ int id = valueList->current()->id;
+ if (id == CSS_VAL__KHTML_TEXT || id == CSS_VAL_TRANSPARENT ||
+ (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU ||
+ (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && !strict))
+ return new CSSPrimitiveValueImpl(id);
+ return parseColor();
+}
+
+CSSValueImpl* CSSParser::parseBackgroundImage()
+{
+ if (valueList->current()->id == CSS_VAL_NONE)
+ return new CSSImageValueImpl();
+ if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
+ DOMString uri = tdehtml::parseURL(domString(valueList->current()->string));
+ if (!uri.isEmpty())
+ return new CSSImageValueImpl(DOMString(KURL(styleElement->baseURL(), uri.string()).url()),
+ styleElement);
+ }
+ return 0;
+}
+
+CSSValueImpl* CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound)
+{
+ int id = valueList->current()->id;
+ if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) {
+ int percent = 0;
+ if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) {
+ if (xFound)
+ return 0;
+ xFound = true;
+ if (id == CSS_VAL_RIGHT)
+ percent = 100;
+ }
+ else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) {
+ if (yFound)
+ return 0;
+ yFound = true;
+ if (id == CSS_VAL_BOTTOM)
+ percent = 100;
+ }
+ else if (id == CSS_VAL_CENTER)
+ // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
+ percent = 50;
+ return new CSSPrimitiveValueImpl(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent|FLength, strict))
+ return new CSSPrimitiveValueImpl(valueList->current()->fValue,
+ (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
+
+ return 0;
+}
+
+void CSSParser::parseBackgroundPosition(CSSValueImpl*& value1, CSSValueImpl*& value2)
+{
+ value1 = value2 = 0;
+ Value* value = valueList->current();
+
+ // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
+ bool value1IsX = false, value1IsY = false;
+ value1 = parseBackgroundPositionXY(value1IsX, value1IsY);
+ if (!value1)
+ return;
+
+ // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
+ // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
+ // value was explicitly specified for our property.
+ value = valueList->next();
+
+ // First check for the comma. If so, we are finished parsing this value or value pair.
+ if (value && value->unit == Value::Operator && value->iValue == ',')
+ value = 0;
+
+ bool value2IsX = false, value2IsY = false;
+ if (value) {
+ value2 = parseBackgroundPositionXY(value2IsX, value2IsY);
+ if (value2)
+ valueList->next();
+ else {
+ if (!inShorthand()) {
+ delete value1;
+ value1 = 0;
+ return;
+ }
+ }
+ }
+
+ if (!value2)
+ // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
+ // is simply 50%. This is our default.
+ // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
+ // For left/right/center, the default of 50% in the y is still correct.
+ value2 = new CSSPrimitiveValueImpl(50, CSSPrimitiveValue::CSS_PERCENTAGE);
+
+ if (value1IsY || value2IsX) {
+ // Swap our two values.
+ CSSValueImpl* val = value2;
+ value2 = value1;
+ value1 = val;
+ }
+}
+
+CSSValueImpl* CSSParser::parseBackgroundSize()
+{
+ Value* value = valueList->current();
+ CSSPrimitiveValueImpl* parsedValue1;
+
+ if (value->id == CSS_VAL_AUTO)
+ parsedValue1 = new CSSPrimitiveValueImpl(0, CSSPrimitiveValue::CSS_UNKNOWN);
+ else {
+ if (!validUnit(value, FLength|FPercent, strict))
+ return 0;
+ parsedValue1 = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
+ }
+
+ CSSPrimitiveValueImpl* parsedValue2 = parsedValue1;
+ if ((value = valueList->next())) {
+ if (value->id == CSS_VAL_AUTO)
+ parsedValue2 = new CSSPrimitiveValueImpl(0, CSSPrimitiveValue::CSS_UNKNOWN);
+ else {
+ if (!validUnit(value, FLength|FPercent, strict)) {
+ delete parsedValue1;
+ return 0;
+ }
+ parsedValue2 = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
+ }
+ }
+
+ PairImpl* pair = new PairImpl(parsedValue1, parsedValue2);
+ return new CSSPrimitiveValueImpl(pair);
+}
+
+bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2,
+ CSSValueImpl*& retValue1, CSSValueImpl*& retValue2)
+{
+#ifdef CSS_DEBUG
+ kdDebug(6080) << "parseBackgroundProperty()" << endl;
+ kdDebug(6080) << "LOOKING FOR: " << getPropertyName(propId).string() << endl;
+#endif
+ CSSValueListImpl *values = 0, *values2 = 0;
+ Value* val;
+ CSSValueImpl *value = 0, *value2 = 0;
+ bool allowComma = false;
+
+ retValue1 = retValue2 = 0;
+ propId1 = propId;
+ propId2 = propId;
+ if (propId == CSS_PROP_BACKGROUND_POSITION) {
+ propId1 = CSS_PROP_BACKGROUND_POSITION_X;
+ propId2 = CSS_PROP_BACKGROUND_POSITION_Y;
+ }
+
+ while ((val = valueList->current())) {
+ CSSValueImpl *currValue = 0, *currValue2 = 0;
+ if (allowComma) {
+ if (val->unit != Value::Operator || val->iValue != ',')
+ goto failed;
+ valueList->next();
+ allowComma = false;
+ }
+ else {
+ switch (propId) {
+ case CSS_PROP_BACKGROUND_ATTACHMENT:
+ if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) {
+ currValue = new CSSPrimitiveValueImpl(val->id);
+ valueList->next();
+ }
+ break;
+ case CSS_PROP_BACKGROUND_COLOR:
+ currValue = parseBackgroundColor();
+ if (currValue)
+ valueList->next();
+ break;
+ case CSS_PROP_BACKGROUND_IMAGE:
+ currValue = parseBackgroundImage();
+ if (currValue)
+ valueList->next();
+ break;
+ case CSS_PROP__KHTML_BACKGROUND_CLIP:
+ case CSS_PROP__KHTML_BACKGROUND_ORIGIN:
+ if (val->id == CSS_VAL_BORDER || val->id == CSS_VAL_PADDING || val->id == CSS_VAL_CONTENT) {
+ currValue = new CSSPrimitiveValueImpl(val->id);
+ valueList->next();
+ }
+ break;
+ case CSS_PROP_BACKGROUND_POSITION:
+ parseBackgroundPosition(currValue, currValue2);
+ // unlike the other functions, parseBackgroundPosition advances the valueList pointer
+ break;
+ case CSS_PROP_BACKGROUND_POSITION_X: {
+ bool xFound = false, yFound = true;
+ currValue = parseBackgroundPositionXY(xFound, yFound);
+ if (currValue)
+ valueList->next();
+ break;
+ }
+ case CSS_PROP_BACKGROUND_POSITION_Y: {
+ bool xFound = true, yFound = false;
+ currValue = parseBackgroundPositionXY(xFound, yFound);
+ if (currValue)
+ valueList->next();
+ break;
+ }
+ case CSS_PROP_BACKGROUND_REPEAT:
+ if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) {
+ currValue = new CSSPrimitiveValueImpl(val->id);
+ valueList->next();
+ }
+ break;
+ case CSS_PROP__KHTML_BACKGROUND_SIZE:
+ currValue = parseBackgroundSize();
+ if (currValue)
+ valueList->next();
+ break;
+ }
+
+ if (!currValue)
+ goto failed;
+
+ if (value && !values) {
+ values = new CSSValueListImpl();
+ values->append(value);
+ value = 0;
+ }
+
+ if (value2 && !values2) {
+ values2 = new CSSValueListImpl();
+ values2->append(value2);
+ value2 = 0;
+ }
+
+ if (values)
+ values->append(currValue);
+ else
+ value = currValue;
+ if (currValue2) {
+ if (values2)
+ values2->append(currValue2);
+ else
+ value2 = currValue2;
+ }
+ allowComma = true;
+ }
+
+ // When parsing the 'background' shorthand property, we let it handle building up the lists for all
+ // properties.
+ if (inShorthand())
+ break;
+ }
+
+ if (values && values->length()) {
+ retValue1 = values;
+ if (values2 && values2->length())
+ retValue2 = values2;
+ return true;
+ }
+ if (value) {
+ retValue1 = value;
+ retValue2 = value2;
+ return true;
+ }
+
+failed:
+ delete values; delete values2;
+ delete value; delete value2;
+ return false;
+}
+
+bool CSSParser::parseShape( int propId, bool important )
+{
+ Value *value = valueList->current();
+ ValueList *args = value->function->args;
+ TQString fname = qString( value->function->name ).lower();
+ //tqDebug( "parseShape: fname: %d", fname.latin1() );
+ if ( fname != "rect(" || !args )
+ return false;
+
+ // rect( t, r, b, l ) || rect( t r b l )
+ if ( args->size() != 4 && args->size() != 7 )
+ return false;
+ RectImpl *rect = new RectImpl();
+ bool valid = true;
+ int i = 0;
+ Value *a = args->current();
+ while ( a ) {
+ valid = validUnit( a, FLength, strict );
+ if ( !valid )
+ break;
+ CSSPrimitiveValueImpl *length =
+ new CSSPrimitiveValueImpl( a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit );
+ if ( i == 0 )
+ rect->setTop( length );
+ else if ( i == 1 )
+ rect->setRight( length );
+ else if ( i == 2 )
+ rect->setBottom( length );
+ else
+ rect->setLeft( length );
+ a = args->next();
+ if ( a && args->size() == 7 ) {
+ if ( a->unit == Value::Operator && a->iValue == ',' ) {
+ a = args->next();
+ } else {
+ valid = false;
+ break;
+ }
+ }
+ i++;
+ }
+ if ( valid ) {
+ addProperty( propId, new CSSPrimitiveValueImpl( rect ), important );
+ valueList->next();
+ return true;
+ }
+ delete rect;
+ return false;
+}
+
+// [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
+bool CSSParser::parseFont( bool important )
+{
+// kdDebug(6080) << "parsing font property current=" << valueList->currentValue << endl;
+ bool valid = true;
+ Value *value = valueList->current();
+ CSSValueListImpl* family = 0;
+ CSSPrimitiveValueImpl *style = 0, *variant = 0, *weight = 0, *size = 0, *lineHeight = 0;
+ // optional font-style, font-variant and font-weight
+ while ( value ) {
+// kdDebug( 6080 ) << "got value " << value->id << " / " << (value->unit == CSSPrimitiveValue::CSS_STRING ||
+ // value->unit == CSSPrimitiveValue::CSS_IDENT ? qString( value->string ) : TQString::null )
+// << endl;
+ int id = value->id;
+ if ( id ) {
+ if ( id == CSS_VAL_NORMAL ) {
+ // do nothing, it's the initial value for all three
+ }
+ /*
+ else if ( id == CSS_VAL_INHERIT ) {
+ // set all non set ones to inherit
+ // This is not that simple as the inherit could also apply to the following font-size.
+ // very ahrd to tell without looking ahead.
+ inherit = true;
+ } */
+ else if ( id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE ) {
+ if ( style )
+ goto invalid;
+ style = new CSSPrimitiveValueImpl( id );
+ } else if ( id == CSS_VAL_SMALL_CAPS ) {
+ if ( variant )
+ goto invalid;
+ variant = new CSSPrimitiveValueImpl( id );
+ } else if ( id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER ) {
+ if ( weight )
+ goto invalid;
+ weight = new CSSPrimitiveValueImpl( id );
+ } else {
+ valid = false;
+ }
+ } else if ( !weight && validUnit( value, FInteger|FNonNeg, true ) ) {
+ int w = (int)value->fValue;
+ int val = 0;
+ if ( w == 100 )
+ val = CSS_VAL_100;
+ else if ( w == 200 )
+ val = CSS_VAL_200;
+ else if ( w == 300 )
+ val = CSS_VAL_300;
+ else if ( w == 400 )
+ val = CSS_VAL_400;
+ else if ( w == 500 )
+ val = CSS_VAL_500;
+ else if ( w == 600 )
+ val = CSS_VAL_600;
+ else if ( w == 700 )
+ val = CSS_VAL_700;
+ else if ( w == 800 )
+ val = CSS_VAL_800;
+ else if ( w == 900 )
+ val = CSS_VAL_900;
+
+ if ( val )
+ weight = new CSSPrimitiveValueImpl( val );
+ else
+ valid = false;
+ } else {
+ valid = false;
+ }
+ if ( !valid )
+ break;
+ value = valueList->next();
+ }
+ if ( !value )
+ goto invalid;
+
+ // set undefined values to default
+ if ( !style )
+ style = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
+ if ( !variant )
+ variant = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
+ if ( !weight )
+ weight = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
+
+// kdDebug( 6080 ) << " got style, variant and weight current=" << valueList->currentValue << endl;
+
+ // now a font size _must_ come
+ // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
+ if ( value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER )
+ size = new CSSPrimitiveValueImpl( value->id );
+ else if ( validUnit( value, FLength|FPercent, strict ) ) {
+ size = new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
+ }
+ value = valueList->next();
+ if ( !size || !value )
+ goto invalid;
+
+ // kdDebug( 6080 ) << " got size" << endl;
+
+ if ( value->unit == Value::Operator && value->iValue == '/' ) {
+ // line-height
+ value = valueList->next();
+ if ( !value )
+ goto invalid;
+ if ( value->id == CSS_VAL_NORMAL ) {
+ // default value, nothing to do
+ } else if ( validUnit( value, FNumber|FLength|FPercent, strict ) ) {
+ lineHeight = new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit );
+ } else {
+ goto invalid;
+ }
+ value = valueList->next();
+ if ( !value )
+ goto invalid;
+ }
+ if ( !lineHeight )
+ lineHeight = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL );
+
+// kdDebug( 6080 ) << " got line height current=" << valueList->currentValue << endl;
+ // font family must come now
+ family = parseFontFamily();
+
+ if ( valueList->current() || !family )
+ goto invalid;
+ //kdDebug( 6080 ) << " got family, parsing ok!" << endl;
+
+ addProperty( CSS_PROP_FONT_FAMILY, family, important );
+ addProperty( CSS_PROP_FONT_STYLE, style, important );
+ addProperty( CSS_PROP_FONT_VARIANT, variant, important );
+ addProperty( CSS_PROP_FONT_WEIGHT, weight, important );
+ addProperty( CSS_PROP_FONT_SIZE, size, important );
+ addProperty( CSS_PROP_LINE_HEIGHT, lineHeight, important );
+ return true;
+
+ invalid:
+ //kdDebug(6080) << " -> invalid" << endl;
+ delete family;
+ delete style;
+ delete variant;
+ delete weight;
+ delete size;
+ delete lineHeight;
+
+ return false;
+}
+
+CSSValueListImpl *CSSParser::parseFontFamily()
+{
+// kdDebug( 6080 ) << "CSSParser::parseFontFamily current=" << valueList->currentValue << endl;
+ CSSValueListImpl *list = new CSSValueListImpl;
+ Value *value = valueList->current();
+ TQString currFace;
+
+ while ( value ) {
+// kdDebug( 6080 ) << "got value " << value->id << " / "
+// << (value->unit == CSSPrimitiveValue::CSS_STRING ||
+// value->unit == CSSPrimitiveValue::CSS_IDENT ? qString( value->string ) : TQString::null )
+// << endl;
+ Value* nextValue = valueList->next();
+ bool nextValBreaksFont = !nextValue ||
+ (nextValue->unit == Value::Operator && nextValue->iValue == ',');
+ bool nextValIsFontName = nextValue &&
+ ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL_MONOSPACE) ||
+ (nextValue->unit == CSSPrimitiveValue::CSS_STRING ||
+ nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
+
+ if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL_MONOSPACE) {
+ if (!currFace.isNull()) {
+ currFace += ' ';
+ currFace += qString(value->string);
+ }
+ else if (nextValBreaksFont || !nextValIsFontName) {
+ if ( !currFace.isNull() ) {
+ list->append( new FontFamilyValueImpl( currFace ) );
+ currFace = TQString::null;
+ }
+ list->append(new CSSPrimitiveValueImpl(value->id));
+ }
+ else {
+ currFace = qString( value->string );
+ }
+ }
+ else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
+ // Strings never share in a family name.
+ currFace = TQString::null;
+ list->append(new FontFamilyValueImpl(qString( value->string) ) );
+ }
+ else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
+ if (!currFace.isNull()) {
+ currFace += ' ';
+ currFace += qString(value->string);
+ }
+ else if (nextValBreaksFont || !nextValIsFontName) {
+ if ( !currFace.isNull() ) {
+ list->append( new FontFamilyValueImpl( currFace ) );
+ currFace = TQString::null;
+ }
+ list->append(new FontFamilyValueImpl( qString( value->string ) ) );
+ }
+ else {
+ currFace = qString( value->string);
+ }
+ }
+ else {
+ //kdDebug( 6080 ) << "invalid family part" << endl;
+ break;
+ }
+
+ if (!nextValue)
+ break;
+
+ if (nextValBreaksFont) {
+ value = valueList->next();
+ if ( !currFace.isNull() )
+ list->append( new FontFamilyValueImpl( currFace ) );
+ currFace = TQString::null;
+ }
+ else if (nextValIsFontName)
+ value = nextValue;
+ else
+ break;
+ }
+
+ if ( !currFace.isNull() )
+ list->append( new FontFamilyValueImpl( currFace ) );
+
+ if ( !list->length() ) {
+ delete list;
+ list = 0;
+ }
+ return list;
+}
+
+
+bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha)
+{
+ ValueList* args = value->function->args;
+ Value* v = args->current();
+ // Get the first value
+ if (!validUnit(v, FInteger | FPercent, true))
+ return false;
+ colorArray[0] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
+ for (int i = 1; i < 3; i++) {
+ v = args->next();
+ if (v->unit != Value::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FInteger | FPercent, true))
+ return false;
+ colorArray[i] = static_cast<int>(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0));
+ }
+ if (parseAlpha) {
+ v = args->next();
+ if (v->unit != Value::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FNumber, true))
+ return false;
+ colorArray[3] = static_cast<int>(kMax(0.0, kMin(1.0, v->fValue)) * 255);
+ }
+ return true;
+}
+
+// CSS3 specification defines the format of a HSL color as
+// hsl(<number>, <percent>, <percent>)
+// and with alpha, the format is
+// hsla(<number>, <percent>, <percent>, <number>)
+// The first value, HUE, is in an angle with a value between 0 and 360
+bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha)
+{
+ ValueList* args = value->function->args;
+ Value* v = args->current();
+ // Get the first value
+ if (!validUnit(v, FInteger, true))
+ return false;
+ // normalize the Hue value and change it to be between 0 and 1.0
+ colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0;
+ for (int i = 1; i < 3; i++) {
+ v = args->next();
+ if (v->unit != Value::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FPercent, true))
+ return false;
+ colorArray[i] = kMax(0.0, kMin(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0
+ }
+ if (parseAlpha) {
+ v = args->next();
+ if (v->unit != Value::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FNumber, true))
+ return false;
+ colorArray[3] = kMax(0.0, kMin(1.0, v->fValue));
+ }
+ return true;
+}
+
+static bool parseColor(int unit, const TQString &name, QRgb& rgb)
+{
+ int len = name.length();
+
+ if ( !len )
+ return false;
+
+
+ bool ok;
+
+ if ( len == 3 || len == 6 ) {
+ int val = name.toInt(&ok, 16);
+ if ( ok ) {
+ if (len == 6) {
+ rgb = (0xff << 24) | val;
+ return true;
+ }
+ else if ( len == 3 ) {
+ // #abc converts to #aabbcc according to the specs
+ rgb = (0xff << 24) |
+ (val&0xf00)<<12 | (val&0xf00)<<8 |
+ (val&0xf0)<<8 | (val&0xf0)<<4 |
+ (val&0xf)<<4 | (val&0xf);
+ return true;
+ }
+ }
+ }
+
+ if ( unit == CSSPrimitiveValue::CSS_IDENT ) {
+ // try a little harder
+ TQColor tc;
+ tc.setNamedColor(name.lower());
+ if ( tc.isValid() ) {
+ rgb = tc.rgb();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+CSSPrimitiveValueImpl *CSSParser::parseColor()
+{
+ return parseColorFromValue(valueList->current());
+}
+
+CSSPrimitiveValueImpl *CSSParser::parseColorFromValue(Value* value)
+{
+ QRgb c = tdehtml::transparentColor;
+ if ( !strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
+ value->fValue >= 0. && value->fValue < 1000000. ) {
+ TQString str;
+ str.sprintf( "%06d", (int)(value->fValue+.5) );
+ if ( !::parseColor( value->unit, str, c ) )
+ return 0;
+ }
+ else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
+ value->unit == CSSPrimitiveValue::CSS_IDENT ||
+ (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
+ if ( !::parseColor( value->unit, qString( value->string ), c) )
+ return 0;
+ }
+ else if ( value->unit == Value::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 5 /* rgb + two commas */ &&
+ qString( value->function->name ).lower() == "rgb(" ) {
+ int colorValues[3];
+ if (!parseColorParameters(value, colorValues, false))
+ return 0;
+ colorValues[0] = kMax( 0, kMin( 255, colorValues[0] ) );
+ colorValues[1] = kMax( 0, kMin( 255, colorValues[1] ) );
+ colorValues[2] = kMax( 0, kMin( 255, colorValues[2] ) );
+ c = tqRgb(colorValues[0], colorValues[1], colorValues[2]);
+ } else if (value->unit == Value::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 7 /* rgba + three commas */ &&
+ domString(value->function->name).lower() == "rgba(") {
+ int colorValues[4];
+ if (!parseColorParameters(value, colorValues, true))
+ return 0;
+ colorValues[0] = kMax( 0, kMin( 255, colorValues[0] ) );
+ colorValues[1] = kMax( 0, kMin( 255, colorValues[1] ) );
+ colorValues[2] = kMax( 0, kMin( 255, colorValues[2] ) );
+ c = tqRgba(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
+ } else if (value->unit == Value::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 5 /* hsl + two commas */ &&
+ domString(value->function->name).lower() == "hsl(") {
+ double colorValues[3];
+ if (!parseHSLParameters(value, colorValues, false))
+ return 0;
+ c = tdehtml::tqRgbaFromHsla(colorValues[0], colorValues[1], colorValues[2], 1.0);
+ } else if (value->unit == Value::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 7 /* hsla + three commas */ &&
+ domString(value->function->name).lower() == "hsla(") {
+ double colorValues[4];
+ if (!parseHSLParameters(value, colorValues, true))
+ return 0;
+ c = tdehtml::tqRgbaFromHsla(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
+ }
+ else
+ return 0;
+
+ return new CSSPrimitiveValueImpl(c);
+}
+
+// This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return)
+// without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
+struct ShadowParseContext {
+ ShadowParseContext()
+ :values(0), x(0), y(0), blur(0), color(0),
+ allowX(true), allowY(false), allowBlur(false), allowColor(true),
+ allowBreak(true)
+ {}
+
+ ~ShadowParseContext() {
+ if (!allowBreak) {
+ delete values;
+ delete x;
+ delete y;
+ delete blur;
+ delete color;
+ }
+ }
+
+ bool allowLength() { return allowX || allowY || allowBlur; }
+
+ bool failed() { return allowBreak = false; }
+
+ void commitValue() {
+ // Handle the ,, case gracefully by doing nothing.
+ if (x || y || blur || color) {
+ if (!values)
+ values = new CSSValueListImpl();
+
+ // Construct the current shadow value and add it to the list.
+ values->append(new ShadowValueImpl(x, y, blur, color));
+ }
+
+ // Now reset for the next shadow value.
+ x = y = blur = color = 0;
+ allowX = allowColor = allowBreak = true;
+ allowY = allowBlur = false;
+ }
+
+ void commitLength(Value* v) {
+ CSSPrimitiveValueImpl* val = new CSSPrimitiveValueImpl(v->fValue,
+ (CSSPrimitiveValue::UnitTypes)v->unit);
+ if (allowX) {
+ x = val;
+ allowX = false; allowY = true; allowColor = false; allowBreak = false;
+ }
+ else if (allowY) {
+ y = val;
+ allowY = false; allowBlur = true; allowColor = true; allowBreak = true;
+ }
+ else if (allowBlur) {
+ blur = val;
+ allowBlur = false;
+ }
+ else
+ delete val;
+ }
+
+ void commitColor(CSSPrimitiveValueImpl* val) {
+ color = val;
+ allowColor = false;
+ if (allowX)
+ allowBreak = false;
+ else
+ allowBlur = false;
+ }
+
+ CSSValueListImpl* values;
+ CSSPrimitiveValueImpl* x;
+ CSSPrimitiveValueImpl* y;
+ CSSPrimitiveValueImpl* blur;
+ CSSPrimitiveValueImpl* color;
+
+ bool allowX;
+ bool allowY;
+ bool allowBlur;
+ bool allowColor;
+ bool allowBreak;
+};
+
+bool CSSParser::parseShadow(int propId, bool important)
+{
+ ShadowParseContext context;
+ Value* val;
+ while ((val = valueList->current())) {
+ // Check for a comma break first.
+ if (val->unit == Value::Operator) {
+ if (val->iValue != ',' || !context.allowBreak)
+ // Other operators aren't legal or we aren't done with the current shadow
+ // value. Treat as invalid.
+ return context.failed();
+
+ // The value is good. Commit it.
+ context.commitValue();
+ }
+ // Check to see if we're a length.
+ else if (validUnit(val, FLength, true)) {
+ // We required a length and didn't get one. Invalid.
+ if (!context.allowLength())
+ return context.failed();
+
+ // A length is allowed here. Construct the value and add it.
+ context.commitLength(val);
+ }
+ else {
+ // The only other type of value that's ok is a color value.
+ CSSPrimitiveValueImpl* parsedColor = 0;
+ bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
+ (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KHTML_TEXT && !strict));
+ if (!context.allowColor)
+ return context.failed();
+
+ if (isColor)
+ parsedColor = new CSSPrimitiveValueImpl(val->id);
+
+ if (!parsedColor)
+ // It's not built-in. Try to parse it as a color.
+ parsedColor = parseColorFromValue(val);
+
+ if (!parsedColor)
+ return context.failed();
+
+ context.commitColor(parsedColor);
+ }
+
+ valueList->next();
+ }
+
+ if (context.allowBreak) {
+ context.commitValue();
+ if (context.values->length()) {
+ addProperty(propId, context.values, important);
+ valueList->next();
+ return true;
+ }
+ }
+
+ return context.failed();
+}
+
+bool CSSParser::parseCounter(int propId, bool increment, bool important)
+{
+ enum { ID, VAL, COMMA } state = ID;
+
+ CSSValueListImpl *list = new CSSValueListImpl;
+ DOMString c;
+ Value* val;
+ while (true) {
+ val = valueList->current();
+ switch (state) {
+ // Commas are not allowed according to the standard, but Opera allows them and being the only
+ // other browser with counter support we need to match their behavior to work with current use
+ case COMMA:
+ state = ID;
+ if (val && val->unit == Value::Operator && val->iValue == ',') {
+ valueList->next();
+ continue;
+ }
+ // no break
+ case ID:
+ if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
+ c = qString(val->string);
+ state = VAL;
+ valueList->next();
+ continue;
+ }
+ break;
+ case VAL: {
+ short i = 0;
+ if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
+ i = (short)val->fValue;
+ valueList->next();
+ } else
+ i = (increment) ? 1 : 0;
+
+ CounterActImpl *cv = new CounterActImpl(c,i);
+ list->append(cv);
+ state = COMMA;
+ continue;
+ }
+ }
+ break;
+ }
+ if(list->length() > 0) {
+ addProperty( propId, list, important );
+ return true;
+ }
+ delete list;
+ return false;
+}
+
+static inline int yyerror( const char *str ) {
+// assert( 0 );
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "CSS parse error " << str << endl;
+#else
+ Q_UNUSED( str );
+#endif
+ return 1;
+}
+
+#define END 0
+
+#include "parser.h"
+
+int DOM::CSSParser::lex( void *_yylval )
+{
+ YYSTYPE *yylval = (YYSTYPE *)_yylval;
+ int token = lex();
+ int length;
+ unsigned short *t = text( &length );
+
+#ifdef TOKEN_DEBUG
+ tqDebug("CSSTokenizer: got token %d: '%s'", token, token == END ? "" : TQString( (TQChar *)t, length ).latin1() );
+#endif
+ switch( token ) {
+ case '{':
+ block_nesting++;
+ break;
+ case '}':
+ if ( block_nesting )
+ block_nesting--;
+ break;
+ case END:
+ if ( block_nesting ) {
+ block_nesting--;
+ return '}';
+ }
+ break;
+ case S:
+ case SGML_CD:
+ case INCLUDES:
+ case DASHMATCH:
+ break;
+
+ case URI:
+ case STRING:
+ case IDENT:
+ case NTH:
+ case HASH:
+ case DIMEN:
+ case UNICODERANGE:
+ case NOTFUNCTION:
+ case FUNCTION:
+ yylval->string.string = t;
+ yylval->string.length = length;
+ break;
+
+ case IMPORT_SYM:
+ case PAGE_SYM:
+ case MEDIA_SYM:
+ case FONT_FACE_SYM:
+ case CHARSET_SYM:
+ case NAMESPACE_SYM:
+
+ case IMPORTANT_SYM:
+ break;
+
+ case QEMS:
+ length--;
+ case GRADS:
+ length--;
+ case DEGS:
+ case RADS:
+ case KHERZ:
+ length--;
+ case MSECS:
+ case HERZ:
+ case EMS:
+ case EXS:
+ case PXS:
+ case CMS:
+ case MMS:
+ case INS:
+ case PTS:
+ case PCS:
+ length--;
+ case SECS:
+ case PERCENTAGE:
+ length--;
+ case FLOAT:
+ case INTEGER:
+ yylval->val = TQString( (TQChar *)t, length ).toDouble();
+ //tqDebug("value = %s, converted=%.2f", TQString( (TQChar *)t, length ).latin1(), yylval->val );
+ break;
+
+ default:
+ break;
+ }
+
+ return token;
+}
+
+static inline int toHex( char c ) {
+ if ( '0' <= c && c <= '9' )
+ return c - '0';
+ if ( 'a' <= c && c <= 'f' )
+ return c - 'a' + 10;
+ if ( 'A' <= c && c<= 'F' )
+ return c - 'A' + 10;
+ return 0;
+}
+
+unsigned short *DOM::CSSParser::text(int *length)
+{
+ unsigned short *start = yytext;
+ int l = yyleng;
+ switch( yyTok ) {
+ case STRING:
+ l--;
+ /* nobreak */
+ case HASH:
+ start++;
+ l--;
+ break;
+ case URI:
+ // "url("{w}{string}{w}")"
+ // "url("{w}{url}{w}")"
+
+ // strip "url(" and ")"
+ start += 4;
+ l -= 5;
+ // strip {w}
+ while ( l &&
+ (*start == ' ' || *start == '\t' || *start == '\r' ||
+ *start == '\n' || *start == '\f' ) ) {
+ start++; l--;
+ }
+ if ( *start == '"' || *start == '\'' ) {
+ start++; l--;
+ }
+ while ( l &&
+ (start[l-1] == ' ' || start[l-1] == '\t' || start[l-1] == '\r' ||
+ start[l-1] == '\n' || start[l-1] == '\f' ) ) {
+ l--;
+ }
+ if ( l && (start[l-1] == '\"' || start[l-1] == '\'' ) )
+ l--;
+
+ default:
+ break;
+ }
+
+ // process escapes
+ unsigned short *out = start;
+ unsigned short *escape = 0;
+
+ for ( int i = 0; i < l; i++ ) {
+ unsigned short *current = start+i;
+ if ( escape == current - 1 ) {
+ if ( ( *current >= '0' && *current <= '9' ) ||
+ ( *current >= 'a' && *current <= 'f' ) ||
+ ( *current >= 'A' && *current <= 'F' ) )
+ continue;
+ if ( yyTok == STRING &&
+ ( *current == '\n' || *current == '\r' || *current == '\f' ) ) {
+ // ### handle \r\n case
+ if ( *current != '\r' )
+ escape = 0;
+ continue;
+ }
+ // in all other cases copy the char to output
+ // ###
+ *out++ = *current;
+ escape = 0;
+ continue;
+ }
+ if ( escape == current - 2 && yyTok == STRING &&
+ *(current-1) == '\r' && *current == '\n' ) {
+ escape = 0;
+ continue;
+ }
+ if ( escape > current - 7 &&
+ ( ( *current >= '0' && *current <= '9' ) ||
+ ( *current >= 'a' && *current <= 'f' ) ||
+ ( *current >= 'A' && *current <= 'F' ) ) )
+ continue;
+ if ( escape ) {
+ // add escaped char
+ int uc = 0;
+ escape++;
+ while ( escape < current ) {
+// tqDebug("toHex( %c = %x", (char)*escape, toHex( *escape ) );
+ uc *= 16;
+ uc += toHex( *escape );
+ escape++;
+ }
+// tqDebug(" converting escape: string='%s', value=0x%x", TQString( (TQChar *)e, current-e ).latin1(), uc );
+ // can't handle chars outside ucs2
+ if ( uc > 0xffff )
+ uc = 0xfffd;
+ *(out++) = (unsigned short)uc;
+ escape = 0;
+ if ( *current == ' ' ||
+ *current == '\t' ||
+ *current == '\r' ||
+ *current == '\n' ||
+ *current == '\f' )
+ continue;
+ }
+ if ( !escape && *current == '\\' ) {
+ escape = current;
+ continue;
+ }
+ *(out++) = *current;
+ }
+ if ( escape ) {
+ // add escaped char
+ int uc = 0;
+ escape++;
+ while ( escape < start+l ) {
+ // tqDebug("toHex( %c = %x", (char)*escape, toHex( *escape ) );
+ uc *= 16;
+ uc += toHex( *escape );
+ escape++;
+ }
+ // tqDebug(" converting escape: string='%s', value=0x%x", TQString( (TQChar *)e, current-e ).latin1(), uc );
+ // can't handle chars outside ucs2
+ if ( uc > 0xffff )
+ uc = 0xfffd;
+ *(out++) = (unsigned short)uc;
+ }
+
+ *length = out - start;
+ return start;
+}
+
+
+#define YY_DECL int DOM::CSSParser::lex()
+#define yyconst const
+typedef int yy_state_type;
+typedef unsigned int YY_CHAR;
+// this line makes sure we treat all Unicode chars correctly.
+#define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c)
+#define YY_DO_BEFORE_ACTION \
+ yytext = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = 0; \
+ yy_c_buf_p = yy_cp;
+#define YY_BREAK break;
+#define ECHO tqDebug( "%s", TQString( (TQChar *)yytext, yyleng ).latin1() )
+#define YY_RULE_SETUP
+#define INITIAL 0
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+#define YY_START ((yy_start - 1) / 2)
+#define yyterminate() yyTok = END; return yyTok
+#define YY_FATAL_ERROR(a) tqFatal(a)
+#define BEGIN yy_start = 1 + 2 *
+#define COMMENT 1
+
+#include "tokenizer.cpp"
diff --git a/tdehtml/css/cssparser.h b/tdehtml/css/cssparser.h
new file mode 100644
index 000000000..0e00ebc16
--- /dev/null
+++ b/tdehtml/css/cssparser.h
@@ -0,0 +1,201 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (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 _CSS_cssparser_h_
+#define _CSS_cssparser_h_
+
+#include <tqstring.h>
+#include <tqcolor.h>
+#include <tqvaluevector.h>
+#include <dom/dom_string.h>
+
+namespace DOM {
+ class StyleListImpl;
+ class CSSStyleSheetImpl;
+ class CSSRuleImpl;
+ class CSSStyleRuleImpl;
+ class DocumentImpl;
+ class CSSValueImpl;
+ class CSSValueListImpl;
+ class CSSPrimitiveValueImpl;
+ class CSSStyleDeclarationImpl;
+ class CSSProperty;
+ class CSSRuleListImpl;
+
+
+ struct ParseString {
+ unsigned short *string;
+ int length;
+ };
+
+ struct Value;
+ class ValueList;
+
+ struct Function {
+ ParseString name;
+ ValueList *args;
+ };
+
+ struct Value {
+ int id;
+ bool isInt;
+ union {
+ double fValue;
+ int iValue;
+ ParseString string;
+ struct Function *function;
+ };
+ enum {
+ Operator = 0x100000,
+ Function = 0x100001,
+ Q_EMS = 0x100002
+ };
+
+ int unit;
+ };
+
+ static inline TQString qString( const ParseString &ps ) {
+ return TQString( (TQChar *)ps.string, ps.length );
+ }
+ static inline DOMString domString( const ParseString &ps ) {
+ return DOMString( (TQChar *)ps.string, ps.length );
+ }
+
+ class ValueList {
+ public:
+ ValueList() : m_current(0) { }
+ ~ValueList();
+ void addValue(const Value& v) { m_values.append(v); }
+ unsigned int size() const { return m_values.size(); }
+ Value* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
+ Value* next() { ++m_current; return current(); }
+ private:
+ TQValueVector<Value> m_values;
+ unsigned int m_current;
+ };
+
+ class CSSParser
+ {
+ public:
+ CSSParser( bool strictParsing = true );
+ ~CSSParser();
+
+ void parseSheet( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string );
+ DOM::CSSRuleImpl *parseRule( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string );
+ bool parseValue( DOM::CSSStyleDeclarationImpl *decls, int id, const DOM::DOMString &string,
+ bool _important, bool _nonCSSHint );
+ bool parseDeclaration( DOM::CSSStyleDeclarationImpl *decls, const DOM::DOMString &string,
+ bool _nonCSSHint );
+
+ static CSSParser *current() { return currentParser; }
+
+
+ DOM::DocumentImpl *document() const;
+
+ unsigned int defaultNamespace();
+
+ void addProperty( int propId, CSSValueImpl *value, bool important );
+ bool hasProperties() const { return numParsedProperties > 0; }
+ CSSStyleDeclarationImpl *createStyleDeclaration( CSSStyleRuleImpl *rule );
+ void clearProperties();
+
+ bool parseValue( int propId, bool important );
+ bool parseShortHand( int propId, const int *properties, int numProperties, bool important );
+ bool parse4Values( int propId, const int *properties, bool important );
+ bool parseContent( int propId, bool important );
+
+ CSSValueImpl* parseBackgroundColor();
+ CSSValueImpl* parseBackgroundImage();
+ CSSValueImpl* parseBackgroundPositionXY(bool& xFound, bool& yFound);
+ void parseBackgroundPosition(CSSValueImpl*& value1, CSSValueImpl*& value2);
+ CSSValueImpl* parseBackgroundSize();
+
+ bool parseBackgroundProperty(int propId, int& propId1, int& propId2, CSSValueImpl*& retValue1, CSSValueImpl*& retValue2);
+ bool parseBackgroundShorthand(bool important);
+
+ void addBackgroundValue(CSSValueImpl*& lval, CSSValueImpl* rval);
+
+ bool parseShape( int propId, bool important );
+ bool parseFont(bool important);
+ bool parseCounter(int propId, bool increment, bool important);
+
+ bool parseColorParameters(Value*, int* colorValues, bool parseAlpha);
+ bool parseHSLParameters(Value*, double* colorValues, bool parseAlpha);
+
+ // returns the found property
+ // 0 if nothing found (or ok == false)
+ // @param forward if true, it parses the next in the list
+ CSSValueListImpl *parseFontFamily();
+ CSSPrimitiveValueImpl *parseColor();
+ CSSPrimitiveValueImpl *parseColorFromValue(Value* val);
+ CSSValueImpl* parseCounterContent(ValueList *args, bool counters);
+
+ static bool parseColor(const TQString &name, QRgb& rgb);
+
+ // CSS3 Parsing Routines (for properties specific to CSS3)
+ bool parseShadow(int propId, bool important);
+
+ bool parseBorderImage(int propId, bool important);
+
+ public:
+ bool strict;
+ bool important;
+ bool nonCSSHint;
+ unsigned int id;
+ DOM::StyleListImpl* styleElement;
+ DOM::CSSRuleImpl *rule;
+ ValueList *valueList;
+ CSSProperty **parsedProperties;
+ int numParsedProperties;
+ int maxParsedProperties;
+
+ int m_inParseShorthand;
+ int m_currentShorthand;
+ bool m_implicitShorthand;
+
+ static CSSParser *currentParser;
+
+ // tokenizer methods and data
+ public:
+ int lex( void *yylval );
+ int token() { return yyTok; }
+ unsigned short *text( int *length);
+ int lex();
+ private:
+ int yyparse();
+ void runParser(int length);
+
+ bool inShorthand() const { return m_inParseShorthand; }
+
+ unsigned short *data;
+ unsigned short *yytext;
+ unsigned short *yy_c_buf_p;
+ unsigned short yy_hold_char;
+ int yy_last_accepting_state;
+ unsigned short *yy_last_accepting_cpos;
+ int block_nesting;
+ int yyleng;
+ int yyTok;
+ int yy_start;
+ };
+
+} // namespace
+#endif
diff --git a/tdehtml/css/cssproperties.c b/tdehtml/css/cssproperties.c
new file mode 100644
index 000000000..da5208412
--- /dev/null
+++ b/tdehtml/css/cssproperties.c
@@ -0,0 +1,678 @@
+/* ANSI-C code produced by gperf version 3.0.2 */
+/* Command-line: gperf -a -L ANSI-C -E -C -c -o -t -k '*' -NfindProp -Hhash_prop -Wwordlist_prop -D -s 2 cssproperties.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 "cssproperties.gperf"
+
+/* This file is automatically generated from cssproperties.in by makeprop, do not edit */
+/* Copyright 1999 W. Bastian */
+#include "cssproperties.h"
+#line 6 "cssproperties.gperf"
+struct props {
+ const char *name;
+ int id;
+};
+
+static const struct props * findProp (register const char *str, register unsigned int len);
+/* maximum key range = 469, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_prop (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 0, 472, 472, 472, 472,
+ 472, 0, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 10, 0, 0,
+ 5, 5, 120, 0, 0, 0, 472, 15, 5, 0,
+ 25, 0, 0, 50, 0, 30, 0, 40, 0, 140,
+ 35, 180, 80, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472, 472, 472, 472, 472,
+ 472, 472, 472, 472, 472, 472
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ 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 props *
+findProp (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 129,
+ MIN_WORD_LENGTH = 3,
+ MAX_WORD_LENGTH = 32,
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 471
+ };
+
+ static const struct props wordlist_prop[] =
+ {
+#line 108 "cssproperties.gperf"
+ {"top", CSS_PROP_TOP},
+#line 99 "cssproperties.gperf"
+ {"right", CSS_PROP_RIGHT},
+#line 40 "cssproperties.gperf"
+ {"bottom", CSS_PROP_BOTTOM},
+#line 43 "cssproperties.gperf"
+ {"clip", CSS_PROP_CLIP},
+#line 44 "cssproperties.gperf"
+ {"color", CSS_PROP_COLOR},
+#line 58 "cssproperties.gperf"
+ {"height", CSS_PROP_HEIGHT},
+#line 119 "cssproperties.gperf"
+ {"border", CSS_PROP_BORDER},
+#line 122 "cssproperties.gperf"
+ {"border-top", CSS_PROP_BORDER_TOP},
+#line 123 "cssproperties.gperf"
+ {"border-right", CSS_PROP_BORDER_RIGHT},
+#line 124 "cssproperties.gperf"
+ {"border-bottom", CSS_PROP_BORDER_BOTTOM},
+#line 42 "cssproperties.gperf"
+ {"clear", CSS_PROP_CLEAR},
+#line 120 "cssproperties.gperf"
+ {"border-color", CSS_PROP_BORDER_COLOR},
+#line 28 "cssproperties.gperf"
+ {"border-top-color", CSS_PROP_BORDER_TOP_COLOR},
+#line 29 "cssproperties.gperf"
+ {"border-right-color", CSS_PROP_BORDER_RIGHT_COLOR},
+#line 30 "cssproperties.gperf"
+ {"border-bottom-color", CSS_PROP_BORDER_BOTTOM_COLOR},
+#line 78 "cssproperties.gperf"
+ {"min-height", CSS_PROP_MIN_HEIGHT},
+#line 130 "cssproperties.gperf"
+ {"margin", CSS_PROP_MARGIN},
+#line 49 "cssproperties.gperf"
+ {"direction", CSS_PROP_DIRECTION},
+#line 65 "cssproperties.gperf"
+ {"margin-top", CSS_PROP_MARGIN_TOP},
+#line 66 "cssproperties.gperf"
+ {"margin-right", CSS_PROP_MARGIN_RIGHT},
+#line 67 "cssproperties.gperf"
+ {"margin-bottom", CSS_PROP_MARGIN_BOTTOM},
+#line 61 "cssproperties.gperf"
+ {"line-height", CSS_PROP_LINE_HEIGHT},
+#line 132 "cssproperties.gperf"
+ {"padding", CSS_PROP_PADDING},
+#line 89 "cssproperties.gperf"
+ {"padding-top", CSS_PROP_PADDING_TOP},
+#line 90 "cssproperties.gperf"
+ {"padding-right", CSS_PROP_PADDING_RIGHT},
+#line 91 "cssproperties.gperf"
+ {"padding-bottom", CSS_PROP_PADDING_BOTTOM},
+#line 76 "cssproperties.gperf"
+ {"max-height", CSS_PROP_MAX_HEIGHT},
+#line 45 "cssproperties.gperf"
+ {"content", CSS_PROP_CONTENT},
+#line 97 "cssproperties.gperf"
+ {"position", CSS_PROP_POSITION},
+#line 80 "cssproperties.gperf"
+ {"orphans", CSS_PROP_ORPHANS},
+#line 110 "cssproperties.gperf"
+ {"vertical-align", CSS_PROP_VERTICAL_ALIGN},
+#line 48 "cssproperties.gperf"
+ {"cursor", CSS_PROP_CURSOR},
+#line 24 "cssproperties.gperf"
+ {"border-collapse", CSS_PROP_BORDER_COLLAPSE},
+#line 131 "cssproperties.gperf"
+ {"outline", CSS_PROP_OUTLINE},
+#line 136 "cssproperties.gperf"
+ {"scrollbar-highlight-color", CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR},
+#line 41 "cssproperties.gperf"
+ {"caption-side", CSS_PROP_CAPTION_SIDE},
+#line 137 "cssproperties.gperf"
+ {"scrollbar-3dlight-color", CSS_PROP_SCROLLBAR_3DLIGHT_COLOR},
+#line 25 "cssproperties.gperf"
+ {"border-spacing", CSS_PROP_BORDER_SPACING},
+#line 102 "cssproperties.gperf"
+ {"text-align", CSS_PROP_TEXT_ALIGN},
+#line 109 "cssproperties.gperf"
+ {"unicode-bidi", CSS_PROP_UNICODE_BIDI},
+#line 82 "cssproperties.gperf"
+ {"outline-color", CSS_PROP_OUTLINE_COLOR},
+#line 60 "cssproperties.gperf"
+ {"letter-spacing", CSS_PROP_LETTER_SPACING},
+#line 103 "cssproperties.gperf"
+ {"text-decoration", CSS_PROP_TEXT_DECORATION},
+#line 139 "cssproperties.gperf"
+ {"scrollbar-track-color", CSS_PROP_SCROLLBAR_TRACK_COLOR},
+#line 118 "cssproperties.gperf"
+ {"background", CSS_PROP_BACKGROUND},
+#line 104 "cssproperties.gperf"
+ {"text-indent", CSS_PROP_TEXT_INDENT},
+#line 69 "cssproperties.gperf"
+ {"-tdehtml-margin-start", CSS_PROP__KHTML_MARGIN_START},
+#line 14 "cssproperties.gperf"
+ {"background-color", CSS_PROP_BACKGROUND_COLOR},
+#line 100 "cssproperties.gperf"
+ {"size", CSS_PROP_SIZE},
+#line 133 "cssproperties.gperf"
+ {"scrollbar-base-color", CSS_PROP_SCROLLBAR_BASE_COLOR},
+#line 47 "cssproperties.gperf"
+ {"counter-reset", CSS_PROP_COUNTER_RESET},
+#line 93 "cssproperties.gperf"
+ {"-tdehtml-padding-start", CSS_PROP__KHTML_PADDING_START},
+#line 15 "cssproperties.gperf"
+ {"background-image", CSS_PROP_BACKGROUND_IMAGE},
+#line 96 "cssproperties.gperf"
+ {"page-break-inside", CSS_PROP_PAGE_BREAK_INSIDE},
+#line 98 "cssproperties.gperf"
+ {"quotes", CSS_PROP_QUOTES},
+#line 16 "cssproperties.gperf"
+ {"background-repeat", CSS_PROP_BACKGROUND_REPEAT},
+#line 59 "cssproperties.gperf"
+ {"left", CSS_PROP_LEFT},
+#line 52 "cssproperties.gperf"
+ {"float", CSS_PROP_FLOAT},
+#line 21 "cssproperties.gperf"
+ {"-tdehtml-background-clip", CSS_PROP__KHTML_BACKGROUND_CLIP},
+#line 70 "cssproperties.gperf"
+ {"-tdehtml-marquee", CSS_PROP__KHTML_MARQUEE},
+#line 27 "cssproperties.gperf"
+ {"-tdehtml-border-vertical-spacing", CSS_PROP__KHTML_BORDER_VERTICAL_SPACING},
+#line 46 "cssproperties.gperf"
+ {"counter-increment", CSS_PROP_COUNTER_INCREMENT},
+#line 128 "cssproperties.gperf"
+ {"font", CSS_PROP_FONT},
+#line 114 "cssproperties.gperf"
+ {"width", CSS_PROP_WIDTH},
+#line 125 "cssproperties.gperf"
+ {"border-left", CSS_PROP_BORDER_LEFT},
+#line 117 "cssproperties.gperf"
+ {"z-index", CSS_PROP_Z_INDEX},
+#line 31 "cssproperties.gperf"
+ {"border-left-color", CSS_PROP_BORDER_LEFT_COLOR},
+#line 22 "cssproperties.gperf"
+ {"-tdehtml-background-origin", CSS_PROP__KHTML_BACKGROUND_ORIGIN},
+#line 17 "cssproperties.gperf"
+ {"background-attachment", CSS_PROP_BACKGROUND_ATTACHMENT},
+#line 126 "cssproperties.gperf"
+ {"border-width", CSS_PROP_BORDER_WIDTH},
+#line 18 "cssproperties.gperf"
+ {"background-position", CSS_PROP_BACKGROUND_POSITION},
+#line 36 "cssproperties.gperf"
+ {"border-top-width", CSS_PROP_BORDER_TOP_WIDTH},
+#line 37 "cssproperties.gperf"
+ {"border-right-width", CSS_PROP_BORDER_RIGHT_WIDTH},
+#line 38 "cssproperties.gperf"
+ {"border-bottom-width", CSS_PROP_BORDER_BOTTOM_WIDTH},
+#line 68 "cssproperties.gperf"
+ {"margin-left", CSS_PROP_MARGIN_LEFT},
+#line 142 "cssproperties.gperf"
+ {"-tdehtml-user-input", CSS_PROP__KHTML_USER_INPUT},
+#line 79 "cssproperties.gperf"
+ {"min-width", CSS_PROP_MIN_WIDTH},
+#line 127 "cssproperties.gperf"
+ {"box-sizing", CSS_PROP_BOX_SIZING},
+#line 92 "cssproperties.gperf"
+ {"padding-left", CSS_PROP_PADDING_LEFT},
+#line 71 "cssproperties.gperf"
+ {"-tdehtml-marquee-direction", CSS_PROP__KHTML_MARQUEE_DIRECTION},
+#line 73 "cssproperties.gperf"
+ {"-tdehtml-marquee-repetition", CSS_PROP__KHTML_MARQUEE_REPETITION},
+#line 95 "cssproperties.gperf"
+ {"page-break-before", CSS_PROP_PAGE_BREAK_BEFORE},
+#line 74 "cssproperties.gperf"
+ {"-tdehtml-marquee-speed", CSS_PROP__KHTML_MARQUEE_SPEED},
+#line 94 "cssproperties.gperf"
+ {"page-break-after", CSS_PROP_PAGE_BREAK_AFTER},
+#line 81 "cssproperties.gperf"
+ {"opacity", CSS_PROP_OPACITY},
+#line 77 "cssproperties.gperf"
+ {"max-width", CSS_PROP_MAX_WIDTH},
+#line 112 "cssproperties.gperf"
+ {"white-space", CSS_PROP_WHITE_SPACE},
+#line 56 "cssproperties.gperf"
+ {"font-variant", CSS_PROP_FONT_VARIANT},
+#line 19 "cssproperties.gperf"
+ {"background-position-x", CSS_PROP_BACKGROUND_POSITION_X},
+#line 134 "cssproperties.gperf"
+ {"scrollbar-face-color", CSS_PROP_SCROLLBAR_FACE_COLOR},
+#line 72 "cssproperties.gperf"
+ {"-tdehtml-marquee-increment", CSS_PROP__KHTML_MARQUEE_INCREMENT},
+#line 116 "cssproperties.gperf"
+ {"word-spacing", CSS_PROP_WORD_SPACING},
+#line 111 "cssproperties.gperf"
+ {"visibility", CSS_PROP_VISIBILITY},
+#line 140 "cssproperties.gperf"
+ {"scrollbar-arrow-color", CSS_PROP_SCROLLBAR_ARROW_COLOR},
+#line 85 "cssproperties.gperf"
+ {"outline-width", CSS_PROP_OUTLINE_WIDTH},
+#line 106 "cssproperties.gperf"
+ {"text-shadow", CSS_PROP_TEXT_SHADOW},
+#line 50 "cssproperties.gperf"
+ {"display", CSS_PROP_DISPLAY},
+#line 107 "cssproperties.gperf"
+ {"text-transform", CSS_PROP_TEXT_TRANSFORM},
+#line 51 "cssproperties.gperf"
+ {"empty-cells", CSS_PROP_EMPTY_CELLS},
+#line 121 "cssproperties.gperf"
+ {"border-style", CSS_PROP_BORDER_STYLE},
+#line 32 "cssproperties.gperf"
+ {"border-top-style", CSS_PROP_BORDER_TOP_STYLE},
+#line 26 "cssproperties.gperf"
+ {"-tdehtml-border-horizontal-spacing", CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING},
+#line 33 "cssproperties.gperf"
+ {"border-right-style", CSS_PROP_BORDER_RIGHT_STYLE},
+#line 34 "cssproperties.gperf"
+ {"border-bottom-style", CSS_PROP_BORDER_BOTTOM_STYLE},
+#line 23 "cssproperties.gperf"
+ {"-tdehtml-background-size", CSS_PROP__KHTML_BACKGROUND_SIZE},
+#line 135 "cssproperties.gperf"
+ {"scrollbar-shadow-color", CSS_PROP_SCROLLBAR_SHADOW_COLOR},
+#line 129 "cssproperties.gperf"
+ {"list-style", CSS_PROP_LIST_STYLE},
+#line 101 "cssproperties.gperf"
+ {"table-layout", CSS_PROP_TABLE_LAYOUT},
+#line 54 "cssproperties.gperf"
+ {"font-size", CSS_PROP_FONT_SIZE},
+#line 86 "cssproperties.gperf"
+ {"overflow", CSS_PROP_OVERFLOW},
+#line 62 "cssproperties.gperf"
+ {"list-style-image", CSS_PROP_LIST_STYLE_IMAGE},
+#line 138 "cssproperties.gperf"
+ {"scrollbar-darkshadow-color", CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR},
+#line 57 "cssproperties.gperf"
+ {"font-weight", CSS_PROP_FONT_WEIGHT},
+#line 39 "cssproperties.gperf"
+ {"border-left-width", CSS_PROP_BORDER_LEFT_WIDTH},
+#line 115 "cssproperties.gperf"
+ {"word-wrap", CSS_PROP_WORD_WRAP},
+#line 84 "cssproperties.gperf"
+ {"outline-style", CSS_PROP_OUTLINE_STYLE},
+#line 141 "cssproperties.gperf"
+ {"-tdehtml-flow-mode", CSS_PROP__KHTML_FLOW_MODE},
+#line 87 "cssproperties.gperf"
+ {"overflow-x", CSS_PROP_OVERFLOW_X},
+#line 113 "cssproperties.gperf"
+ {"widows", CSS_PROP_WIDOWS},
+#line 105 "cssproperties.gperf"
+ {"text-overflow", CSS_PROP_TEXT_OVERFLOW},
+#line 63 "cssproperties.gperf"
+ {"list-style-position", CSS_PROP_LIST_STYLE_POSITION},
+#line 20 "cssproperties.gperf"
+ {"background-position-y", CSS_PROP_BACKGROUND_POSITION_Y},
+#line 83 "cssproperties.gperf"
+ {"outline-offset", CSS_PROP_OUTLINE_OFFSET},
+#line 75 "cssproperties.gperf"
+ {"-tdehtml-marquee-style", CSS_PROP__KHTML_MARQUEE_STYLE},
+#line 55 "cssproperties.gperf"
+ {"font-style", CSS_PROP_FONT_STYLE},
+#line 35 "cssproperties.gperf"
+ {"border-left-style", CSS_PROP_BORDER_LEFT_STYLE},
+#line 64 "cssproperties.gperf"
+ {"list-style-type", CSS_PROP_LIST_STYLE_TYPE},
+#line 88 "cssproperties.gperf"
+ {"overflow-y", CSS_PROP_OVERFLOW_Y},
+#line 53 "cssproperties.gperf"
+ {"font-family", CSS_PROP_FONT_FAMILY}
+ };
+
+ static const short lookup[] =
+ {
+ -1, -1, -1, 0, -1, 1, 2, -1, -1, 3,
+ 4, 5, -1, -1, -1, -1, 6, -1, -1, -1,
+ 7, -1, 8, 9, -1, 10, -1, 11, -1, -1,
+ -1, 12, -1, 13, 14, -1, -1, -1, -1, -1,
+ 15, 16, -1, -1, 17, 18, -1, 19, 20, -1,
+ -1, 21, 22, -1, -1, -1, 23, -1, 24, 25,
+ 26, -1, 27, 28, -1, -1, -1, -1, -1, -1,
+ -1, -1, 29, -1, 30, -1, 31, -1, -1, -1,
+ 32, -1, 33, -1, -1, 34, -1, 35, 36, 37,
+ 38, -1, 39, 40, 41, -1, -1, -1, -1, -1,
+ 42, 43, -1, -1, -1, 44, -1, -1, -1, -1,
+ -1, 45, -1, -1, 46, -1, 47, -1, -1, 48,
+ 49, -1, -1, 50, -1, 51, 52, 53, -1, -1,
+ -1, 54, 55, -1, 56, -1, -1, -1, -1, -1,
+ 57, -1, 58, -1, 59, 60, -1, 61, -1, 62,
+ 63, 64, -1, -1, -1, -1, -1, 65, -1, -1,
+ -1, -1, 66, -1, 67, -1, 68, 69, -1, 70,
+ -1, 71, -1, 72, 73, -1, 74, 75, -1, 76,
+ 77, -1, -1, -1, -1, -1, -1, 78, -1, 79,
+ 80, -1, 81, -1, -1, 82, 83, 84, -1, 85,
+ -1, 86, 87, -1, -1, -1, 88, -1, -1, -1,
+ 89, -1, -1, -1, 90, -1, -1, -1, -1, -1,
+ -1, -1, 91, -1, -1, 92, 93, -1, -1, -1,
+ -1, -1, -1, 94, -1, -1, 95, 96, -1, 97,
+ -1, 98, 99, -1, -1, -1, 100, 101, 102, 103,
+ -1, -1, 104, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 105, -1, -1, 106, -1, 107, -1, 108,
+ -1, -1, -1, -1, -1, -1, -1, -1, 109, -1,
+ -1, -1, -1, -1, -1, -1, 110, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 111, -1, -1, -1,
+ -1, 112, 113, -1, 114, -1, -1, -1, 115, -1,
+ -1, 116, -1, -1, -1, 117, -1, -1, -1, -1,
+ -1, 118, -1, 119, -1, -1, -1, -1, -1, 120,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 121, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 122, -1, -1, -1, -1, -1,
+ 123, -1, -1, -1, -1, 124, -1, 125, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 126, -1, -1, -1, -1,
+ 127, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 128
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_prop (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist_prop[index].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist_prop[index];
+ }
+ }
+ }
+ return 0;
+}
+#line 143 "cssproperties.gperf"
+
+static const char * const propertyList[] = {
+"",
+"background-color",
+"background-image",
+"background-repeat",
+"background-attachment",
+"background-position",
+"background-position-x",
+"background-position-y",
+"-tdehtml-background-clip",
+"-tdehtml-background-origin",
+"-tdehtml-background-size",
+"border-collapse",
+"border-spacing",
+"-tdehtml-border-horizontal-spacing",
+"-tdehtml-border-vertical-spacing",
+"border-top-color",
+"border-right-color",
+"border-bottom-color",
+"border-left-color",
+"border-top-style",
+"border-right-style",
+"border-bottom-style",
+"border-left-style",
+"border-top-width",
+"border-right-width",
+"border-bottom-width",
+"border-left-width",
+"bottom",
+"caption-side",
+"clear",
+"clip",
+"color",
+"content",
+"counter-increment",
+"counter-reset",
+"cursor",
+"direction",
+"display",
+"empty-cells",
+"float",
+"font-family",
+"font-size",
+"font-style",
+"font-variant",
+"font-weight",
+"height",
+"left",
+"letter-spacing",
+"line-height",
+"list-style-image",
+"list-style-position",
+"list-style-type",
+"margin-top",
+"margin-right",
+"margin-bottom",
+"margin-left",
+"-tdehtml-margin-start",
+"-tdehtml-marquee",
+"-tdehtml-marquee-direction",
+"-tdehtml-marquee-increment",
+"-tdehtml-marquee-repetition",
+"-tdehtml-marquee-speed",
+"-tdehtml-marquee-style",
+"max-height",
+"max-width",
+"min-height",
+"min-width",
+"orphans",
+"opacity",
+"outline-color",
+"outline-offset",
+"outline-style",
+"outline-width",
+"overflow",
+"overflow-x",
+"overflow-y",
+"padding-top",
+"padding-right",
+"padding-bottom",
+"padding-left",
+"-tdehtml-padding-start",
+"page-break-after",
+"page-break-before",
+"page-break-inside",
+"position",
+"quotes",
+"right",
+"size",
+"table-layout",
+"text-align",
+"text-decoration",
+"text-indent",
+"text-overflow",
+"text-shadow",
+"text-transform",
+"top",
+"unicode-bidi",
+"vertical-align",
+"visibility",
+"white-space",
+"widows",
+"width",
+"word-wrap",
+"word-spacing",
+"z-index",
+"background",
+"border",
+"border-color",
+"border-style",
+"border-top",
+"border-right",
+"border-bottom",
+"border-left",
+"border-width",
+"box-sizing",
+"font",
+"list-style",
+"margin",
+"outline",
+"padding",
+"scrollbar-base-color",
+"scrollbar-face-color",
+"scrollbar-shadow-color",
+"scrollbar-highlight-color",
+"scrollbar-3dlight-color",
+"scrollbar-darkshadow-color",
+"scrollbar-track-color",
+"scrollbar-arrow-color",
+"-tdehtml-flow-mode",
+"-tdehtml-user-input",
+ 0
+};
+DOMString getPropertyName(unsigned short id)
+{
+ if(id >= CSS_PROP_TOTAL || id == 0)
+ return DOMString();
+ else
+ return DOMString(propertyList[id]);
+}
+
diff --git a/tdehtml/css/cssproperties.h b/tdehtml/css/cssproperties.h
new file mode 100644
index 000000000..be92d93d4
--- /dev/null
+++ b/tdehtml/css/cssproperties.h
@@ -0,0 +1,144 @@
+/* This file is automatically generated from cssproperties.in by makeprop, do not edit */
+/* Copyright 1998 W. Bastian */
+
+#ifndef CSSPROPERTIES_H
+#define CSSPROPERTIES_H
+
+DOM::DOMString getPropertyName(unsigned short id) KDE_NO_EXPORT;
+
+#define CSS_PROP_INVALID 0
+#define CSS_PROP_MIN 1
+#define CSS_PROP_BACKGROUND_COLOR 1
+#define CSS_PROP_BACKGROUND_IMAGE 2
+#define CSS_PROP_BACKGROUND_REPEAT 3
+#define CSS_PROP_BACKGROUND_ATTACHMENT 4
+#define CSS_PROP_BACKGROUND_POSITION 5
+#define CSS_PROP_BACKGROUND_POSITION_X 6
+#define CSS_PROP_BACKGROUND_POSITION_Y 7
+#define CSS_PROP__KHTML_BACKGROUND_CLIP 8
+#define CSS_PROP__KHTML_BACKGROUND_ORIGIN 9
+#define CSS_PROP__KHTML_BACKGROUND_SIZE 10
+#define CSS_PROP_BORDER_COLLAPSE 11
+#define CSS_PROP_BORDER_SPACING 12
+#define CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING 13
+#define CSS_PROP__KHTML_BORDER_VERTICAL_SPACING 14
+#define CSS_PROP_BORDER_TOP_COLOR 15
+#define CSS_PROP_BORDER_RIGHT_COLOR 16
+#define CSS_PROP_BORDER_BOTTOM_COLOR 17
+#define CSS_PROP_BORDER_LEFT_COLOR 18
+#define CSS_PROP_BORDER_TOP_STYLE 19
+#define CSS_PROP_BORDER_RIGHT_STYLE 20
+#define CSS_PROP_BORDER_BOTTOM_STYLE 21
+#define CSS_PROP_BORDER_LEFT_STYLE 22
+#define CSS_PROP_BORDER_TOP_WIDTH 23
+#define CSS_PROP_BORDER_RIGHT_WIDTH 24
+#define CSS_PROP_BORDER_BOTTOM_WIDTH 25
+#define CSS_PROP_BORDER_LEFT_WIDTH 26
+#define CSS_PROP_BOTTOM 27
+#define CSS_PROP_CAPTION_SIDE 28
+#define CSS_PROP_CLEAR 29
+#define CSS_PROP_CLIP 30
+#define CSS_PROP_COLOR 31
+#define CSS_PROP_CONTENT 32
+#define CSS_PROP_COUNTER_INCREMENT 33
+#define CSS_PROP_COUNTER_RESET 34
+#define CSS_PROP_CURSOR 35
+#define CSS_PROP_DIRECTION 36
+#define CSS_PROP_DISPLAY 37
+#define CSS_PROP_EMPTY_CELLS 38
+#define CSS_PROP_FLOAT 39
+#define CSS_PROP_FONT_FAMILY 40
+#define CSS_PROP_FONT_SIZE 41
+#define CSS_PROP_FONT_STYLE 42
+#define CSS_PROP_FONT_VARIANT 43
+#define CSS_PROP_FONT_WEIGHT 44
+#define CSS_PROP_HEIGHT 45
+#define CSS_PROP_LEFT 46
+#define CSS_PROP_LETTER_SPACING 47
+#define CSS_PROP_LINE_HEIGHT 48
+#define CSS_PROP_LIST_STYLE_IMAGE 49
+#define CSS_PROP_LIST_STYLE_POSITION 50
+#define CSS_PROP_LIST_STYLE_TYPE 51
+#define CSS_PROP_MARGIN_TOP 52
+#define CSS_PROP_MARGIN_RIGHT 53
+#define CSS_PROP_MARGIN_BOTTOM 54
+#define CSS_PROP_MARGIN_LEFT 55
+#define CSS_PROP__KHTML_MARGIN_START 56
+#define CSS_PROP__KHTML_MARQUEE 57
+#define CSS_PROP__KHTML_MARQUEE_DIRECTION 58
+#define CSS_PROP__KHTML_MARQUEE_INCREMENT 59
+#define CSS_PROP__KHTML_MARQUEE_REPETITION 60
+#define CSS_PROP__KHTML_MARQUEE_SPEED 61
+#define CSS_PROP__KHTML_MARQUEE_STYLE 62
+#define CSS_PROP_MAX_HEIGHT 63
+#define CSS_PROP_MAX_WIDTH 64
+#define CSS_PROP_MIN_HEIGHT 65
+#define CSS_PROP_MIN_WIDTH 66
+#define CSS_PROP_ORPHANS 67
+#define CSS_PROP_OPACITY 68
+#define CSS_PROP_OUTLINE_COLOR 69
+#define CSS_PROP_OUTLINE_OFFSET 70
+#define CSS_PROP_OUTLINE_STYLE 71
+#define CSS_PROP_OUTLINE_WIDTH 72
+#define CSS_PROP_OVERFLOW 73
+#define CSS_PROP_OVERFLOW_X 74
+#define CSS_PROP_OVERFLOW_Y 75
+#define CSS_PROP_PADDING_TOP 76
+#define CSS_PROP_PADDING_RIGHT 77
+#define CSS_PROP_PADDING_BOTTOM 78
+#define CSS_PROP_PADDING_LEFT 79
+#define CSS_PROP__KHTML_PADDING_START 80
+#define CSS_PROP_PAGE_BREAK_AFTER 81
+#define CSS_PROP_PAGE_BREAK_BEFORE 82
+#define CSS_PROP_PAGE_BREAK_INSIDE 83
+#define CSS_PROP_POSITION 84
+#define CSS_PROP_QUOTES 85
+#define CSS_PROP_RIGHT 86
+#define CSS_PROP_SIZE 87
+#define CSS_PROP_TABLE_LAYOUT 88
+#define CSS_PROP_TEXT_ALIGN 89
+#define CSS_PROP_TEXT_DECORATION 90
+#define CSS_PROP_TEXT_INDENT 91
+#define CSS_PROP_TEXT_OVERFLOW 92
+#define CSS_PROP_TEXT_SHADOW 93
+#define CSS_PROP_TEXT_TRANSFORM 94
+#define CSS_PROP_TOP 95
+#define CSS_PROP_UNICODE_BIDI 96
+#define CSS_PROP_VERTICAL_ALIGN 97
+#define CSS_PROP_VISIBILITY 98
+#define CSS_PROP_WHITE_SPACE 99
+#define CSS_PROP_WIDOWS 100
+#define CSS_PROP_WIDTH 101
+#define CSS_PROP_WORD_WRAP 102
+#define CSS_PROP_WORD_SPACING 103
+#define CSS_PROP_Z_INDEX 104
+#define CSS_PROP_BACKGROUND 105
+#define CSS_PROP_BORDER 106
+#define CSS_PROP_BORDER_COLOR 107
+#define CSS_PROP_BORDER_STYLE 108
+#define CSS_PROP_BORDER_TOP 109
+#define CSS_PROP_BORDER_RIGHT 110
+#define CSS_PROP_BORDER_BOTTOM 111
+#define CSS_PROP_BORDER_LEFT 112
+#define CSS_PROP_BORDER_WIDTH 113
+#define CSS_PROP_BOX_SIZING 114
+#define CSS_PROP_FONT 115
+#define CSS_PROP_LIST_STYLE 116
+#define CSS_PROP_MARGIN 117
+#define CSS_PROP_OUTLINE 118
+#define CSS_PROP_PADDING 119
+#define CSS_PROP_SCROLLBAR_BASE_COLOR 120
+#define CSS_PROP_SCROLLBAR_FACE_COLOR 121
+#define CSS_PROP_SCROLLBAR_SHADOW_COLOR 122
+#define CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR 123
+#define CSS_PROP_SCROLLBAR_3DLIGHT_COLOR 124
+#define CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR 125
+#define CSS_PROP_SCROLLBAR_TRACK_COLOR 126
+#define CSS_PROP_SCROLLBAR_ARROW_COLOR 127
+#define CSS_PROP__KHTML_FLOW_MODE 128
+#define CSS_PROP__KHTML_USER_INPUT 129
+
+#define CSS_PROP_MAX CSS_PROP_Z_INDEX
+#define CSS_PROP_TOTAL 130
+#endif
+
diff --git a/tdehtml/css/cssproperties.in b/tdehtml/css/cssproperties.in
new file mode 100644
index 000000000..27e452322
--- /dev/null
+++ b/tdehtml/css/cssproperties.in
@@ -0,0 +1,148 @@
+#
+# all valid CSS2 properties.
+#
+# aural properties are commented out, as we don't support them anyway.
+#
+# some properties are used in tdehtml, but are not part of CSS. They are used to get
+# HTML4 compatibility in the rendering engine.
+#
+# Mircosoft extensions are documented here:
+# http://msdn.microsoft.com/workshop/author/css/reference/attributes.asp
+#
+# CSS_PROP_BACKGROUND_COLOR:
+#
+background-color
+background-image
+background-repeat
+background-attachment
+background-position
+# IE Extensions
+background-position-x
+background-position-y
+# CSS3 Extensions
+-tdehtml-background-clip
+-tdehtml-background-origin
+-tdehtml-background-size
+
+border-collapse
+border-spacing
+-tdehtml-border-horizontal-spacing
+-tdehtml-border-vertical-spacing
+border-top-color
+border-right-color
+border-bottom-color
+border-left-color
+border-top-style
+border-right-style
+border-bottom-style
+border-left-style
+border-top-width
+border-right-width
+border-bottom-width
+border-left-width
+bottom
+caption-side
+clear
+clip
+color
+content
+counter-increment
+counter-reset
+cursor
+direction
+display
+empty-cells
+float
+font-family
+font-size
+font-style
+font-variant
+font-weight
+height
+left
+letter-spacing
+line-height
+list-style-image
+list-style-position
+list-style-type
+margin-top
+margin-right
+margin-bottom
+margin-left
+-tdehtml-margin-start
+-tdehtml-marquee
+-tdehtml-marquee-direction
+-tdehtml-marquee-increment
+-tdehtml-marquee-repetition
+-tdehtml-marquee-speed
+-tdehtml-marquee-style
+max-height
+max-width
+min-height
+min-width
+orphans
+opacity
+outline-color
+outline-offset
+outline-style
+outline-width
+overflow
+overflow-x
+overflow-y
+padding-top
+padding-right
+padding-bottom
+padding-left
+-tdehtml-padding-start
+#page
+page-break-after
+page-break-before
+page-break-inside
+position
+quotes
+right
+size
+table-layout
+text-align
+text-decoration
+text-indent
+text-overflow
+text-shadow
+text-transform
+top
+unicode-bidi
+vertical-align
+visibility
+white-space
+widows
+width
+word-wrap
+word-spacing
+z-index
+background
+border
+border-color
+border-style
+border-top
+border-right
+border-bottom
+border-left
+border-width
+box-sizing
+font
+list-style
+margin
+outline
+padding
+# some more IE extensions
+scrollbar-base-color
+scrollbar-face-color
+scrollbar-shadow-color
+scrollbar-highlight-color
+scrollbar-3dlight-color
+scrollbar-darkshadow-color
+scrollbar-track-color
+scrollbar-arrow-color
+# tdehtml internals
+-tdehtml-flow-mode
+-tdehtml-user-input
diff --git a/tdehtml/css/cssstyleselector.cpp b/tdehtml/css/cssstyleselector.cpp
new file mode 100644
index 000000000..f2c5703c1
--- /dev/null
+++ b/tdehtml/css/cssstyleselector.cpp
@@ -0,0 +1,4217 @@
+/**
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2003-2004 Apple Computer, Inc.
+ * (C) 2004-2006 Allan Sandfeld Jensen (kde@carewolf.com)
+ * (C) 2004 Germain Garand (germain@ebooksfrance.org)
+ * (C) 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.
+ */
+
+#include "css/cssstyleselector.h"
+#include "rendering/render_style.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/css_ruleimpl.h"
+#include "css/css_valueimpl.h"
+#include "css/csshelper.h"
+#include "rendering/render_object.h"
+#include "html/html_documentimpl.h"
+#include "html/html_elementimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_restyler.h"
+#include "dom/css_rule.h"
+#include "dom/css_value.h"
+#include "tdehtml_factory.h"
+#include "tdehtmlpart_p.h"
+using namespace tdehtml;
+using namespace DOM;
+
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+
+#include "misc/tdehtmllayout.h"
+#include "tdehtml_settings.h"
+#include "misc/htmlhashes.h"
+#include "misc/helper.h"
+#include "misc/loader.h"
+
+#include "rendering/font.h"
+
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+
+#include <kstandarddirs.h>
+#include <kcharsets.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <tqfile.h>
+#include <tqvaluelist.h>
+#include <tqstring.h>
+#include <tqtooltip.h>
+#include <kdebug.h>
+#include <kurl.h>
+#include <assert.h>
+#include <tqpaintdevicemetrics.h>
+#include <stdlib.h>
+
+#define HANDLE_INHERIT(prop, Prop) \
+if (isInherit) \
+{\
+ style->set##Prop(parentStyle->prop());\
+ return;\
+}
+
+#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
+HANDLE_INHERIT(prop, Prop) \
+else if (isInitial) \
+{\
+ style->set##Prop(RenderStyle::initial##Prop());\
+ return;\
+}
+
+#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
+HANDLE_INHERIT(prop, Prop) \
+else if (isInitial) \
+{\
+ style->set##Prop(RenderStyle::initial##Value());\
+ return;\
+}
+
+#define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
+if (isInherit) { \
+ BackgroundLayer* currChild = style->accessBackgroundLayers(); \
+ BackgroundLayer* prevChild = 0; \
+ const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \
+ while (currParent && currParent->is##Prop##Set()) { \
+ if (!currChild) { \
+ /* Need to make a new layer.*/ \
+ currChild = new BackgroundLayer(); \
+ prevChild->setNext(currChild); \
+ } \
+ currChild->set##Prop(currParent->prop()); \
+ prevChild = currChild; \
+ currChild = prevChild->next(); \
+ currParent = currParent->next(); \
+ } \
+ \
+ while (currChild) { \
+ /* Reset any remaining layers to not have the property set. */ \
+ currChild->clear##Prop(); \
+ currChild = currChild->next(); \
+ } \
+ return; \
+} \
+if (isInitial) { \
+ BackgroundLayer* currChild = style->accessBackgroundLayers(); \
+ currChild->set##Prop(RenderStyle::initial##Prop()); \
+ for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
+ currChild->clear##Prop(); \
+ return; \
+}
+
+#define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \
+HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
+if (!value->isPrimitiveValue() && !value->isValueList()) \
+ return; \
+BackgroundLayer* currChild = style->accessBackgroundLayers(); \
+BackgroundLayer* prevChild = 0; \
+if (value->isPrimitiveValue()) { \
+ map##Prop(currChild, value); \
+ currChild = currChild->next(); \
+} \
+else { \
+ /* Walk each value and put it into a layer, creating new layers as needed. */ \
+ CSSValueListImpl* valueList = static_cast<CSSValueListImpl*>(value); \
+ for (unsigned int i = 0; i < valueList->length(); i++) { \
+ if (!currChild) { \
+ /* Need to make a new layer to hold this value */ \
+ currChild = new BackgroundLayer(); \
+ prevChild->setNext(currChild); \
+ } \
+ map##Prop(currChild, valueList->item(i)); \
+ prevChild = currChild; \
+ currChild = currChild->next(); \
+ } \
+} \
+while (currChild) { \
+ /* Reset all remaining layers to not have the property set. */ \
+ currChild->clear##Prop(); \
+ currChild = currChild->next(); \
+} }
+
+#define HANDLE_INHERIT_COND(propID, prop, Prop) \
+if (id == propID) \
+{\
+ style->set##Prop(parentStyle->prop());\
+ return;\
+}
+
+#define HANDLE_INITIAL_COND(propID, Prop) \
+if (id == propID) \
+{\
+ style->set##Prop(RenderStyle::initial##Prop());\
+ return;\
+}
+
+#define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
+if (id == propID) \
+{\
+ style->set##Prop(RenderStyle::initial##Value());\
+ return;\
+}
+
+#define HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
+if (isInherit) \
+{\
+ style->set##Prop(parentStyle->prop());\
+ return;\
+}
+
+#define HANDLE_INITIAL(prop, Prop) \
+if (isInitial) \
+{\
+ style->set##Prop(RenderStyle::initial##Prop());\
+ return;\
+}
+
+#define HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \
+HANDLE_INITIAL(prop, Prop) \
+else \
+HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop)
+
+
+namespace tdehtml {
+
+CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle;
+CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle;
+CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle;
+CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet;
+RenderStyle* CSSStyleSelector::styleNotYetAvailable;
+CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet;
+
+enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited};
+static PseudoState pseudoState;
+
+
+CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, TQString userStyleSheet, StyleSheetListImpl *styleSheets,
+ const KURL &url, bool _strictParsing )
+{
+ KHTMLView* view = doc->view();
+
+ init(view ? view->part()->settings() : 0, doc);
+
+ strictParsing = _strictParsing;
+ m_medium = view ? view->mediaType() : TQString("all");
+
+ selectors = 0;
+ selectorCache = 0;
+ properties = 0;
+ userStyle = 0;
+ userSheet = 0;
+ paintDeviceMetrics = doc->paintDeviceMetrics();
+
+ if(paintDeviceMetrics) // this may be null, not everyone uses tdehtmlview (Niko)
+ computeFontSizes(paintDeviceMetrics, view ? view->part()->zoomFactor() : 100);
+
+ if ( !userStyleSheet.isEmpty() ) {
+ userSheet = new DOM::CSSStyleSheetImpl(doc);
+ userSheet->parseString( DOMString( userStyleSheet ) );
+
+ userStyle = new CSSStyleSelectorList();
+ userStyle->append( userSheet, m_medium );
+ }
+
+ // add stylesheets from document
+ authorStyle = new CSSStyleSelectorList();
+
+
+ TQPtrListIterator<StyleSheetImpl> it( styleSheets->styleSheets );
+ for ( ; it.current(); ++it ) {
+ if ( it.current()->isCSSStyleSheet() && !it.current()->disabled()) {
+ authorStyle->append( static_cast<CSSStyleSheetImpl*>( it.current() ), m_medium );
+ }
+ }
+
+ buildLists();
+
+ //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl;
+ //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl;
+
+ KURL u = url;
+
+ u.setQuery( TQString::null );
+ u.setRef( TQString::null );
+ encodedurl.file = u.url();
+ int pos = encodedurl.file.findRev('/');
+ encodedurl.path = encodedurl.file;
+ if ( pos > 0 ) {
+ encodedurl.path.truncate( pos );
+ encodedurl.path += '/';
+ }
+ u.setPath( TQString::null );
+ encodedurl.host = u.url();
+
+ //kdDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path << endl;
+}
+
+CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet )
+{
+ init(0L, 0L);
+
+ KHTMLView *view = sheet->doc()->view();
+ m_medium = view ? view->mediaType() : "screen";
+
+ authorStyle = new CSSStyleSelectorList();
+ authorStyle->append( sheet, m_medium );
+}
+
+void CSSStyleSelector::init(const KHTMLSettings* _settings, DocumentImpl* doc)
+{
+ element = 0;
+ settings = _settings;
+ paintDeviceMetrics = 0;
+ propsToApply = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
+ pseudoProps = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
+ propsToApplySize = 128;
+ pseudoPropsSize = 128;
+ if(!s_defaultStyle) loadDefaultStyle(settings, doc);
+
+ defaultStyle = s_defaultStyle;
+ defaultPrintStyle = s_defaultPrintStyle;
+ defaultQuirksStyle = s_defaultQuirksStyle;
+}
+
+CSSStyleSelector::~CSSStyleSelector()
+{
+ clearLists();
+ delete authorStyle;
+ delete userStyle;
+ delete userSheet;
+ free(propsToApply);
+ free(pseudoProps);
+}
+
+void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet )
+{
+ KHTMLView *view = sheet->doc()->view();
+ m_medium = view ? view->mediaType() : "screen";
+ authorStyle->append( sheet, m_medium );
+}
+
+void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s, DocumentImpl *doc)
+{
+ if(s_defaultStyle) return;
+
+ {
+ TQFile f(locate( "data", "tdehtml/css/html4.css" ) );
+ f.open(IO_ReadOnly);
+
+ TQCString file( f.size()+1 );
+ int readbytes = f.readBlock( file.data(), f.size() );
+ f.close();
+ if ( readbytes >= 0 )
+ file[readbytes] = '\0';
+
+ TQString style = TQString::fromLatin1( file.data() );
+ if(s)
+ style += s->settingsToCSS();
+ DOMString str(style);
+
+ s_defaultSheet = new DOM::CSSStyleSheetImpl(doc);
+ s_defaultSheet->parseString( str );
+
+ // Collect only strict-mode rules.
+ s_defaultStyle = new CSSStyleSelectorList();
+ s_defaultStyle->append( s_defaultSheet, "screen" );
+
+ s_defaultPrintStyle = new CSSStyleSelectorList();
+ s_defaultPrintStyle->append( s_defaultSheet, "print" );
+ }
+ {
+ TQFile f(locate( "data", "tdehtml/css/quirks.css" ) );
+ f.open(IO_ReadOnly);
+
+ TQCString file( f.size()+1 );
+ int readbytes = f.readBlock( file.data(), f.size() );
+ f.close();
+ if ( readbytes >= 0 )
+ file[readbytes] = '\0';
+
+ TQString style = TQString::fromLatin1( file.data() );
+ DOMString str(style);
+
+ s_quirksSheet = new DOM::CSSStyleSheetImpl(doc);
+ s_quirksSheet->parseString( str );
+
+ // Collect only quirks-mode rules.
+ s_defaultQuirksStyle = new CSSStyleSelectorList();
+ s_defaultQuirksStyle->append( s_quirksSheet, "screen" );
+ }
+
+ //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl;
+}
+
+void CSSStyleSelector::clear()
+{
+ delete s_defaultStyle;
+ delete s_defaultQuirksStyle;
+ delete s_defaultPrintStyle;
+ delete s_defaultSheet;
+ delete styleNotYetAvailable;
+ s_defaultStyle = 0;
+ s_defaultQuirksStyle = 0;
+ s_defaultPrintStyle = 0;
+ s_defaultSheet = 0;
+ styleNotYetAvailable = 0;
+}
+
+void CSSStyleSelector::reparseConfiguration()
+{
+ // nice leak, but best we can do right now. hopefully its only rare.
+ s_defaultStyle = 0;
+ s_defaultQuirksStyle = 0;
+ s_defaultPrintStyle = 0;
+ s_defaultSheet = 0;
+}
+
+#define MAXFONTSIZES 8
+
+void CSSStyleSelector::computeFontSizes(TQPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor)
+{
+ computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fontSizes, false);
+ computeFontSizesFor(paintDeviceMetrics, zoomFactor, m_fixedFontSizes, true);
+}
+
+void CSSStyleSelector::computeFontSizesFor(TQPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor, TQValueVector<int>& fontSizes, bool isFixed)
+{
+#ifdef APPLE_CHANGES
+ // We don't want to scale the settings by the dpi.
+ const float toPix = 1;
+#else
+ Q_UNUSED( isFixed );
+
+ // ### get rid of float / double
+ float toPix = paintDeviceMetrics->logicalDpiY()/72.;
+ if (toPix < 96./72.) toPix = 96./72.;
+#endif // ######### fix isFixed code again.
+
+ fontSizes.resize( MAXFONTSIZES );
+ float scale = 1.0;
+ static const float fontFactors[] = {3./5., 3./4., 8./9., 1., 6./5., 3./2., 2., 3.};
+ static const float smallFontFactors[] = {3./4., 5./6., 8./9., 1., 6./5., 3./2., 2., 3.};
+ float mediumFontSize, minFontSize, factor;
+ if (!tdehtml::printpainter) {
+ scale *= zoomFactor / 100.0;
+#ifdef APPLE_CHANGES
+ if (isFixed)
+ mediumFontSize = settings->mediumFixedFontSize() * toPix;
+ else
+#endif
+ mediumFontSize = settings->mediumFontSize() * toPix;
+ minFontSize = settings->minFontSize() * toPix;
+ }
+ else {
+ // ## depending on something / configurable ?
+ mediumFontSize = 12;
+ minFontSize = 6;
+ }
+ const float* factors = scale*mediumFontSize >= 12.5 ? fontFactors : smallFontFactors;
+ for ( int i = 0; i < MAXFONTSIZES; i++ ) {
+ factor = scale*factors[i];
+ fontSizes[i] = int(KMAX( mediumFontSize*factor +.5f, minFontSize));
+ //kdDebug( 6080 ) << "index: " << i << " factor: " << factors[i] << " font pix size: " << int(KMAX( mediumFontSize*factor +.5f, minFontSize)) << endl;
+ }
+}
+
+#undef MAXFONTSIZES
+
+static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e )
+{
+ while( b < e ) {
+ bool swapped = false;
+ CSSOrderedProperty **y = e+1;
+ CSSOrderedProperty **x = e;
+ CSSOrderedProperty **swappedPos = 0;
+ do {
+ if ( !((**(--x)) < (**(--y))) ) {
+ swapped = true;
+ swappedPos = x;
+ CSSOrderedProperty *tmp = *y;
+ *y = *x;
+ *x = tmp;
+ }
+ } while( x != b );
+ if ( !swapped ) break;
+ b = swappedPos + 1;
+ }
+}
+
+RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e)
+{
+ if (!e->getDocument()->haveStylesheetsLoaded() || !e->getDocument()->view()) {
+ if (!styleNotYetAvailable) {
+ styleNotYetAvailable = new RenderStyle();
+ styleNotYetAvailable->setDisplay(NONE);
+ styleNotYetAvailable->ref();
+ }
+ return styleNotYetAvailable;
+ }
+
+ // set some variables we will need
+ pseudoState = PseudoUnknown;
+
+ element = e;
+ parentNode = e->parentNode();
+ parentStyle = ( parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
+ view = element->getDocument()->view();
+ part = view->part();
+ settings = part->settings();
+ paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
+
+ // reset dynamic DOM dependencies
+ e->getDocument()->dynamicDomRestyler().resetDependencies(e);
+
+ style = new RenderStyle();
+ if( parentStyle )
+ style->inheritFrom( parentStyle );
+ else
+ parentStyle = style;
+
+ unsigned int numPropsToApply = 0;
+ unsigned int numPseudoProps = 0;
+
+ // try to sort out most style rules as early as possible.
+ TQ_UINT16 cssTagId = localNamePart(element->id());
+ int smatch = 0;
+ int schecked = 0;
+
+ for ( unsigned int i = 0; i < selectors_size; i++ ) {
+ TQ_UINT16 tag = localNamePart(selectors[i]->tag);
+ if ( cssTagId == tag || tag == anyLocalName ) {
+ ++schecked;
+
+ checkSelector( i, e );
+
+ if ( selectorCache[i].state == Applies ) {
+ ++smatch;
+
+// tqDebug("adding property" );
+ for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
+ for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j ) {
+ if (numPropsToApply >= propsToApplySize ) {
+ propsToApplySize *= 2;
+ propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
+ }
+ propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j];
+ }
+ } else if ( selectorCache[i].state == AppliesPseudo ) {
+ for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
+ for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) {
+ if (numPseudoProps >= pseudoPropsSize ) {
+ pseudoPropsSize *= 2;
+ pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
+ }
+ pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
+ properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
+ }
+ }
+ }
+ else
+ selectorCache[i].state = Invalid;
+
+ }
+
+ // inline style declarations, after all others. non css hints
+ // count as author rules, and come before all other style sheets, see hack in append()
+ numPropsToApply = addInlineDeclarations( e, e->m_styleDecls, numPropsToApply );
+
+// tqDebug( "styleForElement( %s )", e->tagName().string().latin1() );
+// tqDebug( "%d selectors, %d checked, %d match, %d properties ( of %d )",
+// selectors_size, schecked, smatch, numPropsToApply, properties_size );
+
+ bubbleSort( propsToApply, propsToApply+numPropsToApply-1 );
+ bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 );
+
+ // we can't apply style rules without a view() and a part. This
+ // tends to happen on delayed destruction of widget Renderobjects
+ if ( part ) {
+ fontDirty = false;
+
+ if (numPropsToApply ) {
+ CSSStyleSelector::style = style;
+ for (unsigned int i = 0; i < numPropsToApply; ++i) {
+ if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) {
+ // we are past the font properties, time to update to the
+ // correct font
+#ifdef APPLE_CHANGES
+ checkForGenericFamilyChange(style, parentStyle);
+#endif
+ CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
+ fontDirty = false;
+ }
+ DOM::CSSProperty *prop = propsToApply[i]->prop;
+// if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) kdDebug(6080) << "El: "<<e->nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent() << endl;
+// if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) kdDebug(6080) << "El: "<<e->nodeName().string() << endl;
+ applyRule( prop->m_id, prop->value() );
+ }
+ if ( fontDirty ) {
+#ifdef APPLE_CHANGES
+ checkForGenericFamilyChange(style, parentStyle);
+#endif
+ CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
+ }
+ }
+
+ // Clean up our style object's display and text decorations (among other fixups).
+ adjustRenderStyle(style, e);
+
+ if ( numPseudoProps ) {
+ fontDirty = false;
+ //tqDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
+ for (unsigned int i = 0; i < numPseudoProps; ++i) {
+ if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
+ // we are past the font properties, time to update to the
+ // correct font
+ //We have to do this for all pseudo styles
+ RenderStyle *pseudoStyle = style->pseudoStyle;
+ while ( pseudoStyle ) {
+ pseudoStyle->htmlFont().update( paintDeviceMetrics );
+ pseudoStyle = pseudoStyle->pseudoStyle;
+ }
+ fontDirty = false;
+ }
+
+ RenderStyle *pseudoStyle;
+ pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId);
+ if (!pseudoStyle)
+ {
+ pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId);
+ if (pseudoStyle)
+ pseudoStyle->inheritFrom( style );
+ }
+
+ RenderStyle* oldStyle = style;
+ RenderStyle* oldParentStyle = parentStyle;
+ parentStyle = style;
+ style = pseudoStyle;
+ if ( pseudoStyle ) {
+ DOM::CSSProperty *prop = pseudoProps[i]->prop;
+ applyRule( prop->m_id, prop->value() );
+ }
+ style = oldStyle;
+ parentStyle = oldParentStyle;
+ }
+
+ if ( fontDirty ) {
+ RenderStyle *pseudoStyle = style->pseudoStyle;
+ while ( pseudoStyle ) {
+ pseudoStyle->htmlFont().update( paintDeviceMetrics );
+ pseudoStyle = pseudoStyle->pseudoStyle;
+ }
+ }
+ }
+ }
+
+ // Now adjust all our pseudo-styles.
+ RenderStyle *pseudoStyle = style->pseudoStyle;
+ while (pseudoStyle) {
+ adjustRenderStyle(pseudoStyle, 0);
+ pseudoStyle = pseudoStyle->pseudoStyle;
+ }
+
+ // Now return the style.
+ return style;
+}
+
+void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
+{
+ // Cache our original display.
+ style->setOriginalDisplay(style->display());
+
+ if (style->display() != NONE) {
+ // If we have a <td> that specifies a float property, in quirks mode we just drop the float
+ // property.
+ // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
+ // these tags to retain their display types.
+ if (!strictParsing && e) {
+ if (e->id() == ID_TD) {
+ style->setDisplay(TABLE_CELL);
+ style->setFloating(FNONE);
+ }
+ else if (e->id() == ID_TABLE)
+ style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
+ }
+
+ // Table headers with a text-align of auto will change the text-align to center.
+ if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
+ style->setTextAlign(CENTER);
+
+ // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
+ // position or float an inline, compact, or run-in. Cache the original display, since it
+ // may be needed for positioned elements that have to compute their static normal flow
+ // positions. We also force inline-level roots to be block-level.
+ if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ &&
+ (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE ||
+ (e && e->getDocument()->documentElement() == e))) {
+ if (style->display() == INLINE_TABLE)
+ style->setDisplay(TABLE);
+// else if (style->display() == INLINE_BOX)
+// style->setDisplay(BOX);
+ else if (style->display() == LIST_ITEM) {
+ // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
+ // but only in quirks mode.
+ if (!strictParsing && style->floating() != FNONE)
+ style->setDisplay(BLOCK);
+ }
+ else
+ style->setDisplay(BLOCK);
+ }
+
+ // After performing the display mutation, check our position. We do not honor position:relative on
+ // table rows and some other table displays. This is undefined behaviour in CSS2.1 (cf. 9.3.1)
+ if (style->position() == RELATIVE) {
+ switch (style->display()) {
+ case TABLE_ROW_GROUP:
+ case TABLE_HEADER_GROUP:
+ case TABLE_FOOTER_GROUP:
+ case TABLE_ROW:
+ style->setPosition(STATIC);
+ default:
+ break;
+ }
+ }
+ }
+
+ // Frames and framesets never honor position:relative or position:absolute. This is necessary to
+ // fix a crash where a site tries to position these objects.
+ if ( e ) {
+ // ignore display: none for <frame>
+ if ( e->id() == ID_FRAME ) {
+ style->setPosition( STATIC );
+ style->setDisplay( BLOCK );
+ }
+ else if ( e->id() == ID_FRAMESET ) {
+ style->setPosition( STATIC );
+ }
+ }
+
+ // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
+ // tables, inline blocks, inline tables, or run-ins.
+ if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
+ || style->display() == INLINE_BLOCK /*|| style->display() == INLINE_BOX*/)
+ style->setTextDecorationsInEffect(style->textDecoration());
+ else
+ style->addToTextDecorationsInEffect(style->textDecoration());
+
+ // If either overflow value is not visible, change to auto.
+ if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
+ style->setOverflowY(OMARQUEE);
+ else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
+ style->setOverflowX(OMARQUEE);
+ else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
+ style->setOverflowX(OAUTO);
+ else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
+ style->setOverflowY(OAUTO);
+
+ // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
+ // FIXME: Eventually table sections will support auto and scroll.
+ if (style->display() == TABLE || style->display() == INLINE_TABLE ||
+ style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
+ if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
+ style->setOverflowX(OVISIBLE);
+ if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
+ style->setOverflowY(OVISIBLE);
+ }
+
+ // Cull out any useless layers and also repeat patterns into additional layers.
+ style->adjustBackgroundLayers();
+
+ // Only use slow repaints if we actually have a background image.
+ // FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to
+ // prevent the entire view from blitting on a scroll.
+ if (style->hasFixedBackgroundImage() && view)
+ view->useSlowRepaints();
+}
+
+unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e,
+ DOM::CSSStyleDeclarationImpl *decl,
+ unsigned int numProps)
+{
+ CSSStyleDeclarationImpl* addDecls = 0;
+#ifdef APPLE_CHANGES
+ if (e->id() == ID_TD || e->id() == ID_TH) // For now only TableCellElement implements the
+ addDecls = e->getAdditionalStyleDecls(); // virtual function for shared cell rules.
+#else
+ Q_UNUSED( e );
+#endif
+
+ if (!decl && !addDecls)
+ return numProps;
+
+ TQPtrList<CSSProperty>* values = decl ? decl->values() : 0;
+ TQPtrList<CSSProperty>* addValues = addDecls ? addDecls->values() : 0;
+ if (!values && !addValues)
+ return numProps;
+
+ int firstLen = values ? values->count() : 0;
+ int secondLen = addValues ? addValues->count() : 0;
+ int totalLen = firstLen + secondLen;
+
+ if (inlineProps.size() < (uint)totalLen)
+ inlineProps.resize(totalLen + 1);
+
+ if (numProps + totalLen >= propsToApplySize ) {
+ propsToApplySize += propsToApplySize;
+ propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
+ }
+
+ CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data();
+ for(int i = 0; i < totalLen; i++)
+ {
+ if (i == firstLen)
+ values = addValues;
+
+ CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i);
+ Source source = Inline;
+
+ if( prop->m_important ) source = InlineImportant;
+ if( prop->nonCSSHint ) source = NonCSSHint;
+
+ bool first;
+ // give special priority to font-xxx, color properties
+ switch(prop->m_id)
+ {
+ case CSS_PROP_FONT_STYLE:
+ case CSS_PROP_FONT_SIZE:
+ case CSS_PROP_FONT_WEIGHT:
+ case CSS_PROP_FONT_FAMILY:
+ case CSS_PROP_FONT_VARIANT:
+ case CSS_PROP_FONT:
+ case CSS_PROP_COLOR:
+ case CSS_PROP_DIRECTION:
+ case CSS_PROP_DISPLAY:
+ // these have to be applied first, because other properties use the computed
+ // values of these properties.
+ first = true;
+ break;
+ default:
+ first = false;
+ break;
+ }
+
+ array->prop = prop;
+ array->pseudoId = RenderStyle::NOPSEUDO;
+ array->selector = 0;
+ array->position = i;
+ array->priority = (!first << 30) | (source << 24);
+ propsToApply[numProps++] = array++;
+ }
+ return numProps;
+}
+
+// modified version of the one in kurl.cpp
+static void cleanpath(TQString &path)
+{
+ int pos;
+ while ( (pos = path.find( "/../" )) != -1 ) {
+ int prev = 0;
+ if ( pos > 0 )
+ prev = path.findRev( "/", pos -1 );
+ // don't remove the host, i.e. http://foo.org/../foo.html
+ if (prev < 0 || (prev > 3 && path.findRev("://", prev-1) == prev-2))
+ path.remove( pos, 3);
+ else
+ // matching directory found ?
+ path.remove( prev, pos- prev + 3 );
+ }
+ pos = 0;
+
+ // Don't remove "//" from an anchor identifier. -rjw
+ // Set refPos to -2 to mean "I haven't looked for the anchor yet".
+ // We don't want to waste a function call on the search for the anchor
+ // in the vast majority of cases where there is no "//" in the path.
+ int refPos = -2;
+ while ( (pos = path.find( "//", pos )) != -1) {
+ if (refPos == -2)
+ refPos = path.find("#", 0);
+ if (refPos > 0 && pos >= refPos)
+ break;
+
+ if ( pos == 0 || path[pos-1] != ':' )
+ path.remove( pos, 1 );
+ else
+ pos += 2;
+ }
+ while ( (pos = path.find( "/./" )) != -1)
+ path.remove( pos, 2 );
+ //kdDebug() << "checkPseudoState " << path << endl;
+}
+
+static PseudoState checkPseudoState( const CSSStyleSelector::Encodedurl& encodedurl, DOM::ElementImpl *e )
+{
+ if( e->id() != ID_A ) {
+ return PseudoNone;
+ }
+ DOMString attr = e->getAttribute(ATTR_HREF);
+ if( attr.isNull() ) {
+ return PseudoNone;
+ }
+ TQConstString cu(attr.unicode(), attr.length());
+ TQString u = cu.string();
+ if ( !u.contains("://") ) {
+ if ( u[0] == '/' )
+ u = encodedurl.host + u;
+ else if ( u[0] == '#' )
+ u = encodedurl.file + u;
+ else
+ u = encodedurl.path + u;
+ cleanpath( u );
+ }
+ //completeURL( attr.string() );
+ bool contains = KHTMLFactory::vLinks()->contains( u );
+ if ( !contains && u.contains('/')==2 )
+ contains = KHTMLFactory::vLinks()->contains( u+'/' );
+ return contains ? PseudoVisited : PseudoLink;
+}
+
+// a helper function for parsing nth-arguments
+static bool matchNth(int count, const TQString& nth)
+{
+ if (nth.isEmpty()) return false;
+ int a = 0;
+ int b = 0;
+ if (nth == "odd") {
+ a = 2;
+ b = 1;
+ }
+ else if (nth == "even") {
+ a = 2;
+ b = 0;
+ }
+ else {
+ int n = nth.find('n');
+ if (n != -1) {
+ if (nth[0] == '-')
+ if (n==1)
+ a = -1;
+ else
+ a = nth.mid(1,n-1).toInt();
+ else
+ if (n==0)
+ a = 1;
+ else
+ a = nth.left(n).toInt();
+
+ int p = nth.find('+');
+ if (p != -1)
+ b = nth.mid(p+1).toInt();
+ else {
+ p = nth.find('-');
+ b = -nth.mid(p+1).toInt();
+ }
+ }
+ else {
+ b = nth.toInt();
+ }
+ }
+ if (a == 0)
+ return count == b;
+ else if (a > 0)
+ if (count < b)
+ return false;
+ else
+ return (count - b) % a == 0;
+ else if (a < 0) {
+ if (count > b)
+ return false;
+ else
+ return (b - count) % (-a) == 0;
+ }
+ return false;
+}
+
+
+// Recursively work the combinator to compute static attribute dependency, similar to
+//structure of checkSubSelectors
+static void precomputeAttributeDependenciesAux(DOM::DocumentImpl* doc, DOM::CSSSelector* sel, bool isAncestor, bool isSubject)
+{
+ if(sel->attr)
+ {
+ // Sets up global dependencies of attributes
+ if (isSubject)
+ doc->dynamicDomRestyler().addDependency(sel->attr, PersonalDependency);
+ else if (isAncestor)
+ doc->dynamicDomRestyler().addDependency(sel->attr, AncestorDependency);
+ else
+ doc->dynamicDomRestyler().addDependency(sel->attr, PredecessorDependency);
+ }
+ if(sel->match == CSSSelector::PseudoClass)
+ {
+ switch (sel->pseudoType()) {
+ case CSSSelector::PseudoNot:
+ precomputeAttributeDependenciesAux(doc, sel->simpleSelector, isAncestor, true);
+ break;
+ default:
+ break;
+ }
+ }
+ CSSSelector::Relation relation = sel->relation;
+ sel = sel->tagHistory;
+ if (!sel) return;
+
+ switch(relation)
+ {
+ case CSSSelector::Descendant:
+ case CSSSelector::Child:
+ precomputeAttributeDependenciesAux(doc, sel, true, false);
+ break;
+ case CSSSelector::IndirectAdjacent:
+ case CSSSelector::DirectAdjacent:
+ precomputeAttributeDependenciesAux(doc, sel, false, false);
+ break;
+ case CSSSelector::SubSelector:
+ precomputeAttributeDependenciesAux(doc, sel, isAncestor, isSubject);
+ break;
+ }
+}
+
+void CSSStyleSelector::precomputeAttributeDependencies(DOM::DocumentImpl* doc, DOM::CSSSelector* sel)
+{
+ precomputeAttributeDependenciesAux(doc, sel, false, true);
+}
+
+// Recursive check of selectors and combinators
+// It can return 3 different values:
+// * SelectorMatches - the selector is match for the node e
+// * SelectorFailsLocal - the selector fails for the node e
+// * SelectorFails - the selector fails for e and any sibling or ancestor of e
+CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
+{
+ // The simple selector has to match
+ if(!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) return SelectorFailsLocal;
+
+ // The rest of the selectors has to match
+ CSSSelector::Relation relation = sel->relation;
+
+ // Prepare next sel
+ sel = sel->tagHistory;
+ if (!sel) return SelectorMatches;
+
+ switch(relation) {
+ case CSSSelector::Descendant:
+ {
+ while(true)
+ {
+ DOM::NodeImpl* n = e->parentNode();
+ if(!n || !n->isElementNode()) return SelectorFails;
+ e = static_cast<ElementImpl *>(n);
+ SelectorMatch match = checkSelector(sel, e, true);
+ if (match != SelectorFailsLocal)
+ return match;
+ }
+ break;
+ }
+ case CSSSelector::Child:
+ {
+ DOM::NodeImpl* n = e->parentNode();
+ if (!strictParsing)
+ while (n && n->implicitNode()) n = n->parentNode();
+ if(!n || !n->isElementNode()) return SelectorFails;
+ e = static_cast<ElementImpl *>(n);
+ return checkSelector(sel, e, true);
+ }
+ case CSSSelector::IndirectAdjacent:
+ {
+ // Sibling selectors always generate structural dependencies
+ // because newly inserted element might fullfill them.
+ if (e->parentNode()->isElementNode())
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ while(true)
+ {
+ DOM::NodeImpl* n = e->previousSibling();
+ while( n && !n->isElementNode() )
+ n = n->previousSibling();
+ if( !n ) return SelectorFailsLocal;
+ e = static_cast<ElementImpl *>(n);
+ SelectorMatch match = checkSelector(sel, e, false);
+ if (match != SelectorFailsLocal)
+ return match;
+ };
+ break;
+ }
+ case CSSSelector::DirectAdjacent:
+ {
+ if (e->parentNode()->isElementNode())
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ DOM::NodeImpl* n = e->previousSibling();
+ while( n && !n->isElementNode() )
+ n = n->previousSibling();
+ if( !n ) return SelectorFailsLocal;
+ e = static_cast<ElementImpl *>(n);
+ return checkSelector(sel, e, false);
+ }
+ case CSSSelector::SubSelector:
+ return checkSelector(sel, e, isAncestor, true);
+ }
+ assert(false); // never reached
+ return SelectorFails;
+}
+
+void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl * e)
+{
+ assert(e == element); // yes, actually
+
+ dynamicPseudo = RenderStyle::NOPSEUDO;
+
+ selectorCache[ selIndex ].state = Invalid;
+ CSSSelector *sel = selectors[ selIndex ];
+
+ // Check the selector
+ SelectorMatch match = checkSelector(sel, e, true);
+ if(match != SelectorMatches) return;
+
+ if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
+ selectorCache[selIndex].state = AppliesPseudo;
+ selectors[ selIndex ]->pseudoId = dynamicPseudo;
+ } else
+ selectorCache[ selIndex ].state = Applies;
+ //tqDebug( "selector %d applies", selIndex );
+ //selectors[ selIndex ]->print();
+ return;
+}
+
+void CSSStyleSelector::addDependency(StructuralDependencyType dependencyType, ElementImpl* dependency)
+{
+ element->getDocument()->dynamicDomRestyler().addDependency(element, dependency, dependencyType);
+}
+
+bool CSSStyleSelector::checkSimpleSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector)
+{
+ if(!e)
+ return false;
+
+ if (sel->tag != anyQName) {
+ int eltID = e->id();
+ TQ_UINT16 localName = localNamePart(eltID);
+ TQ_UINT16 ns = namespacePart(eltID);
+ TQ_UINT16 selLocalName = localNamePart(sel->tag);
+ TQ_UINT16 selNS = namespacePart(sel->tag);
+
+ if (localName <= ID_LAST_TAG && ns == defaultNamespace) {
+ assert(e->isHTMLElement());
+ ns = xhtmlNamespace;
+ }
+
+ // match on local
+ if (selLocalName != anyLocalName && localName != selLocalName) return false;
+ // match on namespace
+ if (selNS != anyNamespace && ns != selNS) return false;
+ }
+
+ if(sel->attr)
+ {
+ DOMStringImpl* value = e->getAttributeImpl(sel->attr);
+ if(!value) return false; // attribute is not set
+
+ // attributes are always case-sensitive in XHTML
+ // attributes are sometimes case-sensitive in HTML
+ // we only treat id and class selectors as case-sensitive in HTML strict
+ // for compatibility reasons
+ bool caseSensitive = e->getDocument()->htmlMode() == DocumentImpl::XHtml;
+ bool caseSensitive_alt = strictParsing || caseSensitive;
+ caseSensitive |= (sel->attr > ATTR_LAST_CI_ATTR);
+
+ switch(sel->match)
+ {
+ case CSSSelector::Set:
+ // True if we make it this far
+ break;
+ case CSSSelector::Id:
+ caseSensitive = caseSensitive_alt;
+ // no break
+ case CSSSelector::Exact:
+ return (caseSensitive && !strcmp(sel->value, value)) ||
+ (!caseSensitive && !strcasecmp(sel->value, value));
+ break;
+ case CSSSelector::Class:
+ caseSensitive = caseSensitive_alt;
+ // no break
+ case CSSSelector::List:
+ {
+ int sel_len = sel->value.length();
+ int val_len = value->length();
+ // Be smart compare on length first
+ if (sel_len > val_len) return false;
+ // Selector string may not contain spaces
+ if ((sel->attr != ATTR_CLASS || e->hasClassList()) && sel->value.find(' ') != -1) return false;
+ if (sel_len == val_len)
+ return (caseSensitive && !strcmp(sel->value, value)) ||
+ (!caseSensitive && !strcasecmp(sel->value, value));
+ // else the value is longer and can be a list
+ if ( sel->match == CSSSelector::Class && !e->hasClassList() ) return false;
+
+ TQChar* sel_uc = sel->value.unicode();
+ TQChar* val_uc = value->unicode();
+
+ TQConstString sel_str(sel_uc, sel_len);
+ TQConstString val_str(val_uc, val_len);
+
+ int pos = 0;
+ for ( ;; ) {
+ pos = val_str.string().find(sel_str.string(), pos, caseSensitive);
+ if ( pos == -1 ) return false;
+ if ( pos == 0 || val_uc[pos-1].isSpace() ) {
+ int endpos = pos + sel_len;
+ if ( endpos >= val_len || val_uc[endpos].isSpace() )
+ break; // We have a match.
+ }
+ ++pos;
+ }
+ break;
+ }
+ case CSSSelector::Contain:
+ {
+ //kdDebug( 6080 ) << "checking for contains match" << endl;
+ TQConstString val_str(value->unicode(), value->length());
+ TQConstString sel_str(sel->value.unicode(), sel->value.length());
+ return val_str.string().contains(sel_str.string(), caseSensitive);
+ }
+ case CSSSelector::Begin:
+ {
+ //kdDebug( 6080 ) << "checking for beginswith match" << endl;
+ TQConstString val_str(value->unicode(), value->length());
+ TQConstString sel_str(sel->value.unicode(), sel->value.length());
+ return val_str.string().startsWith(sel_str.string(), caseSensitive);
+ }
+ case CSSSelector::End:
+ {
+ //kdDebug( 6080 ) << "checking for endswith match" << endl;
+ TQConstString val_str(value->unicode(), value->length());
+ TQConstString sel_str(sel->value.unicode(), sel->value.length());
+ return val_str.string().endsWith(sel_str.string(), caseSensitive);
+ }
+ case CSSSelector::Hyphen:
+ {
+ //kdDebug( 6080 ) << "checking for hyphen match" << endl;
+ TQConstString val_str(value->unicode(), value->length());
+ TQConstString sel_str(sel->value.unicode(), sel->value.length());
+ const TQString& str = val_str.string();
+ const TQString& selStr = sel_str.string();
+ if(str.length() < selStr.length()) return false;
+ // Check if str begins with selStr:
+ if(str.find(selStr, 0, caseSensitive) != 0) return false;
+ // It does. Check for exact match or following '-':
+ if(str.length() != selStr.length()
+ && str[selStr.length()] != '-') return false;
+ break;
+ }
+ case CSSSelector::PseudoClass:
+ case CSSSelector::PseudoElement:
+ case CSSSelector::None:
+ break;
+ }
+ }
+
+ if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement)
+ {
+ switch (sel->pseudoType()) {
+ // Pseudo classes:
+ case CSSSelector::PseudoEmpty:
+ addDependency(BackwardsStructuralDependency, e);
+ // If e is not closed yet we don't know the number of children
+ if (!e->closed()) {
+ return false;
+ }
+ if (!e->firstChild())
+ return true;
+ else {
+ // check for empty text nodes
+ NodeImpl *t = e->firstChild();
+
+ while (t && t->isTextNode() && static_cast<TextImpl*>(t)->length() == 0) t = t->nextSibling();
+
+ if (t == 0)
+ return true;
+ else
+ return false;
+ }
+ break;
+ case CSSSelector::PseudoFirstChild: {
+ // first-child matches the first child that is an element!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ // Handle dynamic DOM changes
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n && !n->isElementNode() )
+ n = n->previousSibling();
+ if ( !n )
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoLastChild: {
+ // last-child matches the last child that is an element!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ // Handle unfinished parsing and dynamic DOM changes
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+// kdDebug(6080) << e->nodeName().string() << "::last-child: Parent unclosed" << endl;
+ return false;
+ }
+ DOM::NodeImpl* n = e->nextSibling();
+ while ( n && !n->isElementNode() )
+ n = n->nextSibling();
+ if ( !n )
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoOnlyChild: {
+ // If both first-child and last-child apply, then only-child applies.
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+ return false;
+ }
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n && !n->isElementNode() )
+ n = n->previousSibling();
+ if ( !n ) {
+ n = e->nextSibling();
+ while ( n && !n->isElementNode() )
+ n = n->nextSibling();
+ if ( !n )
+ return true;
+ }
+ }
+ break;
+ }
+ case CSSSelector::PseudoNthChild: {
+ // nth-child matches every (a*n+b)th element!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ int count = 1;
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n ) {
+ if (n->isElementNode()) count++;
+ n = n->previousSibling();
+ }
+// kdDebug(6080) << "NthChild " << count << "=" << sel->string_arg << endl;
+ if (matchNth(count,sel->string_arg.string()))
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoNthLastChild: {
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+ return false;
+ }
+ int count = 1;
+ DOM::NodeImpl* n = e->nextSibling();
+ while ( n ) {
+ if (n->isElementNode()) count++;
+ n = n->nextSibling();
+ }
+// kdDebug(6080) << "NthLastChild " << count << "=" << sel->string_arg << endl;
+ if (matchNth(count,sel->string_arg.string()))
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoFirstOfType: {
+ // first-of-type matches the first element of its type!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ const DOMString& type = e->tagName();
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n ) {
+ if (n->isElementNode())
+ if (static_cast<ElementImpl*>(n)->tagName() == type) break;
+ n = n->previousSibling();
+ }
+ if ( !n )
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoLastOfType: {
+ // last-child matches the last child that is an element!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+ return false;
+ }
+ const DOMString& type = e->tagName();
+ DOM::NodeImpl* n = e->nextSibling();
+ while ( n ) {
+ if (n->isElementNode())
+ if (static_cast<ElementImpl*>(n)->tagName() == type) break;
+ n = n->nextSibling();
+ }
+ if ( !n )
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoOnlyOfType: {
+ // If both first-of-type and last-of-type apply, then only-of-type applies.
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+ return false;
+ }
+ const DOMString& type = e->tagName();
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
+ n = n->previousSibling();
+ if ( !n ) {
+ n = e->nextSibling();
+ while ( n && !(n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type))
+ n = n->nextSibling();
+ if ( !n )
+ return true;
+ }
+ }
+ break;
+ }
+ case CSSSelector::PseudoNthOfType: {
+ // nth-of-type matches every (a*n+b)th element of this type!
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(StructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ int count = 1;
+ const DOMString& type = e->tagName();
+ DOM::NodeImpl* n = e->previousSibling();
+ while ( n ) {
+ if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
+ n = n->previousSibling();
+ }
+// kdDebug(6080) << "NthOfType " << count << "=" << sel->string_arg << endl;
+ if (matchNth(count,sel->string_arg.string()))
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoNthLastOfType: {
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ addDependency(BackwardsStructuralDependency, static_cast<ElementImpl*>(e->parentNode()));
+ if (!e->parentNode()->closed()) {
+ return false;
+ }
+ int count = 1;
+ const DOMString& type = e->tagName();
+ DOM::NodeImpl* n = e->nextSibling();
+ while ( n ) {
+ if (n->isElementNode() && static_cast<ElementImpl*>(n)->tagName() == type) count++;
+ n = n->nextSibling();
+ }
+// kdDebug(6080) << "NthLastOfType " << count << "=" << sel->string_arg << endl;
+ if (matchNth(count,sel->string_arg.string()))
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoTarget:
+ if (e == e->getDocument()->getCSSTarget())
+ return true;
+ break;
+ case CSSSelector::PseudoRoot:
+ if (e == e->getDocument()->documentElement())
+ return true;
+ break;
+ case CSSSelector::PseudoLink:
+ if (e == element) {
+ // cache pseudoState
+ if ( pseudoState == PseudoUnknown )
+ pseudoState = checkPseudoState( encodedurl, e );
+ if ( pseudoState == PseudoLink )
+ return true;
+ } else
+ return checkPseudoState( encodedurl, e ) == PseudoLink;
+ break;
+ case CSSSelector::PseudoVisited:
+ if (e == element) {
+ // cache pseudoState
+ if ( pseudoState == PseudoUnknown )
+ pseudoState = checkPseudoState( encodedurl, e );
+ if ( pseudoState == PseudoVisited )
+ return true;
+ } else
+ return checkPseudoState( encodedurl, e ) == PseudoVisited;
+ break;
+ case CSSSelector::PseudoHover: {
+ // If we're in quirks mode, then *:hover should only match focusable elements.
+ if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable() ) {
+ addDependency(HoverDependency, e);
+
+ if (e->hovered())
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoActive:
+ // If we're in quirks mode, then *:active should only match focusable elements
+ if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable()) {
+ addDependency(ActiveDependency, e);
+
+ if (e->active())
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoFocus:
+ if (e != element && e->isFocusable()) {
+ // *:focus is a default style, no need to track it.
+ addDependency(OtherStateDependency, e);
+ }
+ if (e->focused()) return true;
+ break;
+ case CSSSelector::PseudoLang: {
+ // Set dynamic attribute dependency
+ if (e == element) {
+ e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PersonalDependency);
+ e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
+ }
+ else if (isAncestor)
+ e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency);
+ else
+ e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PredecessorDependency);
+ // ### check xml:lang attribute in XML and XHTML documents
+ DOMString value = e->getAttribute(ATTR_LANG);
+ // The LANG attribute is inherited like a property
+ NodeImpl *n = e->parent();;
+ while (n && value.isEmpty()) {
+ if (n->isElementNode()) {
+ value = static_cast<ElementImpl*>(n)->getAttribute(ATTR_LANG);
+ } else
+ if (n->isDocumentNode()) {
+ value = static_cast<DocumentImpl*>(n)->contentLanguage();
+ }
+ n = n->parent();
+ }
+ if (value.isEmpty()) return false;
+
+ TQString langAttr = value.string();
+ TQString langSel = sel->string_arg.string();
+
+ if(langAttr.length() < langSel.length()) return false;
+
+ langAttr = langAttr.lower();
+ langSel = langSel.lower();
+// kdDebug(6080) << ":lang " << langAttr << "=" << langSel << "?" << endl;
+ return (langAttr == langSel || langAttr.startsWith(langSel+"-"));
+ }
+ case CSSSelector::PseudoNot: {
+ // check the simple selector
+ for (CSSSelector* subSel = sel->simpleSelector; subSel;
+ subSel = subSel->tagHistory) {
+ // :not cannot nest. I don't really know why this is a restriction in CSS3,
+ // but it is, so let's honor it.
+ if (subSel->simpleSelector)
+ break;
+ if (!checkSimpleSelector(subSel, e, isAncestor, true))
+ return true;
+ }
+ break;
+ }
+ case CSSSelector::PseudoEnabled: {
+ if (e->isGenericFormElement()) {
+ addDependency(OtherStateDependency, e);
+ HTMLGenericFormElementImpl *form;
+ form = static_cast<HTMLGenericFormElementImpl*>(e);
+ return !form->disabled();
+ }
+ break;
+ }
+ case CSSSelector::PseudoDisabled: {
+ if (e->isGenericFormElement()) {
+ addDependency(OtherStateDependency, e);
+ HTMLGenericFormElementImpl *form;
+ form = static_cast<HTMLGenericFormElementImpl*>(e);
+ return form->disabled();
+ }
+ break;
+ }
+ case CSSSelector::PseudoContains: {
+ if (e->isHTMLElement()) {
+ addDependency(BackwardsStructuralDependency, e);
+ if (!e->closed()) {
+ return false;
+ }
+ HTMLElementImpl *elem;
+ elem = static_cast<HTMLElementImpl*>(e);
+ DOMString s = elem->innerText();
+ TQString selStr = sel->string_arg.string();
+// kdDebug(6080) << ":contains(\"" << selStr << "\")" << " on \"" << s << "\"" << endl;
+ return s.string().contains(selStr);
+ }
+ break;
+ }
+ case CSSSelector::PseudoChecked: {
+ if (e->isHTMLElement() && e->id() == ID_INPUT) {
+ addDependency(OtherStateDependency, e);
+ return (static_cast<HTMLInputElementImpl*>(e)->checked());
+ }
+ return false;
+ }
+ case CSSSelector::PseudoIndeterminate: {
+#if 0
+ if (e->isHTMLElement() && e->id() == ID_INPUT) {
+ return (static_cast<HTMLInputElementImpl*>(e)->indeterminate() &&
+ !static_cast<HTMLInputElementImpl*>(e)->checked());
+ }
+ return false;
+#endif
+ }
+ case CSSSelector::PseudoOther:
+ break;
+
+ // Pseudo-elements:
+ case CSSSelector::PseudoFirstLine:
+ case CSSSelector::PseudoFirstLetter:
+ case CSSSelector::PseudoSelection:
+ case CSSSelector::PseudoBefore:
+ case CSSSelector::PseudoAfter:
+ case CSSSelector::PseudoMarker:
+ case CSSSelector::PseudoReplaced:
+ // Pseudo-elements can only apply to subject
+ if ( e == element ) {
+ // Pseudo-elements has to be the last sub-selector on subject
+ if (sel->tagHistory && sel->relation == CSSSelector::SubSelector) return false;
+
+ assert(dynamicPseudo == RenderStyle::NOPSEUDO);
+
+ switch (sel->pseudoType()) {
+ case CSSSelector::PseudoFirstLine:
+ dynamicPseudo = RenderStyle::FIRST_LINE;
+ break;
+ case CSSSelector::PseudoFirstLetter:
+ dynamicPseudo = RenderStyle::FIRST_LETTER;
+ break;
+ case CSSSelector::PseudoSelection:
+ dynamicPseudo = RenderStyle::SELECTION;
+ break;
+ case CSSSelector::PseudoBefore:
+ dynamicPseudo = RenderStyle::BEFORE;
+ break;
+ case CSSSelector::PseudoAfter:
+ dynamicPseudo = RenderStyle::AFTER;
+ break;
+ case CSSSelector::PseudoMarker:
+ dynamicPseudo = RenderStyle::MARKER;
+ break;
+ case CSSSelector::PseudoReplaced:
+ dynamicPseudo = RenderStyle::REPLACED;
+ break;
+ default:
+ assert(false);
+ }
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoNotParsed:
+ assert(false);
+ break;
+ }
+ return false;
+ }
+ // ### add the rest of the checks...
+ return true;
+}
+
+void CSSStyleSelector::clearLists()
+{
+ delete [] selectors;
+ if ( selectorCache ) {
+ for ( unsigned int i = 0; i < selectors_size; i++ )
+ delete [] selectorCache[i].props;
+
+ delete [] selectorCache;
+ }
+ if ( properties ) {
+ CSSOrderedProperty **prop = properties;
+ while ( *prop ) {
+ delete (*prop);
+ prop++;
+ }
+ delete [] properties;
+ }
+ selectors = 0;
+ properties = 0;
+ selectorCache = 0;
+}
+
+
+void CSSStyleSelector::buildLists()
+{
+ clearLists();
+ // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup.
+
+ TQPtrList<CSSSelector> selectorList;
+ CSSOrderedPropertyList propertyList;
+
+ if(m_medium == "print" && defaultPrintStyle)
+ defaultPrintStyle->collect( &selectorList, &propertyList, Default,
+ Default );
+ else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList,
+ Default, Default );
+
+ if (!strictParsing && defaultQuirksStyle)
+ defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default );
+
+ if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant );
+ if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant );
+
+ selectors_size = selectorList.count();
+ selectors = new CSSSelector *[selectors_size];
+ CSSSelector *s = selectorList.first();
+ CSSSelector **sel = selectors;
+ while ( s ) {
+ *sel = s;
+ s = selectorList.next();
+ ++sel;
+ }
+
+ selectorCache = new SelectorCache[selectors_size];
+ for ( unsigned int i = 0; i < selectors_size; i++ ) {
+ selectorCache[i].state = Unknown;
+ selectorCache[i].props_size = 0;
+ selectorCache[i].props = 0;
+ }
+
+ // presort properties. Should make the sort() calls in styleForElement faster.
+ propertyList.sort();
+ properties_size = propertyList.count() + 1;
+ properties = new CSSOrderedProperty *[ properties_size ];
+ CSSOrderedProperty *p = propertyList.first();
+ CSSOrderedProperty **prop = properties;
+ while ( p ) {
+ *prop = p;
+ p = propertyList.next();
+ ++prop;
+ }
+ *prop = 0;
+
+ unsigned int* offsets = new unsigned int[selectors_size];
+ if(properties[0])
+ offsets[properties[0]->selector] = 0;
+ for(unsigned int p = 1; p < properties_size; ++p) {
+
+ if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) {
+ unsigned int sel = properties[p - 1]->selector;
+ int* newprops = new int[selectorCache[sel].props_size+2];
+ for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ )
+ newprops[i] = selectorCache[sel].props[i];
+
+ newprops[selectorCache[sel].props_size] = offsets[sel];
+ newprops[selectorCache[sel].props_size+1] = p - offsets[sel];
+ delete [] selectorCache[sel].props;
+ selectorCache[sel].props = newprops;
+ selectorCache[sel].props_size += 2;
+
+ if(properties[p]) {
+ sel = properties[p]->selector;
+ offsets[sel] = p;
+ }
+ }
+ }
+ delete [] offsets;
+}
+
+
+// ----------------------------------------------------------------------
+
+
+CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index)
+{
+ rule = r;
+ if(rule) r->ref();
+ index = _index;
+ selector = s;
+}
+
+CSSOrderedRule::~CSSOrderedRule()
+{
+ if(rule) rule->deref();
+}
+
+// -----------------------------------------------------------------
+
+CSSStyleSelectorList::CSSStyleSelectorList()
+ : TQPtrList<CSSOrderedRule>()
+{
+ setAutoDelete(true);
+}
+CSSStyleSelectorList::~CSSStyleSelectorList()
+{
+}
+
+void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet,
+ const DOMString &medium )
+{
+ if(!sheet || !sheet->isCSSStyleSheet()) return;
+
+ // No media implies "all", but if a medialist exists it must
+ // contain our current medium
+ if( sheet->media() && !sheet->media()->contains( medium ) )
+ return; // style sheet not applicable for this medium
+
+ int len = sheet->length();
+
+ for(int i = 0; i< len; i++)
+ {
+ StyleBaseImpl *item = sheet->item(i);
+ if(item->isStyleRule())
+ {
+ CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item);
+ TQPtrList<CSSSelector> *s = r->selector();
+ for(int j = 0; j < (int)s->count(); j++)
+ {
+ CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count());
+ TQPtrList<CSSOrderedRule>::append(rule);
+ //kdDebug( 6080 ) << "appending StyleRule!" << endl;
+ }
+ }
+ else if(item->isImportRule())
+ {
+ CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
+
+ //kdDebug( 6080 ) << "@import: Media: "
+ // << import->media()->mediaText().string() << endl;
+
+ if( !import->media() || import->media()->contains( medium ) )
+ {
+ CSSStyleSheetImpl *importedSheet = import->styleSheet();
+ append( importedSheet, medium );
+ }
+ }
+ else if( item->isMediaRule() )
+ {
+ CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>( item );
+ CSSRuleListImpl *rules = r->cssRules();
+
+ //DOMString mediaText = media->mediaText();
+ //kdDebug( 6080 ) << "@media: Media: "
+ // << r->media()->mediaText().string() << endl;
+
+ if( ( !r->media() || r->media()->contains( medium ) ) && rules)
+ {
+ // Traverse child elements of the @import rule. Since
+ // many elements are not allowed as child we do not use
+ // a recursive call to append() here
+ for( unsigned j = 0; j < rules->length(); j++ )
+ {
+ //kdDebug( 6080 ) << "*** Rule #" << j << endl;
+
+ CSSRuleImpl *childItem = rules->item( j );
+ if( childItem->isStyleRule() )
+ {
+ // It is a StyleRule, so append it to our list
+ CSSStyleRuleImpl *styleRule =
+ static_cast<CSSStyleRuleImpl *>( childItem );
+
+ TQPtrList<CSSSelector> *s = styleRule->selector();
+ for( int j = 0; j < ( int ) s->count(); j++ )
+ {
+ CSSOrderedRule *orderedRule = new CSSOrderedRule(
+ styleRule, s->at( j ), count() );
+ TQPtrList<CSSOrderedRule>::append( orderedRule );
+ }
+ }
+ else
+ {
+ //kdDebug( 6080 ) << "Ignoring child rule of "
+ // "ImportRule: rule is not a StyleRule!" << endl;
+ }
+ } // for rules
+ } // if rules
+ else
+ {
+ //kdDebug( 6080 ) << "CSSMediaRule not rendered: "
+ // << "rule empty or wrong medium!" << endl;
+ }
+ }
+ // ### include other rules
+ }
+}
+
+
+void CSSStyleSelectorList::collect( TQPtrList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
+ Source regular, Source important )
+{
+ CSSOrderedRule *r = first();
+ while( r ) {
+ CSSSelector *sel = selectorList->first();
+ int selectorNum = 0;
+ while( sel ) {
+ if ( *sel == *(r->selector) )
+ break;
+ sel = selectorList->next();
+ selectorNum++;
+ }
+ if ( !sel )
+ selectorList->append( r->selector );
+// else
+// tqDebug("merged one selector");
+ propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important );
+ r = next();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+int CSSOrderedPropertyList::compareItems(TQPtrCollection::Item i1, TQPtrCollection::Item i2)
+{
+ int diff = static_cast<CSSOrderedProperty *>(i1)->priority
+ - static_cast<CSSOrderedProperty *>(i2)->priority;
+ return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position
+ - static_cast<CSSOrderedProperty *>(i2)->position;
+}
+
+void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
+ Source regular, Source important )
+{
+ TQPtrList<CSSProperty> *values = decl->values();
+ if(!values) return;
+ int len = values->count();
+ for(int i = 0; i < len; i++)
+ {
+ CSSProperty *prop = values->at(i);
+ Source source = regular;
+
+ if( prop->m_important ) source = important;
+ if( prop->nonCSSHint ) source = NonCSSHint;
+
+ bool first = false;
+ // give special priority to font-xxx, color properties
+ switch(prop->m_id)
+ {
+ case CSS_PROP_FONT_STYLE:
+ case CSS_PROP_FONT_SIZE:
+ case CSS_PROP_FONT_WEIGHT:
+ case CSS_PROP_FONT_FAMILY:
+ case CSS_PROP_FONT_VARIANT:
+ case CSS_PROP_FONT:
+ case CSS_PROP_COLOR:
+ case CSS_PROP_DIRECTION:
+ case CSS_PROP_DISPLAY:
+ // these have to be applied first, because other properties use the computed
+ // values of these porperties.
+ first = true;
+ break;
+ default:
+ break;
+ }
+
+ TQPtrList<CSSOrderedProperty>::append(new CSSOrderedProperty(prop, selector,
+ first, source, specificity,
+ count() ));
+ }
+}
+
+// -------------------------------------------------------------------------------------
+// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
+
+static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, TQPaintDeviceMetrics *paintDeviceMetrics, bool *ok = 0 )
+{
+ Length l;
+ if ( !primitiveValue ) {
+ if ( ok )
+ *ok = false;
+ } else {
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent);
+ else if(type == CSSPrimitiveValue::CSS_NUMBER)
+ l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
+ else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
+ l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
+ else if ( ok )
+ *ok = false;
+ }
+ return l;
+}
+
+
+// color mapping code
+struct colorMap {
+ int css_value;
+ QRgb color;
+};
+
+static const colorMap cmap[] = {
+ { CSS_VAL_AQUA, 0xFF00FFFF },
+ { CSS_VAL_BLACK, 0xFF000000 },
+ { CSS_VAL_BLUE, 0xFF0000FF },
+ { CSS_VAL_CRIMSON, 0xFFDC143C },
+ { CSS_VAL_FUCHSIA, 0xFFFF00FF },
+ { CSS_VAL_GRAY, 0xFF808080 },
+ { CSS_VAL_GREEN, 0xFF008000 },
+ { CSS_VAL_INDIGO, 0xFF4B0082 },
+ { CSS_VAL_LIME, 0xFF00FF00 },
+ { CSS_VAL_MAROON, 0xFF800000 },
+ { CSS_VAL_NAVY, 0xFF000080 },
+ { CSS_VAL_OLIVE, 0xFF808000 },
+ { CSS_VAL_ORANGE, 0xFFFFA500 },
+ { CSS_VAL_PURPLE, 0xFF800080 },
+ { CSS_VAL_RED, 0xFFFF0000 },
+ { CSS_VAL_SILVER, 0xFFC0C0C0 },
+ { CSS_VAL_TEAL, 0xFF008080 },
+ { CSS_VAL_WHITE, 0xFFFFFFFF },
+ { CSS_VAL_YELLOW, 0xFFFFFF00 },
+ { CSS_VAL_INVERT, invertedColor },
+ { CSS_VAL_TRANSPARENT, transparentColor },
+ { CSS_VAL_GREY, 0xff808080 },
+ { 0, 0 }
+};
+
+struct uiColors {
+ int css_value;
+ const char * configGroup;
+ const char * configEntry;
+TQPalette::ColorGroup group;
+TQColorGroup::ColorRole role;
+};
+
+const char * const wmgroup = "WM";
+const char * const generalgroup = "General";
+
+/* Mapping system settings to CSS 2
+* Tried hard to get an appropriate mapping - schlpbch
+*/
+static const uiColors uimap[] = {
+ // Active window border.
+ { CSS_VAL_ACTIVEBORDER, wmgroup, "background", TQPalette::Active, TQColorGroup::Light },
+ // Active window caption.
+ { CSS_VAL_ACTIVECAPTION, wmgroup, "background", TQPalette::Active, TQColorGroup::Text },
+ // Text in caption, size box, and scrollbar arrow box.
+ { CSS_VAL_CAPTIONTEXT, wmgroup, "activeForeground", TQPalette::Active, TQColorGroup::Text },
+ // Face color for three-dimensional display elements.
+ { CSS_VAL_BUTTONFACE, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Button },
+ // Dark shadow for three-dimensional display elements (for edges facing away from the light source).
+ { CSS_VAL_BUTTONHIGHLIGHT, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Light },
+ // Shadow color for three-dimensional display elements.
+ { CSS_VAL_BUTTONSHADOW, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Shadow },
+ // Text on push buttons.
+ { CSS_VAL_BUTTONTEXT, wmgroup, "buttonForeground", TQPalette::Inactive, TQColorGroup::ButtonText },
+ // Dark shadow for three-dimensional display elements.
+ { CSS_VAL_THREEDDARKSHADOW, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Dark },
+ // Face color for three-dimensional display elements.
+ { CSS_VAL_THREEDFACE, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Button },
+ // Highlight color for three-dimensional display elements.
+ { CSS_VAL_THREEDHIGHLIGHT, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Light },
+ // Light color for three-dimensional display elements (for edges facing the light source).
+ { CSS_VAL_THREEDLIGHTSHADOW, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Midlight },
+ // Dark shadow for three-dimensional display elements.
+ { CSS_VAL_THREEDSHADOW, wmgroup, 0, TQPalette::Inactive, TQColorGroup::Shadow },
+
+ // Inactive window border.
+ { CSS_VAL_INACTIVEBORDER, wmgroup, "background", TQPalette::Disabled, TQColorGroup::Background },
+ // Inactive window caption.
+ { CSS_VAL_INACTIVECAPTION, wmgroup, "inactiveBackground", TQPalette::Disabled, TQColorGroup::Background },
+ // Color of text in an inactive caption.
+ { CSS_VAL_INACTIVECAPTIONTEXT, wmgroup, "inactiveForeground", TQPalette::Disabled, TQColorGroup::Text },
+ { CSS_VAL_GRAYTEXT, wmgroup, 0, TQPalette::Disabled, TQColorGroup::Text },
+
+ // Menu background
+ { CSS_VAL_MENU, generalgroup, "background", TQPalette::Inactive, TQColorGroup::Background },
+ // Text in menus
+ { CSS_VAL_MENUTEXT, generalgroup, "foreground", TQPalette::Inactive, TQColorGroup::Background },
+
+ // Text of item(s) selected in a control.
+ { CSS_VAL_HIGHLIGHT, generalgroup, "selectBackground", TQPalette::Inactive, TQColorGroup::Background },
+
+ // Text of item(s) selected in a control.
+ { CSS_VAL_HIGHLIGHTTEXT, generalgroup, "selectForeground", TQPalette::Inactive, TQColorGroup::Background },
+
+ // Background color of multiple document interface.
+ { CSS_VAL_APPWORKSPACE, generalgroup, "background", TQPalette::Inactive, TQColorGroup::Text },
+
+ // Scroll bar gray area.
+ { CSS_VAL_SCROLLBAR, generalgroup, "background", TQPalette::Inactive, TQColorGroup::Background },
+
+ // Window background.
+ { CSS_VAL_WINDOW, generalgroup, "windowBackground", TQPalette::Inactive, TQColorGroup::Background },
+ // Window frame.
+ { CSS_VAL_WINDOWFRAME, generalgroup, "windowBackground", TQPalette::Inactive, TQColorGroup::Background },
+ // WindowText
+ { CSS_VAL_WINDOWTEXT, generalgroup, "windowForeground", TQPalette::Inactive, TQColorGroup::Text },
+ { CSS_VAL_TEXT, generalgroup, 0, TQPalette::Inactive, TQColorGroup::Text },
+ { 0, 0, 0, TQPalette::NColorGroups, TQColorGroup::NColorRoles }
+};
+
+static TQColor colorForCSSValue( int css_value )
+{
+ // try the regular ones first
+ const colorMap *col = cmap;
+ while ( col->css_value && col->css_value != css_value )
+ ++col;
+ if ( col->css_value )
+ return col->color;
+
+ const uiColors *uicol = uimap;
+ while ( uicol->css_value && uicol->css_value != css_value )
+ ++uicol;
+#ifndef APPLE_CHANGES
+ if ( !uicol->css_value ) {
+ if ( css_value == CSS_VAL_INFOBACKGROUND )
+ return TQToolTip::palette().inactive().background();
+ else if ( css_value == CSS_VAL_INFOTEXT )
+ return TQToolTip::palette().inactive().foreground();
+ else if ( css_value == CSS_VAL_BACKGROUND ) {
+ TDEConfig bckgrConfig("kdesktoprc", true, false); // No multi-screen support
+ bckgrConfig.setGroup("Desktop0");
+ // Desktop background.
+ return bckgrConfig.readColorEntry("Color1", &tqApp->palette().disabled().background());
+ }
+ return TQColor();
+ }
+#endif
+
+ const TQPalette &pal = tqApp->palette();
+ TQColor c = pal.color( uicol->group, uicol->role );
+#ifndef APPLE_CHANGES
+ if ( uicol->configEntry ) {
+ TDEConfig *globalConfig = TDEGlobal::config();
+ globalConfig->setGroup( uicol->configGroup );
+ c = globalConfig->readColorEntry( uicol->configEntry, &c );
+ }
+#endif
+
+ return c;
+}
+
+static inline int nextFontSize(const TQValueVector<int>& a, int v, bool smaller)
+{
+ // return the nearest bigger/smaller value in scale a, when v is in range.
+ // otherwise increase/decrease value using a 1.2 fixed ratio
+ int m, l = 0, r = a.count()-1;
+ while (l <= r) {
+ m = (l+r)/2;
+ if (a[m] == v)
+ return smaller ? ( m ? a[m-1] : (v*5)/6 ) :
+ ( m+1<int(a.count()) ? a[m+1] : (v*6)/5 );
+ else if (v < a[m])
+ r = m-1;
+ else
+ l = m+1;
+ }
+ if (!l)
+ return smaller ? (v*5)/6 : kMin((v*6)/5, a[0]);
+ if (l == int(a.count()))
+ return smaller ? kMax((v*5)/6, a[r]) : (v*6)/5;
+
+ return smaller ? a[r] : a[l];
+}
+
+void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
+{
+// kdDebug( 6080 ) << "applying property " << getPropertyName(id) << endl;
+
+ CSSPrimitiveValueImpl *primitiveValue = 0;
+ if(value->isPrimitiveValue()) primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
+
+ Length l;
+ bool apply = false;
+
+ bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
+ bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) ||
+ (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT);
+
+ // These properties are used to set the correct margins/padding on RTL lists.
+ if (id == CSS_PROP__KHTML_MARGIN_START)
+ id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT;
+ else if (id == CSS_PROP__KHTML_PADDING_START)
+ id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT;
+
+ // What follows is a list that maps the CSS properties into their corresponding front-end
+ // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
+ // are only hit when mapping "inherit" or "initial" into front-end values.
+ switch(id)
+ {
+// ident only properties
+ case CSS_PROP_BACKGROUND_ATTACHMENT:
+ HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value)
+ break;
+ case CSS_PROP__KHTML_BACKGROUND_CLIP:
+ HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value)
+ break;
+ case CSS_PROP__KHTML_BACKGROUND_ORIGIN:
+ HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value)
+ break;
+ case CSS_PROP_BACKGROUND_REPEAT:
+ HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value)
+ break;
+ case CSS_PROP__KHTML_BACKGROUND_SIZE:
+ HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value)
+ break;
+ case CSS_PROP_BORDER_COLLAPSE:
+ HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
+ if(!primitiveValue) break;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_COLLAPSE:
+ style->setBorderCollapse(true);
+ break;
+ case CSS_VAL_SEPARATE:
+ style->setBorderCollapse(false);
+ break;
+ default:
+ return;
+ }
+ break;
+
+ case CSS_PROP_BORDER_TOP_STYLE:
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
+ if (!primitiveValue) return;
+ style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
+ break;
+ case CSS_PROP_BORDER_RIGHT_STYLE:
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
+ if (!primitiveValue) return;
+ style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
+ break;
+ case CSS_PROP_BORDER_BOTTOM_STYLE:
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
+ if (!primitiveValue) return;
+ style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
+ break;
+ case CSS_PROP_BORDER_LEFT_STYLE:
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
+ if (!primitiveValue) return;
+ style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
+ break;
+ case CSS_PROP_OUTLINE_STYLE:
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
+ if (!primitiveValue) return;
+ style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE));
+ break;
+ case CSS_PROP_CAPTION_SIDE:
+ {
+ HANDLE_INHERIT_AND_INITIAL(captionSide, CaptionSide)
+ if(!primitiveValue) break;
+ ECaptionSide c = RenderStyle::initialCaptionSide();
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_LEFT:
+ c = CAPLEFT; break;
+ case CSS_VAL_RIGHT:
+ c = CAPRIGHT; break;
+ case CSS_VAL_TOP:
+ c = CAPTOP; break;
+ case CSS_VAL_BOTTOM:
+ c = CAPBOTTOM; break;
+ default:
+ return;
+ }
+ style->setCaptionSide(c);
+ return;
+ }
+ case CSS_PROP_CLEAR:
+ {
+ HANDLE_INHERIT_AND_INITIAL(clear, Clear)
+ if(!primitiveValue) break;
+ EClear c = CNONE;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_LEFT:
+ c = CLEFT; break;
+ case CSS_VAL_RIGHT:
+ c = CRIGHT; break;
+ case CSS_VAL_BOTH:
+ c = CBOTH; break;
+ case CSS_VAL_NONE:
+ c = CNONE; break;
+ default:
+ return;
+ }
+ style->setClear(c);
+ return;
+ }
+ case CSS_PROP_DIRECTION:
+ {
+ HANDLE_INHERIT_AND_INITIAL(direction, Direction)
+ if(!primitiveValue) break;
+ style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) );
+ return;
+ }
+ case CSS_PROP_DISPLAY:
+ {
+ HANDLE_INHERIT_AND_INITIAL(display, Display)
+ if(!primitiveValue) break;
+ int id = primitiveValue->getIdent();
+ style->setDisplay( id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE) );
+ break;
+ }
+
+ case CSS_PROP_EMPTY_CELLS:
+ {
+ HANDLE_INHERIT(emptyCells, EmptyCells);
+ if (!primitiveValue) break;
+ int id = primitiveValue->getIdent();
+ if (id == CSS_VAL_SHOW)
+ style->setEmptyCells(SHOW);
+ else if (id == CSS_VAL_HIDE)
+ style->setEmptyCells(HIDE);
+ break;
+ }
+ case CSS_PROP_FLOAT:
+ {
+ HANDLE_INHERIT_AND_INITIAL(floating, Floating)
+ if(!primitiveValue) return;
+ EFloat f;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL__KHTML_LEFT:
+ f = FLEFT_ALIGN; break;
+ case CSS_VAL_LEFT:
+ f = FLEFT; break;
+ case CSS_VAL__KHTML_RIGHT:
+ f = FRIGHT_ALIGN; break;
+ case CSS_VAL_RIGHT:
+ f = FRIGHT; break;
+ case CSS_VAL_NONE:
+ case CSS_VAL_CENTER: //Non standart CSS-Value
+ f = FNONE; break;
+ default:
+ return;
+ }
+ if (f!=FNONE && style->display()==LIST_ITEM)
+ style->setDisplay(BLOCK);
+
+ style->setFloating(f);
+ break;
+ }
+
+ case CSS_PROP_FONT_STYLE:
+ {
+ FontDef fontDef = style->htmlFont().fontDef;
+ if (isInherit)
+ fontDef.italic = parentStyle->htmlFont().fontDef.italic;
+ else if (isInitial)
+ fontDef.italic = false;
+ else {
+ if(!primitiveValue) return;
+ switch(primitiveValue->getIdent()) {
+ case CSS_VAL_OBLIQUE:
+ // ### oblique is the same as italic for the moment...
+ case CSS_VAL_ITALIC:
+ fontDef.italic = true;
+ break;
+ case CSS_VAL_NORMAL:
+ fontDef.italic = false;
+ break;
+ default:
+ return;
+ }
+ }
+ fontDirty |= style->setFontDef( fontDef );
+ break;
+ }
+
+
+ case CSS_PROP_FONT_VARIANT:
+ {
+ FontDef fontDef = style->htmlFont().fontDef;
+ if (isInherit)
+ fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps;
+ else if (isInitial)
+ fontDef.smallCaps = false;
+ else {
+ if(!primitiveValue) return;
+ int id = primitiveValue->getIdent();
+ if ( id == CSS_VAL_NORMAL )
+ fontDef.smallCaps = false;
+ else if ( id == CSS_VAL_SMALL_CAPS )
+ fontDef.smallCaps = true;
+ else
+ return;
+ }
+ fontDirty |= style->setFontDef( fontDef );
+ break;
+ }
+
+ case CSS_PROP_FONT_WEIGHT:
+ {
+ FontDef fontDef = style->htmlFont().fontDef;
+ if (isInherit)
+ fontDef.weight = parentStyle->htmlFont().fontDef.weight;
+ else if (isInitial)
+ fontDef.weight = TQFont::Normal;
+ else {
+ if(!primitiveValue) return;
+ if(primitiveValue->getIdent())
+ {
+ switch(primitiveValue->getIdent()) {
+ // ### we just support normal and bold fonts at the moment...
+ // setWeight can actually accept values between 0 and 99...
+ case CSS_VAL_BOLD:
+ case CSS_VAL_BOLDER:
+ case CSS_VAL_600:
+ case CSS_VAL_700:
+ case CSS_VAL_800:
+ case CSS_VAL_900:
+ fontDef.weight = TQFont::Bold;
+ break;
+ case CSS_VAL_NORMAL:
+ case CSS_VAL_LIGHTER:
+ case CSS_VAL_100:
+ case CSS_VAL_200:
+ case CSS_VAL_300:
+ case CSS_VAL_400:
+ case CSS_VAL_500:
+ fontDef.weight = TQFont::Normal;
+ break;
+ default:
+ return;
+ }
+ }
+ else
+ {
+ // ### fix parsing of 100-900 values in parser, apply them here
+ }
+ }
+ fontDirty |= style->setFontDef( fontDef );
+ break;
+ }
+
+ case CSS_PROP_LIST_STYLE_POSITION:
+ {
+ HANDLE_INHERIT_AND_INITIAL(listStylePosition, ListStylePosition)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent())
+ style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) );
+ return;
+ }
+
+ case CSS_PROP_LIST_STYLE_TYPE:
+ {
+ HANDLE_INHERIT_AND_INITIAL(listStyleType, ListStyleType)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent())
+ {
+ EListStyleType t;
+ int id = primitiveValue->getIdent();
+ if ( id == CSS_VAL_NONE) { // important!!
+ t = LNONE;
+ } else {
+ t = EListStyleType(id - CSS_VAL_DISC);
+ }
+ style->setListStyleType(t);
+ }
+ return;
+ }
+
+ case CSS_PROP_OVERFLOW:
+ {
+ if (isInherit) {
+ style->setOverflowX(parentStyle->overflowX());
+ style->setOverflowY(parentStyle->overflowY());
+ return;
+ }
+
+ if (isInitial) {
+ style->setOverflowX(RenderStyle::initialOverflowX());
+ style->setOverflowY(RenderStyle::initialOverflowY());
+ return;
+ }
+
+ if (!primitiveValue) return;
+ EOverflow o;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_VISIBLE:
+ o = OVISIBLE; break;
+ case CSS_VAL_HIDDEN:
+ o = OHIDDEN; break;
+ case CSS_VAL_SCROLL:
+ o = OSCROLL; break;
+ case CSS_VAL_AUTO:
+ o = OAUTO; break;
+ case CSS_VAL_MARQUEE:
+ o = OMARQUEE; break;
+ default:
+ return;
+ }
+ style->setOverflowX(o);
+ style->setOverflowY(o);
+ return;
+ }
+ case CSS_PROP_OVERFLOW_X:
+ {
+ HANDLE_INHERIT_AND_INITIAL(overflowX, OverflowX)
+ if (!primitiveValue) return;
+ EOverflow o;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_VISIBLE:
+ o = OVISIBLE; break;
+ case CSS_VAL_HIDDEN:
+ o = OHIDDEN; break;
+ case CSS_VAL_SCROLL:
+ o = OSCROLL; break;
+ case CSS_VAL_AUTO:
+ o = OAUTO; break;
+ default:
+ return;
+ }
+ style->setOverflowX(o);
+ return;
+ }
+ case CSS_PROP_OVERFLOW_Y:
+ {
+ HANDLE_INHERIT_AND_INITIAL(overflowY, OverflowY)
+ if (!primitiveValue) return;
+ EOverflow o;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_VISIBLE:
+ o = OVISIBLE; break;
+ case CSS_VAL_HIDDEN:
+ o = OHIDDEN; break;
+ case CSS_VAL_SCROLL:
+ o = OSCROLL; break;
+ case CSS_VAL_AUTO:
+ o = OAUTO; break;
+ default:
+ return;
+ }
+ style->setOverflowY(o);
+ return;
+ }
+ case CSS_PROP_PAGE_BREAK_BEFORE:
+ {
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
+ if (!primitiveValue) return;
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_AUTO:
+ style->setPageBreakBefore(PBAUTO);
+ break;
+ case CSS_VAL_LEFT:
+ case CSS_VAL_RIGHT:
+ // CSS2.1: "Conforming user agents may map left/right to always."
+ case CSS_VAL_ALWAYS:
+ style->setPageBreakBefore(PBALWAYS);
+ break;
+ case CSS_VAL_AVOID:
+ style->setPageBreakBefore(PBAVOID);
+ break;
+ }
+ break;
+ }
+
+ case CSS_PROP_PAGE_BREAK_AFTER:
+ {
+ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
+ if (!primitiveValue) return;
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_AUTO:
+ style->setPageBreakAfter(PBAUTO);
+ break;
+ case CSS_VAL_LEFT:
+ case CSS_VAL_RIGHT:
+ // CSS2.1: "Conforming user agents may map left/right to always."
+ case CSS_VAL_ALWAYS:
+ style->setPageBreakAfter(PBALWAYS);
+ break;
+ case CSS_VAL_AVOID:
+ style->setPageBreakAfter(PBAVOID);
+ break;
+ }
+ break;
+ }
+
+ case CSS_PROP_PAGE_BREAK_INSIDE: {
+ HANDLE_INHERIT_AND_INITIAL(pageBreakInside, PageBreakInside)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent() == CSS_VAL_AUTO)
+ style->setPageBreakInside(true);
+ else if (primitiveValue->getIdent() == CSS_VAL_AVOID)
+ style->setPageBreakInside(false);
+ return;
+ }
+// case CSS_PROP_PAUSE_AFTER:
+// case CSS_PROP_PAUSE_BEFORE:
+ break;
+
+ case CSS_PROP_POSITION:
+ {
+ HANDLE_INHERIT_AND_INITIAL(position, Position)
+ if (!primitiveValue) return;
+ EPosition p;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_STATIC:
+ p = STATIC; break;
+ case CSS_VAL_RELATIVE:
+ p = RELATIVE; break;
+ case CSS_VAL_ABSOLUTE:
+ p = ABSOLUTE; break;
+ case CSS_VAL_FIXED:
+ {
+ view->useSlowRepaints();
+ p = FIXED;
+ break;
+ }
+ default:
+ return;
+ }
+ style->setPosition(p);
+ return;
+ }
+
+ case CSS_PROP_TABLE_LAYOUT: {
+ HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
+
+ if ( !primitiveValue )
+ return;
+
+ ETableLayout l = RenderStyle::initialTableLayout();
+ switch( primitiveValue->getIdent() ) {
+ case CSS_VAL_FIXED:
+ l = TFIXED;
+ // fall through
+ case CSS_VAL_AUTO:
+ style->setTableLayout( l );
+ default:
+ break;
+ }
+ break;
+ }
+
+ case CSS_PROP_UNICODE_BIDI: {
+ HANDLE_INHERIT_AND_INITIAL(unicodeBidi, UnicodeBidi)
+ if(!primitiveValue) break;
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_NORMAL:
+ style->setUnicodeBidi(UBNormal);
+ break;
+ case CSS_VAL_EMBED:
+ style->setUnicodeBidi(Embed);
+ break;
+ case CSS_VAL_BIDI_OVERRIDE:
+ style->setUnicodeBidi(Override);
+ break;
+ default:
+ return;
+ }
+ break;
+ }
+ case CSS_PROP_TEXT_TRANSFORM: {
+ HANDLE_INHERIT_AND_INITIAL(textTransform, TextTransform)
+
+ if(!primitiveValue) break;
+ if(!primitiveValue->getIdent()) return;
+
+ ETextTransform tt;
+ switch(primitiveValue->getIdent()) {
+ case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break;
+ case CSS_VAL_UPPERCASE: tt = UPPERCASE; break;
+ case CSS_VAL_LOWERCASE: tt = LOWERCASE; break;
+ case CSS_VAL_NONE:
+ default: tt = TTNONE; break;
+ }
+ style->setTextTransform(tt);
+ break;
+ }
+
+ case CSS_PROP_VISIBILITY:
+ {
+ HANDLE_INHERIT_AND_INITIAL(visibility, Visibility)
+
+ if(!primitiveValue) break;
+ switch( primitiveValue->getIdent() ) {
+ case CSS_VAL_HIDDEN:
+ style->setVisibility( HIDDEN );
+ break;
+ case CSS_VAL_VISIBLE:
+ style->setVisibility( VISIBLE );
+ break;
+ case CSS_VAL_COLLAPSE:
+ style->setVisibility( COLLAPSE );
+ default:
+ break;
+ }
+ break;
+ }
+ case CSS_PROP_WHITE_SPACE:
+ HANDLE_INHERIT_AND_INITIAL(whiteSpace, WhiteSpace)
+
+ if(!primitiveValue) break;
+ if(!primitiveValue->getIdent()) return;
+
+ EWhiteSpace s;
+ switch(primitiveValue->getIdent()) {
+ case CSS_VAL__KHTML_NOWRAP:
+ s = KHTML_NOWRAP;
+ break;
+ case CSS_VAL_NOWRAP:
+ s = NOWRAP;
+ break;
+ case CSS_VAL_PRE:
+ s = PRE;
+ break;
+ case CSS_VAL_PRE_WRAP:
+ s = PRE_WRAP;
+ break;
+ case CSS_VAL_PRE_LINE:
+ s = PRE_LINE;
+ break;
+ case CSS_VAL_NORMAL:
+ default:
+ s = NORMAL;
+ break;
+ }
+ style->setWhiteSpace(s);
+ break;
+
+ case CSS_PROP_BACKGROUND_POSITION:
+ HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition);
+ HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition);
+ break;
+ case CSS_PROP_BACKGROUND_POSITION_X: {
+ HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value)
+ break;
+ }
+ case CSS_PROP_BACKGROUND_POSITION_Y: {
+ HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value)
+ break;
+ }
+ case CSS_PROP_BORDER_SPACING: {
+ if(value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
+ style->setBorderHorizontalSpacing(parentStyle->borderHorizontalSpacing());
+ style->setBorderVerticalSpacing(parentStyle->borderVerticalSpacing());
+ break;
+ }
+ case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: {
+ HANDLE_INHERIT_AND_INITIAL(borderHorizontalSpacing, BorderHorizontalSpacing)
+ if (!primitiveValue) break;
+ short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
+ style->setBorderHorizontalSpacing(spacing);
+ break;
+ }
+ case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: {
+ HANDLE_INHERIT_AND_INITIAL(borderVerticalSpacing, BorderVerticalSpacing)
+ if (!primitiveValue) break;
+ short spacing = primitiveValue->computeLength(style, paintDeviceMetrics);
+ style->setBorderVerticalSpacing(spacing);
+ break;
+ }
+
+ case CSS_PROP_CURSOR:
+ HANDLE_INHERIT_AND_INITIAL(cursor, Cursor)
+ if(primitiveValue)
+ style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) );
+ break;
+// colors || inherit
+ case CSS_PROP_BACKGROUND_COLOR:
+ case CSS_PROP_BORDER_TOP_COLOR:
+ case CSS_PROP_BORDER_RIGHT_COLOR:
+ case CSS_PROP_BORDER_BOTTOM_COLOR:
+ case CSS_PROP_BORDER_LEFT_COLOR:
+ case CSS_PROP_COLOR:
+ case CSS_PROP_OUTLINE_COLOR:
+ // this property is an extension used to get HTML4 <font> right.
+ case CSS_PROP_SCROLLBAR_BASE_COLOR:
+ case CSS_PROP_SCROLLBAR_FACE_COLOR:
+ case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
+ case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
+ case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
+ case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
+ case CSS_PROP_SCROLLBAR_TRACK_COLOR:
+ case CSS_PROP_SCROLLBAR_ARROW_COLOR:
+ {
+ TQColor col;
+ if (isInherit) {
+ HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor)
+ HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color)
+ HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor)
+ return;
+ } else if (isInitial) {
+ // The border/outline colors will just map to the invalid color |col| above. This will have the
+ // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
+ // not painting the background since the color won't be valid).
+ if (id == CSS_PROP_COLOR)
+ col = RenderStyle::initialColor();
+ } else {
+ if(!primitiveValue )
+ return;
+ int ident = primitiveValue->getIdent();
+ if ( ident ) {
+ if ( ident == CSS_VAL__KHTML_TEXT )
+ col = element->getDocument()->textColor();
+ // ### should be eliminated
+ else if ( ident == CSS_VAL_TRANSPARENT
+ && id != CSS_PROP_BORDER_TOP_COLOR
+ && id != CSS_PROP_BORDER_RIGHT_COLOR
+ && id != CSS_PROP_BORDER_BOTTOM_COLOR
+ && id != CSS_PROP_BORDER_LEFT_COLOR )
+ col = TQColor();
+ else
+ col = colorForCSSValue( ident );
+ } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) {
+#ifndef APPLE_CHANGES
+ if(tqAlpha(primitiveValue->getRGBColorValue()))
+#endif
+ col.setRgb(primitiveValue->getRGBColorValue());
+ } else {
+ return;
+ }
+ }
+ //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
+ switch(id)
+ {
+ case CSS_PROP_BACKGROUND_COLOR:
+ style->setBackgroundColor(col); break;
+ case CSS_PROP_BORDER_TOP_COLOR:
+ style->setBorderTopColor(col); break;
+ case CSS_PROP_BORDER_RIGHT_COLOR:
+ style->setBorderRightColor(col); break;
+ case CSS_PROP_BORDER_BOTTOM_COLOR:
+ style->setBorderBottomColor(col); break;
+ case CSS_PROP_BORDER_LEFT_COLOR:
+ style->setBorderLeftColor(col); break;
+ case CSS_PROP_COLOR:
+ style->setColor(col); break;
+ case CSS_PROP_OUTLINE_COLOR:
+ style->setOutlineColor(col); break;
+#ifndef APPLE_CHANGES
+ case CSS_PROP_SCROLLBAR_FACE_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Button, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Button, col);
+ break;
+ case CSS_PROP_SCROLLBAR_SHADOW_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Shadow, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Shadow, col);
+ break;
+ case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Light, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Light, col);
+ break;
+ case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR:
+ break;
+ case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Dark, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Dark, col);
+ break;
+ case CSS_PROP_SCROLLBAR_TRACK_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Mid, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Mid, col);
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Background, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Background, col);
+ // fall through
+ case CSS_PROP_SCROLLBAR_BASE_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::Base, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::Base, col);
+ break;
+ case CSS_PROP_SCROLLBAR_ARROW_COLOR:
+ style->setPaletteColor(TQPalette::Active, TQColorGroup::ButtonText, col);
+ style->setPaletteColor(TQPalette::Inactive, TQColorGroup::ButtonText, col);
+ break;
+#endif
+ default:
+ return;
+ }
+ return;
+ }
+ break;
+// uri || inherit
+ case CSS_PROP_BACKGROUND_IMAGE:
+ HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value)
+ break;
+ case CSS_PROP_LIST_STYLE_IMAGE:
+ {
+ HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
+ if (!primitiveValue) return;
+ style->setListStyleImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
+ //kdDebug( 6080 ) << "setting image in list to " << image->image() << endl;
+ break;
+ }
+
+// length
+ case CSS_PROP_BORDER_TOP_WIDTH:
+ case CSS_PROP_BORDER_RIGHT_WIDTH:
+ case CSS_PROP_BORDER_BOTTOM_WIDTH:
+ case CSS_PROP_BORDER_LEFT_WIDTH:
+ case CSS_PROP_OUTLINE_WIDTH:
+ {
+ if (isInherit) {
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth)
+ return;
+ }
+ else if (isInitial) {
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth)
+ return;
+ }
+
+ if(!primitiveValue) break;
+ short width = 3;
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_THIN:
+ width = 1;
+ break;
+ case CSS_VAL_MEDIUM:
+ width = 3;
+ break;
+ case CSS_VAL_THICK:
+ width = 5;
+ break;
+ case CSS_VAL_INVALID:
+ {
+ double widthd = primitiveValue->computeLengthFloat(style, paintDeviceMetrics);
+ width = (int)widthd;
+ // somewhat resemble Mozilla's granularity
+ // this makes border-width: 0.5pt borders visible
+ if (width == 0 && widthd >= 0.025) width++;
+ break;
+ }
+ default:
+ return;
+ }
+
+ if(width < 0) return;
+ switch(id)
+ {
+ case CSS_PROP_BORDER_TOP_WIDTH:
+ style->setBorderTopWidth(width);
+ break;
+ case CSS_PROP_BORDER_RIGHT_WIDTH:
+ style->setBorderRightWidth(width);
+ break;
+ case CSS_PROP_BORDER_BOTTOM_WIDTH:
+ style->setBorderBottomWidth(width);
+ break;
+ case CSS_PROP_BORDER_LEFT_WIDTH:
+ style->setBorderLeftWidth(width);
+ break;
+ case CSS_PROP_OUTLINE_WIDTH:
+ style->setOutlineWidth(width);
+ break;
+ default:
+ return;
+ }
+ return;
+ }
+
+ case CSS_PROP_LETTER_SPACING:
+ case CSS_PROP_WORD_SPACING:
+ {
+ if (isInherit) {
+ HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing)
+ HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing)
+ return;
+ } else if (isInitial) {
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing)
+ return;
+ }
+ if(!primitiveValue) return;
+
+ int width = 0;
+ if (primitiveValue->getIdent() != CSS_VAL_NORMAL)
+ width = primitiveValue->computeLength(style, paintDeviceMetrics);
+
+ switch(id)
+ {
+ case CSS_PROP_LETTER_SPACING:
+ style->setLetterSpacing(width);
+ break;
+ case CSS_PROP_WORD_SPACING:
+ style->setWordSpacing(width);
+ break;
+ // ### needs the definitions in renderstyle
+ default: break;
+ }
+ return;
+ }
+
+ // length, percent
+ case CSS_PROP_MAX_WIDTH:
+ // +none +inherit
+ if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
+ apply = true;
+ l = Length(UNDEFINED, Fixed);
+ }
+ case CSS_PROP_TOP:
+ case CSS_PROP_LEFT:
+ case CSS_PROP_RIGHT:
+ case CSS_PROP_BOTTOM:
+ case CSS_PROP_WIDTH:
+ case CSS_PROP_MIN_WIDTH:
+ case CSS_PROP_MARGIN_TOP:
+ case CSS_PROP_MARGIN_RIGHT:
+ case CSS_PROP_MARGIN_BOTTOM:
+ case CSS_PROP_MARGIN_LEFT:
+ // +inherit +auto
+ if(id != CSS_PROP_MAX_WIDTH && primitiveValue &&
+ primitiveValue->getIdent() == CSS_VAL_AUTO)
+ {
+ //kdDebug( 6080 ) << "found value=auto" << endl;
+ apply = true;
+ }
+ case CSS_PROP_PADDING_TOP:
+ case CSS_PROP_PADDING_RIGHT:
+ case CSS_PROP_PADDING_BOTTOM:
+ case CSS_PROP_PADDING_LEFT:
+ case CSS_PROP_TEXT_INDENT:
+ // +inherit
+ {
+ if (isInherit) {
+ HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom)
+ HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top)
+ HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left)
+ HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right)
+ HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width)
+ HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth)
+ HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop)
+ HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight)
+ HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom)
+ HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft)
+ HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop)
+ HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight)
+ HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom)
+ HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft)
+ HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent)
+ return;
+ } else if (isInitial) {
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin)
+ HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent)
+ return;
+ }
+
+ if (primitiveValue && !apply) {
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ // Handle our quirky margin units if we have them.
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed,
+ primitiveValue->isQuirkValue());
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE)
+ l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative);
+ else
+ return;
+ apply = true;
+ }
+ if(!apply) return;
+ switch(id)
+ {
+ case CSS_PROP_MAX_WIDTH:
+ style->setMaxWidth(l); break;
+ case CSS_PROP_BOTTOM:
+ style->setBottom(l); break;
+ case CSS_PROP_TOP:
+ style->setTop(l); break;
+ case CSS_PROP_LEFT:
+ style->setLeft(l); break;
+ case CSS_PROP_RIGHT:
+ style->setRight(l); break;
+ case CSS_PROP_WIDTH:
+ style->setWidth(l); break;
+ case CSS_PROP_MIN_WIDTH:
+ style->setMinWidth(l); break;
+ case CSS_PROP_PADDING_TOP:
+ style->setPaddingTop(l); break;
+ case CSS_PROP_PADDING_RIGHT:
+ style->setPaddingRight(l); break;
+ case CSS_PROP_PADDING_BOTTOM:
+ style->setPaddingBottom(l); break;
+ case CSS_PROP_PADDING_LEFT:
+ style->setPaddingLeft(l); break;
+ case CSS_PROP_MARGIN_TOP:
+ style->setMarginTop(l); break;
+ case CSS_PROP_MARGIN_RIGHT:
+ style->setMarginRight(l); break;
+ case CSS_PROP_MARGIN_BOTTOM:
+ style->setMarginBottom(l); break;
+ case CSS_PROP_MARGIN_LEFT:
+ style->setMarginLeft(l); break;
+ case CSS_PROP_TEXT_INDENT:
+ style->setTextIndent(l); break;
+ default: break;
+ }
+ return;
+ }
+
+ case CSS_PROP_MAX_HEIGHT:
+ if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
+ apply = true;
+ l = Length(UNDEFINED, Fixed);
+ }
+ case CSS_PROP_HEIGHT:
+ case CSS_PROP_MIN_HEIGHT:
+ if(id != CSS_PROP_MAX_HEIGHT && primitiveValue &&
+ primitiveValue->getIdent() == CSS_VAL_AUTO)
+ apply = true;
+ if (isInherit) {
+ HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight)
+ HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height)
+ HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight)
+ return;
+ }
+ else if (isInitial) {
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size)
+ HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize)
+ return;
+ }
+
+ if (primitiveValue && !apply)
+ {
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else
+ return;
+ apply = true;
+ }
+ if(!apply) return;
+ switch(id)
+ {
+ case CSS_PROP_MAX_HEIGHT:
+ style->setMaxHeight(l); break;
+ case CSS_PROP_HEIGHT:
+ style->setHeight(l); break;
+ case CSS_PROP_MIN_HEIGHT:
+ style->setMinHeight(l); break;
+ default:
+ return;
+ }
+ return;
+
+ break;
+
+ case CSS_PROP_VERTICAL_ALIGN:
+ HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent()) {
+ tdehtml::EVerticalAlign align;
+
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_TOP:
+ align = TOP; break;
+ case CSS_VAL_BOTTOM:
+ align = BOTTOM; break;
+ case CSS_VAL_MIDDLE:
+ align = MIDDLE; break;
+ case CSS_VAL_BASELINE:
+ align = BASELINE; break;
+ case CSS_VAL_TEXT_BOTTOM:
+ align = TEXT_BOTTOM; break;
+ case CSS_VAL_TEXT_TOP:
+ align = TEXT_TOP; break;
+ case CSS_VAL_SUB:
+ align = SUB; break;
+ case CSS_VAL_SUPER:
+ align = SUPER; break;
+ case CSS_VAL__KHTML_BASELINE_MIDDLE:
+ align = BASELINE_MIDDLE; break;
+ default:
+ return;
+ }
+ style->setVerticalAlign(align);
+ return;
+ } else {
+ int type = primitiveValue->primitiveType();
+ Length l;
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length( int( primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent );
+
+ style->setVerticalAlign( LENGTH );
+ style->setVerticalAlignLength( l );
+ }
+ break;
+
+ case CSS_PROP_FONT_SIZE:
+ {
+ FontDef fontDef = style->htmlFont().fontDef;
+ int oldSize;
+ int size = 0;
+
+ float toPix = paintDeviceMetrics->logicalDpiY()/72.;
+ if (toPix < 96./72.) toPix = 96./72.;
+
+ int minFontSize = int(settings->minFontSize() * toPix);
+
+ if(parentNode) {
+ oldSize = parentStyle->font().pixelSize();
+ } else
+ oldSize = m_fontSizes[3];
+
+ if (isInherit )
+ size = oldSize;
+ else if (isInitial)
+ size = m_fontSizes[3];
+ else if(primitiveValue->getIdent()) {
+ // keywords are being used. Pick the correct default
+ // based off the font family.
+#ifdef APPLE_CHANGES
+ const TQValueVector<int>& fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ?
+ m_fixedFontSizes : m_fontSizes;
+#else
+ const TQValueVector<int>& fontSizes = m_fontSizes;
+#endif
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_XX_SMALL: size = int( fontSizes[0] ); break;
+ case CSS_VAL_X_SMALL: size = int( fontSizes[1] ); break;
+ case CSS_VAL_SMALL: size = int( fontSizes[2] ); break;
+ case CSS_VAL_MEDIUM: size = int( fontSizes[3] ); break;
+ case CSS_VAL_LARGE: size = int( fontSizes[4] ); break;
+ case CSS_VAL_X_LARGE: size = int( fontSizes[5] ); break;
+ case CSS_VAL_XX_LARGE: size = int( fontSizes[6] ); break;
+ case CSS_VAL__KHTML_XXX_LARGE: size = int( fontSizes[7] ); break;
+ case CSS_VAL_LARGER:
+ size = nextFontSize(fontSizes, oldSize, false);
+ break;
+ case CSS_VAL_SMALLER:
+ size = nextFontSize(fontSizes, oldSize, true);
+ break;
+ default:
+ return;
+ }
+
+ } else {
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
+ if ( !tdehtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
+ view && view->part())
+ size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) *
+ view->part()->zoomFactor() ) / 100;
+ else
+ size = int( primitiveValue->computeLengthFloat(parentStyle, paintDeviceMetrics) );
+ }
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ size = int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)
+ * parentStyle->font().pixelSize()) / 100;
+ else
+ return;
+ }
+
+ if (size < 0) return;
+
+ // we never want to get smaller than the minimum font size to keep fonts readable
+ // do not however maximize zero as that is commonly used for fancy layouting purposes
+ if (size && size < minFontSize) size = minFontSize;
+
+ //kdDebug( 6080 ) << "computed raw font size: " << size << endl;
+
+ fontDef.size = size;
+ fontDirty |= style->setFontDef( fontDef );
+ return;
+ }
+
+ case CSS_PROP_Z_INDEX:
+ {
+ HANDLE_INHERIT(zIndex, ZIndex)
+ else if (isInitial) {
+ style->setHasAutoZIndex();
+ return;
+ }
+
+ if (!primitiveValue)
+ return;
+
+ if (primitiveValue->getIdent() == CSS_VAL_AUTO) {
+ style->setHasAutoZIndex();
+ return;
+ }
+
+ if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
+ return; // Error case.
+
+ style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
+ return;
+ }
+
+ case CSS_PROP_WIDOWS:
+ {
+ HANDLE_INHERIT_AND_INITIAL(widows, Widows)
+ if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
+ return;
+ style->setWidows((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+
+ case CSS_PROP_ORPHANS:
+ {
+ HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
+ if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
+ return;
+ style->setOrphans((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+
+// length, percent, number
+ case CSS_PROP_LINE_HEIGHT:
+ {
+ HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
+ if(!primitiveValue) return;
+ Length lineHeight;
+ int type = primitiveValue->primitiveType();
+ if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
+ lineHeight = Length( -100, Percent );
+ else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) {
+ // Scale for the font zoom factor only for types other than "em" and "ex", since those are
+ // already based on the font size.
+ if ( !tdehtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS &&
+ view && view->part())
+ lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics) *
+ view->part()->zoomFactor()/100, Fixed );
+ else
+ lineHeight = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed );
+ } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed );
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ lineHeight = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent);
+ else
+ return;
+ style->setLineHeight(lineHeight);
+ return;
+ }
+
+// string
+ case CSS_PROP_TEXT_ALIGN:
+ {
+ HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent())
+ style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) );
+ return;
+ }
+
+// rect
+ case CSS_PROP_CLIP:
+ {
+ Length top = Length();
+ Length right = Length();
+ Length bottom = Length();
+ Length left = Length();
+
+ bool hasClip = false;
+
+ if (isInherit && parentStyle->hasClip()) {
+ hasClip = true;
+ top = parentStyle->clipTop();
+ right = parentStyle->clipRight();
+ bottom = parentStyle->clipBottom();
+ left = parentStyle->clipLeft();
+ } else if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
+ RectImpl *rect = primitiveValue->getRectValue();
+ if (rect) {
+ hasClip = true;
+ top = convertToLength( rect->top(), style, paintDeviceMetrics );
+ right = convertToLength( rect->right(), style, paintDeviceMetrics );
+ bottom = convertToLength( rect->bottom(), style, paintDeviceMetrics );
+ left = convertToLength( rect->left(), style, paintDeviceMetrics );
+ }
+ }
+
+ style->setClip(top, right, bottom, left);
+ style->setHasClip(hasClip);
+
+ // rect, ident
+ break;
+ }
+
+// lists
+ case CSS_PROP_CONTENT:
+ // list of string, uri, counter, attr, i
+ {
+ // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
+ // note is a reminder that eventually "inherit" needs to be supported.
+
+ // not allowed on non-generated pseudo-elements:
+ if ( style->styleType()==RenderStyle::FIRST_LETTER ||
+ style->styleType()==RenderStyle::FIRST_LINE ||
+ style->styleType()==RenderStyle::SELECTION )
+ break;
+
+ if (isInitial) {
+ style->setContentNormal();
+ return;
+ }
+
+ if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
+ // normal | none
+ if (primitiveValue->getIdent() == CSS_VAL_NORMAL)
+ style->setContentNormal();
+ else
+ if (primitiveValue->getIdent() == CSS_VAL_NONE)
+ style->setContentNone();
+ else
+ assert(false);
+ return;
+ }
+
+ if(!value->isValueList()) return;
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ int len = list->length();
+
+ style->setContentNormal(); // clear the content
+
+ for(int i = 0; i < len; i++) {
+ CSSValueImpl *item = list->item(i);
+ if(!item->isPrimitiveValue()) continue;
+ CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
+ if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING)
+ {
+ style->addContent(val->getStringValue());
+ }
+ else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR)
+ {
+ // TODO: setup dynamic attribute dependencies
+ int attrID = element->getDocument()->getId(NodeImpl::AttributeId, val->getStringValue(), false, true);
+ if (attrID)
+ style->addContent(element->getAttribute(attrID).implementation());
+ else
+ kdDebug(6080) << "Attribute \"" << val->getStringValue() << "\" not found" << endl;
+ }
+ else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI)
+ {
+ CSSImageValueImpl *image = static_cast<CSSImageValueImpl *>(val);
+ style->addContent(image->image());
+ }
+ else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER)
+ {
+ style->addContent(val->getCounterValue());
+ }
+ else if (val->primitiveType()==CSSPrimitiveValue::CSS_IDENT)
+ {
+ EQuoteContent quote;
+ switch (val->getIdent()) {
+ case CSS_VAL_OPEN_QUOTE:
+ quote = OPEN_QUOTE;
+ break;
+ case CSS_VAL_NO_OPEN_QUOTE:
+ quote = NO_OPEN_QUOTE;
+ break;
+ case CSS_VAL_CLOSE_QUOTE:
+ quote = CLOSE_QUOTE;
+ break;
+ case CSS_VAL_NO_CLOSE_QUOTE:
+ quote = NO_CLOSE_QUOTE;
+ break;
+ default:
+ assert(false);
+ }
+ style->addContent(quote);
+ } else
+ kdDebug(6080) << "Unrecognized CSS content" << endl;
+
+ }
+ break;
+ }
+
+ case CSS_PROP_COUNTER_INCREMENT: {
+ if(!value->isValueList()) return;
+
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ style->setCounterIncrement(list);
+ break;
+ }
+ case CSS_PROP_COUNTER_RESET: {
+ if(!value->isValueList()) return;
+
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ style->setCounterReset(list);
+ break;
+ }
+ case CSS_PROP_FONT_FAMILY:
+ // list of strings and ids
+ {
+ if (isInherit) {
+ FontDef parentFontDef = parentStyle->htmlFont().fontDef;
+ FontDef fontDef = style->htmlFont().fontDef;
+ fontDef.family = parentFontDef.family;
+ if (style->setFontDef(fontDef))
+ fontDirty = true;
+ return;
+ }
+ else if (isInitial) {
+ FontDef fontDef = style->htmlFont().fontDef;
+ FontDef initialDef = FontDef();
+#ifdef APPLE_CHANGES
+ fontDef.family = initialDef.firstFamily();
+#else
+ fontDef.family = TQString::null;
+#endif
+ if (style->setFontDef(fontDef))
+ fontDirty = true;
+ return;
+ }
+ if(!value->isValueList()) return;
+ FontDef fontDef = style->htmlFont().fontDef;
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ int len = list->length();
+ for(int i = 0; i < len; i++) {
+ CSSValueImpl *item = list->item(i);
+ if(!item->isPrimitiveValue()) continue;
+ CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item);
+ TQString face;
+ if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING )
+ face = static_cast<FontFamilyValueImpl *>(val)->fontName();
+ else if ( val->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) {
+ switch( val->getIdent() ) {
+ case CSS_VAL_SERIF:
+ face = settings->serifFontName();
+ break;
+ case CSS_VAL_SANS_SERIF:
+ face = settings->sansSerifFontName();
+ break;
+ case CSS_VAL_CURSIVE:
+ face = settings->cursiveFontName();
+ break;
+ case CSS_VAL_FANTASY:
+ face = settings->fantasyFontName();
+ break;
+ case CSS_VAL_MONOSPACE:
+ face = settings->fixedFontName();
+ break;
+ default:
+ return;
+ }
+ } else {
+ return;
+ }
+ if ( !face.isEmpty() ) {
+ fontDef.family = face;
+ fontDirty |= style->setFontDef( fontDef );
+ return;
+ }
+ }
+ break;
+ }
+ case CSS_PROP_QUOTES:
+ HANDLE_INHERIT_AND_INITIAL(quotes, Quotes)
+ if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
+ // set a set of empty quotes
+ QuotesValueImpl* quotes = new QuotesValueImpl();
+ style->setQuotes(quotes);
+ } else {
+ QuotesValueImpl* quotes = static_cast<QuotesValueImpl *>(value);
+ style->setQuotes(quotes);
+ }
+ break;
+ case CSS_PROP_SIZE:
+ // ### look up
+ break;
+ case CSS_PROP_TEXT_DECORATION: {
+ // list of ident
+ HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
+ int t = RenderStyle::initialTextDecoration();
+ if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) {
+ // do nothing
+ } else {
+ if(!value->isValueList()) return;
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ int len = list->length();
+ for(int i = 0; i < len; i++)
+ {
+ CSSValueImpl *item = list->item(i);
+ if(!item->isPrimitiveValue()) continue;
+ primitiveValue = static_cast<CSSPrimitiveValueImpl *>(item);
+ switch(primitiveValue->getIdent())
+ {
+ case CSS_VAL_NONE:
+ t = TDNONE; break;
+ case CSS_VAL_UNDERLINE:
+ t |= UNDERLINE; break;
+ case CSS_VAL_OVERLINE:
+ t |= OVERLINE; break;
+ case CSS_VAL_LINE_THROUGH:
+ t |= LINE_THROUGH; break;
+ case CSS_VAL_BLINK:
+ t |= BLINK; break;
+ default:
+ return;
+ }
+ }
+ }
+ style->setTextDecoration(t);
+ break;
+ }
+ case CSS_PROP__KHTML_FLOW_MODE:
+ HANDLE_INHERIT_AND_INITIAL(flowAroundFloats, FlowAroundFloats)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent()) {
+ style->setFlowAroundFloats( primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS );
+ return;
+ }
+ break;
+ case CSS_PROP__KHTML_USER_INPUT: {
+ if(value->cssValueType() == CSSValue::CSS_INHERIT)
+ {
+ if(!parentNode) return;
+ style->setUserInput(parentStyle->userInput());
+// kdDebug() << "UI erm" << endl;
+ return;
+ }
+ if(!primitiveValue) return;
+ int id = primitiveValue->getIdent();
+ if (id == CSS_VAL_NONE)
+ style->setUserInput(UI_NONE);
+ else
+ style->setUserInput(EUserInput(id - CSS_VAL_ENABLED));
+// kdDebug(6080) << "userInput: " << style->userEdit() << endl;
+ return;
+ }
+
+// shorthand properties
+ case CSS_PROP_BACKGROUND:
+ if (isInitial) {
+ style->clearBackgroundLayers();
+ return;
+ }
+ else if (isInherit) {
+ if (parentStyle)
+ style->inheritBackgroundLayers(*parentStyle->backgroundLayers());
+ else
+ style->clearBackgroundLayers();
+ return;
+ }
+ break;
+ case CSS_PROP_BORDER:
+ case CSS_PROP_BORDER_STYLE:
+ case CSS_PROP_BORDER_WIDTH:
+ case CSS_PROP_BORDER_COLOR:
+ if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR)
+ {
+ if (isInherit) {
+ style->setBorderTopColor(parentStyle->borderTopColor());
+ style->setBorderBottomColor(parentStyle->borderBottomColor());
+ style->setBorderLeftColor(parentStyle->borderLeftColor());
+ style->setBorderRightColor(parentStyle->borderRightColor());
+ }
+ else if (isInitial) {
+ style->setBorderTopColor(TQColor()); // Reset to invalid color so currentColor is used instead.
+ style->setBorderBottomColor(TQColor());
+ style->setBorderLeftColor(TQColor());
+ style->setBorderRightColor(TQColor());
+ }
+ }
+ if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE)
+ {
+ if (isInherit) {
+ style->setBorderTopStyle(parentStyle->borderTopStyle());
+ style->setBorderBottomStyle(parentStyle->borderBottomStyle());
+ style->setBorderLeftStyle(parentStyle->borderLeftStyle());
+ style->setBorderRightStyle(parentStyle->borderRightStyle());
+ }
+ else if (isInitial) {
+ style->setBorderTopStyle(RenderStyle::initialBorderStyle());
+ style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
+ style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
+ style->setBorderRightStyle(RenderStyle::initialBorderStyle());
+ }
+ }
+ if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH)
+ {
+ if (isInherit) {
+ style->setBorderTopWidth(parentStyle->borderTopWidth());
+ style->setBorderBottomWidth(parentStyle->borderBottomWidth());
+ style->setBorderLeftWidth(parentStyle->borderLeftWidth());
+ style->setBorderRightWidth(parentStyle->borderRightWidth());
+ }
+ else if (isInitial) {
+ style->setBorderTopWidth(RenderStyle::initialBorderWidth());
+ style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
+ style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
+ style->setBorderRightWidth(RenderStyle::initialBorderWidth());
+ }
+ }
+ return;
+ case CSS_PROP_BORDER_TOP:
+ if ( isInherit ) {
+ style->setBorderTopColor(parentStyle->borderTopColor());
+ style->setBorderTopStyle(parentStyle->borderTopStyle());
+ style->setBorderTopWidth(parentStyle->borderTopWidth());
+ } else if (isInitial)
+ style->resetBorderTop();
+ return;
+ case CSS_PROP_BORDER_RIGHT:
+ if (isInherit) {
+ style->setBorderRightColor(parentStyle->borderRightColor());
+ style->setBorderRightStyle(parentStyle->borderRightStyle());
+ style->setBorderRightWidth(parentStyle->borderRightWidth());
+ }
+ else if (isInitial)
+ style->resetBorderRight();
+ return;
+ case CSS_PROP_BORDER_BOTTOM:
+ if (isInherit) {
+ style->setBorderBottomColor(parentStyle->borderBottomColor());
+ style->setBorderBottomStyle(parentStyle->borderBottomStyle());
+ style->setBorderBottomWidth(parentStyle->borderBottomWidth());
+ }
+ else if (isInitial)
+ style->resetBorderBottom();
+ return;
+ case CSS_PROP_BORDER_LEFT:
+ if (isInherit) {
+ style->setBorderLeftColor(parentStyle->borderLeftColor());
+ style->setBorderLeftStyle(parentStyle->borderLeftStyle());
+ style->setBorderLeftWidth(parentStyle->borderLeftWidth());
+ }
+ else if (isInitial)
+ style->resetBorderLeft();
+ return;
+ case CSS_PROP_MARGIN:
+ if (isInherit) {
+ style->setMarginTop(parentStyle->marginTop());
+ style->setMarginBottom(parentStyle->marginBottom());
+ style->setMarginLeft(parentStyle->marginLeft());
+ style->setMarginRight(parentStyle->marginRight());
+ }
+ else if (isInitial)
+ style->resetMargin();
+ return;
+ case CSS_PROP_PADDING:
+ if (isInherit) {
+ style->setPaddingTop(parentStyle->paddingTop());
+ style->setPaddingBottom(parentStyle->paddingBottom());
+ style->setPaddingLeft(parentStyle->paddingLeft());
+ style->setPaddingRight(parentStyle->paddingRight());
+ }
+ else if (isInitial)
+ style->resetPadding();
+ return;
+ case CSS_PROP_FONT:
+ if ( isInherit ) {
+ FontDef fontDef = parentStyle->htmlFont().fontDef;
+ style->setLineHeight( parentStyle->lineHeight() );
+ fontDirty |= style->setFontDef( fontDef );
+ } else if (isInitial) {
+ FontDef fontDef;
+ style->setLineHeight(RenderStyle::initialLineHeight());
+ if (style->setFontDef( fontDef ))
+ fontDirty = true;
+ } else if ( value->isFontValue() ) {
+ FontValueImpl *font = static_cast<FontValueImpl *>(value);
+ if ( !font->style || !font->variant || !font->weight ||
+ !font->size || !font->lineHeight || !font->family )
+ return;
+ applyRule( CSS_PROP_FONT_STYLE, font->style );
+ applyRule( CSS_PROP_FONT_VARIANT, font->variant );
+ applyRule( CSS_PROP_FONT_WEIGHT, font->weight );
+ applyRule( CSS_PROP_FONT_SIZE, font->size );
+
+ // Line-height can depend on font().pixelSize(), so we have to update the font
+ // before we evaluate line-height, e.g., font: 1em/1em. FIXME: Still not
+ // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px.
+ if (fontDirty)
+ CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
+
+ applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight );
+ applyRule( CSS_PROP_FONT_FAMILY, font->family );
+ }
+ return;
+
+ case CSS_PROP_LIST_STYLE:
+ if (isInherit) {
+ style->setListStyleType(parentStyle->listStyleType());
+ style->setListStyleImage(parentStyle->listStyleImage());
+ style->setListStylePosition(parentStyle->listStylePosition());
+ }
+ else if (isInitial) {
+ style->setListStyleType(RenderStyle::initialListStyleType());
+ style->setListStyleImage(RenderStyle::initialListStyleImage());
+ style->setListStylePosition(RenderStyle::initialListStylePosition());
+ }
+ break;
+ case CSS_PROP_OUTLINE:
+ if (isInherit) {
+ style->setOutlineWidth(parentStyle->outlineWidth());
+ style->setOutlineColor(parentStyle->outlineColor());
+ style->setOutlineStyle(parentStyle->outlineStyle());
+ }
+ else if (isInitial)
+ style->resetOutline();
+ break;
+ /* CSS3 properties */
+ case CSS_PROP_BOX_SIZING:
+ HANDLE_INHERIT(boxSizing, BoxSizing)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX)
+ style->setBoxSizing(CONTENT_BOX);
+ else
+ if (primitiveValue->getIdent() == CSS_VAL_BORDER_BOX)
+ style->setBoxSizing(BORDER_BOX);
+ break;
+ case CSS_PROP_OUTLINE_OFFSET: {
+ HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
+
+ int offset = primitiveValue->computeLength(style, paintDeviceMetrics);
+ if (offset < 0) return;
+
+ style->setOutlineOffset(offset);
+ break;
+ }
+ case CSS_PROP_TEXT_SHADOW: {
+ if (isInherit) {
+ style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0);
+ return;
+ }
+ else if (isInitial) {
+ style->setTextShadow(0);
+ return;
+ }
+
+ if (primitiveValue) { // none
+ style->setTextShadow(0);
+ return;
+ }
+
+ if (!value->isValueList()) return;
+ CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+ int len = list->length();
+ for (int i = 0; i < len; i++) {
+ ShadowValueImpl *item = static_cast<ShadowValueImpl*>(list->item(i));
+
+ int x = item->x->computeLength(style, paintDeviceMetrics);
+ int y = item->y->computeLength(style, paintDeviceMetrics);
+ int blur = item->blur ? item->blur->computeLength(style, paintDeviceMetrics) : 0;
+ TQColor col = tdehtml::transparentColor;
+ if (item->color) {
+ int ident = item->color->getIdent();
+ if (ident)
+ col = colorForCSSValue( ident );
+ else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
+ col.setRgb(item->color->getRGBColorValue());
+ }
+ ShadowData* shadowData = new ShadowData(x, y, blur, col);
+ style->setTextShadow(shadowData, i != 0);
+ }
+
+ break;
+ }
+ case CSS_PROP_OPACITY:
+ HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
+ if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
+ return; // Error case.
+
+ // Clamp opacity to the range 0-1
+ style->setOpacity(kMin(1.0f, kMax(0.0f, (float)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))));
+ break;
+ case CSS_PROP__KHTML_MARQUEE:
+ if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return;
+ style->setMarqueeDirection(parentStyle->marqueeDirection());
+ style->setMarqueeIncrement(parentStyle->marqueeIncrement());
+ style->setMarqueeSpeed(parentStyle->marqueeSpeed());
+ style->setMarqueeLoopCount(parentStyle->marqueeLoopCount());
+ style->setMarqueeBehavior(parentStyle->marqueeBehavior());
+ break;
+ case CSS_PROP__KHTML_MARQUEE_REPETITION: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent() == CSS_VAL_INFINITE)
+ style->setMarqueeLoopCount(-1); // -1 means repeat forever.
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
+ style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
+ break;
+ }
+ case CSS_PROP__KHTML_MARQUEE_SPEED: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent()) {
+ switch (primitiveValue->getIdent())
+ {
+ case CSS_VAL_SLOW:
+ style->setMarqueeSpeed(500); // 500 msec.
+ break;
+ case CSS_VAL_NORMAL:
+ style->setMarqueeSpeed(85); // 85msec. The WinIE default.
+ break;
+ case CSS_VAL_FAST:
+ style->setMarqueeSpeed(10); // 10msec. Super fast.
+ break;
+ }
+ }
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
+ style->setMarqueeSpeed(int(1000*primitiveValue->floatValue(CSSPrimitiveValue::CSS_S)));
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
+ style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS)));
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
+ style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)));
+ break;
+ }
+ case CSS_PROP__KHTML_MARQUEE_INCREMENT: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
+ if (!primitiveValue) return;
+ if (primitiveValue->getIdent()) {
+ switch (primitiveValue->getIdent())
+ {
+ case CSS_VAL_SMALL:
+ style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
+ break;
+ case CSS_VAL_NORMAL:
+ style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
+ break;
+ case CSS_VAL_LARGE:
+ style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
+ break;
+ }
+ }
+ else {
+ bool ok = true;
+ Length l = convertToLength(primitiveValue, style, paintDeviceMetrics, &ok);
+ if (ok)
+ style->setMarqueeIncrement(l);
+ }
+ break;
+ }
+ case CSS_PROP__KHTML_MARQUEE_STYLE: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeBehavior, MarqueeBehavior)
+ if (!primitiveValue || !primitiveValue->getIdent()) return;
+ switch (primitiveValue->getIdent())
+ {
+ case CSS_VAL_NONE:
+ style->setMarqueeBehavior(MNONE);
+ break;
+ case CSS_VAL_SCROLL:
+ style->setMarqueeBehavior(MSCROLL);
+ break;
+ case CSS_VAL_SLIDE:
+ style->setMarqueeBehavior(MSLIDE);
+ break;
+ case CSS_VAL_ALTERNATE:
+ style->setMarqueeBehavior(MALTERNATE);
+ break;
+ case CSS_VAL_UNFURL:
+ style->setMarqueeBehavior(MUNFURL);
+ break;
+ }
+ break;
+ }
+ case CSS_PROP__KHTML_MARQUEE_DIRECTION: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
+ if (!primitiveValue || !primitiveValue->getIdent()) return;
+ switch (primitiveValue->getIdent())
+ {
+ case CSS_VAL_FORWARDS:
+ style->setMarqueeDirection(MFORWARD);
+ break;
+ case CSS_VAL_BACKWARDS:
+ style->setMarqueeDirection(MBACKWARD);
+ break;
+ case CSS_VAL_AUTO:
+ style->setMarqueeDirection(MAUTO);
+ break;
+ case CSS_VAL_AHEAD:
+ case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP.
+ style->setMarqueeDirection(MUP);
+ break;
+ case CSS_VAL_REVERSE:
+ case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text.
+ style->setMarqueeDirection(MDOWN);
+ break;
+ case CSS_VAL_LEFT:
+ style->setMarqueeDirection(MLEFT);
+ break;
+ case CSS_VAL_RIGHT:
+ style->setMarqueeDirection(MRIGHT);
+ break;
+ }
+ break;
+ case CSS_PROP_TEXT_OVERFLOW: {
+ // This property is supported by WinIE, and so we leave off the "-tdehtml-" in order to
+ // work with WinIE-specific pages that use the property.
+ HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow)
+ if (!primitiveValue || !primitiveValue->getIdent())
+ return;
+ style->setTextOverflow(primitiveValue->getIdent() == CSS_VAL_ELLIPSIS);
+ break;
+ }
+ }
+ case CSS_PROP_WORD_WRAP: {
+ HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(wordWrap, WordWrap)
+ if (!primitiveValue)
+ return;
+ style->setWordWrap(primitiveValue->getIdent() == CSS_VAL_NORMAL ? WWNORMAL : WWBREAKWORD);
+ break;
+ }
+ default:
+ return;
+ }
+}
+
+void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_FIXED:
+ layer->setBackgroundAttachment(false);
+ break;
+ case CSS_VAL_SCROLL:
+ layer->setBackgroundAttachment(true);
+ break;
+ default:
+ return;
+ }
+}
+
+void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundClip(RenderStyle::initialBackgroundClip());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_BORDER:
+ layer->setBackgroundClip(BGBORDER);
+ break;
+ case CSS_VAL_PADDING:
+ layer->setBackgroundClip(BGPADDING);
+ break;
+ default: // CSS_VAL_CONTENT
+ layer->setBackgroundClip(BGCONTENT);
+ break;
+ }
+}
+
+void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSS_VAL_BORDER:
+ layer->setBackgroundOrigin(BGBORDER);
+ break;
+ case CSS_VAL_PADDING:
+ layer->setBackgroundOrigin(BGPADDING);
+ break;
+ default: // CSS_VAL_CONTENT
+ layer->setBackgroundOrigin(BGCONTENT);
+ break;
+ }
+}
+
+void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundImage(RenderStyle::initialBackgroundImage());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ layer->setBackgroundImage(static_cast<CSSImageValueImpl *>(primitiveValue)->image());
+}
+
+void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ switch(primitiveValue->getIdent()) {
+ case CSS_VAL_REPEAT:
+ layer->setBackgroundRepeat(REPEAT);
+ break;
+ case CSS_VAL_REPEAT_X:
+ layer->setBackgroundRepeat(REPEAT_X);
+ break;
+ case CSS_VAL_REPEAT_Y:
+ layer->setBackgroundRepeat(REPEAT_Y);
+ break;
+ case CSS_VAL_NO_REPEAT:
+ layer->setBackgroundRepeat(NO_REPEAT);
+ break;
+ default:
+ return;
+ }
+}
+
+
+void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValueImpl* value)
+{
+ LengthSize b = RenderStyle::initialBackgroundSize();
+
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundSize(b);
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ PairImpl* pair = primitiveValue->getPairValue();
+ if (!pair)
+ return;
+
+ CSSPrimitiveValueImpl* first = static_cast<CSSPrimitiveValueImpl*>(pair->first());
+ CSSPrimitiveValueImpl* second = static_cast<CSSPrimitiveValueImpl*>(pair->second());
+
+ if (!first || !second)
+ return;
+
+ Length firstLength, secondLength;
+ int firstType = first->primitiveType();
+ int secondType = second->primitiveType();
+
+ if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
+ firstLength = Length(Variable);
+ else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG)
+ firstLength = Length(first->computeLength(style, paintDeviceMetrics), Fixed);
+ else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
+ firstLength = Length((int)first->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else
+ return;
+
+ if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
+ secondLength = Length(Variable);
+ else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG)
+ secondLength = Length(second->computeLength(style, paintDeviceMetrics), Fixed);
+ else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
+ secondLength = Length((int)second->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else
+ return;
+
+ b.width = firstLength;
+ b.height = secondLength;
+ layer->setBackgroundSize(b);
+}
+
+void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ Length l;
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else
+ return;
+ layer->setBackgroundXPosition(l);
+}
+
+void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value)
+{
+ if (value->cssValueType() == CSSValue::CSS_INITIAL) {
+ layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition());
+ return;
+ }
+
+ if (!value->isPrimitiveValue()) return;
+ CSSPrimitiveValueImpl* primitiveValue = static_cast<CSSPrimitiveValueImpl*>(value);
+ Length l;
+ int type = primitiveValue->primitiveType();
+ if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG)
+ l = Length(primitiveValue->computeLength(style, paintDeviceMetrics), Fixed);
+ else if(type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent);
+ else
+ return;
+ layer->setBackgroundYPosition(l);
+}
+
+#ifdef APPLE_CHANGES
+void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle)
+{
+ const FontDef& childFont = aStyle->htmlFont().fontDef;
+
+ if (childFont.sizeSpecified || !aParentStyle)
+ return;
+
+ const FontDef& parentFont = aParentStyle->htmlFont().fontDef;
+
+ if (childFont.genericFamily == parentFont.genericFamily)
+ return;
+
+ // For now, lump all families but monospace together.
+ if (childFont.genericFamily != FontDef::eMonospace &&
+ parentFont.genericFamily != FontDef::eMonospace)
+ return;
+
+ // We know the parent is monospace or the child is monospace, and that font
+ // size was unspecified. We want to alter our font size to use the correct
+ // "medium" font for our family.
+ float size = 0;
+ int minFontSize = settings->minFontSize();
+ size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3];
+ int isize = (int)size;
+ if (isize < minFontSize)
+ isize = minFontSize;
+
+ FontDef newFontDef(childFont);
+ newFontDef.size = isize;
+ aStyle->setFontDef(newFontDef);
+}
+#endif
+
+} // namespace tdehtml
diff --git a/tdehtml/css/cssstyleselector.h b/tdehtml/css/cssstyleselector.h
new file mode 100644
index 000000000..ad6903de7
--- /dev/null
+++ b/tdehtml/css/cssstyleselector.h
@@ -0,0 +1,333 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 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 _CSS_cssstyleselector_h_
+#define _CSS_cssstyleselector_h_
+
+#include <tqptrlist.h>
+#include <tqvaluevector.h>
+
+#include "rendering/render_style.h"
+#include "dom/dom_string.h"
+#include "xml/dom_restyler.h"
+
+class KHTMLSettings;
+class KHTMLView;
+class KHTMLPart;
+class KHTMLFactory;
+class KURL;
+
+namespace DOM {
+ class DocumentImpl;
+ class NodeImpl;
+ class ElementImpl;
+ class StyleSheetImpl;
+ class CSSStyleRuleImpl;
+ class CSSStyleSheetImpl;
+ class CSSSelector;
+ class CSSStyleDeclarationImpl;
+ class CSSProperty;
+ class StyleSheetListImpl;
+ class CSSValueImpl;
+}
+
+namespace tdehtml
+{
+ class CSSStyleSelectorList;
+ class CSSOrderedRule;
+ class CSSOrderedProperty;
+ class CSSOrderedPropertyList;
+ class RenderStyle;
+
+ /*
+ * to remember the source where a rule came from. Differentiates between
+ * important and not important rules. This is ordered in the order they have to be applied
+ * to the RenderStyle.
+ */
+ enum Source {
+ Default = 0,
+ NonCSSHint = 1,
+ User = 2,
+ Author = 3,
+ Inline = 4,
+ AuthorImportant = 5,
+ InlineImportant = 6,
+ UserImportant =7
+ };
+
+ /**
+ * this class selects a RenderStyle for a given Element based on the
+ * collection of stylesheets it contains. This is just a virtual base class
+ * for specific implementations of the Selector. At the moment only CSSStyleSelector
+ * exists, but someone may wish to implement XSL...
+ */
+ class StyleSelector
+ {
+ public:
+ StyleSelector() {}
+
+ /* as nobody has implemented a second style selector up to now comment out
+ the virtual methods until then, so the class has no vptr.
+ */
+// virtual ~StyleSelector() {}
+// virtual RenderStyle *styleForElement(DOM::ElementImpl *e) = 0;
+
+ enum State {
+ None = 0x00,
+ Hover = 0x01,
+ Focus = 0x02,
+ Active = 0x04
+ };
+ };
+
+
+ /**
+ * the StyleSelector implementation for CSS.
+ */
+ class CSSStyleSelector : public StyleSelector
+ {
+ public:
+ /**
+ * creates a new StyleSelector for a Document.
+ * goes through all StyleSheets defined in the document and
+ * creates a list of rules it needs to apply to objects
+ *
+ * Also takes into account special cases for HTML documents,
+ * including the defaultStyle (which is html only)
+ */
+ CSSStyleSelector( DOM::DocumentImpl* doc, TQString userStyleSheet, DOM::StyleSheetListImpl *styleSheets, const KURL &url,
+ bool _strictParsing );
+ /**
+ * same as above but for a single stylesheet.
+ */
+ CSSStyleSelector( DOM::CSSStyleSheetImpl *sheet );
+
+ ~CSSStyleSelector();
+
+ void addSheet( DOM::CSSStyleSheetImpl *sheet );
+ KDE_EXPORT static void clear();
+ static void reparseConfiguration();
+
+ static void loadDefaultStyle(const KHTMLSettings *s, DOM::DocumentImpl *doc);
+
+ RenderStyle *styleForElement(DOM::ElementImpl *e);
+
+ TQValueVector<int> fontSizes() const { return m_fontSizes; }
+ TQValueVector<int> fixedFontSizes() const { return m_fixedFontSizes; }
+
+ bool strictParsing;
+ struct Encodedurl {
+ TQString host; //also contains protocol
+ TQString path;
+ TQString file;
+ } encodedurl;
+
+ void computeFontSizes(TQPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor);
+ void computeFontSizesFor(TQPaintDeviceMetrics* paintDeviceMetrics, int zoomFactor, TQValueVector<int>& fontSizes, bool isFixed);
+
+ static void precomputeAttributeDependencies(DOM::DocumentImpl* doc, DOM::CSSSelector* sel);
+ protected:
+ /* checks if the complete selector (which can be build up from a few CSSSelector's
+ with given relationships matches the given Element */
+ void checkSelector(int selector, DOM::ElementImpl *e);
+ /* checks if the selector matches the given Element */
+ bool checkSimpleSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false);
+
+ enum SelectorMatch {SelectorMatches = 0, SelectorFailsLocal, SelectorFails};
+ SelectorMatch checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false);
+
+ void addDependency(StructuralDependencyType dependencyType, DOM::ElementImpl* dependency);
+#ifdef APPLE_CHANGES
+ /* This function fixes up the default font size if it detects that the
+ current generic font family has changed. -dwh */
+ void checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle);
+#endif
+
+ /* builds up the selectors and properties lists from the CSSStyleSelectorList's */
+ void buildLists();
+ void clearLists();
+
+ void adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e);
+
+ unsigned int addInlineDeclarations(DOM::ElementImpl* e, DOM::CSSStyleDeclarationImpl *decl,
+ unsigned int numProps);
+
+ static DOM::CSSStyleSheetImpl *s_defaultSheet;
+ static DOM::CSSStyleSheetImpl *s_quirksSheet;
+ static CSSStyleSelectorList *s_defaultStyle;
+ static CSSStyleSelectorList *s_defaultQuirksStyle;
+ static CSSStyleSelectorList *s_defaultPrintStyle;
+ static RenderStyle* styleNotYetAvailable;
+
+ CSSStyleSelectorList *defaultStyle;
+ CSSStyleSelectorList *defaultQuirksStyle;
+ CSSStyleSelectorList *defaultPrintStyle;
+
+ CSSStyleSelectorList *authorStyle;
+ CSSStyleSelectorList *userStyle;
+ DOM::CSSStyleSheetImpl *userSheet;
+
+public:
+
+ private:
+ void init(const KHTMLSettings* settings, DOM::DocumentImpl* doc);
+
+ void mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundClip(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundOrigin(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundSize(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+ void mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value);
+
+ public: // we need to make the enum public for SelectorCache
+ enum SelectorState {
+ Unknown = 0,
+ Applies,
+ AppliesPseudo,
+ Invalid
+ };
+
+ enum SelectorMedia {
+ MediaAural = 1,
+ MediaBraille,
+ MediaEmboss,
+ MediaHandheld,
+ MediaPrint,
+ MediaProjection,
+ MediaScreen,
+ MediaTTY,
+ MediaTV
+ };
+ protected:
+
+ struct SelectorCache {
+ SelectorState state;
+ unsigned int props_size;
+ int *props;
+ };
+
+ unsigned int selectors_size;
+ DOM::CSSSelector **selectors;
+ SelectorCache *selectorCache;
+ unsigned int properties_size;
+ CSSOrderedProperty **properties;
+ TQMemArray<CSSOrderedProperty> inlineProps;
+ TQString m_medium;
+ CSSOrderedProperty **propsToApply;
+ CSSOrderedProperty **pseudoProps;
+ unsigned int propsToApplySize;
+ unsigned int pseudoPropsSize;
+
+
+ RenderStyle::PseudoId dynamicPseudo;
+
+ RenderStyle *style;
+ RenderStyle *parentStyle;
+ DOM::ElementImpl *element;
+ DOM::NodeImpl *parentNode;
+ KHTMLView *view;
+ KHTMLPart *part;
+ const KHTMLSettings *settings;
+ TQPaintDeviceMetrics *paintDeviceMetrics;
+ TQValueVector<int> m_fontSizes;
+ TQValueVector<int> m_fixedFontSizes;
+
+ bool fontDirty;
+
+ void applyRule(int id, DOM::CSSValueImpl *value);
+ };
+
+ /*
+ * List of properties that get applied to the Element. We need to collect them first
+ * and then apply them one by one, because we have to change the apply order.
+ * Some properties depend on other one already being applied (for example all properties specifying
+ * some length need to have already the correct font size. Same applies to color
+ *
+ * While sorting them, we have to take care not to mix up the original order.
+ */
+ class CSSOrderedProperty
+ {
+ public:
+ CSSOrderedProperty(DOM::CSSProperty *_prop, uint _selector,
+ bool first, Source source, unsigned int specificity,
+ unsigned int _position )
+ : prop ( _prop ), pseudoId( RenderStyle::NOPSEUDO ), selector( _selector ),
+ position( _position )
+ {
+ priority = (!first << 30) | (source << 24) | specificity;
+ }
+
+ bool operator < ( const CSSOrderedProperty &other ) const {
+ if (priority < other.priority) return true;
+ if (priority > other.priority) return false;
+ if (position < other.position) return true;
+ return false;
+ }
+
+ DOM::CSSProperty *prop;
+ RenderStyle::PseudoId pseudoId;
+ unsigned int selector;
+ unsigned int position;
+
+ TQ_UINT32 priority;
+ };
+
+ /*
+ * This is the list we will collect all properties we need to apply in.
+ * It will get sorted once before applying.
+ */
+ class CSSOrderedPropertyList : public TQPtrList<CSSOrderedProperty>
+ {
+ public:
+ virtual int compareItems(TQPtrCollection::Item i1, TQPtrCollection::Item i2);
+ void append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
+ Source regular, Source important );
+ };
+
+ class CSSOrderedRule
+ {
+ public:
+ CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index);
+ ~CSSOrderedRule();
+
+ DOM::CSSSelector *selector;
+ DOM::CSSStyleRuleImpl *rule;
+ int index;
+ };
+
+ class CSSStyleSelectorList : public TQPtrList<CSSOrderedRule>
+ {
+ public:
+ CSSStyleSelectorList();
+ virtual ~CSSStyleSelectorList();
+
+ void append( DOM::CSSStyleSheetImpl *sheet,
+ const DOM::DOMString &medium = "screen" );
+
+ void collect( TQPtrList<DOM::CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
+ Source regular, Source important );
+ };
+
+}
+#endif
diff --git a/tdehtml/css/cssvalues.c b/tdehtml/css/cssvalues.c
new file mode 100644
index 000000000..28ceede3d
--- /dev/null
+++ b/tdehtml/css/cssvalues.c
@@ -0,0 +1,1344 @@
+/* ANSI-C code produced by gperf version 3.0.2 */
+/* Command-line: gperf -L ANSI-C -E -c -C -n -o -t -k '*' -NfindValue -Hhash_val -Wwordlist_value -D cssvalues.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 "cssvalues.gperf"
+
+/* This file is automatically generated from cssvalues.in by makevalues, do not edit */
+/* Copyright 1999 W. Bastian */
+#include "cssvalues.h"
+#line 6 "cssvalues.gperf"
+struct css_value {
+ const char *name;
+ int id;
+};
+
+static const css_value* findValue (register const char *str, register unsigned int len);
+/* maximum key range = 2876, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_val (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 420, 23, 2876, 0, 0,
+ 105, 100, 40, 35, 20, 15, 10, 5, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 175, 60, 0,
+ 20, 45, 18, 380, 270, 5, 3, 65, 0, 35,
+ 0, 5, 265, 465, 100, 20, 5, 195, 18, 13,
+ 3, 133, 10, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876, 2876,
+ 2876, 2876, 2876, 2876, 2876, 2876, 2876
+ };
+ register int hval = 0;
+
+ switch (len)
+ {
+ default:
+ 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]+1];
+ /*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 css_value *
+findValue (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 275,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 28,
+ MIN_HASH_VALUE = 0,
+ MAX_HASH_VALUE = 2875
+ };
+
+ static const struct css_value wordlist_value[] =
+ {
+#line 40 "cssvalues.gperf"
+ {"100", CSS_VAL_100},
+#line 48 "cssvalues.gperf"
+ {"900", CSS_VAL_900},
+#line 47 "cssvalues.gperf"
+ {"800", CSS_VAL_800},
+#line 46 "cssvalues.gperf"
+ {"700", CSS_VAL_700},
+#line 45 "cssvalues.gperf"
+ {"600", CSS_VAL_600},
+#line 216 "cssvalues.gperf"
+ {"ltr", CSS_VAL_LTR},
+#line 277 "cssvalues.gperf"
+ {"down", CSS_VAL_DOWN},
+#line 146 "cssvalues.gperf"
+ {"disc", CSS_VAL_DISC},
+#line 44 "cssvalues.gperf"
+ {"500", CSS_VAL_500},
+#line 43 "cssvalues.gperf"
+ {"400", CSS_VAL_400},
+#line 252 "cssvalues.gperf"
+ {"loud", CSS_VAL_LOUD},
+#line 259 "cssvalues.gperf"
+ {"scroll", CSS_VAL_SCROLL},
+#line 83 "cssvalues.gperf"
+ {"lime", CSS_VAL_LIME},
+#line 17 "cssvalues.gperf"
+ {"none", CSS_VAL_NONE},
+#line 19 "cssvalues.gperf"
+ {"inset", CSS_VAL_INSET},
+#line 118 "cssvalues.gperf"
+ {"window", CSS_VAL_WINDOW},
+#line 287 "cssvalues.gperf"
+ {"content", CSS_VAL_CONTENT},
+#line 147 "cssvalues.gperf"
+ {"circle", CSS_VAL_CIRCLE},
+#line 86 "cssvalues.gperf"
+ {"olive", CSS_VAL_OLIVE},
+#line 33 "cssvalues.gperf"
+ {"italic", CSS_VAL_ITALIC},
+#line 145 "cssvalues.gperf"
+ {"inside", CSS_VAL_INSIDE},
+#line 25 "cssvalues.gperf"
+ {"solid", CSS_VAL_SOLID},
+#line 281 "cssvalues.gperf"
+ {"slide", CSS_VAL_SLIDE},
+#line 183 "cssvalues.gperf"
+ {"inline", CSS_VAL_INLINE},
+#line 262 "cssvalues.gperf"
+ {"static", CSS_VAL_STATIC},
+#line 204 "cssvalues.gperf"
+ {"move", CSS_VAL_MOVE},
+#line 42 "cssvalues.gperf"
+ {"300", CSS_VAL_300},
+#line 250 "cssvalues.gperf"
+ {"level", CSS_VAL_LEVEL},
+#line 41 "cssvalues.gperf"
+ {"200", CSS_VAL_200},
+#line 69 "cssvalues.gperf"
+ {"serif", CSS_VAL_SERIF},
+#line 91 "cssvalues.gperf"
+ {"teal", CSS_VAL_TEAL},
+#line 51 "cssvalues.gperf"
+ {"small", CSS_VAL_SMALL},
+#line 120 "cssvalues.gperf"
+ {"windowtext", CSS_VAL_WINDOWTEXT},
+#line 37 "cssvalues.gperf"
+ {"bold", CSS_VAL_BOLD},
+#line 77 "cssvalues.gperf"
+ {"blue", CSS_VAL_BLUE},
+#line 239 "cssvalues.gperf"
+ {"blink", CSS_VAL_BLINK},
+#line 221 "cssvalues.gperf"
+ {"visible", CSS_VAL_VISIBLE},
+#line 217 "cssvalues.gperf"
+ {"rtl", CSS_VAL_RTL},
+#line 243 "cssvalues.gperf"
+ {"embed", CSS_VAL_EMBED},
+#line 26 "cssvalues.gperf"
+ {"double", CSS_VAL_DOUBLE},
+#line 128 "cssvalues.gperf"
+ {"middle", CSS_VAL_MIDDLE},
+#line 253 "cssvalues.gperf"
+ {"lower", CSS_VAL_LOWER},
+#line 237 "cssvalues.gperf"
+ {"below", CSS_VAL_BELOW},
+#line 63 "cssvalues.gperf"
+ {"condensed", CSS_VAL_CONDENSED},
+#line 78 "cssvalues.gperf"
+ {"crimson", CSS_VAL_CRIMSON},
+#line 14 "cssvalues.gperf"
+ {"inherit", CSS_VAL_INHERIT},
+#line 248 "cssvalues.gperf"
+ {"invert", CSS_VAL_INVERT},
+#line 255 "cssvalues.gperf"
+ {"mix", CSS_VAL_MIX},
+#line 76 "cssvalues.gperf"
+ {"black", CSS_VAL_BLACK},
+#line 213 "cssvalues.gperf"
+ {"text", CSS_VAL_TEXT},
+#line 89 "cssvalues.gperf"
+ {"red", CSS_VAL_RED},
+#line 256 "cssvalues.gperf"
+ {"overline", CSS_VAL_OVERLINE},
+#line 15 "cssvalues.gperf"
+ {"initial", CSS_VAL_INITIAL},
+#line 214 "cssvalues.gperf"
+ {"wait", CSS_VAL_WAIT},
+#line 149 "cssvalues.gperf"
+ {"box", CSS_VAL_BOX},
+#line 139 "cssvalues.gperf"
+ {"center", CSS_VAL_CENTER},
+#line 279 "cssvalues.gperf"
+ {"fast", CSS_VAL_FAST},
+#line 59 "cssvalues.gperf"
+ {"wider", CSS_VAL_WIDER},
+#line 129 "cssvalues.gperf"
+ {"sub", CSS_VAL_SUB},
+#line 244 "cssvalues.gperf"
+ {"fixed", CSS_VAL_FIXED},
+#line 90 "cssvalues.gperf"
+ {"silver", CSS_VAL_SILVER},
+#line 189 "cssvalues.gperf"
+ {"table", CSS_VAL_TABLE},
+#line 270 "cssvalues.gperf"
+ {"enabled", CSS_VAL_ENABLED},
+#line 93 "cssvalues.gperf"
+ {"yellow", CSS_VAL_YELLOW},
+#line 36 "cssvalues.gperf"
+ {"normal", CSS_VAL_NORMAL},
+#line 84 "cssvalues.gperf"
+ {"maroon", CSS_VAL_MAROON},
+#line 286 "cssvalues.gperf"
+ {"border", CSS_VAL_BORDER},
+#line 49 "cssvalues.gperf"
+ {"xx-small", CSS_VAL_XX_SMALL},
+#line 57 "cssvalues.gperf"
+ {"smaller", CSS_VAL_SMALLER},
+#line 207 "cssvalues.gperf"
+ {"nw-resize", CSS_VAL_NW_RESIZE},
+#line 38 "cssvalues.gperf"
+ {"bolder", CSS_VAL_BOLDER},
+#line 284 "cssvalues.gperf"
+ {"clip", CSS_VAL_CLIP},
+#line 28 "cssvalues.gperf"
+ {"icon", CSS_VAL_ICON},
+#line 264 "cssvalues.gperf"
+ {"thin", CSS_VAL_THIN},
+#line 29 "cssvalues.gperf"
+ {"menu", CSS_VAL_MENU},
+#line 210 "cssvalues.gperf"
+ {"sw-resize", CSS_VAL_SW_RESIZE},
+#line 23 "cssvalues.gperf"
+ {"dotted", CSS_VAL_DOTTED},
+#line 206 "cssvalues.gperf"
+ {"ne-resize", CSS_VAL_NE_RESIZE},
+#line 278 "cssvalues.gperf"
+ {"slow", CSS_VAL_SLOW},
+#line 151 "cssvalues.gperf"
+ {"decimal", CSS_VAL_DECIMAL},
+#line 71 "cssvalues.gperf"
+ {"cursive", CSS_VAL_CURSIVE},
+#line 134 "cssvalues.gperf"
+ {"bottom", CSS_VAL_BOTTOM},
+#line 209 "cssvalues.gperf"
+ {"se-resize", CSS_VAL_SE_RESIZE},
+#line 85 "cssvalues.gperf"
+ {"navy", CSS_VAL_NAVY},
+#line 271 "cssvalues.gperf"
+ {"disabled", CSS_VAL_DISABLED},
+#line 127 "cssvalues.gperf"
+ {"baseline", CSS_VAL_BASELINE},
+#line 92 "cssvalues.gperf"
+ {"white", CSS_VAL_WHITE},
+#line 111 "cssvalues.gperf"
+ {"menutext", CSS_VAL_MENUTEXT},
+#line 263 "cssvalues.gperf"
+ {"thick", CSS_VAL_THICK},
+#line 52 "cssvalues.gperf"
+ {"medium", CSS_VAL_MEDIUM},
+#line 140 "cssvalues.gperf"
+ {"justify", CSS_VAL_JUSTIFY},
+#line 246 "cssvalues.gperf"
+ {"hide", CSS_VAL_HIDE},
+#line 275 "cssvalues.gperf"
+ {"reverse", CSS_VAL_REVERSE},
+#line 272 "cssvalues.gperf"
+ {"forwards", CSS_VAL_FORWARDS},
+#line 112 "cssvalues.gperf"
+ {"scrollbar", CSS_VAL_SCROLLBAR},
+#line 228 "cssvalues.gperf"
+ {"pre", CSS_VAL_PRE},
+#line 18 "cssvalues.gperf"
+ {"hidden", CSS_VAL_HIDDEN},
+#line 184 "cssvalues.gperf"
+ {"block", CSS_VAL_BLOCK},
+#line 220 "cssvalues.gperf"
+ {"lowercase", CSS_VAL_LOWERCASE},
+#line 285 "cssvalues.gperf"
+ {"ellipsis", CSS_VAL_ELLIPSIS},
+#line 242 "cssvalues.gperf"
+ {"cross", CSS_VAL_CROSS},
+#line 202 "cssvalues.gperf"
+ {"pointer", CSS_VAL_POINTER},
+#line 258 "cssvalues.gperf"
+ {"relative", CSS_VAL_RELATIVE},
+#line 137 "cssvalues.gperf"
+ {"left", CSS_VAL_LEFT},
+#line 119 "cssvalues.gperf"
+ {"windowframe", CSS_VAL_WINDOWFRAME},
+#line 265 "cssvalues.gperf"
+ {"underline", CSS_VAL_UNDERLINE},
+#line 82 "cssvalues.gperf"
+ {"indigo", CSS_VAL_INDIGO},
+#line 280 "cssvalues.gperf"
+ {"infinite", CSS_VAL_INFINITE},
+#line 110 "cssvalues.gperf"
+ {"infotext", CSS_VAL_INFOTEXT},
+#line 187 "cssvalues.gperf"
+ {"compact", CSS_VAL_COMPACT},
+#line 60 "cssvalues.gperf"
+ {"narrower", CSS_VAL_NARROWER},
+#line 276 "cssvalues.gperf"
+ {"up", CSS_VAL_UP},
+#line 22 "cssvalues.gperf"
+ {"outset", CSS_VAL_OUTSET},
+#line 106 "cssvalues.gperf"
+ {"inactiveborder", CSS_VAL_INACTIVEBORDER},
+#line 245 "cssvalues.gperf"
+ {"hand", CSS_VAL_HAND},
+#line 161 "cssvalues.gperf"
+ {"hebrew", CSS_VAL_HEBREW},
+#line 133 "cssvalues.gperf"
+ {"top", CSS_VAL_TOP},
+#line 236 "cssvalues.gperf"
+ {"avoid", CSS_VAL_AVOID},
+#line 144 "cssvalues.gperf"
+ {"outside", CSS_VAL_OUTSIDE},
+#line 234 "cssvalues.gperf"
+ {"absolute", CSS_VAL_ABSOLUTE},
+#line 162 "cssvalues.gperf"
+ {"armenian", CSS_VAL_ARMENIAN},
+#line 235 "cssvalues.gperf"
+ {"always", CSS_VAL_ALWAYS},
+#line 101 "cssvalues.gperf"
+ {"buttontext", CSS_VAL_BUTTONTEXT},
+#line 185 "cssvalues.gperf"
+ {"list-item", CSS_VAL_LIST_ITEM},
+#line 240 "cssvalues.gperf"
+ {"both", CSS_VAL_BOTH},
+#line 72 "cssvalues.gperf"
+ {"fantasy", CSS_VAL_FANTASY},
+#line 24 "cssvalues.gperf"
+ {"dashed", CSS_VAL_DASHED},
+#line 81 "cssvalues.gperf"
+ {"green", CSS_VAL_GREEN},
+#line 222 "cssvalues.gperf"
+ {"collapse", CSS_VAL_COLLAPSE},
+#line 227 "cssvalues.gperf"
+ {"nowrap", CSS_VAL_NOWRAP},
+#line 269 "cssvalues.gperf"
+ {"content-box", CSS_VAL_CONTENT_BOX},
+#line 73 "cssvalues.gperf"
+ {"monospace", CSS_VAL_MONOSPACE},
+#line 233 "cssvalues.gperf"
+ {"above", CSS_VAL_ABOVE},
+#line 208 "cssvalues.gperf"
+ {"n-resize", CSS_VAL_N_RESIZE},
+#line 261 "cssvalues.gperf"
+ {"show", CSS_VAL_SHOW},
+#line 199 "cssvalues.gperf"
+ {"auto", CSS_VAL_AUTO},
+#line 21 "cssvalues.gperf"
+ {"ridge", CSS_VAL_RIDGE},
+#line 212 "cssvalues.gperf"
+ {"w-resize", CSS_VAL_W_RESIZE},
+#line 257 "cssvalues.gperf"
+ {"portrait", CSS_VAL_PORTRAIT},
+#line 211 "cssvalues.gperf"
+ {"s-resize", CSS_VAL_S_RESIZE},
+#line 87 "cssvalues.gperf"
+ {"orange", CSS_VAL_ORANGE},
+#line 107 "cssvalues.gperf"
+ {"inactivecaption", CSS_VAL_INACTIVECAPTION},
+#line 205 "cssvalues.gperf"
+ {"e-resize", CSS_VAL_E_RESIZE},
+#line 215 "cssvalues.gperf"
+ {"help", CSS_VAL_HELP},
+#line 53 "cssvalues.gperf"
+ {"large", CSS_VAL_LARGE},
+#line 241 "cssvalues.gperf"
+ {"crop", CSS_VAL_CROP},
+#line 121 "cssvalues.gperf"
+ {"grey", CSS_VAL_GREY},
+#line 50 "cssvalues.gperf"
+ {"x-small", CSS_VAL_X_SMALL},
+#line 188 "cssvalues.gperf"
+ {"inline-block", CSS_VAL_INLINE_BLOCK},
+#line 114 "cssvalues.gperf"
+ {"threedface", CSS_VAL_THREEDFACE},
+#line 64 "cssvalues.gperf"
+ {"semi-condensed", CSS_VAL_SEMI_CONDENSED},
+#line 273 "cssvalues.gperf"
+ {"backwards", CSS_VAL_BACKWARDS},
+#line 138 "cssvalues.gperf"
+ {"right", CSS_VAL_RIGHT},
+#line 108 "cssvalues.gperf"
+ {"inactivecaptiontext", CSS_VAL_INACTIVECAPTIONTEXT},
+#line 27 "cssvalues.gperf"
+ {"caption", CSS_VAL_CAPTION},
+#line 274 "cssvalues.gperf"
+ {"ahead", CSS_VAL_AHEAD},
+#line 126 "cssvalues.gperf"
+ {"no-repeat", CSS_VAL_NO_REPEAT},
+#line 80 "cssvalues.gperf"
+ {"gray", CSS_VAL_GRAY},
+#line 197 "cssvalues.gperf"
+ {"table-cell", CSS_VAL_TABLE_CELL},
+#line 39 "cssvalues.gperf"
+ {"lighter", CSS_VAL_LIGHTER},
+#line 98 "cssvalues.gperf"
+ {"buttonface", CSS_VAL_BUTTONFACE},
+#line 79 "cssvalues.gperf"
+ {"fuchsia", CSS_VAL_FUCHSIA},
+#line 249 "cssvalues.gperf"
+ {"landscape", CSS_VAL_LANDSCAPE},
+#line 102 "cssvalues.gperf"
+ {"captiontext", CSS_VAL_CAPTIONTEXT},
+#line 58 "cssvalues.gperf"
+ {"larger", CSS_VAL_LARGER},
+#line 132 "cssvalues.gperf"
+ {"text-bottom", CSS_VAL_TEXT_BOTTOM},
+#line 186 "cssvalues.gperf"
+ {"run-in", CSS_VAL_RUN_IN},
+#line 55 "cssvalues.gperf"
+ {"xx-large", CSS_VAL_XX_LARGE},
+#line 103 "cssvalues.gperf"
+ {"graytext", CSS_VAL_GRAYTEXT},
+#line 268 "cssvalues.gperf"
+ {"border-box", CSS_VAL_BORDER_BOX},
+#line 282 "cssvalues.gperf"
+ {"alternate", CSS_VAL_ALTERNATE},
+#line 174 "cssvalues.gperf"
+ {"lower-latin", CSS_VAL_LOWER_LATIN},
+#line 194 "cssvalues.gperf"
+ {"table-row", CSS_VAL_TABLE_ROW},
+#line 94 "cssvalues.gperf"
+ {"activeborder", CSS_VAL_ACTIVEBORDER},
+#line 66 "cssvalues.gperf"
+ {"expanded", CSS_VAL_EXPANDED},
+#line 74 "cssvalues.gperf"
+ {"transparent", CSS_VAL_TRANSPARENT},
+#line 88 "cssvalues.gperf"
+ {"purple", CSS_VAL_PURPLE},
+#line 190 "cssvalues.gperf"
+ {"inline-table", CSS_VAL_INLINE_TABLE},
+#line 34 "cssvalues.gperf"
+ {"oblique", CSS_VAL_OBLIQUE},
+#line 20 "cssvalues.gperf"
+ {"groove", CSS_VAL_GROOVE},
+#line 201 "cssvalues.gperf"
+ {"default", CSS_VAL_DEFAULT},
+#line 148 "cssvalues.gperf"
+ {"square", CSS_VAL_SQUARE},
+#line 130 "cssvalues.gperf"
+ {"super", CSS_VAL_SUPER},
+#line 70 "cssvalues.gperf"
+ {"sans-serif", CSS_VAL_SANS_SERIF},
+#line 75 "cssvalues.gperf"
+ {"aqua", CSS_VAL_AQUA},
+#line 123 "cssvalues.gperf"
+ {"repeat", CSS_VAL_REPEAT},
+#line 230 "cssvalues.gperf"
+ {"pre-line", CSS_VAL_PRE_LINE},
+#line 283 "cssvalues.gperf"
+ {"unfurl", CSS_VAL_UNFURL},
+#line 238 "cssvalues.gperf"
+ {"bidi-override", CSS_VAL_BIDI_OVERRIDE},
+#line 196 "cssvalues.gperf"
+ {"table-column", CSS_VAL_TABLE_COLUMN},
+#line 131 "cssvalues.gperf"
+ {"text-top", CSS_VAL_TEXT_TOP},
+#line 218 "cssvalues.gperf"
+ {"capitalize", CSS_VAL_CAPITALIZE},
+#line 159 "cssvalues.gperf"
+ {"lower-roman", CSS_VAL_LOWER_ROMAN},
+#line 288 "cssvalues.gperf"
+ {"padding", CSS_VAL_PADDING},
+#line 95 "cssvalues.gperf"
+ {"activecaption", CSS_VAL_ACTIVECAPTION},
+#line 117 "cssvalues.gperf"
+ {"threedshadow", CSS_VAL_THREEDSHADOW},
+#line 200 "cssvalues.gperf"
+ {"crosshair", CSS_VAL_CROSSHAIR},
+#line 247 "cssvalues.gperf"
+ {"higher", CSS_VAL_HIGHER},
+#line 100 "cssvalues.gperf"
+ {"buttonshadow", CSS_VAL_BUTTONSHADOW},
+#line 232 "cssvalues.gperf"
+ {"break-word", CSS_VAL_BREAK_WORD},
+#line 254 "cssvalues.gperf"
+ {"marquee", CSS_VAL_MARQUEE},
+#line 31 "cssvalues.gperf"
+ {"small-caption", CSS_VAL_SMALL_CAPTION},
+#line 35 "cssvalues.gperf"
+ {"small-caps", CSS_VAL_SMALL_CAPS},
+#line 122 "cssvalues.gperf"
+ {"-tdehtml-text", CSS_VAL__KHTML_TEXT},
+#line 141 "cssvalues.gperf"
+ {"-tdehtml-left", CSS_VAL__KHTML_LEFT},
+#line 97 "cssvalues.gperf"
+ {"background", CSS_VAL_BACKGROUND},
+#line 178 "cssvalues.gperf"
+ {"katakana", CSS_VAL_KATAKANA},
+#line 260 "cssvalues.gperf"
+ {"separate", CSS_VAL_SEPARATE},
+#line 32 "cssvalues.gperf"
+ {"status-bar", CSS_VAL_STATUS_BAR},
+#line 65 "cssvalues.gperf"
+ {"semi-expanded", CSS_VAL_SEMI_EXPANDED},
+#line 62 "cssvalues.gperf"
+ {"extra-condensed", CSS_VAL_EXTRA_CONDENSED},
+#line 198 "cssvalues.gperf"
+ {"table-caption", CSS_VAL_TABLE_CAPTION},
+#line 154 "cssvalues.gperf"
+ {"-tdehtml-lao", CSS_VAL__KHTML_LAO},
+#line 143 "cssvalues.gperf"
+ {"-tdehtml-center", CSS_VAL__KHTML_CENTER},
+#line 54 "cssvalues.gperf"
+ {"x-large", CSS_VAL_X_LARGE},
+#line 30 "cssvalues.gperf"
+ {"message-box", CSS_VAL_MESSAGE_BOX},
+#line 203 "cssvalues.gperf"
+ {"progress", CSS_VAL_PROGRESS},
+#line 16 "cssvalues.gperf"
+ {"-tdehtml-native", CSS_VAL__KHTML_NATIVE},
+#line 177 "cssvalues.gperf"
+ {"hiragana", CSS_VAL_HIRAGANA},
+#line 171 "cssvalues.gperf"
+ {"lower-greek", CSS_VAL_LOWER_GREEK},
+#line 150 "cssvalues.gperf"
+ {"-tdehtml-diamond", CSS_VAL__KHTML_DIAMOND},
+#line 224 "cssvalues.gperf"
+ {"no-close-quote", CSS_VAL_NO_CLOSE_QUOTE},
+#line 61 "cssvalues.gperf"
+ {"ultra-condensed", CSS_VAL_ULTRA_CONDENSED},
+#line 158 "cssvalues.gperf"
+ {"-tdehtml-tibetan", CSS_VAL__KHTML_TIBETAN},
+#line 124 "cssvalues.gperf"
+ {"repeat-x", CSS_VAL_REPEAT_X},
+#line 266 "cssvalues.gperf"
+ {"-tdehtml-normal", CSS_VAL__KHTML_NORMAL},
+#line 113 "cssvalues.gperf"
+ {"threeddarkshadow", CSS_VAL_THREEDDARKSHADOW},
+#line 219 "cssvalues.gperf"
+ {"uppercase", CSS_VAL_UPPERCASE},
+#line 136 "cssvalues.gperf"
+ {"-tdehtml-auto", CSS_VAL__KHTML_AUTO},
+#line 163 "cssvalues.gperf"
+ {"georgian", CSS_VAL_GEORGIAN},
+#line 229 "cssvalues.gperf"
+ {"pre-wrap", CSS_VAL_PRE_WRAP},
+#line 125 "cssvalues.gperf"
+ {"repeat-y", CSS_VAL_REPEAT_Y},
+#line 109 "cssvalues.gperf"
+ {"infobackground", CSS_VAL_INFOBACKGROUND},
+#line 157 "cssvalues.gperf"
+ {"-tdehtml-thai", CSS_VAL__KHTML_THAI},
+#line 226 "cssvalues.gperf"
+ {"open-quote", CSS_VAL_OPEN_QUOTE},
+#line 173 "cssvalues.gperf"
+ {"lower-alpha", CSS_VAL_LOWER_ALPHA},
+#line 156 "cssvalues.gperf"
+ {"-tdehtml-urdu", CSS_VAL__KHTML_URDU},
+#line 223 "cssvalues.gperf"
+ {"close-quote", CSS_VAL_CLOSE_QUOTE},
+#line 104 "cssvalues.gperf"
+ {"highlight", CSS_VAL_HIGHLIGHT},
+#line 225 "cssvalues.gperf"
+ {"no-open-quote", CSS_VAL_NO_OPEN_QUOTE},
+#line 231 "cssvalues.gperf"
+ {"-tdehtml-nowrap", CSS_VAL__KHTML_NOWRAP},
+#line 67 "cssvalues.gperf"
+ {"extra-expanded", CSS_VAL_EXTRA_EXPANDED},
+#line 105 "cssvalues.gperf"
+ {"highlighttext", CSS_VAL_HIGHLIGHTTEXT},
+#line 155 "cssvalues.gperf"
+ {"-tdehtml-persian", CSS_VAL__KHTML_PERSIAN},
+#line 116 "cssvalues.gperf"
+ {"threedlightshadow", CSS_VAL_THREEDLIGHTSHADOW},
+#line 96 "cssvalues.gperf"
+ {"appworkspace", CSS_VAL_APPWORKSPACE},
+#line 68 "cssvalues.gperf"
+ {"ultra-expanded", CSS_VAL_ULTRA_EXPANDED},
+#line 176 "cssvalues.gperf"
+ {"upper-latin", CSS_VAL_UPPER_LATIN},
+#line 164 "cssvalues.gperf"
+ {"cjk-ideographic", CSS_VAL_CJK_IDEOGRAPHIC},
+#line 251 "cssvalues.gperf"
+ {"line-through", CSS_VAL_LINE_THROUGH},
+#line 142 "cssvalues.gperf"
+ {"-tdehtml-right", CSS_VAL__KHTML_RIGHT},
+#line 160 "cssvalues.gperf"
+ {"upper-roman", CSS_VAL_UPPER_ROMAN},
+#line 135 "cssvalues.gperf"
+ {"-tdehtml-baseline-middle", CSS_VAL__KHTML_BASELINE_MIDDLE},
+#line 153 "cssvalues.gperf"
+ {"-tdehtml-arabic-indic", CSS_VAL__KHTML_ARABIC_INDIC},
+#line 152 "cssvalues.gperf"
+ {"decimal-leading-zero", CSS_VAL_DECIMAL_LEADING_ZERO},
+#line 115 "cssvalues.gperf"
+ {"threedhighlight", CSS_VAL_THREEDHIGHLIGHT},
+#line 180 "cssvalues.gperf"
+ {"katakana-iroha", CSS_VAL_KATAKANA_IROHA},
+#line 99 "cssvalues.gperf"
+ {"buttonhighlight", CSS_VAL_BUTTONHIGHLIGHT},
+#line 56 "cssvalues.gperf"
+ {"-tdehtml-xxx-large", CSS_VAL__KHTML_XXX_LARGE},
+#line 267 "cssvalues.gperf"
+ {"-tdehtml-around-floats", CSS_VAL__KHTML_AROUND_FLOATS},
+#line 191 "cssvalues.gperf"
+ {"table-row-group", CSS_VAL_TABLE_ROW_GROUP},
+#line 182 "cssvalues.gperf"
+ {"-tdehtml-close-quote", CSS_VAL__KHTML_CLOSE_QUOTE},
+#line 179 "cssvalues.gperf"
+ {"hiragana-iroha", CSS_VAL_HIRAGANA_IROHA},
+#line 193 "cssvalues.gperf"
+ {"table-footer-group", CSS_VAL_TABLE_FOOTER_GROUP},
+#line 195 "cssvalues.gperf"
+ {"table-column-group", CSS_VAL_TABLE_COLUMN_GROUP},
+#line 175 "cssvalues.gperf"
+ {"upper-alpha", CSS_VAL_UPPER_ALPHA},
+#line 181 "cssvalues.gperf"
+ {"-tdehtml-open-quote", CSS_VAL__KHTML_OPEN_QUOTE},
+#line 165 "cssvalues.gperf"
+ {"-tdehtml-japanese-formal", CSS_VAL__KHTML_JAPANESE_FORMAL},
+#line 166 "cssvalues.gperf"
+ {"-tdehtml-japanese-informal", CSS_VAL__KHTML_JAPANESE_INFORMAL},
+#line 192 "cssvalues.gperf"
+ {"table-header-group", CSS_VAL_TABLE_HEADER_GROUP},
+#line 169 "cssvalues.gperf"
+ {"-tdehtml-trad-chinese-formal", CSS_VAL__KHTML_TRAD_CHINESE_FORMAL},
+#line 170 "cssvalues.gperf"
+ {"-tdehtml-trad-chinese-informal", CSS_VAL__KHTML_TRAD_CHINESE_INFORMAL},
+#line 167 "cssvalues.gperf"
+ {"-tdehtml-simp-chinese-formal", CSS_VAL__KHTML_SIMP_CHINESE_FORMAL},
+#line 168 "cssvalues.gperf"
+ {"-tdehtml-simp-chinese-informal", CSS_VAL__KHTML_SIMP_CHINESE_INFORMAL},
+#line 172 "cssvalues.gperf"
+ {"-tdehtml-upper-greek", CSS_VAL__KHTML_UPPER_GREEK}
+ };
+
+ static const short lookup[] =
+ {
+ 0, -1, -1, -1, -1, 1, -1, -1, -1, -1,
+ 2, -1, -1, -1, -1, 3, -1, -1, -1, -1,
+ 4, -1, -1, -1, -1, 5, -1, -1, 6, -1,
+ 7, -1, -1, -1, -1, 8, -1, -1, -1, -1,
+ 9, -1, -1, 10, -1, 11, -1, -1, -1, -1,
+ 12, -1, -1, -1, -1, 13, -1, -1, -1, -1,
+ 14, 15, -1, -1, -1, 16, -1, -1, -1, -1,
+ 17, 18, -1, -1, -1, 19, -1, -1, -1, -1,
+ 20, -1, -1, -1, -1, 21, -1, -1, 22, -1,
+ 23, -1, -1, -1, -1, 24, -1, -1, 25, -1,
+ 26, -1, -1, 27, -1, 28, -1, -1, 29, -1,
+ 30, -1, -1, -1, -1, 31, -1, -1, -1, 32,
+ 33, -1, -1, 34, -1, -1, -1, -1, 35, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 36, -1,
+ 37, -1, -1, -1, -1, 38, -1, -1, 39, -1,
+ 40, -1, -1, 41, -1, -1, -1, -1, 42, -1,
+ 43, -1, -1, 44, -1, 45, -1, -1, 46, -1,
+ -1, -1, -1, 47, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 48, -1, -1, 49, -1,
+ 50, 51, -1, 52, -1, -1, 53, -1, 54, -1,
+ 55, -1, -1, 56, -1, -1, -1, -1, 57, -1,
+ -1, -1, -1, -1, -1, 58, -1, -1, -1, -1,
+ -1, 59, -1, 60, -1, 61, -1, -1, -1, -1,
+ 62, 63, -1, -1, -1, 64, -1, -1, -1, -1,
+ 65, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 66, -1, -1, -1, -1, -1, -1, -1, -1, 67,
+ 68, 69, -1, -1, -1, 70, -1, -1, 71, -1,
+ 72, -1, -1, -1, -1, -1, -1, -1, 73, -1,
+ 74, 75, -1, -1, -1, -1, -1, -1, -1, -1,
+ 76, -1, -1, 77, -1, -1, -1, -1, 78, -1,
+ 79, -1, -1, 80, -1, 81, -1, -1, -1, -1,
+ -1, -1, -1, 82, -1, -1, -1, -1, -1, -1,
+ -1, 83, -1, -1, -1, -1, -1, -1, -1, -1,
+ 84, -1, -1, -1, -1, 85, 86, -1, 87, -1,
+ -1, -1, -1, 88, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 89, -1, -1, -1, 90, 91, -1, -1, 92, -1,
+ -1, 93, -1, -1, -1, -1, -1, -1, -1, -1,
+ 94, -1, -1, 95, -1, 96, -1, -1, -1, -1,
+ 97, -1, -1, 98, -1, 99, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 100, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 101, -1, -1, -1, -1, 102, -1,
+ 103, -1, -1, -1, 104, 105, -1, -1, -1, -1,
+ 106, -1, -1, -1, -1, 107, -1, -1, 108, -1,
+ 109, -1, -1, -1, -1, -1, -1, -1, 110, -1,
+ 111, -1, -1, -1, -1, 112, -1, -1, 113, -1,
+ 114, -1, -1, 115, -1, 116, -1, -1, -1, -1,
+ -1, -1, -1, 117, -1, 118, -1, -1, -1, -1,
+ 119, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 120, -1, -1, -1, -1, -1, 121, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 122, -1,
+ -1, -1, -1, -1, -1, 123, -1, -1, -1, -1,
+ 124, 125, -1, -1, -1, 126, -1, -1, -1, -1,
+ -1, -1, -1, 127, -1, 128, -1, -1, 129, -1,
+ -1, -1, -1, 130, -1, 131, -1, -1, -1, -1,
+ -1, -1, -1, 132, -1, 133, -1, -1, 134, -1,
+ 135, -1, -1, -1, -1, 136, -1, -1, 137, -1,
+ 138, -1, -1, -1, -1, 139, -1, -1, -1, -1,
+ 140, -1, -1, 141, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 142, -1, -1, -1, -1, 143, -1, -1, -1, -1,
+ 144, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 145, 146, -1, -1, -1, -1, -1, -1, 147, -1,
+ 148, -1, -1, 149, -1, 150, -1, -1, 151, -1,
+ 152, 153, -1, -1, -1, 154, -1, -1, 155, -1,
+ -1, -1, -1, 156, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 157, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 158, -1, -1, -1, -1, 159, -1, -1, 160, -1,
+ -1, -1, -1, 161, -1, 162, -1, -1, -1, -1,
+ -1, -1, -1, 163, -1, -1, -1, -1, -1, -1,
+ 164, -1, -1, 165, -1, 166, -1, -1, -1, 167,
+ -1, 168, -1, -1, -1, -1, -1, -1, 169, -1,
+ 170, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 171, -1,
+ -1, -1, -1, 172, -1, -1, -1, -1, 173, -1,
+ -1, -1, -1, 174, -1, 175, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 176, -1, -1, -1, -1, 177, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 178, -1, -1, 179, -1, -1, -1, -1, -1, -1,
+ 180, -1, -1, 181, -1, 182, -1, -1, 183, -1,
+ -1, -1, -1, 184, -1, 185, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 186, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 187, -1, -1, 188, -1, -1, -1, -1, -1, -1,
+ 189, -1, -1, 190, -1, 191, -1, -1, 192, -1,
+ 193, -1, -1, 194, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 195, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 196, -1, -1, -1, -1,
+ 197, -1, -1, 198, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 199, -1, -1, -1,
+ 200, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 201, -1, -1, -1, -1, 202, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 203, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 204, -1,
+ 205, -1, -1, -1, -1, 206, -1, -1, -1, -1,
+ 207, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 208, -1, -1, 209, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 210, -1, -1, -1, -1, -1, -1,
+ 211, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 212, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 213, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 214, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 215, -1, 216, -1, -1, 217, -1,
+ 218, -1, -1, -1, -1, -1, -1, -1, 219, -1,
+ 220, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 221, -1, -1, -1, -1, -1, -1,
+ 222, -1, -1, -1, -1, 223, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 224, -1,
+ -1, -1, -1, -1, -1, 225, -1, -1, 226, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 227, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 228, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 229, -1, -1, -1, -1, -1, 230, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 231, -1,
+ 232, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 233, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 234, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 235, -1,
+ 236, -1, -1, -1, -1, 237, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 238, -1, -1, 239, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 240, -1,
+ -1, 241, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 242, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 243, -1, -1, -1, -1, -1, -1, -1, 244, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 245, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 246, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 247, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 248, -1, -1, -1, -1, -1, -1,
+ 249, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 250, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 251, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 252, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 253, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 254, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 255, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 256, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 257, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 258,
+ -1, -1, -1, -1, -1, -1, -1, -1, 259, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 260, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 261, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 262, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 263, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 264, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 265, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 266, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 267, -1, -1, -1, -1, 268, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 269, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 270, -1,
+ -1, -1, -1, 271, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 272, -1, -1, -1, -1, 273, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 274
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_val (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist_value[index].name;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist_value[index];
+ }
+ }
+ }
+ return 0;
+}
+#line 289 "cssvalues.gperf"
+
+static const char * const valueList[] = {
+"",
+"inherit",
+"initial",
+"-tdehtml-native",
+"none",
+"hidden",
+"inset",
+"groove",
+"ridge",
+"outset",
+"dotted",
+"dashed",
+"solid",
+"double",
+"caption",
+"icon",
+"menu",
+"message-box",
+"small-caption",
+"status-bar",
+"italic",
+"oblique",
+"small-caps",
+"normal",
+"bold",
+"bolder",
+"lighter",
+"100",
+"200",
+"300",
+"400",
+"500",
+"600",
+"700",
+"800",
+"900",
+"xx-small",
+"x-small",
+"small",
+"medium",
+"large",
+"x-large",
+"xx-large",
+"-tdehtml-xxx-large",
+"smaller",
+"larger",
+"wider",
+"narrower",
+"ultra-condensed",
+"extra-condensed",
+"condensed",
+"semi-condensed",
+"semi-expanded",
+"expanded",
+"extra-expanded",
+"ultra-expanded",
+"serif",
+"sans-serif",
+"cursive",
+"fantasy",
+"monospace",
+"transparent",
+"aqua",
+"black",
+"blue",
+"crimson",
+"fuchsia",
+"gray",
+"green",
+"indigo",
+"lime",
+"maroon",
+"navy",
+"olive",
+"orange",
+"purple",
+"red",
+"silver",
+"teal",
+"white",
+"yellow",
+"activeborder",
+"activecaption",
+"appworkspace",
+"background",
+"buttonface",
+"buttonhighlight",
+"buttonshadow",
+"buttontext",
+"captiontext",
+"graytext",
+"highlight",
+"highlighttext",
+"inactiveborder",
+"inactivecaption",
+"inactivecaptiontext",
+"infobackground",
+"infotext",
+"menutext",
+"scrollbar",
+"threeddarkshadow",
+"threedface",
+"threedhighlight",
+"threedlightshadow",
+"threedshadow",
+"window",
+"windowframe",
+"windowtext",
+"grey",
+"-tdehtml-text",
+"repeat",
+"repeat-x",
+"repeat-y",
+"no-repeat",
+"baseline",
+"middle",
+"sub",
+"super",
+"text-top",
+"text-bottom",
+"top",
+"bottom",
+"-tdehtml-baseline-middle",
+"-tdehtml-auto",
+"left",
+"right",
+"center",
+"justify",
+"-tdehtml-left",
+"-tdehtml-right",
+"-tdehtml-center",
+"outside",
+"inside",
+"disc",
+"circle",
+"square",
+"box",
+"-tdehtml-diamond",
+"decimal",
+"decimal-leading-zero",
+"-tdehtml-arabic-indic",
+"-tdehtml-lao",
+"-tdehtml-persian",
+"-tdehtml-urdu",
+"-tdehtml-thai",
+"-tdehtml-tibetan",
+"lower-roman",
+"upper-roman",
+"hebrew",
+"armenian",
+"georgian",
+"cjk-ideographic",
+"-tdehtml-japanese-formal",
+"-tdehtml-japanese-informal",
+"-tdehtml-simp-chinese-formal",
+"-tdehtml-simp-chinese-informal",
+"-tdehtml-trad-chinese-formal",
+"-tdehtml-trad-chinese-informal",
+"lower-greek",
+"-tdehtml-upper-greek",
+"lower-alpha",
+"lower-latin",
+"upper-alpha",
+"upper-latin",
+"hiragana",
+"katakana",
+"hiragana-iroha",
+"katakana-iroha",
+"-tdehtml-open-quote",
+"-tdehtml-close-quote",
+"inline",
+"block",
+"list-item",
+"run-in",
+"compact",
+"inline-block",
+"table",
+"inline-table",
+"table-row-group",
+"table-header-group",
+"table-footer-group",
+"table-row",
+"table-column-group",
+"table-column",
+"table-cell",
+"table-caption",
+"auto",
+"crosshair",
+"default",
+"pointer",
+"progress",
+"move",
+"e-resize",
+"ne-resize",
+"nw-resize",
+"n-resize",
+"se-resize",
+"sw-resize",
+"s-resize",
+"w-resize",
+"text",
+"wait",
+"help",
+"ltr",
+"rtl",
+"capitalize",
+"uppercase",
+"lowercase",
+"visible",
+"collapse",
+"close-quote",
+"no-close-quote",
+"no-open-quote",
+"open-quote",
+"nowrap",
+"pre",
+"pre-wrap",
+"pre-line",
+"-tdehtml-nowrap",
+"break-word",
+"above",
+"absolute",
+"always",
+"avoid",
+"below",
+"bidi-override",
+"blink",
+"both",
+"crop",
+"cross",
+"embed",
+"fixed",
+"hand",
+"hide",
+"higher",
+"invert",
+"landscape",
+"level",
+"line-through",
+"loud",
+"lower",
+"marquee",
+"mix",
+"overline",
+"portrait",
+"relative",
+"scroll",
+"separate",
+"show",
+"static",
+"thick",
+"thin",
+"underline",
+"-tdehtml-normal",
+"-tdehtml-around-floats",
+"border-box",
+"content-box",
+"enabled",
+"disabled",
+"forwards",
+"backwards",
+"ahead",
+"reverse",
+"up",
+"down",
+"slow",
+"fast",
+"infinite",
+"slide",
+"alternate",
+"unfurl",
+"clip",
+"ellipsis",
+"border",
+"content",
+"padding",
+ 0
+};
+DOMString getValueName(unsigned short id)
+{
+ if(id >= CSS_VAL_TOTAL || id == 0)
+ return DOMString();
+ else
+ return DOMString(valueList[id]);
+}
+
diff --git a/tdehtml/css/cssvalues.h b/tdehtml/css/cssvalues.h
new file mode 100644
index 000000000..36a365754
--- /dev/null
+++ b/tdehtml/css/cssvalues.h
@@ -0,0 +1,290 @@
+/* This file is automatically generated from cssvalues.in by
+#makevalues, do not edit */
+/* Copyright 1998 W. Bastian */
+
+#ifndef CSSVALUES_H
+#define CSSVALUES_H
+
+DOM::DOMString getValueName(unsigned short id) KDE_NO_EXPORT;
+
+#define CSS_VAL_INVALID 0
+#define CSS_VAL_MIN 1
+#define CSS_VAL_INHERIT 1
+#define CSS_VAL_INITIAL 2
+#define CSS_VAL__KHTML_NATIVE 3
+#define CSS_VAL_NONE 4
+#define CSS_VAL_HIDDEN 5
+#define CSS_VAL_INSET 6
+#define CSS_VAL_GROOVE 7
+#define CSS_VAL_RIDGE 8
+#define CSS_VAL_OUTSET 9
+#define CSS_VAL_DOTTED 10
+#define CSS_VAL_DASHED 11
+#define CSS_VAL_SOLID 12
+#define CSS_VAL_DOUBLE 13
+#define CSS_VAL_CAPTION 14
+#define CSS_VAL_ICON 15
+#define CSS_VAL_MENU 16
+#define CSS_VAL_MESSAGE_BOX 17
+#define CSS_VAL_SMALL_CAPTION 18
+#define CSS_VAL_STATUS_BAR 19
+#define CSS_VAL_ITALIC 20
+#define CSS_VAL_OBLIQUE 21
+#define CSS_VAL_SMALL_CAPS 22
+#define CSS_VAL_NORMAL 23
+#define CSS_VAL_BOLD 24
+#define CSS_VAL_BOLDER 25
+#define CSS_VAL_LIGHTER 26
+#define CSS_VAL_100 27
+#define CSS_VAL_200 28
+#define CSS_VAL_300 29
+#define CSS_VAL_400 30
+#define CSS_VAL_500 31
+#define CSS_VAL_600 32
+#define CSS_VAL_700 33
+#define CSS_VAL_800 34
+#define CSS_VAL_900 35
+#define CSS_VAL_XX_SMALL 36
+#define CSS_VAL_X_SMALL 37
+#define CSS_VAL_SMALL 38
+#define CSS_VAL_MEDIUM 39
+#define CSS_VAL_LARGE 40
+#define CSS_VAL_X_LARGE 41
+#define CSS_VAL_XX_LARGE 42
+#define CSS_VAL__KHTML_XXX_LARGE 43
+#define CSS_VAL_SMALLER 44
+#define CSS_VAL_LARGER 45
+#define CSS_VAL_WIDER 46
+#define CSS_VAL_NARROWER 47
+#define CSS_VAL_ULTRA_CONDENSED 48
+#define CSS_VAL_EXTRA_CONDENSED 49
+#define CSS_VAL_CONDENSED 50
+#define CSS_VAL_SEMI_CONDENSED 51
+#define CSS_VAL_SEMI_EXPANDED 52
+#define CSS_VAL_EXPANDED 53
+#define CSS_VAL_EXTRA_EXPANDED 54
+#define CSS_VAL_ULTRA_EXPANDED 55
+#define CSS_VAL_SERIF 56
+#define CSS_VAL_SANS_SERIF 57
+#define CSS_VAL_CURSIVE 58
+#define CSS_VAL_FANTASY 59
+#define CSS_VAL_MONOSPACE 60
+#define CSS_VAL_TRANSPARENT 61
+#define CSS_VAL_AQUA 62
+#define CSS_VAL_BLACK 63
+#define CSS_VAL_BLUE 64
+#define CSS_VAL_CRIMSON 65
+#define CSS_VAL_FUCHSIA 66
+#define CSS_VAL_GRAY 67
+#define CSS_VAL_GREEN 68
+#define CSS_VAL_INDIGO 69
+#define CSS_VAL_LIME 70
+#define CSS_VAL_MAROON 71
+#define CSS_VAL_NAVY 72
+#define CSS_VAL_OLIVE 73
+#define CSS_VAL_ORANGE 74
+#define CSS_VAL_PURPLE 75
+#define CSS_VAL_RED 76
+#define CSS_VAL_SILVER 77
+#define CSS_VAL_TEAL 78
+#define CSS_VAL_WHITE 79
+#define CSS_VAL_YELLOW 80
+#define CSS_VAL_ACTIVEBORDER 81
+#define CSS_VAL_ACTIVECAPTION 82
+#define CSS_VAL_APPWORKSPACE 83
+#define CSS_VAL_BACKGROUND 84
+#define CSS_VAL_BUTTONFACE 85
+#define CSS_VAL_BUTTONHIGHLIGHT 86
+#define CSS_VAL_BUTTONSHADOW 87
+#define CSS_VAL_BUTTONTEXT 88
+#define CSS_VAL_CAPTIONTEXT 89
+#define CSS_VAL_GRAYTEXT 90
+#define CSS_VAL_HIGHLIGHT 91
+#define CSS_VAL_HIGHLIGHTTEXT 92
+#define CSS_VAL_INACTIVEBORDER 93
+#define CSS_VAL_INACTIVECAPTION 94
+#define CSS_VAL_INACTIVECAPTIONTEXT 95
+#define CSS_VAL_INFOBACKGROUND 96
+#define CSS_VAL_INFOTEXT 97
+#define CSS_VAL_MENUTEXT 98
+#define CSS_VAL_SCROLLBAR 99
+#define CSS_VAL_THREEDDARKSHADOW 100
+#define CSS_VAL_THREEDFACE 101
+#define CSS_VAL_THREEDHIGHLIGHT 102
+#define CSS_VAL_THREEDLIGHTSHADOW 103
+#define CSS_VAL_THREEDSHADOW 104
+#define CSS_VAL_WINDOW 105
+#define CSS_VAL_WINDOWFRAME 106
+#define CSS_VAL_WINDOWTEXT 107
+#define CSS_VAL_GREY 108
+#define CSS_VAL__KHTML_TEXT 109
+#define CSS_VAL_REPEAT 110
+#define CSS_VAL_REPEAT_X 111
+#define CSS_VAL_REPEAT_Y 112
+#define CSS_VAL_NO_REPEAT 113
+#define CSS_VAL_BASELINE 114
+#define CSS_VAL_MIDDLE 115
+#define CSS_VAL_SUB 116
+#define CSS_VAL_SUPER 117
+#define CSS_VAL_TEXT_TOP 118
+#define CSS_VAL_TEXT_BOTTOM 119
+#define CSS_VAL_TOP 120
+#define CSS_VAL_BOTTOM 121
+#define CSS_VAL__KHTML_BASELINE_MIDDLE 122
+#define CSS_VAL__KHTML_AUTO 123
+#define CSS_VAL_LEFT 124
+#define CSS_VAL_RIGHT 125
+#define CSS_VAL_CENTER 126
+#define CSS_VAL_JUSTIFY 127
+#define CSS_VAL__KHTML_LEFT 128
+#define CSS_VAL__KHTML_RIGHT 129
+#define CSS_VAL__KHTML_CENTER 130
+#define CSS_VAL_OUTSIDE 131
+#define CSS_VAL_INSIDE 132
+#define CSS_VAL_DISC 133
+#define CSS_VAL_CIRCLE 134
+#define CSS_VAL_SQUARE 135
+#define CSS_VAL_BOX 136
+#define CSS_VAL__KHTML_DIAMOND 137
+#define CSS_VAL_DECIMAL 138
+#define CSS_VAL_DECIMAL_LEADING_ZERO 139
+#define CSS_VAL__KHTML_ARABIC_INDIC 140
+#define CSS_VAL__KHTML_LAO 141
+#define CSS_VAL__KHTML_PERSIAN 142
+#define CSS_VAL__KHTML_URDU 143
+#define CSS_VAL__KHTML_THAI 144
+#define CSS_VAL__KHTML_TIBETAN 145
+#define CSS_VAL_LOWER_ROMAN 146
+#define CSS_VAL_UPPER_ROMAN 147
+#define CSS_VAL_HEBREW 148
+#define CSS_VAL_ARMENIAN 149
+#define CSS_VAL_GEORGIAN 150
+#define CSS_VAL_CJK_IDEOGRAPHIC 151
+#define CSS_VAL__KHTML_JAPANESE_FORMAL 152
+#define CSS_VAL__KHTML_JAPANESE_INFORMAL 153
+#define CSS_VAL__KHTML_SIMP_CHINESE_FORMAL 154
+#define CSS_VAL__KHTML_SIMP_CHINESE_INFORMAL 155
+#define CSS_VAL__KHTML_TRAD_CHINESE_FORMAL 156
+#define CSS_VAL__KHTML_TRAD_CHINESE_INFORMAL 157
+#define CSS_VAL_LOWER_GREEK 158
+#define CSS_VAL__KHTML_UPPER_GREEK 159
+#define CSS_VAL_LOWER_ALPHA 160
+#define CSS_VAL_LOWER_LATIN 161
+#define CSS_VAL_UPPER_ALPHA 162
+#define CSS_VAL_UPPER_LATIN 163
+#define CSS_VAL_HIRAGANA 164
+#define CSS_VAL_KATAKANA 165
+#define CSS_VAL_HIRAGANA_IROHA 166
+#define CSS_VAL_KATAKANA_IROHA 167
+#define CSS_VAL__KHTML_OPEN_QUOTE 168
+#define CSS_VAL__KHTML_CLOSE_QUOTE 169
+#define CSS_VAL_INLINE 170
+#define CSS_VAL_BLOCK 171
+#define CSS_VAL_LIST_ITEM 172
+#define CSS_VAL_RUN_IN 173
+#define CSS_VAL_COMPACT 174
+#define CSS_VAL_INLINE_BLOCK 175
+#define CSS_VAL_TABLE 176
+#define CSS_VAL_INLINE_TABLE 177
+#define CSS_VAL_TABLE_ROW_GROUP 178
+#define CSS_VAL_TABLE_HEADER_GROUP 179
+#define CSS_VAL_TABLE_FOOTER_GROUP 180
+#define CSS_VAL_TABLE_ROW 181
+#define CSS_VAL_TABLE_COLUMN_GROUP 182
+#define CSS_VAL_TABLE_COLUMN 183
+#define CSS_VAL_TABLE_CELL 184
+#define CSS_VAL_TABLE_CAPTION 185
+#define CSS_VAL_AUTO 186
+#define CSS_VAL_CROSSHAIR 187
+#define CSS_VAL_DEFAULT 188
+#define CSS_VAL_POINTER 189
+#define CSS_VAL_PROGRESS 190
+#define CSS_VAL_MOVE 191
+#define CSS_VAL_E_RESIZE 192
+#define CSS_VAL_NE_RESIZE 193
+#define CSS_VAL_NW_RESIZE 194
+#define CSS_VAL_N_RESIZE 195
+#define CSS_VAL_SE_RESIZE 196
+#define CSS_VAL_SW_RESIZE 197
+#define CSS_VAL_S_RESIZE 198
+#define CSS_VAL_W_RESIZE 199
+#define CSS_VAL_TEXT 200
+#define CSS_VAL_WAIT 201
+#define CSS_VAL_HELP 202
+#define CSS_VAL_LTR 203
+#define CSS_VAL_RTL 204
+#define CSS_VAL_CAPITALIZE 205
+#define CSS_VAL_UPPERCASE 206
+#define CSS_VAL_LOWERCASE 207
+#define CSS_VAL_VISIBLE 208
+#define CSS_VAL_COLLAPSE 209
+#define CSS_VAL_CLOSE_QUOTE 210
+#define CSS_VAL_NO_CLOSE_QUOTE 211
+#define CSS_VAL_NO_OPEN_QUOTE 212
+#define CSS_VAL_OPEN_QUOTE 213
+#define CSS_VAL_NOWRAP 214
+#define CSS_VAL_PRE 215
+#define CSS_VAL_PRE_WRAP 216
+#define CSS_VAL_PRE_LINE 217
+#define CSS_VAL__KHTML_NOWRAP 218
+#define CSS_VAL_BREAK_WORD 219
+#define CSS_VAL_ABOVE 220
+#define CSS_VAL_ABSOLUTE 221
+#define CSS_VAL_ALWAYS 222
+#define CSS_VAL_AVOID 223
+#define CSS_VAL_BELOW 224
+#define CSS_VAL_BIDI_OVERRIDE 225
+#define CSS_VAL_BLINK 226
+#define CSS_VAL_BOTH 227
+#define CSS_VAL_CROP 228
+#define CSS_VAL_CROSS 229
+#define CSS_VAL_EMBED 230
+#define CSS_VAL_FIXED 231
+#define CSS_VAL_HAND 232
+#define CSS_VAL_HIDE 233
+#define CSS_VAL_HIGHER 234
+#define CSS_VAL_INVERT 235
+#define CSS_VAL_LANDSCAPE 236
+#define CSS_VAL_LEVEL 237
+#define CSS_VAL_LINE_THROUGH 238
+#define CSS_VAL_LOUD 239
+#define CSS_VAL_LOWER 240
+#define CSS_VAL_MARQUEE 241
+#define CSS_VAL_MIX 242
+#define CSS_VAL_OVERLINE 243
+#define CSS_VAL_PORTRAIT 244
+#define CSS_VAL_RELATIVE 245
+#define CSS_VAL_SCROLL 246
+#define CSS_VAL_SEPARATE 247
+#define CSS_VAL_SHOW 248
+#define CSS_VAL_STATIC 249
+#define CSS_VAL_THICK 250
+#define CSS_VAL_THIN 251
+#define CSS_VAL_UNDERLINE 252
+#define CSS_VAL__KHTML_NORMAL 253
+#define CSS_VAL__KHTML_AROUND_FLOATS 254
+#define CSS_VAL_BORDER_BOX 255
+#define CSS_VAL_CONTENT_BOX 256
+#define CSS_VAL_ENABLED 257
+#define CSS_VAL_DISABLED 258
+#define CSS_VAL_FORWARDS 259
+#define CSS_VAL_BACKWARDS 260
+#define CSS_VAL_AHEAD 261
+#define CSS_VAL_REVERSE 262
+#define CSS_VAL_UP 263
+#define CSS_VAL_DOWN 264
+#define CSS_VAL_SLOW 265
+#define CSS_VAL_FAST 266
+#define CSS_VAL_INFINITE 267
+#define CSS_VAL_SLIDE 268
+#define CSS_VAL_ALTERNATE 269
+#define CSS_VAL_UNFURL 270
+#define CSS_VAL_CLIP 271
+#define CSS_VAL_ELLIPSIS 272
+#define CSS_VAL_BORDER 273
+#define CSS_VAL_CONTENT 274
+#define CSS_VAL_PADDING 275
+
+#define CSS_VAL_TOTAL 276
+#endif
+
diff --git a/tdehtml/css/cssvalues.in b/tdehtml/css/cssvalues.in
new file mode 100644
index 000000000..b85d49f17
--- /dev/null
+++ b/tdehtml/css/cssvalues.in
@@ -0,0 +1,478 @@
+# These are all values accepted for CSS2.
+#
+# WARNING:
+# --------
+#
+# The Values are sorted according to the properties they belong to,
+# and have to be in the same order as the enums in render_style.h.
+#
+# If not, the optimizations in the cssparser and style selector will fail,
+# and produce incorrect results.
+#
+inherit
+initial
+#
+# CSS_PROP_OUTLINE_STYLE
+# CSS_PROP_BORDER_TOP_STYLE
+# CSS_PROP_BORDER_BOTTOM_STYLE
+# CSS_PROP_BORDER_LEFT_STYLE
+-tdehtml-native
+none
+hidden
+inset
+groove
+ridge
+outset
+dotted
+dashed
+solid
+double
+#
+# CSS_PROP_FONT:
+#
+caption
+icon
+menu
+message-box
+small-caption
+status-bar
+#
+# CSS_PROP_FONT_STYLE:
+#
+#normal
+italic
+oblique
+#
+# CSS_PROP_FONT_VARIANT:
+#
+#normal
+small-caps
+#
+# CSS_PROP_FONT_WEIGHT:
+#
+normal
+bold
+bolder
+lighter
+100
+200
+300
+400
+500
+600
+700
+800
+900
+#
+# CSS_PROP_FONT_SIZE:
+#
+xx-small
+x-small
+small
+medium
+large
+x-large
+xx-large
+-tdehtml-xxx-large
+smaller
+larger
+#
+# CSS_PROP_FONT_STRETCH:
+#
+#normal
+wider
+narrower
+ultra-condensed
+extra-condensed
+condensed
+semi-condensed
+semi-expanded
+expanded
+extra-expanded
+ultra-expanded
+#
+# CSS_PROP_GENERIC_FONT_FAMILY:
+#
+serif
+sans-serif
+cursive
+fantasy
+monospace
+#
+#
+# CSS_PROP_BACKGROUND_COLOR:
+#
+transparent
+#
+#
+# CSS_PROP_*_COLOR
+#
+aqua
+black
+blue
+crimson
+fuchsia
+gray
+green
+indigo
+lime
+maroon
+navy
+olive
+orange
+purple
+red
+silver
+teal
+white
+yellow
+activeborder
+activecaption
+appworkspace
+background
+buttonface
+buttonhighlight
+buttonshadow
+buttontext
+captiontext
+graytext
+highlight
+highlighttext
+inactiveborder
+inactivecaption
+inactivecaptiontext
+infobackground
+infotext
+menutext
+scrollbar
+threeddarkshadow
+threedface
+threedhighlight
+threedlightshadow
+threedshadow
+window
+windowframe
+windowtext
+#
+# colors in non strict mode
+grey
+-tdehtml-text
+#
+# CSS_PROP_BACKGROUND_REPEAT:
+#
+repeat
+repeat-x
+repeat-y
+no-repeat
+#
+# CSS_PROP_VERTICAL_ALIGN:
+#
+baseline
+middle
+sub
+super
+text-top
+text-bottom
+top
+bottom
+# HTML alignment MIDDLE has no corresponding CSS alignment
+-tdehtml-baseline-middle
+#
+# CSS_PROP_TEXT_ALIGN:
+#
+-tdehtml-auto
+left
+right
+center
+justify
+-tdehtml-left
+-tdehtml-right
+-tdehtml-center
+#
+# CSS_PROP_LIST_STYLE_POSITION:
+#
+outside
+inside
+#
+# CSS_PROP_LIST_STYLE_TYPE:
+#
+disc
+circle
+square
+box
+-tdehtml-diamond
+decimal
+decimal-leading-zero
+-tdehtml-arabic-indic
+-tdehtml-lao
+-tdehtml-persian
+-tdehtml-urdu
+-tdehtml-thai
+-tdehtml-tibetan
+lower-roman
+upper-roman
+hebrew
+armenian
+georgian
+cjk-ideographic
+-tdehtml-japanese-formal
+-tdehtml-japanese-informal
+-tdehtml-simp-chinese-formal
+-tdehtml-simp-chinese-informal
+-tdehtml-trad-chinese-formal
+-tdehtml-trad-chinese-informal
+lower-greek
+-tdehtml-upper-greek
+lower-alpha
+lower-latin
+upper-alpha
+upper-latin
+hiragana
+katakana
+hiragana-iroha
+katakana-iroha
+-tdehtml-open-quote
+-tdehtml-close-quote
+#none
+#
+# CSS_PROP_DISPLAY:
+#
+inline
+block
+list-item
+run-in
+compact
+inline-block
+table
+inline-table
+table-row-group
+table-header-group
+table-footer-group
+table-row
+table-column-group
+table-column
+table-cell
+table-caption
+#none
+#
+# CSS_PROP_CURSOR:
+#
+auto
+crosshair
+default
+pointer
+progress
+move
+e-resize
+ne-resize
+nw-resize
+n-resize
+se-resize
+sw-resize
+s-resize
+w-resize
+text
+wait
+help
+#
+# CSS_PROP_DIRECTION:
+#
+ltr
+rtl
+#
+# CSS_PROP_TEXT_TRANSFORM:
+#
+capitalize
+uppercase
+lowercase
+#none
+#
+# CSS_PROP_VISIBILITY:
+#
+visible
+#hidden
+collapse
+#
+# CSS_PROP_CONTENT:
+#
+close-quote
+no-close-quote
+no-open-quote
+open-quote
+#
+# CSS_PROP_WHITE_SPACE:
+#
+#normal
+nowrap
+pre
+pre-wrap
+pre-line
+-tdehtml-nowrap
+#
+# CSS_PROP_WORD_WRAP
+#
+#normal
+break-word
+#
+# Unordered rest
+#
+above
+absolute
+always
+avoid
+below
+bidi-override
+blink
+both
+crop
+cross
+embed
+fixed
+hand
+hide
+higher
+invert
+landscape
+level
+line-through
+loud
+lower
+marquee
+mix
+overline
+portrait
+relative
+scroll
+separate
+show
+static
+thick
+thin
+underline
+#
+# CSS_PROP__KHTML_FLOW_MODE
+-tdehtml-normal
+-tdehtml-around-floats
+
+# CSS3 Values
+# CSS_PROP__KHTML_BOX_SIZING
+border-box
+content-box
+
+# CSS_PROP__KHTML_USER_INPUT
+enabled
+disabled
+#none
+
+# CSS_PROP_MARQUEE_DIRECTION
+forwards
+backwards
+ahead
+reverse
+# left
+# right
+up
+down
+# auto
+
+# CSS_PROP_MARQUEE_SPEED
+slow
+# normal
+fast
+
+# CSS_PROP_MARQUEE_REPETITION
+infinite
+
+# CSS_PROP_MARQUEE_STYLE
+# none
+slide
+# scroll
+alternate
+unfurl
+
+#
+# CSS_PROP_TEXT_OVERFLOW
+#
+clip
+ellipsis
+
+#
+# CSS_PROP_BACKGROUND_CLIP/ORIGIN
+#
+border
+content
+padding
+
+#
+# Not supported:
+#
+# CSS_PROP_BORDER_IMAGE
+#
+# stretch
+# repeat
+# round
+#
+# CSS_PROP_AZIMUTH:
+#
+#A left-side
+#A far-left
+#A #left
+#A center-left
+#A #center
+#A center-right
+#A right
+#A far-right
+#A right-side
+#A behind
+#A leftwards
+#A rightwards
+#
+# CSS_PROP_SPEECH_RATE:
+#
+#A x-slow
+#A slow
+#A #medium
+#A x-fast
+#A fast
+#A faster
+#A slower
+#
+# CSS_PROP_VOLUME:
+#
+#A silent
+#A x-soft
+#A soft
+#A #medium
+#A high
+#A x-high
+#A x-loud
+#
+# CSS_PROP_PITCH:
+#
+#A x-low
+#A low
+#A #medium
+#A #high
+#A #x-high
+#
+# CSS_PROP_SPEAK:
+#
+#A #normal
+#A #none
+#A spell-out
+#
+# CSS_PROP_SPEAK_HEADER:
+#
+#A #once
+#A always
+#
+# CSS_PROP_SPEAK_NUMERAL:
+#
+#A digits
+#A continuous
+#
+# CSS_PROP_SPEAK_PUNCTUATION:
+#
+#A code
+#A #none
+
diff --git a/tdehtml/css/html4.css b/tdehtml/css/html4.css
new file mode 100644
index 000000000..ffd599601
--- /dev/null
+++ b/tdehtml/css/html4.css
@@ -0,0 +1,549 @@
+/*
+ * The default style sheet used by tdehtml to render HTML pages
+ * (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ *
+ * Konqueror/tdehtml relies on the existence of this style sheet for
+ * rendering. Do not remove or modify this file unless you know
+ * what you are doing.
+ */
+
+@namespace "http://www.w3.org/1999/xhtml";
+
+html {
+ display: block;
+ color: -tdehtml-text;
+}
+
+/*
+ * head and it's children all have display=none
+ */
+
+head {
+ display: none;
+}
+
+meta {
+ display: none;
+}
+
+title {
+ display: none;
+}
+
+link {
+ display: none;
+}
+
+style {
+ display: none;
+}
+
+script {
+ display: none;
+}
+
+/*
+ * generic block level elements
+ */
+
+@media print {
+ body {
+ display: block;
+ margin: 0px;
+ }
+}
+
+@media screen {
+ body {
+ display: block;
+ margin: 10px;
+ }
+}
+
+p {
+ display: block;
+ margin: 1.0__qem 0px;
+}
+
+div {
+ display: block;
+}
+
+/* to force a block level context for some cases (broken HTML) */
+
+layer {
+ display: block;
+}
+
+address {
+ display: block;
+}
+
+blockquote {
+ display: block;
+ margin: 1__qem 40px 1em 40px;
+}
+
+q {
+ display: inline;
+}
+
+q:before {
+ content: open-quote;
+}
+
+q:after {
+ content: close-quote;
+}
+
+center {
+ display: block;
+ /* special centering to be able to emulate the html4/netscape behavior */
+ text-align: -tdehtml-center;
+}
+
+hr {
+ display: block;
+ margin: 12px auto;
+ border-style: inset;
+ border-width: 1px;
+ -tdehtml-flow-mode: -tdehtml-around-floats
+}
+
+map {
+ display: inline;
+}
+
+/*
+ * heading elements
+ * margin values rely on font-sizes ratio defined in css-2.1 15.7
+ * (cf. cssstyleselector for absolute font-sizes computation)
+ * we have an 1.1/font-ratio margin
+ */
+
+h1 {
+ display: block;
+ font-size: xx-large;
+ margin: .55__qem 0 .55em 0;
+ font-weight: bolder;
+}
+
+h2 {
+ display: block;
+ font-size: x-large;
+ margin: .73__qem 0 .73em 0;
+ font-weight: bolder;
+}
+
+h3 {
+ display: block;
+ font-size: large;
+ margin: 0.92__qem 0 0.92em 0;
+ font-weight: bolder;
+}
+
+h4 {
+ display: block;
+ font-size: medium;
+ margin: 1.1__qem 0 1.1em 0;
+ font-weight: bolder;
+}
+
+h5 {
+ display: block;
+ font-size: small;
+ margin: 1.24__qem 0 1.24em 0;
+ font-weight: bolder;
+}
+
+h6 {
+ display: block;
+ font-size: xx-small;
+ margin: 1.83__qem 0 1.83em 0;
+ font-weight: bolder;
+}
+
+/*
+ * tables
+ */
+
+table {
+ display: table;
+ border-collapse: separate;
+ border-spacing: 2px;
+ -tdehtml-flow-mode: -tdehtml-around-floats;
+ box-sizing: border-box;
+}
+
+table[align="center"] {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table[align="left"] {
+ float: -tdehtml-left;
+}
+
+table[align="right"] {
+ float: -tdehtml-right;
+}
+
+thead {
+ display: table-header-group;
+ border-color: inherit;
+ vertical-align: middle;
+}
+
+tbody {
+ display: table-row-group;
+ border-color: inherit;
+ vertical-align: middle;
+}
+
+tfoot {
+ display: table-footer-group;
+ border-color: inherit;
+ vertical-align: middle;
+}
+
+col {
+ display: table-column;
+}
+
+colgroup {
+ display: table-column-group;
+}
+
+tr {
+ display: table-row;
+ vertical-align: inherit;
+ border-color: inherit;
+}
+
+
+td, th {
+ display: table-cell;
+ vertical-align: inherit;
+}
+
+th {
+ font-weight: bolder;
+}
+
+caption {
+ display: table-caption;
+ text-align: -tdehtml-center;
+}
+
+/*
+ * lists
+ */
+
+ul, menu, dir {
+ display: block;
+ list-style-type: disc;
+ margin: 1__qem 0 1em 0;
+ -tdehtml-padding-start: 40px
+}
+
+ol {
+ display: block;
+ list-style-type: decimal;
+ margin: 1__qem 0 1em 0;
+ -tdehtml-padding-start: 40px
+}
+
+li {
+ display: list-item;
+ -tdehtml-flow-mode: -tdehtml-around-floats;
+}
+
+
+ul ul, ol ul {
+ list-style-type: circle;
+}
+
+ol ol ul, ol ul ul, ul ol ul, ul ul ul {
+ list-style-type: square;
+}
+
+
+dd {
+ display: block;
+}
+
+dl > dd {
+ -tdehtml-margin-start: 40px;
+}
+
+dl {
+ display: block;
+ margin: 1__qem 0 1em 0;
+}
+
+dt {
+ display: block;
+}
+
+dl[compact] > dt {
+ display: compact;
+}
+
+ol ul,
+ul ol,
+ul ul,
+ol ol {
+ margin-top: auto;
+ margin-bottom: auto;
+}
+
+li > p {
+ margin-top: auto;
+/* margin-bottom: auto;*/
+}
+
+li > div {
+ margin-top: auto;
+/* margin-bottom: auto;*/
+}
+
+/*
+ * form elements
+ */
+
+form {
+ display: block;
+ margin: 0__qem 0 1em 0;
+}
+
+legend {
+ display: block;
+ padding-left: 2px;
+ padding-right: 2px;
+ border: none;
+ margin: 0;
+}
+
+fieldset {
+ display: block;
+ padding: 0.75em 0.625em;
+ margin: 1.0em 0;
+ border: 2px groove threedface;
+ -tdehtml-flow-mode: -tdehtml-around-floats
+}
+
+button {
+ display: inline-block;
+ border: 2px outset buttonface;
+ background-color: buttonface;
+ color: buttontext;
+ padding: 2px 2px 2px 2px;
+ cursor: default;
+}
+
+button:active {
+ border-style: inset;
+}
+
+input, textarea {
+ text-align: -tdehtml-auto;
+}
+
+input, textarea, select, button {
+ font-weight: normal;
+ margin: 0__qem;
+}
+
+input { color: windowtext;
+ font-family: sans-serif;
+ font-size: small;
+ border: 2px -tdehtml-native;
+}
+
+input[type="hidden"] {
+ display: none;
+}
+
+input[type="radio"], input[type="checkbox"] {
+ margin: 0 0.5ex;
+ color: buttontext;
+}
+
+input[type="text"], input[type="password"] {
+ cursor: text;
+}
+
+input[type="submit"], input[type="reset"], input[type="button"] {
+ color: buttontext;
+}
+
+isindex { color: windowtext; font-size: small; }
+
+
+option,
+optgroup,
+area,
+param {
+ display: none;
+}
+
+select {
+ font-family: sans-serif;
+ font-size: small;
+ color: windowtext;
+}
+
+textarea {
+ color: windowtext;
+ font-family: monospace;
+ border: 2px -tdehtml-native;
+}
+
+/*
+ * inline elements
+ */
+
+u,
+ins {
+ text-decoration: underline;
+}
+
+strong,
+b {
+ font-weight: bolder;
+}
+
+i,
+cite,
+em,
+var,
+address {
+ font-style: italic;
+}
+
+tt,
+code,
+kbd,
+samp {
+ font-family: monospace;
+}
+
+pre,
+xmp,
+plaintext {
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ margin: 1__qem 0;
+}
+
+big {
+ font-size: larger;
+}
+
+small {
+ font-size: smaller;
+}
+
+s,
+strike,
+del {
+ text-decoration: line-through;
+}
+
+sub {
+ vertical-align: sub;
+ font-size: smaller;
+}
+sup {
+ vertical-align: super;
+ font-size: smaller;
+}
+
+abbr, acronym {
+ font-variant: small-caps;
+ letter-spacing: 0.1em
+}
+
+pre[wrap] {
+ white-space: pre-wrap
+}
+
+*|:focus { outline: 1px dotted invert }
+a:link:active { color: red; outline: 1px dotted invert; }
+a:visited:active { color: red; outline: 1px dotted invert; }
+
+/* with the current design it is too expensive to set this default via css
+:before,:after { white-space: pre-line }
+*/
+
+/* ### use this to replace renderbr
+ br:before { content: "\n" }
+*/
+
+
+/* bidirectionality settings (do not change) */
+
+bdo[dir="ltr"] {
+ direction: ltr;
+ unicode-bidi: bidi-override;
+}
+
+bdo[dir="rtl"] {
+ direction: rtl;
+ unicode-bidi: bidi-override;
+}
+
+/* ### this selector seems to be still broken ...
+ *[dir="ltr"] { direction: ltr; unicode-bidi: embed }
+ *[dir="rtl"] { direction: rtl; unicode-bidi: embed }
+*/
+
+/* elements that are block-level in html4 */
+/* ### don't support unicode-bidi at the moment
+ address, blockquote, body, dd, div, dl, dt, fieldset,
+ form, frame, frameset, h1, h2, h3, h4, h5, h6, iframe,
+ noscript, noframes, object, ol, p, ul, applet, center,
+ dir, hr, menu, pre, li, table, tr, thead, tbody, tfoot,
+ col, colgroup, td, th, caption
+ { unicode-bidi: embed }
+*/
+
+/* end bidi settings */
+
+/*
+ * other elements
+ */
+
+noframes {
+ display: none;
+}
+
+frameset {
+ display: block;
+}
+
+frame {
+ display: block;
+}
+
+nobr {
+ white-space: nowrap;
+}
+
+wbr {
+ white-space: normal;
+}
+
+marquee {
+ display: inline-block;
+ overflow: marquee;
+}
+
+/* noscript is handled internally, as it depends on the html settings */
+
+@media print {
+ h1, h2, h3,
+ h4, h5, h6 { page-break-after: avoid }
+ ul, ol, dl { page-break-before: avoid }
+}
diff --git a/tdehtml/css/makeprop b/tdehtml/css/makeprop
new file mode 100644
index 000000000..a1a30ac97
--- /dev/null
+++ b/tdehtml/css/makeprop
@@ -0,0 +1,57 @@
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1999 Waldo Bastian (bastian@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 -- Script to generate cssproperties.c and cssproperties.h
+#
+grep "^[^\#]" cssproperties.in > cssproperties.strip
+
+echo -e '%{\n/* This file is automatically generated from cssproperties.in by makeprop, do not edit */\n/* Copyright 1999 W. Bastian */\n#include "cssproperties.h"\n%}\nstruct props {\n const char *name;\n int id;\n};\n\nstatic const struct props * findProp (register const char *str, register unsigned int len);\n\n%%' > cssproperties.gperf
+cat cssproperties.strip | awk '{ do { prop = $0; gsub("-", "_"); print prop ", CSS_PROP_" toupper($0) } while (getline) }' >> cssproperties.gperf
+echo '%%' >> cssproperties.gperf
+echo -e '/* This file is automatically generated from cssproperties.in by makeprop, do not edit */\n/* Copyright 1998 W. Bastian */\n\n#ifndef CSSPROPERTIES_H\n#define CSSPROPERTIES_H\n\nDOM::DOMString getPropertyName(unsigned short id) KDE_NO_EXPORT;\n' > cssproperties.h
+cat cssproperties.strip | awk '{ \
+i=1; \
+print "#define CSS_PROP_INVALID 0"; \
+print "#define CSS_PROP_MIN 1"; \
+do { gsub("-", "_"); print "#define CSS_PROP_" toupper($0) " " i; i = i + 1 } while (getline); \
+print ""; \
+print "#define CSS_PROP_MAX CSS_PROP_Z_INDEX"; \
+print "#define CSS_PROP_TOTAL " i \
+}' >> cssproperties.h
+gperf -a -L 'ANSI-C' -E -C -c -o -t -k '*' -NfindProp -Hhash_prop -Wwordlist_prop -D -s 2 cssproperties.gperf > cssproperties.c || exit 1
+echo -e '#endif\n' >> cssproperties.h
+
+cat cssproperties.strip | awk '{ \
+i=1; \
+print "static const char * const propertyList[] = {"; \
+print "\"\","; \
+do { print "\"" $0 "\", "; i = i + 1 } while (getline); \
+print " 0"; \
+print "};"; \
+print "DOMString getPropertyName(unsigned short id)"; \
+print "{"; \
+print " if(id >= CSS_PROP_TOTAL || id == 0)"; \
+print " return DOMString();";\
+print " else";\
+print " return DOMString(propertyList[id]);"; \
+print "}"; \
+print ""; \
+}' >> cssproperties.c
diff --git a/tdehtml/css/makevalues b/tdehtml/css/makevalues
new file mode 100755
index 000000000..0f81f1612
--- /dev/null
+++ b/tdehtml/css/makevalues
@@ -0,0 +1,63 @@
+#!/bin/sh
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1999 Waldo Bastian (bastian@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 -- Script to generate cssvalues.c and cssvalues.h
+#
+grep "^[^\#]" cssvalues.in > cssvalues.strip
+
+echo -e '%{\n/* This file is automatically generated from cssvalues.in by makevalues, do not edit */\n/* Copyright 1999 W. Bastian */\n#include "cssvalues.h"\n%}\nstruct css_value {\n const char *name;\n int id;\n};\n\nstatic const css_value* findValue (register const char *str, register unsigned int len);\n\n%%' > cssvalues.gperf
+cat cssvalues.strip | awk '{ do { prop = $0; gsub("-", "_"); print prop ", CSS_VAL_" toupper($0) } while (getline) }' >> cssvalues.gperf
+echo '%%' >> cssvalues.gperf
+echo -e '/* This file is automatically generated from cssvalues.in by
+#makevalues, do not edit */\n/* Copyright 1998 W. Bastian */\n\n#ifndef CSSVALUES_H\n#define CSSVALUES_H\n\nDOM::DOMString getValueName(unsigned short id) KDE_NO_EXPORT;\n' > cssvalues.h
+cat cssvalues.strip | awk '{ \
+i=1; \
+print "#define CSS_VAL_INVALID 0"; \
+print "#define CSS_VAL_MIN 1"; \
+do { gsub("-", "_"); print "#define CSS_VAL_" toupper($0) " " i; i = i + 1 } while (getline); \
+print ""; \
+print "#define CSS_VAL_TOTAL " i \
+}' >> cssvalues.h
+gperf -L 'ANSI-C' -E -c -C -n -o -t -k '*' -NfindValue -Hhash_val -Wwordlist_value -D cssvalues.gperf > cssvalues.c || exit 1
+echo -e '#endif\n' >> cssvalues.h
+
+cat cssvalues.strip | awk '{ \
+i=1; \
+print "static const char * const valueList[] = {"; \
+print "\"\","; \
+do { print "\"" $0 "\", "; i = i + 1 } while (getline); \
+print " 0"; \
+print "};"; \
+print "DOMString getValueName(unsigned short id)"; \
+print "{"; \
+print " if(id >= CSS_VAL_TOTAL || id == 0)"; \
+print " return DOMString();";\
+print " else";\
+print " return DOMString(valueList[id]);"; \
+print "}"; \
+print ""; \
+}' >> cssvalues.c
+
+
+
+
+
diff --git a/tdehtml/css/parser.cpp b/tdehtml/css/parser.cpp
new file mode 100644
index 000000000..f88b7d002
--- /dev/null
+++ b/tdehtml/css/parser.cpp
@@ -0,0 +1,2875 @@
+/* A Bison parser, made by GNU Bison 1.875d. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 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.
+*/
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* If NAME_PREFIX is specified substitute the variables and functions
+ names. */
+#define yyparse cssyyparse
+#define yylex cssyylex
+#define yyerror cssyyerror
+#define yylval cssyylval
+#define yychar cssyychar
+#define yydebug cssyydebug
+#define yynerrs cssyynerrs
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ UNIMPORTANT_TOK = 258,
+ S = 259,
+ SGML_CD = 260,
+ INCLUDES = 261,
+ DASHMATCH = 262,
+ BEGINSWITH = 263,
+ ENDSWITH = 264,
+ CONTAINS = 265,
+ STRING = 266,
+ IDENT = 267,
+ NTH = 268,
+ HASH = 269,
+ IMPORT_SYM = 270,
+ PAGE_SYM = 271,
+ MEDIA_SYM = 272,
+ FONT_FACE_SYM = 273,
+ CHARSET_SYM = 274,
+ NAMESPACE_SYM = 275,
+ KHTML_RULE_SYM = 276,
+ KHTML_DECLS_SYM = 277,
+ KHTML_VALUE_SYM = 278,
+ IMPORTANT_SYM = 279,
+ QEMS = 280,
+ EMS = 281,
+ EXS = 282,
+ PXS = 283,
+ CMS = 284,
+ MMS = 285,
+ INS = 286,
+ PTS = 287,
+ PCS = 288,
+ DEGS = 289,
+ RADS = 290,
+ GRADS = 291,
+ MSECS = 292,
+ SECS = 293,
+ HERZ = 294,
+ KHERZ = 295,
+ DIMEN = 296,
+ PERCENTAGE = 297,
+ FLOAT = 298,
+ INTEGER = 299,
+ URI = 300,
+ FUNCTION = 301,
+ NOTFUNCTION = 302,
+ UNICODERANGE = 303
+ };
+#endif
+#define UNIMPORTANT_TOK 258
+#define S 259
+#define SGML_CD 260
+#define INCLUDES 261
+#define DASHMATCH 262
+#define BEGINSWITH 263
+#define ENDSWITH 264
+#define CONTAINS 265
+#define STRING 266
+#define IDENT 267
+#define NTH 268
+#define HASH 269
+#define IMPORT_SYM 270
+#define PAGE_SYM 271
+#define MEDIA_SYM 272
+#define FONT_FACE_SYM 273
+#define CHARSET_SYM 274
+#define NAMESPACE_SYM 275
+#define KHTML_RULE_SYM 276
+#define KHTML_DECLS_SYM 277
+#define KHTML_VALUE_SYM 278
+#define IMPORTANT_SYM 279
+#define QEMS 280
+#define EMS 281
+#define EXS 282
+#define PXS 283
+#define CMS 284
+#define MMS 285
+#define INS 286
+#define PTS 287
+#define PCS 288
+#define DEGS 289
+#define RADS 290
+#define GRADS 291
+#define MSECS 292
+#define SECS 293
+#define HERZ 294
+#define KHERZ 295
+#define DIMEN 296
+#define PERCENTAGE 297
+#define FLOAT 298
+#define INTEGER 299
+#define URI 300
+#define FUNCTION 301
+#define NOTFUNCTION 302
+#define UNICODERANGE 303
+
+
+
+
+/* Copy the first part of user declarations. */
+
+
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (c) 2003 Apple Computer
+ * Copyright (C) 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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+
+#include <dom/dom_string.h>
+#include <xml/dom_docimpl.h>
+#include <css/cssstyleselector.h>
+#include <css/css_ruleimpl.h>
+#include <css/css_stylesheetimpl.h>
+#include <css/css_valueimpl.h>
+#include <misc/htmlhashes.h>
+#include "cssparser.h"
+
+#include <assert.h>
+#include <kdebug.h>
+//#define CSS_DEBUG
+
+using namespace DOM;
+
+//
+// The following file defines the function
+// const struct props *findProp(const char *word, int len)
+//
+// with 'props->id' a CSS property in the range from CSS_PROP_MIN to
+// (and including) CSS_PROP_TOTAL-1
+
+// turn off inlining to void warning with newer gcc
+#undef __inline
+#define __inline
+#include "cssproperties.c"
+#include "cssvalues.c"
+#undef __inline
+
+int DOM::getPropertyID(const char *tagStr, int len)
+{
+ const struct props *propsPtr = findProp(tagStr, len);
+ if (!propsPtr)
+ return 0;
+
+ return propsPtr->id;
+}
+
+static inline int getValueID(const char *tagStr, int len)
+{
+ const struct css_value *val = findValue(tagStr, len);
+ if (!val)
+ return 0;
+
+ return val->id;
+}
+
+
+#define YYDEBUG 0
+#undef YYMAXDEPTH
+#define YYPARSE_PARAM parser
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+
+typedef union YYSTYPE {
+ CSSRuleImpl *rule;
+ CSSSelector *selector;
+ TQPtrList<CSSSelector> *selectorList;
+ bool ok;
+ MediaListImpl *mediaList;
+ CSSMediaRuleImpl *mediaRule;
+ CSSRuleListImpl *ruleList;
+ ParseString string;
+ float val;
+ int prop_id;
+ unsigned int attribute;
+ unsigned int element;
+ unsigned int ns;
+ CSSSelector::Relation relation;
+ CSSSelector::Match match;
+ bool b;
+ char tok;
+ Value value;
+ ValueList *valueList;
+} YYSTYPE;
+/* Line 191 of yacc.c. */
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+
+static inline int cssyyerror(const char *x )
+{
+#ifdef CSS_DEBUG
+ tqDebug( "%s", x );
+#else
+ Q_UNUSED( x );
+#endif
+ return 1;
+}
+
+static int cssyylex( YYSTYPE *yylval ) {
+ return CSSParser::current()->lex( yylval );
+}
+
+#define null 1
+
+
+
+/* Line 214 of yacc.c. */
+
+
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
+
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# define YYSTACK_ALLOC alloca
+# endif
+# else
+# if defined (alloca) || defined (_ALLOCA_H)
+# define YYSTACK_ALLOC alloca
+# else
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short int yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 16
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 479
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 67
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 54
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 162
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 305
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 303
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 64, 18, 58, 57, 61, 16, 65, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 15, 56,
+ 2, 63, 60, 2, 66, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 17, 2, 62, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 54, 19, 55, 59, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned short int yyprhs[] =
+{
+ 0, 0, 3, 9, 12, 15, 18, 25, 28, 34,
+ 35, 38, 39, 42, 45, 46, 52, 56, 60, 61,
+ 65, 72, 76, 80, 81, 85, 92, 96, 100, 101,
+ 104, 105, 109, 111, 113, 115, 117, 119, 121, 124,
+ 126, 128, 129, 131, 133, 138, 141, 149, 150, 154,
+ 157, 161, 165, 169, 173, 176, 179, 182, 183, 185,
+ 187, 190, 192, 197, 200, 202, 206, 209, 211, 214,
+ 217, 220, 224, 227, 231, 236, 240, 242, 244, 246,
+ 249, 252, 254, 256, 258, 260, 263, 266, 271, 280,
+ 286, 296, 298, 300, 302, 304, 306, 308, 310, 312,
+ 315, 319, 324, 329, 334, 339, 345, 350, 355, 360,
+ 366, 372, 376, 380, 385, 390, 396, 399, 402, 405,
+ 406, 408, 412, 415, 418, 419, 421, 424, 427, 430,
+ 433, 436, 439, 441, 443, 446, 449, 452, 455, 458,
+ 461, 464, 467, 470, 473, 476, 479, 482, 485, 488,
+ 491, 494, 497, 500, 506, 510, 513, 517, 521, 524,
+ 530, 534, 536
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 68, 0, -1, 74, 73, 75, 77, 80, -1, 69,
+ 72, -1, 70, 72, -1, 71, 72, -1, 26, 54,
+ 72, 92, 72, 55, -1, 27, 106, -1, 28, 54,
+ 72, 111, 55, -1, -1, 72, 4, -1, -1, 73,
+ 5, -1, 73, 4, -1, -1, 24, 72, 11, 72,
+ 56, -1, 24, 1, 119, -1, 24, 1, 56, -1,
+ -1, 75, 76, 73, -1, 20, 72, 82, 72, 83,
+ 56, -1, 20, 1, 119, -1, 20, 1, 56, -1,
+ -1, 77, 78, 73, -1, 25, 72, 79, 82, 72,
+ 56, -1, 25, 1, 119, -1, 25, 1, 56, -1,
+ -1, 12, 4, -1, -1, 80, 81, 73, -1, 92,
+ -1, 85, -1, 88, -1, 89, -1, 118, -1, 117,
+ -1, 76, 1, -1, 11, -1, 50, -1, -1, 84,
+ -1, 87, -1, 84, 57, 72, 87, -1, 84, 1,
+ -1, 22, 72, 84, 54, 72, 86, 55, -1, -1,
+ 86, 92, 72, -1, 12, 72, -1, 21, 1, 119,
+ -1, 21, 1, 56, -1, 23, 1, 119, -1, 23,
+ 1, 56, -1, 58, 72, -1, 59, 72, -1, 60,
+ 72, -1, -1, 61, -1, 58, -1, 93, 106, -1,
+ 94, -1, 93, 57, 72, 94, -1, 93, 1, -1,
+ 96, -1, 94, 90, 96, -1, 94, 1, -1, 19,
+ -1, 18, 19, -1, 12, 19, -1, 97, 72, -1,
+ 97, 98, 72, -1, 98, 72, -1, 95, 97, 72,
+ -1, 95, 97, 98, 72, -1, 95, 98, 72, -1,
+ 12, -1, 18, -1, 99, -1, 98, 99, -1, 98,
+ 1, -1, 14, -1, 100, -1, 102, -1, 105, -1,
+ 16, 12, -1, 12, 72, -1, 17, 72, 101, 62,
+ -1, 17, 72, 101, 103, 72, 104, 72, 62, -1,
+ 17, 72, 95, 101, 62, -1, 17, 72, 95, 101,
+ 103, 72, 104, 72, 62, -1, 63, -1, 6, -1,
+ 7, -1, 8, -1, 9, -1, 10, -1, 12, -1,
+ 11, -1, 15, 12, -1, 15, 15, 12, -1, 15,
+ 51, 13, 64, -1, 15, 51, 49, 64, -1, 15,
+ 51, 12, 64, -1, 15, 51, 11, 64, -1, 15,
+ 52, 72, 96, 64, -1, 54, 72, 108, 55, -1,
+ 54, 72, 1, 55, -1, 54, 72, 107, 55, -1,
+ 54, 72, 107, 108, 55, -1, 54, 72, 107, 1,
+ 55, -1, 108, 56, 72, -1, 1, 56, 72, -1,
+ 107, 108, 56, 72, -1, 107, 1, 56, 72, -1,
+ 109, 15, 72, 111, 110, -1, 1, 119, -1, 12,
+ 72, -1, 29, 72, -1, -1, 113, -1, 111, 112,
+ 113, -1, 65, 72, -1, 57, 72, -1, -1, 114,
+ -1, 91, 114, -1, 46, 72, -1, 11, 72, -1,
+ 12, 72, -1, 50, 72, -1, 53, 72, -1, 116,
+ -1, 115, -1, 49, 72, -1, 48, 72, -1, 47,
+ 72, -1, 33, 72, -1, 34, 72, -1, 35, 72,
+ -1, 36, 72, -1, 37, 72, -1, 38, 72, -1,
+ 39, 72, -1, 40, 72, -1, 41, 72, -1, 42,
+ 72, -1, 43, 72, -1, 44, 72, -1, 45, 72,
+ -1, 31, 72, -1, 30, 72, -1, 32, 72, -1,
+ 51, 72, 111, 64, 72, -1, 51, 72, 1, -1,
+ 14, 72, -1, 66, 1, 119, -1, 66, 1, 56,
+ -1, 1, 119, -1, 54, 1, 120, 1, 55, -1,
+ 54, 1, 55, -1, 119, -1, 120, 1, 119, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short int yyrline[] =
+{
+ 0, 257, 257, 258, 259, 260, 264, 271, 277, 302,
+ 303, 306, 308, 309, 312, 314, 319, 320, 323, 325,
+ 336, 346, 349, 355, 356, 360, 368, 369, 373, 374,
+ 377, 379, 390, 391, 392, 393, 394, 395, 396, 400,
+ 401, 405, 408, 413, 417, 422, 429, 443, 444, 454,
+ 476, 479, 485, 488, 494, 495, 496, 497, 501, 502,
+ 506, 526, 540, 555, 562, 565, 579, 586, 587, 588,
+ 592, 596, 601, 606, 613, 622, 634, 650, 656, 660,
+ 670, 677, 683, 684, 685, 689, 698, 722, 727, 733,
+ 741, 753, 756, 759, 762, 765, 768, 774, 775, 779,
+ 785, 791, 798, 805, 812, 819, 828, 831, 834, 837,
+ 842, 848, 852, 855, 860, 866, 888, 894, 901, 902,
+ 906, 910, 926, 929, 932, 938, 939, 941, 942, 943,
+ 949, 950, 951, 953, 959, 960, 961, 962, 963, 964,
+ 965, 966, 967, 968, 969, 970, 971, 972, 973, 974,
+ 975, 976, 977, 982, 990, 1006, 1013, 1019, 1028, 1054,
+ 1055, 1059, 1060
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "UNIMPORTANT_TOK", "S", "SGML_CD",
+ "INCLUDES", "DASHMATCH", "BEGINSWITH", "ENDSWITH", "CONTAINS", "STRING",
+ "IDENT", "NTH", "HASH", "':'", "'.'", "'['", "'*'", "'|'", "IMPORT_SYM",
+ "PAGE_SYM", "MEDIA_SYM", "FONT_FACE_SYM", "CHARSET_SYM", "NAMESPACE_SYM",
+ "KHTML_RULE_SYM", "KHTML_DECLS_SYM", "KHTML_VALUE_SYM", "IMPORTANT_SYM",
+ "QEMS", "EMS", "EXS", "PXS", "CMS", "MMS", "INS", "PTS", "PCS", "DEGS",
+ "RADS", "GRADS", "MSECS", "SECS", "HERZ", "KHERZ", "DIMEN", "PERCENTAGE",
+ "FLOAT", "INTEGER", "URI", "FUNCTION", "NOTFUNCTION", "UNICODERANGE",
+ "'{'", "'}'", "';'", "','", "'+'", "'~'", "'>'", "'-'", "']'", "'='",
+ "')'", "'/'", "'@'", "$accept", "stylesheet", "tdehtml_rule",
+ "tdehtml_decls", "tdehtml_value", "maybe_space", "maybe_sgml",
+ "maybe_charset", "import_list", "import", "namespace_list", "namespace",
+ "maybe_ns_prefix", "rule_list", "rule", "string_or_uri",
+ "maybe_media_list", "media_list", "media", "ruleset_list", "medium",
+ "page", "font_face", "combinator", "unary_operator", "ruleset",
+ "selector_list", "selector", "namespace_selector", "simple_selector",
+ "element_name", "specifier_list", "specifier", "class", "attrib_id",
+ "attrib", "match", "ident_or_string", "pseudo", "declaration_block",
+ "declaration_list", "declaration", "property", "prio", "expr",
+ "operator", "term", "unary_term", "function", "hexcolor", "invalid_at",
+ "invalid_rule", "invalid_block", "invalid_block_list", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short int yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 58, 46, 91, 42, 124,
+ 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+ 280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
+ 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 300, 301, 302, 303, 123, 125, 59, 44, 43, 126,
+ 62, 45, 93, 61, 41, 47, 64
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 67, 68, 68, 68, 68, 69, 70, 71, 72,
+ 72, 73, 73, 73, 74, 74, 74, 74, 75, 75,
+ 76, 76, 76, 77, 77, 78, 78, 78, 79, 79,
+ 80, 80, 81, 81, 81, 81, 81, 81, 81, 82,
+ 82, 83, 83, 84, 84, 84, 85, 86, 86, 87,
+ 88, 88, 89, 89, 90, 90, 90, 90, 91, 91,
+ 92, 93, 93, 93, 94, 94, 94, 95, 95, 95,
+ 96, 96, 96, 96, 96, 96, 97, 97, 98, 98,
+ 98, 99, 99, 99, 99, 100, 101, 102, 102, 102,
+ 102, 103, 103, 103, 103, 103, 103, 104, 104, 105,
+ 105, 105, 105, 105, 105, 105, 106, 106, 106, 106,
+ 106, 107, 107, 107, 107, 108, 108, 109, 110, 110,
+ 111, 111, 112, 112, 112, 113, 113, 113, 113, 113,
+ 113, 113, 113, 113, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
+ 114, 114, 114, 115, 115, 116, 117, 117, 118, 119,
+ 119, 120, 120
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 5, 2, 2, 2, 6, 2, 5, 0,
+ 2, 0, 2, 2, 0, 5, 3, 3, 0, 3,
+ 6, 3, 3, 0, 3, 6, 3, 3, 0, 2,
+ 0, 3, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 0, 1, 1, 4, 2, 7, 0, 3, 2,
+ 3, 3, 3, 3, 2, 2, 2, 0, 1, 1,
+ 2, 1, 4, 2, 1, 3, 2, 1, 2, 2,
+ 2, 3, 2, 3, 4, 3, 1, 1, 1, 2,
+ 2, 1, 1, 1, 1, 2, 2, 4, 8, 5,
+ 9, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 3, 4, 4, 4, 4, 5, 4, 4, 4, 5,
+ 5, 3, 3, 4, 4, 5, 2, 2, 2, 0,
+ 1, 3, 2, 2, 0, 1, 2, 2, 2, 2,
+ 2, 2, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 3, 2, 3, 3, 2, 5,
+ 3, 1, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 14, 0, 0, 0, 0, 0, 9, 9, 9, 11,
+ 0, 0, 9, 9, 7, 9, 1, 3, 4, 5,
+ 18, 0, 17, 16, 10, 9, 0, 0, 0, 13,
+ 12, 23, 0, 0, 76, 81, 0, 0, 9, 77,
+ 67, 9, 0, 0, 0, 64, 9, 0, 78, 82,
+ 83, 84, 0, 9, 0, 0, 0, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 59, 58, 0, 124, 120, 125, 133,
+ 132, 0, 11, 30, 160, 161, 0, 15, 69, 99,
+ 0, 0, 9, 85, 0, 68, 0, 63, 9, 60,
+ 66, 9, 9, 9, 0, 76, 77, 9, 0, 70,
+ 0, 80, 72, 79, 107, 9, 116, 117, 0, 108,
+ 0, 106, 9, 9, 128, 129, 155, 151, 150, 152,
+ 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
+ 147, 148, 149, 127, 136, 135, 134, 130, 0, 131,
+ 126, 8, 9, 9, 0, 0, 0, 19, 0, 11,
+ 0, 0, 100, 0, 0, 0, 0, 0, 9, 0,
+ 0, 0, 6, 0, 54, 55, 56, 65, 73, 0,
+ 75, 71, 112, 110, 9, 109, 9, 111, 0, 154,
+ 124, 123, 122, 121, 22, 21, 39, 40, 9, 0,
+ 28, 24, 0, 0, 9, 0, 0, 0, 11, 33,
+ 34, 35, 32, 37, 36, 159, 162, 104, 103, 101,
+ 102, 0, 86, 9, 0, 92, 93, 94, 95, 96,
+ 87, 91, 9, 0, 74, 114, 113, 124, 9, 41,
+ 27, 26, 0, 0, 158, 0, 0, 0, 0, 38,
+ 31, 105, 89, 9, 0, 9, 115, 153, 9, 0,
+ 0, 43, 29, 9, 51, 50, 0, 53, 52, 157,
+ 156, 0, 98, 97, 9, 118, 49, 20, 45, 9,
+ 0, 9, 9, 0, 0, 25, 47, 0, 88, 44,
+ 0, 90, 46, 9, 48
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short int yydefgoto[] =
+{
+ -1, 5, 6, 7, 8, 232, 20, 9, 31, 92,
+ 93, 169, 253, 170, 218, 208, 269, 270, 219, 300,
+ 271, 220, 221, 114, 85, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 181, 50, 242, 284, 51, 14,
+ 54, 55, 56, 266, 86, 164, 87, 88, 89, 90,
+ 223, 224, 126, 96
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -167
+static const short int yypact[] =
+{
+ 252, 19, -46, -32, -20, 44, -167, -167, -167, -167,
+ 147, 183, -167, -167, -167, -167, -167, 96, 96, 96,
+ 34, 114, -167, -167, -167, -167, 333, 156, 355, -167,
+ -167, 85, 98, -2, 99, -167, 158, 109, -167, 152,
+ -167, -167, 52, 241, 222, -167, 229, 162, -167, -167,
+ -167, -167, 215, -167, 101, 168, 118, -167, -167, -167,
+ -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+ -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+ -167, -167, -167, -167, -167, 430, 127, -167, -167, -167,
+ -167, 119, -167, 160, -167, -167, 189, -167, -167, -167,
+ 202, 116, -167, -167, 14, -167, 104, -167, -167, -167,
+ -167, -167, -167, -167, 346, -167, -167, 229, 162, 96,
+ 162, -167, 96, -167, -167, -167, -167, 96, 238, -167,
+ 210, -167, -167, -167, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 273, 96,
+ -167, -167, -167, -167, 398, 150, 5, 34, 185, -167,
+ 125, 157, -167, 154, 169, 217, 218, 333, 99, 152,
+ 237, 41, -167, 333, 96, 96, 96, -167, 96, 162,
+ 96, 96, 96, -167, -167, -167, -167, 96, 355, -167,
+ -36, 96, 96, -167, -167, -167, -167, -167, -167, 161,
+ 110, 34, 232, 288, -167, 295, 296, 326, -167, -167,
+ -167, -167, -167, -167, -167, -167, -167, -167, -167, -167,
+ -167, 264, 96, -167, 87, -167, -167, -167, -167, -167,
+ -167, -167, -167, 324, 96, 96, 96, 143, -167, 171,
+ -167, -167, 325, 88, -167, 198, 171, 207, 219, -167,
+ 34, -167, -167, -167, 31, -167, -167, 96, -167, 274,
+ 35, -167, -167, -167, -167, -167, 97, -167, -167, -167,
+ -167, 31, -167, -167, -167, 96, 96, -167, -167, -167,
+ 79, -167, -167, 23, 171, -167, 96, 27, -167, -167,
+ 213, -167, -167, -167, 96
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const short int yypgoto[] =
+{
+ -167, -167, -167, -167, -167, -1, -82, -167, -167, 163,
+ -167, -167, -167, -167, -167, 82, -167, 76, -167, -167,
+ 50, -167, -167, -167, -167, -166, -167, 170, 242, -95,
+ 310, -29, -34, -167, 175, -167, 122, 89, -167, 315,
+ -167, 314, -167, -167, -157, -167, 208, 286, -167, -167,
+ -167, -167, -7, -167
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -120
+static const short int yytable[] =
+{
+ 11, 200, 24, 23, 222, 17, 18, 19, 12, 24,
+ 167, 26, 27, 123, 28, 118, 206, 120, 24, 187,
+ 10, 162, 13, -9, 33, 95, 178, 24, 248, 163,
+ -9, 24, 179, 40, 15, 24, 288, 104, 29, 30,
+ 106, 247, 282, 283, 16, 119, 122, 235, 236, 237,
+ 238, 239, 127, 107, 97, 207, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+ 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+ 158, 159, 231, 24, 123, 298, 123, 211, 189, 301,
+ 166, -42, 289, 235, 236, 237, 238, 239, 288, 206,
+ 24, 177, 128, 240, 241, 91, 13, 183, 24, 108,
+ 184, 185, 186, 53, 24, 32, 188, 190, 98, 191,
+ 165, 103, 252, -9, 192, -2, 212, 173, 174, 175,
+ -9, 197, 198, 133, 303, 295, 260, 34, 207, 35,
+ 36, 37, 38, 39, 40, 91, 213, 214, 215, 262,
+ 241, 291, 21, 94, 289, 123, 129, 52, 205, 182,
+ 24, 201, 202, 121, 226, 176, -9, 210, 53, -9,
+ 99, 105, 265, 100, -9, 24, 35, 36, 37, 38,
+ -9, -9, 161, 268, 162, 168, 209, 24, 244, -9,
+ 171, 216, 163, 245, 25, 246, -9, -9, -119, -119,
+ 162, 21, 251, 22, 21, 254, 204, 249, 163, 101,
+ 102, 21, 225, 256, 172, 21, -9, 250, 227, -9,
+ -9, -9, -9, 131, 132, 34, -9, 35, 36, 37,
+ 38, 39, 40, 228, 115, -9, 35, 36, 37, 38,
+ 116, 264, 110, 35, 36, 37, 38, 267, 275, 233,
+ 278, 280, 21, -57, 274, -57, -57, -57, -57, -57,
+ -57, 21, 281, 277, 285, 195, 196, 286, 302, 21,
+ 124, 125, 290, 21, 199, 279, 1, 24, 2, 3,
+ 4, 229, 230, 293, 57, 58, 21, 59, 294, 255,
+ 296, 297, 21, 193, 194, -61, 257, 258, -61, 111,
+ 112, 113, 304, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 110, 82, 259, 261, 272,
+ 287, 83, 276, 217, 84, 273, -57, 24, -57, -57,
+ -57, -57, -57, -57, 299, 34, 180, 35, 36, 37,
+ 38, 39, 40, 243, 117, 234, 263, 109, 34, 24,
+ 35, 36, 37, 38, 39, 40, 57, 58, 130, 59,
+ 292, 160, 203, 0, 0, 0, 0, 0, -62, 0,
+ 0, -62, 111, 112, 113, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 0, 82, 57,
+ 58, 0, 59, 83, 0, 0, 84, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 0, 82, 0, 0, 0, 0, 83, 0, 0, 84,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 0, 77, 78, 79
+};
+
+static const short int yycheck[] =
+{
+ 1, 158, 4, 10, 170, 6, 7, 8, 54, 4,
+ 92, 12, 13, 47, 15, 44, 11, 46, 4, 114,
+ 1, 57, 54, 4, 25, 32, 12, 4, 64, 65,
+ 11, 4, 18, 19, 54, 4, 1, 38, 4, 5,
+ 41, 198, 11, 12, 0, 46, 47, 6, 7, 8,
+ 9, 10, 53, 1, 56, 50, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 177, 4, 118, 62, 120, 169, 117, 62,
+ 91, 56, 57, 6, 7, 8, 9, 10, 1, 11,
+ 4, 102, 1, 62, 63, 20, 54, 108, 4, 57,
+ 111, 112, 113, 12, 4, 1, 117, 118, 19, 120,
+ 1, 12, 12, 4, 125, 0, 1, 11, 12, 13,
+ 11, 132, 133, 15, 300, 56, 218, 12, 50, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 62,
+ 63, 54, 54, 55, 57, 189, 55, 1, 165, 55,
+ 4, 162, 163, 1, 171, 49, 4, 168, 12, 50,
+ 12, 19, 29, 15, 12, 4, 14, 15, 16, 17,
+ 18, 19, 55, 12, 57, 25, 1, 4, 189, 4,
+ 1, 66, 65, 194, 11, 196, 11, 12, 55, 56,
+ 57, 54, 209, 56, 54, 212, 56, 208, 65, 51,
+ 52, 54, 55, 214, 12, 54, 54, 56, 64, 57,
+ 58, 59, 60, 55, 56, 12, 64, 14, 15, 16,
+ 17, 18, 19, 64, 12, 50, 14, 15, 16, 17,
+ 18, 242, 1, 14, 15, 16, 17, 248, 255, 12,
+ 257, 258, 54, 12, 56, 14, 15, 16, 17, 18,
+ 19, 54, 263, 56, 265, 55, 56, 268, 55, 54,
+ 55, 56, 273, 54, 1, 56, 24, 4, 26, 27,
+ 28, 64, 64, 284, 11, 12, 54, 14, 289, 1,
+ 291, 292, 54, 55, 56, 54, 1, 1, 57, 58,
+ 59, 60, 303, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 1, 53, 1, 64, 4,
+ 56, 58, 256, 170, 61, 253, 12, 4, 14, 15,
+ 16, 17, 18, 19, 294, 12, 104, 14, 15, 16,
+ 17, 18, 19, 183, 44, 180, 234, 42, 12, 4,
+ 14, 15, 16, 17, 18, 19, 11, 12, 54, 14,
+ 281, 85, 164, -1, -1, -1, -1, -1, 54, -1,
+ -1, 57, 58, 59, 60, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, -1, 53, 11,
+ 12, -1, 14, 58, -1, -1, 61, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ -1, 53, -1, -1, -1, -1, 58, -1, -1, 61,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, -1, 47, 48, 49
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 24, 26, 27, 28, 68, 69, 70, 71, 74,
+ 1, 72, 54, 54, 106, 54, 0, 72, 72, 72,
+ 73, 54, 56, 119, 4, 11, 72, 72, 72, 4,
+ 5, 75, 1, 72, 12, 14, 15, 16, 17, 18,
+ 19, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 102, 105, 1, 12, 107, 108, 109, 11, 12, 14,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 53, 58, 61, 91, 111, 113, 114, 115,
+ 116, 20, 76, 77, 55, 119, 120, 56, 19, 12,
+ 15, 51, 52, 12, 72, 19, 72, 1, 57, 106,
+ 1, 58, 59, 60, 90, 12, 18, 97, 98, 72,
+ 98, 1, 72, 99, 55, 56, 119, 72, 1, 55,
+ 108, 55, 56, 15, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 114, 55, 57, 65, 112, 1, 72, 73, 25, 78,
+ 80, 1, 12, 11, 12, 13, 49, 72, 12, 18,
+ 95, 101, 55, 72, 72, 72, 72, 96, 72, 98,
+ 72, 72, 72, 55, 56, 55, 56, 72, 72, 1,
+ 111, 72, 72, 113, 56, 119, 11, 50, 82, 1,
+ 72, 73, 1, 21, 22, 23, 66, 76, 81, 85,
+ 88, 89, 92, 117, 118, 55, 119, 64, 64, 64,
+ 64, 96, 72, 12, 101, 6, 7, 8, 9, 10,
+ 62, 63, 103, 94, 72, 72, 72, 111, 64, 72,
+ 56, 119, 12, 79, 119, 1, 72, 1, 1, 1,
+ 73, 64, 62, 103, 72, 29, 110, 72, 12, 83,
+ 84, 87, 4, 82, 56, 119, 84, 56, 119, 56,
+ 119, 72, 11, 12, 104, 72, 72, 56, 1, 57,
+ 72, 54, 104, 72, 72, 56, 72, 72, 62, 87,
+ 86, 62, 55, 92, 72
+};
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+ are run). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ ((Current).first_line = (Rhs)[1].first_line, \
+ (Current).first_column = (Rhs)[1].first_column, \
+ (Current).last_line = (Rhs)[N].last_line, \
+ (Current).last_column = (Rhs)[N].last_column)
+#endif
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YYDSYMPRINT(Args) \
+do { \
+ if (yydebug) \
+ yysymprint Args; \
+} while (0)
+
+# define YYDSYMPRINTF(Title, Token, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Token, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
+#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YYDSYMPRINT(Args)
+# define YYDSYMPRINTF(Title, Token, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
+{
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
+
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (yytype < YYNTOKENS)
+ {
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+# ifdef YYPRINT
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ }
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
+}
+
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yytype, yyvaluep)
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ switch (yytype)
+ {
+ case 83: /* maybe_media_list */
+
+ { delete yyvaluep->mediaList; yyvaluep->mediaList = 0; };
+
+ break;
+ case 84: /* media_list */
+
+ { delete yyvaluep->mediaList; yyvaluep->mediaList = 0; };
+
+ break;
+ case 86: /* ruleset_list */
+
+ { delete yyvaluep->ruleList; yyvaluep->ruleList = 0; };
+
+ break;
+ case 93: /* selector_list */
+
+ { delete yyvaluep->selectorList; yyvaluep->selectorList = 0; };
+
+ break;
+ case 94: /* selector */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 96: /* simple_selector */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 98: /* specifier_list */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 99: /* specifier */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 100: /* class */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 102: /* attrib */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 105: /* pseudo */
+
+ { delete yyvaluep->selector; yyvaluep->selector = 0; };
+
+ break;
+ case 111: /* expr */
+
+ { delete yyvaluep->valueList; yyvaluep->valueList = 0; };
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+ /* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ register int yystate;
+ register int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ register YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK (yyvsp--, yyssp--)
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
+ int yylen;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short int *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ short int *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 6:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ p->rule = yyvsp[-2].rule;
+ ;}
+ break;
+
+ case 7:
+
+ {
+ /* can be empty */
+ ;}
+ break;
+
+ case 8:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-1].valueList ) {
+ p->valueList = yyvsp[-1].valueList;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got property for " << p->id <<
+ (p->important?" important":"")<< endl;
+ bool ok =
+#endif
+ p->parseValue( p->id, p->important );
+#ifdef CSS_DEBUG
+ if ( !ok )
+ kdDebug( 6080 ) << " couldn't parse value!" << endl;
+#endif
+ }
+#ifdef CSS_DEBUG
+ else
+ kdDebug( 6080 ) << " no value found!" << endl;
+#endif
+ delete p->valueList;
+ p->valueList = 0;
+ ;}
+ break;
+
+ case 15:
+
+ {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "charset rule: " << qString(yyvsp[-2].string) << endl;
+#endif
+ ;}
+ break;
+
+ case 19:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-1].rule && p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ p->styleElement->append( yyvsp[-1].rule );
+ } else {
+ delete yyvsp[-1].rule;
+ }
+ ;}
+ break;
+
+ case 20:
+
+ {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "@import: " << qString(yyvsp[-3].string) << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-1].mediaList && p->styleElement && p->styleElement->isCSSStyleSheet() )
+ yyval.rule = new CSSImportRuleImpl( p->styleElement, domString(yyvsp[-3].string), yyvsp[-1].mediaList );
+ else
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 21:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 22:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 25:
+
+ {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "@namespace: " << qString(yyvsp[-2].string) << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->addNamespace(p, domString(yyvsp[-3].string), domString(yyvsp[-2].string));
+ ;}
+ break;
+
+ case 28:
+
+ { yyval.string.string = 0; ;}
+ break;
+
+ case 29:
+
+ { yyval.string = yyvsp[-1].string; ;}
+ break;
+
+ case 31:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-1].rule && p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ p->styleElement->append( yyvsp[-1].rule );
+ } else {
+ delete yyvsp[-1].rule;
+ }
+ ;}
+ break;
+
+ case 38:
+
+ { delete yyvsp[-1].rule; yyval.rule = 0; ;}
+ break;
+
+ case 41:
+
+ {
+ yyval.mediaList = new MediaListImpl();
+ ;}
+ break;
+
+ case 43:
+
+ {
+ yyval.mediaList = new MediaListImpl();
+ yyval.mediaList->appendMedium( domString(yyvsp[0].string).lower() );
+ ;}
+ break;
+
+ case 44:
+
+ {
+ yyval.mediaList = yyvsp[-3].mediaList;
+ if (yyval.mediaList)
+ yyval.mediaList->appendMedium( domString(yyvsp[0].string).lower() );
+ ;}
+ break;
+
+ case 45:
+
+ {
+ delete yyvsp[-1].mediaList;
+ yyval.mediaList = 0;
+ ;}
+ break;
+
+ case 46:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-4].mediaList && yyvsp[-1].ruleList &&
+ p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ yyval.rule = new CSSMediaRuleImpl( static_cast<CSSStyleSheetImpl*>(p->styleElement), yyvsp[-4].mediaList, yyvsp[-1].ruleList );
+ } else {
+ yyval.rule = 0;
+ delete yyvsp[-4].mediaList;
+ delete yyvsp[-1].ruleList;
+ }
+ ;}
+ break;
+
+ case 47:
+
+ { yyval.ruleList = 0; ;}
+ break;
+
+ case 48:
+
+ {
+ yyval.ruleList = yyvsp[-2].ruleList;
+ if ( yyvsp[-1].rule ) {
+ if ( !yyval.ruleList ) yyval.ruleList = new CSSRuleListImpl();
+ yyval.ruleList->append( yyvsp[-1].rule );
+ }
+ ;}
+ break;
+
+ case 49:
+
+ {
+ yyval.string = yyvsp[-1].string;
+ ;}
+ break;
+
+ case 50:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 51:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 52:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 53:
+
+ {
+ yyval.rule = 0;
+ ;}
+ break;
+
+ case 54:
+
+ { yyval.relation = CSSSelector::DirectAdjacent; ;}
+ break;
+
+ case 55:
+
+ { yyval.relation = CSSSelector::IndirectAdjacent; ;}
+ break;
+
+ case 56:
+
+ { yyval.relation = CSSSelector::Child; ;}
+ break;
+
+ case 57:
+
+ { yyval.relation = CSSSelector::Descendant; ;}
+ break;
+
+ case 58:
+
+ { yyval.val = -1; ;}
+ break;
+
+ case 59:
+
+ { yyval.val = 1; ;}
+ break;
+
+ case 60:
+
+ {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "got ruleset" << endl << " selector:" << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-1].selectorList && yyvsp[0].ok && p->numParsedProperties ) {
+ CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement );
+ CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule );
+ rule->setSelector( yyvsp[-1].selectorList );
+ rule->setDeclaration(decl);
+ yyval.rule = rule;
+ } else {
+ yyval.rule = 0;
+ delete yyvsp[-1].selectorList;
+ p->clearProperties();
+ }
+ ;}
+ break;
+
+ case 61:
+
+ {
+ if ( yyvsp[0].selector ) {
+ yyval.selectorList = new TQPtrList<CSSSelector>;
+ yyval.selectorList->setAutoDelete( true );
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got simple selector:" << endl;
+ yyvsp[0].selector->print();
+#endif
+ yyval.selectorList->append( yyvsp[0].selector );
+ tdehtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), yyvsp[0].selector);
+ } else {
+ yyval.selectorList = 0;
+ }
+ ;}
+ break;
+
+ case 62:
+
+ {
+ if ( yyvsp[-3].selectorList && yyvsp[0].selector ) {
+ yyval.selectorList = yyvsp[-3].selectorList;
+ yyval.selectorList->append( yyvsp[0].selector );
+ tdehtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), yyvsp[0].selector);
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got simple selector:" << endl;
+ yyvsp[0].selector->print();
+#endif
+ } else {
+ delete yyvsp[-3].selectorList;
+ delete yyvsp[0].selector;
+ yyval.selectorList = 0;
+ }
+ ;}
+ break;
+
+ case 63:
+
+ {
+ delete yyvsp[-1].selectorList;
+ yyval.selectorList = 0;
+ ;}
+ break;
+
+ case 64:
+
+ {
+ yyval.selector = yyvsp[0].selector;
+ ;}
+ break;
+
+ case 65:
+
+ {
+ if ( !yyvsp[-2].selector || !yyvsp[0].selector ) {
+ delete yyvsp[-2].selector;
+ delete yyvsp[0].selector;
+ yyval.selector = 0;
+ } else {
+ yyval.selector = yyvsp[0].selector;
+ CSSSelector *end = yyvsp[0].selector;
+ while( end->tagHistory )
+ end = end->tagHistory;
+ end->relation = yyvsp[-1].relation;
+ end->tagHistory = yyvsp[-2].selector;
+ }
+ ;}
+ break;
+
+ case 66:
+
+ {
+ delete yyvsp[-1].selector;
+ yyval.selector = 0;
+ ;}
+ break;
+
+ case 67:
+
+ { yyval.string.string = 0; yyval.string.length = 0; ;}
+ break;
+
+ case 68:
+
+ { static unsigned short star = '*'; yyval.string.string = &star; yyval.string.length = 1; ;}
+ break;
+
+ case 69:
+
+ { yyval.string = yyvsp[-1].string; ;}
+ break;
+
+ case 70:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->tag = yyvsp[-1].element;
+ ;}
+ break;
+
+ case 71:
+
+ {
+ yyval.selector = yyvsp[-1].selector;
+ if ( yyval.selector )
+ yyval.selector->tag = yyvsp[-2].element;
+ ;}
+ break;
+
+ case 72:
+
+ {
+ yyval.selector = yyvsp[-1].selector;
+ if ( yyval.selector )
+ yyval.selector->tag = makeId(static_cast<CSSParser*>(parser)->defaultNamespace(), anyLocalName);
+ ;}
+ break;
+
+ case 73:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->tag = yyvsp[-1].element;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace(yyval.selector->tag, domString(yyvsp[-2].string));
+ ;}
+ break;
+
+ case 74:
+
+ {
+ yyval.selector = yyvsp[-1].selector;
+ if (yyval.selector) {
+ yyval.selector->tag = yyvsp[-2].element;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace(yyval.selector->tag, domString(yyvsp[-3].string));
+ }
+ ;}
+ break;
+
+ case 75:
+
+ {
+ yyval.selector = yyvsp[-1].selector;
+ if (yyval.selector) {
+ yyval.selector->tag = makeId(anyNamespace, anyLocalName);
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace(yyval.selector->tag, domString(yyvsp[-2].string));
+ }
+ ;}
+ break;
+
+ case 76:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ DOM::DocumentImpl *doc = p->document();
+ TQString tag = qString(yyvsp[0].string);
+ if ( doc ) {
+ if (doc->isHTMLDocument())
+ tag = tag.lower();
+ const DOMString dtag(tag);
+ yyval.element = makeId(p->defaultNamespace(), doc->getId(NodeImpl::ElementId, dtag.implementation(), false, true));
+ } else {
+ yyval.element = makeId(p->defaultNamespace(), tdehtml::getTagID(tag.lower().ascii(), tag.length()));
+ // this case should never happen - only when loading
+ // the default stylesheet - which must not contain unknown tags
+// assert($$ != 0);
+ }
+ ;}
+ break;
+
+ case 77:
+
+ {
+ yyval.element = makeId(static_cast<CSSParser*>(parser)->defaultNamespace(), anyLocalName);
+ ;}
+ break;
+
+ case 78:
+
+ {
+ yyval.selector = yyvsp[0].selector;
+ yyval.selector->nonCSSHint = static_cast<CSSParser *>(parser)->nonCSSHint;
+ ;}
+ break;
+
+ case 79:
+
+ {
+ yyval.selector = yyvsp[-1].selector;
+ if ( yyval.selector ) {
+ CSSSelector *end = yyvsp[-1].selector;
+ while( end->tagHistory )
+ end = end->tagHistory;
+ end->relation = CSSSelector::SubSelector;
+ end->tagHistory = yyvsp[0].selector;
+ }
+ ;}
+ break;
+
+ case 80:
+
+ {
+ delete yyvsp[-1].selector;
+ yyval.selector = 0;
+ ;}
+ break;
+
+ case 81:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::Id;
+ yyval.selector->attr = ATTR_ID;
+ yyval.selector->value = domString(yyvsp[0].string);
+ ;}
+ break;
+
+ case 85:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::Class;
+ yyval.selector->attr = ATTR_CLASS;
+ yyval.selector->value = domString(yyvsp[0].string);
+ ;}
+ break;
+
+ case 86:
+
+ {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ DOM::DocumentImpl *doc = p->document();
+
+ TQString attr = qString(yyvsp[-1].string);
+ if ( doc ) {
+ if (doc->isHTMLDocument())
+ attr = attr.lower();
+ const DOMString dattr(attr);
+#ifdef APPLE_CHANGES
+ yyval.attribute = doc->attrId(0, dattr.implementation(), false);
+#else
+ yyval.attribute = doc->getId(NodeImpl::AttributeId, dattr.implementation(), false, true);
+#endif
+ } else {
+ yyval.attribute = tdehtml::getAttrID(attr.lower().ascii(), attr.length());
+ // this case should never happen - only when loading
+ // the default stylesheet - which must not contain unknown attributes
+ assert(yyval.attribute != 0);
+ }
+ ;}
+ break;
+
+ case 87:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->attr = yyvsp[-1].attribute;
+ yyval.selector->match = CSSSelector::Set;
+ ;}
+ break;
+
+ case 88:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->attr = yyvsp[-5].attribute;
+ yyval.selector->match = yyvsp[-4].match;
+ yyval.selector->value = domString(yyvsp[-2].string);
+ ;}
+ break;
+
+ case 89:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->attr = yyvsp[-1].attribute;
+ yyval.selector->match = CSSSelector::Set;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace(yyval.selector->attr, domString(yyvsp[-2].string));
+ ;}
+ break;
+
+ case 90:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->attr = yyvsp[-5].attribute;
+ yyval.selector->match = (CSSSelector::Match)yyvsp[-4].match;
+ yyval.selector->value = domString(yyvsp[-2].string);
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace(yyval.selector->attr, domString(yyvsp[-6].string));
+ ;}
+ break;
+
+ case 91:
+
+ {
+ yyval.match = CSSSelector::Exact;
+ ;}
+ break;
+
+ case 92:
+
+ {
+ yyval.match = CSSSelector::List;
+ ;}
+ break;
+
+ case 93:
+
+ {
+ yyval.match = CSSSelector::Hyphen;
+ ;}
+ break;
+
+ case 94:
+
+ {
+ yyval.match = CSSSelector::Begin;
+ ;}
+ break;
+
+ case 95:
+
+ {
+ yyval.match = CSSSelector::End;
+ ;}
+ break;
+
+ case 96:
+
+ {
+ yyval.match = CSSSelector::Contain;
+ ;}
+ break;
+
+ case 99:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->value = domString(yyvsp[0].string);
+ ;}
+ break;
+
+ case 100:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoElement;
+ yyval.selector->value = domString(yyvsp[0].string);
+ ;}
+ break;
+
+ case 101:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->string_arg = domString(yyvsp[-1].string);
+ yyval.selector->value = domString(yyvsp[-2].string);
+ ;}
+ break;
+
+ case 102:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->string_arg = TQString::number(yyvsp[-1].val);
+ yyval.selector->value = domString(yyvsp[-2].string);
+ ;}
+ break;
+
+ case 103:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->string_arg = domString(yyvsp[-1].string);
+ yyval.selector->value = domString(yyvsp[-2].string);
+ ;}
+ break;
+
+ case 104:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->string_arg = domString(yyvsp[-1].string);
+ yyval.selector->value = domString(yyvsp[-2].string);
+ ;}
+ break;
+
+ case 105:
+
+ {
+ yyval.selector = new CSSSelector();
+ yyval.selector->match = CSSSelector::PseudoClass;
+ yyval.selector->simpleSelector = yyvsp[-1].selector;
+ yyval.selector->value = domString(yyvsp[-3].string);
+ ;}
+ break;
+
+ case 106:
+
+ {
+ yyval.ok = yyvsp[-1].ok;
+ ;}
+ break;
+
+ case 107:
+
+ {
+ yyval.ok = false;
+ ;}
+ break;
+
+ case 108:
+
+ {
+ yyval.ok = yyvsp[-1].ok;
+ ;}
+ break;
+
+ case 109:
+
+ {
+ yyval.ok = yyvsp[-2].ok;
+ if ( yyvsp[-1].ok )
+ yyval.ok = yyvsp[-1].ok;
+ ;}
+ break;
+
+ case 110:
+
+ {
+ yyval.ok = yyvsp[-2].ok;
+ ;}
+ break;
+
+ case 111:
+
+ {
+ yyval.ok = yyvsp[-2].ok;
+ ;}
+ break;
+
+ case 112:
+
+ {
+ yyval.ok = false;
+ ;}
+ break;
+
+ case 113:
+
+ {
+ yyval.ok = yyvsp[-3].ok;
+ if ( yyvsp[-2].ok )
+ yyval.ok = yyvsp[-2].ok;
+ ;}
+ break;
+
+ case 114:
+
+ {
+ yyval.ok = yyvsp[-3].ok;
+ ;}
+ break;
+
+ case 115:
+
+ {
+ yyval.ok = false;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( yyvsp[-4].prop_id && yyvsp[-1].valueList ) {
+ p->valueList = yyvsp[-1].valueList;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got property: " << yyvsp[-4].prop_id <<
+ (yyvsp[0].b?" important":"")<< endl;
+#endif
+ bool ok = p->parseValue( yyvsp[-4].prop_id, yyvsp[0].b );
+ if ( ok )
+ yyval.ok = ok;
+#ifdef CSS_DEBUG
+ else
+ kdDebug( 6080 ) << " couldn't parse value!" << endl;
+#endif
+ } else {
+ delete yyvsp[-1].valueList;
+ }
+ delete p->valueList;
+ p->valueList = 0;
+ ;}
+ break;
+
+ case 116:
+
+ {
+ yyval.ok = false;
+ ;}
+ break;
+
+ case 117:
+
+ {
+ TQString str = qString(yyvsp[-1].string);
+ yyval.prop_id = getPropertyID( str.lower().latin1(), str.length() );
+ ;}
+ break;
+
+ case 118:
+
+ { yyval.b = true; ;}
+ break;
+
+ case 119:
+
+ { yyval.b = false; ;}
+ break;
+
+ case 120:
+
+ {
+ yyval.valueList = new ValueList;
+ yyval.valueList->addValue( yyvsp[0].value );
+ ;}
+ break;
+
+ case 121:
+
+ {
+ yyval.valueList = yyvsp[-2].valueList;
+ if ( yyval.valueList ) {
+ if ( yyvsp[-1].tok ) {
+ Value v;
+ v.id = 0;
+ v.unit = Value::Operator;
+ v.iValue = yyvsp[-1].tok;
+ yyval.valueList->addValue( v );
+ }
+ yyval.valueList->addValue( yyvsp[0].value );
+ }
+ ;}
+ break;
+
+ case 122:
+
+ {
+ yyval.tok = '/';
+ ;}
+ break;
+
+ case 123:
+
+ {
+ yyval.tok = ',';
+ ;}
+ break;
+
+ case 124:
+
+ {
+ yyval.tok = 0;
+ ;}
+ break;
+
+ case 125:
+
+ { yyval.value = yyvsp[0].value; ;}
+ break;
+
+ case 126:
+
+ { yyval.value = yyvsp[0].value; yyval.value.fValue *= yyvsp[-1].val; ;}
+ break;
+
+ case 127:
+
+ { yyval.value.id = 0; yyval.value.string = yyvsp[-1].string; yyval.value.unit = CSSPrimitiveValue::CSS_DIMENSION; ;}
+ break;
+
+ case 128:
+
+ { yyval.value.id = 0; yyval.value.string = yyvsp[-1].string; yyval.value.unit = CSSPrimitiveValue::CSS_STRING; ;}
+ break;
+
+ case 129:
+
+ {
+ TQString str = qString( yyvsp[-1].string );
+ yyval.value.id = getValueID( str.lower().latin1(), str.length() );
+ yyval.value.unit = CSSPrimitiveValue::CSS_IDENT;
+ yyval.value.string = yyvsp[-1].string;
+ ;}
+ break;
+
+ case 130:
+
+ { yyval.value.id = 0; yyval.value.string = yyvsp[-1].string; yyval.value.unit = CSSPrimitiveValue::CSS_URI; ;}
+ break;
+
+ case 131:
+
+ { yyval.value.id = 0; yyval.value.iValue = 0; yyval.value.unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ ;}
+ break;
+
+ case 132:
+
+ { yyval.value.id = 0; yyval.value.string = yyvsp[0].string; yyval.value.unit = CSSPrimitiveValue::CSS_RGBCOLOR; ;}
+ break;
+
+ case 133:
+
+ {
+ yyval.value = yyvsp[0].value;
+ ;}
+ break;
+
+ case 134:
+
+ { yyval.value.id = 0; yyval.value.isInt = true; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_NUMBER; ;}
+ break;
+
+ case 135:
+
+ { yyval.value.id = 0; yyval.value.isInt = false; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_NUMBER; ;}
+ break;
+
+ case 136:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_PERCENTAGE; ;}
+ break;
+
+ case 137:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_PX; ;}
+ break;
+
+ case 138:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_CM; ;}
+ break;
+
+ case 139:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_MM; ;}
+ break;
+
+ case 140:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_IN; ;}
+ break;
+
+ case 141:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_PT; ;}
+ break;
+
+ case 142:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_PC; ;}
+ break;
+
+ case 143:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_DEG; ;}
+ break;
+
+ case 144:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_RAD; ;}
+ break;
+
+ case 145:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_GRAD; ;}
+ break;
+
+ case 146:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_MS; ;}
+ break;
+
+ case 147:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_S; ;}
+ break;
+
+ case 148:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_HZ; ;}
+ break;
+
+ case 149:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_KHZ; ;}
+ break;
+
+ case 150:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_EMS; ;}
+ break;
+
+ case 151:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = Value::Q_EMS; ;}
+ break;
+
+ case 152:
+
+ { yyval.value.id = 0; yyval.value.fValue = yyvsp[-1].val; yyval.value.unit = CSSPrimitiveValue::CSS_EXS; ;}
+ break;
+
+ case 153:
+
+ {
+ Function *f = new Function;
+ f->name = yyvsp[-4].string;
+ f->args = yyvsp[-2].valueList;
+ yyval.value.id = 0;
+ yyval.value.unit = Value::Function;
+ yyval.value.function = f;
+ ;}
+ break;
+
+ case 154:
+
+ {
+ Function *f = new Function;
+ f->name = yyvsp[-2].string;
+ f->args = 0;
+ yyval.value.id = 0;
+ yyval.value.unit = Value::Function;
+ yyval.value.function = f;
+ ;}
+ break;
+
+ case 155:
+
+ { yyval.string = yyvsp[-1].string; ;}
+ break;
+
+ case 156:
+
+ {
+ yyval.rule = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
+#endif
+ ;}
+ break;
+
+ case 157:
+
+ {
+ yyval.rule = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
+#endif
+ ;}
+ break;
+
+ case 158:
+
+ {
+ yyval.rule = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid rule" << endl;
+#endif
+ ;}
+ break;
+
+
+ }
+
+/* Line 1010 of yacc.c. */
+
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+
+
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
+ {
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
+ {
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
+
+ if (yycount < 5)
+ {
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
+ }
+ }
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
+ }
+ else
+ yyerror ("syntax error; also virtual memory exhausted");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror ("syntax error");
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[*yyssp], yyvsp);
+ }
+ }
+ else
+ {
+ YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
+ yydestruct (yytoken, &yylval);
+ yychar = YYEMPTY;
+
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
+#endif
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
+ yydestruct (yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ YYDPRINTF ((stderr, "Shifting error token, "));
+
+ *++yyvsp = yylval;
+
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+ return yyresult;
+}
+
+
+
+
+
+
diff --git a/tdehtml/css/parser.h b/tdehtml/css/parser.h
new file mode 100644
index 000000000..e3375db66
--- /dev/null
+++ b/tdehtml/css/parser.h
@@ -0,0 +1,164 @@
+/* A Bison parser, made by GNU Bison 1.875d. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 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.
+*/
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ UNIMPORTANT_TOK = 258,
+ S = 259,
+ SGML_CD = 260,
+ INCLUDES = 261,
+ DASHMATCH = 262,
+ BEGINSWITH = 263,
+ ENDSWITH = 264,
+ CONTAINS = 265,
+ STRING = 266,
+ IDENT = 267,
+ NTH = 268,
+ HASH = 269,
+ IMPORT_SYM = 270,
+ PAGE_SYM = 271,
+ MEDIA_SYM = 272,
+ FONT_FACE_SYM = 273,
+ CHARSET_SYM = 274,
+ NAMESPACE_SYM = 275,
+ KHTML_RULE_SYM = 276,
+ KHTML_DECLS_SYM = 277,
+ KHTML_VALUE_SYM = 278,
+ IMPORTANT_SYM = 279,
+ QEMS = 280,
+ EMS = 281,
+ EXS = 282,
+ PXS = 283,
+ CMS = 284,
+ MMS = 285,
+ INS = 286,
+ PTS = 287,
+ PCS = 288,
+ DEGS = 289,
+ RADS = 290,
+ GRADS = 291,
+ MSECS = 292,
+ SECS = 293,
+ HERZ = 294,
+ KHERZ = 295,
+ DIMEN = 296,
+ PERCENTAGE = 297,
+ FLOAT = 298,
+ INTEGER = 299,
+ URI = 300,
+ FUNCTION = 301,
+ NOTFUNCTION = 302,
+ UNICODERANGE = 303
+ };
+#endif
+#define UNIMPORTANT_TOK 258
+#define S 259
+#define SGML_CD 260
+#define INCLUDES 261
+#define DASHMATCH 262
+#define BEGINSWITH 263
+#define ENDSWITH 264
+#define CONTAINS 265
+#define STRING 266
+#define IDENT 267
+#define NTH 268
+#define HASH 269
+#define IMPORT_SYM 270
+#define PAGE_SYM 271
+#define MEDIA_SYM 272
+#define FONT_FACE_SYM 273
+#define CHARSET_SYM 274
+#define NAMESPACE_SYM 275
+#define KHTML_RULE_SYM 276
+#define KHTML_DECLS_SYM 277
+#define KHTML_VALUE_SYM 278
+#define IMPORTANT_SYM 279
+#define QEMS 280
+#define EMS 281
+#define EXS 282
+#define PXS 283
+#define CMS 284
+#define MMS 285
+#define INS 286
+#define PTS 287
+#define PCS 288
+#define DEGS 289
+#define RADS 290
+#define GRADS 291
+#define MSECS 292
+#define SECS 293
+#define HERZ 294
+#define KHERZ 295
+#define DIMEN 296
+#define PERCENTAGE 297
+#define FLOAT 298
+#define INTEGER 299
+#define URI 300
+#define FUNCTION 301
+#define NOTFUNCTION 302
+#define UNICODERANGE 303
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+
+typedef union YYSTYPE {
+ CSSRuleImpl *rule;
+ CSSSelector *selector;
+ TQPtrList<CSSSelector> *selectorList;
+ bool ok;
+ MediaListImpl *mediaList;
+ CSSMediaRuleImpl *mediaRule;
+ CSSRuleListImpl *ruleList;
+ ParseString string;
+ float val;
+ int prop_id;
+ unsigned int attribute;
+ unsigned int element;
+ unsigned int ns;
+ CSSSelector::Relation relation;
+ CSSSelector::Match match;
+ bool b;
+ char tok;
+ Value value;
+ ValueList *valueList;
+} YYSTYPE;
+/* Line 1285 of yacc.c. */
+
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+
+
diff --git a/tdehtml/css/parser.y b/tdehtml/css/parser.y
new file mode 100644
index 000000000..bb6f915f9
--- /dev/null
+++ b/tdehtml/css/parser.y
@@ -0,0 +1,1064 @@
+%{
+
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (c) 2003 Apple Computer
+ * Copyright (C) 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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+
+#include <dom/dom_string.h>
+#include <xml/dom_docimpl.h>
+#include <css/cssstyleselector.h>
+#include <css/css_ruleimpl.h>
+#include <css/css_stylesheetimpl.h>
+#include <css/css_valueimpl.h>
+#include <misc/htmlhashes.h>
+#include "cssparser.h"
+
+#include <assert.h>
+#include <kdebug.h>
+//#define CSS_DEBUG
+
+using namespace DOM;
+
+//
+// The following file defines the function
+// const struct props *findProp(const char *word, int len)
+//
+// with 'props->id' a CSS property in the range from CSS_PROP_MIN to
+// (and including) CSS_PROP_TOTAL-1
+
+// turn off inlining to void warning with newer gcc
+#undef __inline
+#define __inline
+#include "cssproperties.c"
+#include "cssvalues.c"
+#undef __inline
+
+int DOM::getPropertyID(const char *tagStr, int len)
+{
+ const struct props *propsPtr = findProp(tagStr, len);
+ if (!propsPtr)
+ return 0;
+
+ return propsPtr->id;
+}
+
+static inline int getValueID(const char *tagStr, int len)
+{
+ const struct css_value *val = findValue(tagStr, len);
+ if (!val)
+ return 0;
+
+ return val->id;
+}
+
+
+#define YYDEBUG 0
+#undef YYMAXDEPTH
+#define YYPARSE_PARAM parser
+%}
+
+%pure_parser
+
+%union {
+ CSSRuleImpl *rule;
+ CSSSelector *selector;
+ QPtrList<CSSSelector> *selectorList;
+ bool ok;
+ MediaListImpl *mediaList;
+ CSSMediaRuleImpl *mediaRule;
+ CSSRuleListImpl *ruleList;
+ ParseString string;
+ float val;
+ int prop_id;
+ unsigned int attribute;
+ unsigned int element;
+ unsigned int ns;
+ CSSSelector::Relation relation;
+ CSSSelector::Match match;
+ bool b;
+ char tok;
+ Value value;
+ ValueList *valueList;
+}
+
+%{
+
+static inline int cssyyerror(const char *x )
+{
+#ifdef CSS_DEBUG
+ tqDebug( "%s", x );
+#else
+ Q_UNUSED( x );
+#endif
+ return 1;
+}
+
+static int cssyylex( YYSTYPE *yylval ) {
+ return CSSParser::current()->lex( yylval );
+}
+
+#define null 1
+
+%}
+
+%destructor { delete $$; $$ = 0; } expr;
+%destructor { delete $$; $$ = 0; } maybe_media_list media_list;
+%destructor { delete $$; $$ = 0; } selector_list;
+%destructor { delete $$; $$ = 0; } ruleset_list;
+%destructor { delete $$; $$ = 0; } specifier specifier_list simple_selector selector class attrib pseudo;
+
+%no-lines
+%verbose
+
+%left UNIMPORTANT_TOK
+
+%token S SGML_CD
+
+%token INCLUDES
+%token DASHMATCH
+%token BEGINSWITH
+%token ENDSWITH
+%token CONTAINS
+
+%token <string> STRING
+
+%right <string> IDENT
+
+%token <string> NTH
+
+%nonassoc <string> HASH
+%nonassoc ':'
+%nonassoc '.'
+%nonassoc '['
+%nonassoc '*'
+%nonassoc error
+%left '|'
+
+%left IMPORT_SYM
+%token PAGE_SYM
+%token MEDIA_SYM
+%token FONT_FACE_SYM
+%token CHARSET_SYM
+%token NAMESPACE_SYM
+%token KHTML_RULE_SYM
+%token KHTML_DECLS_SYM
+%token KHTML_VALUE_SYM
+
+%token IMPORTANT_SYM
+
+%token <val> QEMS
+%token <val> EMS
+%token <val> EXS
+%token <val> PXS
+%token <val> CMS
+%token <val> MMS
+%token <val> INS
+%token <val> PTS
+%token <val> PCS
+%token <val> DEGS
+%token <val> RADS
+%token <val> GRADS
+%token <val> MSECS
+%token <val> SECS
+%token <val> HERZ
+%token <val> KHERZ
+%token <string> DIMEN
+%token <val> PERCENTAGE
+%token <val> FLOAT
+%token <val> INTEGER
+
+%token <string> URI
+%token <string> FUNCTION
+%token <string> NOTFUNCTION
+
+%token <string> UNICODERANGE
+
+%type <relation> combinator
+
+%type <rule> ruleset
+%type <rule> media
+%type <rule> import
+%type <rule> page
+%type <rule> font_face
+%type <rule> invalid_rule
+%type <rule> invalid_at
+%type <rule> rule
+
+%type <string> namespace_selector
+
+%type <string> string_or_uri
+%type <string> ident_or_string
+%type <string> medium
+%type <string> hexcolor
+%type <string> maybe_ns_prefix
+
+%type <mediaList> media_list
+%type <mediaList> maybe_media_list
+
+%type <ruleList> ruleset_list
+
+%type <prop_id> property
+
+%type <selector> specifier
+%type <selector> specifier_list
+%type <selector> simple_selector
+%type <selector> selector
+%type <selectorList> selector_list
+%type <selector> class
+%type <selector> attrib
+%type <selector> pseudo
+
+%type <ok> declaration_block
+%type <ok> declaration_list
+%type <ok> declaration
+
+%type <b> prio
+
+%type <match> match
+%type <val> unary_operator
+%type <tok> operator
+
+%type <valueList> expr
+%type <value> term
+%type <value> unary_term
+%type <value> function
+
+%type <element> element_name
+
+%type <attribute> attrib_id
+
+%%
+
+stylesheet:
+ maybe_charset maybe_sgml import_list namespace_list rule_list
+ | tdehtml_rule maybe_space
+ | tdehtml_decls maybe_space
+ | tdehtml_value maybe_space
+ ;
+
+tdehtml_rule:
+ KHTML_RULE_SYM '{' maybe_space ruleset maybe_space '}' {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ p->rule = $4;
+ }
+;
+
+tdehtml_decls:
+ KHTML_DECLS_SYM declaration_block {
+ /* can be empty */
+ }
+;
+
+tdehtml_value:
+ KHTML_VALUE_SYM '{' maybe_space expr '}' {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $4 ) {
+ p->valueList = $4;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got property for " << p->id <<
+ (p->important?" important":"")<< endl;
+ bool ok =
+#endif
+ p->parseValue( p->id, p->important );
+#ifdef CSS_DEBUG
+ if ( !ok )
+ kdDebug( 6080 ) << " couldn't parse value!" << endl;
+#endif
+ }
+#ifdef CSS_DEBUG
+ else
+ kdDebug( 6080 ) << " no value found!" << endl;
+#endif
+ delete p->valueList;
+ p->valueList = 0;
+ }
+;
+
+maybe_space:
+ /* empty */ %prec UNIMPORTANT_TOK
+ | maybe_space S
+ ;
+
+maybe_sgml:
+ /* empty */
+ | maybe_sgml SGML_CD
+ | maybe_sgml S
+ ;
+
+maybe_charset:
+ /* empty */
+ | CHARSET_SYM maybe_space STRING maybe_space ';' {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "charset rule: " << qString($3) << endl;
+#endif
+ }
+ | CHARSET_SYM error invalid_block
+ | CHARSET_SYM error ';'
+ ;
+
+import_list:
+ /* empty */
+ | import_list import maybe_sgml {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $2 && p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ p->styleElement->append( $2 );
+ } else {
+ delete $2;
+ }
+ }
+ ;
+
+import:
+ IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "@import: " << qString($3) << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $5 && p->styleElement && p->styleElement->isCSSStyleSheet() )
+ $$ = new CSSImportRuleImpl( p->styleElement, domString($3), $5 );
+ else
+ $$ = 0;
+ }
+ | IMPORT_SYM error invalid_block {
+ $$ = 0;
+ }
+ | IMPORT_SYM error ';' {
+ $$ = 0;
+ }
+ ;
+
+namespace_list:
+ /* empty */ %prec UNIMPORTANT_TOK
+ | namespace_list namespace maybe_sgml
+;
+
+namespace:
+NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "@namespace: " << qString($4) << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->addNamespace(p, domString($3), domString($4));
+ }
+| NAMESPACE_SYM error invalid_block
+| NAMESPACE_SYM error ';'
+ ;
+
+maybe_ns_prefix:
+/* empty */ { $$.string = 0; }
+| IDENT S { $$ = $1; }
+ ;
+
+rule_list:
+ /* empty */
+ | rule_list rule maybe_sgml {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $2 && p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ p->styleElement->append( $2 );
+ } else {
+ delete $2;
+ }
+ }
+ ;
+
+rule:
+ ruleset
+ | media
+ | page
+ | font_face
+ | invalid_rule
+ | invalid_at
+ | import error { delete $1; $$ = 0; }
+ ;
+
+string_or_uri:
+ STRING
+ | URI
+ ;
+
+maybe_media_list:
+ /* empty */ {
+ $$ = new MediaListImpl();
+ }
+ | media_list
+;
+
+
+media_list:
+ medium {
+ $$ = new MediaListImpl();
+ $$->appendMedium( domString($1).lower() );
+ }
+ | media_list ',' maybe_space medium {
+ $$ = $1;
+ if ($$)
+ $$->appendMedium( domString($4).lower() );
+ }
+ | media_list error {
+ delete $1;
+ $$ = 0;
+ }
+ ;
+
+media:
+ MEDIA_SYM maybe_space media_list '{' maybe_space ruleset_list '}' {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $3 && $6 &&
+ p->styleElement && p->styleElement->isCSSStyleSheet() ) {
+ $$ = new CSSMediaRuleImpl( static_cast<CSSStyleSheetImpl*>(p->styleElement), $3, $6 );
+ } else {
+ $$ = 0;
+ delete $3;
+ delete $6;
+ }
+ }
+ ;
+
+ruleset_list:
+ /* empty */ { $$ = 0; }
+ | ruleset_list ruleset maybe_space {
+ $$ = $1;
+ if ( $2 ) {
+ if ( !$$ ) $$ = new CSSRuleListImpl();
+ $$->append( $2 );
+ }
+ }
+ ;
+
+medium:
+ IDENT maybe_space {
+ $$ = $1;
+ }
+ ;
+
+/*
+page:
+ PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space
+ '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
+ ;
+
+pseudo_page
+ : ':' IDENT
+ ;
+
+font_face
+ : FONT_FACE_SYM maybe_space
+ '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
+ ;
+*/
+
+page:
+ PAGE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | PAGE_SYM error ';' {
+ $$ = 0;
+ }
+ ;
+
+font_face:
+ FONT_FACE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | FONT_FACE_SYM error ';' {
+ $$ = 0;
+ }
+;
+
+combinator:
+ '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
+ | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
+ | '>' maybe_space { $$ = CSSSelector::Child; }
+ | /* empty */ { $$ = CSSSelector::Descendant; }
+ ;
+
+unary_operator:
+ '-' { $$ = -1; }
+ | '+' { $$ = 1; }
+ ;
+
+ruleset:
+ selector_list declaration_block {
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "got ruleset" << endl << " selector:" << endl;
+#endif
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $1 && $2 && p->numParsedProperties ) {
+ CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement );
+ CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule );
+ rule->setSelector( $1 );
+ rule->setDeclaration(decl);
+ $$ = rule;
+ } else {
+ $$ = 0;
+ delete $1;
+ p->clearProperties();
+ }
+ }
+ ;
+
+selector_list:
+ selector %prec UNIMPORTANT_TOK {
+ if ( $1 ) {
+ $$ = new QPtrList<CSSSelector>;
+ $$->setAutoDelete( true );
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got simple selector:" << endl;
+ $1->print();
+#endif
+ $$->append( $1 );
+ tdehtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), $1);
+ } else {
+ $$ = 0;
+ }
+ }
+ | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
+ if ( $1 && $4 ) {
+ $$ = $1;
+ $$->append( $4 );
+ tdehtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast<CSSParser *>(parser)->document(), $4);
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got simple selector:" << endl;
+ $4->print();
+#endif
+ } else {
+ delete $1;
+ delete $4;
+ $$ = 0;
+ }
+ }
+ | selector_list error {
+ delete $1;
+ $$ = 0;
+ }
+ ;
+
+selector:
+ simple_selector {
+ $$ = $1;
+ }
+ | selector combinator simple_selector {
+ if ( !$1 || !$3 ) {
+ delete $1;
+ delete $3;
+ $$ = 0;
+ } else {
+ $$ = $3;
+ CSSSelector *end = $3;
+ while( end->tagHistory )
+ end = end->tagHistory;
+ end->relation = $2;
+ end->tagHistory = $1;
+ }
+ }
+ | selector error {
+ delete $1;
+ $$ = 0;
+ }
+ ;
+
+namespace_selector:
+ /* empty */ '|' { $$.string = 0; $$.length = 0; }
+ | '*' '|' { static unsigned short star = '*'; $$.string = &star; $$.length = 1; }
+ | IDENT '|' { $$ = $1; }
+;
+
+simple_selector:
+ element_name maybe_space {
+ $$ = new CSSSelector();
+ $$->tag = $1;
+ }
+ | element_name specifier_list maybe_space {
+ $$ = $2;
+ if ( $$ )
+ $$->tag = $1;
+ }
+ | specifier_list maybe_space {
+ $$ = $1;
+ if ( $$ )
+ $$->tag = makeId(static_cast<CSSParser*>(parser)->defaultNamespace(), anyLocalName);
+ }
+ | namespace_selector element_name maybe_space {
+ $$ = new CSSSelector();
+ $$->tag = $2;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
+ }
+ | namespace_selector element_name specifier_list maybe_space {
+ $$ = $3;
+ if ($$) {
+ $$->tag = $2;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
+ }
+ }
+ | namespace_selector specifier_list maybe_space {
+ $$ = $2;
+ if ($$) {
+ $$->tag = makeId(anyNamespace, anyLocalName);
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->tag, domString($1));
+ }
+ }
+ ;
+
+element_name:
+ IDENT {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ DOM::DocumentImpl *doc = p->document();
+ QString tag = qString($1);
+ if ( doc ) {
+ if (doc->isHTMLDocument())
+ tag = tag.lower();
+ const DOMString dtag(tag);
+ $$ = makeId(p->defaultNamespace(), doc->getId(NodeImpl::ElementId, dtag.implementation(), false, true));
+ } else {
+ $$ = makeId(p->defaultNamespace(), tdehtml::getTagID(tag.lower().ascii(), tag.length()));
+ // this case should never happen - only when loading
+ // the default stylesheet - which must not contain unknown tags
+// assert($$ != 0);
+ }
+ }
+ | '*' {
+ $$ = makeId(static_cast<CSSParser*>(parser)->defaultNamespace(), anyLocalName);
+ }
+ ;
+
+specifier_list:
+ specifier {
+ $$ = $1;
+ $$->nonCSSHint = static_cast<CSSParser *>(parser)->nonCSSHint;
+ }
+ | specifier_list specifier {
+ $$ = $1;
+ if ( $$ ) {
+ CSSSelector *end = $1;
+ while( end->tagHistory )
+ end = end->tagHistory;
+ end->relation = CSSSelector::SubSelector;
+ end->tagHistory = $2;
+ }
+ }
+ | specifier_list error {
+ delete $1;
+ $$ = 0;
+ }
+;
+
+specifier:
+ HASH {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::Id;
+ $$->attr = ATTR_ID;
+ $$->value = domString($1);
+ }
+ | class
+ | attrib
+ | pseudo
+ ;
+
+class:
+ '.' IDENT {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::Class;
+ $$->attr = ATTR_CLASS;
+ $$->value = domString($2);
+ }
+ ;
+
+attrib_id:
+ IDENT maybe_space {
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ DOM::DocumentImpl *doc = p->document();
+
+ QString attr = qString($1);
+ if ( doc ) {
+ if (doc->isHTMLDocument())
+ attr = attr.lower();
+ const DOMString dattr(attr);
+#ifdef APPLE_CHANGES
+ $$ = doc->attrId(0, dattr.implementation(), false);
+#else
+ $$ = doc->getId(NodeImpl::AttributeId, dattr.implementation(), false, true);
+#endif
+ } else {
+ $$ = tdehtml::getAttrID(attr.lower().ascii(), attr.length());
+ // this case should never happen - only when loading
+ // the default stylesheet - which must not contain unknown attributes
+ assert($$ != 0);
+ }
+ }
+ ;
+
+attrib:
+ '[' maybe_space attrib_id ']' {
+ $$ = new CSSSelector();
+ $$->attr = $3;
+ $$->match = CSSSelector::Set;
+ }
+ | '[' maybe_space attrib_id match maybe_space ident_or_string maybe_space ']' {
+ $$ = new CSSSelector();
+ $$->attr = $3;
+ $$->match = $4;
+ $$->value = domString($6);
+ }
+ | '[' maybe_space namespace_selector attrib_id ']' {
+ $$ = new CSSSelector();
+ $$->attr = $4;
+ $$->match = CSSSelector::Set;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attr, domString($3));
+ }
+ | '[' maybe_space namespace_selector attrib_id match maybe_space ident_or_string maybe_space ']' {
+ $$ = new CSSSelector();
+ $$->attr = $4;
+ $$->match = (CSSSelector::Match)$5;
+ $$->value = domString($7);
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if (p->styleElement && p->styleElement->isCSSStyleSheet())
+ static_cast<CSSStyleSheetImpl*>(p->styleElement)->determineNamespace($$->attr, domString($3));
+ }
+ ;
+
+match:
+ '=' {
+ $$ = CSSSelector::Exact;
+ }
+ | INCLUDES {
+ $$ = CSSSelector::List;
+ }
+ | DASHMATCH {
+ $$ = CSSSelector::Hyphen;
+ }
+ | BEGINSWITH {
+ $$ = CSSSelector::Begin;
+ }
+ | ENDSWITH {
+ $$ = CSSSelector::End;
+ }
+ | CONTAINS {
+ $$ = CSSSelector::Contain;
+ }
+ ;
+
+ident_or_string:
+ IDENT
+ | STRING
+ ;
+
+pseudo:
+ ':' IDENT {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->value = domString($2);
+ }
+ |
+ ':' ':' IDENT {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoElement;
+ $$->value = domString($3);
+ }
+ // used by :nth-*
+ | ':' FUNCTION NTH ')' {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->string_arg = domString($3);
+ $$->value = domString($2);
+ }
+ // used by :nth-*
+ | ':' FUNCTION INTEGER ')' {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->string_arg = QString::number($3);
+ $$->value = domString($2);
+ }
+ // used by :nth-* and :lang
+ | ':' FUNCTION IDENT ')' {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->string_arg = domString($3);
+ $$->value = domString($2);
+ }
+ // used by :contains
+ | ':' FUNCTION STRING ')' {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->string_arg = domString($3);
+ $$->value = domString($2);
+ }
+ // used only by :not
+ | ':' NOTFUNCTION maybe_space simple_selector ')' {
+ $$ = new CSSSelector();
+ $$->match = CSSSelector::PseudoClass;
+ $$->simpleSelector = $4;
+ $$->value = domString($2);
+ }
+ ;
+
+declaration_block:
+ '{' maybe_space declaration '}' {
+ $$ = $3;
+ }
+ | '{' maybe_space error '}' {
+ $$ = false;
+ }
+ | '{' maybe_space declaration_list '}' {
+ $$ = $3;
+ }
+ | '{' maybe_space declaration_list declaration '}' {
+ $$ = $3;
+ if ( $4 )
+ $$ = $4;
+ }
+ | '{' maybe_space declaration_list error '}' {
+ $$ = $3;
+ }
+ ;
+
+declaration_list:
+ declaration ';' maybe_space {
+ $$ = $1;
+ }
+ |
+ error ';' maybe_space {
+ $$ = false;
+ }
+ | declaration_list declaration ';' maybe_space {
+ $$ = $1;
+ if ( $2 )
+ $$ = $2;
+ }
+ | declaration_list error ';' maybe_space {
+ $$ = $1;
+ }
+ ;
+
+declaration:
+ property ':' maybe_space expr prio {
+ $$ = false;
+ CSSParser *p = static_cast<CSSParser *>(parser);
+ if ( $1 && $4 ) {
+ p->valueList = $4;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << " got property: " << $1 <<
+ ($5?" important":"")<< endl;
+#endif
+ bool ok = p->parseValue( $1, $5 );
+ if ( ok )
+ $$ = ok;
+#ifdef CSS_DEBUG
+ else
+ kdDebug( 6080 ) << " couldn't parse value!" << endl;
+#endif
+ } else {
+ delete $4;
+ }
+ delete p->valueList;
+ p->valueList = 0;
+ }
+ | error invalid_block {
+ $$ = false;
+ }
+ ;
+
+property:
+ IDENT maybe_space {
+ QString str = qString($1);
+ $$ = getPropertyID( str.lower().latin1(), str.length() );
+ }
+ ;
+
+prio:
+ IMPORTANT_SYM maybe_space { $$ = true; }
+ | /* empty */ { $$ = false; }
+ ;
+
+expr:
+ term {
+ $$ = new ValueList;
+ $$->addValue( $1 );
+ }
+ | expr operator term {
+ $$ = $1;
+ if ( $$ ) {
+ if ( $2 ) {
+ Value v;
+ v.id = 0;
+ v.unit = Value::Operator;
+ v.iValue = $2;
+ $$->addValue( v );
+ }
+ $$->addValue( $3 );
+ }
+ }
+ ;
+
+operator:
+ '/' maybe_space {
+ $$ = '/';
+ }
+ | ',' maybe_space {
+ $$ = ',';
+ }
+ | /* empty */ {
+ $$ = 0;
+ }
+ ;
+
+term:
+ unary_term { $$ = $1; }
+ | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
+ /* DIMEN is an unary_term, but since we store the string we must not modify fValue */
+ | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
+ | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
+ | IDENT maybe_space {
+ QString str = qString( $1 );
+ $$.id = getValueID( str.lower().latin1(), str.length() );
+ $$.unit = CSSPrimitiveValue::CSS_IDENT;
+ $$.string = $1;
+ }
+ | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
+ | UNICODERANGE maybe_space { $$.id = 0; $$.iValue = 0; $$.unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ }
+ | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR; }
+/* ### according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
+ | function {
+ $$ = $1;
+ }
+ ;
+
+unary_term:
+ INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | FLOAT maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
+ | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
+ | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
+ | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
+ | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
+ | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
+ | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
+ | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
+ | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
+ | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
+ | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
+ | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
+ | HERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
+ | KHERZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
+ | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
+ | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS; }
+ | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
+ ;
+
+
+function:
+ FUNCTION maybe_space expr ')' maybe_space {
+ Function *f = new Function;
+ f->name = $1;
+ f->args = $3;
+ $$.id = 0;
+ $$.unit = Value::Function;
+ $$.function = f;
+ }
+ | FUNCTION maybe_space error {
+ Function *f = new Function;
+ f->name = $1;
+ f->args = 0;
+ $$.id = 0;
+ $$.unit = Value::Function;
+ $$.function = f;
+ }
+
+ ;
+/*
+ * There is a constraint on the color that it must
+ * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
+ * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
+ */
+hexcolor:
+ HASH maybe_space { $$ = $1; }
+ ;
+
+
+/* error handling rules */
+
+invalid_at:
+ '@' error invalid_block {
+ $$ = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
+#endif
+ }
+ | '@' error ';' {
+ $$ = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid @-rule" << endl;
+#endif
+ }
+ ;
+
+invalid_rule:
+ error invalid_block {
+ $$ = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid rule" << endl;
+#endif
+ }
+/*
+ Seems like the two rules below are trying too much and violating
+ http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
+
+ | error ';' {
+ $$ = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid rule" << endl;
+#endif
+ }
+ | error '}' {
+ $$ = 0;
+#ifdef CSS_DEBUG
+ kdDebug( 6080 ) << "skipped invalid rule" << endl;
+#endif
+ }
+*/
+ ;
+
+invalid_block:
+ '{' error invalid_block_list error '}'
+ | '{' error '}'
+ ;
+
+invalid_block_list:
+ invalid_block
+ | invalid_block_list error invalid_block
+;
+
+%%
+
diff --git a/tdehtml/css/quirks.css b/tdehtml/css/quirks.css
new file mode 100644
index 000000000..b979b77c9
--- /dev/null
+++ b/tdehtml/css/quirks.css
@@ -0,0 +1,41 @@
+/*
+ * This style sheet is used by tdehtml to render HTML pages in quirks mode
+ * (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ *
+ * Konqueror/tdehtml relies on the existence of this style sheet for
+ * rendering. Do not remove or modify this file unless you know
+ * what you are doing.
+ */
+
+/* Give floated images margins of 3px */
+img[align="left"] {
+ margin-right: 3px;
+}
+
+img[align="right"] {
+ margin-left: 3px;
+}
+
+/* Tables reset both line-height and white-space in quirks mode.
+ Compatible with WinIE. For some reason they don't reset font-family */
+table {
+ white-space: normal;
+ line-height: normal;
+ color: -tdehtml-text;
+ font-size: medium;
+ empty-cells: hide;
+ text-align: -tdehtml-auto;
+ font-weight: initial;
+}
+
+LAYER {
+ position: absolute;
+}
+
+DIV > LAYER {
+ position: static;
+}
+
+ILAYER > LAYER {
+ position: relative;
+} \ No newline at end of file
diff --git a/tdehtml/css/tokenizer.cpp b/tdehtml/css/tokenizer.cpp
new file mode 100644
index 000000000..493a98032
--- /dev/null
+++ b/tdehtml/css/tokenizer.cpp
@@ -0,0 +1,930 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2003 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.
+ */
+
+/* This file is mostly data generated by flex. Unfortunately flex
+ can't handle 16bit strings directly, so we just copy the part of
+ the code we need and modify it to our needs.
+
+ Most of the defines below are to make sure we can easily use the
+ flex generated code, using as little editing as possible.
+
+ The flex syntax to generate the lexer are more or less directly
+ copied from the CSS2.1 specs, with some fixes for comments and
+ the important symbol.
+
+ To regenerate, run flex on tokenizer.flex. After this, copy the
+ data tables and the YY_DECL method over to this file. Remove the
+ init code from YY_DECL and change the YY_END_OF_BUFFER to only call
+ yyterminate().
+
+*/
+
+// --------- begin generated code -------------------
+#define YY_NUM_RULES 51
+#define YY_END_OF_BUFFER 52
+static yyconst short int yy_accept[331] =
+ { 0,
+ 0, 0, 52, 50, 2, 2, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 42, 50, 50, 50, 50,
+ 11, 11, 11, 50, 50, 2, 0, 0, 0, 10,
+ 0, 13, 0, 8, 0, 0, 9, 0, 0, 0,
+ 11, 11, 43, 0, 41, 0, 0, 42, 0, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 12,
+ 40, 40, 37, 0, 0, 0, 0, 0, 0, 0,
+ 0, 11, 11, 7, 47, 11, 0, 0, 11, 11,
+ 0, 11, 6, 5, 0, 0, 0, 10, 0, 0,
+ 13, 13, 0, 0, 10, 0, 0, 4, 12, 0,
+
+ 0, 40, 40, 40, 0, 40, 28, 40, 24, 26,
+ 40, 38, 30, 40, 29, 36, 40, 32, 31, 27,
+ 40, 0, 0, 0, 0, 0, 0, 0, 0, 11,
+ 11, 11, 12, 11, 11, 48, 48, 11, 0, 0,
+ 0, 13, 0, 0, 0, 1, 40, 40, 40, 40,
+ 33, 40, 39, 12, 34, 3, 0, 0, 0, 0,
+ 0, 0, 0, 11, 11, 44, 0, 48, 48, 48,
+ 47, 0, 0, 13, 0, 0, 0, 40, 40, 40,
+ 35, 0, 0, 0, 0, 0, 0, 15, 11, 11,
+ 49, 48, 48, 48, 48, 0, 0, 0, 0, 46,
+
+ 0, 0, 0, 13, 0, 40, 40, 25, 0, 0,
+ 0, 0, 16, 0, 11, 11, 49, 48, 48, 48,
+ 48, 48, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 46, 0, 0, 0, 0, 13, 0, 40, 40,
+ 0, 0, 0, 14, 0, 11, 11, 49, 48, 48,
+ 48, 48, 48, 48, 0, 45, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 40, 40, 0, 18, 0, 0, 11, 49, 48,
+ 48, 48, 48, 48, 48, 48, 0, 45, 0, 0,
+ 0, 45, 0, 0, 0, 0, 40, 0, 0, 0,
+
+ 0, 0, 49, 0, 0, 0, 23, 0, 0, 0,
+ 17, 19, 49, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 20, 0, 0, 0, 21, 22, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 4, 5, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 12, 18, 19, 20, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 12, 12, 22,
+ 23, 24, 25, 26, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 39, 52, 39, 53,
+ 12, 27, 12, 28, 29, 12, 30, 31, 32, 33,
+
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 39, 52,
+ 39, 53, 12, 54, 12, 55, 1, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56
+ } ;
+
+static yyconst int yy_meta[57] =
+ { 0,
+ 1, 2, 3, 3, 3, 4, 4, 4, 4, 4,
+ 4, 4, 4, 5, 4, 4, 4, 6, 4, 4,
+ 6, 4, 4, 4, 7, 4, 8, 4, 8, 9,
+ 9, 9, 9, 9, 9, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 4, 4, 8
+ } ;
+
+static yyconst short int yy_base[359] =
+ { 0,
+ 0, 0, 807, 1638, 55, 60, 65, 64, 779, 781,
+ 60, 780, 56, 781, 785, 93, 793, 63, 126, 773,
+ 61, 75, 136, 772, 771, 162, 167, 751, 70, 1638,
+ 204, 764, 154, 1638, 63, 238, 1638, 760, 64, 160,
+ 82, 183, 133, 767, 1638, 755, 760, 0, 183, 53,
+ 753, 52, 83, 169, 135, 121, 57, 192, 205, 206,
+ 225, 86, 745, 752, 729, 731, 723, 716, 723, 726,
+ 725, 231, 276, 1638, 1638, 234, 254, 733, 235, 249,
+ 291, 277, 1638, 1638, 701, 195, 172, 219, 325, 359,
+ 717, 393, 217, 237, 286, 427, 461, 1638, 160, 727,
+
+ 135, 715, 495, 714, 344, 256, 700, 265, 699, 698,
+ 88, 697, 696, 175, 695, 694, 233, 693, 679, 678,
+ 267, 684, 664, 670, 656, 640, 651, 622, 627, 446,
+ 305, 529, 639, 320, 321, 318, 634, 323, 614, 287,
+ 521, 536, 326, 544, 641, 1638, 551, 621, 585, 311,
+ 619, 339, 618, 360, 617, 1638, 594, 582, 556, 559,
+ 564, 567, 566, 577, 592, 1638, 600, 324, 574, 572,
+ 634, 549, 620, 635, 641, 579, 324, 656, 662, 278,
+ 567, 551, 544, 562, 526, 528, 501, 1638, 677, 683,
+ 698, 382, 523, 522, 521, 732, 758, 288, 341, 1638,
+
+ 784, 496, 718, 744, 791, 799, 806, 517, 502, 489,
+ 486, 471, 1638, 474, 814, 821, 829, 383, 493, 485,
+ 484, 481, 400, 343, 407, 863, 356, 897, 931, 957,
+ 983, 1009, 1035, 1069, 475, 848, 882, 917, 943, 969,
+ 486, 453, 460, 1638, 445, 995, 1076, 1084, 416, 448,
+ 447, 444, 443, 426, 440, 1638, 444, 408, 509, 1118,
+ 1152, 601, 358, 1131, 1186, 1220, 1205, 407, 1227, 1235,
+ 1242, 481, 1250, 456, 1638, 417, 406, 535, 1257, 403,
+ 1638, 1638, 1638, 1638, 1638, 1638, 1049, 409, 410, 1265,
+ 1299, 426, 443, 1285, 1300, 370, 676, 354, 334, 352,
+
+ 339, 283, 1306, 1321, 1327, 1342, 1638, 261, 226, 225,
+ 1638, 1638, 1638, 1348, 1363, 1369, 214, 192, 129, 1384,
+ 1390, 1405, 73, 1638, 52, 1411, 1426, 1638, 1638, 1638,
+ 1460, 1464, 1472, 1476, 1482, 1487, 1495, 1501, 1509, 1518,
+ 1520, 1526, 1530, 1536, 1545, 1551, 1555, 1564, 1568, 1576,
+ 1580, 1588, 1596, 1604, 1608, 1616, 1624, 1628
+ } ;
+
+static yyconst short int yy_def[359] =
+ { 0,
+ 330, 1, 330, 330, 330, 330, 330, 331, 332, 330,
+ 333, 330, 334, 330, 330, 330, 330, 330, 335, 330,
+ 336, 336, 336, 330, 330, 330, 330, 330, 331, 330,
+ 337, 332, 338, 330, 333, 339, 330, 330, 330, 335,
+ 336, 336, 16, 340, 330, 341, 330, 16, 342, 343,
+ 343, 343, 343, 343, 343, 343, 343, 343, 343, 343,
+ 343, 343, 343, 330, 330, 330, 330, 330, 330, 330,
+ 330, 336, 336, 330, 330, 336, 344, 330, 336, 336,
+ 330, 336, 330, 330, 330, 331, 331, 331, 331, 337,
+ 332, 332, 333, 333, 333, 333, 339, 330, 330, 340,
+
+ 345, 343, 343, 343, 346, 343, 343, 343, 343, 343,
+ 343, 343, 343, 343, 343, 343, 343, 343, 343, 343,
+ 343, 330, 330, 330, 330, 330, 330, 330, 330, 73,
+ 336, 73, 330, 336, 336, 347, 330, 336, 330, 331,
+ 89, 92, 333, 96, 348, 330, 103, 343, 103, 343,
+ 343, 343, 343, 343, 343, 330, 330, 330, 330, 330,
+ 330, 330, 330, 73, 132, 330, 330, 349, 330, 330,
+ 350, 330, 89, 92, 96, 348, 345, 103, 149, 343,
+ 343, 330, 330, 330, 330, 330, 330, 330, 73, 132,
+ 330, 351, 330, 330, 330, 350, 350, 352, 353, 330,
+
+ 354, 330, 89, 92, 96, 103, 149, 343, 330, 330,
+ 330, 330, 330, 330, 73, 132, 330, 355, 330, 330,
+ 330, 330, 330, 352, 330, 356, 353, 357, 350, 350,
+ 350, 350, 350, 354, 330, 89, 92, 96, 103, 149,
+ 330, 330, 330, 330, 330, 73, 132, 330, 358, 330,
+ 330, 330, 330, 330, 330, 330, 352, 352, 352, 352,
+ 356, 353, 353, 353, 353, 357, 233, 330, 89, 92,
+ 96, 343, 149, 330, 330, 330, 330, 246, 330, 330,
+ 330, 330, 330, 330, 330, 330, 352, 352, 352, 260,
+ 353, 353, 353, 265, 233, 330, 343, 330, 330, 330,
+
+ 330, 330, 330, 260, 265, 233, 330, 330, 330, 330,
+ 330, 330, 330, 260, 265, 233, 330, 330, 330, 260,
+ 265, 233, 330, 330, 330, 260, 265, 330, 330, 0,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330
+ } ;
+
+static yyconst short int yy_nxt[1695] =
+ { 0,
+ 4, 5, 6, 5, 5, 5, 7, 8, 9, 10,
+ 4, 4, 11, 4, 4, 12, 4, 13, 14, 15,
+ 16, 17, 4, 4, 4, 18, 19, 20, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 22, 21, 21, 21, 21, 21, 21, 23,
+ 21, 21, 21, 24, 25, 21, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 27, 27, 27, 27,
+ 27, 30, 30, 38, 75, 30, 39, 30, 105, 105,
+ 65, 106, 40, 105, 39, 329, 36, 77, 75, 36,
+ 31, 78, 79, 107, 66, 75, 31, 67, 42, 113,
+
+ 68, 77, 28, 45, 69, 70, 99, 71, 77, 105,
+ 46, 47, 105, 48, 105, 121, 108, 152, 80, 49,
+ 328, 50, 51, 51, 52, 53, 54, 51, 55, 56,
+ 57, 51, 58, 51, 59, 60, 51, 61, 51, 62,
+ 63, 51, 51, 51, 51, 51, 73, 105, 51, 75,
+ 101, 330, 81, 43, 146, 73, 73, 73, 73, 73,
+ 73, 105, 77, 26, 26, 26, 26, 26, 27, 27,
+ 27, 27, 27, 112, 92, 51, 78, 78, 325, 30,
+ 73, 111, 82, 92, 92, 92, 92, 92, 92, 73,
+ 73, 73, 73, 73, 73, 105, 75, 29, 31, 78,
+
+ 79, 105, 30, 103, 28, 29, 29, 29, 86, 77,
+ 109, 88, 103, 103, 103, 103, 103, 103, 105, 35,
+ 110, 31, 78, 117, 89, 324, 30, 153, 114, 30,
+ 90, 105, 105, 89, 89, 89, 89, 89, 89, 35,
+ 35, 35, 93, 36, 75, 31, 115, 75, 75, 30,
+ 95, 105, 116, 154, 323, 134, 118, 77, 96, 105,
+ 77, 77, 75, 36, 97, 319, 318, 96, 96, 96,
+ 96, 96, 96, 119, 132, 77, 120, 72, 72, 72,
+ 72, 72, 105, 132, 132, 132, 132, 132, 132, 75,
+ 75, 105, 317, 105, 30, 225, 130, 135, 30, 155,
+
+ 151, 150, 77, 77, 105, 130, 130, 130, 130, 130,
+ 130, 136, 36, 31, 226, 137, 312, 138, 75, 208,
+ 136, 136, 136, 136, 136, 136, 87, 140, 140, 140,
+ 87, 77, 30, 75, 166, 167, 171, 105, 30, 177,
+ 134, 167, 169, 146, 180, 141, 77, 77, 193, 77,
+ 225, 31, 36, 225, 141, 141, 141, 141, 141, 141,
+ 29, 29, 29, 86, 149, 105, 88, 228, 225, 226,
+ 225, 181, 311, 149, 149, 149, 149, 149, 149, 89,
+ 154, 310, 228, 309, 228, 90, 105, 308, 89, 89,
+ 89, 89, 89, 89, 91, 91, 91, 91, 91, 167,
+
+ 167, 223, 223, 223, 223, 223, 219, 250, 255, 255,
+ 255, 255, 255, 142, 200, 225, 225, 225, 307, 33,
+ 167, 256, 142, 142, 142, 142, 142, 142, 94, 143,
+ 143, 143, 94, 167, 226, 226, 226, 302, 225, 30,
+ 281, 255, 255, 255, 255, 255, 224, 144, 301, 296,
+ 286, 225, 228, 36, 256, 225, 144, 144, 144, 144,
+ 144, 144, 35, 35, 35, 93, 164, 285, 284, 228,
+ 226, 283, 282, 95, 277, 164, 164, 164, 164, 164,
+ 164, 96, 102, 102, 102, 102, 102, 97, 298, 276,
+ 96, 96, 96, 96, 96, 96, 102, 102, 102, 102,
+
+ 102, 275, 299, 274, 268, 254, 300, 105, 253, 252,
+ 287, 255, 255, 255, 287, 147, 225, 251, 245, 244,
+ 243, 105, 242, 288, 147, 147, 147, 147, 147, 147,
+ 131, 131, 131, 131, 131, 226, 131, 131, 131, 131,
+ 131, 173, 241, 105, 235, 222, 221, 220, 214, 165,
+ 173, 173, 173, 173, 173, 173, 174, 213, 165, 165,
+ 165, 165, 165, 165, 175, 174, 174, 174, 174, 174,
+ 174, 178, 212, 175, 175, 175, 175, 175, 175, 211,
+ 178, 178, 178, 178, 178, 178, 148, 148, 148, 148,
+ 148, 210, 209, 105, 177, 202, 195, 189, 194, 188,
+
+ 187, 186, 185, 227, 184, 179, 189, 189, 189, 189,
+ 189, 189, 190, 225, 179, 179, 179, 179, 179, 179,
+ 191, 190, 190, 190, 190, 190, 190, 228, 183, 191,
+ 191, 191, 191, 191, 191, 196, 196, 196, 196, 196,
+ 203, 198, 182, 105, 105, 105, 199, 105, 200, 203,
+ 203, 203, 203, 203, 203, 204, 177, 172, 170, 133,
+ 201, 205, 163, 162, 204, 204, 204, 204, 204, 204,
+ 205, 205, 205, 205, 205, 205, 206, 148, 148, 148,
+ 148, 148, 207, 161, 160, 206, 206, 206, 206, 206,
+ 206, 207, 207, 207, 207, 207, 207, 215, 159, 158,
+
+ 157, 156, 105, 216, 105, 105, 215, 215, 215, 215,
+ 215, 215, 216, 216, 216, 216, 216, 216, 217, 105,
+ 105, 105, 105, 105, 105, 105, 105, 217, 217, 217,
+ 217, 217, 217, 196, 196, 196, 196, 196, 236, 198,
+ 105, 105, 101, 33, 199, 139, 200, 236, 236, 236,
+ 236, 236, 236, 133, 129, 128, 127, 126, 201, 223,
+ 223, 223, 223, 223, 237, 330, 125, 124, 123, 122,
+ 330, 105, 200, 237, 237, 237, 237, 237, 237, 105,
+ 43, 49, 101, 98, 201, 223, 223, 223, 223, 229,
+ 33, 231, 85, 84, 83, 74, 231, 231, 232, 64,
+
+ 44, 43, 37, 34, 233, 33, 330, 330, 330, 330,
+ 234, 238, 330, 233, 233, 233, 233, 233, 233, 239,
+ 238, 238, 238, 238, 238, 238, 240, 330, 239, 239,
+ 239, 239, 239, 239, 246, 240, 240, 240, 240, 240,
+ 240, 247, 330, 246, 246, 246, 246, 246, 246, 248,
+ 247, 247, 247, 247, 247, 247, 330, 330, 248, 248,
+ 248, 248, 248, 248, 224, 224, 224, 257, 269, 330,
+ 259, 330, 330, 330, 330, 330, 330, 269, 269, 269,
+ 269, 269, 269, 260, 330, 330, 330, 330, 330, 261,
+ 330, 330, 260, 260, 260, 260, 260, 260, 227, 227,
+
+ 227, 262, 270, 330, 330, 330, 330, 330, 330, 264,
+ 330, 270, 270, 270, 270, 270, 270, 265, 330, 330,
+ 330, 330, 330, 266, 330, 330, 265, 265, 265, 265,
+ 265, 265, 223, 223, 223, 223, 223, 271, 330, 330,
+ 330, 330, 330, 330, 330, 200, 271, 271, 271, 271,
+ 271, 271, 330, 330, 330, 330, 330, 201, 223, 223,
+ 223, 223, 223, 272, 330, 330, 330, 330, 330, 330,
+ 330, 200, 272, 272, 272, 272, 272, 272, 330, 330,
+ 330, 330, 330, 201, 223, 223, 223, 223, 223, 273,
+ 330, 330, 330, 330, 330, 330, 330, 200, 273, 273,
+
+ 273, 273, 273, 273, 330, 330, 330, 330, 330, 201,
+ 223, 223, 223, 223, 223, 76, 330, 330, 330, 330,
+ 330, 330, 330, 200, 76, 76, 76, 76, 76, 76,
+ 330, 330, 330, 330, 330, 201, 229, 229, 229, 229,
+ 229, 330, 330, 330, 330, 330, 330, 330, 330, 200,
+ 287, 255, 255, 255, 287, 267, 225, 330, 330, 330,
+ 330, 201, 330, 288, 267, 267, 267, 267, 267, 267,
+ 223, 223, 223, 223, 229, 226, 231, 330, 330, 330,
+ 330, 231, 231, 232, 330, 330, 330, 330, 330, 233,
+ 330, 330, 330, 330, 330, 234, 278, 330, 233, 233,
+
+ 233, 233, 233, 233, 279, 278, 278, 278, 278, 278,
+ 278, 330, 330, 279, 279, 279, 279, 279, 279, 258,
+ 289, 289, 289, 258, 330, 225, 330, 330, 330, 330,
+ 330, 330, 291, 255, 255, 255, 291, 330, 290, 330,
+ 330, 330, 330, 225, 226, 292, 330, 290, 290, 290,
+ 290, 290, 290, 224, 224, 224, 257, 228, 330, 259,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 260, 330, 330, 330, 330, 330, 261, 330,
+ 330, 260, 260, 260, 260, 260, 260, 263, 293, 293,
+ 293, 263, 330, 330, 330, 330, 330, 330, 225, 330,
+
+ 330, 330, 330, 330, 330, 330, 294, 330, 330, 330,
+ 330, 330, 228, 330, 330, 294, 294, 294, 294, 294,
+ 294, 227, 227, 227, 262, 295, 330, 330, 330, 330,
+ 330, 330, 264, 330, 295, 295, 295, 295, 295, 295,
+ 265, 330, 330, 330, 330, 330, 266, 29, 330, 265,
+ 265, 265, 265, 265, 265, 32, 29, 29, 29, 29,
+ 29, 29, 35, 330, 32, 32, 32, 32, 32, 32,
+ 297, 35, 35, 35, 35, 35, 35, 303, 330, 297,
+ 297, 297, 297, 297, 297, 304, 303, 303, 303, 303,
+ 303, 303, 330, 330, 304, 304, 304, 304, 304, 304,
+
+ 291, 255, 255, 255, 291, 305, 330, 330, 330, 330,
+ 330, 225, 330, 292, 305, 305, 305, 305, 305, 305,
+ 306, 330, 330, 330, 330, 228, 313, 330, 330, 306,
+ 306, 306, 306, 306, 306, 313, 313, 313, 313, 313,
+ 313, 314, 330, 330, 330, 330, 330, 315, 330, 330,
+ 314, 314, 314, 314, 314, 314, 315, 315, 315, 315,
+ 315, 315, 316, 330, 330, 330, 330, 330, 320, 330,
+ 330, 316, 316, 316, 316, 316, 316, 320, 320, 320,
+ 320, 320, 320, 321, 330, 330, 330, 330, 330, 322,
+ 330, 330, 321, 321, 321, 321, 321, 321, 322, 322,
+
+ 322, 322, 322, 322, 326, 330, 330, 330, 330, 330,
+ 327, 330, 330, 326, 326, 326, 326, 326, 326, 327,
+ 327, 327, 327, 327, 327, 197, 330, 330, 330, 330,
+ 330, 224, 330, 330, 197, 197, 197, 197, 197, 197,
+ 224, 224, 224, 224, 224, 224, 227, 330, 330, 330,
+ 330, 330, 330, 330, 330, 227, 227, 227, 227, 227,
+ 227, 29, 330, 29, 29, 29, 29, 29, 29, 32,
+ 330, 32, 32, 35, 330, 35, 35, 35, 35, 35,
+ 35, 41, 330, 41, 41, 72, 72, 72, 72, 72,
+ 72, 76, 76, 330, 76, 76, 87, 87, 87, 87,
+
+ 87, 87, 87, 87, 91, 91, 91, 91, 91, 91,
+ 94, 94, 94, 94, 94, 94, 94, 94, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 51, 51, 102,
+ 102, 102, 102, 102, 102, 104, 330, 104, 104, 131,
+ 131, 131, 131, 131, 131, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 148, 148, 148, 148, 148, 148,
+ 168, 168, 330, 168, 176, 176, 176, 176, 176, 176,
+ 176, 176, 176, 192, 192, 330, 192, 197, 197, 197,
+ 330, 197, 197, 197, 197, 218, 218, 330, 218, 224,
+ 330, 224, 224, 224, 224, 224, 224, 227, 330, 227,
+
+ 227, 227, 227, 227, 227, 230, 230, 230, 230, 230,
+ 230, 230, 230, 249, 249, 330, 249, 258, 258, 258,
+ 258, 258, 258, 258, 258, 263, 263, 263, 263, 263,
+ 263, 263, 263, 280, 280, 330, 280, 3, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330
+
+ } ;
+
+static yyconst short int yy_chk[1695] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 7, 7, 7, 7,
+ 7, 8, 11, 13, 21, 35, 13, 29, 52, 50,
+ 18, 50, 13, 57, 39, 325, 11, 21, 22, 35,
+ 8, 22, 22, 52, 18, 41, 29, 18, 13, 57,
+
+ 18, 22, 7, 16, 18, 18, 39, 18, 41, 53,
+ 16, 16, 62, 16, 111, 62, 53, 111, 22, 16,
+ 323, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 19, 56, 16, 23,
+ 101, 43, 23, 43, 101, 19, 19, 19, 19, 19,
+ 19, 55, 23, 26, 26, 26, 26, 26, 27, 27,
+ 27, 27, 27, 56, 33, 43, 99, 99, 319, 87,
+ 40, 55, 23, 33, 33, 33, 33, 33, 33, 40,
+ 40, 40, 40, 40, 40, 54, 42, 86, 87, 42,
+
+ 42, 114, 86, 49, 27, 31, 31, 31, 31, 42,
+ 54, 31, 49, 49, 49, 49, 49, 49, 58, 93,
+ 54, 86, 60, 60, 31, 318, 88, 114, 58, 93,
+ 31, 59, 60, 31, 31, 31, 31, 31, 31, 36,
+ 36, 36, 36, 93, 72, 88, 59, 76, 79, 94,
+ 36, 61, 59, 117, 317, 79, 61, 72, 36, 117,
+ 76, 79, 80, 94, 36, 310, 309, 36, 36, 36,
+ 36, 36, 36, 61, 77, 80, 61, 73, 73, 73,
+ 73, 73, 106, 77, 77, 77, 77, 77, 77, 73,
+ 82, 108, 308, 121, 140, 198, 73, 80, 95, 121,
+
+ 108, 106, 73, 82, 180, 73, 73, 73, 73, 73,
+ 73, 81, 95, 140, 198, 81, 302, 82, 131, 180,
+ 81, 81, 81, 81, 81, 81, 89, 89, 89, 89,
+ 89, 131, 89, 134, 135, 136, 138, 150, 143, 177,
+ 134, 168, 136, 177, 150, 89, 134, 135, 168, 138,
+ 224, 89, 143, 199, 89, 89, 89, 89, 89, 89,
+ 90, 90, 90, 90, 105, 152, 90, 199, 227, 224,
+ 263, 152, 301, 105, 105, 105, 105, 105, 105, 90,
+ 154, 300, 227, 299, 263, 90, 154, 298, 90, 90,
+ 90, 90, 90, 90, 92, 92, 92, 92, 92, 192,
+
+ 218, 223, 223, 223, 223, 223, 192, 218, 225, 225,
+ 225, 225, 225, 92, 223, 258, 288, 289, 296, 92,
+ 280, 225, 92, 92, 92, 92, 92, 92, 96, 96,
+ 96, 96, 96, 249, 258, 288, 289, 277, 292, 96,
+ 249, 255, 255, 255, 255, 255, 257, 96, 276, 268,
+ 254, 257, 292, 96, 255, 293, 96, 96, 96, 96,
+ 96, 96, 97, 97, 97, 97, 130, 253, 252, 293,
+ 257, 251, 250, 97, 245, 130, 130, 130, 130, 130,
+ 130, 97, 272, 272, 272, 272, 272, 97, 274, 243,
+ 97, 97, 97, 97, 97, 97, 103, 103, 103, 103,
+
+ 103, 242, 274, 241, 235, 222, 274, 272, 221, 220,
+ 259, 259, 259, 259, 259, 103, 259, 219, 214, 212,
+ 211, 103, 210, 259, 103, 103, 103, 103, 103, 103,
+ 132, 132, 132, 132, 132, 259, 278, 278, 278, 278,
+ 278, 141, 209, 208, 202, 195, 194, 193, 187, 132,
+ 141, 141, 141, 141, 141, 141, 142, 186, 132, 132,
+ 132, 132, 132, 132, 144, 142, 142, 142, 142, 142,
+ 142, 147, 185, 144, 144, 144, 144, 144, 144, 184,
+ 147, 147, 147, 147, 147, 147, 149, 149, 149, 149,
+ 149, 183, 182, 181, 176, 172, 170, 164, 169, 163,
+
+ 162, 161, 160, 262, 159, 149, 164, 164, 164, 164,
+ 164, 164, 165, 262, 149, 149, 149, 149, 149, 149,
+ 167, 165, 165, 165, 165, 165, 165, 262, 158, 167,
+ 167, 167, 167, 167, 167, 171, 171, 171, 171, 171,
+ 173, 171, 157, 155, 153, 151, 171, 148, 171, 173,
+ 173, 173, 173, 173, 173, 174, 145, 139, 137, 133,
+ 171, 175, 129, 128, 174, 174, 174, 174, 174, 174,
+ 175, 175, 175, 175, 175, 175, 178, 297, 297, 297,
+ 297, 297, 179, 127, 126, 178, 178, 178, 178, 178,
+ 178, 179, 179, 179, 179, 179, 179, 189, 125, 124,
+
+ 123, 122, 297, 190, 120, 119, 189, 189, 189, 189,
+ 189, 189, 190, 190, 190, 190, 190, 190, 191, 118,
+ 116, 115, 113, 112, 110, 109, 107, 191, 191, 191,
+ 191, 191, 191, 196, 196, 196, 196, 196, 203, 196,
+ 104, 102, 100, 91, 196, 85, 196, 203, 203, 203,
+ 203, 203, 203, 78, 71, 70, 69, 68, 196, 197,
+ 197, 197, 197, 197, 204, 197, 67, 66, 65, 64,
+ 197, 63, 197, 204, 204, 204, 204, 204, 204, 51,
+ 47, 46, 44, 38, 197, 201, 201, 201, 201, 201,
+ 32, 201, 28, 25, 24, 20, 201, 201, 201, 17,
+
+ 15, 14, 12, 10, 201, 9, 3, 0, 0, 0,
+ 201, 205, 0, 201, 201, 201, 201, 201, 201, 206,
+ 205, 205, 205, 205, 205, 205, 207, 0, 206, 206,
+ 206, 206, 206, 206, 215, 207, 207, 207, 207, 207,
+ 207, 216, 0, 215, 215, 215, 215, 215, 215, 217,
+ 216, 216, 216, 216, 216, 216, 0, 0, 217, 217,
+ 217, 217, 217, 217, 226, 226, 226, 226, 236, 0,
+ 226, 0, 0, 0, 0, 0, 0, 236, 236, 236,
+ 236, 236, 236, 226, 0, 0, 0, 0, 0, 226,
+ 0, 0, 226, 226, 226, 226, 226, 226, 228, 228,
+
+ 228, 228, 237, 0, 0, 0, 0, 0, 0, 228,
+ 0, 237, 237, 237, 237, 237, 237, 228, 0, 0,
+ 0, 0, 0, 228, 0, 0, 228, 228, 228, 228,
+ 228, 228, 229, 229, 229, 229, 229, 238, 229, 0,
+ 0, 0, 0, 229, 0, 229, 238, 238, 238, 238,
+ 238, 238, 0, 0, 0, 0, 0, 229, 230, 230,
+ 230, 230, 230, 239, 230, 0, 0, 0, 0, 230,
+ 0, 230, 239, 239, 239, 239, 239, 239, 0, 0,
+ 0, 0, 0, 230, 231, 231, 231, 231, 231, 240,
+ 231, 0, 0, 0, 0, 231, 0, 231, 240, 240,
+
+ 240, 240, 240, 240, 0, 0, 0, 0, 0, 231,
+ 232, 232, 232, 232, 232, 246, 232, 0, 0, 0,
+ 0, 232, 0, 232, 246, 246, 246, 246, 246, 246,
+ 0, 0, 0, 0, 0, 232, 233, 233, 233, 233,
+ 233, 0, 233, 0, 0, 0, 0, 233, 0, 233,
+ 287, 287, 287, 287, 287, 233, 287, 0, 0, 0,
+ 0, 233, 0, 287, 233, 233, 233, 233, 233, 233,
+ 234, 234, 234, 234, 234, 287, 234, 0, 0, 0,
+ 0, 234, 234, 234, 0, 0, 0, 0, 0, 234,
+ 0, 0, 0, 0, 0, 234, 247, 0, 234, 234,
+
+ 234, 234, 234, 234, 248, 247, 247, 247, 247, 247,
+ 247, 0, 0, 248, 248, 248, 248, 248, 248, 260,
+ 260, 260, 260, 260, 0, 260, 0, 0, 0, 0,
+ 0, 0, 264, 264, 264, 264, 264, 0, 260, 0,
+ 0, 0, 0, 264, 260, 264, 0, 260, 260, 260,
+ 260, 260, 260, 261, 261, 261, 261, 264, 0, 261,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 261, 0, 0, 0, 0, 0, 261, 0,
+ 0, 261, 261, 261, 261, 261, 261, 265, 265, 265,
+ 265, 265, 0, 0, 0, 0, 0, 0, 265, 0,
+
+ 0, 0, 0, 0, 0, 0, 265, 0, 0, 0,
+ 0, 0, 265, 0, 0, 265, 265, 265, 265, 265,
+ 265, 266, 266, 266, 266, 267, 0, 0, 0, 0,
+ 0, 0, 266, 0, 267, 267, 267, 267, 267, 267,
+ 266, 0, 0, 0, 0, 0, 266, 269, 0, 266,
+ 266, 266, 266, 266, 266, 270, 269, 269, 269, 269,
+ 269, 269, 271, 0, 270, 270, 270, 270, 270, 270,
+ 273, 271, 271, 271, 271, 271, 271, 279, 0, 273,
+ 273, 273, 273, 273, 273, 290, 279, 279, 279, 279,
+ 279, 279, 0, 0, 290, 290, 290, 290, 290, 290,
+
+ 291, 291, 291, 291, 291, 294, 0, 0, 0, 0,
+ 0, 291, 0, 291, 294, 294, 294, 294, 294, 294,
+ 295, 0, 0, 0, 0, 291, 303, 0, 0, 295,
+ 295, 295, 295, 295, 295, 303, 303, 303, 303, 303,
+ 303, 304, 0, 0, 0, 0, 0, 305, 0, 0,
+ 304, 304, 304, 304, 304, 304, 305, 305, 305, 305,
+ 305, 305, 306, 0, 0, 0, 0, 0, 314, 0,
+ 0, 306, 306, 306, 306, 306, 306, 314, 314, 314,
+ 314, 314, 314, 315, 0, 0, 0, 0, 0, 316,
+ 0, 0, 315, 315, 315, 315, 315, 315, 316, 316,
+
+ 316, 316, 316, 316, 320, 0, 0, 0, 0, 0,
+ 321, 0, 0, 320, 320, 320, 320, 320, 320, 321,
+ 321, 321, 321, 321, 321, 322, 0, 0, 0, 0,
+ 0, 326, 0, 0, 322, 322, 322, 322, 322, 322,
+ 326, 326, 326, 326, 326, 326, 327, 0, 0, 0,
+ 0, 0, 0, 0, 0, 327, 327, 327, 327, 327,
+ 327, 331, 0, 331, 331, 331, 331, 331, 331, 332,
+ 0, 332, 332, 333, 0, 333, 333, 333, 333, 333,
+ 333, 334, 0, 334, 334, 335, 335, 335, 335, 335,
+ 335, 336, 336, 0, 336, 336, 337, 337, 337, 337,
+
+ 337, 337, 337, 337, 338, 338, 338, 338, 338, 338,
+ 339, 339, 339, 339, 339, 339, 339, 339, 340, 340,
+ 340, 340, 340, 340, 340, 340, 340, 341, 341, 342,
+ 342, 342, 342, 342, 342, 343, 0, 343, 343, 344,
+ 344, 344, 344, 344, 344, 345, 345, 345, 345, 345,
+ 345, 345, 345, 345, 346, 346, 346, 346, 346, 346,
+ 347, 347, 0, 347, 348, 348, 348, 348, 348, 348,
+ 348, 348, 348, 349, 349, 0, 349, 350, 350, 350,
+ 0, 350, 350, 350, 350, 351, 351, 0, 351, 352,
+ 0, 352, 352, 352, 352, 352, 352, 353, 0, 353,
+
+ 353, 353, 353, 353, 353, 354, 354, 354, 354, 354,
+ 354, 354, 354, 355, 355, 0, 355, 356, 356, 356,
+ 356, 356, 356, 356, 356, 357, 357, 357, 357, 357,
+ 357, 357, 357, 358, 358, 0, 358, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330,
+ 330, 330, 330, 330
+
+ } ;
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register unsigned short *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 25 "tokenizer.flex"
+
+
+#line 1009 "tok"
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 331 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 1638 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 27 "tokenizer.flex"
+/* ignore comments */
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 29 "tokenizer.flex"
+{yyTok = S; return yyTok;}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 31 "tokenizer.flex"
+{yyTok = SGML_CD; return yyTok;}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 32 "tokenizer.flex"
+{yyTok = SGML_CD; return yyTok;}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 33 "tokenizer.flex"
+{yyTok = INCLUDES; return yyTok;}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 34 "tokenizer.flex"
+{yyTok = DASHMATCH; return yyTok;}
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 35 "tokenizer.flex"
+{yyTok = BEGINSWITH; return yyTok;}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 36 "tokenizer.flex"
+{yyTok = ENDSWITH; return yyTok;}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 37 "tokenizer.flex"
+{yyTok = CONTAINS; return yyTok;}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 39 "tokenizer.flex"
+{yyTok = STRING; return yyTok;}
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 41 "tokenizer.flex"
+{yyTok = IDENT; return yyTok;}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 43 "tokenizer.flex"
+{yyTok = NTH; return yyTok;}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 45 "tokenizer.flex"
+{yyTok = HASH; return yyTok;}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 47 "tokenizer.flex"
+{yyTok = IMPORT_SYM; return yyTok;}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 48 "tokenizer.flex"
+{yyTok = PAGE_SYM; return yyTok;}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 49 "tokenizer.flex"
+{yyTok = MEDIA_SYM; return yyTok;}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 50 "tokenizer.flex"
+{yyTok = FONT_FACE_SYM; return yyTok;}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 51 "tokenizer.flex"
+{yyTok = CHARSET_SYM; return yyTok;}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 52 "tokenizer.flex"
+{yyTok = NAMESPACE_SYM; return yyTok; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 53 "tokenizer.flex"
+{yyTok = KHTML_RULE_SYM; return yyTok; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 54 "tokenizer.flex"
+{yyTok = KHTML_DECLS_SYM; return yyTok; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 55 "tokenizer.flex"
+{yyTok = KHTML_VALUE_SYM; return yyTok; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 57 "tokenizer.flex"
+{yyTok = IMPORTANT_SYM; return yyTok;}
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 59 "tokenizer.flex"
+{yyTok = EMS; return yyTok;}
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 60 "tokenizer.flex"
+{yyTok = QEMS; return yyTok;} /* quirky ems */
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 61 "tokenizer.flex"
+{yyTok = EXS; return yyTok;}
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 62 "tokenizer.flex"
+{yyTok = PXS; return yyTok;}
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 63 "tokenizer.flex"
+{yyTok = CMS; return yyTok;}
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 64 "tokenizer.flex"
+{yyTok = MMS; return yyTok;}
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 65 "tokenizer.flex"
+{yyTok = INS; return yyTok;}
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 66 "tokenizer.flex"
+{yyTok = PTS; return yyTok;}
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 67 "tokenizer.flex"
+{yyTok = PCS; return yyTok;}
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 68 "tokenizer.flex"
+{yyTok = DEGS; return yyTok;}
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 69 "tokenizer.flex"
+{yyTok = RADS; return yyTok;}
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 70 "tokenizer.flex"
+{yyTok = GRADS; return yyTok;}
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 71 "tokenizer.flex"
+{yyTok = MSECS; return yyTok;}
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 72 "tokenizer.flex"
+{yyTok = SECS; return yyTok;}
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 73 "tokenizer.flex"
+{yyTok = HERZ; return yyTok;}
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 74 "tokenizer.flex"
+{yyTok = KHERZ; return yyTok;}
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 75 "tokenizer.flex"
+{yyTok = DIMEN; return yyTok;}
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 76 "tokenizer.flex"
+{yyTok = PERCENTAGE; return yyTok;}
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 77 "tokenizer.flex"
+{yyTok = INTEGER; return yyTok;}
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 78 "tokenizer.flex"
+{yyTok = FLOAT; return yyTok;}
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 81 "tokenizer.flex"
+{yyTok = NOTFUNCTION; return yyTok;}
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 82 "tokenizer.flex"
+{yyTok = URI; return yyTok;}
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 83 "tokenizer.flex"
+{yyTok = URI; return yyTok;}
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 84 "tokenizer.flex"
+{yyTok = FUNCTION; return yyTok;}
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 86 "tokenizer.flex"
+{yyTok = UNICODERANGE; return yyTok;}
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 87 "tokenizer.flex"
+{yyTok = UNICODERANGE; return yyTok;}
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 89 "tokenizer.flex"
+{yyTok = *yytext; return yyTok;}
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 91 "tokenizer.flex"
+ECHO;
+ YY_BREAK
+#line 1347 "tok"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ yy_c_buf_p = yytext;
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
diff --git a/tdehtml/css/tokenizer.flex b/tdehtml/css/tokenizer.flex
new file mode 100644
index 000000000..76fcadb7c
--- /dev/null
+++ b/tdehtml/css/tokenizer.flex
@@ -0,0 +1,92 @@
+%option case-insensitive
+%option noyywrap
+%option 8bit
+
+h [0-9a-fA-F]
+nonascii [\200-\377]
+unicode \\{h}{1,6}[ \t\r\n\f]?
+escape {unicode}|\\[ -~\200-\377]
+nmstart [_a-zA-Z]|{nonascii}|{escape}
+nmchar [_a-zA-Z0-9-]|{nonascii}|{escape}
+string1 \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
+string2 \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
+
+ident -?{nmstart}{nmchar}*
+name {nmchar}+
+num [0-9]+|[0-9]*"."[0-9]+
+intnum [0-9]+
+string {string1}|{string2}
+url ([!#$%&*-~]|{nonascii}|{escape})*
+w [ \t\r\n\f]*
+nl \n|\r\n|\r|\f
+range \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h})))))
+nth (-?[0-9]*n[\+-][0-9]+)|(-?[0-9]*n)
+
+%%
+
+\/\*[^*]*\*+([^/*][^*]*\*+)*\/ /* ignore comments */
+
+[ \t\r\n\f]+ {yyTok = S; return yyTok;}
+
+"<!--" {yyTok = SGML_CD; return yyTok;}
+"-->" {yyTok = SGML_CD; return yyTok;}
+"~=" {yyTok = INCLUDES; return yyTok;}
+"|=" {yyTok = DASHMATCH; return yyTok;}
+"^=" {yyTok = BEGINSWITH; return yyTok;}
+"$=" {yyTok = ENDSWITH; return yyTok;}
+"*=" {yyTok = CONTAINS; return yyTok;}
+
+{string} {yyTok = STRING; return yyTok;}
+
+{ident} {yyTok = IDENT; return yyTok;}
+
+{nth} {yyTok = NTH; return yyTok;}
+
+"#"{name} {yyTok = HASH; return yyTok;}
+
+"@import" {yyTok = IMPORT_SYM; return yyTok;}
+"@page" {yyTok = PAGE_SYM; return yyTok;}
+"@media" {yyTok = MEDIA_SYM; return yyTok;}
+"@font-face" {yyTok = FONT_FACE_SYM; return yyTok;}
+"@charset" {yyTok = CHARSET_SYM; return yyTok;}
+"@namespace" {yyTok = NAMESPACE_SYM; return yyTok; }
+"@-tdehtml-rule" {yyTok = KHTML_RULE_SYM; return yyTok; }
+"@-tdehtml-decls" {yyTok = KHTML_DECLS_SYM; return yyTok; }
+"@-tdehtml-value" {yyTok = KHTML_VALUE_SYM; return yyTok; }
+
+"!"{w}"important" {yyTok = IMPORTANT_SYM; return yyTok;}
+
+{num}em {yyTok = EMS; return yyTok;}
+{num}__qem {yyTok = QEMS; return yyTok;} /* quirky ems */
+{num}ex {yyTok = EXS; return yyTok;}
+{num}px {yyTok = PXS; return yyTok;}
+{num}cm {yyTok = CMS; return yyTok;}
+{num}mm {yyTok = MMS; return yyTok;}
+{num}in {yyTok = INS; return yyTok;}
+{num}pt {yyTok = PTS; return yyTok;}
+{num}pc {yyTok = PCS; return yyTok;}
+{num}deg {yyTok = DEGS; return yyTok;}
+{num}rad {yyTok = RADS; return yyTok;}
+{num}grad {yyTok = GRADS; return yyTok;}
+{num}ms {yyTok = MSECS; return yyTok;}
+{num}s {yyTok = SECS; return yyTok;}
+{num}Hz {yyTok = HERZ; return yyTok;}
+{num}kHz {yyTok = KHERZ; return yyTok;}
+{num}{ident} {yyTok = DIMEN; return yyTok;}
+{num}% {yyTok = PERCENTAGE; return yyTok;}
+{intnum} {yyTok = INTEGER; return yyTok;}
+{num} {yyTok = FLOAT; return yyTok;}
+
+
+"not(" {yyTok = NOTFUNCTION; return yyTok;}
+"url("{w}{string}{w}")" {yyTok = URI; return yyTok;}
+"url("{w}{url}{w}")" {yyTok = URI; return yyTok;}
+{ident}"(" {yyTok = FUNCTION; return yyTok;}
+
+U\+{range} {yyTok = UNICODERANGE; return yyTok;}
+U\+{h}{1,6}-{h}{1,6} {yyTok = UNICODERANGE; return yyTok;}
+
+. {yyTok = *yytext; return yyTok;}
+
+%%
+
diff --git a/tdehtml/design.h b/tdehtml/design.h
new file mode 100644
index 000000000..86dbec911
--- /dev/null
+++ b/tdehtml/design.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1998 Waldo Bastian (bastian@kde.org)
+ (C) 1998, 1999 Torben Weis (weis@kde.org)
+ (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.
+*/
+
+
+/**
+ * \mainpage KDE HTML widget
+ *
+ * This library provides a full-featured HTML parser and widget. It is
+ * used for rendering in all KDE applications which allow HTML viewing,
+ * including the Konqueror browser/file manager, KMail, and the KDE Help
+ * system.
+ *
+ * This library provides support for HTML4/XHTML, embedded Java applets,
+ * cascading style sheets (CSS2), and JavaScript.
+ *
+ * If you want to add to your application a widget that only needs simple text
+ * browsing, you can also use the KTextBrowser widget in tdeui.
+ *
+ * KHTMLPart :
+ * The main part/widget for using tdehtml.
+ *
+ * DOM :
+ * The dom implementation used in tdehtml.
+ *
+ */
+
+/**
+ *
+ * The Document Object Model (DOM) is divided into two parts, the
+ * COREDOM core
+ * DOM, specifying some core functionality, and the HTMLDOM HTML DOM,
+ * which deals with the extensions needed for HTML.
+ *
+ *
+ */
+namespace DOM
+{
+};
diff --git a/tdehtml/dom/CMakeLists.txt b/tdehtml/dom/CMakeLists.txt
new file mode 100644
index 000000000..dd637f7bd
--- /dev/null
+++ b/tdehtml/dom/CMakeLists.txt
@@ -0,0 +1,58 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+set( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${USE_EXCEPTIONS} )
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/kio
+)
+
+
+##### headers ###################################
+
+install( FILES
+ dom_exception.h html_base.h html_inline.h
+ css_rule.h dom_html.h html_block.h html_list.h
+ css_stylesheet.h dom_misc.h html_document.h html_misc.h
+ css_value.h dom_node.h html_element.h html_object.h
+ dom_core.h dom_string.h html_form.h html_table.h
+ dom_doc.h dom_text.h html_head.h
+ dom_element.h dom_xml.h html_image.h
+ dom2_range.h dom2_traversal.h dom2_events.h
+ dom2_views.h
+ #css_extensions.h
+ DESTINATION ${INCLUDE_INSTALL_DIR}/dom )
+
+
+##### tdehtmldom-static ############################
+
+set( target tdehtmldom )
+
+set( ${target}_SRCS
+ dom_misc.cpp html_block.cpp html_inline.cpp css_rule.cpp
+ dom_node.cpp html_document.cpp html_list.cpp css_stylesheet.cpp
+ dom_string.cpp html_element.cpp html_misc.cpp css_value.cpp
+ dom_text.cpp html_object.cpp dom_doc.cpp dom_xml.cpp
+ html_head.cpp dom_element.cpp html_base.cpp html_image.cpp
+ html_form.cpp dom2_range.cpp html_table.cpp dom2_traversal.cpp
+ dom2_events.cpp dom2_views.cpp
+ #css_extensions.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
diff --git a/tdehtml/dom/Makefile.am b/tdehtml/dom/Makefile.am
new file mode 100644
index 000000000..6a33de62d
--- /dev/null
+++ b/tdehtml/dom/Makefile.am
@@ -0,0 +1,58 @@
+# 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 = $(USE_EXCEPTIONS) $(WOVERLOADED_VIRTUAL)
+
+noinst_LTLIBRARIES = libtdehtmldom.la
+libtdehtmldom_la_SOURCES = \
+ dom_misc.cpp html_block.cpp html_inline.cpp \
+ css_rule.cpp dom_node.cpp html_document.cpp html_list.cpp \
+ css_stylesheet.cpp dom_string.cpp html_element.cpp html_misc.cpp \
+ css_value.cpp dom_text.cpp html_object.cpp \
+ dom_doc.cpp dom_xml.cpp html_head.cpp \
+ dom_element.cpp html_base.cpp html_image.cpp html_form.cpp \
+ dom2_range.cpp html_table.cpp dom2_traversal.cpp dom2_events.cpp \
+ dom2_views.cpp
+# css_extensions.cpp
+
+libtdehtmldom_la_METASOURCES = AUTO
+
+myincludedir = $(includedir)/dom
+myinclude_HEADERS = \
+ dom_exception.h html_base.h html_inline.h \
+ css_rule.h dom_html.h html_block.h html_list.h \
+ css_stylesheet.h dom_misc.h html_document.h html_misc.h \
+ css_value.h dom_node.h html_element.h html_object.h \
+ dom_core.h dom_string.h html_form.h html_table.h \
+ dom_doc.h dom_text.h html_head.h \
+ dom_element.h dom_xml.h html_image.h \
+ dom2_range.h dom2_traversal.h dom2_events.h \
+ dom2_views.h
+# css_extensions.h
+
+INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/kio -I$(top_srcdir)/dcop \
+ -I$(top_srcdir)/tdehtml -I$(top_srcdir) $(all_includes)
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) tdecore -lqt
+
diff --git a/tdehtml/dom/css_extensions.cpp b/tdehtml/dom/css_extensions.cpp
new file mode 100644
index 000000000..23f7739dc
--- /dev/null
+++ b/tdehtml/dom/css_extensions.cpp
@@ -0,0 +1,2043 @@
+/**
+ * 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 "dom_exception.h"
+#include "dom_string.h"
+
+#include "css_extensions.h"
+#include "css_extensionsimpl.h"
+using namespace DOM;
+
+
+CSS2Azimuth::CSS2Azimuth() : CSSValue()
+{
+}
+
+CSS2Azimuth::CSS2Azimuth(const CSS2Azimuth &other) : CSSValue(other)
+{
+}
+
+CSS2Azimuth::CSS2Azimuth(CSS2AzimuthImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2Azimuth &CSS2Azimuth::operator = (const CSS2Azimuth &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2Azimuth::~CSS2Azimuth()
+{
+}
+
+unsigned short CSS2Azimuth::azimuthType() const
+{
+ if(!impl) return 0;
+ return ((CSS2AzimuthImpl *)impl)->azimuthType();
+}
+
+DOMString CSS2Azimuth::identifier() const
+{
+ if(!impl) return 0;
+ return ((CSS2AzimuthImpl *)impl)->identifier();
+}
+
+bool CSS2Azimuth::behind() const
+{
+ if(!impl) return 0;
+ return ((CSS2AzimuthImpl *)impl)->behind();
+}
+
+void CSS2Azimuth::setAngleValue( const unsigned short unitType, const float floatValue )
+{
+ if(impl)
+ ((CSS2AzimuthImpl *)impl)->setAngleValue( unitType, floatValue );
+}
+
+float CSS2Azimuth::getAngleValue( const unsigned short unitType )
+{
+ if(!impl) return 0;
+ return ((CSS2AzimuthImpl *)impl)->getAngleValue( unitType );
+}
+
+void CSS2Azimuth::setIdentifier( const DOMString &identifier, const bool behind )
+{
+ if(impl)
+ ((CSS2AzimuthImpl *)impl)->setIdentifier( identifier, behind );
+}
+
+
+
+CSS2BackgroundPosition::CSS2BackgroundPosition() : CSSValue()
+{
+}
+
+CSS2BackgroundPosition::CSS2BackgroundPosition(const CSS2BackgroundPosition &other) : CSSValue(other)
+{
+}
+
+CSS2BackgroundPosition::CSS2BackgroundPosition(CSS2BackgroundPositionImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2BackgroundPosition &CSS2BackgroundPosition::operator = (const CSS2BackgroundPosition &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2BackgroundPosition::~CSS2BackgroundPosition()
+{
+}
+
+unsigned short CSS2BackgroundPosition::horizontalType() const
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->horizontalType();
+}
+
+unsigned short CSS2BackgroundPosition::verticalType() const
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->verticalType();
+}
+
+DOMString CSS2BackgroundPosition::horizontalIdentifier() const
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->horizontalIdentifier();
+}
+
+DOMString CSS2BackgroundPosition::verticalIdentifier() const
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->verticalIdentifier();
+}
+
+float CSS2BackgroundPosition::getHorizontalPosition( const float horizontalType )
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->getHorizontalPosition( horizontalType );
+}
+
+float CSS2BackgroundPosition::getVerticalPosition( const float verticalType )
+{
+ if(!impl) return 0;
+ return ((CSS2BackgroundPositionImpl *)impl)->getVerticalPosition( verticalType );
+}
+
+void CSS2BackgroundPosition::setHorizontalPosition( const unsigned short horizontalType, const float value )
+{
+ if(impl)
+ ((CSS2BackgroundPositionImpl *)impl)->setHorizontalPosition( horizontalType, value );
+}
+
+void CSS2BackgroundPosition::setVerticalPosition( const unsigned short verticalType, const float value )
+{
+ if(impl)
+ ((CSS2BackgroundPositionImpl *)impl)->setVerticalPosition( verticalType, value );
+}
+
+void CSS2BackgroundPosition::setPositionIdentifier( const DOMString &horizontalIdentifier, const DOMString &verticalIdentifier )
+{
+ if(impl)
+ ((CSS2BackgroundPositionImpl *)impl)->setPositionIdentifier( horizontalIdentifier, verticalIdentifier );
+}
+
+
+
+CSS2BorderSpacing::CSS2BorderSpacing() : CSSValue()
+{
+}
+
+CSS2BorderSpacing::CSS2BorderSpacing(const CSS2BorderSpacing &other) : CSSValue(other)
+{
+}
+
+CSS2BorderSpacing::CSS2BorderSpacing(CSS2BorderSpacingImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2BorderSpacing &CSS2BorderSpacing::operator = (const CSS2BorderSpacing &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2BorderSpacing::~CSS2BorderSpacing()
+{
+}
+
+unsigned short CSS2BorderSpacing::horizontalType() const
+{
+ if(!impl) return 0;
+ return ((CSS2BorderSpacingImpl *)impl)->horizontalType();
+}
+
+unsigned short CSS2BorderSpacing::verticalType() const
+{
+ if(!impl) return 0;
+ return ((CSS2BorderSpacingImpl *)impl)->verticalType();
+}
+
+float CSS2BorderSpacing::getHorizontalSpacing( const float horizontalType )
+{
+ if(!impl) return 0;
+ return ((CSS2BorderSpacingImpl *)impl)->getHorizontalSpacing( horizontalType );
+}
+
+float CSS2BorderSpacing::getVerticalSpacing( const float verticalType )
+{
+ if(!impl) return 0;
+ return ((CSS2BorderSpacingImpl *)impl)->getVerticalSpacing( verticalType );
+}
+
+void CSS2BorderSpacing::setHorizontalSpacing( const unsigned short horizontalType, const float value )
+{
+ if(impl)
+ ((CSS2BorderSpacingImpl *)impl)->setHorizontalSpacing( horizontalType, value );
+}
+
+void CSS2BorderSpacing::setVerticalSpacing( const unsigned short verticalType, const float value )
+{
+ if(impl)
+ ((CSS2BorderSpacingImpl *)impl)->setVerticalSpacing( verticalType, value );
+}
+
+void CSS2BorderSpacing::setInherit()
+{
+ if(impl)
+ ((CSS2BorderSpacingImpl *)impl)->setInherit();
+}
+
+
+
+CSS2CounterIncrement::CSS2CounterIncrement()
+{
+}
+
+CSS2CounterIncrement::CSS2CounterIncrement(const CSS2CounterIncrement &other)
+{
+}
+
+CSS2CounterIncrement::CSS2CounterIncrement(CSS2CounterIncrementImpl *impl)
+{
+}
+
+CSS2CounterIncrement &CSS2CounterIncrement::operator = (const CSS2CounterIncrement &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2CounterIncrement::~CSS2CounterIncrement()
+{
+}
+
+DOMString CSS2CounterIncrement::identifier() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("identifier");
+}
+
+void CSS2CounterIncrement::setIdentifier( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("identifier", value);
+}
+
+short CSS2CounterIncrement::increment() const
+{
+ if(!impl) return 0;
+ return ((CSS2CounterIncrementImpl *)impl)->increment();
+}
+
+void CSS2CounterIncrement::setIncrement( const short _increment )
+{
+
+ if(impl)
+ ((CSS2CounterIncrementImpl *)impl)->setIncrement( _increment );
+}
+
+
+
+
+CSS2CounterReset::CSS2CounterReset()
+{
+}
+
+CSS2CounterReset::CSS2CounterReset(const CSS2CounterReset &other)
+{
+}
+
+CSS2CounterReset::CSS2CounterReset(CSS2CounterResetImpl *impl)
+{
+}
+
+CSS2CounterReset &CSS2CounterReset::operator = (const CSS2CounterReset &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2CounterReset::~CSS2CounterReset()
+{
+}
+
+DOMString CSS2CounterReset::identifier() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("identifier");
+}
+
+void CSS2CounterReset::setIdentifier( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("identifier", value);
+}
+
+short CSS2CounterReset::reset() const
+{
+ if(!impl) return 0;
+ return ((CSS2CounterResetImpl *)impl)->reset();
+}
+
+void CSS2CounterReset::setReset( const short _reset )
+{
+
+ if(impl)
+ ((CSS2CounterResetImpl *)impl)->setReset( _reset );
+}
+
+
+
+
+CSS2Cursor::CSS2Cursor() : CSSValue()
+{
+}
+
+CSS2Cursor::CSS2Cursor(const CSS2Cursor &other) : CSSValue(other)
+{
+}
+
+CSS2Cursor::CSS2Cursor(CSS2CursorImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2Cursor &CSS2Cursor::operator = (const CSS2Cursor &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2Cursor::~CSS2Cursor()
+{
+}
+
+unsigned short CSS2Cursor::cursorType() const
+{
+ if(!impl) return 0;
+ return ((CSS2CursorImpl *)impl)->cursorType();
+}
+
+void CSS2Cursor::setCursorType( const unsigned short _cursorType )
+{
+
+ if(impl)
+ ((CSS2CursorImpl *)impl)->setCursorType( _cursorType );
+}
+
+CSSValueList CSS2Cursor::uris() const
+{
+ if(!impl) return 0;
+ return ((CSS2CursorImpl *)impl)->uris();
+}
+
+DOMString CSS2Cursor::predefinedCursor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("predefinedCursor");
+}
+
+void CSS2Cursor::setPredefinedCursor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("predefinedCursor", value);
+}
+
+
+
+CSS2FontFaceSrc::CSS2FontFaceSrc()
+{
+}
+
+CSS2FontFaceSrc::CSS2FontFaceSrc(const CSS2FontFaceSrc &other)
+{
+}
+
+CSS2FontFaceSrc::CSS2FontFaceSrc(CSS2FontFaceSrcImpl *impl)
+{
+}
+
+CSS2FontFaceSrc &CSS2FontFaceSrc::operator = (const CSS2FontFaceSrc &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2FontFaceSrc::~CSS2FontFaceSrc()
+{
+}
+
+DOMString CSS2FontFaceSrc::uri() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("uri");
+}
+
+void CSS2FontFaceSrc::setUri( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("uri", value);
+}
+
+CSSValueList CSS2FontFaceSrc::format() const
+{
+ if(!impl) return 0;
+ return ((CSS2FontFaceSrcImpl *)impl)->format();
+}
+
+DOMString CSS2FontFaceSrc::fontFaceName() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontFaceName");
+}
+
+void CSS2FontFaceSrc::setFontFaceName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontFaceName", value);
+}
+
+
+
+CSS2FontFaceWidths::CSS2FontFaceWidths()
+{
+}
+
+CSS2FontFaceWidths::CSS2FontFaceWidths(const CSS2FontFaceWidths &other)
+{
+}
+
+CSS2FontFaceWidths::CSS2FontFaceWidths(CSS2FontFaceWidthsImpl *impl)
+{
+}
+
+CSS2FontFaceWidths &CSS2FontFaceWidths::operator = (const CSS2FontFaceWidths &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2FontFaceWidths::~CSS2FontFaceWidths()
+{
+}
+
+DOMString CSS2FontFaceWidths::urange() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("urange");
+}
+
+void CSS2FontFaceWidths::setUrange( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("urange", value);
+}
+
+CSSValueList CSS2FontFaceWidths::numbers() const
+{
+ if(!impl) return 0;
+ return ((CSS2FontFaceWidthsImpl *)impl)->numbers();
+}
+
+
+
+
+CSS2PageSize::CSS2PageSize() : CSSValue()
+{
+}
+
+CSS2PageSize::CSS2PageSize(const CSS2PageSize &other) : CSSValue(other)
+{
+}
+
+CSS2PageSize::CSS2PageSize(CSS2PageSizeImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2PageSize &CSS2PageSize::operator = (const CSS2PageSize &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2PageSize::~CSS2PageSize()
+{
+}
+
+unsigned short CSS2PageSize::widthType() const
+{
+ if(!impl) return 0;
+ return ((CSS2PageSizeImpl *)impl)->widthType();
+}
+
+unsigned short CSS2PageSize::heightType() const
+{
+ if(!impl) return 0;
+ return ((CSS2PageSizeImpl *)impl)->heightType();
+}
+
+DOMString CSS2PageSize::identifier() const
+{
+ if(!impl) return 0;
+ return ((CSS2PageSizeImpl *)impl)->identifier();
+}
+
+float CSS2PageSize::getWidth( const float widthType )
+{
+ if(!impl) return 0;
+ return ((CSS2PageSizeImpl *)impl)->getWidth( widthType );
+}
+
+float CSS2PageSize::getHeightSize( const float heightType )
+{
+ if(!impl) return 0;
+ return ((CSS2PageSizeImpl *)impl)->getHeightSize( heightType );
+}
+
+void CSS2PageSize::setWidthSize( const unsigned short widthType, const float value )
+{
+ if(impl)
+ ((CSS2PageSizeImpl *)impl)->setWidthSize( widthType, value );
+}
+
+void CSS2PageSize::setHeightSize( const unsigned short heightType, const float value )
+{
+ if(impl)
+ ((CSS2PageSizeImpl *)impl)->setHeightSize( heightType, value );
+}
+
+void CSS2PageSize::setIdentifier( const DOMString &identifier )
+{
+ if(impl)
+ ((CSS2PageSizeImpl *)impl)->setIdentifier( identifier );
+}
+
+
+
+CSS2PlayDuring::CSS2PlayDuring() : CSSValue()
+{
+}
+
+CSS2PlayDuring::CSS2PlayDuring(const CSS2PlayDuring &other) : CSSValue(other)
+{
+}
+
+CSS2PlayDuring::CSS2PlayDuring(CSS2PlayDuringImpl *impl) : CSSValue(impl)
+{
+}
+
+CSS2PlayDuring &CSS2PlayDuring::operator = (const CSS2PlayDuring &other)
+{
+ CSSValue::operator = (other);
+ return *this;
+}
+
+CSS2PlayDuring::~CSS2PlayDuring()
+{
+}
+
+unsigned short CSS2PlayDuring::playDuringType() const
+{
+ if(!impl) return 0;
+ return ((CSS2PlayDuringImpl *)impl)->playDuringType();
+}
+
+DOMString CSS2PlayDuring::playDuringIdentifier() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("playDuringIdentifier");
+}
+
+void CSS2PlayDuring::setPlayDuringIdentifier( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("playDuringIdentifier", value);
+}
+
+DOMString CSS2PlayDuring::uri() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("uri");
+}
+
+void CSS2PlayDuring::setUri( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("uri", value);
+}
+
+bool CSS2PlayDuring::mix() const
+{
+ if(!impl) return 0;
+ return ((CSS2PlayDuringImpl *)impl)->mix();
+}
+
+void CSS2PlayDuring::setMix( const bool _mix )
+{
+
+ if(impl)
+ ((CSS2PlayDuringImpl *)impl)->setMix( _mix );
+}
+
+bool CSS2PlayDuring::repeat() const
+{
+ if(!impl) return 0;
+ return ((CSS2PlayDuringImpl *)impl)->repeat();
+}
+
+void CSS2PlayDuring::setRepeat( const bool _repeat )
+{
+
+ if(impl)
+ ((CSS2PlayDuringImpl *)impl)->setRepeat( _repeat );
+}
+
+
+
+CSS2Properties::CSS2Properties()
+{
+}
+
+CSS2Properties::CSS2Properties(const CSS2Properties &other)
+{
+}
+
+CSS2Properties::CSS2Properties(CSS2PropertiesImpl *impl)
+{
+}
+
+CSS2Properties &CSS2Properties::operator = (const CSS2Properties &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2Properties::~CSS2Properties()
+{
+}
+
+DOMString CSS2Properties::azimuth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("azimuth");
+}
+
+void CSS2Properties::setAzimuth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("azimuth", value);
+}
+
+DOMString CSS2Properties::background() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("background");
+}
+
+void CSS2Properties::setBackground( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("background", value);
+}
+
+DOMString CSS2Properties::backgroundAttachment() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("backgroundAttachment");
+}
+
+void CSS2Properties::setBackgroundAttachment( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("backgroundAttachment", value);
+}
+
+DOMString CSS2Properties::backgroundColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("backgroundColor");
+}
+
+void CSS2Properties::setBackgroundColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("backgroundColor", value);
+}
+
+DOMString CSS2Properties::backgroundImage() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("backgroundImage");
+}
+
+void CSS2Properties::setBackgroundImage( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("backgroundImage", value);
+}
+
+DOMString CSS2Properties::backgroundPosition() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("backgroundPosition");
+}
+
+void CSS2Properties::setBackgroundPosition( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("backgroundPosition", value);
+}
+
+DOMString CSS2Properties::backgroundRepeat() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("backgroundRepeat");
+}
+
+void CSS2Properties::setBackgroundRepeat( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("backgroundRepeat", value);
+}
+
+DOMString CSS2Properties::border() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("border");
+}
+
+void CSS2Properties::setBorder( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("border", value);
+}
+
+DOMString CSS2Properties::borderCollapse() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderCollapse");
+}
+
+void CSS2Properties::setBorderCollapse( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderCollapse", value);
+}
+
+DOMString CSS2Properties::borderColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderColor");
+}
+
+void CSS2Properties::setBorderColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderColor", value);
+}
+
+DOMString CSS2Properties::borderSpacing() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderSpacing");
+}
+
+void CSS2Properties::setBorderSpacing( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderSpacing", value);
+}
+
+DOMString CSS2Properties::borderStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderStyle");
+}
+
+void CSS2Properties::setBorderStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderStyle", value);
+}
+
+DOMString CSS2Properties::borderTop() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderTop");
+}
+
+void CSS2Properties::setBorderTop( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderTop", value);
+}
+
+DOMString CSS2Properties::borderRight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderRight");
+}
+
+void CSS2Properties::setBorderRight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderRight", value);
+}
+
+DOMString CSS2Properties::borderBottom() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderBottom");
+}
+
+void CSS2Properties::setBorderBottom( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderBottom", value);
+}
+
+DOMString CSS2Properties::borderLeft() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderLeft");
+}
+
+void CSS2Properties::setBorderLeft( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderLeft", value);
+}
+
+DOMString CSS2Properties::borderTopColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderTopColor");
+}
+
+void CSS2Properties::setBorderTopColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderTopColor", value);
+}
+
+DOMString CSS2Properties::borderRightColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderRightColor");
+}
+
+void CSS2Properties::setBorderRightColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderRightColor", value);
+}
+
+DOMString CSS2Properties::borderBottomColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderBottomColor");
+}
+
+void CSS2Properties::setBorderBottomColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderBottomColor", value);
+}
+
+DOMString CSS2Properties::borderLeftColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderLeftColor");
+}
+
+void CSS2Properties::setBorderLeftColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderLeftColor", value);
+}
+
+DOMString CSS2Properties::borderTopStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderTopStyle");
+}
+
+void CSS2Properties::setBorderTopStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderTopStyle", value);
+}
+
+DOMString CSS2Properties::borderRightStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderRightStyle");
+}
+
+void CSS2Properties::setBorderRightStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderRightStyle", value);
+}
+
+DOMString CSS2Properties::borderBottomStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderBottomStyle");
+}
+
+void CSS2Properties::setBorderBottomStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderBottomStyle", value);
+}
+
+DOMString CSS2Properties::borderLeftStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderLeftStyle");
+}
+
+void CSS2Properties::setBorderLeftStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderLeftStyle", value);
+}
+
+DOMString CSS2Properties::borderTopWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderTopWidth");
+}
+
+void CSS2Properties::setBorderTopWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderTopWidth", value);
+}
+
+DOMString CSS2Properties::borderRightWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderRightWidth");
+}
+
+void CSS2Properties::setBorderRightWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderRightWidth", value);
+}
+
+DOMString CSS2Properties::borderBottomWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderBottomWidth");
+}
+
+void CSS2Properties::setBorderBottomWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderBottomWidth", value);
+}
+
+DOMString CSS2Properties::borderLeftWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderLeftWidth");
+}
+
+void CSS2Properties::setBorderLeftWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderLeftWidth", value);
+}
+
+DOMString CSS2Properties::borderWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("borderWidth");
+}
+
+void CSS2Properties::setBorderWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("borderWidth", value);
+}
+
+DOMString CSS2Properties::bottom() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("bottom");
+}
+
+void CSS2Properties::setBottom( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("bottom", value);
+}
+
+DOMString CSS2Properties::captionSide() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("captionSide");
+}
+
+void CSS2Properties::setCaptionSide( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("captionSide", value);
+}
+
+DOMString CSS2Properties::clear() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("clear");
+}
+
+void CSS2Properties::setClear( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("clear", value);
+}
+
+DOMString CSS2Properties::clip() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("clip");
+}
+
+void CSS2Properties::setClip( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("clip", value);
+}
+
+DOMString CSS2Properties::color() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("color");
+}
+
+void CSS2Properties::setColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("color", value);
+}
+
+DOMString CSS2Properties::content() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("content");
+}
+
+void CSS2Properties::setContent( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("content", value);
+}
+
+DOMString CSS2Properties::counterIncrement() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("counterIncrement");
+}
+
+void CSS2Properties::setCounterIncrement( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("counterIncrement", value);
+}
+
+DOMString CSS2Properties::counterReset() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("counterReset");
+}
+
+void CSS2Properties::setCounterReset( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("counterReset", value);
+}
+
+DOMString CSS2Properties::cue() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("cue");
+}
+
+void CSS2Properties::setCue( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("cue", value);
+}
+
+DOMString CSS2Properties::cueAfter() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("cueAfter");
+}
+
+void CSS2Properties::setCueAfter( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("cueAfter", value);
+}
+
+DOMString CSS2Properties::cueBefore() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("cueBefore");
+}
+
+void CSS2Properties::setCueBefore( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("cueBefore", value);
+}
+
+DOMString CSS2Properties::cursor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("cursor");
+}
+
+void CSS2Properties::setCursor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("cursor", value);
+}
+
+DOMString CSS2Properties::direction() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("direction");
+}
+
+void CSS2Properties::setDirection( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("direction", value);
+}
+
+DOMString CSS2Properties::display() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("display");
+}
+
+void CSS2Properties::setDisplay( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("display", value);
+}
+
+DOMString CSS2Properties::elevation() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("elevation");
+}
+
+void CSS2Properties::setElevation( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("elevation", value);
+}
+
+DOMString CSS2Properties::emptyCells() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("emptyCells");
+}
+
+void CSS2Properties::setEmptyCells( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("emptyCells", value);
+}
+
+DOMString CSS2Properties::cssFloat() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("cssFloat");
+}
+
+void CSS2Properties::setCssFloat( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("cssFloat", value);
+}
+
+DOMString CSS2Properties::font() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("font");
+}
+
+void CSS2Properties::setFont( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("font", value);
+}
+
+DOMString CSS2Properties::fontFamily() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontFamily");
+}
+
+void CSS2Properties::setFontFamily( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontFamily", value);
+}
+
+DOMString CSS2Properties::fontSize() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontSize");
+}
+
+void CSS2Properties::setFontSize( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontSize", value);
+}
+
+DOMString CSS2Properties::fontSizeAdjust() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontSizeAdjust");
+}
+
+void CSS2Properties::setFontSizeAdjust( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontSizeAdjust", value);
+}
+
+DOMString CSS2Properties::fontStretch() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontStretch");
+}
+
+void CSS2Properties::setFontStretch( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontStretch", value);
+}
+
+DOMString CSS2Properties::fontStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontStyle");
+}
+
+void CSS2Properties::setFontStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontStyle", value);
+}
+
+DOMString CSS2Properties::fontVariant() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontVariant");
+}
+
+void CSS2Properties::setFontVariant( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontVariant", value);
+}
+
+DOMString CSS2Properties::fontWeight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("fontWeight");
+}
+
+void CSS2Properties::setFontWeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("fontWeight", value);
+}
+
+DOMString CSS2Properties::height() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("height");
+}
+
+void CSS2Properties::setHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("height", value);
+}
+
+DOMString CSS2Properties::left() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("left");
+}
+
+void CSS2Properties::setLeft( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("left", value);
+}
+
+DOMString CSS2Properties::letterSpacing() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("letterSpacing");
+}
+
+void CSS2Properties::setLetterSpacing( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("letterSpacing", value);
+}
+
+DOMString CSS2Properties::lineHeight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("lineHeight");
+}
+
+void CSS2Properties::setLineHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("lineHeight", value);
+}
+
+DOMString CSS2Properties::listStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("listStyle");
+}
+
+void CSS2Properties::setListStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("listStyle", value);
+}
+
+DOMString CSS2Properties::listStyleImage() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("listStyleImage");
+}
+
+void CSS2Properties::setListStyleImage( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("listStyleImage", value);
+}
+
+DOMString CSS2Properties::listStylePosition() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("listStylePosition");
+}
+
+void CSS2Properties::setListStylePosition( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("listStylePosition", value);
+}
+
+DOMString CSS2Properties::listStyleType() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("listStyleType");
+}
+
+void CSS2Properties::setListStyleType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("listStyleType", value);
+}
+
+DOMString CSS2Properties::margin() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("margin");
+}
+
+void CSS2Properties::setMargin( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("margin", value);
+}
+
+DOMString CSS2Properties::marginTop() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("marginTop");
+}
+
+void CSS2Properties::setMarginTop( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("marginTop", value);
+}
+
+DOMString CSS2Properties::marginRight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("marginRight");
+}
+
+void CSS2Properties::setMarginRight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("marginRight", value);
+}
+
+DOMString CSS2Properties::marginBottom() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("marginBottom");
+}
+
+void CSS2Properties::setMarginBottom( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("marginBottom", value);
+}
+
+DOMString CSS2Properties::marginLeft() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("marginLeft");
+}
+
+void CSS2Properties::setMarginLeft( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("marginLeft", value);
+}
+
+DOMString CSS2Properties::markerOffset() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("markerOffset");
+}
+
+void CSS2Properties::setMarkerOffset( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("markerOffset", value);
+}
+
+DOMString CSS2Properties::marks() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("marks");
+}
+
+void CSS2Properties::setMarks( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("marks", value);
+}
+
+DOMString CSS2Properties::maxHeight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("maxHeight");
+}
+
+void CSS2Properties::setMaxHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("maxHeight", value);
+}
+
+DOMString CSS2Properties::maxWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("maxWidth");
+}
+
+void CSS2Properties::setMaxWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("maxWidth", value);
+}
+
+DOMString CSS2Properties::minHeight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("minHeight");
+}
+
+void CSS2Properties::setMinHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("minHeight", value);
+}
+
+DOMString CSS2Properties::minWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("minWidth");
+}
+
+void CSS2Properties::setMinWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("minWidth", value);
+}
+
+DOMString CSS2Properties::orphans() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("orphans");
+}
+
+void CSS2Properties::setOrphans( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("orphans", value);
+}
+
+DOMString CSS2Properties::outline() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("outline");
+}
+
+void CSS2Properties::setOutline( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("outline", value);
+}
+
+DOMString CSS2Properties::outlineColor() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("outlineColor");
+}
+
+void CSS2Properties::setOutlineColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("outlineColor", value);
+}
+
+DOMString CSS2Properties::outlineStyle() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("outlineStyle");
+}
+
+void CSS2Properties::setOutlineStyle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("outlineStyle", value);
+}
+
+DOMString CSS2Properties::outlineWidth() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("outlineWidth");
+}
+
+void CSS2Properties::setOutlineWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("outlineWidth", value);
+}
+
+DOMString CSS2Properties::overflow() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("overflow");
+}
+
+void CSS2Properties::setOverflow( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("overflow", value);
+}
+
+DOMString CSS2Properties::padding() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("padding");
+}
+
+void CSS2Properties::setPadding( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("padding", value);
+}
+
+DOMString CSS2Properties::paddingTop() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("paddingTop");
+}
+
+void CSS2Properties::setPaddingTop( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("paddingTop", value);
+}
+
+DOMString CSS2Properties::paddingRight() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("paddingRight");
+}
+
+void CSS2Properties::setPaddingRight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("paddingRight", value);
+}
+
+DOMString CSS2Properties::paddingBottom() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("paddingBottom");
+}
+
+void CSS2Properties::setPaddingBottom( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("paddingBottom", value);
+}
+
+DOMString CSS2Properties::paddingLeft() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("paddingLeft");
+}
+
+void CSS2Properties::setPaddingLeft( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("paddingLeft", value);
+}
+
+DOMString CSS2Properties::page() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("page");
+}
+
+void CSS2Properties::setPage( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("page", value);
+}
+
+DOMString CSS2Properties::pageBreakAfter() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pageBreakAfter");
+}
+
+void CSS2Properties::setPageBreakAfter( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pageBreakAfter", value);
+}
+
+DOMString CSS2Properties::pageBreakBefore() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pageBreakBefore");
+}
+
+void CSS2Properties::setPageBreakBefore( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pageBreakBefore", value);
+}
+
+DOMString CSS2Properties::pageBreakInside() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pageBreakInside");
+}
+
+void CSS2Properties::setPageBreakInside( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pageBreakInside", value);
+}
+
+DOMString CSS2Properties::pause() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pause");
+}
+
+void CSS2Properties::setPause( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pause", value);
+}
+
+DOMString CSS2Properties::pauseAfter() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pauseAfter");
+}
+
+void CSS2Properties::setPauseAfter( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pauseAfter", value);
+}
+
+DOMString CSS2Properties::pauseBefore() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pauseBefore");
+}
+
+void CSS2Properties::setPauseBefore( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pauseBefore", value);
+}
+
+DOMString CSS2Properties::pitch() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pitch");
+}
+
+void CSS2Properties::setPitch( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pitch", value);
+}
+
+DOMString CSS2Properties::pitchRange() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("pitchRange");
+}
+
+void CSS2Properties::setPitchRange( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("pitchRange", value);
+}
+
+DOMString CSS2Properties::playDuring() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("playDuring");
+}
+
+void CSS2Properties::setPlayDuring( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("playDuring", value);
+}
+
+DOMString CSS2Properties::position() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("position");
+}
+
+void CSS2Properties::setPosition( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("position", value);
+}
+
+DOMString CSS2Properties::quotes() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("quotes");
+}
+
+void CSS2Properties::setQuotes( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("quotes", value);
+}
+
+DOMString CSS2Properties::richness() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("richness");
+}
+
+void CSS2Properties::setRichness( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("richness", value);
+}
+
+DOMString CSS2Properties::right() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("right");
+}
+
+void CSS2Properties::setRight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("right", value);
+}
+
+DOMString CSS2Properties::size() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("size");
+}
+
+void CSS2Properties::setSize( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("size", value);
+}
+
+DOMString CSS2Properties::speak() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("speak");
+}
+
+void CSS2Properties::setSpeak( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("speak", value);
+}
+
+DOMString CSS2Properties::speakHeader() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("speakHeader");
+}
+
+void CSS2Properties::setSpeakHeader( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("speakHeader", value);
+}
+
+DOMString CSS2Properties::speakNumeral() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("speakNumeral");
+}
+
+void CSS2Properties::setSpeakNumeral( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("speakNumeral", value);
+}
+
+DOMString CSS2Properties::speakPunctuation() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("speakPunctuation");
+}
+
+void CSS2Properties::setSpeakPunctuation( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("speakPunctuation", value);
+}
+
+DOMString CSS2Properties::speechRate() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("speechRate");
+}
+
+void CSS2Properties::setSpeechRate( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("speechRate", value);
+}
+
+DOMString CSS2Properties::stress() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("stress");
+}
+
+void CSS2Properties::setStress( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("stress", value);
+}
+
+DOMString CSS2Properties::tableLayout() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("tableLayout");
+}
+
+void CSS2Properties::setTableLayout( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("tableLayout", value);
+}
+
+DOMString CSS2Properties::textAlign() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("textAlign");
+}
+
+void CSS2Properties::setTextAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("textAlign", value);
+}
+
+DOMString CSS2Properties::textDecoration() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("textDecoration");
+}
+
+void CSS2Properties::setTextDecoration( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("textDecoration", value);
+}
+
+DOMString CSS2Properties::textIndent() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("textIndent");
+}
+
+void CSS2Properties::setTextIndent( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("textIndent", value);
+}
+
+DOMString CSS2Properties::textShadow() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("textShadow");
+}
+
+void CSS2Properties::setTextShadow( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("textShadow", value);
+}
+
+DOMString CSS2Properties::textTransform() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("textTransform");
+}
+
+void CSS2Properties::setTextTransform( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("textTransform", value);
+}
+
+DOMString CSS2Properties::top() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("top");
+}
+
+void CSS2Properties::setTop( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("top", value);
+}
+
+DOMString CSS2Properties::unicodeBidi() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("unicodeBidi");
+}
+
+void CSS2Properties::setUnicodeBidi( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("unicodeBidi", value);
+}
+
+DOMString CSS2Properties::verticalAlign() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("verticalAlign");
+}
+
+void CSS2Properties::setVerticalAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("verticalAlign", value);
+}
+
+DOMString CSS2Properties::visibility() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("visibility");
+}
+
+void CSS2Properties::setVisibility( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("visibility", value);
+}
+
+DOMString CSS2Properties::voiceFamily() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("voiceFamily");
+}
+
+void CSS2Properties::setVoiceFamily( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("voiceFamily", value);
+}
+
+DOMString CSS2Properties::volume() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("volume");
+}
+
+void CSS2Properties::setVolume( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("volume", value);
+}
+
+DOMString CSS2Properties::whiteSpace() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("whiteSpace");
+}
+
+void CSS2Properties::setWhiteSpace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("whiteSpace", value);
+}
+
+DOMString CSS2Properties::widows() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("widows");
+}
+
+void CSS2Properties::setWidows( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("widows", value);
+}
+
+DOMString CSS2Properties::width() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("width");
+}
+
+void CSS2Properties::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("width", value);
+}
+
+DOMString CSS2Properties::wordSpacing() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("wordSpacing");
+}
+
+void CSS2Properties::setWordSpacing( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("wordSpacing", value);
+}
+
+DOMString CSS2Properties::zIndex() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute("zIndex");
+}
+
+void CSS2Properties::setZIndex( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute("zIndex", value);
+}
+
+
+
+CSS2TextShadow::CSS2TextShadow()
+{
+}
+
+CSS2TextShadow::CSS2TextShadow(const CSS2TextShadow &other)
+{
+}
+
+CSS2TextShadow::CSS2TextShadow(CSS2TextShadowImpl *impl)
+{
+}
+
+CSS2TextShadow &CSS2TextShadow::operator = (const CSS2TextShadow &other)
+{
+ ::operator = (other);
+ return *this;
+}
+
+CSS2TextShadow::~CSS2TextShadow()
+{
+}
+
+CSSValue CSS2TextShadow::color() const
+{
+ if(!impl) return 0;
+ return ((CSS2TextShadowImpl *)impl)->color();
+}
+
+CSSValue CSS2TextShadow::horizontal() const
+{
+ if(!impl) return 0;
+ return ((CSS2TextShadowImpl *)impl)->horizontal();
+}
+
+CSSValue CSS2TextShadow::vertical() const
+{
+ if(!impl) return 0;
+ return ((CSS2TextShadowImpl *)impl)->vertical();
+}
+
+CSSValue CSS2TextShadow::blur() const
+{
+ if(!impl) return 0;
+ return ((CSS2TextShadowImpl *)impl)->blur();
+}
+
+
+
diff --git a/tdehtml/dom/css_extensions.h b/tdehtml/dom/css_extensions.h
new file mode 100644
index 000000000..a6cdb2149
--- /dev/null
+++ b/tdehtml/dom/css_extensions.h
@@ -0,0 +1,2702 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Candidate Recommendation)
+ * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _CSS_css_extensions_h_
+#define _CSS_css_extensions_h_
+
+#include <css_value.h>
+#include <dom/dom_string.h>
+
+namespace DOM {
+
+/**
+ * The \c CSS2Azimuth interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-azimuth">
+ * azimuth </a> CSS Level 2 property.
+ *
+ */
+class CSS2Azimuth : public CSSValue
+{
+public:
+ CSS2Azimuth();
+ CSS2Azimuth(const CSS2Azimuth &other);
+ CSS2Azimuth(CSS2AzimuthImpl *impl);
+public:
+
+ CSS2Azimuth & operator = (const CSS2Azimuth &other);
+
+ ~CSS2Azimuth();
+
+ /**
+ * A code defining the type of the value as defined in
+ * \c CSSValue . It would be one of \c CSS_DEG ,
+ * \c CSS_RAD , \c CSS_GRAD or
+ * \c CSS_IDENT .
+ *
+ */
+ unsigned short azimuthType() const;
+
+ /**
+ * If \c azimuthType is \c CSS_IDENT ,
+ * \c identifier contains one of left-side, far-left,
+ * left, center-left, center, center-right, right, far-right,
+ * right-side, leftwards, rightwards. The empty string if none is
+ * set.
+ *
+ */
+ DOM::DOMString identifier() const;
+
+ /**
+ * \c behind indicates whether the behind identifier
+ * has been set.
+ *
+ */
+ bool behind() const;
+
+ /**
+ * A method to set the angle value with a specified unit. This
+ * method will unset any previously set identifiers values.
+ *
+ * @param unitType The unitType could only be one of
+ * \c CSS_DEG , \c CSS_RAD or \c CSS_GRAD ).
+ *
+ * @param floatValue The new float value of the angle.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raised if the unit type is invalid.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this property is
+ * readonly.
+ *
+ */
+ void setAngleValue ( const unsigned short unitType, const float floatValue );
+
+ /**
+ * Used to retrieved the float value of the azimuth property.
+ *
+ * @param unitType The unit type can be only an angle unit type (
+ * \c CSS_DEG , \c CSS_RAD or
+ * \c CSS_GRAD ).
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raised if the unit type is invalid.
+ *
+ */
+ float getAngleValue ( const unsigned short unitType );
+
+ /**
+ * Setting the identifier for the azimuth property will unset any
+ * previously set angle value. The value of \c azimuthType
+ * is set to \c CSS_IDENT
+ *
+ * @param identifier The new identifier. If the identifier is
+ * "leftwards" or "rightward", the behind attribute is ignored.
+ *
+ * @param behind The new value for behind.
+ *
+ * @return
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified \c identifier
+ * has a syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this property is
+ * readonly.
+ *
+ */
+ void setIdentifier ( const DOM::DOMString &identifier, const bool behind );
+};
+
+
+class CSS2BackgroundPositionImpl;
+
+/**
+ * The \c CSS2BackgroundPosition interface represents the
+ * <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-position">
+ * background-position </a> CSS Level 2 property.
+ *
+ */
+class CSS2BackgroundPosition : public CSSValue
+{
+public:
+ CSS2BackgroundPosition();
+ CSS2BackgroundPosition(const CSS2BackgroundPosition &other);
+ CSS2BackgroundPosition(CSS2BackgroundPositionImpl *impl);
+public:
+
+ CSS2BackgroundPosition & operator = (const CSS2BackgroundPosition &other);
+
+ ~CSS2BackgroundPosition();
+
+ /**
+ * A code defining the type of the horizontal value. It would be
+ * one \c CSS_PERCENTAGE , \c CSS_EMS ,
+ * \c CSS_EXS , \c CSS_PX , \c CSS_CM ,
+ * \c CSS_MM , \c CSS_IN ,
+ * \c CSS_PT , \c CSS_PC ,
+ * \c CSS_IDENT , \c CSS_INHERIT . If one of
+ * horizontal or vertical is \c CSS_IDENT or
+ * \c CSS_INHERIT , it's guaranteed that the other is the
+ * same.
+ *
+ */
+ unsigned short horizontalType() const;
+
+ /**
+ * A code defining the type of the horizontal value. The code can
+ * be one of the following units : \c CSS_PERCENTAGE ,
+ * \c CSS_EMS , \c CSS_EXS , \c CSS_PX
+ * , \c CSS_CM , \c CSS_MM ,
+ * \c CSS_IN , \c CSS_PT , \c CSS_PC
+ * , \c CSS_IDENT , \c CSS_INHERIT
+ * . If one of horizontal or vertical is \c CSS_IDENT
+ * or \c CSS_INHERIT , it's guaranteed that the other
+ * is the same.
+ *
+ */
+ unsigned short verticalType() const;
+
+ /**
+ * If \c horizontalType is \c CSS_IDENT or
+ * \c CSS_INHERIT , this attribute contains the string
+ * representation of the ident, otherwise it contains an empty
+ * string.
+ *
+ */
+ DOM::DOMString horizontalIdentifier() const;
+
+ /**
+ * If \c verticalType is \c CSS_IDENT or
+ * \c CSS_INHERIT , this attribute contains the string
+ * representation of the ident, otherwise it contains an empty
+ * string. The value is \c "center" if only the
+ * horizontalIdentifier has been set. The value is
+ * \c "inherit" if the horizontalIdentifier is
+ * \c "inherit" .
+ *
+ */
+ DOM::DOMString verticalIdentifier() const;
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c horizontalPosition represents a length or
+ * a percentage. If the float doesn't contain a float value or
+ * can't be converted into the specified unit, a
+ * \c DOMException is raised.
+ *
+ * @param horizontalType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getHorizontalPosition ( const float horizontalType );
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c verticalPosition represents a length or a
+ * percentage. If the float doesn't contain a float value or can't
+ * be converted into the specified unit, a \c DOMException
+ * is raised. The value is \c 50% if only the
+ * horizontal value has been specified.
+ *
+ * @param verticalType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getVerticalPosition ( const float verticalType );
+
+ /**
+ * This method is used to set the horizontal position with a
+ * specified unit. If the vertical value is not a percentage or a
+ * length, it sets the vertical position to \c 50% .
+ *
+ * @param horizontalType The specified unit (a length or a
+ * percentage).
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length or a percentage.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setHorizontalPosition ( const unsigned short horizontalType, const float value );
+
+ /**
+ * This method is used to set the vertical position with a
+ * specified unit. If the horizontal value is not a percentage or
+ * a length, it sets the vertical position to \c 50% .
+ *
+ * @param verticalType The specified unit (a length or a
+ * percentage).
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length or a percentage.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setVerticalPosition ( const unsigned short verticalType, const float value );
+
+ /**
+ * Sets the identifiers. If the second identifier is the empty
+ * string, the vertical identifier is set to his default value (
+ * \c "center" ). If the first identfier is
+ * \c "inherit , the second identifier is ignored and is set
+ * to \c "inherit" .
+ *
+ * @param horizontalIdentifier The new horizontal identifier.
+ *
+ * @param verticalIdentifier The new vertical identifier.
+ *
+ * @return
+ * @exception DOMException
+ * SYNTAX_ERR: Raises if the identifiers have a syntax error and
+ * is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setPositionIdentifier ( const DOM::DOMString &horizontalIdentifier, const DOM::DOMString &verticalIdentifier );
+};
+
+
+class CSS2BorderSpacingImpl;
+
+/**
+ * The \c CSS2BorderSpacing interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-border-spacing">
+ * border-spacing </a> CSS Level 2 property.
+ *
+ */
+class CSS2BorderSpacing : public CSSValue
+{
+public:
+ CSS2BorderSpacing();
+ CSS2BorderSpacing(const CSS2BorderSpacing &other);
+ CSS2BorderSpacing(CSS2BorderSpacingImpl *impl);
+public:
+
+ CSS2BorderSpacing & operator = (const CSS2BorderSpacing &other);
+
+ ~CSS2BorderSpacing();
+
+ /**
+ * The A code defining the type of the value as defined in
+ * \c CSSValue . It would be one of \c CSS_EMS ,
+ * \c CSS_EXS , \c CSS_PX , \c CSS_CM
+ * , \c CSS_MM , \c CSS_IN ,
+ * \c CSS_PT , \c CSS_PC or
+ * \c CSS_INHERIT .
+ *
+ */
+ unsigned short horizontalType() const;
+
+ /**
+ * The A code defining the type of the value as defined in
+ * \c CSSValue . It would be one of \c CSS_EMS ,
+ * \c CSS_EXS , \c CSS_PX , \c CSS_CM
+ * , \c CSS_MM , \c CSS_IN ,
+ * \c CSS_PT , \c CSS_PC or
+ * \c CSS_INHERIT .
+ *
+ */
+ unsigned short verticalType() const;
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c horizontalSpacing represents a length. If
+ * the float doesn't contain a float value or can't be converted
+ * into the specified unit, a \c DOMException is
+ * raised.
+ *
+ * @param horizontalType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getHorizontalSpacing ( const float horizontalType );
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c verticalSpacing represents a length. If
+ * the float doesn't contain a float value or can't be converted
+ * into the specified unit, a \c DOMException is
+ * raised. The value is \c 0 if only the horizontal
+ * value has been specified.
+ *
+ * @param verticalType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getVerticalSpacing ( const float verticalType );
+
+ /**
+ * This method is used to set the horizontal spacing with a
+ * specified unit. If the vertical value is a length, it sets the
+ * vertical spacing to \c 0 .
+ *
+ * @param horizontalType The specified unit.
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setHorizontalSpacing ( const unsigned short horizontalType, const float value );
+
+ /**
+ * This method is used to set the vertical spacing with a
+ * specified unit. If the horizontal value is not a length, it
+ * sets the vertical spacing to \c 0 .
+ *
+ * @param verticalType The specified unit.
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length or a percentage.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setVerticalSpacing ( const unsigned short verticalType, const float value );
+
+ /**
+ * Set this property as inherit. \c horizontalType and
+ * \c verticalType will be inherited.
+ *
+ * @return
+ */
+ void setInherit();
+};
+
+
+class CSS2CounterIncrementImpl;
+
+/**
+ * The \c CSS2CounterIncrement interface represents a
+ * imple value for the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-counter-increment">
+ * counter-increment </a> CSS Level 2 property.
+ *
+ */
+class CSS2CounterIncrement
+{
+public:
+ CSS2CounterIncrement();
+ CSS2CounterIncrement(const CSS2CounterIncrement &other);
+ CSS2CounterIncrement(CSS2CounterIncrementImpl *impl);
+public:
+
+ CSS2CounterIncrement & operator = (const CSS2CounterIncrement &other);
+
+ ~CSS2CounterIncrement();
+
+ /**
+ * The element name.
+ *
+ */
+ DOM::DOMString identifier() const;
+
+ /**
+ * see identifier
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified identifier has a syntax
+ * error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this identifier is
+ * readonly.
+ *
+ */
+ void setIdentifier( const DOM::DOMString & );
+
+ /**
+ * The increment (default value is 1).
+ *
+ */
+ short increment() const;
+
+ /**
+ * see increment
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this identifier is
+ * readonly.
+ *
+ */
+ void setIncrement( const short );
+};
+
+
+class CSS2CounterResetImpl;
+
+/**
+ * The \c CSS2CounterReset interface represents a simple
+ * value for the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-counter-reset">
+ * counter-reset </a> CSS Level 2 property.
+ *
+ */
+class CSS2CounterReset
+{
+public:
+ CSS2CounterReset();
+ CSS2CounterReset(const CSS2CounterReset &other);
+ CSS2CounterReset(CSS2CounterResetImpl *impl);
+public:
+
+ CSS2CounterReset & operator = (const CSS2CounterReset &other);
+
+ ~CSS2CounterReset();
+
+ /**
+ * The element name.
+ *
+ */
+ DOM::DOMString identifier() const;
+
+ /**
+ * see identifier
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified identifier has a syntax
+ * error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this identifier is
+ * readonly.
+ *
+ */
+ void setIdentifier( const DOM::DOMString & );
+
+ /**
+ * The reset (default value is 0).
+ *
+ */
+ short reset() const;
+
+ /**
+ * see reset
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this identifier is
+ * readonly.
+ *
+ */
+ void setReset( const short );
+};
+
+
+class CSS2CursorImpl;
+class CSSValueList;
+
+/**
+ * The \c CSS2Cursor interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-cursor"> cursor
+ * </a> CSS Level 2 property.
+ *
+ */
+class CSS2Cursor : public CSSValue
+{
+public:
+ CSS2Cursor();
+ CSS2Cursor(const CSS2Cursor &other);
+ CSS2Cursor(CSS2CursorImpl *impl);
+public:
+
+ CSS2Cursor & operator = (const CSS2Cursor &other);
+
+ ~CSS2Cursor();
+
+ /**
+ * A code defining the type of the property. It would one of
+ * \c CSS_UNKNOWN or \c CSS_INHERIT . If
+ * the type is \c CSS_UNKNOWN , then \c uris
+ * contains a list of URIs and \c predefinedCursor
+ * contains an ident. Setting this attribute from
+ * \c CSS_INHERIT to \c CSS_UNKNOWN will set the
+ * \c predefinedCursor to \c "auto" .
+ *
+ */
+ unsigned short cursorType() const;
+
+ /**
+ * see cursorType
+ */
+ void setCursorType( const unsigned short );
+
+ /**
+ * \c uris represents the list of URIs (
+ * \c CSS_URI ) on the cursor property. The list can be
+ * empty.
+ *
+ */
+ CSSValueList uris() const;
+
+ /**
+ * This identifier represents a generic cursor name or an empty
+ * string.
+ *
+ */
+ DOM::DOMString predefinedCursor() const;
+
+ /**
+ * see predefinedCursor
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setPredefinedCursor( const DOM::DOMString & );
+};
+
+
+class CSS2FontFaceSrcImpl;
+class CSSValueList;
+
+/**
+ * The \c CSS2Cursor interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#descdef-src"> src
+ * </a> CSS Level 2 descriptor.
+ *
+ */
+class CSS2FontFaceSrc
+{
+public:
+ CSS2FontFaceSrc();
+ CSS2FontFaceSrc(const CSS2FontFaceSrc &other);
+ CSS2FontFaceSrc(CSS2FontFaceSrcImpl *impl);
+public:
+
+ CSS2FontFaceSrc & operator = (const CSS2FontFaceSrc &other);
+
+ ~CSS2FontFaceSrc();
+
+ /**
+ * Specifies the source of the font, empty string otherwise.
+ *
+ */
+ DOM::DOMString uri() const;
+
+ /**
+ * see uri
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setUri( const DOM::DOMString & );
+
+ /**
+ * This attribute contains a list of strings for the format CSS
+ * function.
+ *
+ */
+ CSSValueList format() const;
+
+ /**
+ * Specifies the full font name of a locally installed font.
+ *
+ */
+ DOM::DOMString fontFaceName() const;
+
+ /**
+ * see fontFaceName
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setFontFaceName( const DOM::DOMString & );
+};
+
+
+class CSS2FontFaceWidthsImpl;
+class CSSValueList;
+
+/**
+ * The \c CSS2Cursor interface represents a simple value
+ * for the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#descdef-widths">
+ * widths </a> CSS Level 2 descriptor.
+ *
+ */
+class CSS2FontFaceWidths
+{
+public:
+ CSS2FontFaceWidths();
+ CSS2FontFaceWidths(const CSS2FontFaceWidths &other);
+ CSS2FontFaceWidths(CSS2FontFaceWidthsImpl *impl);
+public:
+
+ CSS2FontFaceWidths & operator = (const CSS2FontFaceWidths &other);
+
+ ~CSS2FontFaceWidths();
+
+ /**
+ * The range for the characters.
+ *
+ */
+ DOM::DOMString urange() const;
+
+ /**
+ * see urange
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setUrange( const DOM::DOMString & );
+
+ /**
+ * A list of numbers representing the glyph widths.
+ *
+ */
+ CSSValueList numbers() const;
+};
+
+
+class CSS2PageSizeImpl;
+
+/**
+ * The \c CSS2Cursor interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-size"> size
+ * </a> CSS Level 2 descriptor.
+ *
+ */
+class CSS2PageSize : public CSSValue
+{
+public:
+ CSS2PageSize();
+ CSS2PageSize(const CSS2PageSize &other);
+ CSS2PageSize(CSS2PageSizeImpl *impl);
+public:
+
+ CSS2PageSize & operator = (const CSS2PageSize &other);
+
+ ~CSS2PageSize();
+
+ /**
+ * A code defining the type of the width of the page. It would be
+ * one of \c CSS_EMS , \c CSS_EXS ,
+ * \c CSS_PX , \c CSS_CM , \c CSS_MM
+ * , \c CSS_IN , \c CSS_PT , \c CSS_PC
+ * , \c CSS_IDENT , \c CSS_INHERIT
+ * . If one of width or height is \c CSS_IDENT or
+ * \c CSS_INHERIT , it's guaranteed that the other is
+ * the same.
+ *
+ */
+ unsigned short widthType() const;
+
+ /**
+ * A code defining the type of the height of the page. It would be
+ * one of \c CSS_EMS , \c CSS_EXS ,
+ * \c CSS_PX , \c CSS_CM , \c CSS_MM
+ * , \c CSS_IN , \c CSS_PT , \c CSS_PC
+ * , \c CSS_IDENT , \c CSS_INHERIT
+ * . If one of width or height is \c CSS_IDENT or
+ * \c CSS_INHERIT , it's guaranteed that the other is
+ * the same.
+ *
+ */
+ unsigned short heightType() const;
+
+ /**
+ * If \c width is \c CSS_IDENT or
+ * \c CSS_INHERIT , this attribute contains the string
+ * representation of the ident, otherwise it contains an empty
+ * string.
+ *
+ */
+ DOM::DOMString identifier() const;
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c widthType represents a length. If the
+ * float doesn't contain a float value or can't be converted into
+ * the specified unit, a \c DOMException is raised.
+ *
+ * @param widthType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getWidth ( const float widthType );
+
+ /**
+ * This method is used to get the float value in a specified unit
+ * if the \c heightType represents a length. If the
+ * float doesn't contain a float value or can't be converted into
+ * the specified unit, a \c DOMException is raised. If
+ * only the width value has been specified, the height value is
+ * the same.
+ *
+ * @param heightType The specified unit.
+ *
+ * @return The float value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the property doesn't contain a
+ * float or the value can't be converted.
+ *
+ */
+ float getHeightSize ( const float heightType );
+
+ /**
+ * This method is used to set the width position with a specified
+ * unit. If the \c heightType is not a length, it sets
+ * the height position to the same value.
+ *
+ * @param widthType The specified unit.
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length or a percentage.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setWidthSize ( const unsigned short widthType, const float value );
+
+ /**
+ * This method is used to set the height position with a specified
+ * unit. If the \c widthType is not a length, it sets
+ * the width position to the same value.
+ *
+ * @param heightType The specified unit.
+ *
+ * @param value The new value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the specified unit is not a
+ * length or a percentage.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setHeightSize ( const unsigned short heightType, const float value );
+
+ /**
+ * Sets the identifier.
+ *
+ * @param identifier The new identifier.
+ *
+ * @return
+ * @exception DOMException
+ * SYNTAX_ERR: Raises if the identifier has a syntax error and is
+ * unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raises if this property is
+ * readonly.
+ *
+ */
+ void setIdentifier ( const DOM::DOMString &identifier );
+};
+
+
+class CSS2PlayDuringImpl;
+
+/**
+ * The \c CSS2PlayDuring interface represents the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-play-during">
+ * play-during </a> CSS Level 2 property.
+ *
+ */
+class CSS2PlayDuring : public CSSValue
+{
+public:
+ CSS2PlayDuring();
+ CSS2PlayDuring(const CSS2PlayDuring &other);
+ CSS2PlayDuring(CSS2PlayDuringImpl *impl);
+public:
+
+ CSS2PlayDuring & operator = (const CSS2PlayDuring &other);
+
+ ~CSS2PlayDuring();
+
+ /**
+ * A code defining the type of the value as define in
+ * \c CSSvalue . It would be one of \c CSS_UNKNOWN
+ * , \c CSS_INHERIT , \c CSS_IDENT
+ *
+ */
+ unsigned short playDuringType() const;
+
+ /**
+ * One of \c "inherit" , \c "auto" ,
+ * \c "none" or the empty string if the
+ * \c playDuringType is \c CSS_UNKNOWN . On
+ * setting, it will set the \c uri to the empty string
+ * and \c mix and \c repeat to
+ * \c false .
+ *
+ */
+ DOM::DOMString playDuringIdentifier() const;
+
+ /**
+ * see playDuringIdentifier
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setPlayDuringIdentifier( const DOM::DOMString & );
+
+ /**
+ * The sound specified by the \c uri . It will set the
+ * \c playDuringType attribute to \c CSS_UNKNOWN .
+ *
+ */
+ DOM::DOMString uri() const;
+
+ /**
+ * see uri
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setUri( const DOM::DOMString & );
+
+ /**
+ * \c true if the sound should be mixed. It will be
+ * ignored if the attribute doesn't contain a \c uri .
+ *
+ */
+ bool mix() const;
+
+ /**
+ * see mix
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setMix( const bool );
+
+ /**
+ * \c true if the sound should be repeated. It will be
+ * ignored if the attribute doesn't contain a \c uri .
+ *
+ */
+ bool repeat() const;
+
+ /**
+ * see repeat
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setRepeat( const bool );
+};
+
+
+class CSS2PropertiesImpl;
+
+/**
+ * The \c CSS2Properties interface represents a
+ * convenience mechanism for retrieving and setting properties within
+ * a \c CSSStyleDeclaration . The attributes of this
+ * interface correspond to all the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> properties
+ * specified in CSS2 </a> . Getting an attribute of this interface is
+ * equivalent to calling the \c getPropertyValue method of
+ * the \c CSSStyleDeclaration interface. Setting an
+ * attribute of this interface is equivalent to calling the
+ * \c setProperty method of the \c CSSStyleDeclaration
+ * interface.
+ *
+ * A compliant implementation is not required to implement the
+ * \c CSS2Properties interface. If an implementation does
+ * implement this interface, the expectation is that language-specific
+ * methods can be used to cast from an instance of the
+ * \c CSSStyleDeclaration interface to the \c CSS2Properties
+ * interface.
+ *
+ * If an implementation does implement this interface, it is expected
+ * to understand the specific syntax of the shorthand properties, and
+ * apply their semantics; when the \c margin property is
+ * set, for example, the \c marginTop , \c marginRight
+ * , \c marginBottom and \c marginLeft
+ * properties are actually being set by the underlying implementation.
+ *
+ * When dealing with CSS "shorthand" properties, the shorthand
+ * properties should be decomposed into their component longhand
+ * properties as appropriate, and when querying for their value, the
+ * form returned should be the shortest form exactly equivalent to the
+ * declarations made in the ruleset. However, if there is no shorthand
+ * declaration that could be added to the ruleset without changing in
+ * any way the rules already declared in the ruleset (i.e., by adding
+ * longhand rules that were previously not declared in the ruleset),
+ * then the empty string should be returned for the shorthand
+ * property.
+ *
+ * For example, querying for the \c font property should
+ * not return "normal normal normal 14pt/normal Arial, sans-serif",
+ * when "14pt Arial, sans-serif" suffices (the normals are initial
+ * values, and are implied by use of the longhand property).
+ *
+ * If the values for all the longhand properties that compose a
+ * particular string are the initial values, then a string consisting
+ * of all the initial values should be returned (e.g. a
+ * \c border-width value of "medium" should be returned as such,
+ * not as "").
+ *
+ * For some shorthand properties that take missing values from other
+ * sides, such as the \c margin , \c padding ,
+ * and \c border-[width|style|color] properties, the
+ * minimum number of sides possible should be used, i.e., "0px 10px"
+ * will be returned instead of "0px 10px 0px 10px".
+ *
+ * If the value of a shorthand property can not be decomposed into
+ * its component longhand properties, as is the case for the
+ * \c font property with a value of "menu", querying for the
+ * values of the component longhand properties should return the empty
+ * string.
+ *
+ */
+class CSS2Properties
+{
+public:
+ CSS2Properties();
+ CSS2Properties(const CSS2Properties &other);
+ CSS2Properties(CSS2PropertiesImpl *impl);
+public:
+
+ CSS2Properties & operator = (const CSS2Properties &other);
+
+ ~CSS2Properties();
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-azimuth">
+ * azimuth property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString azimuth() const;
+
+ /**
+ * see azimuth
+ */
+ void setAzimuth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background">
+ * background property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString background() const;
+
+ /**
+ * see background
+ */
+ void setBackground( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-attachment">
+ * background-attachment property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString backgroundAttachment() const;
+
+ /**
+ * see backgroundAttachment
+ */
+ void setBackgroundAttachment( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-color">
+ * background-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString backgroundColor() const;
+
+ /**
+ * see backgroundColor
+ */
+ void setBackgroundColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-image">
+ * background-image property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString backgroundImage() const;
+
+ /**
+ * see backgroundImage
+ */
+ void setBackgroundImage( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-position">
+ * background-position property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString backgroundPosition() const;
+
+ /**
+ * see backgroundPosition
+ */
+ void setBackgroundPosition( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-background-repeat">
+ * background-repeat property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString backgroundRepeat() const;
+
+ /**
+ * see backgroundRepeat
+ */
+ void setBackgroundRepeat( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border">
+ * border property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString border() const;
+
+ /**
+ * see border
+ */
+ void setBorder( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-border-collapse">
+ * border-collapse property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderCollapse() const;
+
+ /**
+ * see borderCollapse
+ */
+ void setBorderCollapse( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-color">
+ * border-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderColor() const;
+
+ /**
+ * see borderColor
+ */
+ void setBorderColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-border-spacing">
+ * border-spacing property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderSpacing() const;
+
+ /**
+ * see borderSpacing
+ */
+ void setBorderSpacing( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-style">
+ * border-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderStyle() const;
+
+ /**
+ * see borderStyle
+ */
+ void setBorderStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-top">
+ * border-top property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderTop() const;
+
+ /**
+ * see borderTop
+ */
+ void setBorderTop( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-right">
+ * border-right property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderRight() const;
+
+ /**
+ * see borderRight
+ */
+ void setBorderRight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-bottom">
+ * border-bottom property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderBottom() const;
+
+ /**
+ * see borderBottom
+ */
+ void setBorderBottom( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-left">
+ * border-left property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderLeft() const;
+
+ /**
+ * see borderLeft
+ */
+ void setBorderLeft( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-top-color">
+ * border-top-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderTopColor() const;
+
+ /**
+ * see borderTopColor
+ */
+ void setBorderTopColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-right-color">
+ * border-right-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderRightColor() const;
+
+ /**
+ * see borderRightColor
+ */
+ void setBorderRightColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/#propdef-border-bottom-color">
+ * border-bottom-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderBottomColor() const;
+
+ /**
+ * see borderBottomColor
+ */
+ void setBorderBottomColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-left-color">
+ * border-left-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderLeftColor() const;
+
+ /**
+ * see borderLeftColor
+ */
+ void setBorderLeftColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-top-style">
+ * border-top-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderTopStyle() const;
+
+ /**
+ * see borderTopStyle
+ */
+ void setBorderTopStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-right-style">
+ * border-right-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderRightStyle() const;
+
+ /**
+ * see borderRightStyle
+ */
+ void setBorderRightStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-bottom-style">
+ * border-bottom-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderBottomStyle() const;
+
+ /**
+ * see borderBottomStyle
+ */
+ void setBorderBottomStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-left-style">
+ * border-left-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderLeftStyle() const;
+
+ /**
+ * see borderLeftStyle
+ */
+ void setBorderLeftStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-top-width">
+ * border-top-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderTopWidth() const;
+
+ /**
+ * see borderTopWidth
+ */
+ void setBorderTopWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-right-width">
+ * border-right-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderRightWidth() const;
+
+ /**
+ * see borderRightWidth
+ */
+ void setBorderRightWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-bottom-width">
+ * border-bottom-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderBottomWidth() const;
+
+ /**
+ * see borderBottomWidth
+ */
+ void setBorderBottomWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-left-width">
+ * border-left-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderLeftWidth() const;
+
+ /**
+ * see borderLeftWidth
+ */
+ void setBorderLeftWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-border-width">
+ * border-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString borderWidth() const;
+
+ /**
+ * see borderWidth
+ */
+ void setBorderWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-bottom">
+ * bottom property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString bottom() const;
+
+ /**
+ * see bottom
+ */
+ void setBottom( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-caption-side">
+ * caption-side property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString captionSide() const;
+
+ /**
+ * see captionSide
+ */
+ void setCaptionSide( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-clear">
+ * clear property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString clear() const;
+
+ /**
+ * see clear
+ */
+ void setClear( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visufx#propdef-clip"> clip
+ * property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString clip() const;
+
+ /**
+ * see clip
+ */
+ void setClip( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/colors.html#propdef-color">
+ * color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString color() const;
+
+ /**
+ * see color
+ */
+ void setColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-content">
+ * content property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString content() const;
+
+ /**
+ * see content
+ */
+ void setContent( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-counter-increment">
+ * counter-increment property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString counterIncrement() const;
+
+ /**
+ * see counterIncrement
+ */
+ void setCounterIncrement( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-counter-reset">
+ * counter-reset property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString counterReset() const;
+
+ /**
+ * see counterReset
+ */
+ void setCounterReset( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-cue">
+ * cue property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString cue() const;
+
+ /**
+ * see cue
+ */
+ void setCue( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-cue-fter">
+ * cue-after property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString cueAfter() const;
+
+ /**
+ * see cueAfter
+ */
+ void setCueAfter( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-cue-before">
+ * cue-before property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString cueBefore() const;
+
+ /**
+ * see cueBefore
+ */
+ void setCueBefore( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-cursor">
+ * cursor property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString cursor() const;
+
+ /**
+ * see cursor
+ */
+ void setCursor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-direction">
+ * direction property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString direction() const;
+
+ /**
+ * see direction
+ */
+ void setDirection( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-display">
+ * display property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString display() const;
+
+ /**
+ * see display
+ */
+ void setDisplay( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-elevation">
+ * elevation property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString elevation() const;
+
+ /**
+ * see elevation
+ */
+ void setElevation( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-empty-cells">
+ * empty-cells property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString emptyCells() const;
+
+ /**
+ * see emptyCells
+ */
+ void setEmptyCells( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-float">
+ * float property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString cssFloat() const;
+
+ /**
+ * see cssFloat
+ */
+ void setCssFloat( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font">
+ * font property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString font() const;
+
+ /**
+ * see font
+ */
+ void setFont( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-family">
+ * font-family property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontFamily() const;
+
+ /**
+ * see fontFamily
+ */
+ void setFontFamily( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-size">
+ * font-size property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontSize() const;
+
+ /**
+ * see fontSize
+ */
+ void setFontSize( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-size-adjust">
+ * font-size-adjust property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontSizeAdjust() const;
+
+ /**
+ * see fontSizeAdjust
+ */
+ void setFontSizeAdjust( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-stretch">
+ * font-stretch property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontStretch() const;
+
+ /**
+ * see fontStretch
+ */
+ void setFontStretch( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-style">
+ * font-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontStyle() const;
+
+ /**
+ * see fontStyle
+ */
+ void setFontStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-variant">
+ * font-variant property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontVariant() const;
+
+ /**
+ * see fontVariant
+ */
+ void setFontVariant( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#propdef-font-weight">
+ * font-weight property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString fontWeight() const;
+
+ /**
+ * see fontWeight
+ */
+ void setFontWeight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-height">
+ * height property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-left">
+ * left property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString left() const;
+
+ /**
+ * see left
+ */
+ void setLeft( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-letter-spacing">
+ * letter-spacing property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString letterSpacing() const;
+
+ /**
+ * see letterSpacing
+ */
+ void setLetterSpacing( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height">
+ * line-height property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString lineHeight() const;
+
+ /**
+ * see lineHeight
+ */
+ void setLineHeight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-list-style">
+ * list-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString listStyle() const;
+
+ /**
+ * see listStyle
+ */
+ void setListStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-list-style-image">
+ * list-style-image property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString listStyleImage() const;
+
+ /**
+ * see listStyleImage
+ */
+ void setListStyleImage( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-list-style-position">
+ * list-style-position property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString listStylePosition() const;
+
+ /**
+ * see listStylePosition
+ */
+ void setListStylePosition( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-list-style-type">
+ * list-style-type property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString listStyleType() const;
+
+ /**
+ * see listStyleType
+ */
+ void setListStyleType( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-margin">
+ * margin property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString margin() const;
+
+ /**
+ * see margin
+ */
+ void setMargin( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-margin-top">
+ * margin-top property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString marginTop() const;
+
+ /**
+ * see marginTop
+ */
+ void setMarginTop( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-margin-right">
+ * margin-right property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString marginRight() const;
+
+ /**
+ * see marginRight
+ */
+ void setMarginRight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-margin-bottom">
+ * margin-bottom property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString marginBottom() const;
+
+ /**
+ * see marginBottom
+ */
+ void setMarginBottom( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-margin-left">
+ * margin-left property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString marginLeft() const;
+
+ /**
+ * see marginLeft
+ */
+ void setMarginLeft( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-marker-offset">
+ * marker-offset property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString markerOffset() const;
+
+ /**
+ * see markerOffset
+ */
+ void setMarkerOffset( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-marks">
+ * marks property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString marks() const;
+
+ /**
+ * see marks
+ */
+ void setMarks( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-max-height">
+ * max-height property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString maxHeight() const;
+
+ /**
+ * see maxHeight
+ */
+ void setMaxHeight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-max-width">
+ * max-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString maxWidth() const;
+
+ /**
+ * see maxWidth
+ */
+ void setMaxWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-min-height">
+ * min-height property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString minHeight() const;
+
+ /**
+ * see minHeight
+ */
+ void setMinHeight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-min-width">
+ * min-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString minWidth() const;
+
+ /**
+ * see minWidth
+ */
+ void setMinWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-orphans">
+ * orphans property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString orphans() const;
+
+ /**
+ * see orphans
+ */
+ void setOrphans( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-outline">
+ * outline property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString outline() const;
+
+ /**
+ * see outline
+ */
+ void setOutline( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-outline-color">
+ * outline-color property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString outlineColor() const;
+
+ /**
+ * see outlineColor
+ */
+ void setOutlineColor( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-outline-style">
+ * outline-style property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString outlineStyle() const;
+
+ /**
+ * see outlineStyle
+ */
+ void setOutlineStyle( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/ui.html#propdef-outline-width">
+ * outline-width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString outlineWidth() const;
+
+ /**
+ * see outlineWidth
+ */
+ void setOutlineWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visufx.html#propdef-overflow">
+ * overflow property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString overflow() const;
+
+ /**
+ * see overflow
+ */
+ void setOverflow( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-padding">
+ * padding property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString padding() const;
+
+ /**
+ * see padding
+ */
+ void setPadding( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-padding-top">
+ * padding-top property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString paddingTop() const;
+
+ /**
+ * see paddingTop
+ */
+ void setPaddingTop( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-padding-right">
+ * padding-right property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString paddingRight() const;
+
+ /**
+ * see paddingRight
+ */
+ void setPaddingRight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-padding-bottom">
+ * padding-bottom property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString paddingBottom() const;
+
+ /**
+ * see paddingBottom
+ */
+ void setPaddingBottom( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/box.html#propdef-padding-left">
+ * padding-left property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString paddingLeft() const;
+
+ /**
+ * see paddingLeft
+ */
+ void setPaddingLeft( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-page">
+ * page property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString page() const;
+
+ /**
+ * see page
+ */
+ void setPage( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-page-break-after">
+ * page-break-after property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pageBreakAfter() const;
+
+ /**
+ * see pageBreakAfter
+ */
+ void setPageBreakAfter( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-page-break-before">
+ * page-break-before property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pageBreakBefore() const;
+
+ /**
+ * see pageBreakBefore
+ */
+ void setPageBreakBefore( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-page-break-inside">
+ * page-break-inside property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pageBreakInside() const;
+
+ /**
+ * see pageBreakInside
+ */
+ void setPageBreakInside( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-pause">
+ * pause property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pause() const;
+
+ /**
+ * see pause
+ */
+ void setPause( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-pause-after">
+ * pause-after property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pauseAfter() const;
+
+ /**
+ * see pauseAfter
+ */
+ void setPauseAfter( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-pause-before">
+ * pause-before property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pauseBefore() const;
+
+ /**
+ * see pauseBefore
+ */
+ void setPauseBefore( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-pitch">
+ * pitch property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pitch() const;
+
+ /**
+ * see pitch
+ */
+ void setPitch( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-pitch-range">
+ * pitch-range property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString pitchRange() const;
+
+ /**
+ * see pitchRange
+ */
+ void setPitchRange( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-play-during">
+ * play-during property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString playDuring() const;
+
+ /**
+ * see playDuring
+ */
+ void setPlayDuring( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-position">
+ * position property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString position() const;
+
+ /**
+ * see position
+ */
+ void setPosition( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/generate.html#propdef-quotes">
+ * quotes property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString quotes() const;
+
+ /**
+ * see quotes
+ */
+ void setQuotes( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-richness">
+ * richness property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString richness() const;
+
+ /**
+ * see richness
+ */
+ void setRichness( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-right">
+ * right property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString right() const;
+
+ /**
+ * see right
+ */
+ void setRight( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-size">
+ * size property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString size() const;
+
+ /**
+ * see size
+ */
+ void setSize( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-speak">
+ * speak property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString speak() const;
+
+ /**
+ * see speak
+ */
+ void setSpeak( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-speak-header">
+ * speak-header property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString speakHeader() const;
+
+ /**
+ * see speakHeader
+ */
+ void setSpeakHeader( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-speak-numeral">
+ * speak-numeral property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString speakNumeral() const;
+
+ /**
+ * see speakNumeral
+ */
+ void setSpeakNumeral( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-speak-punctuation">
+ * speak-punctuation property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString speakPunctuation() const;
+
+ /**
+ * see speakPunctuation
+ */
+ void setSpeakPunctuation( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-speech-rate">
+ * speech-rate property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString speechRate() const;
+
+ /**
+ * see speechRate
+ */
+ void setSpeechRate( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-stress">
+ * stress property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString stress() const;
+
+ /**
+ * see stress
+ */
+ void setStress( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/tables.html#propdef-table-layout">
+ * table-layout property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString tableLayout() const;
+
+ /**
+ * see tableLayout
+ */
+ void setTableLayout( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-align">
+ * text-align property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString textAlign() const;
+
+ /**
+ * see textAlign
+ */
+ void setTextAlign( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-decoration">
+ * text-decoration property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString textDecoration() const;
+
+ /**
+ * see textDecoration
+ */
+ void setTextDecoration( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-indent">
+ * text-indent property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString textIndent() const;
+
+ /**
+ * see textIndent
+ */
+ void setTextIndent( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow">
+ * text-shadow property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString textShadow() const;
+
+ /**
+ * see textShadow
+ */
+ void setTextShadow( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-transform">
+ * text-transform property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString textTransform() const;
+
+ /**
+ * see textTransform
+ */
+ void setTextTransform( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-top">
+ * top property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString top() const;
+
+ /**
+ * see top
+ */
+ void setTop( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visuren.html#propdef-unicode-bidi">
+ * unicode-bidi property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString unicodeBidi() const;
+
+ /**
+ * see unicodeBidi
+ */
+ void setUnicodeBidi( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align">
+ * vertical-align property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString verticalAlign() const;
+
+ /**
+ * see verticalAlign
+ */
+ void setVerticalAlign( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visufx.html#propdef-visibility">
+ * visibility property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString visibility() const;
+
+ /**
+ * see visibility
+ */
+ void setVisibility( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-voice-family">
+ * voice-family property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString voiceFamily() const;
+
+ /**
+ * see voiceFamily
+ */
+ void setVoiceFamily( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/aural.html#propdef-volume">
+ * volume property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString volume() const;
+
+ /**
+ * see volume
+ */
+ void setVolume( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-white-space">
+ * white-space property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString whiteSpace() const;
+
+ /**
+ * see whiteSpace
+ */
+ void setWhiteSpace( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#propdef-widows">
+ * widows property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString widows() const;
+
+ /**
+ * see widows
+ */
+ void setWidows( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-width">
+ * width property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-word-spacing">
+ * word-spacing property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString wordSpacing() const;
+
+ /**
+ * see wordSpacing
+ */
+ void setWordSpacing( const DOM::DOMString & );
+
+ /**
+ * See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/visufx.html#propdef-z-index">
+ * z-index property definition </a> in CSS2.
+ *
+ */
+ DOM::DOMString zIndex() const;
+
+ /**
+ * see zIndex
+ */
+ void setZIndex( const DOM::DOMString & );
+};
+
+
+class CSS2TextShadowImpl;
+class CSSValue;
+
+/**
+ * The \c CSS2TextShadow interface represents a simple
+ * value for the <a
+ * href="http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow">
+ * text-shadow </a> CSS Level 2 property.
+ *
+ */
+class CSS2TextShadow
+{
+public:
+ CSS2TextShadow();
+ CSS2TextShadow(const CSS2TextShadow &other);
+ CSS2TextShadow(CSS2TextShadowImpl *impl);
+public:
+
+ CSS2TextShadow & operator = (const CSS2TextShadow &other);
+
+ ~CSS2TextShadow();
+
+ /**
+ * Specified the color of the text shadow. The CSS Value can
+ * contain an empty string if no color has been specified.
+ *
+ */
+ CSSValue color() const;
+
+ /**
+ * The horizontal position of the text shadow. \c 0 if
+ * no length has been specified.
+ *
+ */
+ CSSValue horizontal() const;
+
+ /**
+ * The vertical position of the text shadow. \c 0 if
+ * no length has been specified.
+ *
+ */
+ CSSValue vertical() const;
+
+ /**
+ * The blur radius of the text shadow. \c 0 if no
+ * length has been specified.
+ *
+ */
+ CSSValue blur() const;
+};
+
+
+}; // namespace
+
+#endif
diff --git a/tdehtml/dom/css_rule.cpp b/tdehtml/dom/css_rule.cpp
new file mode 100644
index 000000000..e73ff493a
--- /dev/null
+++ b/tdehtml/dom/css_rule.cpp
@@ -0,0 +1,546 @@
+/**
+ * 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 "css/css_ruleimpl.h"
+
+using namespace DOM;
+
+CSSRule::CSSRule()
+{
+ impl = 0;
+}
+
+CSSRule::CSSRule(const CSSRule &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+CSSRule::CSSRule(CSSRuleImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+CSSRule &CSSRule::operator = (const CSSRule &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSRule::~CSSRule()
+{
+ if(impl) impl->deref();
+}
+
+unsigned short CSSRule::type() const
+{
+ if(!impl) return 0;
+ return ((CSSRuleImpl *)impl)->type();
+}
+
+DOMString CSSRule::cssText() const
+{
+ if(!impl) return DOMString();
+ return impl->cssText();
+}
+
+void CSSRule::setCssText( const DOMString &value )
+{
+ if(!impl) return;
+ impl->setCssText(value);
+}
+
+CSSStyleSheet CSSRule::parentStyleSheet() const
+{
+ if(!impl) return CSSStyleSheet();
+ return ((CSSRuleImpl *)impl)->parentStyleSheet();
+}
+
+CSSRule CSSRule::parentRule() const
+{
+ if(!impl) return 0;
+ return ((CSSRuleImpl *)impl)->parentRule();
+}
+
+CSSRuleImpl *CSSRule::handle() const
+{
+ return impl;
+}
+
+bool CSSRule::isNull() const
+{
+ return (impl == 0);
+}
+
+void CSSRule::assignOther( const CSSRule &other, RuleType thisType )
+{
+ if (other.type() != thisType ) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else
+ CSSRule::operator = ( other );
+}
+
+// ----------------------------------------------------------
+
+
+CSSCharsetRule::CSSCharsetRule()
+ : CSSRule()
+{
+}
+
+CSSCharsetRule::CSSCharsetRule(const CSSCharsetRule &other) : CSSRule(other)
+{
+}
+
+CSSCharsetRule::CSSCharsetRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSCharsetRule::CSSCharsetRule(CSSCharsetRuleImpl *impl) : CSSRule(impl)
+{
+}
+
+CSSCharsetRule &CSSCharsetRule::operator = (const CSSCharsetRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSCharsetRule &CSSCharsetRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::CHARSET_RULE);
+ return *this;
+}
+
+CSSCharsetRule::~CSSCharsetRule()
+{
+}
+
+DOMString CSSCharsetRule::encoding() const
+{
+ if(!impl) return DOMString();
+ return ((CSSCharsetRuleImpl*)impl)->encoding();
+}
+
+void CSSCharsetRule::setEncoding( const DOMString &value )
+{
+ ((CSSCharsetRuleImpl*)impl)->setEncoding(value);
+}
+
+
+// ----------------------------------------------------------
+
+
+CSSFontFaceRule::CSSFontFaceRule() : CSSRule()
+{
+}
+
+CSSFontFaceRule::CSSFontFaceRule(const CSSFontFaceRule &other) : CSSRule(other)
+{
+}
+
+CSSFontFaceRule::CSSFontFaceRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSFontFaceRule::CSSFontFaceRule(CSSFontFaceRuleImpl *impl) : CSSRule(impl)
+{
+}
+
+CSSFontFaceRule &CSSFontFaceRule::operator = (const CSSFontFaceRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSFontFaceRule &CSSFontFaceRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::FONT_FACE_RULE );
+ return *this;
+}
+
+CSSFontFaceRule::~CSSFontFaceRule()
+{
+}
+
+CSSStyleDeclaration CSSFontFaceRule::style() const
+{
+ if(!impl) return CSSStyleDeclaration();
+ return ((CSSFontFaceRuleImpl *)impl)->style();
+}
+
+
+// ----------------------------------------------------------
+
+
+CSSImportRule::CSSImportRule() : CSSRule()
+{
+}
+
+CSSImportRule::CSSImportRule(const CSSImportRule &other) : CSSRule(other)
+{
+}
+
+CSSImportRule::CSSImportRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSImportRule::CSSImportRule(CSSImportRuleImpl *impl) : CSSRule(impl)
+{
+}
+
+CSSImportRule &CSSImportRule::operator = (const CSSImportRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSImportRule &CSSImportRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::IMPORT_RULE );
+ return *this;
+}
+
+CSSImportRule::~CSSImportRule()
+{
+}
+
+DOMString CSSImportRule::href() const
+{
+ if(!impl) return DOMString();
+ return ((CSSImportRuleImpl *)impl)->href();
+}
+
+MediaList CSSImportRule::media() const
+{
+ if(!impl) return MediaList();
+ return ((CSSImportRuleImpl *)impl)->media();
+}
+
+CSSStyleSheet CSSImportRule::styleSheet() const
+{
+ if(!impl) return CSSStyleSheet();
+ return ((CSSImportRuleImpl *)impl)->styleSheet();
+}
+
+
+// ----------------------------------------------------------
+
+
+CSSMediaRule::CSSMediaRule() : CSSRule()
+{
+}
+
+CSSMediaRule::CSSMediaRule(const CSSMediaRule &other) : CSSRule(other)
+{
+}
+
+CSSMediaRule::CSSMediaRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSMediaRule::CSSMediaRule(CSSMediaRuleImpl *impl) : CSSRule(impl)
+{
+}
+
+CSSMediaRule &CSSMediaRule::operator = (const CSSMediaRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSMediaRule &CSSMediaRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::MEDIA_RULE );
+ return *this;
+}
+
+CSSMediaRule::~CSSMediaRule()
+{
+}
+
+MediaList CSSMediaRule::media() const
+{
+ if(!impl) return MediaList();
+ return ((CSSMediaRuleImpl *)impl)->media();
+}
+
+CSSRuleList CSSMediaRule::cssRules() const
+{
+ if(!impl) return CSSRuleList();
+ return ((CSSMediaRuleImpl *)impl)->cssRules();
+}
+
+unsigned long CSSMediaRule::insertRule( const DOMString &rule, unsigned long index )
+{
+ if(!impl) return 0;
+ return ((CSSMediaRuleImpl *)impl)->insertRule( rule, index );
+}
+
+void CSSMediaRule::deleteRule( unsigned long index )
+{
+ if(impl)
+ ((CSSMediaRuleImpl *)impl)->deleteRule( index );
+}
+
+
+// ----------------------------------------------------------
+
+
+CSSPageRule::CSSPageRule() : CSSRule()
+{
+}
+
+CSSPageRule::CSSPageRule(const CSSPageRule &other) : CSSRule(other)
+{
+}
+
+CSSPageRule::CSSPageRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSPageRule::CSSPageRule(CSSPageRuleImpl *impl) : CSSRule(impl)
+{
+}
+
+CSSPageRule &CSSPageRule::operator = (const CSSPageRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSPageRule &CSSPageRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::PAGE_RULE );
+ return *this;
+}
+
+CSSPageRule::~CSSPageRule()
+{
+}
+
+DOMString CSSPageRule::selectorText() const
+{
+ if(!impl) return DOMString();
+ return ((CSSPageRuleImpl*)impl)->selectorText();
+}
+
+void CSSPageRule::setSelectorText( const DOMString &value )
+{
+ ((CSSPageRuleImpl*)impl)->setSelectorText(value);
+}
+
+CSSStyleDeclaration CSSPageRule::style() const
+{
+ if(!impl) return CSSStyleDeclaration();
+ return ((CSSPageRuleImpl *)impl)->style();
+}
+
+
+// ----------------------------------------------------------
+
+CSSStyleRule::CSSStyleRule() : CSSRule()
+{
+}
+
+CSSStyleRule::CSSStyleRule(const CSSStyleRule &other)
+ : CSSRule(other)
+{
+}
+
+CSSStyleRule::CSSStyleRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+
+CSSStyleRule::CSSStyleRule(CSSStyleRuleImpl *impl)
+ : CSSRule(impl)
+{
+}
+
+CSSStyleRule &CSSStyleRule::operator = (const CSSStyleRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSStyleRule &CSSStyleRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::STYLE_RULE );
+ return *this;
+}
+
+CSSStyleRule::~CSSStyleRule()
+{
+}
+
+DOMString CSSStyleRule::selectorText() const
+{
+ if(!impl) return DOMString();
+ return ((CSSStyleRuleImpl*)impl)->selectorText();
+}
+
+void CSSStyleRule::setSelectorText( const DOMString &value )
+{
+ ((CSSStyleRuleImpl*)impl)->setSelectorText(value);
+}
+
+CSSStyleDeclaration CSSStyleRule::style() const
+{
+ if(!impl) return CSSStyleDeclaration();
+ return ((CSSStyleRuleImpl *)impl)->style();
+}
+
+
+// ----------------------------------------------------------
+
+
+CSSUnknownRule::CSSUnknownRule() : CSSRule()
+{
+}
+
+CSSUnknownRule::CSSUnknownRule(const CSSUnknownRule &other)
+ : CSSRule(other)
+{
+}
+
+CSSUnknownRule::CSSUnknownRule(const CSSRule &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSUnknownRule::CSSUnknownRule(CSSUnknownRuleImpl *impl)
+ : CSSRule(impl)
+{
+}
+
+CSSUnknownRule &CSSUnknownRule::operator = (const CSSUnknownRule &other)
+{
+ CSSRule::operator = (other);
+ return *this;
+}
+
+CSSUnknownRule &CSSUnknownRule::operator = (const CSSRule &other)
+{
+ assignOther( other, CSSRule::UNKNOWN_RULE );
+ return *this;
+}
+
+CSSUnknownRule::~CSSUnknownRule()
+{
+}
+
+
+// ----------------------------------------------------------
+
+CSSRuleList::CSSRuleList()
+{
+ impl = 0;
+}
+
+CSSRuleList::CSSRuleList(const CSSRuleList &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+CSSRuleList::CSSRuleList(CSSRuleListImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+CSSRuleList::CSSRuleList(StyleListImpl *lst)
+{
+ impl = new CSSRuleListImpl;
+ impl->ref();
+ if (lst)
+ {
+ for( unsigned long i = 0; i < lst->length() ; ++i )
+ {
+ StyleBaseImpl* style = lst->item( i );
+ if ( style->isRule() )
+ impl->insertRule( static_cast<CSSRuleImpl *>(style), impl->length() );
+ }
+ }
+}
+
+CSSRuleList &CSSRuleList::operator = (const CSSRuleList &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSRuleList::~CSSRuleList()
+{
+ if(impl) impl->deref();
+}
+
+unsigned long CSSRuleList::length() const
+{
+ if(!impl) return 0;
+ return ((CSSRuleListImpl *)impl)->length();
+ return 0;
+}
+
+CSSRule CSSRuleList::item( unsigned long index )
+{
+ if(!impl) return CSSRule();
+ return ((CSSRuleListImpl *)impl)->item( index );
+}
+
+CSSRuleListImpl *CSSRuleList::handle() const
+{
+ return impl;
+}
+
+bool CSSRuleList::isNull() const
+{
+ return (impl == 0);
+}
+
+
+
+
diff --git a/tdehtml/dom/css_rule.h b/tdehtml/dom/css_rule.h
new file mode 100644
index 000000000..5f27e8f8a
--- /dev/null
+++ b/tdehtml/dom/css_rule.h
@@ -0,0 +1,534 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Candidate Recommendation)
+ * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _CSS_css_rule_h_
+#define _CSS_css_rule_h_
+
+#include <dom/dom_string.h>
+#include <dom/css_stylesheet.h>
+#include <dom/css_value.h>
+
+namespace DOM {
+
+class CSSRuleImpl;
+
+/**
+ * The \c CSSRule interface is the abstract base interface
+ * for any type of CSS <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#q5"> statement
+ * </a> . This includes both <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8"> rule sets
+ * </a> and <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#at-rules">
+ * at-rules </a> . An implementation is expected to preserve all rules
+ * specified in a CSS style sheet, even if it is not recognized.
+ * Unrecognized rules are represented using the \c CSSUnknownRule
+ * interface.
+ *
+ */
+class KHTML_EXPORT CSSRule
+{
+public:
+ CSSRule();
+ CSSRule(const CSSRule &other);
+ CSSRule(CSSRuleImpl *impl);
+public:
+
+ CSSRule & operator = (const CSSRule &other);
+
+ ~CSSRule();
+ /**
+ * An integer indicating which type of rule this is.
+ *
+ */
+ enum RuleType {
+ UNKNOWN_RULE = 0,
+ STYLE_RULE = 1,
+ CHARSET_RULE = 2,
+ IMPORT_RULE = 3,
+ MEDIA_RULE = 4,
+ FONT_FACE_RULE = 5,
+ PAGE_RULE = 6,
+ QUIRKS_RULE = 100 // KHTML CSS Extension
+ };
+
+ /**
+ * The type of the rule, as defined above. The expectation is that
+ * binding-specific casting methods can be used to cast down from
+ * an instance of the \c CSSRule interface to the
+ * specific derived interface implied by the \c type .
+ *
+ */
+ unsigned short type() const;
+
+ /**
+ * The parsable textual representation of the rule. This reflects
+ * the current state of the rule and not its initial value.
+ *
+ */
+ DOM::DOMString cssText() const;
+
+ /**
+ * see cssText
+ * @exception DOMException
+ *
+ * HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted
+ * at this point in the style sheet.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this style sheet is
+ * readonly.
+ *
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * INVALID_MODIFICATION_ERR: Raised if the specified CSS string value
+ * represents a different type of rule than the current one.
+ */
+ void setCssText( const DOM::DOMString & );
+
+ /**
+ * The style sheet that contains this rule.
+ *
+ */
+ CSSStyleSheet parentStyleSheet() const;
+
+ /**
+ * If this rule is contained inside another rule (e.g. a style
+ * rule inside an \@media block), this is the containing rule. If
+ * this rule is not nested inside any other rules, this returns
+ * \c null .
+ *
+ */
+ CSSRule parentRule() const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ CSSRuleImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ CSSRuleImpl *impl;
+
+ void assignOther( const CSSRule &other, RuleType thisType );
+};
+
+class CSSCharsetRuleImpl;
+
+/**
+ * The \c CSSCharsetRule interface a <a href=""> \@charset
+ * rule </a> in a CSS style sheet. A \c \@charset rule can
+ * be used to define the encoding of the style sheet.
+ *
+ */
+class KHTML_EXPORT CSSCharsetRule : public CSSRule
+{
+public:
+ CSSCharsetRule();
+ CSSCharsetRule(const CSSCharsetRule &other);
+ CSSCharsetRule(const CSSRule &other);
+ CSSCharsetRule(CSSCharsetRuleImpl *impl);
+public:
+
+ CSSCharsetRule & operator = (const CSSCharsetRule &other);
+ CSSCharsetRule & operator = (const CSSRule &other);
+
+ ~CSSCharsetRule();
+
+ /**
+ * The encoding information used in this \c \@charset
+ * rule.
+ *
+ */
+ DOM::DOMString encoding() const;
+
+ /**
+ * see encoding
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified encoding value has a syntax
+ * error and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this encoding rule is
+ * readonly.
+ *
+ */
+ void setEncoding( const DOM::DOMString & );
+};
+
+
+class CSSFontFaceRuleImpl;
+/**
+ * The \c CSSFontFaceRule interface represents a <a
+ * href="http://www.w3.org/TR/REC-CSS2/fonts.html#font-descriptions">
+ * \c \@font-face rule </a> in a CSS style sheet. The \c \@font-face
+ * rule is used to hold a set of font descriptions.
+ *
+ */
+class KHTML_EXPORT CSSFontFaceRule : public CSSRule
+{
+public:
+ CSSFontFaceRule();
+ CSSFontFaceRule(const CSSFontFaceRule &other);
+ CSSFontFaceRule(const CSSRule &other);
+ CSSFontFaceRule(CSSFontFaceRuleImpl *impl);
+public:
+
+ CSSFontFaceRule & operator = (const CSSFontFaceRule &other);
+ CSSFontFaceRule & operator = (const CSSRule &other);
+
+ ~CSSFontFaceRule();
+
+ /**
+ * The <a href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8">
+ * declaration-block </a> of this rule.
+ *
+ */
+ CSSStyleDeclaration style() const;
+};
+
+class CSSImportRuleImpl;
+/**
+ * The \c CSSImportRule interface represents a <a
+ * href="http://www.w3.org/TR/REC-CSS2/cascade.html#at-import">
+ * \c \@import rule </a> within a CSS style sheet. The \c \@import
+ * rule is used to import style rules from other style sheets.
+ *
+ */
+class KHTML_EXPORT CSSImportRule : public CSSRule
+{
+public:
+ CSSImportRule();
+ CSSImportRule(const CSSImportRule &other);
+ CSSImportRule(const CSSRule &other);
+ CSSImportRule(CSSImportRuleImpl *impl);
+public:
+
+ CSSImportRule & operator = (const CSSImportRule &other);
+ CSSImportRule & operator = (const CSSRule &other);
+
+ ~CSSImportRule();
+
+ /**
+ * The location of the style sheet to be imported. The attribute
+ * will not contain the \c "url(...)" specifier around
+ * the URI.
+ *
+ */
+ DOM::DOMString href() const;
+
+ /**
+ * A list of media types for which this style sheet may be used.
+ *
+ */
+ MediaList media() const;
+
+ /**
+ * The style sheet referred to by this rule, if it has been
+ * loaded. The value of this attribute is null if the style sheet
+ * has not yet been loaded or if it will not be loaded (e.g. if
+ * the style sheet is for a media type not supported by the user
+ * agent).
+ *
+ */
+ CSSStyleSheet styleSheet() const;
+};
+
+class CSSMediaRuleImpl;
+/**
+ * The \c CSSMediaRule interface represents a <a
+ * href="http://www.w3.org/TR/REC-CSS2/media.html#at-media-rule">
+ * \@media rule </a> in a CSS style sheet. A \c \@media rule
+ * can be used to delimit style rules for specific media types.
+ *
+ */
+class KHTML_EXPORT CSSMediaRule : public CSSRule
+{
+public:
+ CSSMediaRule();
+ CSSMediaRule(const CSSMediaRule &other);
+ CSSMediaRule(const CSSRule &other);
+ CSSMediaRule(CSSMediaRuleImpl *impl);
+public:
+
+ CSSMediaRule & operator = (const CSSMediaRule &other);
+ CSSMediaRule & operator = (const CSSRule &other);
+
+ ~CSSMediaRule();
+
+ /**
+ * A list of <a
+ * href="http://www.w3.org/TR/REC-CSS2/media.html#media-types">
+ * media types </a> for this rule.
+ *
+ */
+ MediaList media() const;
+
+ /**
+ * A list of all CSS rules contained within the media block.
+ *
+ */
+ CSSRuleList cssRules() const;
+
+ /**
+ * Used to insert a new rule into the media block.
+ *
+ * @param rule The parsable text representing the rule. For rule
+ * sets this contains both the selector and the style declaration.
+ * For at-rules, this specifies both the at-identifier and the
+ * rule content.
+ *
+ * @param index The index within the media block's rule collection
+ * of the rule before which to insert the specified rule. If the
+ * specified index is equal to the length of the media blocks's
+ * rule collection, the rule will be added to the end of the media
+ * block.
+ *
+ * @return The index within the media block's rule collection of
+ * the newly inserted rule.
+ *
+ * \exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at
+ * the specified index. e.g. if an \c \@import rule is
+ * inserted after a standard rule set or other at-rule.
+ *
+ * INDEX_SIZE_ERR: Raised if the specified index is not a valid
+ * insertion point.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this media rule is
+ * readonly.
+ *
+ * \exception CSSException
+ * SYNTAX_ERR: Raised if the specified rule has a syntax error
+ * and is unparsable.
+ *
+ */
+ unsigned long insertRule ( const DOM::DOMString &rule, unsigned long index );
+
+ /**
+ * Used to delete a rule from the media block.
+ *
+ * @param index The index within the media block's rule collection
+ * of the rule to remove.
+ *
+ * @return
+ *
+ * \exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified index does not
+ * correspond to a rule in the media rule list.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this media rule is
+ * readonly.
+ *
+ */
+ void deleteRule ( unsigned long index );
+};
+
+
+class CSSPageRuleImpl;
+/**
+ * The \c CSSPageRule interface represents a <a
+ * href="http://www.w3.org/TR/REC-CSS2/page.html#page-box"> page rule
+ * </a> within a CSS style sheet. The \c @page rule is
+ * used to specify the dimensions, orientation, margins, etc. of a
+ * page box for paged media.
+ *
+ */
+class KHTML_EXPORT CSSPageRule : public CSSRule
+{
+public:
+ CSSPageRule();
+ CSSPageRule(const CSSPageRule &other);
+ CSSPageRule(const CSSRule &other);
+ CSSPageRule(CSSPageRuleImpl *impl);
+public:
+
+ CSSPageRule & operator = (const CSSPageRule &other);
+ CSSPageRule & operator = (const CSSRule &other);
+
+ ~CSSPageRule();
+
+ /**
+ * The parsable textual representation of the page selector for
+ * the rule.
+ *
+ */
+ DOM::DOMString selectorText() const;
+
+ /**
+ * see selectorText
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this style sheet is
+ * readonly.
+ *
+ */
+ void setSelectorText( const DOM::DOMString & );
+
+ /**
+ * The <a href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8">
+ * declaration-block </a> of this rule.
+ *
+ */
+ CSSStyleDeclaration style() const;
+};
+
+class CSSStyleRuleImpl;
+/**
+ * The \c CSSStyleRule interface represents a single <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8"> rule set </a>
+ * in a CSS style sheet.
+ *
+ */
+class KHTML_EXPORT CSSStyleRule : public CSSRule
+{
+public:
+ CSSStyleRule();
+ CSSStyleRule(const CSSStyleRule &other);
+ CSSStyleRule(const CSSRule &other);
+ CSSStyleRule(CSSStyleRuleImpl *impl);
+public:
+
+ CSSStyleRule & operator = (const CSSStyleRule &other);
+ CSSStyleRule & operator = (const CSSRule &other);
+
+ ~CSSStyleRule();
+
+ /**
+ * The textual representation of the <a
+ * href="http://www.w3.org/TR/REC-CSS2/selector.html"> selector
+ * </a> for the rule set. The implementation may have stripped out
+ * insignificant whitespace while parsing the selector.
+ *
+ */
+ DOM::DOMString selectorText() const;
+
+ /**
+ * see selectorText
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this style sheet is
+ * readonly.
+ *
+ */
+ void setSelectorText( const DOM::DOMString & );
+
+ /**
+ * The <a href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8">
+ * declaration-block </a> of this rule set.
+ *
+ */
+ CSSStyleDeclaration style() const;
+};
+
+class CSSUnknownRuleImpl;
+/**
+ * The \c CSSUnkownRule interface represents an at-rule
+ * not supported by this user agent.
+ *
+ */
+class KHTML_EXPORT CSSUnknownRule : public CSSRule
+{
+public:
+ CSSUnknownRule();
+ CSSUnknownRule(const CSSUnknownRule &other);
+ CSSUnknownRule(const CSSRule &other);
+ CSSUnknownRule(CSSUnknownRuleImpl *impl);
+public:
+
+ CSSUnknownRule & operator = (const CSSUnknownRule &other);
+ CSSUnknownRule & operator = (const CSSRule &other);
+
+ ~CSSUnknownRule();
+};
+
+
+class CSSRuleListImpl;
+class StyleListImpl;
+/**
+ * The \c CSSRuleList interface provides the abstraction
+ * of an ordered collection of CSS rules.
+ *
+ */
+class KHTML_EXPORT CSSRuleList
+{
+public:
+ CSSRuleList();
+ CSSRuleList(const CSSRuleList &other);
+ CSSRuleList(CSSRuleListImpl *i);
+ CSSRuleList(StyleListImpl *i);
+public:
+
+ CSSRuleList & operator = (const CSSRuleList &other);
+
+ ~CSSRuleList();
+
+ /**
+ * The number of \c CSSRule s in the list. The range
+ * of valid child rule indices is \c 0 to
+ * \c length-1 inclusive.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Used to retrieve a CSS rule by ordinal index. The order in this
+ * collection represents the order of the rules in the CSS style
+ * sheet.
+ *
+ * @param index Index into the collection
+ *
+ * @return The style rule at the \c index position in
+ * the \c CSSRuleList , or \c null if that
+ * is not a valid index.
+ *
+ */
+ CSSRule item ( unsigned long index );
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ CSSRuleListImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ // we just need a pointer to an implementation here.
+ CSSRuleListImpl *impl;
+};
+
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/css_stylesheet.cpp b/tdehtml/dom/css_stylesheet.cpp
new file mode 100644
index 000000000..ab5ce1451
--- /dev/null
+++ b/tdehtml/dom/css_stylesheet.cpp
@@ -0,0 +1,457 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2003 Apple Compputer, 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 "dom/dom_exception.h"
+#include "dom/css_rule.h"
+#include "dom/dom_doc.h"
+
+#include "xml/dom_docimpl.h"
+
+#include "html/html_headimpl.h"
+
+#include "css/css_stylesheetimpl.h"
+#include "misc/htmlhashes.h"
+
+#include <stdio.h>
+
+using namespace DOM;
+
+StyleSheet::StyleSheet()
+{
+ impl = 0;
+}
+
+StyleSheet::StyleSheet(const StyleSheet &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+StyleSheet::StyleSheet(StyleSheetImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+StyleSheet &StyleSheet::operator = (const StyleSheet &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+StyleSheet::~StyleSheet()
+{
+ if(impl) impl->deref();
+}
+
+DOMString StyleSheet::type() const
+{
+ if(!impl) return DOMString();
+ return ((StyleSheetImpl *)impl)->type();
+}
+
+bool StyleSheet::disabled() const
+{
+ if(!impl) return 0;
+ return ((StyleSheetImpl *)impl)->disabled();
+}
+
+void StyleSheet::setDisabled( bool _disabled )
+{
+ if(impl)
+ ((StyleSheetImpl *)impl)->setDisabled( _disabled );
+}
+
+DOM::Node StyleSheet::ownerNode() const
+{
+ if(!impl) return Node();
+ return ((StyleSheetImpl *)impl)->ownerNode();
+}
+
+StyleSheet StyleSheet::parentStyleSheet() const
+{
+ if(!impl) return 0;
+ return ((StyleSheetImpl *)impl)->parentStyleSheet();
+}
+
+DOMString StyleSheet::href() const
+{
+ if(!impl) return DOMString();
+ return ((StyleSheetImpl *)impl)->href();
+}
+
+DOMString StyleSheet::title() const
+{
+ if(!impl) return DOMString();
+ return ((StyleSheetImpl *)impl)->title();
+}
+
+MediaList StyleSheet::media() const
+{
+ if(!impl) return 0;
+ return ((StyleSheetImpl *)impl)->media();
+}
+
+bool StyleSheet::isCSSStyleSheet() const
+{
+ if(!impl) return false;
+ return ((StyleSheetImpl *)impl)->isCSSStyleSheet();
+}
+
+CSSStyleSheet::CSSStyleSheet() : StyleSheet()
+{
+}
+
+CSSStyleSheet::CSSStyleSheet(const CSSStyleSheet &other) : StyleSheet(other)
+{
+}
+
+CSSStyleSheet::CSSStyleSheet(const StyleSheet &other)
+{
+ if (!other.isCSSStyleSheet())
+ impl = 0;
+ else
+ operator=(other);
+}
+
+CSSStyleSheet::CSSStyleSheet(CSSStyleSheetImpl *impl) : StyleSheet(impl)
+{
+}
+
+CSSStyleSheet &CSSStyleSheet::operator = (const CSSStyleSheet &other)
+{
+ StyleSheet::operator = (other);
+ return *this;
+}
+
+CSSStyleSheet &CSSStyleSheet::operator = (const StyleSheet &other)
+{
+ if(!other.handle()->isCSSStyleSheet())
+ {
+ if(impl) impl->deref();
+ impl = 0;
+ } else {
+ StyleSheet::operator = (other);
+ }
+ return *this;
+}
+
+CSSStyleSheet::~CSSStyleSheet()
+{
+}
+
+CSSRule CSSStyleSheet::ownerRule() const
+{
+ if(!impl) return 0;
+ return ((CSSStyleSheetImpl *)impl)->ownerRule();
+}
+
+CSSRuleList CSSStyleSheet::cssRules() const
+{
+ if(!impl) return (CSSRuleListImpl*)0;
+ return ((CSSStyleSheetImpl *)impl)->cssRules();
+}
+
+unsigned long CSSStyleSheet::insertRule( const DOMString &rule, unsigned long index )
+{
+ int exceptioncode = 0;
+ if(!impl) return 0;
+ unsigned long retval = ((CSSStyleSheetImpl *)impl)->insertRule( rule, index, exceptioncode );
+ if ( exceptioncode >= CSSException::_EXCEPTION_OFFSET )
+ throw CSSException( exceptioncode - CSSException::_EXCEPTION_OFFSET );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return retval;
+}
+
+void CSSStyleSheet::deleteRule( unsigned long index )
+{
+ int exceptioncode = 0;
+ if(impl)
+ ((CSSStyleSheetImpl *)impl)->deleteRule( index, exceptioncode );
+ if ( exceptioncode >= CSSException::_EXCEPTION_OFFSET )
+ throw CSSException( exceptioncode - CSSException::_EXCEPTION_OFFSET );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+
+
+StyleSheetList::StyleSheetList()
+{
+ impl = 0;
+}
+
+StyleSheetList::StyleSheetList(const StyleSheetList &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+StyleSheetList::StyleSheetList(StyleSheetListImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+StyleSheetList &StyleSheetList::operator = (const StyleSheetList &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+StyleSheetList::~StyleSheetList()
+{
+ if(impl) impl->deref();
+}
+
+unsigned long StyleSheetList::length() const
+{
+ if(!impl) return 0;
+ return ((StyleSheetListImpl *)impl)->length();
+}
+
+StyleSheet StyleSheetList::item( unsigned long index )
+{
+ if(!impl) return StyleSheet();
+ return ((StyleSheetListImpl *)impl)->item( index );
+}
+
+StyleSheetListImpl *StyleSheetList::handle() const
+{
+ return impl;
+}
+
+bool StyleSheetList::isNull() const
+{
+ return (impl == 0);
+}
+
+// ----------------------------------------------------------
+
+MediaList::MediaList()
+{
+ impl = 0;
+}
+
+MediaList::MediaList(const MediaList &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+MediaList::MediaList(MediaListImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+MediaList &MediaList::operator = (const MediaList &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+MediaList::~MediaList()
+{
+ if(impl) impl->deref();
+}
+
+DOM::DOMString MediaList::mediaText() const
+{
+ if(!impl) return DOMString();
+ return static_cast<MediaListImpl *>(impl)->mediaText();
+}
+
+void MediaList::setMediaText(const DOM::DOMString &value )
+{
+ if(impl)
+ static_cast<MediaListImpl *>(impl)->setMediaText( value );
+}
+
+unsigned long MediaList::length() const
+{
+ if(!impl) return 0;
+ return ((MediaListImpl *)impl)->length();
+}
+
+DOM::DOMString MediaList::item(unsigned long index) const
+{
+ if(!impl) return DOMString();
+ return ((MediaListImpl *)impl)->item( index );
+}
+
+void MediaList::deleteMedium(const DOM::DOMString &oldMedium)
+{
+ if(impl)
+ ((MediaListImpl *)impl)->deleteMedium( oldMedium );
+}
+
+void MediaList::appendMedium(const DOM::DOMString &newMedium)
+{
+ if(impl)
+ ((MediaListImpl *)impl)->appendMedium( newMedium );
+}
+
+MediaListImpl *MediaList::handle() const
+{
+ return impl;
+}
+
+bool MediaList::isNull() const
+{
+ return (impl == 0);
+}
+
+// ----------------------------------------------------------
+
+LinkStyle::LinkStyle()
+{
+ node = 0;
+}
+
+LinkStyle::LinkStyle(const LinkStyle &other)
+{
+ node = other.node;
+ if(node) node->ref();
+}
+
+LinkStyle & LinkStyle::operator = (const LinkStyle &other)
+{
+ if ( node != other.node ) {
+ if(node) node->deref();
+ node = other.node;
+ if(node) node->ref();
+ }
+ return *this;
+}
+
+LinkStyle & LinkStyle::operator = (const Node &other)
+{
+ if(node) node->deref();
+ node = 0;
+ // ### add processing instructions
+ NodeImpl *n = other.handle();
+
+ // ### check link is really linking a style sheet
+ if( n && n->isElementNode() &&
+ (n->id() == ID_STYLE || n->id() == ID_LINK) ) {
+ node = n;
+ if(node) node->ref();
+ }
+ return *this;
+}
+
+LinkStyle::~LinkStyle()
+{
+ if(node) node->deref();
+}
+
+StyleSheet LinkStyle::sheet()
+{
+ int id = node ? node->id() : 0;
+ // ### add PI
+ return
+ ( id == ID_STYLE) ?
+ static_cast<HTMLStyleElementImpl *>(node)->sheet()
+ : ( (id == ID_LINK) ?
+ static_cast<HTMLLinkElementImpl *>(node)->sheet()
+ : StyleSheet() );
+}
+
+bool LinkStyle::isNull() const
+{
+ return (node == 0);
+}
+
+
+// ----------------------------------------------------------
+
+DocumentStyle::DocumentStyle()
+{
+ doc = 0;
+}
+
+DocumentStyle::DocumentStyle(const DocumentStyle &other)
+{
+ doc = other.doc;
+ if(doc) doc->ref();
+}
+
+DocumentStyle & DocumentStyle::operator = (const DocumentStyle &other)
+{
+ if ( doc != other.doc ) {
+ if(doc) doc->deref();
+ doc = other.doc;
+ if(doc) doc->ref();
+ }
+ return *this;
+}
+
+DocumentStyle & DocumentStyle::operator = (const Document &other)
+{
+ DocumentImpl *odoc = static_cast<DocumentImpl *>(other.handle());
+ if ( doc != odoc ) {
+ if(doc) doc->deref();
+ doc = odoc;
+ if(doc) doc->ref();
+ }
+ return *this;
+}
+
+DocumentStyle::~DocumentStyle()
+{
+ if(doc) doc->deref();
+}
+
+StyleSheetList DocumentStyle::styleSheets()
+{
+ return doc->styleSheets();
+}
+
+DOMString DocumentStyle::preferredStylesheetSet() const
+{
+ return doc->preferredStylesheetSet();
+}
+
+void DocumentStyle::setSelectedStylesheetSet(const DOMString& aStr)
+{
+ return doc->setSelectedStylesheetSet(aStr);
+}
+
+DOMString DocumentStyle::selectedStylesheetSet() const
+{
+ return doc->selectedStylesheetSet();
+}
diff --git a/tdehtml/dom/css_stylesheet.h b/tdehtml/dom/css_stylesheet.h
new file mode 100644
index 000000000..d220ffa76
--- /dev/null
+++ b/tdehtml/dom/css_stylesheet.h
@@ -0,0 +1,496 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Candidate Recommendation)
+ * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _CSS_css_stylesheet_h_
+#define _CSS_css_stylesheet_h_
+
+#include <dom/dom_string.h>
+#include <dom/dom_node.h>
+#include <dom/dom_misc.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class StyleSheetImpl;
+class MediaList;
+class NodeImpl;
+class DocumentImpl;
+
+/**
+ * The \c StyleSheet interface is the abstract base
+ * interface for any type of style sheet. It represents a single style
+ * sheet associated with a structured document. In HTML, the
+ * StyleSheet interface represents either an external style sheet,
+ * included via the HTML <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#h-12.3">
+ * LINK </a> element, or an inline <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#h-14.2.3">
+ * STYLE </a> element. In XML, this interface represents an external
+ * style sheet, included via a <a
+ * href="http://www.w3.org/TR/xml-stylesheet"> style sheet processing
+ * instruction </a> .
+ *
+ */
+class KHTML_EXPORT StyleSheet
+{
+public:
+ StyleSheet();
+ StyleSheet(const StyleSheet &other);
+ StyleSheet(StyleSheetImpl *impl);
+public:
+
+ StyleSheet & operator = (const StyleSheet &other);
+
+ ~StyleSheet();
+
+ /**
+ * This specifies the style sheet language for this style sheet.
+ * The style sheet language is specified as a content type (e.g.
+ * "text/css"). The content type is often specified in the
+ * \c ownerNode . A list of registered content types can be
+ * found at <a
+ * href="ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/">
+ * ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/ </a> .
+ * Also see the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-type-A">
+ * type attribute definition </a> for the \c LINK
+ * element in HTML 4.0, and the type pseudo-attribute for the XML
+ * <a href="http://www.w3.org/TR/xml-stylesheet"> style sheet
+ * processing instruction </a> .
+ *
+ */
+ DOM::DOMString type() const;
+
+ /**
+ * \c false if the style sheet is applied to the
+ * document. \c true if it is not. Modifying this
+ * attribute may cause a reresolution of style for the document.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * The node that associates this style sheet with the document.
+ * For HTML, this may be the corresponding \c LINK or
+ * \c STYLE element. For XML, it may be the linking
+ * processing instruction. For style sheets that are included by
+ * other style sheets, this attribute has a value of null.
+ *
+ */
+ DOM::Node ownerNode() const;
+
+ /**
+ * For style sheet languages that support the concept of style
+ * sheet inclusion, this attribute represents the including style
+ * sheet, if one exists. If the style sheet is a top-level style
+ * sheet, or the style sheet language does not support inclusion,
+ * the value of the attribute is null.
+ *
+ */
+ StyleSheet parentStyleSheet() const;
+
+ /**
+ * If the style sheet is a linked style sheet, the value of its
+ * attribute is its location. For inline style sheets, the value
+ * of this attribute is null. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-href">
+ * href attribute definition </a> for the \c LINK
+ * element in HTML 4.0, and the href pseudo-attribute for the XML
+ * <a href="http://www.w3.org/TR/xml-stylesheet"> style sheet
+ * processing instruction </a> .
+ *
+ */
+ DOM::DOMString href() const;
+
+ /**
+ * The advisory title. The title is often specified in the
+ * \c ownerNode . See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-title">
+ * title attribute definition </a> for the \c LINK
+ * element in HTML 4.0, and the title pseudo-attribute for the XML
+ * <a href="http://www.w3.org/TR/xml-stylesheet"> style sheet
+ * processing instruction </a> .
+ *
+ */
+ DOM::DOMString title() const;
+
+ /**
+ * The intended destination media for style information. The media
+ * is often specified in the \c ownerNode . See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#adef-media">
+ * media attribute definition </a> for the \c LINK
+ * element in HTML 4.0, and the media pseudo-attribute for the XML
+ * <a href="http://www.w3.org/TR/WD-xml-stylesheet"> style sheet
+ * processing instruction </a> .
+ *
+ */
+ MediaList media() const;
+
+ /**
+ * @internal
+ */
+ bool isCSSStyleSheet() const;
+ StyleSheetImpl *handle() const { return impl; }
+ bool isNull() const { return !impl; }
+protected:
+ StyleSheetImpl *impl;
+};
+
+
+/**
+ * This exception is raised when a specific CSS operation is impossible
+ * to perform.
+ */
+class KHTML_EXPORT CSSException
+{
+public:
+ CSSException(unsigned short _code) { code = _code; }
+ CSSException(const CSSException &other) { code = other.code; }
+
+ CSSException & operator = (const CSSException &other)
+ { code = other.code; return *this; }
+
+ virtual ~CSSException() {}
+ /**
+ * An integer indicating the type of error generated.
+ *
+ */
+ unsigned short code;
+
+ enum ExceptionCode
+ {
+ SYNTAX_ERR = 0,
+ INVALID_MODIFICATION_ERR = 1,
+ _EXCEPTION_OFFSET = 1000
+ };
+};
+
+class CSSStyleSheetImpl;
+class CSSRule;
+class CSSRuleList;
+
+/**
+ * The \c CSSStyleSheet interface is a concrete interface
+ * used to represent a CSS style sheet i.e. a style sheet whose
+ * content type is "text/css".
+ *
+ */
+class KHTML_EXPORT CSSStyleSheet : public StyleSheet
+{
+public:
+ CSSStyleSheet();
+ CSSStyleSheet(const CSSStyleSheet &other);
+ CSSStyleSheet(const StyleSheet &other);
+ CSSStyleSheet(CSSStyleSheetImpl *impl);
+public:
+
+ CSSStyleSheet & operator = (const CSSStyleSheet &other);
+ CSSStyleSheet & operator = (const StyleSheet &other);
+
+ ~CSSStyleSheet();
+
+ /**
+ * If this style sheet comes from an \c \@import rule,
+ * the \c ownerRule attribute will contain the
+ * \c CSSImportRule . In that case, the \c ownerNode
+ * attribute in the \c StyleSheet interface
+ * will be \c null . If the style sheet comes from an
+ * element or a processing instruction, the \c ownerRule
+ * attribute will be \c null and the
+ * \c ownerNode attribute will contain the \c Node .
+ *
+ */
+ CSSRule ownerRule() const;
+
+ /**
+ * The list of all CSS rules contained within the style sheet.
+ * This includes both <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#q8"> rule sets
+ * </a> and <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#at-rules">
+ * at-rules </a> .
+ *
+ */
+ CSSRuleList cssRules() const;
+
+ /**
+ * Used to insert a new rule into the style sheet. The new rule
+ * now becomes part of the cascade.
+ *
+ * @param rule The parsable text representing the rule. For rule
+ * sets this contains both the selector and the style declaration.
+ * For at-rules, this specifies both the at-identifier and the
+ * rule content.
+ *
+ * @param index The index within the style sheet's rule list of
+ * the rule before which to insert the specified rule. If the
+ * specified index is equal to the length of the style sheet's
+ * rule collection, the rule will be added to the end of the style
+ * sheet.
+ *
+ * @return The index within the style sheet's rule collection of
+ * the newly inserted rule.
+ *
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at
+ * the specified index e.g. if an \c \@import rule is
+ * inserted after a standard rule set or other at-rule.
+ *
+ * INDEX_SIZE_ERR: Raised if the specified index is not a valid
+ * insertion point.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this style sheet is
+ * readonly.
+ *
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified rule has a syntax error
+ * and is unparsable.
+ *
+ */
+ unsigned long insertRule ( const DOM::DOMString &rule, unsigned long index );
+
+ /**
+ * Used to delete a rule from the style sheet.
+ *
+ * @param index The index within the style sheet's rule list of
+ * the rule to remove.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified index does not
+ * correspond to a rule in the style sheet's rule list.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this style sheet is
+ * readonly.
+ *
+ */
+ void deleteRule ( unsigned long index );
+};
+
+
+class StyleSheetListImpl;
+class StyleSheet;
+
+/**
+ * The \c StyleSheetList interface provides the
+ * abstraction of an ordered collection of style sheets.
+ *
+ */
+class KHTML_EXPORT StyleSheetList
+{
+public:
+ StyleSheetList();
+ StyleSheetList(const StyleSheetList &other);
+ StyleSheetList(StyleSheetListImpl *impl);
+public:
+
+ StyleSheetList & operator = (const StyleSheetList &other);
+
+ ~StyleSheetList();
+
+ /**
+ * The number of \c StyleSheet in the list. The range
+ * of valid child stylesheet indices is \c 0 to
+ * \c length-1 inclusive.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Used to retrieve a style sheet by ordinal index.
+ *
+ * @param index Index into the collection
+ *
+ * @return The style sheet at the \c index position in
+ * the \c StyleSheetList , or \c null if
+ * that is not a valid index.
+ *
+ */
+ StyleSheet item ( unsigned long index );
+
+ /**
+ * @internal
+ */
+ StyleSheetListImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ StyleSheetListImpl *impl;
+};
+
+
+class MediaListImpl;
+class CSSRule;
+class CSSStyleSheet;
+
+/**
+ * The \c MediaList interface provides the abstraction of
+ * an ordered collection of media, without defining or constraining
+ * how this collection is implemented. All media are lowercase
+ * strings.
+ *
+ */
+class KHTML_EXPORT MediaList
+{
+public:
+ MediaList();
+ MediaList(const MediaList &other);
+ MediaList(MediaListImpl *impl);
+public:
+
+ MediaList & operator = (const MediaList &other);
+
+ ~MediaList();
+
+ /**
+ * The parsable textual representation of the media list. This is a
+ * comma-separated list of media.
+ *
+ * @exception DOMException
+ * SYNTAX_ERR: Raised if the specified string value has a syntax error and
+ * is unparsable.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this media list is readonly.
+ */
+ DOM::DOMString mediaText() const;
+
+ /**
+ * see mediaText
+ */
+ void setMediaText(const DOM::DOMString &value);
+
+ /**
+ * The number of media in the list. The range of valid media is 0 to length-1 inclusive.
+ */
+ unsigned long length() const;
+
+
+ /**
+ * Returns the indexth in the list. If index is greater than or equal to
+ * the number of media in the list, this returns null.
+ *
+ * @param index Index into the collection.
+ *
+ * @return The medium at the indexth position in the MediaList, or null if
+ * that is not a valid index.
+ */
+ DOM::DOMString item(unsigned long index) const;
+
+ /**
+ * Deletes the medium indicated by oldMedium from the list.
+ *
+ * @param oldMedium The medium to delete in the media list.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this list is readonly.
+ *
+ * NOT_FOUND_ERR: Raised if oldMedium is not in the list.
+ */
+ void deleteMedium(const DOM::DOMString &oldMedium);
+
+ /**
+ * Adds the medium newMedium to the end of the list. If the newMedium is
+ * already used, it is first removed.
+ *
+ * @param newMedium The new medium to add.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: If the medium contains characters that are
+ * invalid in the underlying style language.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this list is readonly.
+ */
+ void appendMedium(const DOM::DOMString &newMedium);
+
+ /**
+ * @internal
+ */
+ MediaListImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ MediaListImpl *impl;
+};
+
+class LinkStyleImpl;
+
+class KHTML_EXPORT LinkStyle
+{
+public:
+ LinkStyle();
+ LinkStyle(const LinkStyle &other);
+
+ LinkStyle & operator = (const LinkStyle &other);
+ LinkStyle & operator = (const Node &other);
+
+ ~LinkStyle();
+
+ StyleSheet sheet();
+
+ bool isNull() const;
+
+protected:
+ DOM::NodeImpl *node;
+ LinkStyleImpl *impl;
+};
+
+class DocumentStyleImpl;
+
+class KHTML_EXPORT DocumentStyle
+{
+public:
+ DocumentStyle();
+ DocumentStyle(const DocumentStyle &other);
+
+ DocumentStyle & operator = (const DocumentStyle &other);
+ DocumentStyle & operator = (const Document &other);
+
+ ~DocumentStyle();
+
+ // KDE 4:: make const
+ StyleSheetList styleSheets();
+
+ DOMString preferredStylesheetSet() const;
+ DOMString selectedStylesheetSet() const;
+ void setSelectedStylesheetSet( const DOMString& aString );
+
+ bool isNull() const { return !impl; }
+
+protected:
+ DOM::DocumentImpl *doc;
+ DocumentStyleImpl *impl;
+};
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/css_value.cpp b/tdehtml/dom/css_value.cpp
new file mode 100644
index 000000000..4e365644a
--- /dev/null
+++ b/tdehtml/dom/css_value.cpp
@@ -0,0 +1,587 @@
+/*
+ * 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 "dom/css_rule.h"
+#include "dom/dom_exception.h"
+
+#include "css/css_renderstyledeclarationimpl.h"
+#include "css/css_valueimpl.h"
+
+namespace DOM {
+
+CSSStyleDeclaration::CSSStyleDeclaration()
+{
+ impl = 0;
+}
+
+CSSStyleDeclaration::CSSStyleDeclaration(const CSSStyleDeclaration &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+CSSStyleDeclaration::CSSStyleDeclaration(CSSStyleDeclarationImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+CSSStyleDeclaration &CSSStyleDeclaration::operator = (const CSSStyleDeclaration &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSStyleDeclaration::~CSSStyleDeclaration()
+{
+ if(impl) impl->deref();
+}
+
+DOMString CSSStyleDeclaration::cssText() const
+{
+ if(!impl) return DOMString();
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->cssText();
+}
+
+void CSSStyleDeclaration::setCssText( const DOMString &value )
+{
+ if(!impl) return;
+ impl->setCssText(value);
+}
+
+DOMString CSSStyleDeclaration::getPropertyValue( const DOMString &propertyName )
+{
+ return const_cast<const CSSStyleDeclaration*>( this )->getPropertyValue( propertyName );
+}
+
+DOMString CSSStyleDeclaration::getPropertyValue( const DOMString &propertyName ) const
+{
+ if(!impl) return DOMString();
+ int id = getPropertyID(propertyName.string().ascii(), propertyName.length());
+ if (!id) return DOMString();
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->getPropertyValue(id);
+}
+
+CSSValue CSSStyleDeclaration::getPropertyCSSValue( const DOMString &propertyName )
+{
+ return const_cast<const CSSStyleDeclaration*>( this )->getPropertyCSSValue( propertyName );
+}
+
+CSSValue CSSStyleDeclaration::getPropertyCSSValue( const DOMString &propertyName ) const
+{
+ if(!impl) return 0;
+ int id = getPropertyID(propertyName.string().ascii(), propertyName.length());
+ if (!id) return 0;
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->getPropertyCSSValue(id);
+}
+
+DOMString CSSStyleDeclaration::removeProperty( const DOMString &property )
+{
+ int id = getPropertyID(property.string().ascii(), property.length());
+ if(!impl || !id) return DOMString();
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->removeProperty( id );
+}
+
+DOMString CSSStyleDeclaration::getPropertyPriority( const DOMString &propertyName )
+{
+ return const_cast<const CSSStyleDeclaration*>( this )->getPropertyPriority( propertyName );
+}
+
+DOMString CSSStyleDeclaration::getPropertyPriority( const DOMString &propertyName ) const
+{
+ int id = getPropertyID(propertyName.string().ascii(), propertyName.length());
+ if(!impl || !id) return DOMString();
+ if (impl->getPropertyPriority(id))
+ return DOMString("important");
+ return DOMString();
+}
+
+void CSSStyleDeclaration::setProperty( const DOMString &propName, const DOMString &value, const DOMString &priority )
+{
+ if(!impl) return;
+ int id = getPropertyID(propName.string().lower().ascii(), propName.length());
+ if (!id) return;
+ bool important = false;
+ TQString str = priority.string();
+ if (str.find("important", 0, false) != -1)
+ important = true;
+
+ static_cast<CSSStyleDeclarationImpl *>(impl)->setProperty( id, value, important );
+}
+
+unsigned long CSSStyleDeclaration::length() const
+{
+ if(!impl) return 0;
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->length();
+}
+
+DOMString CSSStyleDeclaration::item( unsigned long index )
+{
+ return const_cast<const CSSStyleDeclaration*>( this )->item( index );
+}
+
+DOMString CSSStyleDeclaration::item( unsigned long index ) const
+{
+ if(!impl) return DOMString();
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->item( index );
+}
+CSSRule CSSStyleDeclaration::parentRule() const
+{
+ if(!impl) return 0;
+ return static_cast<CSSStyleDeclarationImpl *>(impl)->parentRule();
+}
+
+CSSStyleDeclarationImpl *CSSStyleDeclaration::handle() const
+{
+ return impl;
+}
+
+bool CSSStyleDeclaration::isNull() const
+{
+ return (impl == 0);
+}
+
+// ----------------------------------------------------------
+
+CSSValue::CSSValue()
+{
+ impl = 0;
+}
+
+CSSValue::CSSValue(const CSSValue &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+CSSValue::CSSValue(CSSValueImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+CSSValue &CSSValue::operator = (const CSSValue &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSValue::~CSSValue()
+{
+ if(impl) impl->deref();
+}
+
+DOMString CSSValue::cssText() const
+{
+ if(!impl) return DOMString();
+ return ((CSSValueImpl *)impl)->cssText();
+}
+
+void CSSValue::setCssText( const DOMString &/*value*/ )
+{
+ if(!impl) return;
+ ((CSSValueImpl *)impl)->cssText();
+}
+
+unsigned short CSSValue::cssValueType() const
+{
+ if(!impl) return 0;
+ return ((CSSValueImpl *)impl)->cssValueType();
+}
+
+bool CSSValue::isCSSValueList() const
+{
+ if(!impl) return false;
+ return ((CSSValueImpl *)impl)->isValueList();
+}
+
+bool CSSValue::isCSSPrimitiveValue() const
+{
+ if(!impl) return false;
+ return ((CSSValueImpl *)impl)->isPrimitiveValue();
+}
+
+CSSValueImpl *CSSValue::handle() const
+{
+ return impl;
+}
+
+bool CSSValue::isNull() const
+{
+ return (impl == 0);
+}
+
+// ----------------------------------------------------------
+
+CSSValueList::CSSValueList() : CSSValue()
+{
+}
+
+CSSValueList::CSSValueList(const CSSValueList &other) : CSSValue(other)
+{
+}
+
+CSSValueList::CSSValueList(const CSSValue &other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSValueList::CSSValueList(CSSValueListImpl *impl) : CSSValue(impl)
+{
+}
+
+CSSValueList &CSSValueList::operator = (const CSSValueList &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.handle();
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSValueList &CSSValueList::operator = (const CSSValue &other)
+{
+ CSSValueImpl *ohandle = other.handle() ;
+ if ( impl != ohandle ) {
+ if (impl) impl->deref();
+ if (!other.isNull() && !other.isCSSValueList()) {
+ impl = 0;
+ } else {
+ impl = ohandle;
+ if (impl) impl->ref();
+ }
+ }
+ return *this;
+}
+
+CSSValueList::~CSSValueList()
+{
+}
+
+unsigned long CSSValueList::length() const
+{
+ if(!impl) return 0;
+ return ((CSSValueListImpl *)impl)->length();
+}
+
+CSSValue CSSValueList::item( unsigned long index )
+{
+ if(!impl) return 0;
+ return ((CSSValueListImpl *)impl)->item( index );
+}
+
+// ----------------------------------------------------------
+
+CSSPrimitiveValue::CSSPrimitiveValue() : CSSValue()
+{
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(const CSSPrimitiveValue &other) : CSSValue(other)
+{
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(const CSSValue &other) : CSSValue(other)
+{
+ impl = 0;
+ operator=(other);
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(CSSPrimitiveValueImpl *impl) : CSSValue(impl)
+{
+}
+
+CSSPrimitiveValue &CSSPrimitiveValue::operator = (const CSSPrimitiveValue &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.handle();
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+CSSPrimitiveValue &CSSPrimitiveValue::operator = (const CSSValue &other)
+{
+ CSSValueImpl *ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (impl) impl->deref();
+ if (!other.isNull() && !other.isCSSPrimitiveValue()) {
+ impl = 0;
+ } else {
+ impl = ohandle;
+ if (impl) impl->ref();
+ }
+ }
+ return *this;
+}
+
+CSSPrimitiveValue::~CSSPrimitiveValue()
+{
+}
+
+unsigned short CSSPrimitiveValue::primitiveType() const
+{
+ if(!impl) return 0;
+ return ((CSSPrimitiveValueImpl *)impl)->primitiveType();
+}
+
+void CSSPrimitiveValue::setFloatValue( unsigned short unitType, float floatValue )
+{
+ if(!impl) return;
+ int exceptioncode = 0;
+ ((CSSPrimitiveValueImpl *)impl)->setFloatValue( unitType, floatValue, exceptioncode );
+ if ( exceptioncode >= CSSException::_EXCEPTION_OFFSET )
+ throw CSSException( exceptioncode - CSSException::_EXCEPTION_OFFSET );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+float CSSPrimitiveValue::getFloatValue( unsigned short unitType )
+{
+ if(!impl) return 0;
+ // ### add unit conversion
+ if(primitiveType() != unitType)
+ throw CSSException(CSSException::SYNTAX_ERR);
+ return ((CSSPrimitiveValueImpl *)impl)->floatValue( unitType );
+}
+
+void CSSPrimitiveValue::setStringValue( unsigned short stringType, const DOMString &stringValue )
+{
+ int exceptioncode = 0;
+ if(impl)
+ ((CSSPrimitiveValueImpl *)impl)->setStringValue( stringType, stringValue, exceptioncode );
+ if ( exceptioncode >= CSSException::_EXCEPTION_OFFSET )
+ throw CSSException( exceptioncode - CSSException::_EXCEPTION_OFFSET );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+
+}
+
+DOMString CSSPrimitiveValue::getStringValue( )
+{
+ if(!impl) return DOMString();
+ return ((CSSPrimitiveValueImpl *)impl)->getStringValue( );
+}
+
+Counter CSSPrimitiveValue::getCounterValue( )
+{
+ if(!impl) return Counter();
+ return ((CSSPrimitiveValueImpl *)impl)->getCounterValue( );
+}
+
+Rect CSSPrimitiveValue::getRectValue( )
+{
+ if(!impl) return Rect();
+ return ((CSSPrimitiveValueImpl *)impl)->getRectValue( );
+}
+
+RGBColor CSSPrimitiveValue::getRGBColorValue( )
+{
+ // ###
+ return RGBColor();
+ //if(!impl) return RGBColor();
+ //return ((CSSPrimitiveValueImpl *)impl)->getRGBColorValue( );
+}
+
+// -------------------------------------------------------------------
+
+Counter::Counter()
+{
+}
+
+Counter::Counter(const Counter &/*other*/)
+{
+ impl = 0;
+}
+
+Counter &Counter::operator = (const Counter &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+Counter::Counter(CounterImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+Counter::~Counter()
+{
+ if (impl) impl->deref();
+}
+
+DOMString Counter::identifier() const
+{
+ if (!impl) return DOMString();
+ return impl->identifier();
+}
+
+DOMString Counter::listStyle() const
+{
+ if (!impl) return DOMString();
+ return tdehtml::stringForListStyleType((tdehtml::EListStyleType)impl->listStyle());
+}
+
+DOMString Counter::separator() const
+{
+ if (!impl) return DOMString();
+ return impl->separator();
+}
+
+CounterImpl *Counter::handle() const
+{
+ return impl;
+}
+
+bool Counter::isNull() const
+{
+ return (impl == 0);
+}
+
+// --------------------------------------------------------------------
+
+RGBColor::RGBColor()
+{
+}
+
+RGBColor::RGBColor(const RGBColor &other)
+{
+ m_color = other.m_color;
+}
+
+RGBColor::RGBColor(QRgb color)
+{
+ m_color = color;
+}
+
+RGBColor &RGBColor::operator = (const RGBColor &other)
+{
+ m_color = other.m_color;
+ return *this;
+}
+
+RGBColor::~RGBColor()
+{
+}
+
+CSSPrimitiveValue RGBColor::red() const
+{
+ return new CSSPrimitiveValueImpl(float(tqAlpha(m_color) ? tqRed(m_color) : 0), CSSPrimitiveValue::CSS_DIMENSION);
+}
+
+CSSPrimitiveValue RGBColor::green() const
+{
+ return new CSSPrimitiveValueImpl(float(tqAlpha(m_color) ? tqGreen(m_color) : 0), CSSPrimitiveValue::CSS_DIMENSION);
+}
+
+CSSPrimitiveValue RGBColor::blue() const
+{
+ return new CSSPrimitiveValueImpl(float(tqAlpha(m_color) ? tqBlue(m_color) : 0), CSSPrimitiveValue::CSS_DIMENSION);
+}
+
+
+// ---------------------------------------------------------------------
+
+Rect::Rect()
+{
+ impl = 0;
+}
+
+Rect::Rect(const Rect &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+Rect::Rect(RectImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+Rect &Rect::operator = (const Rect &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+Rect::~Rect()
+{
+ if (impl) impl->deref();
+}
+
+CSSPrimitiveValue Rect::top() const
+{
+ if (!impl) return 0;
+ return impl->top();
+}
+
+CSSPrimitiveValue Rect::right() const
+{
+ if (!impl) return 0;
+ return impl->right();
+}
+
+CSSPrimitiveValue Rect::bottom() const
+{
+ if (!impl) return 0;
+ return impl->bottom();
+}
+
+CSSPrimitiveValue Rect::left() const
+{
+ if (!impl) return 0;
+ return impl->left();
+}
+
+RectImpl *Rect::handle() const
+{
+ return impl;
+}
+
+bool Rect::isNull() const
+{
+ return (impl == 0);
+}
+
+} // namespace
+
+
diff --git a/tdehtml/dom/css_value.h b/tdehtml/dom/css_value.h
new file mode 100644
index 000000000..5d4a043c7
--- /dev/null
+++ b/tdehtml/dom/css_value.h
@@ -0,0 +1,745 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Style)
+ * http://www.w3.org/TR/DOM-Level-2-Style/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _CSS_css_value_h_
+#define _CSS_css_value_h_
+
+#include <dom/dom_string.h>
+
+#include <tqcolor.h>
+
+#include <kdemacros.h>
+
+namespace DOM {
+
+class CSSStyleDeclarationImpl;
+class CSSRule;
+class CSSValue;
+
+/**
+ * The \c CSSStyleDeclaration interface represents a
+ * single <a href="http://www.w3.org/TR/REC-CSS2/syndata.html#block">
+ * CSS declaration block </a> . This interface may be used to
+ * determine the style properties currently set in a block or to set
+ * style properties explicitly within the block.
+ *
+ * While an implementation may not recognize all CSS properties
+ * within a CSS declaration block, it is expected to provide access to
+ * all specified properties through the \c CSSStyleDeclaration
+ * interface. Furthermore, implementations that support a
+ * specific level of CSS should correctly handle <a
+ * href="http://www.w3.org/TR/REC-CSS2/about.html#shorthand"> CSS
+ * shorthand </a> properties for that level. For a further discussion
+ * of shorthand properties, see the \c CSS2Properties
+ * interface.
+ *
+ */
+class KHTML_EXPORT CSSStyleDeclaration
+{
+public:
+ CSSStyleDeclaration();
+ CSSStyleDeclaration(const CSSStyleDeclaration &other);
+ CSSStyleDeclaration(CSSStyleDeclarationImpl *impl);
+public:
+
+ CSSStyleDeclaration & operator = (const CSSStyleDeclaration &other);
+
+ ~CSSStyleDeclaration();
+
+ /**
+ * The parsable textual representation of the declaration block
+ * (including the surrounding curly braces). Setting this
+ * attribute will result in the parsing of the new value and
+ * resetting of the properties in the declaration block.
+ *
+ */
+ DOM::DOMString cssText() const;
+
+ /**
+ * see cssText
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setCssText( const DOM::DOMString & );
+
+ /**
+ * The number of properties that have been explicitly set in this
+ * declaration block.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * The CSS rule that contains this declaration block.
+ *
+ */
+ CSSRule parentRule() const;
+
+ /**
+ * Used to retrieve the value of a CSS property if it has been
+ * explicitly set within this declaration block.
+ *
+ * @param propertyName The name of the CSS property. See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> CSS property
+ * index </a> .
+ *
+ * @return Returns the value of the property if it has been
+ * explicitly set for this declaration block. Returns the empty
+ * string if the property has not been set.
+ *
+ */
+ DOM::DOMString getPropertyValue ( const DOM::DOMString &propertyName ) const;
+ DOM::DOMString getPropertyValue ( const DOM::DOMString &propertyName );
+
+ /**
+ * Used to retrieve the object representation of the value of a
+ * CSS property if it has been explicitly set within this
+ * declaration block. This method returns null if the property is
+ * a <a href="http://www.w3.org/TR/REC-CSS2/about.html#shorthand">
+ * shorthand </a> property. Shorthand property values can only be
+ * accessed and modified as strings, using the
+ * \c getPropertyValue and \c setProperty
+ * methods.
+ *
+ * @param propertyName The name of the CSS property. See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> CSS property
+ * index </a> .
+ *
+ * @return Returns the value of the property if it has been
+ * explicitly set for this declaration block. Returns the
+ * \c null if the property has not been set.
+ *
+ */
+ CSSValue getPropertyCSSValue ( const DOM::DOMString &propertyName ) const;
+ CSSValue getPropertyCSSValue ( const DOM::DOMString &propertyName );
+
+ /**
+ * Used to remove a CSS property if it has been explicitly set
+ * within this declaration block.
+ *
+ * @param propertyName The name of the CSS property. See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> CSS property
+ * index </a> .
+ *
+ * @return Returns the value of the property if it has been
+ * explicitly set for this declaration block. Returns the empty
+ * string if the property has not been set or the property name
+ * does not correspond to a valid CSS2 property.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ DOM::DOMString removeProperty ( const DOM::DOMString &propertyName );
+
+ /**
+ * Used to retrieve the priority of a CSS property (e.g. the
+ * \c "important" qualifier) if the property has been
+ * explicitly set in this declaration block.
+ *
+ * @param propertyName The name of the CSS property. See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> CSS property
+ * index </a> .
+ *
+ * @return A string representing the priority (e.g.
+ * \c "important" ) if one exists. The empty string if none
+ * exists.
+ *
+ */
+ DOM::DOMString getPropertyPriority ( const DOM::DOMString &propertyName ) const;
+ DOM::DOMString getPropertyPriority ( const DOM::DOMString &propertyName );
+
+ /**
+ * Used to set a property value and priority within this
+ * declaration block.
+ *
+ * @param propertyName The name of the CSS property. See the <a
+ * href="http://www.w3.org/TR/REC-CSS2/propidx.html"> CSS property
+ * index </a> .
+ *
+ * @param value The new value of the property.
+ *
+ * @param priority The new priority of the property (e.g.
+ * \c "important" ).
+ *
+ * @return
+ *
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified value has a syntax error
+ * and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setProperty ( const DOM::DOMString &propertyName, const DOM::DOMString &value, const DOM::DOMString &priority );
+
+ /**
+ * Used to retrieve the properties that have been explicitly set
+ * in this declaration block. The order of the properties
+ * retrieved using this method does not have to be the order in
+ * which they were set. This method can be used to iterate over
+ * all properties in this declaration block.
+ *
+ * @param index Index of the property name to retrieve.
+ *
+ * @return The name of the property at this ordinal position. The
+ * empty string if no property exists at this position.
+ *
+ */
+ DOM::DOMString item ( unsigned long index ) const;
+ DOM::DOMString item ( unsigned long index );
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ CSSStyleDeclarationImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ CSSStyleDeclarationImpl *impl;
+};
+
+
+class CSSValueImpl;
+
+/**
+ * The \c CSSValue interface represents a simple or a
+ * complexe value.
+ *
+ */
+class KHTML_EXPORT CSSValue
+{
+public:
+ CSSValue();
+ CSSValue(const CSSValue &other);
+ CSSValue(CSSValueImpl *impl);
+public:
+
+ CSSValue & operator = (const CSSValue &other);
+
+ ~CSSValue();
+ /**
+ * An integer indicating which type of unit applies to the value.
+ *
+ * All CSS2 constants are not supposed to be required by the
+ * implementation since all CSS2 interfaces are optionals.
+ *
+ */
+ enum UnitTypes {
+ CSS_INHERIT = 0,
+ CSS_PRIMITIVE_VALUE = 1,
+ CSS_VALUE_LIST = 2,
+ CSS_CUSTOM = 3,
+ CSS_INITIAL = 4
+ };
+
+ /**
+ * A string representation of the current value.
+ *
+ */
+ DOM::DOMString cssText() const;
+
+ /**
+ * see cssText
+ * @exception CSSException
+ * SYNTAX_ERR: Raised if the specified CSS string value has a
+ * syntax error and is unparsable.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this declaration is
+ * readonly.
+ *
+ */
+ void setCssText( const DOM::DOMString & );
+
+ /**
+ * A code defining the type of the value as defined above.
+ *
+ */
+ unsigned short cssValueType() const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ bool isCSSValueList() const;
+ bool isCSSPrimitiveValue() const;
+ CSSValueImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ CSSValueImpl *impl;
+};
+
+
+class CSSValueListImpl;
+class CSSValue;
+
+/**
+ * The \c CSSValueList interface provides the absraction
+ * of an ordered collection of CSS values.
+ *
+ */
+class KHTML_EXPORT CSSValueList : public CSSValue
+{
+public:
+ CSSValueList();
+ CSSValueList(const CSSValueList &other);
+ CSSValueList(const CSSValue &other);
+ CSSValueList(CSSValueListImpl *impl);
+public:
+
+ CSSValueList & operator = (const CSSValueList &other);
+ CSSValueList & operator = (const CSSValue &other);
+
+ ~CSSValueList();
+
+ /**
+ * The number of \c CSSValue s in the list. The range
+ * of valid values indices is \c 0 to \c length-1
+ * inclusive.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Used to retrieve a CSS rule by ordinal index. The order in this
+ * collection represents the order of the values in the CSS style
+ * property.
+ *
+ * @param index Index into the collection.
+ *
+ * @return The style rule at the \c index position in
+ * the \c CSSValueList , or \c null if
+ * that is not valid index.
+ *
+ */
+ CSSValue item ( unsigned long index );
+
+protected:
+ CSSValueListImpl *vimpl;
+};
+
+
+class CSSPrimitiveValueImpl;
+class Counter;
+class RGBColor;
+class Rect;
+
+/**
+ * The \c CSSPrimitiveValue interface represents a single
+ * <a href="http://www.w3.org/TR/REC-CSS2/syndata.html#values"> CSS
+ * value </a> . This interface may be used to determine the value of a
+ * specific style property currently set in a block or to set a
+ * specific style properties explicitly within the block. An instance
+ * of this interface can be obtained from the
+ * \c getPropertyCSSValue method of the
+ * \c CSSStyleDeclaration interface.
+ *
+ */
+class KHTML_EXPORT CSSPrimitiveValue : public CSSValue
+{
+public:
+ CSSPrimitiveValue();
+ CSSPrimitiveValue(const CSSPrimitiveValue &other);
+ CSSPrimitiveValue(const CSSValue &other);
+ CSSPrimitiveValue(CSSPrimitiveValueImpl *impl);
+public:
+
+ CSSPrimitiveValue & operator = (const CSSPrimitiveValue &other);
+ CSSPrimitiveValue & operator = (const CSSValue &other);
+
+ ~CSSPrimitiveValue();
+ /**
+ * An integer indicating which type of unit applies to the value.
+ *
+ */
+ enum UnitTypes {
+ CSS_UNKNOWN = 0,
+ CSS_NUMBER = 1,
+ CSS_PERCENTAGE = 2,
+ CSS_EMS = 3,
+ CSS_EXS = 4,
+ CSS_PX = 5,
+ CSS_CM = 6,
+ CSS_MM = 7,
+ CSS_IN = 8,
+ CSS_PT = 9,
+ CSS_PC = 10,
+ CSS_DEG = 11,
+ CSS_RAD = 12,
+ CSS_GRAD = 13,
+ CSS_MS = 14,
+ CSS_S = 15,
+ CSS_HZ = 16,
+ CSS_KHZ = 17,
+ CSS_DIMENSION = 18,
+ CSS_STRING = 19,
+ CSS_URI = 20,
+ CSS_IDENT = 21,
+ CSS_ATTR = 22,
+ CSS_COUNTER = 23,
+ CSS_RECT = 24,
+ CSS_RGBCOLOR = 25,
+ CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs
+ CSS_HTML_RELATIVE = 255
+ };
+
+ /**
+ * The type of the value as defined by the constants specified
+ * above.
+ *
+ */
+ unsigned short primitiveType() const;
+
+ /**
+ * A method to set the float value with a specified unit. If the
+ * property attached with this value can not accept the specified
+ * unit or the float value, the value will be unchanged and a
+ * \c DOMException will be raised.
+ *
+ * @param unitType A unit code as defined above. The unit code can
+ * only be a float unit type (e.g. \c NUMBER ,
+ * \c PERCENTAGE , \c CSS_EMS , \c CSS_EXS
+ * , \c CSS_PX , \c CSS_PX ,
+ * \c CSS_CM , \c CSS_MM , \c CSS_IN
+ * , \c CSS_PT , \c CSS_PC ,
+ * \c CSS_DEG , \c CSS_RAD ,
+ * \c CSS_GRAD , \c CSS_MS , \c CSS_S
+ * , \c CSS_HZ , \c CSS_KHZ ,
+ * \c CSS_DIMENSION ).
+ *
+ * @param floatValue The new float value.
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the attached property doesn't
+ * support the float value or the unit type.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this property is
+ * readonly.
+ *
+ */
+ void setFloatValue ( unsigned short unitType, float floatValue );
+
+ /**
+ * This method is used to get a float value in a specified unit.
+ * If this CSS value doesn't contain a float value or can't be
+ * converted into the specified unit, a \c DOMException
+ * is raised.
+ *
+ * @param unitType A unit code to get the float value. The unit
+ * code can only be a float unit type (e.g. \c CSS_NUMBER
+ * , \c CSS_PERCENTAGE , \c CSS_EMS
+ * , \c CSS_EXS , \c CSS_PX ,
+ * \c CSS_PX , \c CSS_CM , \c CSS_MM
+ * , \c CSS_IN , \c CSS_PT ,
+ * \c CSS_PC , \c CSS_DEG , \c CSS_RAD
+ * , \c CSS_GRAD , \c CSS_MS ,
+ * \c CSS_S , \c CSS_HZ , \c CSS_KHZ
+ * , \c CSS_DIMENSION ).
+ *
+ * @return The float value in the specified unit.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the CSS value doesn't contain a
+ * float value or if the float value can't be converted into the
+ * specified unit.
+ *
+ */
+ // ### KDE 4: make this const!
+ float getFloatValue ( unsigned short unitType );
+
+ /**
+ * A method to set the string value with a specified unit. If the
+ * property attached to this value can't accept the specified unit
+ * or the string value, the value will be unchanged and a
+ * \c DOMException will be raised.
+ *
+ * @param stringType A string code as defined above. The string
+ * code can only be a string unit type (e.g. \c CSS_URI
+ * , \c CSS_IDENT , \c CSS_INHERIT
+ * and \c CSS_ATTR ).
+ *
+ * @param stringValue The new string value. If the
+ * \c stringType is equal to \c CSS_INHERIT , the
+ * \c stringValue should be \c inherit .
+ *
+ * @return
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the CSS value doesn't contain a
+ * string value or if the string value can't be converted into the
+ * specified unit.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this property is
+ * readonly.
+ *
+ */
+ void setStringValue ( unsigned short stringType, const DOM::DOMString &stringValue );
+
+ /**
+ * This method is used to get the string value in a specified
+ * unit. If the CSS value doesn't contain a string value, a
+ * \c DOMException is raised.
+ *
+ * @return The string value in the current unit. The current
+ * \c valueType can only be a string unit type (e.g.
+ * \c CSS_URI , \c CSS_IDENT and
+ * \c CSS_ATTR ).
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the CSS value doesn't contain a
+ * string value.
+ *
+ */
+ // ### KDE4: make this const!
+ DOM::DOMString getStringValue ( );
+
+ /**
+ * This method is used to get the Counter value. If this CSS value
+ * doesn't contain a counter value, a \c DOMException
+ * is raised. Modification to the corresponding style property can
+ * be achieved using the \c Counter interface.
+ *
+ * @return The Counter value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the CSS value doesn't contain a
+ * Counter value.
+ *
+ */
+ // ### KDE4: make this const!
+ Counter getCounterValue ( );
+
+ /**
+ * This method is used to get the Rect value. If this CSS value
+ * doesn't contain a rect value, a \c DOMException is
+ * raised. Modification to the corresponding style property can be
+ * achieved using the \c Rect interface.
+ *
+ * @return The Rect value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the CSS value doesn't contain a
+ * Rect value.
+ *
+ */
+ // ### KDE4: make this const!
+ Rect getRectValue ( );
+
+ /**
+ * This method is used to get the RGB color. If this CSS value
+ * doesn't contain a RGB color value, a \c DOMException
+ * is raised. Modification to the corresponding style
+ * property can be achieved using the \c RGBColor
+ * interface.
+ *
+ * @return the RGB color value.
+ *
+ * @exception DOMException
+ * INVALID_ACCESS_ERR: Raises if the attached property can't
+ * return a RGB color value.
+ *
+ */
+ // ### KDE4: make this const!
+ RGBColor getRGBColorValue ( );
+};
+
+
+
+/**
+ * The \c RGBColor interface is used to represent any <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#value-def-color">
+ * RGB color </a> value. This interface reflects the values in the
+ * underlying style property. Hence, modifications made through this
+ * interface modify the style property.
+ *
+ */
+class KHTML_EXPORT RGBColor
+{
+public:
+ RGBColor();
+ /**
+ * @deprecated
+ */
+ RGBColor(const TQColor& c) { m_color = c.rgb(); }
+ RGBColor(QRgb color);
+
+ RGBColor(const RGBColor &other);
+ RGBColor & operator = (const RGBColor &other);
+
+ ~RGBColor();
+
+ /**
+ * This attribute is used for the red value of the RGB color.
+ *
+ */
+ CSSPrimitiveValue red() const;
+
+ /**
+ * This attribute is used for the green value of the RGB color.
+ *
+ */
+ CSSPrimitiveValue green() const;
+
+ /**
+ * This attribute is used for the blue value of the RGB color.
+ *
+ */
+ CSSPrimitiveValue blue() const;
+
+ /**
+ * @internal
+ */
+ QRgb color() const { return m_color; }
+protected:
+ QRgb m_color;
+};
+
+class RectImpl;
+
+/**
+ * The \c Rect interface is used to represent any <a
+ * href="http://www.w3.org/TR/REC-CSS2/visufx.html#value-def-shape">
+ * rect </a> value. This interface reflects the values in the
+ * underlying style property. Hence, modifications made through this
+ * interface modify the style property.
+ *
+ */
+class KHTML_EXPORT Rect
+{
+ friend class CSSPrimitiveValue;
+public:
+ Rect();
+ Rect(const Rect &other);
+
+ Rect & operator = (const Rect &other);
+
+ ~Rect();
+
+ /**
+ * This attribute is used for the top of the rect.
+ *
+ */
+ CSSPrimitiveValue top() const;
+
+ /**
+ * This attribute is used for the right of the rect.
+ *
+ */
+ CSSPrimitiveValue right() const;
+
+ /**
+ * This attribute is used for the bottom of the rect.
+ *
+ */
+ CSSPrimitiveValue bottom() const;
+
+ /**
+ * This attribute is used for the left of the rect.
+ *
+ */
+ CSSPrimitiveValue left() const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ RectImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ RectImpl *impl;
+ Rect(RectImpl *i);
+};
+
+class CounterImpl;
+
+/**
+ * The \c Counter interface is used to represent any <a
+ * href="http://www.w3.org/TR/REC-CSS2/syndata.html#value-def-counter">
+ * counter or counters function </a> value. This interface reflects
+ * the values in the underlying style property. Hence, modifications
+ * made through this interface modify the style property.
+ *
+ */
+class KHTML_EXPORT Counter
+{
+ friend class CSSPrimitiveValue;
+public:
+ Counter();
+ Counter(const Counter &other);
+public:
+
+ Counter & operator = (const Counter &other);
+
+ ~Counter();
+
+ /**
+ * This attribute is used for the identifier of the counter.
+ *
+ */
+ DOM::DOMString identifier() const;
+
+ /**
+ * This attribute is used for the style of the list.
+ *
+ */
+ DOM::DOMString listStyle() const;
+
+ /**
+ * This attribute is used for the separator of nested counters.
+ *
+ */
+ DOM::DOMString separator() const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ CounterImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ CounterImpl *impl;
+ Counter(CounterImpl *i);
+};
+
+
+} // namespace
+
+
+#endif
diff --git a/tdehtml/dom/dom2_events.cpp b/tdehtml/dom/dom2_events.cpp
new file mode 100644
index 000000000..898a73bc3
--- /dev/null
+++ b/tdehtml/dom/dom2_events.cpp
@@ -0,0 +1,725 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#include "dom/dom2_views.h"
+#include "dom/dom_exception.h"
+#include "xml/dom2_eventsimpl.h"
+
+using namespace DOM;
+
+EventListener::EventListener()
+{
+}
+
+EventListener::~EventListener()
+{
+}
+
+void EventListener::handleEvent(Event &/*evt*/)
+{
+}
+
+DOMString EventListener::eventListenerType()
+{
+ return "";
+}
+
+// -----------------------------------------------------------------------------
+
+Event::Event()
+{
+ impl = 0;
+}
+
+
+Event::Event(const Event &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+Event::Event(EventImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+Event::~Event()
+{
+ if (impl) impl->deref();
+}
+
+Event &Event::operator = (const Event &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+DOMString Event::type() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->type();
+}
+
+Node Event::target() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->target();
+}
+
+Node Event::currentTarget() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->currentTarget();
+}
+
+unsigned short Event::eventPhase() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->eventPhase();
+}
+
+bool Event::bubbles() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->bubbles();
+}
+
+bool Event::cancelable() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->cancelable();
+}
+
+DOMTimeStamp Event::timeStamp() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->timeStamp();
+}
+
+void Event::stopPropagation()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ impl->stopPropagation(true);
+}
+
+void Event::preventDefault()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ impl->preventDefault(true);
+}
+
+void Event::initEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ impl->initEvent(eventTypeArg,canBubbleArg,cancelableArg);
+}
+
+EventImpl *Event::handle() const
+{
+ return impl;
+}
+
+bool Event::isNull() const
+{
+ return (impl == 0);
+}
+
+// -----------------------------------------------------------------------------
+
+#ifndef SAVE_SPACE
+
+EventException::EventException(unsigned short _code)
+{
+ code = _code;
+}
+
+EventException::EventException(const EventException &other)
+{
+ code = other.code;
+}
+
+EventException & EventException::operator = (const EventException &other)
+{
+ code = other.code;
+ return *this;
+}
+
+#endif
+
+// -----------------------------------------------------------------------------
+
+UIEvent::UIEvent() : Event()
+{
+}
+
+UIEvent::UIEvent(const UIEvent &other) : Event(other)
+{
+}
+
+UIEvent::UIEvent(const Event &other) : Event()
+{
+ (*this)=other;
+}
+
+UIEvent::UIEvent(UIEventImpl *impl) : Event(impl)
+{
+}
+
+UIEvent &UIEvent::operator = (const UIEvent &other)
+{
+ Event::operator = (other);
+ return *this;
+}
+
+UIEvent &UIEvent::operator = (const Event &other)
+{
+ Event e;
+ e = other;
+ if (!e.isNull() && !e.handle()->isUIEvent()) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else
+ Event::operator = (other);
+ return *this;
+}
+
+UIEvent::~UIEvent()
+{
+}
+
+AbstractView UIEvent::view() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<UIEventImpl*>(impl)->view();
+}
+
+long UIEvent::detail() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<UIEventImpl*>(impl)->detail();
+}
+
+int UIEvent::keyCode() const
+{
+ if ( !impl ) throw DOMException( DOMException::INVALID_STATE_ERR );
+
+ if( impl->isTextInputEvent() || impl->isKeyboardEvent() )
+ return static_cast<KeyEventBaseImpl*>( impl )->keyCode();
+
+ return 0;
+}
+
+int UIEvent::charCode() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ if( impl->isTextInputEvent() || impl->isKeyboardEvent() )
+ return static_cast<KeyEventBaseImpl*>( impl )->charCode();
+
+ return 0;
+}
+
+int UIEvent::pageX() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ if (impl->isMouseEvent() )
+ return static_cast<MouseEventImpl*>( impl )->pageX();
+ else
+ return 0;
+}
+
+int UIEvent::pageY() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ if ( impl->isMouseEvent() )
+ return static_cast<MouseEventImpl*>( impl )->pageY();
+ else
+ return 0;
+}
+
+int UIEvent::layerX() const
+{
+ if( !impl )
+ throw DOMException( DOMException::INVALID_STATE_ERR );
+
+ if( impl->isMouseEvent() )
+ return static_cast<MouseEventImpl*>( impl )->layerX();
+ return 0;
+}
+
+int UIEvent::layerY() const
+{
+ if( !impl )
+ throw DOMException( DOMException::INVALID_STATE_ERR );
+
+ if( impl->isMouseEvent() )
+ return static_cast<MouseEventImpl*>( impl )->layerY();
+ return 0;
+}
+
+int UIEvent::which() const
+{
+ if( !impl ) throw DOMException( DOMException::INVALID_STATE_ERR );
+
+ if( impl->isMouseEvent() )
+ return static_cast<MouseEventImpl*>( impl )->button() + 1;
+ else if( impl->isTextInputEvent() || impl->isKeyboardEvent() )
+ {
+ // return 0 unless the key has an ascii value
+ if ( static_cast<KeyEventBaseImpl*>( impl )->keyVal() )
+ return static_cast<KeyEventBaseImpl*>( impl )->keyCode();
+ }
+
+ return 0;
+}
+
+void UIEvent::initUIEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<UIEventImpl*>(impl)->initUIEvent(typeArg,canBubbleArg,cancelableArg,
+ viewArg,detailArg);
+}
+
+// -----------------------------------------------------------------------------
+
+MouseEvent::MouseEvent() : UIEvent()
+{
+}
+
+MouseEvent::MouseEvent(const MouseEvent &other) : UIEvent(other)
+{
+}
+
+MouseEvent::MouseEvent(const Event &other) : UIEvent()
+{
+ (*this)=other;
+}
+
+MouseEvent::MouseEvent(MouseEventImpl *impl) : UIEvent(impl)
+{
+}
+
+MouseEvent &MouseEvent::operator = (const MouseEvent &other)
+{
+ UIEvent::operator = (other);
+ return *this;
+}
+
+MouseEvent &MouseEvent::operator = (const Event &other)
+{
+ Event e;
+ e = other;
+ if (!e.isNull() && !e.handle()->isMouseEvent()) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else
+ UIEvent::operator = (other);
+ return *this;
+}
+
+MouseEvent::~MouseEvent()
+{
+}
+
+long MouseEvent::screenX() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->screenX();
+}
+
+long MouseEvent::screenY() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->screenY();
+}
+
+long MouseEvent::clientX() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->clientX();
+}
+
+long MouseEvent::clientY() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->clientY();
+}
+
+bool MouseEvent::ctrlKey() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->ctrlKey();
+}
+
+bool MouseEvent::shiftKey() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->shiftKey();
+}
+
+bool MouseEvent::altKey() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->altKey();
+}
+
+bool MouseEvent::metaKey() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->metaKey();
+}
+
+unsigned short MouseEvent::button() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->button();
+}
+
+Node MouseEvent::relatedTarget() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MouseEventImpl*>(impl)->relatedTarget();
+}
+
+void MouseEvent::initMouseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ const Node &relatedTargetArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<MouseEventImpl*>(impl)->initMouseEvent(typeArg,canBubbleArg,
+ cancelableArg,viewArg,detailArg,screenXArg,screenYArg,clientXArg,
+ clientYArg,ctrlKeyArg,altKeyArg,shiftKeyArg,metaKeyArg,buttonArg,
+ relatedTargetArg);
+}
+
+// -----------------------------------------------------------------------------
+
+TextEvent::TextEvent() : UIEvent()
+{
+}
+
+TextEvent::TextEvent(const TextEvent &other) : UIEvent(other)
+{
+}
+
+TextEvent::TextEvent(const Event &other) : UIEvent()
+{
+ (*this)=other;
+}
+
+TextEvent::TextEvent(KeyEventBaseImpl *impl) : UIEvent(impl)
+{
+}
+
+TextEvent &TextEvent::operator = (const TextEvent &other)
+{
+ UIEvent::operator = (other);
+ return *this;
+}
+
+TextEvent &TextEvent::operator = (const Event &other)
+{
+ Event e;
+ e = other;
+ if (!e.isNull() && !(e.handle()->isTextInputEvent() || e.handle()->isKeyboardEvent())) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else
+ UIEvent::operator = (other);
+ return *this;
+}
+
+TextEvent::~TextEvent()
+{
+}
+
+void TextEvent::initTextEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long /*detailArg*/,
+ const DOMString &outputStringArg,
+ unsigned long keyValArg,
+ unsigned long virtKeyValArg,
+ bool /*inputGeneratedArg*/,
+ bool numPadArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ if (impl->isTextInputEvent()) {
+ //Initialize based on the outputStringArg or virtKeyValArg.
+ TQString text = outputStringArg.string();
+ if (outputStringArg.length() == 0 && virtKeyValArg) {
+ text += TQChar((unsigned short)virtKeyValArg);
+ }
+
+ TextEventImpl* tImpl = static_cast<TextEventImpl*>(impl);
+ tImpl->initTextEvent(typeArg, canBubbleArg, cancelableArg, viewArg, text);
+ } else {
+ KeyboardEventImpl* kbImpl = static_cast<KeyboardEventImpl*>(impl);
+ kbImpl->initKeyboardEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
+ keyValArg, virtKeyValArg, 0, numPadArg ?
+ KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD : KeyboardEventImpl::DOM_KEY_LOCATION_STANDARD);
+ }
+}
+
+unsigned long TextEvent::keyVal() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<KeyEventBaseImpl*>(impl)->keyVal();
+}
+
+DOMString TextEvent::outputString() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ KeyEventBaseImpl* ke = static_cast<KeyEventBaseImpl*>(impl);
+ if (ke->isTextInputEvent())
+ return static_cast<TextEventImpl*>(ke)->data();
+ else {
+ if (ke->keyVal())
+ return TQString(TQChar((ushort)ke->keyVal()));
+ else
+ return DOMString();
+ }
+}
+
+unsigned long TextEvent::virtKeyVal() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<KeyEventBaseImpl*>(impl)->virtKeyVal();
+}
+
+void TextEvent::initModifier(unsigned long modifierArg, bool valueArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<KeyEventBaseImpl*>(impl)->initModifier(modifierArg,valueArg);
+}
+
+bool TextEvent::checkModifier(unsigned long modifierArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<KeyEventBaseImpl*>(impl)->checkModifier(modifierArg);
+}
+
+bool TextEvent::inputGenerated() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<KeyEventBaseImpl*>(impl)->inputGenerated();
+}
+
+bool TextEvent::numPad() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ KeyEventBaseImpl* ke = static_cast<KeyEventBaseImpl*>(impl);
+ if (ke->isKeyboardEvent())
+ return static_cast<KeyboardEventImpl*>(ke)->keyLocation() ==
+ KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD;
+ else return false;
+}
+// -----------------------------------------------------------------------------
+
+MutationEvent::MutationEvent() : Event()
+{
+}
+
+MutationEvent::MutationEvent(const MutationEvent &other) : Event(other)
+{
+}
+
+MutationEvent::MutationEvent(const Event &other) : Event()
+{
+ (*this)=other;
+}
+
+MutationEvent::MutationEvent(MutationEventImpl *impl) : Event(impl)
+{
+}
+
+MutationEvent &MutationEvent::operator = (const MutationEvent &other)
+{
+ Event::operator = (other);
+ return *this;
+}
+
+MutationEvent &MutationEvent::operator = (const Event &other)
+{
+ Event e;
+ e = other;
+ if (!e.isNull() && !e.handle()->isMutationEvent()) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else
+ Event::operator = (other);
+ return *this;
+}
+
+MutationEvent::~MutationEvent()
+{
+}
+
+Node MutationEvent::relatedNode() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MutationEventImpl*>(impl)->relatedNode();
+}
+
+DOMString MutationEvent::prevValue() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MutationEventImpl*>(impl)->prevValue();
+}
+
+DOMString MutationEvent::newValue() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MutationEventImpl*>(impl)->newValue();
+}
+
+DOMString MutationEvent::attrName() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MutationEventImpl*>(impl)->attrName();
+}
+
+unsigned short MutationEvent::attrChange() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<MutationEventImpl*>(impl)->attrChange();
+}
+
+void MutationEvent::initMutationEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<MutationEventImpl*>(impl)->initMutationEvent(typeArg,
+ canBubbleArg,cancelableArg,relatedNodeArg,prevValueArg,
+ newValueArg,attrNameArg,attrChangeArg);
+}
+
+
diff --git a/tdehtml/dom/dom2_events.h b/tdehtml/dom/dom2_events.h
new file mode 100644
index 000000000..285a0c10e
--- /dev/null
+++ b/tdehtml/dom/dom2_events.h
@@ -0,0 +1,846 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * (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 _DOM_Events_h_
+#define _DOM_Events_h_
+
+#include <dom/dom_node.h>
+#include <dom/dom_misc.h>
+
+namespace DOM {
+
+class Event;
+class EventException;
+class UIEvent;
+class MouseEvent;
+class TextEvent;
+class MutationEvent;
+class AbstractView;
+
+class EventListenerImpl;
+class EventImpl;
+class UIEventImpl;
+class MouseEventImpl;
+class KeyEventBaseImpl;
+class MutationEventImpl;
+
+
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * The EventListener interface is the primary method for handling events.
+ * Users implement the EventListener interface and register their listener on
+ * an EventTarget using the AddEventListener method. The users should also
+ * remove their EventListener from its EventTarget after they have completed
+ * using the listener.
+ *
+ * When a Node is copied using the cloneNode method the EventListeners attached
+ * to the source Node are not attached to the copied Node. If the user wishes
+ * the same EventListeners to be added to the newly created copy the user must
+ * add them manually.
+ *
+ */
+class KHTML_EXPORT EventListener : public DomShared {
+public:
+ EventListener();
+ virtual ~EventListener();
+
+ /**
+ * This method is called whenever an event occurs of the type for which the
+ * EventListener interface was registered. Parameters
+ *
+ * @param evt The Event contains contextual information about the event. It
+ * also contains the stopPropagation and preventDefault methods which are
+ * used in determining the event's flow and default action.
+ *
+ */
+ virtual void handleEvent(Event &evt);
+
+ /**
+ * @internal
+ * not part of the DOM
+ *
+ * Returns a name specifying the type of listener. Useful for checking
+ * if an event is of a particular sublass.
+ *
+ */
+ virtual DOMString eventListenerType();
+
+protected:
+ /**
+ * @internal
+ * Reserved. Do not use in your subclasses.
+ */
+ EventListenerImpl *impl;
+};
+
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * The Event interface is used to provide contextual information about an event
+ * to the handler processing the event. An object which implements the Event
+ * interface is generally passed as the first parameter to an event handler.
+ * More specific context information is passed to event handlers by deriving
+ * additional interfaces from Event which contain information directly relating
+ * to the type of event they accompany. These derived interfaces are also
+ * implemented by the object passed to the event listener.
+ *
+ */
+class KHTML_EXPORT Event {
+ friend class Document;
+ friend class NodeImpl;
+ friend class DocumentImpl;
+public:
+ Event();
+ Event(const Event &other);
+ virtual ~Event();
+
+ Event & operator = (const Event &other);
+
+ /**
+ * An integer indicating which phase of event flow is being processed.
+ *
+ * AT_TARGET: The event is currently being evaluated at the target
+ * EventTarget.
+ *
+ * BUBBLING_PHASE: The current event phase is the bubbling phase.
+ *
+ * CAPTURING_PHASE: The current event phase is the capturing phase.
+ *
+ */
+ enum PhaseType {
+ CAPTURING_PHASE = 1,
+ AT_TARGET = 2,
+ BUBBLING_PHASE = 3
+ };
+
+ /**
+ * The name of the event (case-insensitive). The name must be an XML name.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * Used to indicate the EventTarget to which the event was originally
+ * dispatched.
+ *
+ */
+ Node target() const;
+
+ /**
+ * Used to indicate the EventTarget whose EventListeners are currently
+ * being processed. This is particularly useful during capturing and
+ * bubbling.
+ *
+ */
+ Node currentTarget() const;
+
+ /**
+ * Used to indicate which phase of event flow is currently being evaluated.
+ *
+ */
+ unsigned short eventPhase() const;
+
+ /**
+ * Used to indicate whether or not an event is a bubbling event. If the
+ * event can bubble the value is true, else the value is false.
+ *
+ */
+ bool bubbles() const;
+
+ /**
+ * Used to indicate whether or not an event can have its default action
+ * prevented. If the default action can be prevented the value is true,
+ * else the value is false.
+ *
+ */
+ bool cancelable() const;
+
+ /**
+ * Used to specify the time (in milliseconds relative to the epoch) at
+ * which the event was created. Due to the fact that some systems may not
+ * provide this information the value of timeStamp may be not available for
+ * all events. When not available, a value of 0 will be returned. Examples
+ * of epoch time are the time of the system start or 0:0:0 UTC 1st January 1970.
+ *
+ */
+ DOMTimeStamp timeStamp() const;
+
+ /**
+ * The stopPropagation method is used prevent further propagation of an
+ * event during event flow. If this method is called by any EventListener
+ * the event will cease propagating through the tree. The event will
+ * complete dispatch to all listeners on the current EventTarget before
+ * event flow stops. This method may be used during any stage of event flow.
+ *
+ */
+ void stopPropagation();
+
+ /**
+ * If an event is cancelable, the preventDefault method is used to signify
+ * that the event is to be canceled, meaning any default action normally
+ * taken by the implementation as a result of the event will not occur. If,
+ * during any stage of event flow, the preventDefault method is called the
+ * event is canceled. Any default action associated with the event will not
+ * occur. Calling this method for a non-cancelable event has no effect.
+ * Once preventDefault has been called it will remain in effect throughout
+ * the remainder of the event's propagation. This method may be used during
+ * any stage of event flow.
+ *
+ */
+ void preventDefault();
+
+ /**
+ * The initEvent method is used to initialize the value of an Event created
+ * through the DocumentEvent interface. This method may only be called
+ * before the Event has been dispatched via the dispatchEvent method,
+ * though it may be called multiple times during that phase if necessary.
+ * If called multiple times the final invocation takes precedence. If
+ * called from a subclass of Event interface only the values specified in
+ * the initEvent method are modified, all other attributes are left
+ * unchanged.
+ *
+ * @param eventTypeArg Specifies the event type. This type may be any event
+ * type currently defined in this specification or a new event type.. The
+ * string must be an XML name.
+ *
+ * Any new event type must not begin with any upper, lower, or mixed case
+ * version of the string "DOM". This prefix is reserved for future DOM
+ * event sets. It is also strongly recommended that third parties adding
+ * their own events use their own prefix to avoid confusion and lessen the
+ * probability of conflicts with other new events.
+ *
+ * @param canBubbleArg Specifies whether or not the event can bubble.
+ *
+ * @param cancelableArg Specifies whether or not the event's default action can be prevented.
+ *
+ */
+ void initEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg);
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ EventImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ Event(EventImpl *i);
+ EventImpl *impl;
+};
+
+
+/**
+ * Introduced in DOM Level 2:
+ *
+ * Event operations may throw an EventException as specified in their method
+ * descriptions.
+ *
+ */
+class KHTML_EXPORT EventException
+{
+public:
+ EventException(unsigned short _code);
+ EventException(const EventException &other);
+ EventException & operator = (const EventException &other);
+ virtual ~EventException() {}
+
+ /**
+ * An integer indicating the type of error generated.
+ *
+ * UNSPECIFIED_EVENT_TYPE_ERR: If the Event's type was not specified by
+ * initializing the event before the method was called. Specification of
+ * the Event's type as null or an empty string will also trigger this
+ * exception.
+ *
+ */
+ enum EventExceptionCode {
+ UNSPECIFIED_EVENT_TYPE_ERR = 0
+ };
+
+ unsigned short code;
+};
+
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * The UIEvent interface provides specific contextual information associated
+ * with User Interface events.
+ *
+ */
+class KHTML_EXPORT UIEvent : public Event {
+public:
+ UIEvent();
+ UIEvent(const UIEvent &other);
+ UIEvent(const Event &other);
+ UIEvent & operator = (const UIEvent &other);
+ UIEvent & operator = (const Event &other);
+ virtual ~UIEvent();
+
+ /**
+ * The view attribute identifies the AbstractView from which the event was
+ * generated.
+ *
+ */
+ AbstractView view() const;
+
+ /**
+ * Specifies some detail information about the Event, depending on the type
+ * of event.
+ *
+ */
+ long detail() const;
+
+ /**
+ * Non-standard extension to support IE-style keyCode event property.
+ *
+ */
+ int keyCode() const;
+
+ /**
+ * Non-standard extension to support IE-style charCode event property.
+ *
+ */
+ int charCode() const;
+
+ /**
+ * Non-standard extensions to support Netscape-style pageX and pageY event properties.
+ *
+ */
+ int pageX() const;
+ int pageY() const;
+
+ /**
+ * Non-standard extensions to support Netscape-style layerX and layerY event properties.
+ *
+ */
+ int layerX() const;
+ int layerY() const;
+
+ /**
+ * Non-standard extension to support Netscape-style "which" event property.
+ *
+ */
+ int which() const;
+
+ /**
+ * The initUIEvent method is used to initialize the value of a UIEvent
+ * created through the DocumentEvent interface. This method may only be
+ * called before the UIEvent has been dispatched via the dispatchEvent
+ * method, though it may be called multiple times during that phase if
+ * necessary. If called multiple times, the final invocation takes
+ * precedence.
+ *
+ * @param typeArg Specifies the event type.
+ *
+ * @param canBubbleArg Specifies whether or not the event can bubble.
+ *
+ * @param cancelableArg Specifies whether or not the event's default action
+ * can be prevented.
+ *
+ * @param viewArg Specifies the Event's AbstractView.
+ *
+ * @param detailArg Specifies the Event's detail.
+ *
+ */
+ void initUIEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg);
+protected:
+ UIEvent(UIEventImpl *impl);
+};
+
+
+
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * The MouseEvent interface provides specific contextual information associated
+ * with Mouse events.
+ *
+ * The detail attribute inherited from UIEvent indicates the number of times a
+ * mouse button has been pressed and released over the same screen location
+ * during a user action. The attribute value is 1 when the user begins this
+ * action and increments by 1 for each full sequence of pressing and releasing.
+ * If the user moves the mouse between the mousedown and mouseup the value will
+ * be set to 0, indicating that no click is occurring.
+ *
+ * In the case of nested elements mouse events are always targeted at the most
+ * deeply nested element. Ancestors of the targeted element may use bubbling to
+ * obtain notification of mouse events which occur within its descendent elements.
+ *
+ */
+class KHTML_EXPORT MouseEvent : public UIEvent {
+public:
+ MouseEvent();
+ MouseEvent(const MouseEvent &other);
+ MouseEvent(const Event &other);
+ MouseEvent & operator = (const MouseEvent &other);
+ MouseEvent & operator = (const Event &other);
+ virtual ~MouseEvent();
+
+ /**
+ * The horizontal coordinate at which the event occurred relative to the
+ * origin of the screen coordinate system.
+ *
+ */
+ long screenX() const;
+
+ /**
+ * The vertical coordinate at which the event occurred relative to the
+ * origin of the screen coordinate system.
+ *
+ */
+ long screenY() const;
+
+ /**
+ * The horizontal coordinate at which the event occurred relative to the
+ * DOM implementation's client area.
+ *
+ */
+ long clientX() const;
+
+ /**
+ * The vertical coordinate at which the event occurred relative to the DOM
+ * implementation's client area.
+ *
+ */
+ long clientY() const;
+
+ /**
+ * Used to indicate whether the 'ctrl' key was depressed during the firing
+ * of the event.
+ */
+ bool ctrlKey() const;
+
+ /**
+ * Used to indicate whether the 'shift' key was depressed during the firing
+ * of the event.
+ *
+ */
+ bool shiftKey() const;
+
+ /**
+ * Used to indicate whether the 'alt' key was depressed during the firing
+ * of the event. On some platforms this key may map to an alternative key
+ * name.
+ *
+ */
+ bool altKey() const;
+
+ /**
+ * Used to indicate whether the 'meta' key was depressed during the firing
+ * of the event. On some platforms this key may map to an alternative key
+ * name.
+ *
+ */
+ bool metaKey() const;
+
+ /**
+ * During mouse events caused by the depression or release of a mouse
+ * button, button is used to indicate which mouse button changed state. The
+ * values for button range from zero to indicate the left button of the
+ * mouse, one to indicate the middle button if present, and two to indicate
+ * the right button. For mice configured for left handed use in which the
+ * button actions are reversed the values are instead read from right to
+ * left.
+ *
+ */
+ unsigned short button() const;
+
+ /**
+ * Used to identify a secondary EventTarget related to a UI event.
+ * Currently this attribute is used with the mouseover event to indicate
+ * the EventTarget which the pointing device exited and with the mouseout
+ * event to indicate the EventTarget which the pointing device entered.
+ *
+ */
+ Node relatedTarget() const;
+
+ /**
+ * The initMouseEvent method is used to initialize the value of a
+ * MouseEvent created through the DocumentEvent interface. This method may
+ * only be called before the MouseEvent has been dispatched via the
+ * dispatchEvent method, though it may be called multiple times during that
+ * phase if necessary. If called multiple times, the final invocation takes
+ * precedence. Parameters
+ *
+ * @param typeArg Specifies the event type.
+ *
+ * @param canBubbleArg Specifies whether or not the event can bubble.
+ *
+ * @param cancelableArg Specifies whether or not the event's default action can be prevented.
+ *
+ * @param viewArg Specifies the Event's AbstractView.
+ *
+ * @param detailArg Specifies the Event's mouse click count.
+ *
+ * @param screenXArg Specifies the Event's screen x coordinate
+ *
+ * @param screenYArg Specifies the Event's screen y coordinate
+ *
+ * @param clientXArg Specifies the Event's client x coordinate
+ *
+ * @param clientYArg Specifies the Event's client y coordinate
+ *
+ * @param ctrlKeyArg Specifies whether or not control key was depressed during the Event.
+ *
+ * @param altKeyArg Specifies whether or not alt key was depressed during the Event.
+ *
+ * @param shiftKeyArg Specifies whether or not shift key was depressed during the Event.
+ *
+ * @param metaKeyArg Specifies whether or not meta key was depressed during the Event.
+ *
+ * @param buttonArg Specifies the Event's mouse button.
+ *
+ * @param relatedTargetArg Specifies the Event's related EventTarget.
+ *
+ */
+ void initMouseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ const Node &relatedTargetArg);
+protected:
+ MouseEvent(MouseEventImpl *impl);
+};
+
+// Introduced in DOM Level 3:
+/**
+ * DOM::TextEvent
+ * The detail attribute inherited from UIEvent is used to indicate
+ * the number of keypresses which have occurred during key repetition.
+ * If this information is not available this value should be 0.
+ *
+ * ### KDE4: split this up into proper KeyboardEvent and TextEvent classes
+ * as specified in current DOM3 Events revision. This is doing heavy emulation
+ * at the moment
+ */
+class KHTML_EXPORT TextEvent : public UIEvent {
+public:
+ TextEvent();
+ TextEvent(const TextEvent &other);
+ TextEvent(const Event &other);
+ TextEvent & operator = (const TextEvent &other);
+ TextEvent & operator = (const Event &other);
+ virtual ~TextEvent();
+
+ /**
+ * initTextEvent
+ *
+ * The initTextEvent method is used to initialize the value of a
+ * MouseEvent created through the DocumentEvent interface. This
+ * method may only be called before the TextEvent has been dispatched
+ * via the dispatchEvent method, though it may be called multiple
+ * times during that phase if necessary. If called multiple times,
+ * the final invocation takes precedence. This method has no effect
+ * if called after the event has been dispatched.
+ *
+ * Parameters:
+ *
+ * typeArg of type DOMString
+ * Specifies the event type.
+ * canBubbleArg of type boolean
+ * Specifies whether or not the event can bubble.
+ * cancelableArg of type boolean
+ * Specifies whether or not the event's default action can be prevent.
+ * viewArg of type views::AbstractView
+ * Specifies the TextEvent's AbstractView.
+ * detailArg of type unsigned short
+ * Specifies the number of repeated keypresses, if available.
+ * outputStringArg of type DOMString
+ * Specifies the TextEvent's outputString attribute
+ * keyValArg of type unsigned long
+ * Specifies the TextEvent's keyValattribute
+ * virtKeyValArg of type unsigned long
+ * Specifies the TextEvent's virtKeyValattribute
+ * inputGeneratedArg of type boolean
+ * Specifies the TextEvent's inputGeneratedattribute
+ * numPadArg of type boolean
+ * Specifies the TextEvent's numPadattribute
+ *
+ * No Return Value.
+ * No Exceptions.
+ */
+ void initTextEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg,
+ const DOMString &outputStringArg,
+ unsigned long keyValArg,
+ unsigned long virtKeyValArg,
+ bool inputGeneratedArg,
+ bool numPadArg);
+
+ /**
+ * initModifier
+ *
+ * The initModifier method is used to initialize the values of any
+ * modifiers associated with a TextEvent created through the
+ * DocumentEvent interface. This method may only be called before the
+ * TextEvent has been dispatched via the dispatchEvent method, though
+ * it may be called multiple times during that phase if necessary. If
+ * called multiple times with the same modifier property the final
+ * invocation takes precedence. Unless explicitly give a value of
+ * true, all modifiers have a value of false. This method has no
+ * effect if called after the event has been dispatched. The list of
+ * keys below represents the allowable modifier parameters for this
+ * method (note: this was not documented properly in earlier versions):
+ *
+ * Qt::ShiftButton, Qt::AltButton, Qt::ControlButton, Qt::MetaButton
+ *
+ * Parameters:
+ *
+ * modifier of type unsigned long
+ * The modifier which the user wishes to initialize
+ * value of type boolean
+ * The new value of the modifier.
+ *
+ * No Return Value
+ * No Exceptions
+ */
+ void initModifier(unsigned long modifierArg, bool valueArg);
+
+ /**
+ * inputGenerated of type boolean
+ *
+ * The inputGenerated attribute indicates whether the key event will
+ * normally cause visible output. If the key event does not
+ * generate any visible output, such as the use of a function key
+ * or the combination of certain modifier keys used in conjunction
+ * with another key, then the value will be false. If visible
+ * output is normally generated by the key event then the value
+ * will be true. The value of inputGenerated does not guarantee
+ * the creation of a character. If a key event causing visible
+ * output is cancelable it may be prevented from causing
+ * output. This attribute is intended primarily to differentiate
+ * between keys events which may or may not produce visible output
+ * depending on the system state.
+ */
+ bool inputGenerated() const;
+
+ /** keyVal of type unsigned long
+ *
+ * The value of keyVal holds the value of the Unicode character
+ * associated with the depressed key. If the key has no Unicode
+ * representation or no Unicode character is available the value is
+ * 0.
+ */
+ unsigned long keyVal() const;
+
+ /** numPad of type boolean
+ *
+ * The numPad attribute indicates whether or not the key event was
+ * generated on the number pad section of the keyboard. If the number
+ * pad was used to generate the key event the value is true,
+ * otherwise the value is false.
+ */
+ bool numPad() const;
+
+ /**
+ *outputString of type DOMString
+ *
+ * outputString holds the value of the output generated by the key
+ * event. This may be a single Unicode character or it may be a
+ * string. It may also be null in the case where no output was
+ * generated by the key event.
+ */
+
+ DOMString outputString() const;
+ /** virtKeyVal of type unsigned long
+ *
+ * When the key associated with a key event is not representable via
+ * a Unicode character virtKeyVale holds the virtual key code
+ * associated with the depressed key. If the key has a Unicode
+ * representation or no virtual code is available the value is
+ * DOM_VK_UNDEFINED.
+ */
+ unsigned long virtKeyVal() const;
+
+ /**
+ * checkModifier
+ *
+ * Note: the below description does not match the actual behavior.
+ * it's extended in a way that you can query multiple modifiers
+ * at once by logically OR`ing them.
+ * also, we use the Qt modifier enum instead of the DOM one.
+ *
+ * The CheckModifier method is used to check the status of a single
+ * modifier key associated with a TextEvent. The identifier of the
+ * modifier in question is passed into the CheckModifier function. If
+ * the modifier is triggered it will return true. If not, it will
+ * return false. The list of keys below represents the allowable
+ * modifier parameters for this method (warning: this was not documented
+ * properly in earlier versions):
+ * Qt::ShiftButton, Qt::AltButton, Qt::ControlButton, Qt::MetaButton
+ *
+ * Parameters:
+ *
+ * modifier of type unsigned long
+ * The modifier which the user wishes to query.
+ *
+ * Return Value: boolean
+ * The status of the modifier represented as a boolean.
+ *
+ * No Exceptions
+ */
+ bool checkModifier(unsigned long modifierArg); // ### KDE 4: const!
+
+protected:
+ TextEvent(KeyEventBaseImpl *impl);
+};
+
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * The MutationEvent interface provides specific contextual information
+ * associated with Mutation events.
+ *
+ */
+class KHTML_EXPORT MutationEvent : public Event {
+public:
+ MutationEvent();
+ MutationEvent(const MutationEvent &other);
+ MutationEvent(const Event &other);
+ MutationEvent & operator = (const MutationEvent &other);
+ MutationEvent & operator = (const Event &other);
+ virtual ~MutationEvent();
+
+ /**
+ * An integer indicating in which way the Attr was changed.
+ *
+ * ADDITION: The Attr was just added.
+ *
+ * MODIFICATION: The Attr was modified in place.
+ *
+ * REMOVAL: The Attr was just removed.
+ *
+ */
+ enum attrChangeType {
+ MODIFICATION = 1,
+ ADDITION = 2,
+ REMOVAL = 3
+ };
+
+
+ /**
+ * relatedNode is used to identify a secondary node related to a mutation
+ * event. For example, if a mutation event is dispatched to a node
+ * indicating that its parent has changed, the relatedNode is the changed
+ * parent. If an event is instead dispatched to a subtree indicating a node
+ * was changed within it, the relatedNode is the changed node. In the case
+ * of the DOMAttrModified event it indicates the Attr node which was
+ * modified, added, or removed.
+ *
+ */
+ Node relatedNode() const;
+
+ /**
+ * prevValue indicates the previous value of the Attr node in
+ * DOMAttrModified events, and of the CharacterData node in
+ * DOMCharDataModified events.
+ *
+ */
+ DOMString prevValue() const;
+
+ /**
+ * newValue indicates the new value of the Attr node in DOMAttrModified
+ * events, and of the CharacterData node in DOMCharDataModified events.
+ *
+ */
+ DOMString newValue() const;
+
+ /**
+ * attrName indicates the name of the changed Attr node in a
+ * DOMAttrModified event.
+ *
+ */
+ DOMString attrName() const;
+
+ /**
+ * attrChange indicates the type of change which triggered the
+ * DOMAttrModified event. The values can be MODIFICATION, ADDITION, or
+ * REMOVAL.
+ *
+ */
+ unsigned short attrChange() const;
+
+ /**
+ * The initMutationEvent method is used to initialize the value of a
+ * MutationEvent created through the DocumentEvent interface. This method
+ * may only be called before the MutationEvent has been dispatched via the
+ * dispatchEvent method, though it may be called multiple times during that
+ * phase if necessary. If called multiple times, the final invocation takes
+ * precedence.
+ *
+ * @param typeArg Specifies the event type.
+ *
+ * @param canBubbleArg Specifies whether or not the event can bubble.
+ *
+ * @param cancelableArg Specifies whether or not the event's default action can be prevented.
+ *
+ * @param relatedNodeArg Specifies the Event's related Node.
+ *
+ * @param prevValueArg Specifies the Event's prevValue attribute. This value may be null.
+ *
+ * @param newValueArg Specifies the Event's newValue attribute. This value may be null.
+ *
+ * @param attrNameArg Specifies the Event's attrName attribute. This value may be null.
+ *
+ * @param attrChangeArg Specifies the Event's attrChange attribute
+ *
+ */
+ void initMutationEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg);
+protected:
+ MutationEvent(MutationEventImpl *impl);
+};
+
+
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom2_range.cpp b/tdehtml/dom/dom2_range.cpp
new file mode 100644
index 000000000..87bdab145
--- /dev/null
+++ b/tdehtml/dom/dom2_range.cpp
@@ -0,0 +1,406 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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.
+ *
+ */
+#include "dom/dom_exception.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_rangeimpl.h"
+
+using namespace DOM;
+
+Range::Range()
+{
+ // a range can't exist by itself - it must be associated with a document
+ impl = 0;
+}
+
+Range::Range(const Document rootContainer)
+{
+ if(rootContainer.handle())
+ {
+ impl = new RangeImpl(rootContainer.handle()->docPtr());
+ impl->ref();
+ }
+ else
+ impl = 0;
+}
+
+Range::Range(const Range &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+Range::Range(const Node startContainer, const long startOffset, const Node endContainer, const long endOffset)
+{
+ if (startContainer.isNull() || endContainer.isNull()) {
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+ }
+
+ if (!startContainer.handle()->getDocument() ||
+ startContainer.handle()->getDocument() != endContainer.handle()->getDocument()) {
+ throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
+ }
+
+ impl = new RangeImpl(startContainer.handle()->docPtr(),startContainer.handle(),startOffset,endContainer.handle(),endOffset);
+ impl->ref();
+}
+
+Range::Range(RangeImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+Range &Range::operator = (const Range &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+Range::~Range()
+{
+ if (impl) impl->deref();
+}
+
+Node Range::startContainer() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = impl->startContainer(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+long Range::startOffset() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ long r = impl->startOffset(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+
+}
+
+Node Range::endContainer() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = impl->endContainer(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+long Range::endOffset() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ long r = impl->endOffset(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+bool Range::collapsed() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ bool r = impl->collapsed(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+Node Range::commonAncestorContainer()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = impl->commonAncestorContainer(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+void Range::setStart( const Node &refNode, long offset )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->setStart(refNode.handle(),offset,exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::setEnd( const Node &refNode, long offset )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->setEnd(refNode.handle(),offset,exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::setStartBefore( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+
+ int exceptioncode = 0;
+ impl->setStartBefore(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::setStartAfter( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->setStartAfter(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::setEndBefore( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->setEndBefore(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::setEndAfter( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->setEndAfter(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::collapse( bool toStart )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->collapse(toStart,exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::selectNode( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->selectNode(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::selectNodeContents( const Node &refNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->selectNodeContents(refNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+short Range::compareBoundaryPoints( CompareHow how, const Range &sourceRange )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ short r = impl->compareBoundaryPoints(how,sourceRange.handle(),exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+bool Range::boundaryPointsValid( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->boundaryPointsValid();
+}
+
+void Range::deleteContents( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->deleteContents(exceptioncode);
+ throwException(exceptioncode);
+}
+
+DocumentFragment Range::extractContents( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ DocumentFragmentImpl *r = impl->extractContents(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+DocumentFragment Range::cloneContents( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ DocumentFragmentImpl *r = impl->cloneContents(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+void Range::insertNode( const Node &newNode )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->insertNode(newNode.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+void Range::surroundContents( const Node &newParent )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->surroundContents(newParent.handle(),exceptioncode);
+ throwException(exceptioncode);
+}
+
+Range Range::cloneRange( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ RangeImpl *r = impl->cloneRange(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+DOMString Range::toString( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ DOMString r = impl->toString(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+
+}
+
+DOMString Range::toHTML( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+ int exceptioncode = 0;
+ DOMString r = impl->toHTML(exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+DocumentFragment Range::createContextualFragment( const DOMString &html )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ DocumentFragment r = impl->createContextualFragment(html, exceptioncode);
+ throwException(exceptioncode);
+ return r;
+}
+
+
+void Range::detach( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->detach(exceptioncode);
+ throwException(exceptioncode);
+}
+
+bool Range::isDetached() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->isDetached();
+}
+
+RangeImpl *Range::handle() const
+{
+ return impl;
+}
+
+bool Range::isNull() const
+{
+ return (impl == 0);
+}
+
+void Range::throwException(int exceptioncode) const
+{
+ if (!exceptioncode)
+ return;
+
+ // ### also check for CSS & other exceptions?
+ if (exceptioncode >= RangeException::_EXCEPTION_OFFSET && exceptioncode <= RangeException::_EXCEPTION_MAX)
+ throw RangeException(static_cast<RangeException::RangeExceptionCode>(exceptioncode-RangeException::_EXCEPTION_OFFSET));
+ else
+ throw DOMException(exceptioncode);
+}
+
+
+
diff --git a/tdehtml/dom/dom2_range.h b/tdehtml/dom/dom2_range.h
new file mode 100644
index 000000000..290f4f48c
--- /dev/null
+++ b/tdehtml/dom/dom2_range.h
@@ -0,0 +1,475 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Candidate Recommendation)
+ * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _dom2_range_h_
+#define _dom2_range_h_
+
+#include <dom/dom_doc.h>
+#include <dom/dom_misc.h>
+
+namespace DOM {
+
+class DocumentFragment;
+class Node;
+class DOMString;
+class DocumentImpl;
+class RangeImpl;
+
+class DOMException;
+
+// Introduced in DOM Level 2:
+class KHTML_EXPORT RangeException {
+public:
+ RangeException(unsigned short _code) { code = _code; }
+ RangeException(const RangeException &other) { code = other.code; }
+
+ RangeException & operator = (const RangeException &other)
+ { code = other.code; return *this; }
+
+ virtual ~RangeException() {}
+ /**
+ * An integer indicating the type of error generated.
+ *
+ */
+ enum RangeExceptionCode {
+ BAD_BOUNDARYPOINTS_ERR = 1,
+ INVALID_NODE_TYPE_ERR = 2,
+ _EXCEPTION_OFFSET = 2000,
+ _EXCEPTION_MAX = 2999
+ };
+ unsigned short code;
+};
+
+
+class KHTML_EXPORT Range
+{
+ friend class DocumentImpl;
+ friend class Document;
+ friend class RangeImpl;
+public:
+ Range();
+ Range(const Document rootContainer);
+ Range(const Range &other);
+ Range(const Node startContainer, const long startOffset, const Node endContainer, const long endOffset);
+
+ Range & operator = (const Range &other);
+
+ ~Range();
+
+ /**
+ * Node within which the range begins
+ *
+ */
+ Node startContainer() const;
+
+ /**
+ * Offset within the starting node of the range.
+ *
+ */
+ long startOffset() const;
+
+ /**
+ * Node within which the range ends
+ *
+ */
+ Node endContainer() const;
+
+ /**
+ * Offset within the ending node of the range.
+ *
+ */
+ long endOffset() const;
+
+ /**
+ * true if the range is collapsed
+ *
+ */
+ bool collapsed() const;
+
+ /**
+ * Gets the common ancestor container of the range's two end-points.
+ * Also sets it.
+ *
+ */
+ // ### BIC make const in the next release
+ Node commonAncestorContainer();
+
+ /**
+ * Sets the attributes describing the start of the range.
+ *
+ * @param refNode The \c refNode value. This parameter
+ * must be different from \c null .
+ *
+ * @param offset The \c startOffset value.
+ *
+ * @return
+ *
+ * @exception RangeException
+ * NULL_NODE_ERR: Raised if \c refNode is \c null .
+ *
+ * INVALID_NODE_TYPE_ERR: Raised if \c refNode or an
+ * ancestor of \c refNode is an Attr, Entity,
+ * Notation, or DocumentType node.
+ *
+ * If an offset is out-of-bounds, should it just be fixed up or
+ * should an exception be raised.
+ *
+ */
+ void setStart ( const Node &refNode, long offset );
+
+ /**
+ * Sets the attributes describing the end of a range.
+ *
+ * @param refNode The \c refNode value. This parameter
+ * must be different from \c null .
+ *
+ * @param offset The \c endOffset value.
+ *
+ * @return
+ *
+ * @exception RangeException
+ * NULL_NODE_ERR: Raised if \c refNode is \c null .
+ *
+ * INVALID_NODE_TYPE_ERR: Raised if \c refNode or an
+ * ancestor of \c refNode is an Attr, Entity,
+ * Notation, or DocumentType node.
+ *
+ */
+ void setEnd ( const Node &refNode, long offset );
+
+ /**
+ * Sets the start position to be before a node
+ *
+ * @param refNode Range starts before \c refNode
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of \c refNode
+ * is an Attr, Entity, Notation, or DocumentType node or
+ * if \c refNode is a Document, DocumentFragment,
+ * Attr, Entity, or Notation node.
+ *
+ */
+ void setStartBefore ( const Node &refNode );
+
+ /**
+ * Sets the start position to be after a node
+ *
+ * @param refNode Range starts after \c refNode
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of \c refNode
+ * is an Attr, Entity, Notation, or DocumentType node or
+ * if \c refNode is a Document, DocumentFragment,
+ * Attr, Entity, or Notation node.
+ *
+ */
+ void setStartAfter ( const Node &refNode );
+
+ /**
+ * Sets the end position to be before a node.
+ *
+ * @param refNode Range ends before \c refNode
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of \c refNode
+ * is an Attr, Entity, Notation, or DocumentType node or
+ * if \c refNode is a Document, DocumentFragment,
+ * Attr, Entity, or Notation node.
+ *
+ */
+ void setEndBefore ( const Node &refNode );
+
+ /**
+ * Sets the end of a range to be after a node
+ *
+ * @param refNode Range ends after \c refNode .
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of \c refNode
+ * is an Attr, Entity, Notation or DocumentType node or if
+ * \c refNode is a Document, DocumentFragment, Attr,
+ * Entity, or Notation node.
+ *
+ */
+ void setEndAfter ( const Node &refNode );
+
+ /**
+ * Collapse a range onto one of its end-points
+ *
+ * @param toStart If true, collapses the Range onto its start; if
+ * false, collapses it onto its end.
+ *
+ * @return
+ *
+ */
+ void collapse ( bool toStart );
+
+ /**
+ * Select a node and its contents
+ *
+ * @param refNode The node to select.
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if an ancestor of \c refNode
+ * is an Attr, Entity, Notation or DocumentType node or if
+ * \c refNode is a Document, DocumentFragment, Attr,
+ * Entity, or Notation node.
+ *
+ */
+ void selectNode ( const Node &refNode );
+
+ /**
+ * Select the contents within a node
+ *
+ * @param refNode Node to select from
+ *
+ * @return
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if \c refNode or an
+ * ancestor of \c refNode is an Attr, Entity, Notation
+ * or DocumentType node.
+ *
+ */
+ void selectNodeContents ( const Node &refNode );
+
+ enum CompareHow {
+ START_TO_START = 0,
+ START_TO_END = 1,
+ END_TO_END = 2,
+ END_TO_START = 3
+ };
+
+ /**
+ * Compare the end-points of two ranges in a document.
+ *
+ * @param how
+ *
+ * @param sourceRange
+ *
+ * @return -1, 0 or 1 depending on whether the corresponding
+ * end-point of the Range is before, equal to, or after the
+ * corresponding end-point of \c sourceRange .
+ *
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if the two Ranges are not in the
+ * same document or document fragment.
+ *
+ */
+ short compareBoundaryPoints ( CompareHow how, const Range &sourceRange );
+
+ /**
+ * @internal
+ * not part of the DOM
+ *
+ * Compare the boundary-points of a range.
+ *
+ * Return true if the startContainer is before the endContainer,
+ * or if they are equal.
+ * Return false if the startContainer is after the endContainer.
+ *
+ */
+ bool boundaryPointsValid ( );
+
+ /**
+ * Removes the contents of a range from the containing document or
+ * document fragment without returning a reference to the removed
+ * content.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the
+ * content of the range is read-only or any of the nodes that
+ * contain any of the content of the range are read-only.
+ *
+ */
+ void deleteContents ( );
+
+ /**
+ * Moves the contents of a range from the containing document or
+ * document fragment to a new DocumentFragment.
+ *
+ * @return A DocumentFragment containing the extracted contents.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if any portion of the
+ * content of the range is read-only or any of the nodes which
+ * contain any of the content of the range are read-only.
+ *
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be
+ * extracted into the new DocumentFragment.
+ *
+ */
+ DocumentFragment extractContents ( );
+
+ /**
+ * Duplicates the contents of a range
+ *
+ * @return A DocumentFragment containing contents equivalent to
+ * those of this range.
+ *
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if a DocumentType node would be
+ * extracted into the new DocumentFragment.
+ *
+ */
+ DocumentFragment cloneContents ( );
+
+ /**
+ * Inserts a node into the document or document fragment at the
+ * start of the range.
+ *
+ * @param newNode The node to insert at the start of the range
+ *
+ * @return
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of
+ * the start of the range is read-only.
+ *
+ * WRONG_DOCUMENT_ERR: Raised if \c newNode and the
+ * container of the start of the Range were not created from the
+ * same document.
+ *
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the start of
+ * the Range is of a type that does not allow children of the type
+ * of \c newNode or if \c newNode is an
+ * ancestor of the container .
+ *
+ * @exception RangeException
+ * INVALID_NODE_TYPE_ERR: Raised if \c node is an
+ * Attr, Entity, Notation, DocumentFragment, or Document node.
+ *
+ */
+ void insertNode ( const Node &newNode );
+
+ /**
+ * Reparents the contents of the range to the given node and
+ * inserts the node at the position of the start of the range.
+ *
+ * @param newParent The node to surround the contents with.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of
+ * either end-point of the range is read-only.
+ *
+ * WRONG_DOCUMENT_ERR: Raised if \c newParent and the
+ * container of the start of the Range were not created from the
+ * same document.
+ *
+ * HIERARCHY_REQUEST_ERR: Raised if the container of the start of
+ * the Range is of a type that does not allow children of the type
+ * of \c newParent or if \c newParent is
+ * an ancestor of the container or if \c node would
+ * end up with a child node of a type not allowed by the type of
+ * \c node .
+ *
+ * @exception RangeException
+ * BAD_ENDPOINTS_ERR: Raised if the range partially selects a
+ * non-text node.
+ *
+ * INVALID_NODE_TYPE_ERR: Raised if \c node is an
+ * Attr, Entity, DocumentType, Notation, Document, or
+ * DocumentFragment node.
+ *
+ */
+ void surroundContents ( const Node &newParent );
+
+ /**
+ * Produces a new range whose end-points are equal to the
+ * end-points of the range.
+ *
+ * @return The duplicated range.
+ *
+ */
+ Range cloneRange ( );
+
+ /**
+ * Returns the contents of a range as a string.
+ *
+ * @return The contents of the range.
+ *
+ */
+ DOMString toString ( );
+
+ /**
+ * @internal Not part of DOM
+ */
+ DOMString toHTML ( );
+
+ /* Mozilla extension - only works for HTML documents. */
+ DocumentFragment createContextualFragment (const DOMString &html);
+
+ /**
+ * Called to indicate that the range is no longer in use and that
+ * the implementation may relinquish any resources associated with
+ * this range. Subsequent calls to any methods or attribute getters
+ * on this range will result in a DOMException being thrown with an
+ * error code of INVALID_STATE_ERR.
+ *
+ */
+ void detach ( );
+
+ /**
+ * not part of the DOM
+ * true if the range is detached
+ *
+ */
+ bool isDetached() const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ RangeImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ RangeImpl *impl;
+ Range(RangeImpl *i);
+private:
+ void throwException(int exceptioncode) const;
+};
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/dom2_traversal.cpp b/tdehtml/dom/dom2_traversal.cpp
new file mode 100644
index 000000000..c0a09435b
--- /dev/null
+++ b/tdehtml/dom/dom2_traversal.cpp
@@ -0,0 +1,381 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * 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 "dom/dom_exception.h"
+#include "dom/dom_string.h"
+#include "xml/dom2_traversalimpl.h"
+
+using namespace DOM;
+
+
+NodeIterator::NodeIterator()
+{
+ impl = 0;
+}
+
+NodeIterator::NodeIterator(const NodeIterator &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+NodeIterator::NodeIterator(NodeIteratorImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+NodeIterator &NodeIterator::operator = (const NodeIterator &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+NodeIterator::~NodeIterator()
+{
+ if (impl) impl->deref();
+}
+
+Node NodeIterator::root()
+{
+ if (impl) return impl->root();
+ return 0;
+}
+
+unsigned long NodeIterator::whatToShow()
+{
+ if (impl) return impl->whatToShow();
+ return 0;
+}
+
+NodeFilter NodeIterator::filter()
+{
+ if (impl) return impl->filter();
+ return 0;
+}
+
+bool NodeIterator::expandEntityReferences()
+{
+ if (impl) return impl->expandEntityReferences();
+ return 0;
+}
+
+Node NodeIterator::nextNode( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = impl->nextNode(exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+Node NodeIterator::previousNode( )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = impl->previousNode(exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+void NodeIterator::detach()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ impl->detach(exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+NodeIteratorImpl *NodeIterator::handle() const
+{
+ return impl;
+}
+
+bool NodeIterator::isNull() const
+{
+ return (impl == 0);
+}
+
+// -----------------------------------------------------------
+
+NodeFilter::NodeFilter()
+{
+ impl = 0;
+}
+
+NodeFilter::NodeFilter(const NodeFilter &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+NodeFilter::NodeFilter(NodeFilterImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+NodeFilter &NodeFilter::operator = (const NodeFilter &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+NodeFilter::~NodeFilter()
+{
+ if (impl) impl->deref();
+}
+
+short NodeFilter::acceptNode(const Node &n)
+{
+ if (impl) return impl->acceptNode(n);
+ return 0;
+}
+
+void NodeFilter::setCustomNodeFilter(CustomNodeFilter *custom)
+{
+ if (impl) impl->setCustomNodeFilter(custom);
+}
+
+CustomNodeFilter *NodeFilter::customNodeFilter()
+{
+ if (impl) return impl->customNodeFilter();
+ return 0;
+}
+
+NodeFilterImpl *NodeFilter::handle() const
+{
+ return impl;
+}
+
+bool NodeFilter::isNull() const
+{
+ return (impl == 0);
+}
+
+NodeFilter NodeFilter::createCustom(CustomNodeFilter *custom)
+{
+ NodeFilterImpl *i = new NodeFilterImpl();
+ i->setCustomNodeFilter(custom);
+ return i;
+}
+
+// --------------------------------------------------------------
+CustomNodeFilter::CustomNodeFilter()
+{
+ impl = 0;
+}
+
+CustomNodeFilter::~CustomNodeFilter()
+{
+}
+
+short CustomNodeFilter::acceptNode (const Node &/*n*/)
+{
+ return NodeFilter::FILTER_ACCEPT;
+}
+
+bool CustomNodeFilter::isNull()
+{
+ return false;
+}
+
+DOMString CustomNodeFilter::customNodeFilterType()
+{
+ return "";
+}
+
+// --------------------------------------------------------------
+
+TreeWalker::TreeWalker()
+{
+ impl = 0;
+}
+
+TreeWalker::TreeWalker(const TreeWalker &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+TreeWalker::TreeWalker(TreeWalkerImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+TreeWalker & TreeWalker::operator = (const TreeWalker &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+
+ return *this;
+}
+
+TreeWalker::~TreeWalker()
+{
+ if (impl) impl->deref();
+}
+
+Node TreeWalker::root()
+{
+ if (impl) return impl->getRoot();
+ return 0;
+}
+
+unsigned long TreeWalker::whatToShow()
+{
+ if (impl) return impl->getWhatToShow();
+ return 0;
+}
+
+NodeFilter TreeWalker::filter()
+{
+ if (impl) return impl->getFilter();
+ return 0;
+}
+
+bool TreeWalker::expandEntityReferences()
+{
+ if (impl) return impl->getExpandEntityReferences();
+ return false;
+}
+
+Node TreeWalker::currentNode()
+{
+ if (impl) return impl->getCurrentNode();
+ return 0;
+}
+
+void TreeWalker::setCurrentNode(const Node& _currentNode)
+{
+ if (impl) impl->setCurrentNode(_currentNode.handle());
+}
+
+Node TreeWalker::parentNode()
+{
+ if (impl) return impl->parentNode();
+ return 0;
+}
+
+Node TreeWalker::firstChild()
+{
+ if (impl) return impl->firstChild();
+ return 0;
+}
+
+Node TreeWalker::lastChild()
+{
+ if (impl) return impl->lastChild();
+ return 0;
+}
+
+Node TreeWalker::previousSibling()
+{
+ if (impl) return impl->previousSibling();
+ return 0;
+}
+
+Node TreeWalker::nextSibling()
+{
+ if (impl) return impl->nextSibling();
+ return 0;
+}
+
+Node TreeWalker::previousNode()
+{
+ if (impl) return impl->previousNode();
+ return 0;
+}
+
+Node TreeWalker::nextNode()
+{
+ if (impl) return impl->nextNode();
+ return 0;
+}
+
+TreeWalkerImpl *TreeWalker::handle() const
+{
+ return impl;
+}
+
+bool TreeWalker::isNull() const
+{
+ return (impl == 0);
+}
+
+// -----------------------------------------------------------------------
+
+/*DocumentTraversal::DocumentTraversal()
+{
+}
+
+DocumentTraversal::DocumentTraversal(const DocumentTraversal &other)
+{
+}
+
+DocumentTraversal &DocumentTraversal::operator = (const DocumentTraversal &other)
+{
+ DocumentTraversal::operator = (other);
+ return *this;
+}
+
+DocumentTraversal::~DocumentTraversal()
+{
+}
+
+NodeIterator DocumentTraversal::createNodeIterator( const Node &root, long whatToShow,
+ const NodeFilter &filter,
+ bool entityReferenceExpansion )
+{
+ return NodeIterator();
+}
+
+TreeWalker DocumentTraversal::createTreeWalker( const Node &root, long whatToShow,
+ const NodeFilter &filter,
+ bool entityReferenceExpansion )
+{
+ return TreeWalker();
+}
+
+*/
+
diff --git a/tdehtml/dom/dom2_traversal.h b/tdehtml/dom/dom2_traversal.h
new file mode 100644
index 000000000..ea3d3521b
--- /dev/null
+++ b/tdehtml/dom/dom2_traversal.h
@@ -0,0 +1,617 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 2 Specification (Candidate Recommendation)
+ * http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510/
+ * Copyright © 2000 W3C® (MIT, INRIA, Keio), All Rights Reserved.
+ *
+ */
+#ifndef _dom2_traversal_h_
+#define _dom2_traversal_h_
+#include <dom/dom_node.h>
+#include <dom/dom_misc.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+class Node;
+class NodeFilter;
+class NodeImpl;
+class NodeIteratorImpl;
+class NodeFilterImpl;
+class TreeWalkerImpl;
+class CustomNodeFilter;
+class CustomNodeFilterImpl;
+
+/**
+ * NodeIterators are used to step through a set of nodes, e.g. the set
+ * of nodes in a NodeList, the document subtree governed by a
+ * particular node, the results of a query, or any other set of nodes.
+ * The set of nodes to be iterated is determined by the implementation
+ * of the NodeIterator. DOM Level 2 specifies a single NodeIterator
+ * implementation for document-order traversal of a document subtree.
+ * Instances of these iterators are created by calling
+ * DocumentTraversal.createNodeIterator().
+ *
+ * Any Iterator that returns nodes may implement the
+ * \c NodeIterator interface. Users and vendor libraries may also
+ * choose to create Iterators that implement the \c NodeIterator
+ * interface.
+ *
+ */
+class KHTML_EXPORT NodeIterator
+{
+ friend class NodeIteratorImpl;
+ friend class Document;
+public:
+ NodeIterator();
+ NodeIterator(const NodeIterator &other);
+
+ NodeIterator & operator = (const NodeIterator &other);
+
+ ~NodeIterator();
+
+ /**
+ * The root node of the NodeIterator, as specified when it was created.
+ */
+ Node root();
+
+ /**
+ * This attribute determines which node types are presented via the
+ * iterator. The available set of constants is defined in the NodeFilter
+ * interface. Nodes not accepted by whatToShow will be skipped, but their
+ * children may still be considered. Note that this skip takes precedence
+ * over the filter, if any.
+ */
+ unsigned long whatToShow();
+
+ /**
+ * The NodeFilter used to screen nodes.
+ */
+ NodeFilter filter();
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the iterator. If false, they and
+ * their descendents will be rejected. Note that this rejection takes
+ * precedence over whatToShow and the filter. Also note that this is
+ * currently the only situation where NodeIterators may reject a complete
+ * subtree rather than skipping individual nodes.
+ *
+ * To produce a view of the document that has entity references expanded
+ * and does not expose the entity reference node itself, use the whatToShow
+ * flags to hide the entity reference node and set expandEntityReferences to
+ * true when creating the iterator. To produce a view of the document that
+ * has entity reference nodes but no entity expansion, use the whatToShow
+ * flags to show the entity reference node and set expandEntityReferences to
+ * false.
+ */
+ bool expandEntityReferences();
+
+ /**
+ * Returns the next node in the set and advances the position of
+ * the Iterator in the set. After a NodeIterator is created, the
+ * first call to nextNode() returns the first node in the set.
+ *
+ * @return The next \c Node in the set being iterated
+ * over, or \c null if there are no more members in
+ * that set.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node nextNode();
+
+ /**
+ * Returns the previous node in the set and moves the position of
+ * the Iterator backwards in the set.
+ *
+ * @return The previous \c Node in the set being
+ * iterated over, or \c null if there are no more
+ * members in that set.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node previousNode();
+
+ /**
+ * Detaches the NodeIterator from the set which it iterated over,
+ * releasing any computational resources and placing the iterator in the
+ * INVALID state. After detach has been invoked, calls to nextNode or
+ * previousNode will raise the exception INVALID_STATE_ERR.
+ */
+ void detach();
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ NodeIteratorImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ NodeIteratorImpl *impl;
+ NodeIterator(NodeIteratorImpl *i);
+};
+
+
+/**
+ * Filters are objects that know how to "filter out" nodes. If an
+ * Iterator or \c TreeWalker is given a filter, before it
+ * returns the next node, it applies the filter. If the filter says to
+ * accept the node, the Iterator returns it; otherwise, the Iterator
+ * looks for the next node and pretends that the node that was
+ * rejected was not there.
+ *
+ * The DOM does not provide any filters. Filter is just an interface
+ * that users can implement to provide their own filters.
+ *
+ * Filters do not need to know how to iterate, nor do they need to
+ * know anything about the data structure that is being iterated. This
+ * makes it very easy to write filters, since the only thing they have
+ * to know how to do is evaluate a single node. One filter may be used
+ * with a number of different kinds of Iterators, encouraging code
+ * reuse.
+ *
+ * To create your own custom NodeFilter, define a subclass of
+ * CustomNodeFilter which overrides the acceptNode() method and assign
+ * an instance of it to the NodeFilter. For more details see the
+ * CustomNodeFilter class
+ */
+class KHTML_EXPORT NodeFilter
+{
+ friend class NodeIterator;
+ friend class NodeIteratorImpl;
+ friend class TreeWalker;
+ friend class TreeWalkerImpl;
+ friend class NodeFilterImpl;
+public:
+ NodeFilter();
+ NodeFilter(const NodeFilter &other);
+ NodeFilter(NodeFilterImpl *i);
+
+ virtual NodeFilter & operator = (const NodeFilter &other);
+
+ virtual ~NodeFilter();
+ /**
+ * The following constants are returned by the acceptNode()
+ * method:
+ *
+ */
+ enum AcceptCode {
+ FILTER_ACCEPT = 1,
+ FILTER_REJECT = 2,
+ FILTER_SKIP = 3
+ };
+
+ /**
+ * These are the available values for the whatToShow parameter.
+ * They are the same as the set of possible types for Node, and
+ * their values are derived by using a bit position corresponding
+ * to the value of NodeType for the equivalent node type.
+ *
+ */
+ enum ShowCode {
+ SHOW_ALL = 0xFFFFFFFF,
+ SHOW_ELEMENT = 0x00000001,
+ SHOW_ATTRIBUTE = 0x00000002,
+ SHOW_TEXT = 0x00000004,
+ SHOW_CDATA_SECTION = 0x00000008,
+ SHOW_ENTITY_REFERENCE = 0x00000010,
+ SHOW_ENTITY = 0x00000020,
+ SHOW_PROCESSING_INSTRUCTION = 0x00000040,
+ SHOW_COMMENT = 0x00000080,
+ SHOW_DOCUMENT = 0x00000100,
+ SHOW_DOCUMENT_TYPE = 0x00000200,
+ SHOW_DOCUMENT_FRAGMENT = 0x00000400,
+ SHOW_NOTATION = 0x00000800
+ };
+
+ /**
+ * Test whether a specified node is visible in the logical view of
+ * a TreeWalker or NodeIterator. This function will be called by
+ * the implementation of TreeWalker and NodeIterator; it is not
+ * intended to be called directly from user code.
+ *
+ * @param n The node to check to see if it passes the filter or
+ * not.
+ *
+ * @return a constant to determine whether the node is accepted,
+ * rejected, or skipped, as defined <a
+ * href="#Traversal-NodeFilter-acceptNode-constants"> above </a> .
+ *
+ */
+ virtual short acceptNode (const Node &n);
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ virtual NodeFilterImpl *handle() const;
+ virtual bool isNull() const;
+
+ void setCustomNodeFilter(CustomNodeFilter *custom);
+ CustomNodeFilter *customNodeFilter();
+ static NodeFilter createCustom(CustomNodeFilter *custom);
+
+protected:
+ NodeFilterImpl *impl;
+};
+
+/**
+ * CustomNodeFilter can be used to define your own NodeFilter for use
+ * with NodeIterators and TreeWalkers. You can create a custom filter
+ * by doing the following:
+ *
+ * class MyCustomNodeFilter {
+ * .....
+ * virtual short acceptNode (const Node &n);
+ * .....
+ * }
+ *
+ * Then in your program:
+ *
+ * short MyCustomNodeFilter::acceptNode (const Node &n)
+ * {
+ * if (condition)
+ * return NodeFilter::FILTER_ACCEPT;
+ * else
+ * ....
+ * }
+ *
+ *
+ * MyCustomFilter *filter = new MyCustomFilter();
+ * NodeFilter nf = NodeFilter::createCustom(filter);
+ * NodeIterator ni = document.createNodeIterator(document,NodeFilter.SHOW_ALL,nf,false);
+ *
+ * The default implementation of acceptNode() returns NodeFilter::FILTER_ACCEPT
+ * for all nodes.
+ *
+ */
+
+class KHTML_EXPORT CustomNodeFilter : public DomShared {
+public:
+ CustomNodeFilter();
+ virtual ~CustomNodeFilter();
+ virtual short acceptNode (const Node &n);
+ virtual bool isNull();
+
+ /**
+ * @internal
+ * not part of the DOM
+ *
+ * Returns a name specifying the type of custom node filter. Useful for checking
+ * if an custom node filter is of a particular sublass.
+ *
+ */
+ virtual DOMString customNodeFilterType();
+
+protected:
+ /**
+ * @internal
+ * Reserved. Do not use in your subclasses.
+ */
+ CustomNodeFilterImpl *impl;
+};
+
+/**
+ * \c TreeWalker objects are used to navigate a document
+ * tree or subtree using the view of the document defined by its
+ * \c whatToShow flags and any filters that are defined
+ * for the \c TreeWalker . Any function which performs
+ * navigation using a \c TreeWalker will automatically
+ * support any view defined by a \c TreeWalker .
+ *
+ * Omitting nodes from the logical view of a subtree can result in a
+ * structure that is substantially different from the same subtree in
+ * the complete, unfiltered document. Nodes that are siblings in the
+ * TreeWalker view may be children of different, widely separated
+ * nodes in the original view. For instance, consider a Filter that
+ * skips all nodes except for Text nodes and the root node of a
+ * document. In the logical view that results, all text nodes will be
+ * siblings and appear as direct children of the root node, no matter
+ * how deeply nested the structure of the original document.
+ *
+ */
+class KHTML_EXPORT TreeWalker
+{
+ friend class Document;
+ friend class TreeWalkerImpl;
+public:
+ TreeWalker();
+ TreeWalker(const TreeWalker &other);
+
+ TreeWalker & operator = (const TreeWalker &other);
+
+ ~TreeWalker();
+
+
+ /**
+ * The root node of the TreeWalker, as specified when it was created.
+ */
+ Node root();
+
+ /**
+ * This attribute determines which node types are presented via the
+ * TreeWalker. The available set of constants is defined in the NodeFilter
+ * interface. Nodes not accepted by whatToShow will be skipped, but their
+ * children may still be considered. Note that this skip takes precedence
+ * over the filter, if any.
+ */
+ unsigned long whatToShow();
+
+ /**
+ * The filter used to screen nodes.
+ */
+ NodeFilter filter();
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the TreeWalker. If false, they and their
+ * descendents will be rejected. Note that this rejection takes precedence
+ * over whatToShow and the filter, if any.
+ *
+ * To produce a view of the document that has entity references expanded
+ * and does not expose the entity reference node itself, use the whatToShow
+ * flags to hide the entity reference node and set expandEntityReferences
+ * to true when creating the TreeWalker. To produce a view of the document
+ * that has entity reference nodes but no entity expansion, use the
+ * whatToShow flags to show the entity reference node and set
+ * expandEntityReferences to false.
+ */
+ bool expandEntityReferences();
+
+ /**
+ * The node at which the TreeWalker is currently positioned.
+ * Alterations to the DOM tree may cause the current node to no longer be
+ * accepted by the TreeWalker's associated filter. currentNode may also be
+ * explicitly set to any node, whether or not it is within the subtree
+ * specified by the root node or would be accepted by the filter and
+ * whatToShow flags. Further traversal occurs relative to currentNode even
+ * if it is not part of the current view, by applying the filters in the
+ * requested direction; if no traversal is possible, currentNode is not changed.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if an attempt is made to set currentNode to null.
+ */
+ Node currentNode();
+
+ /**
+ * see currentNode
+ */
+ void setCurrentNode(const Node &_currentNode);
+
+ /**
+ * Moves to and returns the parent node of the current node. If
+ * there is no parent node, or if the current node is the root
+ * node from which this TreeWalker was created, retains the
+ * current position and returns null.
+ *
+ * @return The new parent node, or null if the current node has no
+ * parent in the TreeWalker's logical view.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node parentNode();
+
+ /**
+ * Moves the \c TreeWalker to the first child of the
+ * current node, and returns the new node. If the current node has
+ * no children, returns \c null , and retains the
+ * current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no children.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node firstChild();
+
+ /**
+ * Moves the \c TreeWalker to the last child of the
+ * current node, and returns the new node. If the current node has
+ * no children, returns \c null , and retains the
+ * current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no children.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node lastChild();
+
+ /**
+ * Moves the \c TreeWalker to the previous sibling of
+ * the current node, and returns the new node. If the current node
+ * has no previous sibling, returns \c null , and
+ * retains the current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no previous sibling.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node previousSibling();
+
+ /**
+ * Moves the \c TreeWalker to the next sibling of the
+ * current node, and returns the new node. If the current node has
+ * no next sibling, returns \c null , and retains the
+ * current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no next sibling.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node nextSibling();
+
+ /**
+ * Moves the \c TreeWalker to the previous node in
+ * document order relative to the current node, and returns the
+ * new node. If the current node has no previous node, returns
+ * \c null , and retains the current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no previous node.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node previousNode();
+
+ /**
+ * Moves the \c TreeWalker to the next node in
+ * document order relative to the current node, and returns the
+ * new node. If the current node has no next node, returns
+ * \c null , and retains the current node.
+ *
+ * @return The new node, or \c null if the current
+ * node has no next node.
+ *
+ * @exception Exceptions from user code
+ * Any exceptions raised by a user-written Filter will propagate
+ * through.
+ *
+ */
+ Node nextNode();
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ TreeWalkerImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ TreeWalker(TreeWalkerImpl *i);
+ TreeWalkerImpl *impl;
+};
+
+
+// ### not sure if this this class is really needed - both methods are in
+// Document
+
+/**
+ * \c DocumentTraversal contains methods that creates
+ * Iterators to traverse a node and its children in document order
+ * (depth first, pre-order traversal, which is equivalent to the order
+ * in which the start tags occur in the text representation of the
+ * document).
+ *
+ *
+class DocumentTraversal // : public Document ?
+{
+public:
+ DocumentTraversal();
+ DocumentTraversal(const DocumentTraversal &other);
+
+ DocumentTraversal & operator = (const DocumentTraversal &other);
+
+ ~DocumentTraversal();
+
+ **
+ *
+ *
+ * @param root The node which will be iterated together with its
+ * children. The iterator is initially positioned just before this
+ * node. The whatToShow flags and the filter, if any, are not
+ * considered when setting this position.
+ *
+ * @param whatToShow This flag specifies which node types may
+ * appear in the logical view of the tree presented by the
+ * Iterator. See the description of Iterator for the set of
+ * possible values. These flags can be combined using OR.
+ *
+ * These flags can be combined using \c OR .
+ *
+ * @param filter The Filter to be used with this TreeWalker, or
+ * null to indicate no filter.
+ *
+ * @param entityReferenceExpansion The value of this flag
+ * determines whether entity reference nodes are expanded.
+ *
+ * @return The newly created \c NodeIterator .
+ *
+ *
+ NodeIterator createNodeIterator ( const Node &root, long whatToShow,
+ const NodeFilter &filter, bool entityReferenceExpansion );
+
+ **
+ * Create a new TreeWalker over the subtree rooted by the
+ * specified node.
+ *
+ * @param root The node which will serve as the root for the
+ * \c TreeWalker . The currentNode of the TreeWalker
+ * is set to this node. The whatToShow flags and the NodeFilter
+ * are not considered when setting this value; any node type will
+ * be accepted as the root. The root must not be null.
+ *
+ * @param whatToShow This flag specifies which node types may
+ * appear in the logical view of the tree presented by the
+ * Iterator. See the description of TreeWalker for the set of
+ * possible values. These flags can be combined using OR.
+ *
+ * These flags can be combined using \c OR .
+ *
+ * @param filter The Filter to be used with this TreeWalker, or
+ * null to indicate no filter.
+ *
+ * @param entityReferenceExpansion The value of this flag
+ * determines whether entity reference nodes are expanded.
+ *
+ * @return The newly created \c TreeWalker .
+ *
+ * @exception DOMException
+ * Raises the exception NOT_SUPPORTED_ERR if the specified root
+ * node is null.
+ *
+ *
+ TreeWalker createTreeWalker ( const Node &root, long whatToShow,
+ const NodeFilter &filter, bool entityReferenceExpansion );
+};
+*/
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/dom2_views.cpp b/tdehtml/dom/dom2_views.cpp
new file mode 100644
index 000000000..11b07fbb0
--- /dev/null
+++ b/tdehtml/dom/dom2_views.cpp
@@ -0,0 +1,95 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#include "dom/dom2_views.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_doc.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom2_viewsimpl.h"
+
+using namespace DOM;
+
+
+AbstractView::AbstractView()
+{
+ impl = 0;
+}
+
+
+AbstractView::AbstractView(const AbstractView &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+
+AbstractView::AbstractView(AbstractViewImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+AbstractView::~AbstractView()
+{
+ if (impl)
+ impl->deref();
+}
+
+AbstractView &AbstractView::operator = (const AbstractView &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+Document AbstractView::document() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->document();
+}
+
+CSSStyleDeclaration AbstractView::getComputedStyle(const Element &elt, const DOMString &pseudoElt)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return impl->getComputedStyle(static_cast<ElementImpl*>(elt.handle()),pseudoElt.implementation());
+}
+
+
+AbstractViewImpl *AbstractView::handle() const
+{
+ return impl;
+}
+
+bool AbstractView::isNull() const
+{
+ return (impl == 0);
+}
+
+
+
diff --git a/tdehtml/dom/dom2_views.h b/tdehtml/dom/dom2_views.h
new file mode 100644
index 000000000..6f326aaa3
--- /dev/null
+++ b/tdehtml/dom/dom2_views.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _DOM_Views_h_
+#define _DOM_Views_h_
+
+#include <tdelibs_export.h>
+namespace DOM {
+
+class Document;
+class AbstractViewImpl;
+class CSSStyleDeclaration;
+class Element;
+class DOMString;
+
+/**
+ * Introduced in DOM Level 2
+ *
+ * A base interface that all views shall derive from.
+ *
+ */
+class KHTML_EXPORT AbstractView {
+ friend class Event;
+ friend class UIEvent;
+ friend class MouseEvent;
+ friend class MutationEvent;
+ friend class Document;
+public:
+ AbstractView();
+ AbstractView(const AbstractView &other);
+ virtual ~AbstractView();
+
+ AbstractView & operator = (const AbstractView &other);
+
+ /**
+ * The source DocumentView of which this is an AbstractView.
+ */
+ Document document() const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the ViewCSS interface
+ *
+ * This method is used to get the computed style as it is defined in
+ * [CSS2].
+ *
+ * @param elt The element whose style is to be computed. This parameter
+ * cannot be null.
+ *
+ * @param pseudoElt The pseudo-element or null if none.
+ *
+ * @return The computed style. The CSSStyleDeclaration is read-only and
+ * contains only absolute values.
+ */
+ CSSStyleDeclaration getComputedStyle(const Element &elt, const DOMString &pseudoElt);
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ AbstractViewImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ AbstractView(AbstractViewImpl *i);
+ AbstractViewImpl *impl;
+};
+
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_core.h b/tdehtml/dom/dom_core.h
new file mode 100644
index 000000000..c3c8f2893
--- /dev/null
+++ b/tdehtml/dom/dom_core.h
@@ -0,0 +1,34 @@
+/*
+ * 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_CORE_H_
+#define _DOM_CORE_H_
+
+#include <dom/dom_doc.h>
+#include <dom/dom_element.h>
+#include <dom/dom_misc.h>
+#include <dom/dom_exception.h>
+#include <dom/dom_node.h>
+#include <dom/dom_string.h>
+#include <dom/dom_text.h>
+#include <dom/dom_xml.h>
+
+#endif
diff --git a/tdehtml/dom/dom_doc.cpp b/tdehtml/dom/dom_doc.cpp
new file mode 100644
index 000000000..0ff123444
--- /dev/null
+++ b/tdehtml/dom/dom_doc.cpp
@@ -0,0 +1,684 @@
+/*
+ * 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 "dom/dom_exception.h"
+#include "dom/dom_xml.h"
+#include "dom/dom2_range.h"
+#include "dom/dom2_events.h"
+#include "dom/dom2_views.h"
+#include "dom/dom2_traversal.h"
+#include "dom/html_document.h"
+#include "html/html_documentimpl.h"
+
+#include "xml/dom_docimpl.h"
+#include "xml/dom_elementimpl.h"
+
+#include <kdebug.h>
+
+namespace DOM {
+
+DOMImplementation::DOMImplementation()
+{
+ impl = 0;
+}
+
+DOMImplementation::DOMImplementation(const DOMImplementation &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+DOMImplementation::DOMImplementation(DOMImplementationImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+DOMImplementation &DOMImplementation::operator = (const DOMImplementation &other)
+{
+ if ( impl != other.impl ) {
+ if (impl) impl->deref();
+ impl = other.impl;
+ if (impl) impl->ref();
+ }
+ return *this;
+}
+
+DOMImplementation::~DOMImplementation()
+{
+ if (impl) impl->deref();
+}
+
+bool DOMImplementation::hasFeature( const DOMString &feature, const DOMString &version )
+{
+ if (!impl)
+ return false; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return impl->hasFeature(feature,version);
+}
+
+DocumentType DOMImplementation::createDocumentType ( const DOMString &qualifiedName,
+ const DOMString &publicId,
+ const DOMString &systemId )
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ DocumentTypeImpl *r = impl->createDocumentType(qualifiedName, publicId, systemId, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return r;
+}
+
+Document DOMImplementation::createDocument ( const DOMString &namespaceURI,
+ const DOMString &qualifiedName,
+ const DocumentType &doctype )
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ DocumentImpl *r = impl->createDocument(namespaceURI, qualifiedName, doctype, exceptioncode );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return r;
+}
+
+HTMLDocument DOMImplementation::createHTMLDocument( const DOMString& title )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ HTMLDocumentImpl* r = impl->createHTMLDocument( 0 /* ### create a view otherwise it doesn't work */);
+
+ r->open();
+
+ r->write(TQString::fromLatin1("<HTML><HEAD><TITLE>") + title.string() +
+ TQString::fromLatin1("</TITLE></HEAD>"));
+
+ return r;
+}
+
+DOMImplementation DOMImplementation::getInterface(const DOMString &feature) const
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return impl->getInterface(feature);
+}
+
+CSSStyleSheet DOMImplementation::createCSSStyleSheet(const DOMString &title, const DOMString &media)
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ CSSStyleSheetImpl *r = impl->createCSSStyleSheet(title.implementation(), media.implementation(),
+ exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return r;
+}
+
+DOMImplementationImpl *DOMImplementation::handle() const
+{
+ return impl;
+}
+
+bool DOMImplementation::isNull() const
+{
+ return (impl == 0);
+}
+
+// ----------------------------------------------------------------------------
+
+Document::Document()
+ : Node()
+{
+ // we always want an implementation
+ impl = DOMImplementationImpl::instance()->createDocument();
+ impl->ref();
+}
+
+Document::Document(bool create)
+ : Node()
+{
+ if(create)
+ {
+ impl = DOMImplementationImpl::instance()->createDocument();
+ impl->ref();
+ }
+ else
+ impl = 0;
+// kdDebug(6090) << "Document::Document(bool)" << endl;
+}
+
+Document::Document(const Document &other) : Node(other)
+{
+// kdDebug(6090) << "Document::Document(Document &)" << endl;
+}
+
+Document::Document(DocumentImpl *i) : Node(i)
+{
+// kdDebug(6090) << "Document::Document(DocumentImpl)" << endl;
+}
+
+Document &Document::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != DOCUMENT_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Document &Document::operator = (const Document &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Document::~Document()
+{
+// kdDebug(6090) << "Document::~Document\n" << endl;
+}
+
+DocumentType Document::doctype() const
+{
+ if (impl) return ((DocumentImpl *)impl)->doctype();
+ return 0;
+}
+
+DOMImplementation Document::implementation() const
+{
+ if (impl) return ((DocumentImpl *)impl)->implementation();
+ return 0;
+}
+
+Element Document::documentElement() const
+{
+ if (impl) return ((DocumentImpl *)impl)->documentElement();
+ return 0;
+}
+
+Element Document::createElement( const DOMString &tagName )
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ElementImpl* r = ((DocumentImpl *)impl)->createElement(tagName, &exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return r;
+}
+
+Element Document::createElementNS( const DOMString &namespaceURI, const DOMString &qualifiedName )
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ElementImpl* r = ((DocumentImpl *)impl)->createElementNS(namespaceURI,qualifiedName, &exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return r;
+}
+
+DocumentFragment Document::createDocumentFragment( )
+{
+ if (impl) return ((DocumentImpl *)impl)->createDocumentFragment();
+ return 0;
+}
+
+Text Document::createTextNode( const DOMString &data )
+{
+ if (impl) return ((DocumentImpl *)impl)->createTextNode( data.implementation() );
+ return 0;
+}
+
+Comment Document::createComment( const DOMString &data )
+{
+ if (impl) return ((DocumentImpl *)impl)->createComment( data.implementation() );
+ return 0;
+}
+
+CDATASection Document::createCDATASection( const DOMString &data )
+{
+ // ### DOM1 spec says raise exception if html documents - what about XHTML documents?
+ if (impl) return ((DocumentImpl *)impl)->createCDATASection( data.implementation() );
+ return 0;
+}
+
+ProcessingInstruction Document::createProcessingInstruction( const DOMString &target, const DOMString &data )
+{
+ if (impl) return ((DocumentImpl *)impl)->createProcessingInstruction( target, data.implementation() );
+ return 0;
+}
+
+Attr Document::createAttribute( const DOMString &name )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (name.isNull()) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ AttrImpl* a = impl->getDocument()->createAttribute(name, &exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return a;
+}
+
+Attr Document::createAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (qualifiedName.isNull()) throw DOMException(DOMException::NAMESPACE_ERR);
+ int exceptioncode = 0;
+ AttrImpl* a = impl->getDocument()->createAttributeNS(namespaceURI, qualifiedName, &exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return a;
+}
+
+EntityReference Document::createEntityReference( const DOMString &name )
+{
+ if (impl) return ((DocumentImpl *)impl)->createEntityReference( name );
+ return 0;
+}
+
+Element Document::getElementById( const DOMString &elementId ) const
+{
+ if(impl) return ((DocumentImpl *)impl)->getElementById( elementId );
+ return 0;
+}
+
+NodeList Document::getElementsByTagName( const DOMString &tagName )
+{
+ if (!impl) return 0;
+ NodeImpl::Id id;
+ if ( tagName == "*" )
+ id = 0;
+ else
+ id = impl->getDocument()->getId(NodeImpl::ElementId, tagName.implementation(), false, true);
+ return new TagNodeListImpl( impl, id );
+}
+
+NodeList Document::getElementsByTagNameNS( const DOMString &namespaceURI, const DOMString &localName )
+{
+ if (!impl) return 0;
+ return new TagNodeListImpl( impl, namespaceURI, localName );
+}
+
+Node Document::importNode( const Node & importedNode, bool deep )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeImpl *r = static_cast<DocumentImpl*>(impl)->importNode(importedNode.handle(), deep, exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+bool Document::isHTMLDocument() const
+{
+ if (impl) return ((DocumentImpl *)impl)->isHTMLDocument();
+ return 0;
+}
+
+Range Document::createRange()
+{
+ if (impl) return ((DocumentImpl *)impl)->createRange();
+ return 0;
+}
+
+NodeIterator Document::createNodeIterator(Node root, unsigned long whatToShow,
+ NodeFilter filter, bool entityReferenceExpansion)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ NodeIteratorImpl *r = static_cast<DocumentImpl*>(impl)->createNodeIterator(root.handle(),
+ whatToShow,filter,entityReferenceExpansion,exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+TreeWalker Document::createTreeWalker(Node root, unsigned long whatToShow, NodeFilter filter,
+ bool entityReferenceExpansion)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+
+ TreeWalkerImpl *tw = static_cast<DocumentImpl *>(impl)->createTreeWalker(
+ root.handle(), whatToShow, filter.handle(), entityReferenceExpansion, exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+
+ return tw;
+}
+
+Event Document::createEvent(const DOMString &eventType)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ EventImpl *r = ((DocumentImpl *)impl)->createEvent(eventType,exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+AbstractView Document::defaultView() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>(impl)->defaultView();
+}
+
+StyleSheetList Document::styleSheets() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>(impl)->styleSheets();
+}
+
+DOMString Document::preferredStylesheetSet()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>(impl)->preferredStylesheetSet();
+}
+
+DOMString Document::selectedStylesheetSet()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>(impl)->selectedStylesheetSet();
+}
+
+void Document::setSelectedStylesheetSet(const DOMString& s)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<DocumentImpl*>(impl)->setSelectedStylesheetSet(s);
+}
+
+
+KHTMLView *Document::view() const
+{
+ if (!impl) return 0;
+
+ return static_cast<DocumentImpl*>(impl)->view();
+}
+
+CSSStyleDeclaration Document::getOverrideStyle(const Element &elt, const DOMString &pseudoElt)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode = 0;
+ CSSStyleDeclarationImpl *r = ((DocumentImpl *)impl)->getOverrideStyle(static_cast<ElementImpl*>(elt.handle()),pseudoElt.implementation());
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+bool Document::async() const
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>( impl )->async( );
+}
+
+void Document::setAsync( bool b )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<DocumentImpl*>( impl )->setAsync( b );
+}
+
+void Document::abort()
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+
+ static_cast<DocumentImpl*>( impl )->abort( );
+}
+
+void Document::load( const DOMString &uri )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<DocumentImpl*>( impl )->load( uri );
+}
+
+void Document::loadXML( const DOMString &source )
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+
+ static_cast<DocumentImpl*>( impl )->loadXML( source );
+}
+
+bool Document::designMode() const {
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ return static_cast<DocumentImpl*>( impl )->designMode();
+}
+
+void Document::setDesignMode(bool enable) {
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<DocumentImpl*>( impl )->setDesignMode( enable );
+}
+
+DOMString Document::completeURL(const DOMString& url)
+{
+ if ( !impl ) return url;
+ return static_cast<DocumentImpl*>( impl )->completeURL( url.string() );
+}
+
+DOMString Document::toString() const
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentImpl*>(impl)->toString();
+}
+
+void Document::updateRendering()
+{
+ if ( !impl ) return;
+ static_cast<DocumentImpl*>( impl )->updateRendering( );
+}
+
+void Document::addStyleSheet(const StyleSheet &sheet)
+{
+ if (!impl || sheet.isNull())
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode;
+ static_cast<DocumentImpl*>( impl )->addStyleSheet( sheet.handle(), &exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+void Document::removeStyleSheet(const StyleSheet &sheet)
+{
+ if (!impl || sheet.isNull())
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ int exceptioncode;
+ static_cast<DocumentImpl*>( impl )->removeStyleSheet( sheet.handle(), &exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+// ----------------------------------------------------------------------------
+
+DocumentFragment::DocumentFragment() : Node()
+{
+}
+
+DocumentFragment::DocumentFragment(const DocumentFragment &other) : Node(other)
+{
+}
+
+DocumentFragment &DocumentFragment::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != DOCUMENT_FRAGMENT_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+DocumentFragment &DocumentFragment::operator = (const DocumentFragment &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+DocumentFragment::~DocumentFragment()
+{
+}
+
+DocumentFragment::DocumentFragment(DocumentFragmentImpl *i) : Node(i)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+DocumentType::DocumentType()
+ : Node()
+{
+}
+
+DocumentType::DocumentType(const DocumentType &other)
+ : Node(other)
+{
+}
+
+DocumentType::DocumentType(DocumentTypeImpl *impl) : Node(impl)
+{
+}
+
+DocumentType &DocumentType::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != DOCUMENT_TYPE_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+DocumentType &DocumentType::operator = (const DocumentType &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+DocumentType::~DocumentType()
+{
+}
+
+DOMString DocumentType::name() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->name();
+}
+
+NamedNodeMap DocumentType::entities() const
+{
+ if (!impl)
+ return 0; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->entities();
+}
+
+NamedNodeMap DocumentType::notations() const
+{
+ if (!impl)
+ return 0; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->notations();
+}
+
+DOMString DocumentType::publicId() const
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->publicId();
+}
+
+DOMString DocumentType::systemId() const
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->systemId();
+}
+
+DOMString DocumentType::internalSubset() const
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return static_cast<DocumentTypeImpl*>(impl)->internalSubset();
+}
+
+} // namespace
diff --git a/tdehtml/dom/dom_doc.h b/tdehtml/dom/dom_doc.h
new file mode 100644
index 000000000..9a5331295
--- /dev/null
+++ b/tdehtml/dom/dom_doc.h
@@ -0,0 +1,1107 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ */
+
+#ifndef _DOM_Document_h_
+#define _DOM_Document_h_
+
+#include <dom/dom_node.h>
+#include <dom/css_stylesheet.h>
+
+class KHTMLView;
+class KHTMLPart;
+
+namespace DOM {
+
+class DOMString;
+class DocumentType;
+class NodeList;
+class CDATASection;
+class Comment;
+class DocumentFragment;
+class Text;
+class DOMImplementation;
+class Element;
+class Attr;
+class EntityReference;
+class ProcessingInstruction;
+class DocumentImpl;
+class Range;
+class NodeIterator;
+class TreeWalker;
+class NodeFilter;
+class DOMImplementationImpl;
+class DocumentTypeImpl;
+class Event;
+class AbstractView;
+class CSSStyleDeclaration;
+class HTMLElementImpl;
+class HTMLFrameElement;
+class HTMLElementImpl;
+class HTMLIFrameElement;
+class HTMLObjectElement;
+class HTMLDocument;
+
+/**
+ * The \c DOMImplementation interface provides a number of
+ * methods for performing operations that are independent of any
+ * particular instance of the document object model.
+ *
+ * DOM Level 2 and newer provide means for creating documents directly,
+ * which was not possible with DOM Level 1.
+ */
+class KHTML_EXPORT DOMImplementation
+{
+ friend class Document;
+public:
+ DOMImplementation();
+ DOMImplementation(const DOMImplementation &other);
+
+ DOMImplementation & operator = (const DOMImplementation &other);
+ ~DOMImplementation();
+
+ /**
+ * Test if the DOM implementation implements a specific feature.
+ *
+ * @param feature The package name of the feature to test. In
+ * Level 1, the legal values are "HTML" and "XML"
+ * (case-insensitive).
+ *
+ * @param version This is the version number of the package name
+ * to test. In Level 1, this is the string "1.0". If the version
+ * is not specified, supporting any version of the feature will
+ * cause the method to return \c true .
+ *
+ * @return \c true if the feature is implemented in
+ * the specified version, \c false otherwise.
+ *
+ */
+ bool hasFeature ( const DOMString &feature, const DOMString &version );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Creates an empty DocumentType node. Entity declarations and notations
+ * are not made available. Entity reference expansions and default
+ * attribute additions do not occur. It is expected that a future version
+ * of the DOM will provide a way for populating a DocumentType.
+ *
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param qualifiedName The qualified name of the document type to be
+ * created.
+ *
+ * @param publicId The external subset public identifier.
+ *
+ * @param systemId The external subset system identifier.
+ *
+ * @return A new DocumentType node with Node.ownerDocument set to null.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified qualified name contains
+ * an illegal character.
+ *
+ * NAMESPACE_ERR: Raised if the qualifiedName is malformed.
+ */
+ DocumentType createDocumentType ( const DOMString &qualifiedName,
+ const DOMString &publicId,
+ const DOMString &systemId );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Creates an XML Document object of the specified type with its document
+ * element. HTML-only DOM implementations do not need to implement this
+ * method.
+ *
+ * @param namespaceURI The namespace URI of the document element to create.
+ *
+ * @param qualifiedName The qualified name of the document element to be
+ * created.
+ *
+ * @param doctype The type of document to be created or null. When doctype
+ * is not null, its Node.ownerDocument attribute is set to the document
+ * being created.
+ *
+ * @return A new Document object.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified qualified name contains
+ * an illegal character.
+ *
+ * NAMESPACE_ERR: Raised if the qualifiedName is malformed, if the
+ * qualifiedName has a prefix and the namespaceURI is null, or if the
+ * qualifiedName has a prefix that is "xml" and the namespaceURI is
+ * different from "http://www.w3.org/XML/1998/namespace" [Namespaces].
+ *
+ * WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a
+ * different document or was created from a different implementation.
+ */
+ Document createDocument ( const DOMString &namespaceURI,
+ const DOMString &qualifiedName,
+ const DocumentType &doctype );
+
+ /**
+ * Introduced in DOM Level 3
+ * This method makes available a DOMImplementation's specialized
+ * interface.
+ *
+ * @param feature The name of the feature requested (case-insensitive)
+ *
+ * @return Returns an alternate DOMImplementation which implements
+ * the specialized APIs of the specified feature, if any, or null
+ * if there is no alternate DOMImplementation object which implements
+ * interfaces associated with that feature. Any alternate DOMImplementation
+ * returned by this method must delegate to the primary core DOMImplementation
+ * and not return results inconsistent with the primary DOMImplementation.
+ */
+ DOMImplementation getInterface(const DOMString &feature) const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DOMImplementationCSS interface
+ *
+ * Creates a new CSSStyleSheet.
+ *
+ * @param title The advisory title. See also the Style Sheet Interfaces
+ * section.
+ *
+ * @param media The comma-separated list of media associated with the
+ * new style sheet. See also the Style Sheet Interfaces section.
+ *
+ * @return A new CSS style sheet.
+ *
+ * @exception SYNTAX_ERR: Raised if the specified media string value has a syntax error and is unparsable.
+ */
+ CSSStyleSheet createCSSStyleSheet(const DOMString &title, const DOMString &media);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the HTMLDOMImplementation interface
+ *
+ * Creates an HTMLDocument with the minimal tree made of these
+ * elements: HTML,HEAD,TITLE and BODY.
+ * It extends the core interface which can be used to create an
+ * XHTML document by passing the XHTML namespace as the namespace
+ * for the root element.
+ *
+ * @param title The title of the document to be set as the content
+ * of the TITLE element, through a child Text node.
+ *
+ * @return the HTMLdocument
+ */
+ HTMLDocument createHTMLDocument(const DOMString& title);
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ DOMImplementationImpl *handle() const;
+ bool isNull() const;
+
+protected:
+ DOMImplementation(DOMImplementationImpl *i);
+ DOMImplementationImpl *impl;
+};
+
+/**
+ * The \c Document interface represents the entire HTML or
+ * XML document. Conceptually, it is the root of the document tree,
+ * and provides the primary access to the document's data.
+ *
+ * Since elements, text nodes, comments, processing instructions,
+ * etc. cannot exist outside the context of a \c Document
+ * , the \c Document interface also contains the factory
+ * methods needed to create these objects. The \c Node
+ * objects created have a \c ownerDocument attribute which
+ * associates them with the \c Document within whose
+ * context they were created.
+ *
+ */
+class KHTML_EXPORT Document : public Node
+{
+ friend class ::KHTMLView;
+ friend class ::KHTMLPart;
+ friend class AbstractView;
+ friend class DOMImplementation;
+ friend class HTMLFrameElement;
+ friend class HTMLIFrameElement;
+ friend class HTMLObjectElement;
+
+public:
+ Document();
+ /**
+ * don't create an implementation if false
+ * use at own risk
+ */
+ Document(bool);
+ Document(const Document &other);
+ Document(const Node &other) : Node()
+ {(*this)=other;}
+
+ Document & operator = (const Node &other);
+ Document & operator = (const Document &other);
+
+ ~Document();
+
+ /**
+ * The Document Type Declaration (see \c DocumentType
+ * ) associated with this document. For HTML documents as well as
+ * XML documents without a document type declaration this returns
+ * \c null . The DOM Level 1 does not support editing
+ * the Document Type Declaration, therefore \c docType
+ * cannot be altered in any way.
+ *
+ */
+ DocumentType doctype() const;
+
+ /**
+ * The \c DOMImplementation object that handles this
+ * document. A DOM application may use objects from multiple
+ * implementations.
+ *
+ */
+ DOMImplementation implementation() const;
+
+ /**
+ * This is a convenience attribute that allows direct access to
+ * the child node that is the root element of the document. For
+ * HTML documents, this is the element with the tagName "HTML".
+ *
+ */
+ Element documentElement() const;
+
+ /**
+ * Creates an element of the type specified. Note that the
+ * instance returned implements the Element interface, so
+ * attributes can be specified directly on the returned object.
+ *
+ * @param tagName The name of the element type to instantiate. For
+ * XML, this is case-sensitive. For HTML, the \c tagName
+ * parameter may be provided in any case, but it must be
+ * mapped to the canonical uppercase form by the DOM
+ * implementation.
+ *
+ * @return A new \c Element object.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ *
+ */
+ Element createElement ( const DOMString &tagName );
+
+ /**
+ * Introduced in DOM Level 2
+ * Creates an element of the given qualified name and namespace URI.
+ *
+ * @param namespaceURI The namespace URI of the element to create.
+ *
+ * @param qualifiedName The qualified name of the element type to instantiate.
+ *
+ * @return A new Element object with the following attributes:
+ *
+ * @exception INVALID_CHARACTER_ERR Raised if the specified qualified name
+ * contains an illegal character.
+ *
+ * @exception NAMESPACE_ERR Raised if the qualifiedName is malformed, if
+ * the qualifiedName has a prefix and the namespaceURI is null, or if the
+ * qualifiedName has a prefix that is "xml" and the namespaceURI is
+ * different from "http://www.w3.org/XML/1998/namespace"
+ */
+ Element createElementNS( const DOMString &namespaceURI,
+ const DOMString &qualifiedName );
+
+ /**
+ * Creates an empty \c DocumentFragment object.
+ *
+ * @return A new \c DocumentFragment .
+ *
+ */
+ DocumentFragment createDocumentFragment ( );
+
+ /**
+ * Creates a \c Text node given the specified string.
+ *
+ * @param data The data for the node.
+ *
+ * @return The new \c Text object.
+ *
+ */
+ Text createTextNode ( const DOMString &data );
+
+ /**
+ * Creates a \c Comment node given the specified
+ * string.
+ *
+ * @param data The data for the node.
+ *
+ * @return The new \c Comment object.
+ *
+ */
+ Comment createComment ( const DOMString &data );
+
+ /**
+ * Creates a \c CDATASection node whose value is the
+ * specified string.
+ *
+ * @param data The data for the \c CDATASection
+ * contents.
+ *
+ * @return The new \c CDATASection object.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if this document is an HTML document.
+ *
+ */
+ CDATASection createCDATASection ( const DOMString &data );
+
+ /**
+ * Creates a \c ProcessingInstruction node given the
+ * specified name and data strings.
+ *
+ * @param target The target part of the processing instruction.
+ *
+ * @param data The data for the node.
+ *
+ * @return The new \c ProcessingInstruction object.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if an invalid character is
+ * specified.
+ *
+ * NOT_SUPPORTED_ERR: Raised if this document is an HTML
+ * document.
+ *
+ */
+ ProcessingInstruction createProcessingInstruction ( const DOMString &target,
+ const DOMString &data );
+
+ /**
+ * Creates an \c Attr of the given name. Note that the
+ * \c Attr instance can then be set on an \c Element
+ * using the \c setAttribute method.
+ *
+ * @param name The name of the attribute.
+ *
+ * @return A new \c Attr object.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ *
+ */
+ Attr createAttribute ( const DOMString &name );
+
+ /**
+ * Introduced in DOM Level 2
+ * Creates an attribute of the given qualified name and namespace URI.
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to create.
+ *
+ * @param qualifiedName The qualified name of the attribute to instantiate.
+ *
+ * @return A new Attr object with the following attributes:
+ * Node.nodeName - qualifiedName
+ * Node.namespaceURI - namespaceURI
+ * Node.prefix - prefix, extracted from qualifiedName, or null if there is
+ * no prefix
+ * Node.localName - local name, extracted from qualifiedName
+ * Attr.name - qualifiedName
+ * Node.nodeValue - the empty string
+ *
+ * @exception INVALID_CHARACTER_ERR Raised if the specified qualified name
+ * contains an illegal character.
+ *
+ * @exception NAMESPACE_ERR Raised if the qualifiedName is malformed, if
+ * the qualifiedName has a prefix and the namespaceURI is null, if the
+ * qualifiedName has a prefix that is "xml" and the namespaceURI is
+ * different from "http://www.w3.org/XML/1998/namespace", or if the
+ * qualifiedName is "xmlns" and the namespaceURI is different from
+ * "http://www.w3.org/2000/xmlns/".
+ */
+ Attr createAttributeNS( const DOMString &namespaceURI,
+ const DOMString &qualifiedName );
+
+ /**
+ * Creates an EntityReference object.
+ *
+ * @param name The name of the entity to reference.
+ *
+ * @return The new \c EntityReference object.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ *
+ * NOT_SUPPORTED_ERR: Raised if this document is an HTML
+ * document.
+ *
+ */
+ EntityReference createEntityReference ( const DOMString &name );
+
+ /**
+ * Moved from HTMLDocument in DOM Level 2
+ * Returns the Element whose \c id is given by
+ * elementId. If no such element exists, returns \c null
+ * . Behavior is not defined if more than one element has
+ * this \c id .
+ *
+ * @param elementId The unique \c id value for an
+ * element.
+ *
+ * @return The matching element.
+ *
+ */
+ Element getElementById ( const DOMString &elementId ) const;
+
+ /**
+ * No Exceptions.
+ *
+ * Returns a \c NodeList of all the \c Element 's
+ * with a given tag name in the order in which they
+ * would be encountered in a preorder traversal of the
+ * \c Document tree.
+ *
+ * @param tagname The name of the tag to match on. The special
+ * value "*" matches all tags.
+ *
+ * @return A new \c NodeList object containing all the
+ * matched \c Element s.
+ *
+ */
+ NodeList getElementsByTagName ( const DOMString &tagname );
+
+ /**
+ * Introduced in DOM Level 2
+ * No Exceptions
+ *
+ * Returns a NodeList of all the Elements with a given local name and
+ * namespace URI in the order in which they are encountered in a preorder
+ * traversal of the Document tree.
+ *
+ * @param namespaceURI The namespace URI of the elements to match on. The
+ * special value "*" matches all namespaces.
+ *
+ * @param localName The local name of the elements to match on. The special
+ * value "*" matches all local names.
+ *
+ * @return A new NodeList object containing all the matched Elements.
+ */
+ NodeList getElementsByTagNameNS( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Imports a node from another document to this document. The returned node
+ * has no parent; (parentNode is null). The source node is not altered or
+ * removed from the original document; this method creates a new copy of
+ * the source node.
+ *
+ * For all nodes, importing a node creates a node object owned by the
+ * importing document, with attribute values identical to the source node's
+ * nodeName and nodeType, plus the attributes related to namespaces
+ * (prefix, localName, and namespaceURI).
+ *
+ * As in the cloneNode operation on a Node, the source node is not altered.
+ * Additional information is copied as appropriate to the nodeType,
+ * attempting to mirror the behavior expected if a fragment of XML or HTML
+ * source was copied from one document to another, recognizing that the two
+ * documents may have different DTDs in the XML case. The following list
+ * describes the specifics for each type of node.
+ *
+ * ATTRIBUTE_NODE
+ * The ownerElement attribute is set to null and the specified flag is set
+ * to true on the generated Attr. The descendants of the source Attr are
+ * recursively imported and the resulting nodes reassembled to form the
+ * corresponding subtree. Note that the deep parameter has no effect on
+ * Attr nodes; they always carry their children with them when imported.
+ *
+ * DOCUMENT_FRAGMENT_NODE
+ * If the deep option was set to true, the descendants of the source
+ * element are recursively imported and the resulting nodes reassembled to
+ * form the corresponding subtree. Otherwise, this simply generates an
+ * empty DocumentFragment.
+ *
+ * DOCUMENT_NODE
+ * Document nodes cannot be imported.
+ *
+ * DOCUMENT_TYPE_NODE
+ * DocumentType nodes cannot be imported.
+ *
+ * ELEMENT_NODE
+ * Specified attribute nodes of the source element are imported, and the
+ * generated Attr nodes are attached to the generated Element. Default
+ * attributes are not copied, though if the document being imported into
+ * defines default attributes for this element name, those are assigned. If
+ * the importNode deep parameter was set to true, the descendants of the
+ * source element are recursively imported and the resulting nodes
+ * reassembled to form the corresponding subtree.
+ *
+ * ENTITY_NODE
+ * Entity nodes can be imported, however in the current release of the DOM
+ * the DocumentType is readonly. Ability to add these imported nodes to a
+ * DocumentType will be considered for addition to a future release of the
+ * DOM.
+ * On import, the publicId, systemId, and notationName attributes are
+ * copied. If a deep import is requested, the descendants of the the source
+ * Entity are recursively imported and the resulting nodes reassembled to
+ * form the corresponding subtree.
+ *
+ * ENTITY_REFERENCE_NODE Only the EntityReference itself is copied, even if
+ * a deep import is requested, since the source and destination documents
+ * might have defined the entity differently. If the document being
+ * imported into provides a definition for this entity name, its value is
+ * assigned.
+ *
+ * NOTATION_NODE
+ * Notation nodes can be imported, however in the current release of the
+ * DOM the DocumentType is readonly. Ability to add these imported nodes to
+ * a DocumentType will be considered for addition to a future release of
+ * the DOM.
+ * On import, the publicId and systemId attributes are copied.
+ * Note that the deep parameter has no effect on Notation nodes since they
+ * never have any children.
+ *
+ * PROCESSING_INSTRUCTION_NODE
+ * The imported node copies its target and data values from those of the
+ * source node.
+ *
+ * TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE
+ * These three types of nodes inheriting from CharacterData copy their data
+ * and length attributes from those of the source node.
+ *
+ * @param importedNode The node to import.
+ *
+ * @param deep If true, recursively import the subtree under the specified
+ * node; if false, import only the node itself, as explained above. This
+ * has no effect on Attr, EntityReference, and Notation nodes.
+ *
+ * @return The imported node that belongs to this Document.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the type of node being imported is not
+ * supported.
+ */
+ Node importNode( const Node & importedNode, bool deep );
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ bool isHTMLDocument() const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentRange interface
+ *
+ * @return Range
+ * The initial state of the Range returned from this method is such that
+ * both of its boundary-points are positioned at the beginning of the
+ * corresponding Document, before any content. The Range returned can only
+ * be used to select content associated with this Document, or with
+ * DocumentFragments and Attrs for which this Document is the ownerDocument.
+ */
+ Range createRange();
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentTraversal interface
+ *
+ * Create a new NodeIterator over the subtree rooted at the specified node.
+ *
+ * @param root The node which will be iterated together with its children.
+ * The iterator is initially positioned just before this node. The
+ * whatToShow flags and the filter, if any, are not considered when setting
+ * this position. The root must not be null.
+ *
+ * @param whatToShow This flag specifies which node types may appear in the
+ * logical view of the tree presented by the iterator. See the description
+ * of NodeFilter for the set of possible SHOW_ values. These flags can be
+ * combined using OR.
+ *
+ * @param filter The NodeFilter to be used with this NodeIterator, or null to
+ * indicate no filter.
+ *
+ * @param entityReferenceExpansion The value of this flag determines
+ * whether entity reference nodes are expanded.
+ *
+ * @return NodeIterator The newly created NodeIterator.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the specified root is null.
+ */
+ NodeIterator createNodeIterator(Node root, unsigned long whatToShow,
+ NodeFilter filter,
+ bool entityReferenceExpansion);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentTraversal interface
+ *
+ * Create a new TreeWalker over the subtree rooted at the specified node.
+ *
+ * @param root The node which will serve as the root for the TreeWalker.
+ * The whatToShow flags and the NodeFilter are not considered when setting
+ * this value; any node type will be accepted as the root. The currentNode
+ * of the TreeWalker is initialized to this node, whether or not it is
+ * visible. The root functions as a stopping point for traversal methods
+ * that look upward in the document structure, such as parentNode and
+ * nextNode. The root must not be null.
+ *
+ * @param whatToShow This flag specifies which node types may appear in the
+ * logical view of the tree presented by the tree-walker. See the
+ * description of NodeFilter for the set of possible SHOW_ values. These
+ * flags can be combined using OR.
+ *
+ * @param filter The NodeFilter to be used with this TreeWalker, or null to
+ * indicate no filter.
+ *
+ * @param entityReferenceExpansion If this flag is false, the contents of
+ * EntityReference nodes are not presented in the logical view.
+ *
+ * @return The newly created TreeWalker.
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the specified root is null.
+ */
+ TreeWalker createTreeWalker(Node root, unsigned long whatToShow,
+ NodeFilter filter,
+ bool entityReferenceExpansion);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentEvent interface
+ *
+ * The createEvent method is used in creating Events when it is either
+ * inconvenient or unnecessary for the user to create an Event themselves.
+ * In cases where the implementation provided Event is insufficient, users
+ * may supply their own Event implementations for use with the
+ * dispatchEvent method.
+ *
+ * @param eventType The eventType parameter specifies the type of Event
+ * interface to be created. If the Event interface specified is supported
+ * by the implementation this method will return a new Event of the
+ * interface type requested. If the Event is to be dispatched via the
+ * dispatchEvent method the appropriate event init method must be called
+ * after creation in order to initialize the Event's values. As an example,
+ * a user wishing to synthesize some kind of UIEvent would call createEvent
+ * with the parameter "UIEvents". The initUIEvent method could then be
+ * called on the newly created UIEvent to set the specific type of UIEvent
+ * to be dispatched and set its context information.
+ *
+ * @return The newly created EventExceptions
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the implementation does not support the
+ * type of Event interface requested
+ */
+ Event createEvent(const DOMString &eventType);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentView interface
+ *
+ * The default AbstractView for this Document, or null if none available.
+ */
+ AbstractView defaultView() const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentStyle interface
+ *
+ * A list containing all the style sheets explicitly linked into or
+ * embedded in a document. For HTML documents, this includes external style
+ * sheets, included via the HTML LINK element, and inline STYLE elements.
+ * In XML, this includes external style sheets, included via style sheet
+ * processing instructions (see [XML-StyleSheet]).
+ */
+ StyleSheetList styleSheets() const;
+
+ /**
+ * CSS3 mechanism for selecting alternate stylesheets using the DOM.
+ * Might change without further notice.
+ */
+
+ DOMString preferredStylesheetSet();
+ DOMString selectedStylesheetSet();
+ void setSelectedStylesheetSet(const DOMString& aString);
+
+ /**
+ * Adds a new style sheet to the list of style sheets.
+ *
+ * The new style sheet will be applied after all author and implicit
+ * style sheets, but before the user style sheet.
+ *
+ * Create new style sheets with e. g.
+ * \c DOMImplementation::createCSSStyleSheet
+ *
+ * This is not part of the official DOM.
+ *
+ * @param sheet style sheet
+ * @exception DOMException
+ * @since 3.4
+ */
+ void addStyleSheet(const StyleSheet &sheet);
+
+ /**
+ * Removes a style sheet to the list of style sheets.
+ *
+ * Only sheets added by \c addStyleSheet may be removed.
+ *
+ * This is not part of the official DOM.
+ *
+ * @param sheet style sheet to remove
+ * @exception DOMException
+ * NOT_FOUND_ERR \c sheet is not contained in the list of style sheets or
+ * it has not been added by \c addStyleSheet
+ * @since 3.4
+ */
+ void removeStyleSheet(const StyleSheet &sheet);
+
+ /**
+ * @return The KHTML view widget of this document.
+ */
+ KHTMLView *view() const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the DocumentCSS interface
+ *
+ * This method is used to retrieve the override style declaration for a
+ * specified element and a specified pseudo-element.
+ *
+ * @param elt The element whose style is to be modified. This parameter
+ * cannot be null.
+ *
+ * @param pseudoElt The pseudo-element or null if none.
+ *
+ * @return The override style declaration.
+ */
+ CSSStyleDeclaration getOverrideStyle(const Element &elt,
+ const DOMString &pseudoElt);
+
+ /**
+ * Introduced in DOM Level 3
+ * This method is from the DocumentLS interface
+ *
+ * Indicates whether the method DocumentLS.load() should be synchronous or
+ * asynchronous. When the async attribute is set to true the load method
+ * returns control to the caller before the document has completed loading.
+ * The default value of this attribute is true.
+ */
+ bool async() const;
+
+ /**
+ * Introduced in DOM Level 3
+ * This method is from the DocumentLS interface
+ *
+ * see async
+ *
+ * @exception DOMException
+ * NOT_SUPPORTED_ERR: Raised if the implementation doesn't support the mode
+ * the attribute is being set to.
+ */
+ void setAsync( bool );
+
+
+ /**
+ * Introduced in DOM Level 3
+ * This method is from the DocumentLS interface
+ *
+ * If the document is currently being loaded as a result of the method load
+ * being invoked the loading and parsing is immediately aborted. The
+ * possibly partial result of parsing the document is discarded and the
+ * document is cleared.
+ */
+ void abort();
+
+ /**
+ * Introduced in DOM Level 3
+ * This method is from the DocumentLS interface
+ *
+ * Replaces the content of the document with the result of parsing the
+ * given URI. Invoking this method will either block the caller or return
+ * to the caller immediately depending on the value of the async attribute.
+ * Once the document is fully loaded a "load" event (as defined in
+ * [DOM Level 3 Events], except that the Event.targetNode will be the
+ * document, not an element) will be dispatched on the document. If an
+ * error occurs, an implementation dependent "error" event will be
+ * dispatched on the document. If this method is called on a document that
+ * is currently loading, the current load is interrupted and the new URI
+ * load is initiated.
+ *
+ * When invoking this method the parameters used in the DOMParser interface
+ * are assumed to have their default values with the exception that the
+ * parameters "entities", "normalize-characters",
+ * "check-character-normalization" are set to "false".
+ *
+ * The result of a call to this method is the same the result of a call to
+ * DOMParser.parseWithContext with an input stream referencing the URI that
+ * was passed to this call, the document as the context node, and the
+ * action ACTION_REPLACE_CHILDREN.
+ *
+ * @param uri of type DOMString
+ * The URI reference for the XML file to be loaded. If this is a relative
+ * URI, the base URI used by the implementation is implementation dependent.
+ *
+ * @return If async is set to true load returns true if the document load
+ * was successfully initiated. If an error occurred when initiating the
+ * document load, load returns false.
+ * If async is set to false load returns true if the document was
+ * successfully loaded and parsed. If an error occurred when either loading
+ * or parsing the URI, load returns false.
+ */
+ void load( const DOMString &uri );
+
+ /**
+ * Introduced in DOM Level 3
+ * This method is from the DocumentLS interface
+ *
+ * Replace the content of the document with the result of parsing the input
+ * string, this method is always synchronous. This method always parses
+ * from a DOMString, which means the data is always UTF-16. All other
+ * encoding information is ignored.
+ *
+ * The parameters used in the DOMParser interface are assumed to have their
+ * default values when invoking this method.
+ *
+ * The result of a call to this method is the same as the result of a call
+ * to DOMParser.parseWithContext with an input stream containing the string
+ * passed to this call, the document as the context node, and the action
+ * ACTION_REPLACE_CHILDREN.
+ *
+ * @param source A string containing an XML document.
+ */
+ void loadXML( const DOMString &source );
+
+ /**
+ * not part of the official DOM
+ *
+ * Documents are read-only by default, but they can be made editable by
+ * entering "design mode".
+ *
+ * @return whether this document is in design mode.
+ * @since 3.2
+ */
+ bool designMode() const;
+
+ /**
+ * not part of the official DOM
+ *
+ * @param enable @p true to enable design mode, @p false to disable.
+ * @see designMode
+ * @since 3.2
+ */
+ void setDesignMode(bool enable);
+
+ /**
+ * not part of the DOM
+ *
+ * completes a given URL
+ */
+ DOMString completeURL(const DOMString& url);
+
+ DOMString toString() const;
+
+ /**
+ * not part of the DOM
+ *
+ * Updates the rendered display after one or more changes to
+ * the DOM structure
+ */
+ void updateRendering();
+
+ Document( DocumentImpl *i);
+protected:
+
+ friend class Node;
+};
+
+class DocumentFragmentImpl;
+
+/**
+ * \c DocumentFragment is a "lightweight" or "minimal"
+ * \c Document object. It is very common to want to be
+ * able to extract a portion of a document's tree or to create a new
+ * fragment of a document. Imagine implementing a user command like
+ * cut or rearranging a document by moving fragments around. It is
+ * desirable to have an object which can hold such fragments and it is
+ * quite natural to use a Node for this purpose. While it is true that
+ * a \c Document object could fulfil this role, a
+ * \c Document object can potentially be a heavyweight object,
+ * depending on the underlying implementation. What is really needed
+ * for this is a very lightweight object. \c DocumentFragment
+ * is such an object.
+ *
+ * Furthermore, various operations -- such as inserting nodes as
+ * children of another \c Node -- may take
+ * \c DocumentFragment objects as arguments; this results in all
+ * the child nodes of the \c DocumentFragment being moved
+ * to the child list of this node.
+ *
+ * The children of a \c DocumentFragment node are zero or
+ * more nodes representing the tops of any sub-trees defining the
+ * structure of the document. \c DocumentFragment nodes do
+ * not need to be well-formed XML documents (although they do need to
+ * follow the rules imposed upon well-formed XML parsed entities,
+ * which can have multiple top nodes). For example, a
+ * \c DocumentFragment might have only one child and that child
+ * node could be a \c Text node. Such a structure model
+ * represents neither an HTML document nor a well-formed XML document.
+ *
+ * When a \c DocumentFragment is inserted into a
+ * \c Document (or indeed any other \c Node that may
+ * take children) the children of the \c DocumentFragment
+ * and not the \c DocumentFragment itself are inserted
+ * into the \c Node . This makes the
+ * \c DocumentFragment very useful when the user wishes to create
+ * nodes that are siblings; the \c DocumentFragment acts
+ * as the parent of these nodes so that the user can use the standard
+ * methods from the \c Node interface, such as
+ * \c insertBefore() and \c appendChild() .
+ *
+ */
+class KHTML_EXPORT DocumentFragment : public Node
+{
+ friend class Document;
+ friend class HTMLElementImpl;
+ friend class Range;
+
+public:
+ DocumentFragment();
+ DocumentFragment(const DocumentFragment &other);
+ DocumentFragment(const Node &other) : Node()
+ {(*this)=other;}
+
+ DocumentFragment & operator = (const Node &other);
+ DocumentFragment & operator = (const DocumentFragment &other);
+
+ ~DocumentFragment();
+
+protected:
+ DocumentFragment(DocumentFragmentImpl *i);
+};
+
+class NamedNodeMap;
+class DOMString;
+
+/**
+ * Each \c Document has a \c doctype attribute
+ * whose value is either \c null or a \c DocumentType
+ * object. The \c DocumentType interface in the
+ * DOM Level 1 Core provides an interface to the list of entities that
+ * are defined for the document, and little else because the effect of
+ * namespaces and the various XML scheme efforts on DTD representation
+ * are not clearly understood as of this writing.
+ *
+ * The DOM Level 1 doesn't support editing \c DocumentType
+ * nodes.
+ *
+ */
+class KHTML_EXPORT DocumentType : public Node
+{
+ friend class Document;
+ friend class DOMImplementation;
+public:
+ DocumentType();
+ DocumentType(const DocumentType &other);
+
+ DocumentType(const Node &other) : Node()
+ {(*this)=other;}
+ DocumentType & operator = (const Node &other);
+ DocumentType & operator = (const DocumentType &other);
+
+ ~DocumentType();
+
+ /**
+ * The name of DTD; i.e., the name immediately following the
+ * \c DOCTYPE keyword.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * A \c NamedNodeMap containing the general entities,
+ * both external and internal, declared in the DTD. Duplicates are
+ * discarded. For example in: &lt;!DOCTYPE ex SYSTEM "ex.dtd" [
+ * &lt;!ENTITY foo "foo"> &lt;!ENTITY bar "bar"> &lt;!ENTITY % baz
+ * "baz"> ]> &lt;ex/> the interface provides access to \c foo
+ * and \c bar but not \c baz .
+ * Every node in this map also implements the \c Entity
+ * interface.
+ *
+ * The DOM Level 1 does not support editing entities, therefore
+ * \c entities cannot be altered in any way.
+ *
+ */
+ NamedNodeMap entities() const;
+
+ /**
+ * A \c NamedNodeMap containing the notations declared
+ * in the DTD. Duplicates are discarded. Every node in this map
+ * also implements the \c Notation interface.
+ *
+ * The DOM Level 1 does not support editing notations, therefore
+ * \c notations cannot be altered in any way.
+ *
+ */
+ NamedNodeMap notations() const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The public identifier of the external subset.
+ */
+ DOMString publicId() const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The system identifier of the external subset.
+ */
+ DOMString systemId() const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The internal subset as a string.
+ *
+ * Note: The actual content returned depends on how much information is
+ * available to the implementation. This may vary depending on various
+ * parameters, including the XML processor used to build the document.
+ */
+ DOMString internalSubset() const;
+
+protected:
+ DocumentType(DocumentTypeImpl *impl);
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_element.cpp b/tdehtml/dom/dom_element.cpp
new file mode 100644
index 000000000..d9872e37c
--- /dev/null
+++ b/tdehtml/dom/dom_element.cpp
@@ -0,0 +1,409 @@
+/**
+ * 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 "dom/dom_exception.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "html/html_formimpl.h"
+
+using namespace DOM;
+
+Attr::Attr() : Node()
+{
+}
+
+Attr::Attr(const Attr &other) : Node(other)
+{
+}
+
+Attr::Attr( AttrImpl *_impl )
+{
+ impl= _impl;
+ if (impl) impl->ref();
+}
+
+Attr &Attr::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || !ohandle->isAttributeNode()) {
+ if (impl) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Attr &Attr::operator = (const Attr &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Attr::~Attr()
+{
+}
+
+DOMString Attr::name() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return ((AttrImpl *)impl)->name();
+}
+
+bool Attr::specified() const
+{
+ if (impl) return ((AttrImpl *)impl)->specified();
+ return 0;
+}
+
+Element Attr::ownerElement() const
+{
+ if (!impl) return 0;
+ return static_cast<AttrImpl*>(impl)->ownerElement();
+}
+
+DOMString Attr::value() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->nodeValue();
+}
+
+void Attr::setValue( const DOMString &newValue )
+{
+ if (!impl)
+ return;
+
+ int exceptioncode = 0;
+ ((AttrImpl *)impl)->setValue(newValue,exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+// ---------------------------------------------------------------------------
+
+Element::Element() : Node()
+{
+}
+
+Element::Element(const Element &other) : Node(other)
+{
+}
+
+Element::Element(ElementImpl *impl) : Node(impl)
+{
+}
+
+Element &Element::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || !ohandle->isElementNode()) {
+ if (impl) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Element &Element::operator = (const Element &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Element::~Element()
+{
+}
+
+DOMString Element::tagName() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return static_cast<ElementImpl*>(impl)->tagName();
+}
+
+DOMString Element::getAttribute( const DOMString &name )
+{
+ // ### getAttribute() and getAttributeNS() are supposed to return the empty string if the attribute
+ // does not exist. However, there are a number of places around tdehtml that expect a null string
+ // for nonexistent attributes. These need to be changed to use hasAttribute() instead.
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,name.implementation(),true,true);
+ if (!id) return DOMString();
+
+ ElementImpl* e = static_cast<ElementImpl*>(impl);
+ return e->getAttribute(id, false, name);
+}
+
+void Element::setAttribute( const DOMString &name, const DOMString &value )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), false /* allocate */,
+ true, &exceptioncode);
+
+ static_cast<ElementImpl*>(impl)->setAttribute(id, value, name, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void Element::removeAttribute( const DOMString &name )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true);
+ if (!id) return;
+
+ int exceptioncode = 0;
+ NamedNodeMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false);
+ attributes->removeNamedItem(id, false, name.implementation(), exceptioncode);
+ // it's allowed to remove attributes that don't exist.
+ if ( exceptioncode && exceptioncode != DOMException::NOT_FOUND_ERR )
+ throw DOMException( exceptioncode );
+}
+
+Attr Element::getAttributeNode( const DOMString &name )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!name.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR);
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true);
+ if (!id) return 0;
+
+ ElementImpl* e = static_cast<ElementImpl*>(impl);
+ if (!e->attributes()) return 0;
+
+ return static_cast<AttrImpl*>(e->attributes()->getNamedItem(id, false, name.implementation()));
+}
+
+Attr Element::setAttributeNode( const Attr &newAttr )
+{
+ if (!impl || newAttr.isNull())
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+ // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem
+
+ int exceptioncode = 0;
+ Attr r = static_cast<ElementImpl*>(impl)->attributes(false)->setNamedItem(newAttr.handle(), false,
+ newAttr.handle()->nodeName().implementation(), exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ static_cast<AttrImpl *>(newAttr.handle())->setOwnerElement( static_cast<ElementImpl*>(impl) );
+ return r;
+}
+
+Attr Element::removeAttributeNode( const Attr &oldAttr )
+{
+ if (!impl || oldAttr.isNull() || oldAttr.ownerElement().handle() != impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ if (impl->isReadOnly())
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+
+ if (!static_cast<ElementImpl*>(impl)->attributes(true))
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ NamedAttrMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false);
+ return attributes->removeAttr(static_cast<AttrImpl*>(static_cast<AttrImpl*>(oldAttr.handle())));
+}
+
+NodeList Element::getElementsByTagName( const DOMString &tagName )
+{
+ if (!impl) return 0;
+ NodeImpl::Id id;
+ if ( tagName == "*" )
+ id = 0;
+ else
+ id = impl->getDocument()->getId(NodeImpl::ElementId, tagName.implementation(), false, true);
+ return new TagNodeListImpl( impl, id );
+}
+
+NodeList Element::getElementsByTagNameNS( const DOMString &namespaceURI,
+ const DOMString &localName )
+{
+ if (!impl) return 0;
+ return new TagNodeListImpl( impl, namespaceURI, localName );
+}
+
+DOMString Element::getAttributeNS( const DOMString &namespaceURI,
+ const DOMString &localName)
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR);
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), true, true);
+ ElementImpl* e = static_cast<ElementImpl*>(impl);
+ return e->getAttribute(id, true);
+}
+
+void Element::setAttributeNS( const DOMString &namespaceURI,
+ const DOMString &qualifiedName,
+ const DOMString &value)
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ static_cast<ElementImpl*>(impl)->setAttributeNS(namespaceURI, qualifiedName, value, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void Element::removeAttributeNS( const DOMString &namespaceURI,
+ const DOMString &localName )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ NamedNodeMapImpl *attributes = static_cast<ElementImpl*>(impl)->attributes(false);
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(), 0/*prefix*/, localName.implementation(), false, true);
+ attributes->removeNamedItem(id, true, 0, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+Attr Element::getAttributeNodeNS( const DOMString &namespaceURI,
+ const DOMString &localName )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!localName.implementation()) throw DOMException(DOMException::NOT_FOUND_ERR);
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, namespaceURI.implementation(),
+ 0/*prefix*/, localName.implementation(), true, true);
+ ElementImpl* e = static_cast<ElementImpl*>(impl);
+ if (!e->attributes()) return 0;
+
+ return static_cast<AttrImpl*>(e->attributes()->getNamedItem(id, true));
+}
+
+Attr Element::setAttributeNodeNS( const Attr &newAttr )
+{
+ if (!impl || newAttr.isNull())
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+ // WRONG_DOCUMENT_ERR and INUSE_ATTRIBUTE_ERR are already tested & thrown by setNamedItem
+
+ int exceptioncode = 0;
+ Attr r = static_cast<ElementImpl*>(impl)->attributes(false)->setNamedItem(newAttr.handle(), true, 0, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ static_cast<AttrImpl *>(newAttr.handle())->setOwnerElement( static_cast<ElementImpl*>(impl) );
+ return r;
+}
+
+
+bool Element::hasAttribute( const DOMString& name )
+{
+ if (!impl || !static_cast<ElementImpl*>(impl)->attributes()) return false; // ### throw ?
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId, name.implementation(), true, true);
+ if (!id) return false;
+
+ if (!static_cast<ElementImpl*>(impl)->attributes(true /*readonly*/)) return false;
+ return static_cast<ElementImpl*>(impl)->attributes(true)->getValue(id, false, name.implementation()) != 0;
+}
+
+bool Element::hasAttributeNS( const DOMString &namespaceURI,
+ const DOMString &localName )
+{
+ if (!impl || !static_cast<ElementImpl*>(impl)->attributes()) return false; // ### throw ?
+ if (!static_cast<ElementImpl*>(impl)->attributes(true /*readonly*/)) return false;
+ NodeImpl::Id id = impl->getDocument()->getId(NodeImpl::AttributeId,namespaceURI.implementation(),
+ 0/*prefix*/, localName.implementation(), true, true);
+ return static_cast<ElementImpl*>(impl)->attributes(true)->getValue(id, true) != 0;
+}
+
+bool Element::isHTMLElement() const
+{
+ if(!impl) return false;
+ return ((ElementImpl *)impl)->isHTMLElement();
+}
+
+Element Element::form() const
+{
+ if (!impl || !impl->isGenericFormElement()) return 0;
+ return static_cast<HTMLGenericFormElementImpl*>(impl)->form();
+ ElementImpl* f = static_cast<HTMLGenericFormElementImpl*>( impl )->form();
+
+ if( f && f->implicitNode() )
+ return 0;
+ return f;
+}
+
+CSSStyleDeclaration Element::style()
+{
+ if (impl) return ((ElementImpl *)impl)->styleRules();
+ return 0;
+}
+
+bool Element::contentEditable() const {
+ if(!impl) return false;
+ return static_cast<ElementImpl *>(impl)->contentEditable();
+}
+
+void Element::setContentEditable(bool enabled) {
+ if(!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ static_cast<ElementImpl *>(impl)->setContentEditable(enabled);
+}
+
+bool Element::tdehtmlValidAttrName(const DOMString &name)
+{
+ // Check if name is valid
+ // http://www.w3.org/TR/2000/REC-xml-20001006#NT-Name
+ DOMStringImpl* _name = name.implementation();
+ TQChar ch = _name->s[0];
+ if ( !ch.isLetter() && ch != '_' && ch != ':' )
+ return false; // first char isn't valid
+ for ( uint i = 0; i < _name->l; ++i )
+ {
+ ch = _name->s[i];
+ if ( !ch.isLetter() && !ch.isDigit() && ch != '.'
+ && ch != '-' && ch != '_' && ch != ':'
+ && ch.category() != TQChar::Mark_SpacingCombining
+ /* no idea what "extender is" */ )
+ return false;
+ }
+ return true;
+}
+
+bool Element::tdehtmlValidPrefix(const DOMString &name)
+{
+ // Null prefix is ok. If not null, reuse code from tdehtmlValidAttrName
+ return !name.implementation() || tdehtmlValidAttrName(name);
+}
+
+bool Element::tdehtmlValidQualifiedName(const DOMString &name)
+{
+ return tdehtmlValidAttrName(name);
+}
+
+bool Element::tdehtmlMalformedQualifiedName(const DOMString &name)
+{
+ // #### Not clearly defined in the DOM spec...
+ // But we know for sure that a null qualified name is malformed
+ return name.isNull();
+}
+
+bool Element::tdehtmlMalformedPrefix(const DOMString &/*name*/)
+{
+ // ####
+ return false;
+}
diff --git a/tdehtml/dom/dom_element.h b/tdehtml/dom/dom_element.h
new file mode 100644
index 000000000..d3313628e
--- /dev/null
+++ b/tdehtml/dom/dom_element.h
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef _DOM_ELEMENT_h_
+#define _DOM_ELEMENT_h_
+
+#include <dom/dom_node.h>
+#include <dom/css_value.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class DOMString;
+class AttrImpl;
+class Element;
+class ElementImpl;
+class NamedAttrMapImpl;
+class DocumentImpl;
+
+/**
+ * The \c Attr interface represents an attribute in an
+ * \c Element object. Typically the allowable values for
+ * the attribute are defined in a document type definition.
+ *
+ * \c Attr objects inherit the \c Node
+ * interface, but since they are not actually child nodes of the
+ * element they describe, the DOM does not consider them part of the
+ * document tree. Thus, the \c Node attributes
+ * \c parentNode , \c previousSibling , and
+ * \c nextSibling have a null value for \c Attr
+ * objects. The DOM takes the view that attributes are properties of
+ * elements rather than having a separate identity from the elements
+ * they are associated with; this should make it more efficient to
+ * implement such features as default attributes associated with all
+ * elements of a given type. Furthermore, \c Attr nodes
+ * may not be immediate children of a \c DocumentFragment
+ * . However, they can be associated with \c Element nodes
+ * contained within a \c DocumentFragment . In short,
+ * users and implementors of the DOM need to be aware that \c Attr
+ * nodes have some things in common with other objects
+ * inheriting the \c Node interface, but they also are
+ * quite distinct.
+ *
+ * The attribute's effective value is determined as follows: if this
+ * attribute has been explicitly assigned any value, that value is the
+ * attribute's effective value; otherwise, if there is a declaration
+ * for this attribute, and that declaration includes a default value,
+ * then that default value is the attribute's effective value;
+ * otherwise, the attribute does not exist on this element in the
+ * structure model until it has been explicitly added. Note that the
+ * \c nodeValue attribute on the \c Attr
+ * instance can also be used to retrieve the string version of the
+ * attribute's value(s).
+ *
+ * In XML, where the value of an attribute can contain entity
+ * references, the child nodes of the \c Attr node provide
+ * a representation in which entity references are not expanded. These
+ * child nodes may be either \c Text or
+ * \c EntityReference nodes. Because the attribute type may be
+ * unknown, there are no tokenized attribute values.
+ *
+ */
+class KHTML_EXPORT Attr : public Node
+{
+ friend class Element;
+ friend class Document;
+ friend class DocumentImpl;
+ friend class HTMLDocument;
+ friend class ElementImpl;
+ friend class NamedAttrMapImpl;
+ friend class AttrImpl;
+
+public:
+ Attr();
+ Attr(const Node &other) : Node()
+ {(*this)=other;}
+ Attr(const Attr &other);
+
+ Attr & operator = (const Node &other);
+ Attr & operator = (const Attr &other);
+
+ ~Attr();
+
+ /**
+ * Returns the name of this attribute.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * If this attribute was explicitly given a value in the original
+ * document, this is \c true ; otherwise, it is
+ * \c false . Note that the implementation is in charge of
+ * this attribute, not the user. If the user changes the value of
+ * the attribute (even if it ends up having the same value as the
+ * default value) then the \c specified flag is
+ * automatically flipped to \c true . To re-specify
+ * the attribute as the default value from the DTD, the user must
+ * delete the attribute. The implementation will then make a new
+ * attribute available with \c specified set to
+ * \c false and the default value (if one exists).
+ *
+ * In summary:
+ * \li If the attribute has an assigned
+ * value in the document then \c specified is
+ * \c true , and the value is the assigned value.
+ *
+ * \li If the attribute has no assigned value in the
+ * document and has a default value in the DTD, then
+ * \c specified is \c false , and the value is
+ * the default value in the DTD.
+ *
+ * \li If the attribute has no assigned value in the
+ * document and has a value of #IMPLIED in the DTD, then the
+ * attribute does not appear in the structure model of the
+ * document.
+ *
+ *
+ *
+ */
+ bool specified() const;
+
+ /**
+ * On retrieval, the value of the attribute is returned as a
+ * string. Character and general entity references are replaced
+ * with their values.
+ *
+ * On setting, this creates a \c Text node with the
+ * unparsed contents of the string.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The Element node this attribute is attached to or null if this attribute
+ * is not in use.
+ */
+ Element ownerElement() const;
+
+protected:
+
+ Attr( AttrImpl *_impl );
+};
+
+class NodeList;
+class Attr;
+class DOMString;
+
+/**
+ * By far the vast majority of objects (apart from text) that authors
+ * encounter when traversing a document are \c Element
+ * nodes. Assume the following XML document: &lt;elementExample
+ * id=&quot;demo&quot;&gt; &lt;subelement1/&gt;
+ * &lt;subelement2&gt;&lt;subsubelement/&gt;&lt;/subelement2&gt;
+ * &lt;/elementExample&gt;
+ *
+ * When represented using DOM, the top node is an \c Element
+ * node for &quot;elementExample&quot;, which contains two
+ * child \c Element nodes, one for &quot;subelement1&quot;
+ * and one for &quot;subelement2&quot;. &quot;subelement1&quot;
+ * contains no child nodes.
+ *
+ * Elements may have attributes associated with them; since the
+ * \c Element interface inherits from \c Node
+ * , the generic \c Node interface method
+ * \c getAttributes may be used to retrieve the set of all
+ * attributes for an element. There are methods on the \c Element
+ * interface to retrieve either an \c Attr object
+ * by name or an attribute value by name. In XML, where an attribute
+ * value may contain entity references, an \c Attr object
+ * should be retrieved to examine the possibly fairly complex sub-tree
+ * representing the attribute value. On the other hand, in HTML, where
+ * all attributes have simple string values, methods to directly
+ * access an attribute value can safely be used as a convenience.
+ *
+ */
+class KHTML_EXPORT Element : public Node
+{
+ friend class Document;
+ friend class HTMLDocument;
+// friend class AttrImpl;
+ friend class Attr;
+
+public:
+ Element();
+ Element(const Node &other) : Node()
+ {(*this)=other;}
+ Element(const Element &other);
+
+ Element & operator = (const Node &other);
+ Element & operator = (const Element &other);
+
+ ~Element();
+
+ /**
+ * The name of the element. For example, in: &lt;elementExample
+ * id=&quot;demo&quot;&gt; ... &lt;/elementExample&gt; ,
+ * \c tagName has the value \c &quot;elementExample&quot;
+ * . Note that this is case-preserving in XML, as are all
+ * of the operations of the DOM. The HTML DOM returns the
+ * \c tagName of an HTML element in the canonical uppercase
+ * form, regardless of the case in the source HTML document.
+ *
+ */
+ DOMString tagName() const;
+
+ /**
+ * Retrieves an attribute value by name.
+ *
+ * @param name The name of the attribute to retrieve.
+ *
+ * @return The \c Attr value as a string, or the empty
+ * string if that attribute does not have a specified or default
+ * value.
+ *
+ */
+ DOMString getAttribute ( const DOMString &name );
+
+ /**
+ * Adds a new attribute. If an attribute with that name is already
+ * present in the element, its value is changed to be that of the
+ * value parameter. This value is a simple string, it is not
+ * parsed as it is being set. So any markup (such as syntax to be
+ * recognized as an entity reference) is treated as literal text,
+ * and needs to be appropriately escaped by the implementation
+ * when it is written out. In order to assign an attribute value
+ * that contains entity references, the user must create an
+ * \c Attr node plus any \c Text and
+ * \c EntityReference nodes, build the appropriate subtree,
+ * and use \c setAttributeNode to assign it as the
+ * value of an attribute.
+ *
+ * @param name The name of the attribute to create or alter.
+ *
+ * @param value Value to set in string form.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void setAttribute ( const DOMString &name, const DOMString &value );
+
+ /**
+ * Removes an attribute by name. If the removed attribute has a
+ * default value it is immediately replaced.
+ *
+ * @param name The name of the attribute to remove.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void removeAttribute ( const DOMString &name );
+
+ /**
+ * Retrieves an \c Attr node by name.
+ *
+ * @param name The name of the attribute to retrieve.
+ *
+ * @return The \c Attr node with the specified
+ * attribute name or \c null if there is no such
+ * attribute.
+ *
+ */
+ Attr getAttributeNode ( const DOMString &name );
+
+ /**
+ * Adds a new attribute. If an attribute with that name is already
+ * present in the element, it is replaced by the new one.
+ *
+ * @param newAttr The \c Attr node to add to the
+ * attribute list.
+ *
+ * @return If the \c newAttr attribute replaces an
+ * existing attribute with the same name, the previously existing
+ * \c Attr node is returned, otherwise \c null
+ * is returned.
+ *
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if \c newAttr was
+ * created from a different document than the one that created the
+ * element.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * INUSE_ATTRIBUTE_ERR: Raised if \c newAttr is
+ * already an attribute of another \c Element object.
+ * The DOM user must explicitly clone \c Attr nodes to
+ * re-use them in other elements.
+ *
+ */
+ Attr setAttributeNode ( const Attr &newAttr );
+
+ /**
+ * Removes the specified attribute.
+ *
+ * @param oldAttr The \c Attr node to remove from the
+ * attribute list. If the removed \c Attr has a
+ * default value it is immediately replaced.
+ *
+ * @return The \c Attr node that was removed.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NOT_FOUND_ERR: Raised if \c oldAttr is not an
+ * attribute of the element.
+ *
+ */
+ Attr removeAttributeNode ( const Attr &oldAttr );
+
+ /**
+ * Returns a \c NodeList of all descendant elements
+ * with a given tag name, in the order in which they would be
+ * encountered in a preorder traversal of the \c Element
+ * tree.
+ *
+ * @param name The name of the tag to match on. The special value
+ * "*" matches all tags.
+ *
+ * @return A list of matching \c Element nodes.
+ *
+ */
+ NodeList getElementsByTagName ( const DOMString &name );
+
+ /**
+ * Introduced in DOM Level 2
+ * Returns a NodeList of all the descendant Elements with a given local
+ * name and namespace URI in the order in which they are encountered in a
+ * preorder traversal of this Element tree.
+ *
+ * @param namespaceURI The namespace URI of the elements to match on. The
+ * special value "*" matches all namespaces.
+ *
+ * @param localName The local name of the elements to match on. The special
+ * value "*" matches all local names.
+ *
+ * @return A new NodeList object containing all the matched Elements.
+ */
+ NodeList getElementsByTagNameNS ( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2.
+ *
+ * No Exceptions.
+ *
+ * Retrieves an attribute value by local name and namespace URI. HTML-only
+ * DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to retrieve.
+ *
+ * @param localName The local name of the attribute to retrieve.
+ *
+ * @return The Attr value as a string, or the empty string if that
+ * attribute does not have a specified or default value.
+ */
+ DOMString getAttributeNS ( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Adds a new attribute. If an attribute with the same local name and
+ * namespace URI is already present on the element, its prefix is changed
+ * to be the prefix part of the qualifiedName, and its value is changed to
+ * be the value parameter. This value is a simple string; it is not parsed
+ * as it is being set. So any markup (such as syntax to be recognized as an
+ * entity reference) is treated as literal text, and needs to be
+ * appropriately escaped by the implementation when it is written out. In
+ * order to assign an attribute value that contains entity references, the
+ * user must create an Attr node plus any Text and EntityReference nodes,
+ * build the appropriate subtree, and use setAttributeNodeNS or
+ * setAttributeNode to assign it as the value of an attribute.
+ *
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to create or
+ * alter.
+ *
+ * @param qualifiedName The qualified name of the attribute to create or
+ * alter.
+ *
+ * @param value The value to set in string form.
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified qualified name contains
+ * an illegal character.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NAMESPACE_ERR: Raised if the qualifiedName is malformed, if the
+ * qualifiedName has a prefix and the namespaceURI is null, if the
+ * qualifiedName has a prefix that is "xml" and the namespaceURI is
+ * different from "http://www.w3.org/XML/1998/namespace", or if the
+ * qualifiedName is "xmlns" and the namespaceURI is different from
+ * "http://www.w3.org/2000/xmlns/".
+ */
+ void setAttributeNS ( const DOMString &namespaceURI,
+ const DOMString &qualifiedName,
+ const DOMString &value );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Removes an attribute by local name and namespace URI. If the removed
+ * attribute has a default value it is immediately replaced. The replacing
+ * attribute has the same namespace URI and local name, as well as the
+ * original prefix.
+ *
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to remove.
+ *
+ * @param localName The local name of the attribute to remove.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ */
+ void removeAttributeNS ( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Retrieves an Attr node by local name and namespace URI. HTML-only DOM
+ * implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to retrieve.
+ *
+ * @param localName The local name of the attribute to retrieve.
+ *
+ * @return The Attr node with the specified attribute local name and
+ * namespace URI or null if there is no such attribute.
+ */
+ Attr getAttributeNodeNS ( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Adds a new attribute. If an attribute with that local name and that
+ * namespace URI is already present in the element, it is replaced by the
+ * new one.
+ *
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param newAttr The Attr node to add to the attribute list.
+ *
+ * @return If the newAttr attribute replaces an existing attribute with the
+ * same local name and namespace URI, the replaced Attr node is returned,
+ * otherwise null is returned.
+ *
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if newAttr was created from a different
+ * document than the one that created the element.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * INUSE_ATTRIBUTE_ERR: Raised if newAttr is already an attribute of
+ * another Element object. The DOM user must explicitly clone Attr nodes to
+ * re-use them in other elements.
+ */
+ Attr setAttributeNodeNS ( const Attr &newAttr );
+
+ /**
+ * Returns true when an attribute with a given name is specified on this
+ * element or has a default value, false otherwise.
+ * Introduced in DOM Level 2.
+ *
+ * @param name The name of the attribute to look for.
+ *
+ * @return true if an attribute with the given name is specified on this
+ * element or has a default value, false otherwise.
+ */
+ bool hasAttribute( const DOMString& name );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Returns true when an attribute with a given local name and namespace URI
+ * is specified on this element or has a default value, false otherwise.
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the attribute to look for.
+ *
+ * @param localName The local name of the attribute to look for.
+ *
+ * @return true if an attribute with the given local name and namespace URI
+ * is specified or has a default value on this element, false otherwise.
+ */
+ bool hasAttributeNS ( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the CSSStyleDeclaration interface
+ *
+ * The style attribute
+ */
+ CSSStyleDeclaration style ( );
+
+ /**
+ * not part of the official DOM
+ *
+ * This method will always reflect the editability setting of this
+ * element as specified by a direct or indirect (that means, inherited)
+ * assignment to contentEditable or the respective CSS rule, even if
+ * design mode is active.
+ *
+ * @return whether this element is editable.
+ * @since 3.2
+ * @see setContentEditable
+ */
+ bool contentEditable() const;
+
+ /**
+ * not part of the official DOM
+ *
+ * This element can be made editable by setting its contentEditable
+ * property to @p true. The setting will be inherited to its children
+ * as well.
+ *
+ * Setting or clearing contentEditable when design mode is active will
+ * take no effect. However, its status will still be propagated to all
+ * child elements.
+ *
+ * @param enabled @p true to make this element editable, @p false
+ * otherwise.
+ * @see DOM::Document::designMode
+ * @since 3.2
+ */
+ void setContentEditable(bool enabled);
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ bool isHTMLElement() const;
+
+ /**
+ * KHTML extension to DOM
+ * This method returns the associated form element.
+ * returns null if this element is not a form-like element
+ * or if this elment is not in the scope of a form element.
+ */
+ Element form() const;
+
+ static bool tdehtmlValidAttrName(const DOMString &name);
+ static bool tdehtmlValidPrefix(const DOMString &name);
+ static bool tdehtmlValidQualifiedName(const DOMString &name);
+
+ static bool tdehtmlMalformedQualifiedName(const DOMString &name);
+ static bool tdehtmlMalformedPrefix(const DOMString &name);
+protected:
+ Element(ElementImpl *_impl);
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_exception.h b/tdehtml/dom/dom_exception.h
new file mode 100644
index 000000000..cef032206
--- /dev/null
+++ b/tdehtml/dom/dom_exception.h
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef _DOM_DOMException_h_
+#define _DOM_DOMException_h_
+
+#include <dom/dom_misc.h>
+
+namespace DOM {
+
+
+/**
+ * DOM operations only raise exceptions in &quot;exceptional&quot;
+ * circumstances, i.e., when an operation is impossible to perform
+ * (either for logical reasons, because data is lost, or because the
+ * implementation has become unstable). In general, DOM methods return
+ * specific error values in ordinary processing situation, such as
+ * out-of-bound errors when using \c NodeList .
+ *
+ * Implementations may raise other exceptions under other
+ * circumstances. For example, implementations may raise an
+ * implementation-dependent exception if a \c null
+ * argument is passed.
+ *
+ * Some languages and object systems do not support the concept of
+ * exceptions. For such systems, error conditions may be indicated
+ * using native error reporting mechanisms. For some bindings, for
+ * example, methods may return error codes similar to those listed in
+ * the corresponding method descriptions.
+ *
+ */
+class KHTML_EXPORT DOMException
+{
+public:
+ DOMException(unsigned short _code) { code = _code; }
+ DOMException(const DOMException &other) { code = other.code; }
+
+ DOMException & operator = (const DOMException &other)
+ { code = other.code; return *this; }
+
+ virtual ~DOMException() {}
+ /**
+ * An integer indicating the type of error generated.
+ *
+ */
+ enum ExceptionCode {
+ INDEX_SIZE_ERR = 1,
+ DOMSTRING_SIZE_ERR = 2,
+ HIERARCHY_REQUEST_ERR = 3,
+ WRONG_DOCUMENT_ERR = 4,
+ INVALID_CHARACTER_ERR = 5,
+ NO_DATA_ALLOWED_ERR = 6,
+ NO_MODIFICATION_ALLOWED_ERR = 7,
+ NOT_FOUND_ERR = 8,
+ NOT_SUPPORTED_ERR = 9,
+ INUSE_ATTRIBUTE_ERR = 10,
+ INVALID_STATE_ERR = 11,
+ SYNTAX_ERR = 12,
+ INVALID_MODIFICATION_ERR = 13,
+ NAMESPACE_ERR = 14,
+ INVALID_ACCESS_ERR = 15
+ };
+ unsigned short code;
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_html.h b/tdehtml/dom/dom_html.h
new file mode 100644
index 000000000..f8aa02e99
--- /dev/null
+++ b/tdehtml/dom/dom_html.h
@@ -0,0 +1,40 @@
+/*
+ * 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_HTML_H
+#define DOM_HTML_H
+
+#include <dom/dom_core.h>
+
+#include <dom/html_base.h>
+#include <dom/html_block.h>
+#include <dom/html_document.h>
+#include <dom/html_element.h>
+#include <dom/html_form.h>
+#include <dom/html_head.h>
+#include <dom/html_image.h>
+#include <dom/html_inline.h>
+#include <dom/html_list.h>
+#include <dom/html_misc.h>
+#include <dom/html_object.h>
+#include <dom/html_table.h>
+
+#endif
diff --git a/tdehtml/dom/dom_misc.cpp b/tdehtml/dom/dom_misc.cpp
new file mode 100644
index 000000000..d296b954a
--- /dev/null
+++ b/tdehtml/dom/dom_misc.cpp
@@ -0,0 +1,37 @@
+/**
+ * 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 "dom_misc.h"
+using namespace DOM;
+
+DomShared::~DomShared()
+{
+ // deliberately left blank
+}
+
+
+bool DomShared::deleteMe()
+{
+ return !_ref;
+}
+
+
diff --git a/tdehtml/dom/dom_misc.h b/tdehtml/dom/dom_misc.h
new file mode 100644
index 000000000..4cded0f00
--- /dev/null
+++ b/tdehtml/dom/dom_misc.h
@@ -0,0 +1,60 @@
+/*
+ * 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_RefCountImpl_h_
+#define _DOM_RefCountImpl_h_
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+/*
+ * This implements the reference counting scheme used for all internal
+ * DOM objects.
+ *
+ * Other objects should overload deleteMe() to fit their needs. The default
+ * implementation deletes the object if the ref count drops to 0.
+ */
+class KHTML_EXPORT DomShared
+{
+public:
+ DomShared() : _ref( 0 ) {}
+ virtual ~DomShared();
+
+ /* Overload this function if you want a different deletion behavior
+ */
+ virtual bool deleteMe();
+
+ void ref() { _ref++; }
+ void deref() { if(_ref) _ref--; if(!_ref && deleteMe()) delete this; }
+ bool hasOneRef() const { return _ref == 1; }
+ unsigned int refCount() const { return _ref; }
+
+protected:
+ // the number of DOMObjects referencing this Node
+ // An implementation object will delete itself, if it has
+ // no DOMObject referencing it, and deleteMe() returns true.
+ unsigned int _ref;
+};
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/dom_node.cpp b/tdehtml/dom/dom_node.cpp
new file mode 100644
index 000000000..9971bdb00
--- /dev/null
+++ b/tdehtml/dom/dom_node.cpp
@@ -0,0 +1,495 @@
+/**
+ * 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 "dom/dom_doc.h"
+#include "dom/dom_exception.h"
+#include "dom/dom2_events.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <tqrect.h>
+
+using namespace DOM;
+
+NamedNodeMap::NamedNodeMap()
+{
+ impl = 0;
+}
+
+NamedNodeMap::NamedNodeMap(const NamedNodeMap &other)
+{
+ impl = other.impl;
+ if (impl) impl->ref();
+}
+
+NamedNodeMap::NamedNodeMap(NamedNodeMapImpl *i)
+{
+ impl = i;
+ if (impl) impl->ref();
+}
+
+NamedNodeMap &NamedNodeMap::operator = (const NamedNodeMap &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+NamedNodeMap::~NamedNodeMap()
+{
+ if(impl) impl->deref();
+}
+
+Node NamedNodeMap::getNamedItem( const DOMString &name ) const
+{
+ if (!impl) return 0;
+ NodeImpl::Id nid = impl->mapId(0, name.implementation(), true);
+ if (!nid) return 0;
+ return impl->getNamedItem(nid, false, name.implementation());
+}
+
+Node NamedNodeMap::setNamedItem( const Node &arg )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!arg.impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ Node r = impl->setNamedItem(arg.impl, false,
+ arg.impl->nodeName().implementation(), exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+Node NamedNodeMap::removeNamedItem( const DOMString &name )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ Node r = impl->removeNamedItem(impl->mapId(0, name.implementation(), false),
+ false, name.implementation(), exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+Node NamedNodeMap::item( unsigned long index ) const
+{
+ if (!impl) return 0;
+ return impl->item(index);
+}
+
+Node NamedNodeMap::getNamedItemNS( const DOMString &namespaceURI, const DOMString &localName ) const
+{
+ if (!impl) return 0;
+ NodeImpl::Id nid = impl->mapId( namespaceURI.implementation(), localName.implementation(), true );
+ return impl->getNamedItem(nid, true);
+}
+
+Node NamedNodeMap::setNamedItemNS( const Node &arg )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ Node r = impl->setNamedItem(arg.impl, true, 0, exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+Node NamedNodeMap::removeNamedItemNS( const DOMString &namespaceURI, const DOMString &localName )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ NodeImpl::Id nid = impl->mapId( namespaceURI.implementation(), localName.implementation(), false );
+ Node r = impl->removeNamedItem(nid, true, 0, exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return r;
+}
+
+unsigned long NamedNodeMap::length() const
+{
+ if (!impl) return 0;
+ return impl->length();
+}
+
+// ---------------------------------------------------------------------------
+
+Node::Node(const Node &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+Node::Node( NodeImpl *i )
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+Node &Node::operator = (const Node &other)
+{
+ if(impl != other.impl) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+bool Node::operator == (const Node &other) const
+{
+ return (impl == other.impl);
+}
+
+bool Node::operator != (const Node &other) const
+{
+ return !(impl == other.impl);
+}
+
+Node::~Node()
+{
+ if(impl) impl->deref();
+}
+
+DOMString Node::nodeName() const
+{
+ if(impl) return impl->nodeName();
+ return DOMString();
+}
+
+DOMString Node::nodeValue() const
+{
+ // ### should throw exception on plain node ?
+ if(impl) return impl->nodeValue();
+ return DOMString();
+}
+
+void Node::setNodeValue( const DOMString &_str )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ if(impl) impl->setNodeValue( _str,exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+unsigned short Node::nodeType() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->nodeType();
+}
+
+Node Node::parentNode() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->parentNode();
+}
+
+NodeList Node::childNodes() const
+{
+ if (!impl) return 0;
+ return impl->childNodes();
+}
+
+Node Node::firstChild() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->firstChild();
+}
+
+Node Node::lastChild() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->lastChild();
+}
+
+Node Node::previousSibling() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->previousSibling();
+}
+
+Node Node::nextSibling() const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->nextSibling();
+}
+
+NamedNodeMap Node::attributes() const
+{
+ if (!impl || !impl->isElementNode()) return 0;
+ return static_cast<ElementImpl*>(impl)->attributes();
+}
+
+Document Node::ownerDocument() const
+{
+ // braindead DOM spec says that ownerDocument
+ // should return null if called on the document node
+ // we don't do that in the *impl tree to avoid excessive if()'s
+ // so we simply hack it here in one central place.
+ if (!impl || impl->getDocument() == impl) return Document(false);
+
+ return impl->getDocument();
+}
+
+Node Node::insertBefore( const Node &newChild, const Node &refChild )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ NodeImpl *r = impl->insertBefore( newChild.impl, refChild.impl, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ if (!newChild.impl->closed()) newChild.impl->close();
+ return r;
+}
+
+Node Node::replaceChild( const Node &newChild, const Node &oldChild )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ impl->replaceChild( newChild.impl, oldChild.impl, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ if (newChild.impl && !newChild.impl->closed()) newChild.impl->close();
+
+ return oldChild;
+}
+
+Node Node::removeChild( const Node &oldChild )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ impl->removeChild( oldChild.impl, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+
+ return oldChild;
+}
+
+Node Node::appendChild( const Node &newChild )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ NodeImpl *r = impl->appendChild( newChild.impl, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ if (!newChild.impl->closed()) newChild.impl->close();
+ return r;
+}
+
+bool Node::hasAttributes()
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ if (!impl->isElementNode()) return false;
+ ElementImpl* e = static_cast<ElementImpl*>(impl);
+ return e->attributes(true) && e->attributes(true)->length();
+}
+
+bool Node::hasChildNodes( )
+{
+ if (!impl) return false;
+ return impl->hasChildNodes();
+}
+
+Node Node::cloneNode( bool deep )
+{
+ if (!impl) return 0;
+ return impl->cloneNode( deep );
+}
+
+void Node::normalize ( )
+{
+ if (!impl) return;
+ impl->normalize();
+}
+
+bool Node::isSupported( const DOMString &feature,
+ const DOMString & /*version*/ ) const
+{
+ DOMString upFeature = feature.upper();
+ return (upFeature == "HTML" ||
+ upFeature == "XML" ||
+ upFeature == "CORE");
+}
+
+DOMString Node::namespaceURI( ) const
+{
+ if (!impl) return DOMString();
+ return impl->namespaceURI();
+}
+
+DOMString Node::prefix( ) const
+{
+ if (!impl) return DOMString();
+ return impl->prefix();
+}
+
+void Node::setPrefix(const DOMString &prefix )
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int exceptioncode = 0;
+ impl->setPrefix(prefix,exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+DOMString Node::localName( ) const
+{
+ if (!impl) return DOMString();
+ return impl->localName();
+}
+
+void Node::addEventListener(const DOMString &type,
+ EventListener *listener,
+ const bool useCapture)
+{
+ if (!impl) return;
+ if (listener)
+ impl->addEventListener(EventImpl::typeToId(type),listener,useCapture);
+}
+
+void Node::removeEventListener(const DOMString &type,
+ EventListener *listener,
+ bool useCapture)
+{
+ if (!impl) return;
+ impl->removeEventListener(EventImpl::typeToId(type),listener,useCapture);
+}
+
+bool Node::dispatchEvent(const Event &evt)
+{
+ if (!impl)
+ throw DOMException(DOMException::INVALID_STATE_ERR);
+
+ if (!evt.handle())
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ impl->dispatchEvent(evt.handle(),exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return !evt.handle()->defaultPrevented();
+}
+
+
+unsigned int Node::elementId() const
+{
+ if (!impl) return 0;
+ return impl->id();
+}
+
+unsigned long Node::index() const
+{
+ if (!impl) return 0;
+ return impl->nodeIndex();
+}
+
+TQString Node::toHTML()
+{
+ if (!impl) return TQString::null;
+ return impl->toString().string();
+}
+
+void Node::applyChanges()
+{
+ if (!impl) return;
+ impl->recalcStyle( NodeImpl::Inherit );
+}
+
+void Node::getCursor(int offset, int &_x, int &_y, int &height)
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ int dummy;
+ impl->getCaret(offset, false, _x, _y, dummy, height);
+}
+
+TQRect Node::getRect()
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+ return impl->getRect();
+}
+
+DOMString Node::textContent( ) const
+{
+ if(impl) return impl->textContent();
+ return DOMString();
+}
+
+void Node::setTextContent(const DOMString &content) const
+{
+ if (!impl) throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ impl->setTextContent( content, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+//-----------------------------------------------------------------------------
+
+NodeList::NodeList()
+{
+ impl = 0;
+}
+
+NodeList::NodeList(const NodeList &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+NodeList::NodeList(const NodeListImpl *i)
+{
+ impl = const_cast<NodeListImpl *>(i);
+ if(impl) impl->ref();
+}
+
+NodeList &NodeList::operator = (const NodeList &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+NodeList::~NodeList()
+{
+ if(impl) impl->deref();
+}
+
+Node NodeList::item( unsigned long index ) const
+{
+ if (!impl) return 0;
+ return impl->item(index);
+}
+
+unsigned long NodeList::length() const
+{
+ if (!impl) return 0;
+ return impl->length();
+}
diff --git a/tdehtml/dom/dom_node.h b/tdehtml/dom/dom_node.h
new file mode 100644
index 000000000..594aa5e3e
--- /dev/null
+++ b/tdehtml/dom/dom_node.h
@@ -0,0 +1,991 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 3 Core Specification (Recommendation)
+ * http://www.w3.org/TR/DOM-Level-3-Core/
+ * Copyright ©2004 W3C® (MIT, ERCIM, Keio), All Rights Reserved.
+ */
+#ifndef _DOM_Node_h_
+#define _DOM_Node_h_
+
+#include <tqstring.h>
+#include <tdelibs_export.h>
+
+class TQRect;
+
+namespace KJS {
+ class HTMLDocument;
+ class Window;
+}
+namespace DOM {
+
+class Node;
+class DOMString;
+class NodeImpl;
+class NamedNodeMapImpl;
+class EventListener;
+class Event;
+
+/**
+ * Objects implementing the \c NamedNodeMap interface are
+ * used to represent collections of nodes that can be accessed by
+ * name. Note that \c NamedNodeMap does not inherit from
+ * \c NodeList ; \c NamedNodeMap s are not
+ * maintained in any particular order. Objects contained in an object
+ * implementing \c NamedNodeMap may also be accessed by an
+ * ordinal index, but this is simply to allow convenient enumeration
+ * of the contents of a \c NamedNodeMap , and does not
+ * imply that the DOM specifies an order to these Nodes.
+ *
+ */
+class KHTML_EXPORT NamedNodeMap
+{
+public:
+ NamedNodeMap();
+ NamedNodeMap(const NamedNodeMap &other);
+
+ NamedNodeMap & operator = (const NamedNodeMap &other);
+
+ ~NamedNodeMap();
+
+ /**
+ * The number of nodes in the map. The range of valid child node
+ * indices is 0 to \c length-1 inclusive.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Retrieves a node specified by name.
+ *
+ * @param name Name of a node to retrieve.
+ *
+ * @return A \c Node (of any type) with the specified
+ * name, or \c null if the specified name did not
+ * identify any node in the map.
+ *
+ */
+ Node getNamedItem ( const DOMString &name ) const;
+
+ /**
+ * Adds a node using its \c nodeName attribute.
+ *
+ * As the \c nodeName attribute is used to derive the
+ * name which the node must be stored under, multiple nodes of
+ * certain types (those that have a "special" string value) cannot
+ * be stored as the names would clash. This is seen as preferable
+ * to allowing nodes to be aliased.
+ *
+ * @param arg A node to store in a named node map. The node will
+ * later be accessible using the value of the \c nodeName
+ * attribute of the node. If a node with that name is
+ * already present in the map, it is replaced by the new one.
+ *
+ * @return If the new \c Node replaces an existing
+ * node with the same name the previously existing \c Node
+ * is returned, otherwise \c null is returned.
+ *
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if \c arg was created
+ * from a different document than the one that created the
+ * \c NamedNodeMap .
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this
+ * \c NamedNodeMap is readonly.
+ *
+ * INUSE_ATTRIBUTE_ERR: Raised if \c arg is an
+ * \c Attr that is already an attribute of another
+ * \c Element object. The DOM user must explicitly clone
+ * \c Attr nodes to re-use them in other elements.
+ *
+ */
+ Node setNamedItem ( const Node &arg );
+
+ /**
+ * Removes a node specified by name. If the removed node is an
+ * \c Attr with a default value it is immediately
+ * replaced.
+ *
+ * @param name The name of a node to remove.
+ *
+ * @return The node removed from the map or \c null if
+ * no node with such a name exists.
+ *
+ * @exception DOMException
+ * NOT_FOUND_ERR: Raised if there is no node named \c name
+ * in the map.
+ *
+ */
+ Node removeNamedItem ( const DOMString &name );
+
+ /**
+ * Returns the \c index th item in the map. If
+ * \c index is greater than or equal to the number of nodes
+ * in the map, this returns \c null .
+ *
+ * @param index Index into the map.
+ *
+ * @return The node at the \c index th position in the
+ * \c NamedNodeMap , or \c null if that is
+ * not a valid index.
+ *
+ */
+ Node item ( unsigned long index ) const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Retrieves a node specified by local name and namespace URI. HTML-only
+ * DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the node to retrieve.
+ *
+ * @param localName The local name of the node to retrieve.
+ *
+ * @return A Node (of any type) with the specified local name and namespace
+ * URI, or null if they do not identify any node in this map.
+ */
+ Node getNamedItemNS( const DOMString &namespaceURI,
+ const DOMString &localName ) const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Adds a node using its namespaceURI and localName. If a node with that
+ * namespace URI and that local name is already present in this map, it is
+ * replaced by the new one.
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param arg A node to store in this map. The node will later be
+ * accessible using the value of its namespaceURI and localName attributes.
+ *
+ * @return If the new Node replaces an existing node the replaced Node is
+ * returned, otherwise null is returned.
+ *
+ * @exception DOMException
+ * WRONG_DOCUMENT_ERR: Raised if arg was created from a different document
+ * than the one that created this map.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ *
+ * INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an
+ * attribute of another Element object. The DOM user must explicitly clone
+ * Attr nodes to re-use them in other elements.
+ */
+ Node setNamedItemNS( const Node &arg );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Removes a node specified by local name and namespace URI. A removed
+ * attribute may be known to have a default value when this map contains
+ * the attributes attached to an element, as returned by the attributes
+ * attribute of the Node interface. If so, an attribute immediately appears
+ * containing the default value as well as the corresponding namespace URI,
+ * local name, and prefix when applicable.
+ * HTML-only DOM implementations do not need to implement this method.
+ *
+ * @param namespaceURI The namespace URI of the node to remove.
+ *
+ * @param localName The local name of the node to remove.
+ *
+ * @return The node removed from this map if a node with such a local name
+ * and namespace URI exists.
+ *
+ * @exception DOMException
+ * NOT_FOUND_ERR: Raised if there is no node with the specified
+ * namespaceURI and localName in this map.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ */
+ Node removeNamedItemNS( const DOMString &namespaceURI,
+ const DOMString &localName );
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ NamedNodeMapImpl *handle() const { return impl; }
+ bool isNull() const { return !impl; }
+
+protected:
+ NamedNodeMap( NamedNodeMapImpl *i);
+ NamedNodeMapImpl *impl;
+
+ friend class Node;
+ friend class DocumentType;
+ friend class NodeImpl;
+};
+
+class NamedNodeMap;
+class NodeList;
+class Document;
+class DOMString;
+class StyleSheet;
+
+class NodeImpl;
+
+/**
+ * The \c Node interface is the primary datatype for the
+ * entire Document Object Model. It represents a single node in the
+ * document tree. While all objects implementing the \c Node
+ * interface expose methods for dealing with children, not all
+ * objects implementing the \c Node interface may have
+ * children. For example, \c Text nodes may not have
+ * children, and adding children to such nodes results in a
+ * \c DOMException being raised.
+ *
+ * The attributes \c nodeName , \c nodeValue
+ * and \c attributes are included as a mechanism to get at
+ * node information without casting down to the specific derived
+ * interface. In cases where there is no obvious mapping of these
+ * attributes for a specific \c nodeType (e.g.,
+ * \c nodeValue for an Element or \c attributes for a
+ * Comment), this returns \c null . Note that the
+ * specialized interfaces may contain additional and more convenient
+ * mechanisms to get and set the relevant information.
+ *
+ */
+class KHTML_EXPORT Node
+{
+ friend class NamedNodeMap;
+ friend class NodeList;
+ friend class HTMLCollection;
+ friend class StyleSheet;
+
+public:
+ Node() : impl(0) {}
+ Node(const Node &other);
+
+ /**
+ * @internal
+ */
+ Node( NodeImpl *_impl);
+
+ Node & operator = (const Node &other);
+
+ bool operator == (const Node &other) const;
+
+ bool operator != (const Node &other) const;
+
+ virtual ~Node();
+ /**
+ * An integer indicating which type of node this is.
+ *
+ *
+ * <p>The values of \c nodeName, \c nodeValue,
+ * and \c attributes vary according to the node type as follows:
+ * <table border="1">
+ * <tr>
+ * <td></td>
+ * <td>nodeName</td>
+ * <td>nodeValue</td>
+ * <td>attributes</td>
+ * </tr>
+ * <tr>
+ * <td>Element</td>
+ * <td>tagName</td>
+ * <td>null</td>
+ * <td>NamedNodeMap</td>
+ * </tr>
+ * <tr>
+ * <td>Attr</td>
+ * <td>name of attribute</td>
+ * <td>value of attribute</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>Text</td>
+ * <td>#text</td>
+ * <td>content of the text node</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>CDATASection</td>
+ * <td>#cdata-section</td>
+ * <td>content of the CDATA Section</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>EntityReference</td>
+ * <td>name of entity referenced</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>Entity</td>
+ * <td>entity name</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>ProcessingInstruction</td>
+ * <td>target</td>
+ * <td>entire content excluding the target</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>Comment</td>
+ * <td>#comment</td>
+ * <td>content of the comment</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>Document</td>
+ * <td>#document</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>DocumentType</td>
+ * <td>document type name</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>DocumentFragment</td>
+ * <td>#document-fragment</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * <tr>
+ * <td>Notation</td>
+ * <td>notation name</td>
+ * <td>null</td>
+ * <td>null</td>
+ * </tr>
+ * </table>
+ * </p>
+ */
+ enum NodeType {
+ ELEMENT_NODE = 1,
+ ATTRIBUTE_NODE = 2,
+ TEXT_NODE = 3,
+ CDATA_SECTION_NODE = 4,
+ ENTITY_REFERENCE_NODE = 5,
+ ENTITY_NODE = 6,
+ PROCESSING_INSTRUCTION_NODE = 7,
+ COMMENT_NODE = 8,
+ DOCUMENT_NODE = 9,
+ DOCUMENT_TYPE_NODE = 10,
+ DOCUMENT_FRAGMENT_NODE = 11,
+ NOTATION_NODE = 12
+ };
+
+ /**
+ * The name of this node, depending on its type; see the table
+ * above.
+ *
+ */
+ DOMString nodeName() const;
+
+ /**
+ * The value of this node, depending on its type; see the table
+ * above.
+ *
+ * @exception DOMException
+ * DOMSTRING_SIZE_ERR: Raised when it would return more characters
+ * than fit in a \c DOMString variable on the
+ * implementation platform.
+ *
+ */
+ DOMString nodeValue() const;
+
+ /**
+ * see nodeValue
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ *
+ */
+ void setNodeValue( const DOMString & );
+
+ /**
+ * A code representing the type of the underlying object, as
+ * defined above.
+ *
+ */
+ unsigned short nodeType() const;
+
+ /**
+ * The parent of this node. All nodes, except \c Document
+ * , \c DocumentFragment , and \c Attr
+ * may have a parent. However, if a node has just been
+ * created and not yet added to the tree, or if it has been
+ * removed from the tree, this is \c null .
+ *
+ */
+ Node parentNode() const;
+
+ /**
+ * A \c NodeList that contains all children of this
+ * node. If there are no children, this is a \c NodeList
+ * containing no nodes. The content of the returned
+ * \c NodeList is &quot;live&quot; in the sense that, for
+ * instance, changes to the children of the node object that it
+ * was created from are immediately reflected in the nodes
+ * returned by the \c NodeList accessors; it is not a
+ * static snapshot of the content of the node. This is true for
+ * every \c NodeList , including the ones returned by
+ * the \c getElementsByTagName method.
+ *
+ */
+ NodeList childNodes() const;
+
+ /**
+ * The first child of this node. If there is no such node, this
+ * returns \c null .
+ *
+ */
+ Node firstChild() const;
+
+ /**
+ * The last child of this node. If there is no such node, this
+ * returns \c null .
+ *
+ */
+ Node lastChild() const;
+
+ /**
+ * The node immediately preceding this node. If there is no such
+ * node, this returns \c null .
+ *
+ */
+ Node previousSibling() const;
+
+ /**
+ * The node immediately following this node. If there is no such
+ * node, this returns \c null .
+ *
+ */
+ Node nextSibling() const;
+
+ /**
+ * A \c NamedNodeMap containing the attributes of this
+ * node (if it is an \c Element ) or \c null
+ * otherwise.
+ *
+ */
+ NamedNodeMap attributes() const;
+
+ /**
+ * The \c Document object associated with this node.
+ * This is also the \c Document object used to create
+ * new nodes. When this node is a \c Document this is
+ * \c null .
+ *
+ */
+ Document ownerDocument() const;
+
+ /**
+ * Inserts the node \c newChild before the existing
+ * child node \c refChild . If \c refChild
+ * is \c null , insert \c newChild at the
+ * end of the list of children.
+ *
+ * If \c newChild is a \c DocumentFragment
+ * object, all of its children are inserted, in the same
+ * order, before \c refChild . If the \c newChild
+ * is already in the tree, it is first removed.
+ *
+ * @param newChild The node to insert.
+ *
+ * @param refChild The reference node, i.e., the node before which
+ * the new node must be inserted.
+ *
+ * @return The node being inserted.
+ *
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
+ * does not allow children of the type of the \c newChild
+ * node, or if the node to insert is one of this node's
+ * ancestors.
+ *
+ * WRONG_DOCUMENT_ERR: Raised if \c newChild was
+ * created from a different document than the one that created
+ * this node.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NOT_FOUND_ERR: Raised if \c refChild is not a
+ * child of this node.
+ *
+ */
+ Node insertBefore ( const Node &newChild, const Node &refChild );
+
+ /**
+ * Replaces the child node \c oldChild with
+ * \c newChild in the list of children, and returns the
+ * \c oldChild node. If the \c newChild is
+ * already in the tree, it is first removed.
+ *
+ * @param newChild The new node to put in the child list.
+ *
+ * @param oldChild The node being replaced in the list.
+ *
+ * @return The node replaced.
+ *
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
+ * does not allow children of the type of the \c newChild
+ * node, or it the node to put in is one of this node's
+ * ancestors.
+ *
+ * WRONG_DOCUMENT_ERR: Raised if \c newChild was
+ * created from a different document than the one that created
+ * this node.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NOT_FOUND_ERR: Raised if \c oldChild is not a
+ * child of this node.
+ *
+ */
+ Node replaceChild ( const Node &newChild, const Node &oldChild );
+
+ /**
+ * Removes the child node indicated by \c oldChild
+ * from the list of children, and returns it.
+ *
+ * @param oldChild The node being removed.
+ *
+ * @return The node removed.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NOT_FOUND_ERR: Raised if \c oldChild is not a
+ * child of this node.
+ *
+ */
+ Node removeChild ( const Node &oldChild );
+
+ /**
+ * Adds the node \c newChild to the end of the list of
+ * children of this node. If the \c newChild is
+ * already in the tree, it is first removed.
+ *
+ * @param newChild The node to add.
+ *
+ * If it is a \c DocumentFragment object, the entire
+ * contents of the document fragment are moved into the child list
+ * of this node
+ *
+ * @return The node added.
+ *
+ * @exception DOMException
+ * HIERARCHY_REQUEST_ERR: Raised if this node is of a type that
+ * does not allow children of the type of the \c newChild
+ * node, or if the node to append is one of this node's
+ * ancestors.
+ *
+ * WRONG_DOCUMENT_ERR: Raised if \c newChild was
+ * created from a different document than the one that created
+ * this node.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ Node appendChild ( const Node &newChild );
+
+ /**
+ * This is a convenience method to allow easy determination of
+ * whether a node has any children.
+ *
+ * @return \c true if the node has any children,
+ * \c false if the node has no children.
+ *
+ */
+ bool hasChildNodes ( );
+
+ /**
+ * Returns a duplicate of this node, i.e., serves as a generic
+ * copy constructor for nodes. The duplicate node has no parent (
+ * \c parentNode returns \c null .).
+ *
+ * Cloning an \c Element copies all attributes and
+ * their values, including those generated by the XML processor to
+ * represent defaulted attributes, but this method does not copy
+ * any text it contains unless it is a deep clone, since the text
+ * is contained in a child \c Text node. Cloning any
+ * other type of node simply returns a copy of this node.
+ *
+ * @param deep If \c true , recursively clone the
+ * subtree under the specified node; if \c false ,
+ * clone only the node itself (and its attributes, if it is an
+ * \c Element ).
+ *
+ * @return The duplicate node.
+ *
+ */
+ Node cloneNode ( bool deep );
+
+ /**
+ * Modified in DOM Level 2
+ *
+ * Puts all Text nodes in the full depth of the sub-tree underneath this
+ * Node, including attribute nodes, into a "normal" form where only
+ * structure (e.g., elements, comments, processing instructions, CDATA
+ * sections, and entity references) separates Text nodes, i.e., there are
+ * neither adjacent Text nodes nor empty Text nodes. This can be used to
+ * ensure that the DOM view of a document is the same as if it were saved
+ * and re-loaded, and is useful when operations (such as XPointer
+ * [XPointer] lookups) that depend on a particular document tree structure
+ * are to be used.
+ *
+ * Note: In cases where the document contains CDATASections, the normalize
+ * operation alone may not be sufficient, since XPointers do not
+ * differentiate between Text nodes and CDATASection nodes.
+ */
+ void normalize ( );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Tests whether the DOM implementation implements a specific feature and
+ * that feature is supported by this node.
+ *
+ * @param feature The name of the feature to test. This is the same name
+ * which can be passed to the method hasFeature on DOMImplementation.
+ *
+ * @param version This is the version number of the feature to test. In
+ * Level 2, version 1, this is the string "2.0". If the version is not
+ * specified, supporting any version of the feature will cause the method
+ * to return true.
+ *
+ * @return Returns true if the specified feature is supported on this node,
+ * false otherwise.
+ */
+ bool isSupported( const DOMString &feature,
+ const DOMString &version ) const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The namespace URI of this node, or null if it is unspecified.
+ * This is not a computed value that is the result of a namespace lookup
+ * based on an examination of the namespace declarations in scope. It is
+ * merely the namespace URI given at creation time. For nodes of any type
+ * other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM
+ * Level 1 method, such as createElement from the Document interface, this
+ * is always null.
+ *
+ * Note: Per the Namespaces in XML Specification [Namespaces] an attribute
+ * does not inherit its namespace from the element it is attached to. If an
+ * attribute is not explicitly given a namespace, it simply has no
+ * namespace.
+ */
+ DOMString namespaceURI( ) const;
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * The namespace prefix of this node, or null if it is unspecified.
+ * Note that setting this attribute, when permitted, changes the nodeName
+ * attribute, which holds the qualified name, as well as the tagName and
+ * name attributes of the Element and Attr interfaces, when applicable.
+ * Note also that changing the prefix of an attribute that is known to have
+ * a default value, does not make a new attribute with the default value
+ * and the original prefix appear, since the namespaceURI and localName do
+ * not change.
+ * For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and
+ * nodes created with a DOM Level 1 method, such as createElement from the
+ * Document interface, this is always null.
+ */
+ DOMString prefix( ) const;
+
+ /**
+ * see prefix
+ *
+ * @exception DOMException
+ * INVALID_CHARACTER_ERR: Raised if the specified prefix contains an
+ * illegal character.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * NAMESPACE_ERR: Raised if the specified prefix is malformed, if the
+ * namespaceURI of this node is null, if the specified prefix is "xml" and
+ * the namespaceURI of this node is different from
+ * "http://www.w3.org/XML/1998/namespace", if this node is an attribute and
+ * the specified prefix is "xmlns" and the namespaceURI of this node is
+ * different from "http://www.w3.org/2000/xmlns/", or if this node is an
+ * attribute and the qualifiedName of this node is "xmlns" [Namespaces].
+ */
+ void setPrefix(const DOMString &prefix );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Returns the local part of the qualified name of this node.
+ * For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and
+ * nodes created with a DOM Level 1 method, such as createElement from the
+ * Document interface, this is always null.
+ */
+ DOMString localName( ) const;
+
+ /**
+ * Returns whether this node (if it is an element) has any attributes.
+ * @return a boolean. True if this node has any attributes, false otherwise.
+ * Introduced in DOM Level 2
+ */
+ bool hasAttributes ( );
+
+ /**
+ * Introduced in DOM Level 3
+ *
+ * This attribute returns the text content of this node and its descendants.
+ * On getting, no serialization is performed, the returned string does not contain any markup.
+ *
+ * @since 3.5.7
+ */
+ DOMString textContent( ) const;
+
+ /**
+ * Introduced in DOM Level 3
+ *
+ * @see textContent
+ *
+ * On setting, any possible children this node may have are removed and, if the new
+ * string is not empty or null, replaced by a single Text node containing the string this attribute is set to.
+ * No parsing is performed, the input string is taken as pure textual content.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ * Note: KHTML will also raise this if setContent is called on things
+ * that do not have child nodes.
+ *
+ * @since 3.5.7
+ */
+ void setTextContent(const DOMString &content) const;
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the EventTarget interface
+ *
+ * This method allows the registration of event listeners on the event
+ * target. If an EventListener is added to an EventTarget while it is
+ * processing an event, it will not be triggered by the current actions but
+ * may be triggered during a later stage of event flow, such as the
+ * bubbling phase.
+ *
+ * If multiple identical EventListeners are registered on the same
+ * EventTarget with the same parameters the duplicate instances are
+ * discarded. They do not cause the EventListener to be called twice and
+ * since they are discarded they do not need to be removed with the
+ * removeEventListener method. Parameters
+ *
+ * @param type The event type for which the user is registering
+ *
+ * @param listener The listener parameter takes an interface implemented by
+ * the user which contains the methods to be called when the event occurs.
+ *
+ * @param useCapture If true, useCapture indicates that the user wishes to
+ * initiate capture. After initiating capture, all events of the specified
+ * type will be dispatched to the registered EventListener before being
+ * dispatched to any EventTargets beneath them in the tree. Events which
+ * are bubbling upward through the tree will not trigger an EventListener
+ * designated to use capture.
+ */
+ void addEventListener(const DOMString &type,
+ EventListener *listener,
+ const bool useCapture);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the EventTarget interface
+ *
+ * This method allows the removal of event listeners from the event target.
+ * If an EventListener is removed from an EventTarget while it is
+ * processing an event, it will not be triggered by the current actions.
+ *
+ * EventListeners can never be invoked after being removed.
+ *
+ * Calling removeEventListener with arguments which do not identify any
+ * currently registered EventListener on the EventTarget has no effect.
+ *
+ * @param type Specifies the event type of the EventListener being removed.
+ *
+ * @param listener The EventListener parameter indicates the EventListener
+ * to be removed.
+ *
+ * @param useCapture Specifies whether the EventListener being removed was
+ * registered as a capturing listener or not. If a listener was registered
+ * twice, one with capture and one without, each must be removed
+ * separately. Removal of a capturing listener does not affect a
+ * non-capturing version of the same listener, and vice versa.
+ */
+
+ void removeEventListener(const DOMString &type,
+ EventListener *listener,
+ bool useCapture);
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the EventTarget interface
+ *
+ * This method allows the dispatch of events into the implementations event
+ * model. Events dispatched in this manner will have the same capturing and
+ * bubbling behavior as events dispatched directly by the implementation.
+ * The target of the event is the EventTarget on which dispatchEvent is
+ * called.
+ *
+ * @param evt Specifies the event type, behavior, and contextual
+ * information to be used in processing the event.
+ *
+ * @return The return value of dispatchEvent indicates whether any of the
+ * listeners which handled the event called preventDefault. If
+ * preventDefault was called the value is false, else the value is true.
+ *
+ * @exception EventException
+ * UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type was not specified
+ * by initializing the event before dispatchEvent was called. Specification
+ * of the Event's type as null or an empty string will also trigger this
+ * exception.
+ */
+ bool dispatchEvent(const Event &evt);
+
+
+
+ /**
+ * @internal
+ * not part of the DOM.
+ * @returns the element id, in case this is an element, 0 otherwise
+ */
+ TQ_UINT32 elementId() const;
+
+ /**
+ * tests if this Node is 0. Useful especially, if casting to a derived
+ * class:
+ *
+ * \code
+ * Node n = .....;
+ * // try to convert into an Element:
+ * Element e = n;
+ * if( e.isNull() )
+ * kdDebug(300) << "node isn't an element node" << endl;
+ * \endcode
+ */
+ bool isNull() const { return !impl; }
+
+ /**
+ * @internal handle to the implementation object
+ */
+ NodeImpl *handle() const { return impl; }
+
+ /**
+ * @internal returns the index of a node
+ */
+ unsigned long index() const;
+ TQString toHTML() KDE_DEPRECATED;
+ void applyChanges();
+ /**
+ * @deprecated without substitution since 3.2
+ */
+ void getCursor(int offset, int &_x, int &_y, int &height) KDE_DEPRECATED;
+ /**
+ * not part of the DOM.
+ * @returns the exact coordinates and size of this element.
+ */
+ TQRect getRect();
+
+protected:
+ NodeImpl *impl;
+};
+
+
+class NodeListImpl;
+
+/**
+ * The \c NodeList interface provides the abstraction of
+ * an ordered collection of nodes, without defining or constraining
+ * how this collection is implemented.
+ *
+ * The items in the \c NodeList are accessible via an
+ * integral index, starting from 0.
+ *
+ */
+class KHTML_EXPORT NodeList
+{
+ friend class Element;
+ friend class Node;
+ friend class Document;
+ friend class HTMLDocument;
+ friend class KJS::HTMLDocument;
+ friend class KJS::Window;
+
+public:
+ NodeList();
+ NodeList(const NodeList &other);
+
+ NodeList & operator = (const NodeList &other);
+
+ ~NodeList();
+
+ /**
+ * The number of nodes in the list. The range of valid child node
+ * indices is 0 to \c length-1 inclusive.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Returns the \c index th item in the collection. If
+ * \c index is greater than or equal to the number of
+ * nodes in the list, this returns \c null .
+ *
+ * @param index Index into the collection.
+ *
+ * @return The node at the \c index th position in the
+ * \c NodeList , or \c null if that is not
+ * a valid index.
+ *
+ */
+ Node item ( unsigned long index ) const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ NodeListImpl *handle() const { return impl; }
+ bool isNull() const { return !impl; }
+
+protected:
+ NodeList(const NodeListImpl *i);
+ NodeListImpl *impl;
+};
+
+
+
+/**
+ * A DOMTimeStamp represents a number of milliseconds.
+ *
+ */
+typedef unsigned long long DOMTimeStamp;
+
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_string.cpp b/tdehtml/dom/dom_string.cpp
new file mode 100644
index 000000000..14bdc2613
--- /dev/null
+++ b/tdehtml/dom/dom_string.cpp
@@ -0,0 +1,300 @@
+/**
+ * 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 "dom/dom_string.h"
+#include "xml/dom_stringimpl.h"
+
+
+using namespace DOM;
+
+
+DOMString::DOMString(const TQChar *str, uint len)
+{
+ impl = new DOMStringImpl( str, len );
+ impl->ref();
+}
+
+DOMString::DOMString(const TQString &str)
+{
+ if (str.isNull()) {
+ impl = 0;
+ return;
+ }
+
+ impl = new DOMStringImpl( str.unicode(), str.length() );
+ impl->ref();
+}
+
+DOMString::DOMString(const char *str)
+{
+ if (!str) {
+ impl = 0;
+ return;
+ }
+
+ impl = new DOMStringImpl( str );
+ impl->ref();
+}
+
+DOMString::DOMString(DOMStringImpl *i)
+{
+ impl = i;
+ if(impl) impl->ref();
+}
+
+DOMString::DOMString(const DOMString &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+DOMString::~DOMString()
+{
+ if(impl) impl->deref();
+}
+
+DOMString &DOMString::operator =(const DOMString &other)
+{
+ if ( impl != other.impl ) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+DOMString &DOMString::operator += (const DOMString &str)
+{
+ if(!impl)
+ {
+ // ### FIXME!!!
+ impl = str.impl;
+ if (impl)
+ impl->ref();
+ return *this;
+ }
+ if(str.impl)
+ {
+ DOMStringImpl *i = impl->copy();
+ impl->deref();
+ impl = i;
+ impl->ref();
+ impl->append(str.impl);
+ }
+ return *this;
+}
+
+DOMString DOMString::operator + (const DOMString &str)
+{
+ if(!impl) return str.copy();
+ if(str.impl)
+ {
+ DOMString s = copy();
+ s += str;
+ return s;
+ }
+
+ return copy();
+}
+
+void DOMString::insert(DOMString str, uint pos)
+{
+ if(!impl)
+ {
+ impl = str.impl->copy();
+ impl->ref();
+ }
+ else
+ impl->insert(str.impl, pos);
+}
+
+
+const TQChar &DOMString::operator [](unsigned int i) const
+{
+ static const TQChar nullChar = 0;
+
+ if(!impl || i >= impl->l ) return nullChar;
+
+ return *(impl->s+i);
+}
+
+int DOMString::find(const TQChar c, int start) const
+{
+ unsigned int l = start;
+ if(!impl || l >= impl->l ) return -1;
+ while( l < impl->l )
+ {
+ if( *(impl->s+l) == c ) return l;
+ l++;
+ }
+ return -1;
+}
+
+uint DOMString::length() const
+{
+ if(!impl) return 0;
+ return impl->l;
+}
+
+void DOMString::truncate( unsigned int len )
+{
+ if(impl) impl->truncate(len);
+}
+
+void DOMString::remove(unsigned int pos, int len)
+{
+ if(impl) impl->remove(pos, len);
+}
+
+DOMString DOMString::split(unsigned int pos)
+{
+ if(!impl) return DOMString();
+ return impl->split(pos);
+}
+
+DOMString DOMString::lower() const
+{
+ if(!impl) return DOMString();
+ return impl->lower();
+}
+
+DOMString DOMString::upper() const
+{
+ if(!impl) return DOMString();
+ return impl->upper();
+}
+
+bool DOMString::percentage(int &_percentage) const
+{
+ if(!impl || !impl->l) return false;
+
+ if ( *(impl->s+impl->l-1) != TQChar('%'))
+ return false;
+
+ _percentage = TQConstString(impl->s, impl->l-1).string().toInt();
+ return true;
+}
+
+TQChar *DOMString::unicode() const
+{
+ if(!impl) return 0;
+ return impl->unicode();
+}
+
+TQString DOMString::string() const
+{
+ if(!impl) return TQString::null;
+
+ return impl->string();
+}
+
+int DOMString::toInt() const
+{
+ if(!impl) return 0;
+
+ return impl->toInt();
+}
+
+DOMString DOMString::copy() const
+{
+ if(!impl) return DOMString();
+ return impl->copy();
+}
+
+// ------------------------------------------------------------------------
+
+bool DOM::strcasecmp( const DOMString &as, const DOMString &bs )
+{
+ if ( as.length() != bs.length() ) return true;
+
+ const TQChar *a = as.unicode();
+ const TQChar *b = bs.unicode();
+ if ( a == b ) return false;
+ if ( !( a && b ) ) return true;
+ int l = as.length();
+ while ( l-- ) {
+ if ( *a != *b && a->lower() != b->lower() ) return true;
+ a++,b++;
+ }
+ return false;
+}
+
+bool DOM::strcasecmp( const DOMString &as, const char* bs )
+{
+ const TQChar *a = as.unicode();
+ int l = as.length();
+ if ( !bs ) return ( l != 0 );
+ while ( l-- ) {
+ if ( a->latin1() != *bs ) {
+ char cc = ( ( *bs >= 'A' ) && ( *bs <= 'Z' ) ) ? ( ( *bs ) + 'a' - 'A' ) : ( *bs );
+ if ( a->lower().latin1() != cc ) return true;
+ }
+ a++, bs++;
+ }
+ return ( *bs != '\0' );
+}
+
+bool DOMString::isEmpty() const
+{
+ return (!impl || impl->l == 0);
+}
+
+//-----------------------------------------------------------------------------
+
+bool DOM::operator==( const DOMString &a, const DOMString &b )
+{
+ unsigned int l = a.length();
+
+ if( l != b.length() ) return false;
+
+ if(!memcmp(a.unicode(), b.unicode(), l*sizeof(TQChar)))
+ return true;
+ return false;
+}
+
+bool DOM::operator==( const DOMString &a, const TQString &b )
+{
+ unsigned int l = a.length();
+
+ if( l != b.length() ) return false;
+
+ if(!memcmp(a.unicode(), b.unicode(), l*sizeof(TQChar)))
+ return true;
+ return false;
+}
+
+bool DOM::operator==( const DOMString &a, const char *b )
+{
+ DOMStringImpl* aimpl = a.impl;
+ if ( !b ) return !aimpl;
+
+ if ( aimpl ) {
+ int alen = aimpl->l;
+ const TQChar *aptr = aimpl->s;
+ while ( alen-- ) {
+ unsigned char c = *b++;
+ if ( !c || ( *aptr++ ).unicode() != c )
+ return false;
+ }
+ }
+
+ return !*b;
+}
diff --git a/tdehtml/dom/dom_string.h b/tdehtml/dom/dom_string.h
new file mode 100644
index 000000000..3d4706b5a
--- /dev/null
+++ b/tdehtml/dom/dom_string.h
@@ -0,0 +1,144 @@
+/*
+ * 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_DOMString_h_
+#define _DOM_DOMString_h_
+
+#include <kdebug.h>
+#include <tqstring.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class DOMStringImpl;
+
+/**
+ * This class implements the basic string we use in the DOM. We do not use
+ * TQString for 2 reasons: Memory overhead, and the missing explicit sharing
+ * of strings we need for the DOM.
+ *
+ * All DOMStrings are explicitly shared (they behave like pointers), meaning
+ * that modifications to one instance will also modify all others. If you
+ * wish to get a DOMString that is independent, use copy().
+ */
+class KHTML_EXPORT DOMString
+{
+ friend class CharacterDataImpl;
+ friend KHTML_EXPORT bool operator==( const DOMString &a, const char *b );
+public:
+ /**
+ * default constructor. Gives an empty DOMString
+ */
+ DOMString() : impl(0) {}
+
+ DOMString(const TQChar *str, uint len);
+ DOMString(const TQString &);
+ DOMString(const char *str);
+ DOMString(DOMStringImpl *i);
+
+ virtual ~DOMString();
+
+ // assign and copy
+ DOMString(const DOMString &str);
+ DOMString &operator =(const DOMString &str);
+
+ /**
+ * append str to this string
+ */
+ DOMString &operator += (const DOMString &str);
+ /**
+ * add two DOMString's
+ */
+ DOMString operator + (const DOMString &str);
+
+ void insert(DOMString str, uint pos);
+
+ /**
+ * The character at position i of the DOMString. If i >= length(), the
+ * character returned will be 0.
+ */
+ const TQChar &operator [](unsigned int i) const;
+
+ int find(const TQChar c, int start = 0) const;
+
+ uint length() const;
+ void truncate( unsigned int len );
+ void remove(unsigned int pos, int len=1);
+ /**
+ * Splits the string into two. The original string gets truncated to pos, and the rest is returned.
+ */
+ DOMString split(unsigned int pos);
+
+ /**
+ * Returns a lowercase version of the string
+ */
+ DOMString lower() const;
+ /**
+ * Returns an uppercase version of the string
+ */
+ DOMString upper() const;
+
+ TQChar *unicode() const;
+ TQString string() const;
+
+ int toInt() const;
+ bool percentage(int &_percentage) const;
+
+ DOMString copy() const;
+
+ bool isNull() const { return (impl == 0); }
+ bool isEmpty() const;
+
+ /**
+ * @internal get a handle to the imlementation of the DOMString
+ * Use at own risk!!!
+ */
+ DOMStringImpl *implementation() const { return impl; }
+
+protected:
+ DOMStringImpl *impl;
+};
+
+#ifndef NDEBUG
+inline kdbgstream &operator<<(kdbgstream &stream, const DOMString &string) {
+ return (stream << string.string());
+}
+#else
+inline kndbgstream &operator<<(kndbgstream &stream, const DOMString &) {
+ return stream;
+}
+#endif
+
+KHTML_EXPORT bool operator==( const DOMString &a, const DOMString &b );
+KHTML_EXPORT bool operator==( const DOMString &a, const TQString &b );
+KHTML_EXPORT bool operator==( const DOMString &a, const char *b );
+inline bool operator!=( const DOMString &a, const DOMString &b ) { return !(a==b); }
+inline bool operator!=( const DOMString &a, const TQString &b ) { return !(a==b); }
+inline bool operator!=( const DOMString &a, const char *b ) { return !(a==b); }
+inline bool strcmp( const DOMString &a, const DOMString &b ) { return a != b; }
+
+// returns false when equal, true otherwise (ignoring case)
+KHTML_EXPORT bool strcasecmp( const DOMString &a, const DOMString &b );
+KHTML_EXPORT bool strcasecmp( const DOMString& a, const char* b );
+
+}
+#endif
diff --git a/tdehtml/dom/dom_text.cpp b/tdehtml/dom/dom_text.cpp
new file mode 100644
index 000000000..af4584410
--- /dev/null
+++ b/tdehtml/dom/dom_text.cpp
@@ -0,0 +1,237 @@
+/**
+ * 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 "dom/dom_exception.h"
+#include "dom/dom_text.h"
+#include "xml/dom_textimpl.h"
+
+using namespace DOM;
+
+CharacterData::CharacterData() : Node()
+{
+}
+
+CharacterData::CharacterData(const CharacterData &other) : Node(other)
+{
+}
+
+CharacterData &CharacterData::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle ||
+ ( ohandle->nodeType() != CDATA_SECTION_NODE &&
+ ohandle->nodeType() != TEXT_NODE &&
+ ohandle->nodeType() != COMMENT_NODE )) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+CharacterData &CharacterData::operator = (const CharacterData &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+CharacterData::~CharacterData()
+{
+}
+
+DOMString CharacterData::data() const
+{
+ if(!impl) return DOMString();
+ return ((CharacterDataImpl *)impl)->data();
+}
+
+void CharacterData::setData( const DOMString &str )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((CharacterDataImpl *)impl)->setData(str, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return;
+}
+
+unsigned long CharacterData::length() const
+{
+ if ( impl )
+ return ((CharacterDataImpl *)impl)->length();
+ return 0;
+}
+
+DOMString CharacterData::substringData( const unsigned long offset, const unsigned long count )
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ DOMString str = ((CharacterDataImpl *)impl)->substringData(offset, count, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return str;
+}
+
+void CharacterData::appendData( const DOMString &arg )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((CharacterDataImpl *)impl)->appendData(arg, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void CharacterData::insertData( const unsigned long offset, const DOMString &arg )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((CharacterDataImpl *)impl)->insertData(offset, arg, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void CharacterData::deleteData( const unsigned long offset, const unsigned long count )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((CharacterDataImpl *)impl)->deleteData(offset, count, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void CharacterData::replaceData( const unsigned long offset, const unsigned long count, const DOMString &arg )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((CharacterDataImpl *)impl)->replaceData(offset, count, arg, exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+CharacterData::CharacterData(CharacterDataImpl *i) : Node(i)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+Comment::Comment() : CharacterData()
+{
+}
+
+Comment::Comment(const Comment &other) : CharacterData(other)
+{
+}
+
+Comment &Comment::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != COMMENT_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Comment &Comment::operator = (const Comment &other)
+{
+ CharacterData::operator =(other);
+ return *this;
+}
+
+Comment::~Comment()
+{
+}
+
+Comment::Comment(CommentImpl *i) : CharacterData(i)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+Text::Text()
+{
+}
+
+Text::Text(const Text &other) : CharacterData(other)
+{
+}
+
+Text &Text::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle ||
+ (ohandle->nodeType() != TEXT_NODE &&
+ ohandle->nodeType() != CDATA_SECTION_NODE)) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Text &Text::operator = (const Text &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Text::~Text()
+{
+}
+
+Text Text::splitText( const unsigned long offset )
+{
+ if (!impl)
+ return 0; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ TextImpl *newText = static_cast<TextImpl *>(impl)->splitText(offset, exceptioncode );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return newText;
+}
+
+Text::Text(TextImpl *i) : CharacterData(i)
+{
+}
diff --git a/tdehtml/dom/dom_text.h b/tdehtml/dom/dom_text.h
new file mode 100644
index 000000000..c6f92fb1d
--- /dev/null
+++ b/tdehtml/dom/dom_text.h
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef _DOM_CharacterData_h_
+#define _DOM_CharacterData_h_
+
+#include <dom/dom_node.h>
+
+namespace DOM {
+
+class DOMString;
+class CharacterDataImpl;
+
+/**
+ * The \c CharacterData interface extends Node with a set
+ * of attributes and methods for accessing character data in the DOM.
+ * For clarity this set is defined here rather than on each object
+ * that uses these attributes and methods. No DOM objects correspond
+ * directly to \c CharacterData , though \c Text
+ * and others do inherit the interface from it. All
+ * <code>offset</code>s in this interface start from 0.
+ *
+ */
+class KHTML_EXPORT CharacterData : public Node
+{
+ friend class CharacterDataImpl;
+
+public:
+ CharacterData();
+ CharacterData(const CharacterData &other);
+ CharacterData(const Node &other) : Node()
+ {(*this)=other;}
+
+ CharacterData & operator = (const Node &other);
+ CharacterData & operator = (const CharacterData &other);
+
+ ~CharacterData();
+
+ /**
+ * The character data of the node that implements this interface.
+ * The DOM implementation may not put arbitrary limits on the
+ * amount of data that may be stored in a \c CharacterData
+ * node. However, implementation limits may mean that the
+ * entirety of a node's data may not fit into a single
+ * \c DOMString . In such cases, the user may call
+ * \c substringData to retrieve the data in appropriately
+ * sized pieces.
+ *
+ * @exception DOMException
+ * DOMSTRING_SIZE_ERR: Raised when it would return more characters
+ * than fit in a \c DOMString variable on the
+ * implementation platform.
+ *
+ */
+ DOMString data() const;
+
+ /**
+ * see data
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ *
+ */
+ void setData( const DOMString & );
+
+ /**
+ * The number of characters that are available through \c data
+ * and the \c substringData method below. This
+ * may have the value zero, i.e., \c CharacterData
+ * nodes may be empty.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * Extracts a range of data from the node.
+ *
+ * @param offset Start offset of substring to extract.
+ *
+ * @param count The number of characters to extract.
+ *
+ * @return The specified substring. If the sum of \c offset
+ * and \c count exceeds the \c length
+ * , then all characters to the end of the data are
+ * returned.
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or
+ * greater than the number of characters in \c data ,
+ * or if the specified \c count is negative.
+ *
+ * DOMSTRING_SIZE_ERR: Raised if the specified range of text does
+ * not fit into a \c DOMString .
+ *
+ */
+ DOMString substringData ( const unsigned long offset, const unsigned long count );
+
+ /**
+ * Append the string to the end of the character data of the node.
+ * Upon success, \c data provides access to the
+ * concatenation of \c data and the \c DOMString
+ * specified.
+ *
+ * @param arg The \c DOMString to append.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void appendData ( const DOMString &arg );
+
+ /**
+ * Insert a string at the specified character offset.
+ *
+ * @param offset The character offset at which to insert.
+ *
+ * @param arg The \c DOMString to insert.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or
+ * greater than the number of characters in \c data .
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void insertData ( const unsigned long offset, const DOMString &arg );
+
+ /**
+ * Remove a range of characters from the node. Upon success,
+ * \c data and \c length reflect the
+ * change.
+ *
+ * @param offset The offset from which to remove characters.
+ *
+ * @param count The number of characters to delete. If the sum of
+ * \c offset and \c count exceeds
+ * \c length then all characters from \c offset
+ * to the end of the data are deleted.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or
+ * greater than the number of characters in \c data ,
+ * or if the specified \c count is negative.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void deleteData ( const unsigned long offset, const unsigned long count );
+
+ /**
+ * Replace the characters starting at the specified character
+ * offset with the specified string.
+ *
+ * @param offset The offset from which to start replacing.
+ *
+ * @param count The number of characters to replace. If the sum of
+ * \c offset and \c count exceeds
+ * \c length , then all characters to the end of the data are
+ * replaced (i.e., the effect is the same as a \c remove
+ * method call with the same range, followed by an
+ * \c append method invocation).
+ *
+ * @param arg The \c DOMString with which the range
+ * must be replaced.
+ *
+ * @return
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or
+ * greater than the number of characters in \c data ,
+ * or if the specified \c count is negative.
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ void replaceData ( const unsigned long offset, const unsigned long count, const DOMString &arg );
+
+protected:
+ CharacterData(CharacterDataImpl *i);
+};
+
+
+class CommentImpl;
+
+/**
+ * This represents the content of a comment, i.e., all the characters
+ * between the starting ' \c &lt;!-- ' and ending '
+ * \c --&gt; '. Note that this is the definition of a comment in
+ * XML, and, in practice, HTML, although some HTML tools may implement
+ * the full SGML comment structure.
+ *
+ */
+class KHTML_EXPORT Comment : public CharacterData
+{
+ friend class Document;
+ friend class TextImpl;
+
+public:
+ Comment();
+ Comment(const Comment &other);
+ Comment(const Node &other) : CharacterData()
+ {(*this)=other;}
+
+ Comment & operator = (const Node &other);
+ Comment & operator = (const Comment &other);
+
+ ~Comment();
+
+protected:
+ Comment(CommentImpl *i);
+};
+
+class TextImpl;
+
+/**
+ * The \c Text interface represents the textual content
+ * (termed <a href="&xml-spec;#syntax"> character data </a> in XML) of
+ * an \c Element or \c Attr . If there is no
+ * markup inside an element's content, the text is contained in a
+ * single object implementing the \c Text interface that
+ * is the only child of the element. If there is markup, it is parsed
+ * into a list of elements and \c Text nodes that form the
+ * list of children of the element.
+ *
+ * When a document is first made available via the DOM, there is only
+ * one \c Text node for each block of text. Users may
+ * create adjacent \c Text nodes that represent the
+ * contents of a given element without any intervening markup, but
+ * should be aware that there is no way to represent the separations
+ * between these nodes in XML or HTML, so they will not (in general)
+ * persist between DOM editing sessions. The \c normalize()
+ * method on \c Element merges any such adjacent
+ * \c Text objects into a single node for each block of
+ * text; this is recommended before employing operations that depend
+ * on a particular document structure, such as navigation with
+ * \c XPointers.
+ *
+ */
+class KHTML_EXPORT Text : public CharacterData
+{
+ friend class Document;
+ friend class TextImpl;
+
+public:
+ Text();
+ Text(const Text &other);
+ Text(const Node &other) : CharacterData()
+ {(*this)=other;}
+
+ Text & operator = (const Node &other);
+ Text & operator = (const Text &other);
+
+ ~Text();
+
+ /**
+ * Breaks this \c Text node into two Text nodes at the
+ * specified offset, keeping both in the tree as siblings. This
+ * node then only contains all the content up to the \c offset
+ * point. And a new \c Text node, which is
+ * inserted as the next sibling of this node, contains all the
+ * content at and after the \c offset point.
+ *
+ * @param offset The offset at which to split, starting from 0.
+ *
+ * @return The new \c Text node.
+ *
+ * @exception DOMException
+ * INDEX_SIZE_ERR: Raised if the specified offset is negative or
+ * greater than the number of characters in \c data .
+ *
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ */
+ Text splitText ( const unsigned long offset );
+
+protected:
+ Text(TextImpl *i);
+
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/dom_xml.cpp b/tdehtml/dom/dom_xml.cpp
new file mode 100644
index 000000000..524bbe218
--- /dev/null
+++ b/tdehtml/dom/dom_xml.cpp
@@ -0,0 +1,293 @@
+/**
+ * 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 "dom/dom_xml.h"
+#include "dom/dom_exception.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_xmlimpl.h"
+
+using namespace DOM;
+
+CDATASection::CDATASection()
+{
+}
+
+CDATASection::CDATASection(const CDATASection &) : Text()
+{
+}
+
+CDATASection &CDATASection::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != CDATA_SECTION_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+CDATASection &CDATASection::operator = (const CDATASection &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+CDATASection::~CDATASection()
+{
+}
+
+CDATASection::CDATASection(CDATASectionImpl *i) : Text(i)
+{
+}
+
+// ----------------------------------------------------------------------------
+Entity::Entity()
+{
+}
+
+Entity::Entity(const Entity &) : Node()
+{
+}
+
+Entity &Entity::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != ENTITY_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Entity &Entity::operator = (const Entity &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Entity::~Entity()
+{
+}
+
+DOMString Entity::publicId() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((EntityImpl*)impl)->publicId();
+}
+
+DOMString Entity::systemId() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((EntityImpl*)impl)->systemId();
+}
+
+DOMString Entity::notationName() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((EntityImpl*)impl)->notationName();
+}
+
+Entity::Entity(EntityImpl *i) : Node(i)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+EntityReference::EntityReference()
+{
+}
+
+EntityReference::EntityReference(const EntityReference &) : Node()
+{
+}
+
+EntityReference &EntityReference::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != ENTITY_REFERENCE_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+EntityReference &EntityReference::operator = (const EntityReference &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+EntityReference::~EntityReference()
+{
+}
+
+EntityReference::EntityReference(EntityReferenceImpl *i) : Node(i)
+{
+}
+
+// ----------------------------------------------------------------------------
+
+Notation::Notation()
+{
+}
+
+Notation::Notation(const Notation &) : Node()
+{
+}
+
+Notation &Notation::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != NOTATION_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+Notation &Notation::operator = (const Notation &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+Notation::~Notation()
+{
+}
+
+DOMString Notation::publicId() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((NotationImpl*)impl)->publicId();
+}
+
+DOMString Notation::systemId() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((NotationImpl*)impl)->systemId();
+}
+
+Notation::Notation(NotationImpl *i) : Node(i)
+{
+}
+
+
+// ----------------------------------------------------------------------------
+
+ProcessingInstruction::ProcessingInstruction()
+{
+}
+
+ProcessingInstruction::ProcessingInstruction(const ProcessingInstruction &)
+ : Node()
+{
+}
+
+ProcessingInstruction &ProcessingInstruction::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if ( impl != ohandle ) {
+ if (!ohandle || ohandle->nodeType() != PROCESSING_INSTRUCTION_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+ProcessingInstruction &ProcessingInstruction::operator = (const ProcessingInstruction &other)
+{
+ Node::operator =(other);
+ return *this;
+}
+
+ProcessingInstruction::~ProcessingInstruction()
+{
+}
+
+DOMString ProcessingInstruction::target() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((ProcessingInstructionImpl*)impl)->target();
+}
+
+DOMString ProcessingInstruction::data() const
+{
+ if (!impl)
+ return DOMString(); // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ return ((ProcessingInstructionImpl*)impl)->data();
+}
+
+void ProcessingInstruction::setData( const DOMString &_data )
+{
+ if (!impl)
+ return; // ### enable throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ ((ProcessingInstructionImpl*)impl)->setData(_data, exceptioncode);
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+ProcessingInstruction::ProcessingInstruction(ProcessingInstructionImpl *i) : Node(i)
+{
+}
+
+StyleSheet ProcessingInstruction::sheet() const
+{
+ if (impl) return ((ProcessingInstructionImpl*)impl)->sheet();
+ return 0;
+}
+
+
diff --git a/tdehtml/dom/dom_xml.h b/tdehtml/dom/dom_xml.h
new file mode 100644
index 000000000..12e70d9e5
--- /dev/null
+++ b/tdehtml/dom/dom_xml.h
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef _DOM_XML_h
+#define _DOM_XML_h
+
+#include <dom/dom_text.h>
+#include <dom/css_stylesheet.h>
+
+namespace DOM {
+
+class CDATASectionImpl;
+class EntityImpl;
+class EntityReferenceImpl;
+class NotationImpl;
+class ProcessingInstructionImpl;
+
+
+
+/**
+ * CDATA sections are used to escape blocks of text containing
+ * characters that would otherwise be regarded as markup. The only
+ * delimiter that is recognized in a CDATA section is the "]]&gt;"
+ * string that ends the CDATA section. CDATA sections can not be
+ * nested. The primary purpose is for including material such as XML
+ * fragments, without needing to escape all the delimiters.
+ *
+ * The \c DOMString attribute of the \c Text
+ * node holds the text that is contained by the CDATA section. Note
+ * that this may contain characters that need to be escaped outside of
+ * CDATA sections and that, depending on the character encoding
+ * ("charset") chosen for serialization, it may be impossible to write
+ * out some characters as part of a CDATA section.
+ *
+ * The \c CDATASection interface inherits the
+ * \c CharacterData interface through the \c Text
+ * interface. Adjacent \c CDATASections nodes are not
+ * merged by use of the Element.normalize() method.
+ *
+ */
+class KHTML_EXPORT CDATASection : public Text
+{
+ friend class Document;
+public:
+ CDATASection();
+ CDATASection(const CDATASection &other);
+ CDATASection(const Node &other) : Text()
+ {(*this)=other;}
+
+ CDATASection & operator = (const Node &other);
+ CDATASection & operator = (const CDATASection &other);
+
+ ~CDATASection();
+protected:
+ CDATASection(CDATASectionImpl *i);
+};
+
+class DOMString;
+
+/**
+ * This interface represents an entity, either parsed or unparsed, in
+ * an XML document. Note that this models the entity itself not the
+ * entity declaration. \c Entity declaration modeling has
+ * been left for a later Level of the DOM specification.
+ *
+ * The \c nodeName attribute that is inherited from
+ * \c Node contains the name of the entity.
+ *
+ * An XML processor may choose to completely expand entities before
+ * the structure model is passed to the DOM; in this case there will
+ * be no \c EntityReference nodes in the document tree.
+ *
+ * XML does not mandate that a non-validating XML processor read and
+ * process entity declarations made in the external subset or declared
+ * in external parameter entities. This means that parsed entities
+ * declared in the external subset need not be expanded by some
+ * classes of applications, and that the replacement value of the
+ * entity may not be available. When the replacement value is
+ * available, the corresponding \c Entity node's child
+ * list represents the structure of that replacement text. Otherwise,
+ * the child list is empty.
+ *
+ * The resolution of the children of the \c Entity (the
+ * replacement value) may be lazily evaluated; actions by the user
+ * (such as calling the \c childNodes method on the
+ * \c Entity Node) are assumed to trigger the evaluation.
+ *
+ * The DOM Level 1 does not support editing \c Entity
+ * nodes; if a user wants to make changes to the contents of an
+ * \c Entity , every related \c EntityReference node
+ * has to be replaced in the structure model by a clone of the
+ * \c Entity 's contents, and then the desired changes must be
+ * made to each of those clones instead. All the descendants of an
+ * \c Entity node are readonly.
+ *
+ * An \c Entity node does not have any parent.
+ *
+ */
+class KHTML_EXPORT Entity : public Node
+{
+public:
+ Entity();
+ Entity(const Entity &other);
+ Entity(const Node &other) : Node()
+ {(*this)=other;}
+
+ Entity & operator = (const Node &other);
+ Entity & operator = (const Entity &other);
+
+ ~Entity();
+
+ /**
+ * The public identifier associated with the entity, if specified.
+ * If the public identifier was not specified, this is \c null .
+ *
+ */
+ DOMString publicId() const;
+
+ /**
+ * The system identifier associated with the entity, if specified.
+ * If the system identifier was not specified, this is \c null .
+ *
+ */
+ DOMString systemId() const;
+
+ /**
+ * For unparsed entities, the name of the notation for the entity.
+ * For parsed entities, this is \c null .
+ *
+ */
+ DOMString notationName() const;
+protected:
+ Entity(EntityImpl *i);
+};
+
+
+/**
+ * \c EntityReference objects may be inserted into the
+ * structure model when an entity reference is in the source document,
+ * or when the user wishes to insert an entity reference. Note that
+ * character references and references to predefined entities are
+ * considered to be expanded by the HTML or XML processor so that
+ * characters are represented by their Unicode equivalent rather than
+ * by an entity reference. Moreover, the XML processor may completely
+ * expand references to entities while building the structure model,
+ * instead of providing \c EntityReference objects. If it
+ * does provide such objects, then for a given \c EntityReference
+ * node, it may be that there is no \c Entity node
+ * representing the referenced entity; but if such an \c Entity
+ * exists, then the child list of the \c EntityReference
+ * node is the same as that of the \c Entity node.
+ * As with the \c Entity node, all descendants of the
+ * \c EntityReference are readonly.
+ *
+ * The resolution of the children of the \c EntityReference
+ * (the replacement value of the referenced \c Entity
+ * ) may be lazily evaluated; actions by the user (such as
+ * calling the \c childNodes method on the
+ * \c EntityReference node) are assumed to trigger the
+ * evaluation.
+ *
+ */
+class KHTML_EXPORT EntityReference : public Node
+{
+ friend class Document;
+public:
+ EntityReference();
+ EntityReference(const EntityReference &other);
+ EntityReference(const Node &other) : Node()
+ {(*this)=other;}
+
+ EntityReference & operator = (const Node &other);
+ EntityReference & operator = (const EntityReference &other);
+
+ ~EntityReference();
+protected:
+ EntityReference(EntityReferenceImpl *i);
+};
+
+class DOMString;
+
+/**
+ * This interface represents a notation declared in the DTD. A
+ * notation either declares, by name, the format of an unparsed entity
+ * (see section 4.7 of the XML 1.0 specification), or is used for
+ * formal declaration of Processing Instruction targets (see section
+ * 2.6 of the XML 1.0 specification). The \c nodeName
+ * attribute inherited from \c Node is set to the declared
+ * name of the notation.
+ *
+ * The DOM Level 1 does not support editing \c Notation
+ * nodes; they are therefore readonly.
+ *
+ * A \c Notation node does not have any parent.
+ *
+ */
+class KHTML_EXPORT Notation : public Node
+{
+public:
+ Notation();
+ Notation(const Notation &other);
+ Notation(const Node &other) : Node()
+ {(*this)=other;}
+
+ Notation & operator = (const Node &other);
+ Notation & operator = (const Notation &other);
+
+ ~Notation();
+
+ /**
+ * The public identifier of this notation. If the public
+ * identifier was not specified, this is \c null .
+ *
+ */
+ DOMString publicId() const;
+
+ /**
+ * The system identifier of this notation. If the system
+ * identifier was not specified, this is \c null .
+ *
+ */
+ DOMString systemId() const;
+protected:
+ Notation(NotationImpl *i);
+};
+
+
+/**
+ * The \c ProcessingInstruction interface represents a
+ * &quot;processing instruction&quot;, used in XML as a way to keep
+ * processor-specific information in the text of the document.
+ *
+ */
+class KHTML_EXPORT ProcessingInstruction : public Node
+{
+ friend class Document;
+public:
+ ProcessingInstruction();
+ ProcessingInstruction(const ProcessingInstruction &other);
+ ProcessingInstruction(const Node &other) : Node()
+ {(*this)=other;}
+
+ ProcessingInstruction & operator = (const Node &other);
+ ProcessingInstruction & operator = (const ProcessingInstruction &other);
+
+ ~ProcessingInstruction();
+
+ /**
+ * The target of this processing instruction. XML defines this as
+ * being the first token following the markup that begins the
+ * processing instruction.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * The content of this processing instruction. This is from the
+ * first non white space character after the target to the
+ * character immediately preceding the \c ?&gt; .
+ *
+ */
+ DOMString data() const;
+
+ /**
+ * see data
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ *
+ */
+ void setData( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the LinkStyle interface
+ *
+ * The style sheet.
+ */
+ StyleSheet sheet() const;
+
+protected:
+ ProcessingInstruction(ProcessingInstructionImpl *i);
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/dom/html_base.cpp b/tdehtml/dom/html_base.cpp
new file mode 100644
index 000000000..e35fdaa0a
--- /dev/null
+++ b/tdehtml/dom/html_base.cpp
@@ -0,0 +1,533 @@
+/**
+ * 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 "xml/dom_docimpl.h"
+#include "dom/html_base.h"
+#include "dom/dom_doc.h"
+#include "html/html_baseimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLBodyElement::HTMLBodyElement() : HTMLElement()
+{
+}
+
+HTMLBodyElement::HTMLBodyElement(const HTMLBodyElement &other) : HTMLElement(other)
+{
+}
+
+HTMLBodyElement::HTMLBodyElement(HTMLBodyElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLBodyElement &HTMLBodyElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BODY );
+ return *this;
+}
+
+HTMLBodyElement &HTMLBodyElement::operator = (const HTMLBodyElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLBodyElement::~HTMLBodyElement()
+{
+}
+
+DOMString HTMLBodyElement::aLink() const
+{
+ return impl ? ((ElementImpl *)impl)->getAttribute(ATTR_ALINK) : DOMString();
+}
+
+void HTMLBodyElement::setALink( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALINK, value);
+}
+
+DOMString HTMLBodyElement::background() const
+{
+ return impl ? ((ElementImpl *)impl)->getAttribute(ATTR_BACKGROUND) : DOMString();
+}
+
+void HTMLBodyElement::setBackground( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BACKGROUND, value);
+}
+
+DOMString HTMLBodyElement::bgColor() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BGCOLOR);
+}
+
+void HTMLBodyElement::setBgColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BGCOLOR, value);
+}
+
+DOMString HTMLBodyElement::link() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_LINK);
+}
+
+void HTMLBodyElement::setLink( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_LINK, value);
+}
+
+DOMString HTMLBodyElement::text() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TEXT);
+}
+
+void HTMLBodyElement::setText( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TEXT, value);
+}
+
+DOMString HTMLBodyElement::vLink() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VLINK);
+}
+
+void HTMLBodyElement::setVLink( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VLINK, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLFrameElement::HTMLFrameElement() : HTMLElement()
+{
+}
+
+HTMLFrameElement::HTMLFrameElement(const HTMLFrameElement &other) : HTMLElement(other)
+{
+}
+
+HTMLFrameElement::HTMLFrameElement(HTMLFrameElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLFrameElement &HTMLFrameElement::operator = (const Node &other)
+{
+ assignOther( other, ID_FRAME );
+ return *this;
+}
+
+HTMLFrameElement &HTMLFrameElement::operator = (const HTMLFrameElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLFrameElement::~HTMLFrameElement()
+{
+}
+
+DOMString HTMLFrameElement::frameBorder() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_FRAMEBORDER);
+}
+
+void HTMLFrameElement::setFrameBorder( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_FRAMEBORDER, value);
+}
+
+DOMString HTMLFrameElement::longDesc() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_LONGDESC);
+}
+
+void HTMLFrameElement::setLongDesc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_LONGDESC, value);
+}
+
+DOMString HTMLFrameElement::marginHeight() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MARGINHEIGHT);
+}
+
+void HTMLFrameElement::setMarginHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MARGINHEIGHT, value);
+}
+
+DOMString HTMLFrameElement::marginWidth() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MARGINWIDTH);
+}
+
+void HTMLFrameElement::setMarginWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MARGINWIDTH, value);
+}
+
+DOMString HTMLFrameElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLFrameElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+bool HTMLFrameElement::noResize() const
+{
+ if(!impl) return false;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_NORESIZE).isNull();
+}
+
+void HTMLFrameElement::setNoResize( bool _noResize )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _noResize )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_NORESIZE, str);
+ }
+}
+
+DOMString HTMLFrameElement::scrolling() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SCROLLING);
+}
+
+void HTMLFrameElement::setScrolling( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SCROLLING, value);
+}
+
+DOMString HTMLFrameElement::src() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SRC);
+}
+
+void HTMLFrameElement::setSrc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SRC, value);
+}
+
+Document HTMLFrameElement::contentDocument() const
+{
+ if (impl) return static_cast<HTMLFrameElementImpl*>(impl)->contentDocument();
+ return Document();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLIFrameElement::HTMLIFrameElement() : HTMLElement()
+{
+}
+
+HTMLIFrameElement::HTMLIFrameElement(const HTMLIFrameElement &other) : HTMLElement(other)
+{
+}
+
+HTMLIFrameElement::HTMLIFrameElement(HTMLIFrameElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLIFrameElement &HTMLIFrameElement::operator = (const Node &other)
+{
+ assignOther( other, ID_IFRAME );
+ return *this;
+}
+
+HTMLIFrameElement &HTMLIFrameElement::operator = (const HTMLIFrameElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLIFrameElement::~HTMLIFrameElement()
+{
+}
+
+DOMString HTMLIFrameElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLIFrameElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLIFrameElement::frameBorder() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_FRAMEBORDER);
+}
+
+void HTMLIFrameElement::setFrameBorder( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_FRAMEBORDER, value);
+}
+
+DOMString HTMLIFrameElement::height() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HEIGHT);
+}
+
+void HTMLIFrameElement::setHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEIGHT, value);
+}
+
+DOMString HTMLIFrameElement::longDesc() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_LONGDESC);
+}
+
+void HTMLIFrameElement::setLongDesc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_LONGDESC, value);
+}
+
+DOMString HTMLIFrameElement::marginHeight() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MARGINHEIGHT);
+}
+
+void HTMLIFrameElement::setMarginHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MARGINHEIGHT, value);
+}
+
+DOMString HTMLIFrameElement::marginWidth() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MARGINWIDTH);
+}
+
+void HTMLIFrameElement::setMarginWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MARGINWIDTH, value);
+}
+
+DOMString HTMLIFrameElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLIFrameElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLIFrameElement::scrolling() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SCROLLING);
+}
+
+void HTMLIFrameElement::setScrolling( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SCROLLING, value);
+}
+
+DOMString HTMLIFrameElement::src() const
+{
+ if(!impl) return DOMString();
+ DOMString s = ((ElementImpl *)impl)->getAttribute(ATTR_SRC);
+ return !s.isNull() ? impl->getDocument()->completeURL( s.string() ) : s;
+}
+
+void HTMLIFrameElement::setSrc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SRC, value);
+}
+
+DOMString HTMLIFrameElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLIFrameElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+Document HTMLIFrameElement::contentDocument() const
+{
+ if (impl) return static_cast<HTMLIFrameElementImpl*>(impl)->contentDocument();
+ return Document();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLFrameSetElement::HTMLFrameSetElement() : HTMLElement()
+{
+}
+
+HTMLFrameSetElement::HTMLFrameSetElement(const HTMLFrameSetElement &other) : HTMLElement(other)
+{
+}
+
+HTMLFrameSetElement::HTMLFrameSetElement(HTMLFrameSetElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLFrameSetElement &HTMLFrameSetElement::operator = (const Node &other)
+{
+ assignOther( other, ID_FRAMESET );
+ return *this;
+}
+
+HTMLFrameSetElement &HTMLFrameSetElement::operator = (const HTMLFrameSetElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLFrameSetElement::~HTMLFrameSetElement()
+{
+}
+
+DOMString HTMLFrameSetElement::cols() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COLS);
+}
+
+void HTMLFrameSetElement::setCols( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_COLS, value);
+}
+
+DOMString HTMLFrameSetElement::rows() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ROWS);
+}
+
+void HTMLFrameSetElement::setRows( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ROWS, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLHeadElement::HTMLHeadElement() : HTMLElement()
+{
+}
+
+HTMLHeadElement::HTMLHeadElement(const HTMLHeadElement &other) : HTMLElement(other)
+{
+}
+
+HTMLHeadElement::HTMLHeadElement(HTMLHeadElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLHeadElement &HTMLHeadElement::operator = (const Node &other)
+{
+ assignOther( other, ID_HEAD );
+ return *this;
+}
+
+HTMLHeadElement &HTMLHeadElement::operator = (const HTMLHeadElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLHeadElement::~HTMLHeadElement()
+{
+}
+
+DOMString HTMLHeadElement::profile() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_PROFILE);
+}
+
+void HTMLHeadElement::setProfile( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_PROFILE, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLHtmlElement::HTMLHtmlElement() : HTMLElement()
+{
+}
+
+HTMLHtmlElement::HTMLHtmlElement(const HTMLHtmlElement &other) : HTMLElement(other)
+{
+}
+
+HTMLHtmlElement::HTMLHtmlElement(HTMLHtmlElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLHtmlElement &HTMLHtmlElement::operator = (const Node &other)
+{
+ assignOther( other, ID_HTML );
+ return *this;
+}
+
+HTMLHtmlElement &HTMLHtmlElement::operator = (const HTMLHtmlElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLHtmlElement::~HTMLHtmlElement()
+{
+}
+
+DOMString HTMLHtmlElement::version() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VERSION);
+}
+
+void HTMLHtmlElement::setVersion( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VERSION, value);
+}
+
diff --git a/tdehtml/dom/html_base.h b/tdehtml/dom/html_base.h
new file mode 100644
index 000000000..c7ed878ce
--- /dev/null
+++ b/tdehtml/dom/html_base.h
@@ -0,0 +1,610 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+
+#ifndef HTML_BASE_H
+#define HTML_BASE_H
+
+#include <dom/html_element.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class HTMLBodyElementImpl;
+class DOMString;
+
+/**
+ * The HTML document body. This element is always present in the DOM
+ * API, even if the tags are not present in the source document. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-BODY">
+ * BODY element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLBodyElement : public HTMLElement
+{
+public:
+ HTMLBodyElement();
+ HTMLBodyElement(const HTMLBodyElement &other);
+ HTMLBodyElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLBodyElement(HTMLBodyElementImpl *impl);
+public:
+
+ HTMLBodyElement & operator = (const HTMLBodyElement &other);
+ HTMLBodyElement & operator = (const Node &other);
+
+ ~HTMLBodyElement();
+
+ /**
+ * Color of active links (after mouse-button down, but before
+ * mouse-button up). See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-alink">
+ * alink attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString aLink() const;
+
+ /**
+ * see aLink
+ */
+ void setALink( const DOMString & );
+
+ /**
+ * URI of the background texture tile image. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-background">
+ * background attribute definition </a> in HTML 4.0. This
+ * attribute is deprecated in HTML 4.0.
+ *
+ */
+ DOMString background() const;
+
+ /**
+ * see background
+ */
+ void setBackground( const DOMString & );
+
+ /**
+ * Document background color. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-bgcolor">
+ * bgcolor attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString bgColor() const;
+
+ /**
+ * see bgColor
+ */
+ void setBgColor( const DOMString & );
+
+ /**
+ * Color of links that are not active and unvisited. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-link">
+ * link attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString link() const;
+
+ /**
+ * see link
+ */
+ void setLink( const DOMString & );
+
+ /**
+ * Document text color. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-text">
+ * text attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString text() const;
+
+ /**
+ * see text
+ */
+ void setText( const DOMString & );
+
+ /**
+ * Color of links that have been visited by the user. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-vlink">
+ * vlink attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString vLink() const;
+
+ /**
+ * see vLink
+ */
+ void setVLink( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLFrameElementImpl;
+class DOMString;
+
+/**
+ * Create a frame. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#edef-FRAME">
+ * FRAME element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLFrameElement : public HTMLElement
+{
+public:
+ HTMLFrameElement();
+ HTMLFrameElement(const HTMLFrameElement &other);
+ HTMLFrameElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLFrameElement(HTMLFrameElementImpl *impl);
+public:
+
+ HTMLFrameElement & operator = (const HTMLFrameElement &other);
+ HTMLFrameElement & operator = (const Node &other);
+
+ ~HTMLFrameElement();
+
+ /**
+ * Request frame borders. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-frameborder">
+ * frameborder attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString frameBorder() const;
+
+ /**
+ * see frameBorder
+ */
+ void setFrameBorder( const DOMString & );
+
+ /**
+ * URI designating a long description of this image or frame. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-longdesc-FRAME">
+ * longdesc attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString longDesc() const;
+
+ /**
+ * see longDesc
+ */
+ void setLongDesc( const DOMString & );
+
+ /**
+ * Frame margin height, in pixels. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-marginheight">
+ * marginheight attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString marginHeight() const;
+
+ /**
+ * see marginHeight
+ */
+ void setMarginHeight( const DOMString & );
+
+ /**
+ * Frame margin width, in pixels. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-marginwidth">
+ * marginwidth attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString marginWidth() const;
+
+ /**
+ * see marginWidth
+ */
+ void setMarginWidth( const DOMString & );
+
+ /**
+ * The frame name (object of the \c target attribute).
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-name-FRAME">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * When true, forbid user from resizing frame. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-noresize">
+ * noresize attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool noResize() const;
+
+ /**
+ * see noResize
+ */
+ void setNoResize( bool );
+
+ /**
+ * Specify whether or not the frame should have scrollbars. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-scrolling">
+ * scrolling attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString scrolling() const;
+
+ /**
+ * see scrolling
+ */
+ void setScrolling( const DOMString & );
+
+ /**
+ * A URI designating the initial frame contents. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-src-FRAME">
+ * src attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString src() const;
+
+ /**
+ * see src
+ */
+ void setSrc( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Returns the document this frame contains, if there is any and
+ * it is available, a Null document otherwise. The attribute is
+ * read-only.
+ *
+ * @return The content Document if available.
+ */
+ Document contentDocument() const;
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLFrameSetElementImpl;
+class DOMString;
+
+/**
+ * Create a grid of frames. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#edef-FRAMESET">
+ * FRAMESET element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLFrameSetElement : public HTMLElement
+{
+public:
+ HTMLFrameSetElement();
+ HTMLFrameSetElement(const HTMLFrameSetElement &other);
+ HTMLFrameSetElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLFrameSetElement(HTMLFrameSetElementImpl *impl);
+public:
+
+ HTMLFrameSetElement & operator = (const HTMLFrameSetElement &other);
+ HTMLFrameSetElement & operator = (const Node &other);
+
+ ~HTMLFrameSetElement();
+
+ /**
+ * The number of columns of frames in the frameset. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-cols-FRAMESET">
+ * cols attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cols() const;
+
+ /**
+ * see cols
+ */
+ void setCols( const DOMString & );
+
+ /**
+ * The number of rows of frames in the frameset. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-rows-FRAMESET">
+ * rows attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rows() const;
+
+ /**
+ * see rows
+ */
+ void setRows( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLIFrameElementImpl;
+
+/**
+ * Inline subwindows. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#edef-IFRAME">
+ * IFRAME element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLIFrameElement : public HTMLElement
+{
+public:
+ HTMLIFrameElement();
+ HTMLIFrameElement(const HTMLIFrameElement &other);
+ HTMLIFrameElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLIFrameElement(HTMLIFrameElementImpl *impl);
+public:
+
+ HTMLIFrameElement & operator = (const HTMLIFrameElement &other);
+ HTMLIFrameElement & operator = (const Node &other);
+
+ ~HTMLIFrameElement();
+
+ /**
+ * Aligns this object (vertically or horizontally) with respect to
+ * its surrounding text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-align-IMG">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Request frame borders. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-frameborder">
+ * frameborder attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString frameBorder() const;
+
+ /**
+ * see frameBorder
+ */
+ void setFrameBorder( const DOMString & );
+
+ /**
+ * Frame height. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-height-IFRAME">
+ * height attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( const DOMString & );
+
+ /**
+ * URI designating a long description of this image or frame. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-longdesc-IFRAME">
+ * longdesc attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString longDesc() const;
+
+ /**
+ * see longDesc
+ */
+ void setLongDesc( const DOMString & );
+
+ /**
+ * Frame margin height, in pixels. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-marginheight">
+ * marginheight attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString marginHeight() const;
+
+ /**
+ * see marginHeight
+ */
+ void setMarginHeight( const DOMString & );
+
+ /**
+ * Frame margin width, in pixels. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-marginwidth">
+ * marginwidth attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString marginWidth() const;
+
+ /**
+ * see marginWidth
+ */
+ void setMarginWidth( const DOMString & );
+
+ /**
+ * The frame name (object of the \c target attribute).
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-name-IFRAME">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Specify whether or not the frame should have scrollbars. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-scrolling">
+ * scrolling attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString scrolling() const;
+
+ /**
+ * see scrolling
+ */
+ void setScrolling( const DOMString & );
+
+ /**
+ * A URI designating the initial frame contents. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-src-FRAME">
+ * src attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString src() const;
+
+ /**
+ * see src
+ */
+ void setSrc( const DOMString & );
+
+ /**
+ * Frame width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-width-IFRAME">
+ * width attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Returns the document this iframe contains, if there is any and
+ * it is available, a Null document otherwise. The attribute is
+ * read-only.
+ *
+ * @return The content Document if available.
+ */
+ Document contentDocument() const;
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLHeadElementImpl;
+class DOMString;
+
+/**
+ * Document head information. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-HEAD">
+ * HEAD element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLHeadElement : public HTMLElement
+{
+public:
+ HTMLHeadElement();
+ HTMLHeadElement(const HTMLHeadElement &other);
+ HTMLHeadElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLHeadElement(HTMLHeadElementImpl *impl);
+public:
+
+ HTMLHeadElement & operator = (const HTMLHeadElement &other);
+ HTMLHeadElement & operator = (const Node &other);
+
+ ~HTMLHeadElement();
+
+ /**
+ * URI designating a metadata profile. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-profile">
+ * profile attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString profile() const;
+
+ /**
+ * see profile
+ */
+ void setProfile( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLHtmlElementImpl;
+class DOMString;
+
+/**
+ * Root of an HTML document. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-HTML">
+ * HTML element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLHtmlElement : public HTMLElement
+{
+public:
+ HTMLHtmlElement();
+ HTMLHtmlElement(const HTMLHtmlElement &other);
+ HTMLHtmlElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLHtmlElement(HTMLHtmlElementImpl *impl);
+public:
+
+ HTMLHtmlElement & operator = (const HTMLHtmlElement &other);
+ HTMLHtmlElement & operator = (const Node &other);
+
+ ~HTMLHtmlElement();
+
+ /**
+ * Version information about the document's DTD. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-version">
+ * version attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString version() const;
+
+ /**
+ * see version
+ */
+ void setVersion( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_block.cpp b/tdehtml/dom/html_block.cpp
new file mode 100644
index 000000000..9e499adb0
--- /dev/null
+++ b/tdehtml/dom/html_block.cpp
@@ -0,0 +1,443 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (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.
+ *
+ */
+// --------------------------------------------------------------------------
+
+
+#include "dom/html_block.h"
+#include "dom/html_misc.h"
+#include "html/html_blockimpl.h"
+#include "html/html_miscimpl.h"
+
+using namespace DOM;
+
+#include "misc/htmlhashes.h"
+
+HTMLBlockquoteElement::HTMLBlockquoteElement()
+ : HTMLElement()
+{
+}
+
+HTMLBlockquoteElement::HTMLBlockquoteElement(const HTMLBlockquoteElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLBlockquoteElement::HTMLBlockquoteElement(HTMLElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLBlockquoteElement &HTMLBlockquoteElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BLOCKQUOTE );
+ return *this;
+}
+
+HTMLBlockquoteElement &HTMLBlockquoteElement::operator = (const HTMLBlockquoteElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLBlockquoteElement::~HTMLBlockquoteElement()
+{
+}
+
+DOMString HTMLBlockquoteElement::cite() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CITE);
+}
+
+void HTMLBlockquoteElement::setCite( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CITE, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLDivElement::HTMLDivElement()
+ : HTMLElement()
+{
+}
+
+HTMLDivElement::HTMLDivElement(const HTMLDivElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLDivElement::HTMLDivElement(HTMLDivElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLDivElement &HTMLDivElement::operator = (const Node &other)
+{
+ assignOther( other, ID_DIV );
+ return *this;
+}
+
+HTMLDivElement &HTMLDivElement::operator = (const HTMLDivElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLDivElement::~HTMLDivElement()
+{
+}
+
+DOMString HTMLDivElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLDivElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLHRElement::HTMLHRElement()
+ : HTMLElement()
+{
+}
+
+HTMLHRElement::HTMLHRElement(const HTMLHRElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLHRElement::HTMLHRElement(HTMLHRElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLHRElement &HTMLHRElement::operator = (const Node &other)
+{
+ assignOther( other, ID_HR );
+ return *this;
+}
+
+HTMLHRElement &HTMLHRElement::operator = (const HTMLHRElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLHRElement::~HTMLHRElement()
+{
+}
+
+DOMString HTMLHRElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLHRElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+bool HTMLHRElement::noShade() const
+{
+ if(!impl) return false;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_NOSHADE).isNull();
+}
+
+void HTMLHRElement::setNoShade( bool _noShade )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _noShade )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_NOSHADE, str);
+ }
+}
+
+DOMString HTMLHRElement::size() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SIZE);
+}
+
+void HTMLHRElement::setSize( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SIZE, value);
+}
+
+DOMString HTMLHRElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLHRElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLHeadingElement::HTMLHeadingElement()
+ : HTMLElement()
+{
+}
+
+HTMLHeadingElement::HTMLHeadingElement(const HTMLHeadingElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLHeadingElement::HTMLHeadingElement(HTMLElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLHeadingElement &HTMLHeadingElement::operator = (const Node &other)
+{
+ if(other.elementId() != ID_H1 &&
+ other.elementId() != ID_H2 &&
+ other.elementId() != ID_H3 &&
+ other.elementId() != ID_H4 &&
+ other.elementId() != ID_H5 &&
+ other.elementId() != ID_H6 )
+ {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+ return *this;
+}
+
+HTMLHeadingElement &HTMLHeadingElement::operator = (const HTMLHeadingElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLHeadingElement::~HTMLHeadingElement()
+{
+}
+
+DOMString HTMLHeadingElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLHeadingElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLParagraphElement::HTMLParagraphElement() : HTMLElement()
+{
+}
+
+HTMLParagraphElement::HTMLParagraphElement(const HTMLParagraphElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLParagraphElement::HTMLParagraphElement(HTMLElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLParagraphElement &HTMLParagraphElement::operator = (const Node &other)
+{
+ assignOther( other, ID_P );
+ return *this;
+}
+
+HTMLParagraphElement &HTMLParagraphElement::operator = (const HTMLParagraphElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLParagraphElement::~HTMLParagraphElement()
+{
+}
+
+DOMString HTMLParagraphElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLParagraphElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLPreElement::HTMLPreElement() : HTMLElement()
+{
+}
+
+HTMLPreElement::HTMLPreElement(const HTMLPreElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLPreElement::HTMLPreElement(HTMLPreElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLPreElement &HTMLPreElement::operator = (const Node &other)
+{
+ assignOther( other, ID_PRE );
+ return *this;
+}
+
+HTMLPreElement &HTMLPreElement::operator = (const HTMLPreElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLPreElement::~HTMLPreElement()
+{
+}
+
+long HTMLPreElement::width() const
+{
+ if(!impl) return 0;
+ DOMString w = ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+ return w.toInt();
+}
+
+void HTMLPreElement::setWidth( long _width )
+{
+ if(!impl) return;
+
+ TQString aStr;
+ aStr.sprintf("%ld", _width);
+ DOMString value(aStr);
+ ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLLayerElement::HTMLLayerElement() : HTMLElement()
+{
+}
+
+HTMLLayerElement::HTMLLayerElement(const HTMLLayerElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLLayerElement::HTMLLayerElement(HTMLLayerElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLLayerElement &HTMLLayerElement::operator = (const Node &other)
+{
+ assignOther( other, ID_LAYER );
+ return *this;
+}
+
+HTMLLayerElement &HTMLLayerElement::operator = (const HTMLLayerElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLLayerElement::~HTMLLayerElement()
+{
+}
+
+long HTMLLayerElement::top() const
+{
+ if(!impl) return 0;
+ DOMString t = ((ElementImpl *)impl)->getAttribute(ATTR_TOP);
+ return t.toInt();
+}
+
+void HTMLLayerElement::setTop( long _top )
+{
+ if(!impl) return;
+
+ TQString aStr;
+ aStr.sprintf("%ld", _top);
+ DOMString value(aStr);
+ ((ElementImpl *)impl)->setAttribute(ATTR_TOP, value);
+}
+
+long HTMLLayerElement::left() const
+{
+ if(!impl) return 0;
+ DOMString l = ((ElementImpl *)impl)->getAttribute(ATTR_LEFT);
+ return l.toInt();
+}
+
+void HTMLLayerElement::setLeft( long _left )
+{
+ if(!impl) return;
+
+ TQString aStr;
+ aStr.sprintf("%ld", _left);
+ DOMString value(aStr);
+ ((ElementImpl *)impl)->setAttribute(ATTR_LEFT, value);
+}
+
+DOMString HTMLLayerElement::visibility() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VISIBILITY);
+}
+
+void HTMLLayerElement::setVisibility( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VISIBILITY, value);
+}
+
+DOMString HTMLLayerElement::bgColor() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BGCOLOR);
+}
+
+void HTMLLayerElement::setBgColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BGCOLOR, value);
+}
+
+HTMLCollection HTMLLayerElement::layers() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_LAYERS);
+}
diff --git a/tdehtml/dom/html_block.h b/tdehtml/dom/html_block.h
new file mode 100644
index 000000000..4283bafa2
--- /dev/null
+++ b/tdehtml/dom/html_block.h
@@ -0,0 +1,406 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+// --------------------------------------------------------------------------
+
+#ifndef HTML_BLOCK_H
+#define HTML_BLOCK_H
+
+#include <dom/html_element.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class HTMLElementImpl;
+class DOMString;
+
+/**
+ * ??? See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-BLOCKQUOTE">
+ * BLOCKQUOTE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLBlockquoteElement : public HTMLElement
+{
+public:
+ HTMLBlockquoteElement();
+ HTMLBlockquoteElement(const HTMLBlockquoteElement &other);
+ HTMLBlockquoteElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLBlockquoteElement(HTMLElementImpl *impl);
+public:
+
+ HTMLBlockquoteElement & operator = (const HTMLBlockquoteElement &other);
+ HTMLBlockquoteElement & operator = (const Node &other);
+
+ ~HTMLBlockquoteElement();
+
+ /**
+ * A URI designating a document that describes the reason for the
+ * change. See the <a href="http://www.w3.org/TR/REC-html40/">
+ * cite attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cite() const;
+
+ /**
+ * see cite
+ */
+ void setCite( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLDivElementImpl;
+class DOMString;
+
+/**
+ * Generic block container. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-DIV">
+ * DIV element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLDivElement : public HTMLElement
+{
+public:
+ HTMLDivElement();
+ HTMLDivElement(const HTMLDivElement &other);
+ HTMLDivElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLDivElement(HTMLDivElementImpl *impl);
+public:
+
+ HTMLDivElement & operator = (const HTMLDivElement &other);
+ HTMLDivElement & operator = (const Node &other);
+
+ ~HTMLDivElement();
+
+ /**
+ * Horizontal text alignment. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-align">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLHRElementImpl;
+class DOMString;
+
+/**
+ * Create a horizontal rule. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#edef-HR">
+ * HR element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLHRElement : public HTMLElement
+{
+public:
+ HTMLHRElement();
+ HTMLHRElement(const HTMLHRElement &other);
+ HTMLHRElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLHRElement(HTMLHRElementImpl *impl);
+public:
+
+ HTMLHRElement & operator = (const HTMLHRElement &other);
+ HTMLHRElement & operator = (const Node &other);
+
+ ~HTMLHRElement();
+
+ /**
+ * Align the rule on the page. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-align-HR">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Indicates to the user agent that there should be no shading in
+ * the rendering of this element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-noshade">
+ * noshade attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool noShade() const;
+
+ /**
+ * see noShade
+ */
+ void setNoShade( bool );
+
+ /**
+ * The height of the rule. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-size-HR">
+ * size attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString size() const;
+
+ /**
+ * see size
+ */
+ void setSize( const DOMString & );
+
+ /**
+ * The width of the rule. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-width-HR">
+ * width attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class DOMString;
+
+/**
+ * For the \c H1 to \c H6 elements. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-H1">
+ * H1 element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLHeadingElement : public HTMLElement
+{
+public:
+ HTMLHeadingElement();
+ HTMLHeadingElement(const HTMLHeadingElement &other);
+ HTMLHeadingElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLHeadingElement(HTMLElementImpl *impl);
+public:
+
+ HTMLHeadingElement & operator = (const HTMLHeadingElement &other);
+ HTMLHeadingElement & operator = (const Node &other);
+
+ ~HTMLHeadingElement();
+
+ /**
+ * Horizontal text alignment. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-align">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class DOMString;
+
+/**
+ * Paragraphs. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-P"> P
+ * element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLParagraphElement : public HTMLElement
+{
+public:
+ HTMLParagraphElement();
+ HTMLParagraphElement(const HTMLParagraphElement &other);
+ HTMLParagraphElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLParagraphElement(HTMLElementImpl *impl);
+public:
+
+ HTMLParagraphElement & operator = (const HTMLParagraphElement &other);
+ HTMLParagraphElement & operator = (const Node &other);
+
+ ~HTMLParagraphElement();
+
+ /**
+ * Horizontal text alignment. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-align">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLPreElementImpl;
+
+/**
+ * Preformatted text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-PRE">
+ * PRE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLPreElement : public HTMLElement
+{
+public:
+ HTMLPreElement();
+ HTMLPreElement(const HTMLPreElement &other);
+ HTMLPreElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLPreElement(HTMLPreElementImpl *impl);
+public:
+
+ HTMLPreElement & operator = (const HTMLPreElement &other);
+ HTMLPreElement & operator = (const Node &other);
+
+ ~HTMLPreElement();
+
+ /**
+ * Fixed width for content. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#adef-width-PRE">
+ * width attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( long );
+};
+
+class HTMLLayerElementImpl;
+
+/**
+ * Layer container for Netscape 4.x compatability.
+ * Behaves mostly like absolute positioned DIV-blocks.
+ *
+ */
+class KHTML_EXPORT HTMLLayerElement : public HTMLElement
+{
+public:
+ HTMLLayerElement();
+ HTMLLayerElement(const HTMLLayerElement &other);
+ HTMLLayerElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLLayerElement(HTMLLayerElementImpl *impl);
+public:
+
+ HTMLLayerElement & operator = (const HTMLLayerElement &other);
+ HTMLLayerElement & operator = (const Node &other);
+
+ ~HTMLLayerElement();
+
+ /**
+ * The absolute position of the layer from the top.
+ *
+ */
+ long top() const;
+
+ /**
+ * see top
+ */
+ void setTop( long );
+
+ /**
+ * The absolute position of the layer from the left.
+ *
+ */
+ long left() const;
+
+ /**
+ * see left
+ */
+ void setLeft( long );
+
+ /**
+ * The visibility of layers is either "show" or "hide"
+ *
+ */
+ DOMString visibility() const;
+
+ /**
+ * see visibility
+ */
+ void setVisibility( const DOMString & );
+
+ /**
+ * The background color of the layer.
+ *
+ */
+ DOMString bgColor() const;
+
+ /**
+ * see bgColor
+ */
+ void setBgColor( const DOMString & );
+
+ /**
+ * The collection of sub-layers
+ *
+ */
+ HTMLCollection layers() const;
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_document.cpp b/tdehtml/dom/html_document.cpp
new file mode 100644
index 000000000..c24bf65f7
--- /dev/null
+++ b/tdehtml/dom/html_document.cpp
@@ -0,0 +1,233 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (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_document.h"
+#include "css/csshelper.h"
+#include "dom/html_misc.h"
+#include "dom/dom_exception.h"
+#include "xml/dom_textimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_miscimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLDocument::HTMLDocument() : Document(false) // create the impl here
+{
+ impl = DOMImplementationImpl::instance()->createHTMLDocument();
+ impl->ref();
+
+}
+
+HTMLDocument::HTMLDocument(KHTMLView *parent)
+ : Document(false) // create the impl here
+{
+ impl = DOMImplementationImpl::instance()->createHTMLDocument(parent);
+ impl->ref();
+}
+
+HTMLDocument::HTMLDocument(const HTMLDocument &other) : Document(other)
+{
+}
+
+HTMLDocument::HTMLDocument(HTMLDocumentImpl *impl) : Document(impl)
+{
+}
+
+HTMLDocument &HTMLDocument::operator = (const Node &other)
+{
+ if(other.nodeType() != DOCUMENT_NODE) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ DocumentImpl *d = static_cast<DocumentImpl *>(other.handle());
+ if(!d->isHTMLDocument()) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator =(other);
+ }
+ }
+ return *this;
+}
+
+HTMLDocument &HTMLDocument::operator = (const HTMLDocument &other)
+{
+ Document::operator =(other);
+ return *this;
+}
+
+HTMLDocument::~HTMLDocument()
+{
+}
+
+DOMString HTMLDocument::title() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLDocumentImpl *>(impl)->title();
+}
+
+void HTMLDocument::setTitle( const DOMString &value )
+{
+ if (impl)
+ static_cast<HTMLDocumentImpl *>(impl)->setTitle(value);
+}
+
+DOMString HTMLDocument::referrer() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLDocumentImpl *)impl)->referrer();
+}
+
+DOMString HTMLDocument::completeURL(const DOMString& str) const
+{
+ if(!impl) return str;
+ DOMString parsed = tdehtml::parseURL(str);
+ return ((HTMLDocumentImpl *)impl)->completeURL(parsed.string());
+}
+
+DOMString HTMLDocument::domain() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLDocumentImpl *)impl)->domain();
+}
+
+DOMString HTMLDocument::lastModified() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLDocumentImpl *)impl)->lastModified();
+}
+
+DOMString HTMLDocument::URL() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLDocumentImpl *)impl)->URL().url();
+}
+
+HTMLElement HTMLDocument::body() const
+{
+ if(!impl) return 0;
+ return ((HTMLDocumentImpl *)impl)->body();
+}
+
+void HTMLDocument::setBody(const HTMLElement &_body)
+{
+ if (!impl) return;
+ int exceptioncode = 0;
+ ((HTMLDocumentImpl *)impl)->setBody(static_cast<HTMLElementImpl *>(_body.handle()), exceptioncode);
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+ return;
+}
+
+HTMLCollection HTMLDocument::images() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_IMAGES);
+}
+
+HTMLCollection HTMLDocument::applets() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_APPLETS);
+}
+
+HTMLCollection HTMLDocument::scripts() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_SCRIPTS);
+}
+
+HTMLCollection HTMLDocument::links() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_LINKS);
+}
+
+HTMLCollection HTMLDocument::forms() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_FORMS);
+}
+
+HTMLCollection HTMLDocument::layers() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_LAYERS);
+}
+
+HTMLCollection HTMLDocument::anchors() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_ANCHORS);
+}
+
+HTMLCollection HTMLDocument::all() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_ALL);
+}
+
+DOMString HTMLDocument::cookie() const
+{
+ if (!impl) return DOMString();
+ return ((HTMLDocumentImpl *)impl)->cookie();
+}
+
+void HTMLDocument::setCookie( const DOMString & value )
+{
+ if (impl)
+ ((HTMLDocumentImpl *)impl)->setCookie(value);
+
+}
+
+void HTMLDocument::open( )
+{
+ if(impl)
+ ((HTMLDocumentImpl *)impl)->open( );
+}
+
+void HTMLDocument::close( )
+{
+ if(impl)
+ ((HTMLDocumentImpl *)impl)->close( );
+}
+
+void HTMLDocument::write( const DOMString &text )
+{
+ if(impl)
+ ((HTMLDocumentImpl *)impl)->write( text );
+}
+
+void HTMLDocument::writeln( const DOMString &text )
+{
+ if(impl)
+ ((HTMLDocumentImpl *)impl)->writeln( text );
+}
+
+NodeList HTMLDocument::getElementsByName( const DOMString &elementName )
+{
+ if(!impl) return 0;
+ return new NameNodeListImpl(impl, elementName);
+}
+
diff --git a/tdehtml/dom/html_document.h b/tdehtml/dom/html_document.h
new file mode 100644
index 000000000..aa53de96c
--- /dev/null
+++ b/tdehtml/dom/html_document.h
@@ -0,0 +1,304 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+
+#ifndef HTML_DOCUMENT_H
+#define HTML_DOCUMENT_H
+
+#include <dom/dom_doc.h>
+#include <dom/dom_string.h>
+
+#include <tdelibs_export.h>
+
+class KHTMLView;
+class KHTMLPart;
+
+namespace DOM {
+
+class HTMLDocumentImpl;
+class DOMImplementation;
+class HTMLCollection;
+class NodeList;
+class Element;
+class HTMLElement;
+
+/**
+ * An \c HTMLDocument is the root of the HTML hierarchy
+ * and holds the entire content. Beside providing access to the
+ * hierarchy, it also provides some convenience methods for accessing
+ * certain sets of information from the document.
+ *
+ * The following properties have been deprecated in favor of the
+ * corresponding ones for the BODY element:
+ *
+ * \li \c alinkColor
+ *
+ * \li \c background
+ *
+ * \li \c bgColor
+ *
+ * \li \c fgColor
+ *
+ * \li \c linkColor
+ *
+ * \li \c vlinkColor
+ *
+ *
+ */
+class KHTML_EXPORT HTMLDocument : public Document
+{
+ friend class ::KHTMLView;
+ friend class ::KHTMLPart;
+ friend class DOMImplementation;
+public:
+ HTMLDocument();
+ /**
+ * The parent is the widget the document should render itself in.
+ * Rendering information (like sizes, etc...) is only created if
+ * parent != 0
+ */
+ HTMLDocument(KHTMLView *parent);
+ HTMLDocument(const HTMLDocument &other);
+ HTMLDocument(const Node &other) : Document(false)
+ {(*this)=other;}
+protected:
+ HTMLDocument(HTMLDocumentImpl *impl);
+public:
+
+ HTMLDocument & operator = (const HTMLDocument &other);
+ HTMLDocument & operator = (const Node &other);
+
+ ~HTMLDocument();
+
+ /**
+ * The title of a document as specified by the \c TITLE
+ * element in the head of the document.
+ *
+ */
+ DOMString title() const;
+
+ /**
+ * see title
+ */
+ void setTitle( const DOMString & );
+
+ /**
+ * Returns the URI of the page that linked to this page. The value
+ * is an empty string if the user navigated to the page directly
+ * (not through a link, but, for example, via a bookmark).
+ */
+ DOMString referrer() const;
+
+ /**
+ * The domain name of the server that served the document, or a
+ * null string if the server cannot be identified by a domain
+ * name.
+ *
+ */
+ DOMString domain() const;
+
+ /**
+ * The absolute URI of the document.
+ */
+ DOMString URL() const;
+
+ /**
+ * The element that contains the content for the document. In
+ * documents with \c BODY contents, returns the
+ * \c BODY element, and in frameset documents, this returns
+ * the outermost \c FRAMESET element.
+ *
+ */
+ HTMLElement body() const;
+
+ /**
+ * see body
+ */
+ void setBody(const HTMLElement &);
+
+ /**
+ * A collection of all the \c IMG elements in a
+ * document. The behavior is limited to \c IMG
+ * elements for backwards compatibility.
+ *
+ */
+ HTMLCollection images() const;
+
+ /**
+ * A collection of all the \c OBJECT elements that
+ * include applets and \c APPLET ( deprecated )
+ * elements in a document.
+ *
+ */
+ HTMLCollection applets() const;
+
+ /**
+ * A collection of all \c AREA elements and anchor (
+ * \c A ) elements in a document with a value for the
+ * \c href attribute.
+ *
+ */
+ HTMLCollection links() const;
+
+ /**
+ * A collection of all the forms of a document.
+ *
+ */
+ HTMLCollection forms() const;
+
+ /**
+ * A collection of all the layers of a document.
+ *
+ */
+ HTMLCollection layers() const;
+
+ /**
+ * A collection of all the scripts in the document.
+ *
+ */
+ HTMLCollection scripts() const;
+
+ /**
+ * A collection of all the anchor ( \c A ) elements in
+ * a document with a value for the \c name attribute.
+ * Note. For reasons of backwards compatibility, the returned set
+ * of anchors only contains those anchors created with the
+ * \c name attribute, not those created with the \c id
+ * attribute.
+ *
+ */
+ HTMLCollection anchors() const;
+
+ /**
+ * The cookies associated with this document. If there are none,
+ * the value is an empty string. Otherwise, the value is a string:
+ * a semicolon-delimited list of "name, value" pairs for all the
+ * cookies associated with the page. For example,
+ * \c name=value;expires=date .
+ *
+ */
+ DOMString cookie() const;
+
+ /**
+ * see cookie
+ */
+ void setCookie( const DOMString & );
+
+ /**
+ * Note. This method and the ones following allow a user to add to
+ * or replace the structure model of a document using strings of
+ * unparsed HTML. At the time of writing alternate methods for
+ * providing similar functionality for both HTML and XML documents
+ * were being considered. The following methods may be deprecated
+ * at some point in the future in favor of a more general-purpose
+ * mechanism.
+ *
+ * Open a document stream for writing. If a document exists in
+ * the target, this method clears it.
+ *
+ * @return
+ *
+ */
+ void open ( );
+
+ /**
+ * Closes a document stream opened by \c open() and
+ * forces rendering.
+ *
+ * @return
+ *
+ */
+ void close ( );
+
+ /**
+ * Write a string of text to a document stream opened by
+ * \c open() . The text is parsed into the document's
+ * structure model.
+ *
+ * @param text The string to be parsed into some structure in the
+ * document structure model.
+ *
+ * @return
+ *
+ */
+ void write ( const DOMString &text );
+
+ /**
+ * Write a string of text followed by a newline character to a
+ * document stream opened by \c open() . The text is
+ * parsed into the document's structure model.
+ *
+ * @param text The string to be parsed into some structure in the
+ * document structure model.
+ *
+ * @return
+ *
+ */
+ void writeln ( const DOMString &text );
+
+ /**
+ * Returns the (possibly empty) collection of elements whose
+ * \c name value is given by \c elementName .
+ *
+ * @param elementName The \c name attribute value for
+ * an element.
+ *
+ * @return The matching elements.
+ *
+ */
+ NodeList getElementsByName ( const DOMString &elementName );
+
+ /**
+ * not part of the DOM
+ *
+ * converts the given (potentially relative) URL in a
+ * full-qualified one, using the baseURL / document URL for
+ * the missing parts.
+ */
+ DOMString completeURL( const DOMString& url) const;
+
+ /**
+ * Not part of the DOM
+ *
+ * The date the document was last modified.
+ */
+ DOMString lastModified() const;
+
+ /**
+ * Not part of the DOM
+ *
+ * A collection of all the \c IMG, \c OBJECT,
+ * \c AREA, \c A, forms and anchor elements of
+ * a document.
+ */
+ HTMLCollection all() const;
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_element.cpp b/tdehtml/dom/html_element.cpp
new file mode 100644
index 000000000..0063985ea
--- /dev/null
+++ b/tdehtml/dom/html_element.cpp
@@ -0,0 +1,186 @@
+/**
+ * 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 "dom/dom_exception.h"
+#include "dom/html_misc.h"
+#include "css/css_base.h"
+#include "html/html_miscimpl.h" // HTMLCollectionImpl
+
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLElement::HTMLElement() : Element()
+{
+}
+
+HTMLElement::HTMLElement(const HTMLElement &other) : Element(other)
+{
+}
+
+HTMLElement::HTMLElement(HTMLElementImpl *impl) : Element(impl)
+{
+}
+
+HTMLElement &HTMLElement::operator = (const HTMLElement &other)
+{
+ Element::operator = (other);
+ return *this;
+}
+
+HTMLElement &HTMLElement::operator = (const Node &other)
+{
+ NodeImpl* ohandle = other.handle();
+ if (!ohandle || !ohandle->isHTMLElement()) {
+ if (impl) impl->deref();
+ impl = 0;
+ return *this;
+ }
+ Node::operator = (other);
+ return *this;
+}
+
+HTMLElement::~HTMLElement()
+{
+}
+
+DOMString HTMLElement::id() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ID);
+}
+
+void HTMLElement::setId( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ID, value);
+}
+
+DOMString HTMLElement::title() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TITLE);
+}
+
+void HTMLElement::setTitle( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TITLE, value);
+}
+
+DOMString HTMLElement::lang() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_LANG);
+}
+
+void HTMLElement::setLang( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_LANG, value);
+}
+
+DOMString HTMLElement::dir() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_DIR);
+}
+
+void HTMLElement::setDir( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_DIR, value);
+}
+
+DOMString HTMLElement::className() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CLASS);
+}
+
+void HTMLElement::setClassName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CLASS, value);
+}
+
+void HTMLElement::removeCSSProperty( const DOMString &property )
+{
+ int id = getPropertyID(property.string().lower().ascii(), property.length());
+ if(id && impl)
+ static_cast<HTMLElementImpl*>(impl)->removeCSSProperty(id);
+}
+
+void HTMLElement::addCSSProperty( const DOMString &property, const DOMString &value )
+{
+ int id = getPropertyID(property.string().lower().ascii(), property.length());
+ if(id && impl)
+ static_cast<HTMLElementImpl*>(impl)->addCSSProperty(id, value);
+}
+
+DOMString HTMLElement::innerHTML() const
+{
+ if ( !impl ) return DOMString();
+ return ((HTMLElementImpl *)impl)->innerHTML();
+}
+
+void HTMLElement::setInnerHTML( const DOMString &html )
+{
+ if( !impl )
+ return;
+ int exceptioncode = 0;
+ ((HTMLElementImpl *)impl)->setInnerHTML( html, exceptioncode );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+DOMString HTMLElement::innerText() const
+{
+ if ( !impl ) return DOMString();
+ return ((HTMLElementImpl *)impl)->innerText();
+}
+
+void HTMLElement::setInnerText( const DOMString &text )
+{
+ if( !impl )
+ return;
+ int exceptioncode = 0;
+ ((HTMLElementImpl *)impl)->setInnerText( text, exceptioncode );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+HTMLCollection HTMLElement::children() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::NODE_CHILDREN);
+}
+
+HTMLCollection HTMLElement::all() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::DOC_ALL /*it's called "doc" but it works from any node */);
+}
+
+void HTMLElement::assignOther( const Node &other, int elementId )
+{
+ if (other.elementId() != static_cast<TQ_UINT32>(elementId)) {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+}
diff --git a/tdehtml/dom/html_element.h b/tdehtml/dom/html_element.h
new file mode 100644
index 000000000..1329793b2
--- /dev/null
+++ b/tdehtml/dom/html_element.h
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_ELEMENT_H
+#define HTML_ELEMENT_H
+
+#include <dom/dom_element.h>
+#include <tdelibs_export.h>
+
+class KHTMLView;
+
+namespace DOM {
+
+class HTMLElementImpl;
+class DOMString;
+class Element;
+class HTMLCollection;
+
+/**
+ * All HTML element interfaces derive from this class. Elements that
+ * only expose the HTML core attributes are represented by the base
+ * \c HTMLElement interface. These elements are as
+ * follows:
+ *
+ * \li \c HEAD
+ *
+ * \li special: <tt> SUB, SUP, SPAN, BDO </tt>
+ *
+ * \li font: <tt> TT, I, B, U, S, STRIKE, BIG, SMALL </tt>
+ *
+ * \li phrase: <tt> EM, STRONG, DFN, CODE, SAMP, KBD, VAR,
+ * CITE, ACRONYM, ABBR</tt>
+ *
+ * \li list: <tt> DD, DT </tt>
+ *
+ * \li <tt> NOFRAMES, NOSCRIPT </tt>
+ *
+ * \li <tt> ADDRESS, CENTER </tt>
+ *
+ * Note: The \c style attribute for this
+ * interface is reserved for future usage.
+ *
+ */
+class KHTML_EXPORT HTMLElement : public Element
+{
+ friend class HTMLDocument;
+ friend class ::KHTMLView;
+ friend class HTMLTableElement;
+ friend class HTMLTableRowElement;
+ friend class HTMLTableSectionElement;
+
+public:
+ HTMLElement();
+ HTMLElement(const HTMLElement &other);
+ HTMLElement(const Node &other) : Element()
+ {(*this)=other;}
+
+protected:
+ HTMLElement(HTMLElementImpl *impl);
+public:
+
+ HTMLElement & operator = (const HTMLElement &other);
+ HTMLElement & operator = (const Node &other);
+
+ ~HTMLElement();
+
+ /**
+ * The element's identifier. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-id">
+ * id attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString id() const;
+
+ /**
+ * see id
+ */
+ void setId( const DOMString & );
+
+ /**
+ * The element's advisory title. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-title">
+ * title attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString title() const;
+
+ /**
+ * see title
+ */
+ void setTitle( const DOMString & );
+
+ /**
+ * Language code defined in RFC 1766. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/dirlang.html#adef-lang">
+ * lang attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString lang() const;
+
+ /**
+ * see lang
+ */
+ void setLang( const DOMString & );
+
+ /**
+ * Specifies the base direction of directionally neutral text and
+ * the directionality of tables. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/dirlang.html#adef-dir">
+ * dir attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString dir() const;
+
+ /**
+ * see dir
+ */
+ void setDir( const DOMString & );
+
+ /**
+ * The class attribute of the element. This attribute has been
+ * renamed due to conflicts with the "class" keyword exposed by
+ * many languages. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-class">
+ * class attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString className() const;
+
+ /**
+ * see className
+ */
+ void setClassName( const DOMString & );
+
+ /**
+ * The HTML code contained in this element.
+ * This function is not part of the DOM specifications as defined by the w3c.
+ */
+ DOMString innerHTML() const;
+
+ /**
+ * Set the HTML content of this node.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if there is the element does not allow
+ * children.
+ */
+ void setInnerHTML( const DOMString &html );
+
+ /**
+ * The text contained in this element.
+ * This function is not part of the DOM specifications as defined by the w3c.
+ */
+ DOMString innerText() const;
+
+ /**
+ * Set the text content of this node.
+ *
+ * @exception DOMException
+ * NO_MODIFICATION_ALLOWED_ERR: Raised if there is the element does not allow
+ * children.
+ */
+ void setInnerText( const DOMString &text );
+
+ /**
+ * Retrieves a collection of nodes that are direct descendants of this node.
+ * IE-specific extension.
+ */
+ HTMLCollection children() const;
+
+ /**
+ * Retrieves a collection of all nodes that descend from this node.
+ * IE-specific extension.
+ */
+ HTMLCollection all() const;
+
+ /*
+ * @internal
+ */
+ void removeCSSProperty( const DOMString& property );
+
+ /*
+ * @internal
+ */
+ void addCSSProperty( const DOMString &property, const DOMString &value );
+
+protected:
+ /*
+ * @internal
+ */
+ void assignOther( const Node &other, int elementId );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_form.cpp b/tdehtml/dom/html_form.cpp
new file mode 100644
index 000000000..5d9aec633
--- /dev/null
+++ b/tdehtml/dom/html_form.cpp
@@ -0,0 +1,1302 @@
+/**
+ * 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 "dom/html_form.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_doc.h"
+
+#include "html/html_formimpl.h"
+#include "html/html_miscimpl.h"
+
+#include "xml/dom_docimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLButtonElement::HTMLButtonElement() : HTMLElement()
+{
+}
+
+HTMLButtonElement::HTMLButtonElement(const HTMLButtonElement &other) : HTMLElement(other)
+{
+}
+
+HTMLButtonElement::HTMLButtonElement(HTMLButtonElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLButtonElement &HTMLButtonElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BUTTON );
+ return *this;
+}
+
+HTMLButtonElement &HTMLButtonElement::operator = (const HTMLButtonElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLButtonElement::~HTMLButtonElement()
+{
+}
+
+HTMLFormElement HTMLButtonElement::form() const
+{
+ return Element::form();
+}
+
+DOMString HTMLButtonElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLButtonElement::setAccessKey( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+bool HTMLButtonElement::disabled() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLButtonElement::setDisabled( bool _disabled )
+{
+ if (impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+DOMString HTMLButtonElement::name() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLButtonElement::setName( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_NAME, value);
+}
+
+void HTMLButtonElement::focus( )
+{
+ if(impl)
+ static_cast<HTMLButtonElementImpl*>(impl)->focus();
+}
+
+void HTMLButtonElement::blur( )
+{
+ if(impl)
+ static_cast<HTMLButtonElementImpl*>(impl)->blur();
+}
+
+long HTMLButtonElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return static_cast<ElementImpl*>(impl)->tabIndex();
+}
+
+void HTMLButtonElement::setTabIndex( long _tabIndex )
+{
+ if (!impl) return;
+ static_cast<ElementImpl*>(impl)->setTabIndex(_tabIndex);
+}
+
+DOMString HTMLButtonElement::type() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLButtonElementImpl*>(impl)->type();
+}
+
+DOMString HTMLButtonElement::value() const
+{
+ if(!impl) return DOMString();
+ DOMString s = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_VALUE);
+ if (s.isNull()) return DOMString("");
+ return s;
+}
+
+void HTMLButtonElement::setValue( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_VALUE, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLFieldSetElement::HTMLFieldSetElement() : HTMLElement()
+{
+}
+
+HTMLFieldSetElement::HTMLFieldSetElement(const HTMLFieldSetElement &other) : HTMLElement(other)
+{
+}
+
+HTMLFieldSetElement::HTMLFieldSetElement(HTMLFieldSetElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLFieldSetElement &HTMLFieldSetElement::operator = (const Node &other)
+{
+ assignOther( other, ID_FIELDSET );
+ return *this;
+}
+
+HTMLFieldSetElement &HTMLFieldSetElement::operator = (const HTMLFieldSetElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLFieldSetElement::~HTMLFieldSetElement()
+{
+}
+
+HTMLFormElement HTMLFieldSetElement::form() const
+{
+ return Element::form();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLFormElement::HTMLFormElement() : HTMLElement()
+{
+}
+
+HTMLFormElement::HTMLFormElement(const HTMLFormElement &other) : HTMLElement(other)
+{
+}
+
+HTMLFormElement::HTMLFormElement(HTMLFormElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLFormElement &HTMLFormElement::operator = (const Node &other)
+{
+ assignOther( other, ID_FORM );
+ return *this;
+}
+
+HTMLFormElement &HTMLFormElement::operator = (const HTMLFormElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLFormElement::~HTMLFormElement()
+{
+}
+
+HTMLCollection HTMLFormElement::elements() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLFormCollection(impl);
+}
+
+long HTMLFormElement::length() const
+{
+ if(!impl) return 0;
+ return static_cast<HTMLFormElementImpl*>(impl)->length();
+}
+
+DOMString HTMLFormElement::name() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLFormElement::setName( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLFormElement::acceptCharset() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACCEPT_CHARSET);
+}
+
+void HTMLFormElement::setAcceptCharset( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACCEPT_CHARSET, value);
+}
+
+DOMString HTMLFormElement::action() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACTION);
+}
+
+void HTMLFormElement::setAction( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACTION, value);
+}
+
+DOMString HTMLFormElement::enctype() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ENCTYPE);
+}
+
+void HTMLFormElement::setEnctype( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ENCTYPE, value);
+}
+
+DOMString HTMLFormElement::method() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_METHOD);
+}
+
+void HTMLFormElement::setMethod( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_METHOD, value);
+}
+
+DOMString HTMLFormElement::target() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_TARGET);
+}
+
+void HTMLFormElement::setTarget( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_TARGET, value);
+}
+
+void HTMLFormElement::submit( )
+{
+ if(impl) static_cast<HTMLFormElementImpl*>(impl)->submit( );
+}
+
+void HTMLFormElement::reset( )
+{
+ if(impl) static_cast<HTMLFormElementImpl*>(impl)->reset( );
+}
+
+// --------------------------------------------------------------------------
+
+HTMLInputElement::HTMLInputElement() : HTMLElement()
+{
+}
+
+HTMLInputElement::HTMLInputElement(const HTMLInputElement &other) : HTMLElement(other)
+{
+}
+
+HTMLInputElement::HTMLInputElement(HTMLInputElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLInputElement &HTMLInputElement::operator = (const Node &other)
+{
+ assignOther( other, ID_INPUT );
+ return *this;
+}
+
+HTMLInputElement &HTMLInputElement::operator = (const HTMLInputElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLInputElement::~HTMLInputElement()
+{
+}
+
+DOMString HTMLInputElement::defaultValue() const
+{
+ if(!impl) return DOMString();
+ DOMString s = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_VALUE);
+ if (s.isNull()) return DOMString("");
+ return s;
+
+}
+
+void HTMLInputElement::setDefaultValue( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALUE, value);
+}
+
+bool HTMLInputElement::defaultChecked() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_CHECKED).isNull();
+}
+
+void HTMLInputElement::setDefaultChecked( bool _defaultChecked )
+{
+ if(impl)
+ ((ElementImpl *)impl)->setAttribute(ATTR_CHECKED, _defaultChecked ? "" : 0);
+}
+
+HTMLFormElement HTMLInputElement::form() const
+{
+ return Element::form();
+}
+
+DOMString HTMLInputElement::accept() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ACCEPT);
+}
+
+void HTMLInputElement::setAccept( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ACCEPT, value);
+}
+
+DOMString HTMLInputElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLInputElement::setAccessKey( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+DOMString HTMLInputElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLInputElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLInputElement::alt() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALT);
+}
+
+void HTMLInputElement::setAlt( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALT, value);
+}
+
+bool HTMLInputElement::checked() const
+{
+ if(!impl) return 0;
+ return ((HTMLInputElementImpl*)impl)->checked();
+}
+
+void HTMLInputElement::setChecked( bool _checked )
+{
+ if(impl)
+ ((HTMLInputElementImpl*)impl)->setChecked(_checked);
+}
+
+bool HTMLInputElement::indeterminate() const
+{
+ if(!impl) return 0;
+ return ((HTMLInputElementImpl*)impl)->indeterminate();
+}
+
+void HTMLInputElement::setIndeterminate( bool _indeterminate )
+{
+ if(impl)
+ ((HTMLInputElementImpl*)impl)->setIndeterminate(_indeterminate);
+}
+
+bool HTMLInputElement::disabled() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLInputElement::setDisabled( bool _disabled )
+{
+ if(impl)
+ {
+ ((ElementImpl *)impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+ }
+}
+
+long HTMLInputElement::maxLength() const
+{
+ if(!impl) return 0;
+ return ((HTMLInputElementImpl *)impl)->getAttribute(ATTR_MAXLENGTH).toInt();
+}
+
+void HTMLInputElement::setMaxLength( long _maxLength )
+{
+ if(impl) {
+ DOMString value(TQString::number(_maxLength));
+ ((ElementImpl *)impl)->setAttribute(ATTR_MAXLENGTH,value);
+ }
+}
+
+DOMString HTMLInputElement::name() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLInputElementImpl* const>(impl)->name();
+}
+
+void HTMLInputElement::setName( const DOMString &value )
+{
+ if(impl) static_cast<HTMLInputElementImpl*>(impl)->setName(value);
+}
+
+bool HTMLInputElement::readOnly() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_READONLY).isNull();
+}
+
+void HTMLInputElement::setReadOnly( bool _readOnly )
+{
+ if(impl)
+ static_cast<ElementImpl*>(impl)->setAttribute(ATTR_READONLY, _readOnly ? "" : 0);
+}
+
+/* The next two are provided for backwards compatibility. */
+DOMString HTMLInputElement::size() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_SIZE);
+}
+
+void HTMLInputElement::setSize( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_SIZE, value);
+}
+
+long HTMLInputElement::getSize() const
+{
+ if(!impl) return 0;
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_SIZE).toInt();
+}
+
+void HTMLInputElement::setSize( long value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_SIZE, TQString::number(value));
+}
+
+DOMString HTMLInputElement::src() const
+{
+ if(!impl) return DOMString();
+ DOMString s = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_SRC);
+ return !s.isNull() ? impl->getDocument()->completeURL( s.string() ) : s;
+}
+
+void HTMLInputElement::setSrc( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_SRC, value);
+}
+
+long HTMLInputElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return static_cast<ElementImpl*>(impl)->tabIndex();
+}
+
+void HTMLInputElement::setTabIndex( long _tabIndex )
+{
+ if (!impl) return;
+ static_cast<ElementImpl*>(impl)->setTabIndex(_tabIndex);
+}
+
+DOMString HTMLInputElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLInputElementImpl *)impl)->type();
+}
+
+void HTMLInputElement::setType(const DOMString& _type)
+{
+ if (!impl) return;
+ static_cast<HTMLInputElementImpl*>(impl)->setType(_type);
+}
+
+DOMString HTMLInputElement::useMap() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_USEMAP);
+}
+
+void HTMLInputElement::setUseMap( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_USEMAP, value);
+}
+
+DOMString HTMLInputElement::value() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLInputElementImpl*)impl)->value();
+}
+
+void HTMLInputElement::setValue( const DOMString &value )
+{
+ if (impl)
+ ((HTMLInputElementImpl*)impl)->setValue(value);
+
+}
+
+void HTMLInputElement::blur( )
+{
+ if(impl)
+ ((HTMLInputElementImpl*)impl)->blur();
+}
+
+void HTMLInputElement::focus( )
+{
+ if(impl)
+ ((HTMLInputElementImpl*)impl)->focus();
+}
+
+void HTMLInputElement::select( )
+{
+ if(impl)
+ ((HTMLInputElementImpl *)impl)->select( );
+}
+
+void HTMLInputElement::click( )
+{
+ if(impl)
+ ((HTMLInputElementImpl *)impl)->click( );
+}
+
+long HTMLInputElement::selectionStart()
+{
+ if (impl)
+ return ((HTMLInputElementImpl *)impl)->selectionStart( );
+ return -1;
+}
+
+long HTMLInputElement::selectionEnd()
+{
+ if (impl)
+ return ((HTMLInputElementImpl *)impl)->selectionEnd( );
+ return -1;
+}
+
+void HTMLInputElement::setSelectionStart(long pos)
+{
+ if (impl)
+ ((HTMLInputElementImpl *)impl)->setSelectionStart( pos );
+}
+
+void HTMLInputElement::setSelectionEnd(long pos)
+{
+ if (impl)
+ ((HTMLInputElementImpl *)impl)->setSelectionEnd( pos );
+}
+
+void HTMLInputElement::setSelectionRange(long start, long end)
+{
+ if (impl)
+ ((HTMLInputElementImpl *)impl)->setSelectionRange( start, end );
+}
+
+// --------------------------------------------------------------------------
+
+HTMLLabelElement::HTMLLabelElement() : HTMLElement()
+{
+}
+
+HTMLLabelElement::HTMLLabelElement(const HTMLLabelElement &other) : HTMLElement(other)
+{
+}
+
+HTMLLabelElement::HTMLLabelElement(HTMLLabelElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLLabelElement &HTMLLabelElement::operator = (const Node &other)
+{
+ assignOther( other, ID_LABEL );
+ return *this;
+}
+
+HTMLLabelElement &HTMLLabelElement::operator = (const HTMLLabelElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLLabelElement::~HTMLLabelElement()
+{
+}
+
+DOMString HTMLLabelElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLLabelElement::setAccessKey( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+DOMString HTMLLabelElement::htmlFor() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_FOR);
+}
+
+void HTMLLabelElement::setHtmlFor( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_FOR, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLLegendElement::HTMLLegendElement() : HTMLElement()
+{
+}
+
+HTMLLegendElement::HTMLLegendElement(const HTMLLegendElement &other) : HTMLElement(other)
+{
+}
+
+HTMLLegendElement::HTMLLegendElement(HTMLLegendElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLLegendElement &HTMLLegendElement::operator = (const Node &other)
+{
+ assignOther( other, ID_LEGEND );
+ return *this;
+}
+
+HTMLLegendElement &HTMLLegendElement::operator = (const HTMLLegendElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLLegendElement::~HTMLLegendElement()
+{
+}
+
+HTMLFormElement HTMLLegendElement::form() const
+{
+ return Element::form();
+}
+
+DOMString HTMLLegendElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLLegendElement::setAccessKey( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+DOMString HTMLLegendElement::align() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLLegendElement::setAlign( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLOptGroupElement::HTMLOptGroupElement() : HTMLElement()
+{
+}
+
+HTMLOptGroupElement::HTMLOptGroupElement(const HTMLOptGroupElement &other) : HTMLElement(other)
+{
+}
+
+HTMLOptGroupElement::HTMLOptGroupElement(HTMLOptGroupElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLOptGroupElement &HTMLOptGroupElement::operator = (const Node &other)
+{
+ assignOther( other, ID_OPTGROUP );
+ return *this;
+}
+
+HTMLOptGroupElement &HTMLOptGroupElement::operator = (const HTMLOptGroupElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLOptGroupElement::~HTMLOptGroupElement()
+{
+}
+
+bool HTMLOptGroupElement::disabled() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLOptGroupElement::setDisabled( bool _disabled )
+{
+ if(impl)
+ static_cast<ElementImpl*>(impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+DOMString HTMLOptGroupElement::label() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_LABEL);
+}
+
+void HTMLOptGroupElement::setLabel( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_LABEL, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLSelectElement::HTMLSelectElement() : HTMLElement()
+{
+}
+
+HTMLSelectElement::HTMLSelectElement(const HTMLSelectElement &other) : HTMLElement(other)
+{
+}
+
+HTMLSelectElement::HTMLSelectElement(HTMLSelectElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLSelectElement &HTMLSelectElement::operator = (const Node &other)
+{
+ assignOther( other, ID_SELECT );
+ return *this;
+}
+
+HTMLSelectElement &HTMLSelectElement::operator = (const HTMLSelectElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLSelectElement::~HTMLSelectElement()
+{
+}
+
+DOMString HTMLSelectElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLSelectElementImpl *)impl)->type();
+}
+
+long HTMLSelectElement::selectedIndex() const
+{
+ if(!impl) return 0;
+ return ((HTMLSelectElementImpl *)impl)->selectedIndex();
+}
+
+void HTMLSelectElement::setSelectedIndex( long _selectedIndex )
+{
+ if(impl)
+ ((HTMLSelectElementImpl *)impl)->setSelectedIndex(_selectedIndex);
+}
+
+DOMString HTMLSelectElement::value() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLSelectElementImpl*>(impl)->value();
+}
+
+void HTMLSelectElement::setValue( const DOMString &value )
+{
+ if(!impl || value.isNull()) return;
+ static_cast<HTMLSelectElementImpl*>(impl)->setValue(value.implementation());
+}
+
+long HTMLSelectElement::length() const
+{
+ if(!impl) return 0;
+ return ((HTMLSelectElementImpl *)impl)->length();
+}
+
+HTMLFormElement HTMLSelectElement::form() const
+{
+ return Element::form();
+}
+
+HTMLCollection HTMLSelectElement::options() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::SELECT_OPTIONS);
+}
+
+bool HTMLSelectElement::disabled() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLSelectElement::setDisabled( bool _disabled )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+
+bool HTMLSelectElement::multiple() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_MULTIPLE).isNull();
+}
+
+void HTMLSelectElement::setMultiple( bool _multiple )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_MULTIPLE, _multiple ? "" : 0);
+}
+
+DOMString HTMLSelectElement::name() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLSelectElementImpl* const>(impl)->name();
+}
+
+void HTMLSelectElement::setName( const DOMString &value )
+{
+ if(impl) static_cast<HTMLSelectElementImpl*>(impl)->setName(value);
+}
+
+long HTMLSelectElement::size() const
+{
+ if(!impl) return 0;
+ return ((HTMLSelectElementImpl *)impl)->getAttribute(ATTR_SIZE).toInt();
+}
+
+void HTMLSelectElement::setSize( long _size )
+{
+
+ if(impl) {
+ DOMString value(TQString::number(_size));
+ static_cast<ElementImpl*>(impl)->setAttribute(ATTR_SIZE,value);
+ }
+}
+
+long HTMLSelectElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return static_cast<ElementImpl*>(impl)->tabIndex();
+}
+
+void HTMLSelectElement::setTabIndex( long _tabIndex )
+{
+ if (!impl) return;
+ static_cast<ElementImpl*>(impl)->setTabIndex(_tabIndex);
+}
+
+void HTMLSelectElement::add( const HTMLElement &element, const HTMLElement &before )
+{
+ if (!impl)
+ throw DOMException(DOMException::NOT_FOUND_ERR);
+
+ int exceptioncode = 0;
+ static_cast<HTMLSelectElementImpl*>(impl)->add( element, before, exceptioncode );
+ if ( exceptioncode )
+ throw DOMException( exceptioncode );
+}
+
+void HTMLSelectElement::remove( long index )
+{
+ if(impl) static_cast<HTMLSelectElementImpl*>(impl)->remove( index );
+}
+
+void HTMLSelectElement::blur( )
+{
+ if(impl)
+ ((HTMLSelectElementImpl*)impl)->blur();
+}
+
+void HTMLSelectElement::focus( )
+{
+ if(impl)
+ ((HTMLSelectElementImpl*)impl)->focus();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTextAreaElement::HTMLTextAreaElement() : HTMLElement()
+{
+}
+
+HTMLTextAreaElement::HTMLTextAreaElement(const HTMLTextAreaElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTextAreaElement::HTMLTextAreaElement(HTMLTextAreaElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTextAreaElement &HTMLTextAreaElement::operator = (const Node &other)
+{
+ assignOther( other, ID_TEXTAREA );
+ return *this;
+}
+
+HTMLTextAreaElement &HTMLTextAreaElement::operator = (const HTMLTextAreaElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTextAreaElement::~HTMLTextAreaElement()
+{
+}
+
+DOMString HTMLTextAreaElement::defaultValue() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLTextAreaElementImpl *)impl)->defaultValue();
+}
+
+void HTMLTextAreaElement::setDefaultValue( const DOMString &value )
+{
+ if (impl) ((HTMLTextAreaElementImpl *)impl)->setDefaultValue(value);
+}
+
+HTMLFormElement HTMLTextAreaElement::form() const
+{
+ return Element::form();
+}
+
+DOMString HTMLTextAreaElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLTextAreaElement::setAccessKey( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+long HTMLTextAreaElement::cols() const
+{
+ if(!impl) return 0;
+ return ((HTMLTextAreaElementImpl *)impl)->getAttribute(ATTR_COLS).toInt();
+}
+
+void HTMLTextAreaElement::setCols( long _cols )
+{
+
+ if(impl) {
+ DOMString value(TQString::number(_cols));
+ static_cast<ElementImpl*>(impl)->setAttribute(ATTR_COLS,value);
+ }
+}
+
+bool HTMLTextAreaElement::disabled() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLTextAreaElement::setDisabled( bool _disabled )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+DOMString HTMLTextAreaElement::name() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLTextAreaElementImpl* const>(impl)->name();
+}
+
+void HTMLTextAreaElement::setName( const DOMString &value )
+{
+ if(impl) static_cast<HTMLTextAreaElementImpl*>(impl)->setName(value);
+}
+
+bool HTMLTextAreaElement::readOnly() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_READONLY).isNull();
+}
+
+void HTMLTextAreaElement::setReadOnly( bool _readOnly )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_READONLY, _readOnly ? "" : 0);
+}
+
+long HTMLTextAreaElement::rows() const
+{
+ if(!impl) return 0;
+ return ((HTMLTextAreaElementImpl *)impl)->getAttribute(ATTR_ROWS).toInt();
+}
+
+void HTMLTextAreaElement::setRows( long _rows )
+{
+
+ if(impl) {
+ DOMString value(TQString::number(_rows));
+ static_cast<ElementImpl*>(impl)->setAttribute(ATTR_ROWS,value);
+ }
+}
+
+long HTMLTextAreaElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return static_cast<ElementImpl*>(impl)->tabIndex();
+}
+
+void HTMLTextAreaElement::setTabIndex( long _tabIndex )
+{
+ if (!impl) return;
+ static_cast<ElementImpl*>(impl)->setTabIndex(_tabIndex);
+}
+
+DOMString HTMLTextAreaElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLTextAreaElementImpl *)impl)->type();
+}
+
+DOMString HTMLTextAreaElement::value() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLTextAreaElementImpl *)impl)->value();
+}
+
+void HTMLTextAreaElement::setValue( const DOMString &value )
+{
+ if(impl) ((HTMLTextAreaElementImpl *)impl)->setValue(value);
+}
+
+void HTMLTextAreaElement::blur( )
+{
+ if(impl)
+ ((HTMLTextAreaElementImpl*)impl)->blur();
+}
+
+void HTMLTextAreaElement::focus( )
+{
+ if(impl)
+ ((HTMLTextAreaElementImpl*)impl)->focus();
+}
+
+void HTMLTextAreaElement::select( )
+{
+ if(impl)
+ ((HTMLTextAreaElementImpl *)impl)->select( );
+}
+
+long HTMLTextAreaElement::selectionStart()
+{
+ if (impl)
+ return ((HTMLTextAreaElementImpl *)impl)->selectionStart( );
+ return 0;
+}
+
+long HTMLTextAreaElement::selectionEnd()
+{
+ if (impl)
+ return ((HTMLTextAreaElementImpl *)impl)->selectionEnd( );
+ return 0;
+}
+
+long HTMLTextAreaElement::textLength()
+{
+ if (impl)
+ return ((HTMLTextAreaElementImpl *)impl)->textLength( );
+ return 0;
+}
+
+void HTMLTextAreaElement::setSelectionStart(long pos)
+{
+ if (impl)
+ ((HTMLTextAreaElementImpl *)impl)->setSelectionStart( pos );
+}
+
+void HTMLTextAreaElement::setSelectionEnd(long pos)
+{
+ if (impl)
+ ((HTMLTextAreaElementImpl *)impl)->setSelectionEnd( pos );
+}
+
+void HTMLTextAreaElement::setSelectionRange(long start, long end)
+{
+ if (impl)
+ ((HTMLTextAreaElementImpl *)impl)->setSelectionRange( start, end );
+}
+
+// --------------------------------------------------------------------------
+
+HTMLOptionElement::HTMLOptionElement() : HTMLElement()
+{
+}
+
+HTMLOptionElement::HTMLOptionElement(const HTMLOptionElement &other) : HTMLElement(other)
+{
+}
+
+HTMLOptionElement::HTMLOptionElement(HTMLOptionElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLOptionElement &HTMLOptionElement::operator = (const Node &other)
+{
+ assignOther( other, ID_OPTION );
+ return *this;
+}
+
+HTMLOptionElement &HTMLOptionElement::operator = (const HTMLOptionElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLOptionElement::~HTMLOptionElement()
+{
+}
+
+HTMLFormElement HTMLOptionElement::form() const
+{
+ return Element::form();
+}
+
+bool HTMLOptionElement::defaultSelected() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_SELECTED).isNull();
+}
+
+void HTMLOptionElement::setDefaultSelected( bool _defaultSelected )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_SELECTED, _defaultSelected ? "" : 0);
+}
+
+DOMString HTMLOptionElement::text() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLOptionElementImpl *)impl)->text();
+}
+
+long HTMLOptionElement::index() const
+{
+ if(!impl) return 0;
+ return ((HTMLOptionElementImpl *)impl)->index();
+}
+
+void HTMLOptionElement::setIndex( long /*_index*/ )
+{
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+}
+
+bool HTMLOptionElement::disabled() const
+{
+ if(!impl) return 0;
+ return !static_cast<ElementImpl*>(impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLOptionElement::setDisabled( bool _disabled )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+DOMString HTMLOptionElement::label() const
+{
+ if(!impl) return DOMString();
+ return static_cast<ElementImpl*>(impl)->getAttribute(ATTR_LABEL);
+}
+
+void HTMLOptionElement::setLabel( const DOMString &value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_LABEL, value);
+}
+
+bool HTMLOptionElement::selected() const
+{
+ if(!impl) return 0;
+ return ((HTMLOptionElementImpl *)impl)->selected();
+}
+
+void HTMLOptionElement::setSelected(bool _selected) {
+ if(!impl) return;
+ ((HTMLOptionElementImpl *)impl)->setSelected(_selected);
+}
+
+DOMString HTMLOptionElement::value() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLOptionElementImpl*>(impl)->value();
+}
+
+void HTMLOptionElement::setValue( const DOMString &value )
+{
+ if(impl) static_cast<HTMLOptionElementImpl*>(impl)->setValue(value.implementation());
+}
+
+// -----------------------------------------------------------------------------
+
+HTMLIsIndexElement::HTMLIsIndexElement() : HTMLElement()
+{
+}
+
+HTMLIsIndexElement::HTMLIsIndexElement(const HTMLIsIndexElement &other) : HTMLElement(other)
+{
+}
+
+HTMLIsIndexElement::HTMLIsIndexElement(HTMLIsIndexElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLIsIndexElement &HTMLIsIndexElement::operator = (const Node &other)
+{
+ assignOther( other, ID_ISINDEX );
+ return *this;
+}
+
+HTMLIsIndexElement &HTMLIsIndexElement::operator = (const HTMLIsIndexElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLIsIndexElement::~HTMLIsIndexElement()
+{
+}
+
+HTMLFormElement HTMLIsIndexElement::form() const
+{
+ return Element::form();
+}
+
+DOMString HTMLIsIndexElement::prompt() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLIsIndexElementImpl*>(impl)->prompt();
+}
+
+void HTMLIsIndexElement::setPrompt( const DOMString &value )
+{
+ if(impl) static_cast<HTMLIsIndexElementImpl*>(impl)->setPrompt(value);
+}
diff --git a/tdehtml/dom/html_form.h b/tdehtml/dom/html_form.h
new file mode 100644
index 000000000..0623e421b
--- /dev/null
+++ b/tdehtml/dom/html_form.h
@@ -0,0 +1,1427 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_FORM_H
+#define HTML_FORM_H
+
+// --------------------------------------------------------------------------
+#include <dom/html_element.h>
+#include <dom/html_misc.h>
+
+#include <kdemacros.h>
+
+namespace DOM {
+
+class HTMLButtonElementImpl;
+class HTMLFormElement;
+class DOMString;
+
+/**
+ * Push button. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-BUTTON">
+ * BUTTON element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLButtonElement : public HTMLElement
+{
+public:
+ HTMLButtonElement();
+ HTMLButtonElement(const HTMLButtonElement &other);
+ HTMLButtonElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLButtonElement(HTMLButtonElementImpl *impl);
+public:
+
+ HTMLButtonElement & operator = (const HTMLButtonElement &other);
+ HTMLButtonElement & operator = (const Node &other);
+
+ ~HTMLButtonElement();
+
+ /**
+ * Returns the \c FORM element containing this
+ * control. Returns null if this control is not within the context
+ * of a form.
+ *
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Form control or object name when submitted with a form. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-name-BUTTON">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * The type of button. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-type-BUTTON">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * The current form control value. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-value-BUTTON">
+ * value attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * Removes keyboard focus from this element.
+ *
+ */
+ void blur ( );
+
+ /**
+ * Gives keyboard focus to this element.
+ *
+ */
+ void focus ( );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLFieldSetElementImpl;
+/**
+ * Organizes form controls into logical groups. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-FIELDSET">
+ * FIELDSET element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLFieldSetElement : public HTMLElement
+{
+public:
+ HTMLFieldSetElement();
+ HTMLFieldSetElement(const HTMLFieldSetElement &other);
+ HTMLFieldSetElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLFieldSetElement(HTMLFieldSetElementImpl *impl);
+public:
+
+ HTMLFieldSetElement & operator = (const HTMLFieldSetElement &other);
+ HTMLFieldSetElement & operator = (const Node &other);
+
+ ~HTMLFieldSetElement();
+
+ /**
+ * ### KDE 4.0: remove.
+ */
+ HTMLFormElement form() const;
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLFormElementImpl;
+/**
+ * The \c FORM element encompasses behavior similar to a
+ * collection and an element. It provides direct access to the
+ * contained input elements as well as the attributes of the form
+ * element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-FORM">
+ * FORM element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLFormElement : public HTMLElement
+{
+ friend class HTMLButtonElement;
+ friend class HTMLFieldSetElement;
+ friend class HTMLInputElement;
+ friend class HTMLLabelElement;
+ friend class HTMLLegendElement;
+ friend class HTMLSelectElement;
+ friend class HTMLTextAreaElement;
+ friend class HTMLOptionElement;
+ friend class HTMLIsIndexElement;
+ friend class HTMLObjectElement;
+
+public:
+ HTMLFormElement();
+ HTMLFormElement(const HTMLFormElement &other);
+ HTMLFormElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLFormElement(HTMLFormElementImpl *impl);
+public:
+
+ HTMLFormElement & operator = (const HTMLFormElement &other);
+ HTMLFormElement & operator = (const Node &other);
+
+ ~HTMLFormElement();
+
+ /**
+ * Returns a collection of all control elements in the form.
+ *
+ */
+ HTMLCollection elements() const;
+
+ /**
+ * The number of form controls in the form.
+ *
+ */
+ long length() const;
+
+ /**
+ * Names the form.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * List of character sets supported by the server. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accept-charset">
+ * accept-charset attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString acceptCharset() const;
+
+ /**
+ * see acceptCharset
+ */
+ void setAcceptCharset( const DOMString & );
+
+ /**
+ * Server-side form handler. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-action">
+ * action attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString action() const;
+
+ /**
+ * see action
+ */
+ void setAction( const DOMString & );
+
+ /**
+ * The content type of the submitted form, generally
+ * "application/x-www-form-urlencoded". See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-enctype">
+ * enctype attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString enctype() const;
+
+ /**
+ * see enctype
+ */
+ void setEnctype( const DOMString & );
+
+ /**
+ * HTTP method used to submit form. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-method">
+ * method attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString method() const;
+
+ /**
+ * see method
+ */
+ void setMethod( const DOMString & );
+
+ /**
+ * Frame to render the resource in. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">
+ * target attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * see target
+ */
+ void setTarget( const DOMString & );
+
+ /**
+ * Submits the form. It performs the same action as a submit
+ * button.
+ *
+ */
+ void submit ( );
+
+ /**
+ * Restores a form element's default values. It performs the same
+ * action as a reset button.
+ *
+ */
+ void reset ( );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLInputElementImpl;
+/**
+ * Form control. Note. Depending upon the environment the page is
+ * being viewed, the value property may be read-only for the file
+ * upload input type. For the "password" input type, the actual value
+ * returned may be masked to prevent unauthorized use. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-INPUT">
+ * INPUT element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLInputElement : public HTMLElement
+{
+public:
+ HTMLInputElement();
+ HTMLInputElement(const HTMLInputElement &other);
+ HTMLInputElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLInputElement(HTMLInputElementImpl *impl);
+public:
+
+ HTMLInputElement & operator = (const HTMLInputElement &other);
+ HTMLInputElement & operator = (const Node &other);
+
+ ~HTMLInputElement();
+
+ /**
+ * Stores the initial control value (i.e., the initial value of
+ * \c value ).
+ *
+ */
+ DOMString defaultValue() const;
+
+ /**
+ * see defaultValue
+ */
+ void setDefaultValue( const DOMString & );
+
+ /**
+ * When \c type has the value "Radio" or "Checkbox",
+ * stores the initial value of the \c checked
+ * attribute.
+ *
+ */
+ bool defaultChecked() const;
+
+ /**
+ * see defaultChecked
+ */
+ void setDefaultChecked( bool );
+
+ /**
+ * ### KDE 4.0: remove.
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * A comma-separated list of content types that a server
+ * processing this form will handle correctly. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accept">
+ * accept attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accept() const;
+
+ /**
+ * see accept
+ */
+ void setAccept( const DOMString & );
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * Aligns this object (vertically or horizontally) with respect to
+ * its surrounding text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-align-IMG">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Alternate text for user agents not rendering the normal content
+ * of this element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-alt">
+ * alt attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString alt() const;
+
+ /**
+ * see alt
+ */
+ void setAlt( const DOMString & );
+
+ /**
+ * Describes whether a radio or check box is checked, when
+ * \c type has the value "Radio" or "Checkbox". The value is
+ * true if explicitly set. Represents the current state of the
+ * checkbox or radio button. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-checked">
+ * checked attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool checked() const;
+
+ /**
+ * see checked
+ */
+ void setChecked( bool );
+
+ /**
+ * Describes whether a radio box is indeterminate
+ */
+ bool indeterminate() const;
+
+ /**
+ * see indeterminate
+ */
+ void setIndeterminate( bool );
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Maximum number of characters for text fields, when \c type
+ * has the value "Text" or "Password". See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-maxlength">
+ * maxlength attribute definition </a> in HTML 4.0.
+ *
+ */
+ long maxLength() const;
+
+ /**
+ * see maxLength
+ */
+ void setMaxLength( long );
+
+ /**
+ * Form control or object name when submitted with a form. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-name-INPUT">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * This control is read-only. When \c type has the
+ * value "text" or "password" only. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-readonly">
+ * readonly attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool readOnly() const;
+
+ // ### remove in 4.0
+ /**
+ * see readOnly
+ */
+ void setReadOnly( bool );
+
+ /**
+ * @deprecated
+ */
+ DOMString size() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setSize( const DOMString & ) KDE_DEPRECATED;
+
+ /**
+ * Size information. The precise meaning is specific to each type
+ * of field. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-size-INPUT">
+ * size attribute definition </a> in HTML 4.0.
+ *
+ */
+ long getSize() const;
+
+ /**
+ * see getSize
+ */
+ void setSize( long );
+
+ /**
+ * When the \c type attribute has the value "Image",
+ * this attribute specifies the location of the image to be used
+ * to decorate the graphical submit button. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-src">
+ * src attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString src() const;
+
+ /**
+ * see src
+ */
+ void setSrc( const DOMString & );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * The type of control created. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-type-INPUT">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType(const DOMString&);
+
+ /**
+ * Use client-side image map. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-usemap">
+ * usemap attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString useMap() const;
+
+ /**
+ * see useMap
+ */
+ void setUseMap( const DOMString & );
+
+ /**
+ * The current form control value. Used for radio buttons and
+ * check boxes. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-value-INPUT">
+ * value attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * Removes keyboard focus from this element.
+ *
+ */
+ void blur ( );
+
+ /**
+ * Gives keyboard focus to this element.
+ *
+ */
+ void focus ( );
+
+ /**
+ * Select the contents of the text area. For \c INPUT
+ * elements whose \c type attribute has one of the
+ * following values: "Text", "File", or "Password".
+ *
+ */
+ void select ( );
+
+ /**
+ * Simulate a mouse-click. For \c INPUT elements whose
+ * \c type attribute has one of the following values:
+ * "Button", "Checkbox", "Radio", "Reset", or "Submit".
+ */
+ void click ( );
+
+
+ /**
+ * Returns the character offset of beginning of selection, or if none,
+ * the cursor position.
+ * This operation is only supported if the type of this element is text;
+ * otherwise -1 is returned.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ long selectionStart();
+
+ /**
+ * Move the beginning of the selection to the given offset in text
+ * This call has no effect if the type of this input element isn't text
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionStart(long offset);
+
+ /**
+ * Returns the character offset of end of selection, or if none,
+ * the cursor position.
+ * This operation is only supported if the type of this element is text;
+ * otherwise -1 is returned.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ long selectionEnd();
+
+ /**
+ * Move the end of the selection (and the cursor) to the given offset in text
+ * This call has no effect if the type of this input element isn't text
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionEnd(long offset);
+
+ /**
+ * Makes the position span from start to end, and positions the cursor after the selection.
+ * This call has no effect if the type of this input element isn't text or if it is not rendered.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionRange(long start, long end);
+
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLLabelElementImpl;
+/**
+ * Form field label text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-LABEL">
+ * LABEL element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLLabelElement : public HTMLElement
+{
+public:
+ HTMLLabelElement();
+ HTMLLabelElement(const HTMLLabelElement &other);
+ HTMLLabelElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLLabelElement(HTMLLabelElementImpl *impl);
+public:
+
+ HTMLLabelElement & operator = (const HTMLLabelElement &other);
+ HTMLLabelElement & operator = (const Node &other);
+
+ ~HTMLLabelElement();
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * This attribute links this label with another form control by
+ * \c id attribute. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-for">
+ * for attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString htmlFor() const;
+
+ /**
+ * see htmlFor
+ */
+ void setHtmlFor( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLLegendElementImpl;
+/**
+ * Provides a caption for a \c FIELDSET grouping. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-LEGEND">
+ * LEGEND element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLLegendElement : public HTMLElement
+{
+public:
+ HTMLLegendElement();
+ HTMLLegendElement(const HTMLLegendElement &other);
+ HTMLLegendElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLLegendElement(HTMLLegendElementImpl *impl);
+public:
+
+ HTMLLegendElement & operator = (const HTMLLegendElement &other);
+ HTMLLegendElement & operator = (const Node &other);
+
+ ~HTMLLegendElement();
+
+ /**
+ * ### KDE 4.0: remove
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * Text alignment relative to \c FIELDSET . See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-align-LEGEND">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLOptGroupElementImpl;
+/**
+ * Group options together in logical subdivisions. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP">
+ * OPTGROUP element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLOptGroupElement : public HTMLElement
+{
+public:
+ HTMLOptGroupElement();
+ HTMLOptGroupElement(const HTMLOptGroupElement &other);
+ HTMLOptGroupElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLOptGroupElement(HTMLOptGroupElementImpl *impl);
+public:
+
+ HTMLOptGroupElement & operator = (const HTMLOptGroupElement &other);
+ HTMLOptGroupElement & operator = (const Node &other);
+
+ ~HTMLOptGroupElement();
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Assigns a label to this option group. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-label-OPTGROUP">
+ * label attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString label() const;
+
+ /**
+ * see label
+ */
+ void setLabel( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLSelectElementImpl;
+/**
+ * The select element allows the selection of an option. The contained
+ * options can be directly accessed through the select element as a
+ * collection. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-SELECT">
+ * SELECT element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLSelectElement : public HTMLElement
+{
+public:
+ HTMLSelectElement();
+ HTMLSelectElement(const HTMLSelectElement &other);
+ HTMLSelectElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLSelectElement(HTMLSelectElementImpl *impl);
+public:
+
+ HTMLSelectElement & operator = (const HTMLSelectElement &other);
+ HTMLSelectElement & operator = (const Node &other);
+
+ ~HTMLSelectElement();
+
+ /**
+ * The type of control created.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * The ordinal index of the selected option. The value -1 is
+ * returned if no element is selected. If multiple options are
+ * selected, the index of the first selected option is returned.
+ *
+ */
+ long selectedIndex() const;
+
+ /**
+ * see selectedIndex
+ */
+ void setSelectedIndex( long );
+
+ /**
+ * The current form control value.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * The number of options in this \c SELECT .
+ *
+ */
+ long length() const;
+
+ /**
+ * ### KDE 4.0: remove.
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * The collection of \c OPTION elements contained by
+ * this element.
+ *
+ */
+ HTMLCollection options() const;
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * If true, multiple \c OPTION elements may be
+ * selected in this \c SELECT . See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-multiple">
+ * multiple attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool multiple() const;
+
+ /**
+ * see multiple
+ */
+ void setMultiple( bool );
+
+ /**
+ * Form control or object name when submitted with a form. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-name-SELECT">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Number of visible rows. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-size-SELECT">
+ * size attribute definition </a> in HTML 4.0.
+ *
+ */
+ long size() const;
+
+ /**
+ * see size
+ */
+ void setSize( long );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * Add a new element to the collection of \c OPTION
+ * elements for this \c SELECT .
+ *
+ * @param element The element to add.
+ *
+ * @param before The element to insert before, or 0 for the
+ * tail of the list.
+ *
+ */
+ void add ( const HTMLElement &element, const HTMLElement &before );
+
+ /**
+ * Remove an element from the collection of \c OPTION
+ * elements for this \c SELECT . Does nothing if no
+ * element has the given index.
+ *
+ * @param index The index of the item to remove.
+ *
+ */
+ void remove ( long index );
+
+ /**
+ * Removes keyboard focus from this element.
+ *
+ */
+ void blur ( );
+
+ /**
+ * Gives keyboard focus to this element.
+ *
+ */
+ void focus ( );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTextAreaElementImpl;
+/**
+ * Multi-line text field. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-TEXTAREA">
+ * TEXTAREA element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTextAreaElement : public HTMLElement
+{
+public:
+ HTMLTextAreaElement();
+ HTMLTextAreaElement(const HTMLTextAreaElement &other);
+ HTMLTextAreaElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLTextAreaElement(HTMLTextAreaElementImpl *impl);
+public:
+
+ HTMLTextAreaElement & operator = (const HTMLTextAreaElement &other);
+ HTMLTextAreaElement & operator = (const Node &other);
+
+ ~HTMLTextAreaElement();
+
+ /**
+ * Stores the initial control value (i.e., the initial value of
+ * \c value ).
+ *
+ */
+ DOMString defaultValue() const;
+
+ /**
+ * see defaultValue
+ */
+ void setDefaultValue( const DOMString & );
+
+ /**
+ * ### KDE 4.0: remove.
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * Width of control (in characters). See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-cols-TEXTAREA">
+ * cols attribute definition </a> in HTML 4.0.
+ *
+ */
+ long cols() const;
+
+ /**
+ * see cols
+ */
+ void setCols( long );
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Form control or object name when submitted with a form. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-name-TEXTAREA">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * This control is read-only. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-readonly">
+ * readonly attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool readOnly() const;
+
+ /**
+ * see readOnly
+ */
+ void setReadOnly( bool );
+
+ /**
+ * Number of text rows. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-rows-TEXTAREA">
+ * rows attribute definition </a> in HTML 4.0.
+ *
+ */
+ long rows() const;
+
+ /**
+ * see rows
+ */
+ void setRows( long );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * The type of this form control.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * The current textual content of the multi-line text field. If
+ * the entirety of the data can not fit into a single wstring, the
+ * implementation may truncate the data.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * Removes keyboard focus from this element.
+ */
+ void blur ( );
+
+ /**
+ * Gives keyboard focus to this element.
+ */
+ void focus ( );
+
+ /**
+ * Select the contents of the \c TEXTAREA .
+ */
+ void select ( );
+
+ /**
+ * Returns the character offset of beginning of selection, or if none,
+ * the cursor position.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ long selectionStart();
+
+ /**
+ * Move the beginning of the selection to the given offset in text
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionStart(long offset);
+
+ /**
+ * Returns the character offset of end of selection, or if none,
+ * the cursor position.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ long selectionEnd();
+
+ /**
+ * Move the end of the selection (and the cursor) to the given offset in text
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionEnd(long offset);
+
+ /**
+ * Selects the text from start to end, and positions the cursor after the selection.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ void setSelectionRange(long start, long end);
+
+ /**
+ * Returns the length of the text.
+ * NOTE: this method is not part of the DOM, but a Mozilla extension
+ * @since 3.5.2
+ */
+ long textLength();
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLOptionElementImpl;
+/**
+ * A selectable choice. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTION">
+ * OPTION element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLOptionElement : public HTMLElement
+{
+public:
+ HTMLOptionElement();
+ HTMLOptionElement(const HTMLOptionElement &other);
+ HTMLOptionElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLOptionElement(HTMLOptionElementImpl *impl);
+public:
+
+ HTMLOptionElement & operator = (const HTMLOptionElement &other);
+ HTMLOptionElement & operator = (const Node &other);
+
+ ~HTMLOptionElement();
+
+ /**
+ * ### KDE 4.0: remove
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * Stores the initial value of the \c selected
+ * attribute.
+ *
+ */
+ bool defaultSelected() const;
+
+ /**
+ * see defaultSelected
+ */
+ void setDefaultSelected( bool );
+
+ /**
+ * The text contained within the option element.
+ *
+ */
+ DOMString text() const;
+
+ /**
+ * The index of this \c OPTION in its parent
+ * \c SELECT .
+ *
+ */
+ long index() const;
+
+ /**
+ * see index
+ *
+ * This function is obsolete - the index property is actually supposed to be read-only
+ * (http://www.w3.org/DOM/updates/REC-DOM-Level-1-19981001-errata.html)
+ */
+ void setIndex( long );
+
+ /**
+ * The control is unavailable in this context. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-disabled">
+ * disabled attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Option label for use in hierarchical menus. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-label-OPTION">
+ * label attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString label() const;
+
+ /**
+ * see label
+ */
+ void setLabel( const DOMString & );
+
+ /**
+ * Means that this option is initially selected. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-selected">
+ * selected attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool selected() const;
+
+ /**
+ * see selected
+ */
+ void setSelected( bool );
+
+ /**
+ * The current form control value. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-value-OPTION">
+ * value attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+};
+
+
+// --------------------------------------------------------------------------
+
+class HTMLIsIndexElementImpl;
+class HTMLFormElement;
+
+/**
+ * This element is used for single-line text input. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#edef-ISINDEX">
+ * ISINDEX element definition </a> in HTML 4.0. This element is
+ * deprecated in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLIsIndexElement : public HTMLElement
+{
+public:
+ HTMLIsIndexElement();
+ HTMLIsIndexElement(const HTMLIsIndexElement &other);
+ HTMLIsIndexElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLIsIndexElement(HTMLIsIndexElementImpl *impl);
+public:
+
+ HTMLIsIndexElement & operator = (const HTMLIsIndexElement &other);
+ HTMLIsIndexElement & operator = (const Node &other);
+
+ ~HTMLIsIndexElement();
+
+ /**
+ * ### KDE 4.0: remove
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * The prompt message. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-prompt">
+ * prompt attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString prompt() const;
+
+ /**
+ * see prompt
+ */
+ void setPrompt( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_head.cpp b/tdehtml/dom/html_head.cpp
new file mode 100644
index 000000000..e5e72e73b
--- /dev/null
+++ b/tdehtml/dom/html_head.cpp
@@ -0,0 +1,515 @@
+/**
+ * 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 "dom/html_head.h"
+#include "html/html_headimpl.h"
+#include "misc/htmlhashes.h"
+#include "xml/dom_docimpl.h"
+
+using namespace DOM;
+
+HTMLBaseElement::HTMLBaseElement() : HTMLElement()
+{
+}
+
+HTMLBaseElement::HTMLBaseElement(const HTMLBaseElement &other) : HTMLElement(other)
+{
+}
+
+HTMLBaseElement::HTMLBaseElement(HTMLBaseElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLBaseElement &HTMLBaseElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BASE );
+ return *this;
+}
+
+HTMLBaseElement &HTMLBaseElement::operator = (const HTMLBaseElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLBaseElement::~HTMLBaseElement()
+{
+}
+
+DOMString HTMLBaseElement::href() const
+{
+ if(!impl) return DOMString();
+ DOMString href = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_HREF);
+ return !href.isNull() ? impl->getDocument()->completeURL(href.string()) : href;
+}
+
+void HTMLBaseElement::setHref( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREF, value);
+}
+
+DOMString HTMLBaseElement::target() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TARGET);
+}
+
+void HTMLBaseElement::setTarget( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TARGET, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLLinkElement::HTMLLinkElement() : HTMLElement()
+{
+}
+
+HTMLLinkElement::HTMLLinkElement(const HTMLLinkElement &other) : HTMLElement(other)
+{
+}
+
+HTMLLinkElement::HTMLLinkElement(HTMLLinkElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLLinkElement &HTMLLinkElement::operator = (const Node &other)
+{
+ assignOther( other, ID_LINK );
+ return *this;
+}
+
+HTMLLinkElement &HTMLLinkElement::operator = (const HTMLLinkElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLLinkElement::~HTMLLinkElement()
+{
+}
+
+bool HTMLLinkElement::disabled() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLLinkElement::setDisabled( bool _disabled )
+{
+ if(impl)
+ ((ElementImpl *)impl)->setAttribute(ATTR_DISABLED, _disabled ? "" : 0);
+}
+
+DOMString HTMLLinkElement::charset() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHARSET);
+}
+
+void HTMLLinkElement::setCharset( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHARSET, value);
+}
+
+DOMString HTMLLinkElement::href() const
+{
+ if(!impl) return DOMString();
+ DOMString href = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_HREF);
+ return !href.isNull() ? impl->getDocument()->completeURL(href.string()) : href;
+}
+
+void HTMLLinkElement::setHref( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREF, value);
+}
+
+DOMString HTMLLinkElement::hreflang() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HREFLANG);
+}
+
+void HTMLLinkElement::setHreflang( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREFLANG, value);
+}
+
+DOMString HTMLLinkElement::media() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MEDIA);
+}
+
+void HTMLLinkElement::setMedia( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MEDIA, value);
+}
+
+DOMString HTMLLinkElement::rel() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_REL);
+}
+
+void HTMLLinkElement::setRel( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_REL, value);
+}
+
+DOMString HTMLLinkElement::rev() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_REV);
+}
+
+void HTMLLinkElement::setRev( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_REV, value);
+}
+
+DOMString HTMLLinkElement::target() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TARGET);
+}
+
+void HTMLLinkElement::setTarget( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TARGET, value);
+}
+
+DOMString HTMLLinkElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLLinkElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+StyleSheet HTMLLinkElement::sheet() const
+{
+ if(!impl) return 0;
+ return ((HTMLLinkElementImpl *)impl)->sheet();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLMetaElement::HTMLMetaElement() : HTMLElement()
+{
+}
+
+HTMLMetaElement::HTMLMetaElement(const HTMLMetaElement &other) : HTMLElement(other)
+{
+}
+
+HTMLMetaElement::HTMLMetaElement(HTMLMetaElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLMetaElement &HTMLMetaElement::operator = (const Node &other)
+{
+ assignOther( other, ID_META );
+ return *this;
+}
+
+HTMLMetaElement &HTMLMetaElement::operator = (const HTMLMetaElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLMetaElement::~HTMLMetaElement()
+{
+}
+
+DOMString HTMLMetaElement::content() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CONTENT);
+}
+
+void HTMLMetaElement::setContent( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CONTENT, value);
+}
+
+DOMString HTMLMetaElement::httpEquiv() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HTTP_EQUIV);
+}
+
+void HTMLMetaElement::setHttpEquiv( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HTTP_EQUIV, value);
+}
+
+DOMString HTMLMetaElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLMetaElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLMetaElement::scheme() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SCHEME);
+}
+
+void HTMLMetaElement::setScheme( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SCHEME, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLScriptElement::HTMLScriptElement() : HTMLElement()
+{
+}
+
+HTMLScriptElement::HTMLScriptElement(const HTMLScriptElement &other) : HTMLElement(other)
+{
+}
+
+HTMLScriptElement::HTMLScriptElement(HTMLScriptElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLScriptElement &HTMLScriptElement::operator = (const Node &other)
+{
+ assignOther( other, ID_SCRIPT );
+ return *this;
+}
+
+HTMLScriptElement &HTMLScriptElement::operator = (const HTMLScriptElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLScriptElement::~HTMLScriptElement()
+{
+}
+
+DOMString HTMLScriptElement::text() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLScriptElementImpl *)impl)->text();
+}
+
+void HTMLScriptElement::setText( const DOMString &value )
+{
+ if(impl) ((HTMLScriptElementImpl *)impl)->setText(value);
+}
+
+DOMString HTMLScriptElement::htmlFor() const
+{
+ // DOM Level 1 says: reserved for future use...
+ return DOMString();
+}
+
+void HTMLScriptElement::setHtmlFor( const DOMString &/*value*/ )
+{
+ // DOM Level 1 says: reserved for future use...
+}
+
+DOMString HTMLScriptElement::event() const
+{
+ // DOM Level 1 says: reserved for future use...
+ return DOMString();
+}
+
+void HTMLScriptElement::setEvent( const DOMString &/*value*/ )
+{
+ // DOM Level 1 says: reserved for future use...
+}
+
+DOMString HTMLScriptElement::charset() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHARSET);
+}
+
+void HTMLScriptElement::setCharset( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHARSET, value);
+}
+
+bool HTMLScriptElement::defer() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_DEFER).isNull();
+}
+
+void HTMLScriptElement::setDefer( bool _defer )
+{
+
+ if(impl)
+ ((ElementImpl *)impl)->setAttribute(ATTR_DEFER,_defer ? "" : 0);
+}
+
+DOMString HTMLScriptElement::src() const
+{
+ if(!impl) return DOMString();
+ DOMString s = ((ElementImpl *)impl)->getAttribute(ATTR_SRC);
+ return !s.isNull() ? impl->getDocument()->completeURL(s.string()) : s;
+}
+
+void HTMLScriptElement::setSrc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SRC, value);
+}
+
+DOMString HTMLScriptElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLScriptElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLStyleElement::HTMLStyleElement() : HTMLElement()
+{
+}
+
+HTMLStyleElement::HTMLStyleElement(const HTMLStyleElement &other) : HTMLElement(other)
+{
+}
+
+HTMLStyleElement::HTMLStyleElement(HTMLStyleElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLStyleElement &HTMLStyleElement::operator = (const Node &other)
+{
+ assignOther( other, ID_STYLE );
+ return *this;
+}
+
+HTMLStyleElement &HTMLStyleElement::operator = (const HTMLStyleElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLStyleElement::~HTMLStyleElement()
+{
+}
+
+bool HTMLStyleElement::disabled() const
+{
+ if(!impl) return 0;
+ return !((HTMLStyleElementImpl *)impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLStyleElement::setDisabled( bool _disabled )
+{
+
+ if(impl)
+ ((ElementImpl *)impl)->setAttribute(ATTR_DISABLED,_disabled ? "" : 0);
+}
+
+DOMString HTMLStyleElement::media() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_MEDIA);
+}
+
+void HTMLStyleElement::setMedia( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_MEDIA, value);
+}
+
+DOMString HTMLStyleElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLStyleElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+StyleSheet HTMLStyleElement::sheet() const
+{
+ if(!impl) return 0;
+ return ((HTMLStyleElementImpl *)impl)->sheet();
+}
+
+
+// --------------------------------------------------------------------------
+
+HTMLTitleElement::HTMLTitleElement() : HTMLElement()
+{
+}
+
+HTMLTitleElement::HTMLTitleElement(const HTMLTitleElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTitleElement::HTMLTitleElement(HTMLTitleElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTitleElement &HTMLTitleElement::operator = (const Node &other)
+{
+ assignOther( other, ID_TITLE );
+ return *this;
+}
+
+HTMLTitleElement &HTMLTitleElement::operator = (const HTMLTitleElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTitleElement::~HTMLTitleElement()
+{
+}
+
+DOMString HTMLTitleElement::text() const
+{
+ if(!impl) return DOMString();
+ return ((HTMLTitleElementImpl *)impl)->text();
+}
+
+void HTMLTitleElement::setText( const DOMString &value )
+{
+ if(impl) ((HTMLTitleElementImpl *)impl)->setText(value);
+}
+
diff --git a/tdehtml/dom/html_head.h b/tdehtml/dom/html_head.h
new file mode 100644
index 000000000..e8dc52d21
--- /dev/null
+++ b/tdehtml/dom/html_head.h
@@ -0,0 +1,552 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_HEAD_H
+#define HTML_HEAD_H
+
+#include <dom/html_element.h>
+#include <dom/css_stylesheet.h>
+
+namespace DOM {
+
+class HTMLBaseElementImpl;
+class DOMString;
+
+/**
+ * Document base URI. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#edef-BASE">
+ * BASE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLBaseElement : public HTMLElement
+{
+public:
+ HTMLBaseElement();
+ HTMLBaseElement(const HTMLBaseElement &other);
+ HTMLBaseElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLBaseElement(HTMLBaseElementImpl *impl);
+public:
+
+ HTMLBaseElement & operator = (const HTMLBaseElement &other);
+ HTMLBaseElement & operator = (const Node &other);
+
+ ~HTMLBaseElement();
+
+ /**
+ * The base URI See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-href-BASE">
+ * href attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString href() const;
+
+ /**
+ * see href
+ */
+ void setHref( const DOMString & );
+
+ /**
+ * The default target frame. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">
+ * target attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * see target
+ */
+ void setTarget( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLLinkElementImpl;
+
+/**
+ * The \c LINK element specifies a link to an external
+ * resource, and defines this document's relationship to that resource
+ * (or vice versa). See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#edef-LINK">
+ * LINK element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLLinkElement : public HTMLElement
+{
+public:
+ HTMLLinkElement();
+ HTMLLinkElement(const HTMLLinkElement &other);
+ HTMLLinkElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLLinkElement(HTMLLinkElementImpl *impl);
+public:
+
+ HTMLLinkElement & operator = (const HTMLLinkElement &other);
+ HTMLLinkElement & operator = (const Node &other);
+
+ ~HTMLLinkElement();
+
+ /**
+ * Enables/disables the link. This is currently only used for
+ * style sheet links, and may be used to activate or deactivate
+ * style sheets.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * The character encoding of the resource being linked to. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-charset">
+ * charset attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString charset() const;
+
+ /**
+ * see charset
+ */
+ void setCharset( const DOMString & );
+
+ /**
+ * The URI of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-href">
+ * href attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString href() const;
+
+ /**
+ * see href
+ */
+ void setHref( const DOMString & );
+
+ /**
+ * Language code of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-hreflang">
+ * hreflang attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString hreflang() const;
+
+ /**
+ * see hreflang
+ */
+ void setHreflang( const DOMString & );
+
+ /**
+ * Designed for use with one or more target media. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#adef-media">
+ * media attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString media() const;
+
+ /**
+ * see media
+ */
+ void setMedia( const DOMString & );
+
+ /**
+ * Forward link type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-rel">
+ * rel attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rel() const;
+
+ /**
+ * see rel
+ */
+ void setRel( const DOMString & );
+
+ /**
+ * Reverse link type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-rev">
+ * rev attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rev() const;
+
+ /**
+ * see rev
+ */
+ void setRev( const DOMString & );
+
+ /**
+ * Frame to render the resource in. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">
+ * target attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * see target
+ */
+ void setTarget( const DOMString & );
+
+ /**
+ * Advisory content type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-type-A">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the LinkStyle interface
+ *
+ * The style sheet.
+ */
+ StyleSheet sheet() const;
+
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLMetaElementImpl;
+
+/**
+ * This contains generic meta-information about the document. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-META">
+ * META element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLMetaElement : public HTMLElement
+{
+public:
+ HTMLMetaElement();
+ HTMLMetaElement(const HTMLMetaElement &other);
+ HTMLMetaElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLMetaElement(HTMLMetaElementImpl *impl);
+public:
+
+ HTMLMetaElement & operator = (const HTMLMetaElement &other);
+ HTMLMetaElement & operator = (const Node &other);
+
+ ~HTMLMetaElement();
+
+ /**
+ * Associated information. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-content">
+ * content attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString content() const;
+
+ /**
+ * see content
+ */
+ void setContent( const DOMString & );
+
+ /**
+ * HTTP response header name. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-http-equiv">
+ * http-equiv attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString httpEquiv() const;
+
+ /**
+ * see httpEquiv
+ */
+ void setHttpEquiv( const DOMString & );
+
+ /**
+ * Meta information name. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-name-META">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Select form of content. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#adef-scheme">
+ * scheme attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString scheme() const;
+
+ /**
+ * see scheme
+ */
+ void setScheme( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLScriptElementImpl;
+
+/**
+ * Script statements. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/scripts.html#edef-SCRIPT">
+ * SCRIPT element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLScriptElement : public HTMLElement
+{
+public:
+ HTMLScriptElement();
+ HTMLScriptElement(const HTMLScriptElement &other);
+ HTMLScriptElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLScriptElement(HTMLScriptElementImpl *impl);
+public:
+
+ HTMLScriptElement & operator = (const HTMLScriptElement &other);
+ HTMLScriptElement & operator = (const Node &other);
+
+ ~HTMLScriptElement();
+
+ /**
+ * The script content of the element.
+ *
+ */
+ DOMString text() const;
+
+ /**
+ * see text
+ */
+ void setText( const DOMString & );
+
+ /**
+ * Reserved for future use.
+ *
+ */
+ DOMString htmlFor() const;
+
+ /**
+ * see htmlFor
+ */
+ void setHtmlFor( const DOMString & );
+
+ /**
+ * Reserved for future use.
+ *
+ */
+ DOMString event() const;
+
+ /**
+ * see event
+ */
+ void setEvent( const DOMString & );
+
+ /**
+ * The character encoding of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-charset">
+ * charset attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString charset() const;
+
+ /**
+ * see charset
+ */
+ void setCharset( const DOMString & );
+
+ /**
+ * Indicates that the user agent can defer processing of the
+ * script. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer">
+ * defer attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool defer() const;
+
+ /**
+ * see defer
+ */
+ void setDefer( bool );
+
+ /**
+ * URI designating an external script. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-src-SCRIPT">
+ * src attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString src() const;
+
+ /**
+ * see src
+ */
+ void setSrc( const DOMString & );
+
+ /**
+ * The content type of the script language. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-type-SCRIPT">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLStyleElementImpl;
+
+/**
+ * Style information. A more detailed style sheet object model is
+ * planned to be defined in a separate document. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#edef-STYLE">
+ * STYLE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLStyleElement : public HTMLElement
+{
+public:
+ HTMLStyleElement();
+ HTMLStyleElement(const HTMLStyleElement &other);
+ HTMLStyleElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLStyleElement(HTMLStyleElementImpl *impl);
+public:
+
+ HTMLStyleElement & operator = (const HTMLStyleElement &other);
+ HTMLStyleElement & operator = (const Node &other);
+
+ ~HTMLStyleElement();
+
+ /**
+ * Enables/disables the style sheet.
+ *
+ */
+ bool disabled() const;
+
+ /**
+ * see disabled
+ */
+ void setDisabled( bool );
+
+ /**
+ * Designed for use with one or more target media. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#adef-media">
+ * media attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString media() const;
+
+ /**
+ * see media
+ */
+ void setMedia( const DOMString & );
+
+ /**
+ * The style sheet language (Internet media type). See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/styles.html#adef-type-STYLE">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ * This method is from the LinkStyle interface
+ *
+ * The style sheet.
+ */
+ StyleSheet sheet() const;
+
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTitleElementImpl;
+
+/**
+ * The document title. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/global.html#edef-TITLE">
+ * TITLE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTitleElement : public HTMLElement
+{
+public:
+ HTMLTitleElement();
+ HTMLTitleElement(const HTMLTitleElement &other);
+ HTMLTitleElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLTitleElement(HTMLTitleElementImpl *impl);
+public:
+
+ HTMLTitleElement & operator = (const HTMLTitleElement &other);
+ HTMLTitleElement & operator = (const Node &other);
+
+ ~HTMLTitleElement();
+
+ /**
+ * The specified title as a string.
+ *
+ */
+ DOMString text() const;
+
+ /**
+ * see text
+ */
+ void setText( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_image.cpp b/tdehtml/dom/html_image.cpp
new file mode 100644
index 000000000..f7c9dac26
--- /dev/null
+++ b/tdehtml/dom/html_image.cpp
@@ -0,0 +1,413 @@
+/**
+ * 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 "dom/dom_doc.h"
+#include "dom/html_image.h"
+#include "dom/html_misc.h"
+
+#include "html/html_imageimpl.h"
+#include "html/html_miscimpl.h"
+#include "misc/htmlhashes.h"
+#include "xml/dom_docimpl.h"
+
+using namespace DOM;
+
+HTMLAreaElement::HTMLAreaElement() : HTMLElement()
+{
+}
+
+HTMLAreaElement::HTMLAreaElement(const HTMLAreaElement &other) : HTMLElement(other)
+{
+}
+
+HTMLAreaElement::HTMLAreaElement(HTMLAreaElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLAreaElement &HTMLAreaElement::operator = (const Node &other)
+{
+ assignOther( other, ID_AREA );
+ return *this;
+}
+
+HTMLAreaElement &HTMLAreaElement::operator = (const HTMLAreaElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLAreaElement::~HTMLAreaElement()
+{
+}
+
+DOMString HTMLAreaElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLAreaElement::setAccessKey( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+DOMString HTMLAreaElement::alt() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALT);
+}
+
+void HTMLAreaElement::setAlt( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALT, value);
+}
+
+DOMString HTMLAreaElement::coords() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COORDS);
+}
+
+void HTMLAreaElement::setCoords( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_COORDS, value);
+}
+
+DOMString HTMLAreaElement::href() const
+{
+ if(!impl) return DOMString();
+ DOMString href = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_HREF);
+ return !href.isNull() ? impl->getDocument()->completeURL(href.string()) : href;
+}
+
+void HTMLAreaElement::setHref( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREF, value);
+}
+
+bool HTMLAreaElement::noHref() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_NOHREF).isNull();
+}
+
+void HTMLAreaElement::setNoHref( bool _noHref )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _noHref )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_NOHREF, str);
+ }
+}
+
+DOMString HTMLAreaElement::shape() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SHAPE);
+}
+
+void HTMLAreaElement::setShape( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SHAPE, value);
+}
+
+long HTMLAreaElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TABINDEX).toInt();
+}
+
+void HTMLAreaElement::setTabIndex( long _tabIndex )
+{
+ if(impl) {
+ DOMString value(TQString::number(_tabIndex));
+ ((ElementImpl *)impl)->setAttribute(ATTR_TABINDEX,value);
+ }
+}
+
+DOMString HTMLAreaElement::target() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TARGET);
+}
+
+void HTMLAreaElement::setTarget( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TARGET, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLImageElement::HTMLImageElement() : HTMLElement()
+{
+}
+
+HTMLImageElement::HTMLImageElement(const HTMLImageElement &other) : HTMLElement(other)
+{
+}
+
+HTMLImageElement::HTMLImageElement(HTMLImageElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLImageElement &HTMLImageElement::operator = (const Node &other)
+{
+ assignOther( other, ID_IMG );
+ return *this;
+}
+
+HTMLImageElement &HTMLImageElement::operator = (const HTMLImageElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLImageElement::~HTMLImageElement()
+{
+}
+
+DOMString HTMLImageElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLImageElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLImageElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLImageElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLImageElement::alt() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALT);
+}
+
+void HTMLImageElement::setAlt( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALT, value);
+}
+
+long HTMLImageElement::border() const
+{
+ if(!impl) return 0;
+ // ### return value in pixels
+ return static_cast<HTMLImageElementImpl*>(impl)->getAttribute(ATTR_BORDER).toInt();
+}
+
+void HTMLImageElement::setBorder( long value )
+{
+ if (impl) static_cast<HTMLImageElementImpl*>(impl)->setAttribute(ATTR_BORDER, TQString::number(value));
+}
+
+DOMString HTMLImageElement::getBorder() const
+{
+ if(!impl) return DOMString();
+ return static_cast<HTMLImageElementImpl*>(impl)->getAttribute(ATTR_BORDER);
+}
+
+void HTMLImageElement::setBorder( const DOMString& value )
+{
+ if (impl) static_cast<HTMLImageElementImpl*>(impl)->setAttribute(ATTR_BORDER, value);
+}
+
+
+long HTMLImageElement::height() const
+{
+ if(!impl) return 0;
+ return static_cast<HTMLImageElementImpl*>(impl)->height();
+}
+
+void HTMLImageElement::setHeight( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEIGHT, TQString::number(value));
+}
+
+long HTMLImageElement::hspace() const
+{
+ if(!impl) return 0;
+ // ### return actual value
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HSPACE).toInt();
+}
+
+void HTMLImageElement::setHspace( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HSPACE, TQString::number(value));
+}
+
+bool HTMLImageElement::isMap() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_DISABLED).isNull();
+}
+
+void HTMLImageElement::setIsMap( bool _isMap )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _isMap )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_ISMAP, str);
+ }
+}
+
+DOMString HTMLImageElement::longDesc() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_LONGDESC);
+}
+
+void HTMLImageElement::setLongDesc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_LONGDESC, value);
+}
+
+DOMString HTMLImageElement::src() const
+{
+ if(!impl) return DOMString();
+ DOMString s = ((ElementImpl *)impl)->getAttribute(ATTR_SRC);
+ return !s.isNull() ? impl->getDocument()->completeURL( s.string() ) : s;
+}
+
+void HTMLImageElement::setSrc( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SRC, value);
+}
+
+DOMString HTMLImageElement::useMap() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_USEMAP);
+}
+
+void HTMLImageElement::setUseMap( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_USEMAP, value);
+}
+
+long HTMLImageElement::vspace() const
+{
+ if(!impl) return 0;
+ // ### return actual vspace
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VSPACE).toInt();
+}
+
+void HTMLImageElement::setVspace( long value )
+{
+ if(impl) static_cast<ElementImpl*>(impl)->setAttribute(ATTR_VSPACE, TQString::number(value));
+}
+
+long HTMLImageElement::width() const
+{
+ if(!impl) return 0;
+ return static_cast<HTMLImageElementImpl*>(impl)->width();
+}
+
+void HTMLImageElement::setWidth( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, TQString::number(value));
+}
+
+long HTMLImageElement::x() const
+{
+ if (impl && impl->renderer()) {
+ int x = 0;
+ int y = 0;
+ impl->renderer()->absolutePosition(x,y);
+ return x;
+ }
+ return 0;
+}
+
+long HTMLImageElement::y() const
+{
+ if (impl && impl->renderer()) {
+ int x = 0;
+ int y = 0;
+ impl->renderer()->absolutePosition(x,y);
+ return y;
+ }
+ return 0;
+}
+
+// --------------------------------------------------------------------------
+
+HTMLMapElement::HTMLMapElement() : HTMLElement()
+{
+}
+
+HTMLMapElement::HTMLMapElement(const HTMLMapElement &other) : HTMLElement(other)
+{
+}
+
+HTMLMapElement::HTMLMapElement(HTMLMapElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLMapElement &HTMLMapElement::operator = (const Node &other)
+{
+ assignOther( other, ID_MAP );
+ return *this;
+}
+
+HTMLMapElement &HTMLMapElement::operator = (const HTMLMapElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLMapElement::~HTMLMapElement()
+{
+}
+
+HTMLCollection HTMLMapElement::areas() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::MAP_AREAS);
+}
+
+DOMString HTMLMapElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLMapElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
diff --git a/tdehtml/dom/html_image.h b/tdehtml/dom/html_image.h
new file mode 100644
index 000000000..9f30aaa14
--- /dev/null
+++ b/tdehtml/dom/html_image.h
@@ -0,0 +1,431 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_IMAGE_H
+#define HTML_IMAGE_H
+
+#include <dom/html_element.h>
+
+#include <kdemacros.h>
+
+namespace DOM {
+
+class HTMLAreaElementImpl;
+class DOMString;
+
+/**
+ * Client-side image map area definition. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-AREA">
+ * AREA element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLAreaElement : public HTMLElement
+{
+public:
+ HTMLAreaElement();
+ HTMLAreaElement(const HTMLAreaElement &other);
+ HTMLAreaElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLAreaElement(HTMLAreaElementImpl *impl);
+public:
+
+ HTMLAreaElement & operator = (const HTMLAreaElement &other);
+ HTMLAreaElement & operator = (const Node &other);
+
+ ~HTMLAreaElement();
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * Alternate text for user agents not rendering the normal content
+ * of this element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-alt">
+ * alt attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString alt() const;
+
+ /**
+ * see alt
+ */
+ void setAlt( const DOMString & );
+
+ /**
+ * Comma-separated list of lengths, defining an active region
+ * geometry. See also \c shape for the shape of the
+ * region. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-coords">
+ * coords attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString coords() const;
+
+ /**
+ * see coords
+ */
+ void setCoords( const DOMString & );
+
+ /**
+ * The URI of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-href">
+ * href attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString href() const;
+
+ /**
+ * see href
+ */
+ void setHref( const DOMString & );
+
+ /**
+ * Specifies that this area is inactive, i.e., has no associated
+ * action. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-nohref">
+ * nohref attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool noHref() const;
+
+ /**
+ * see noHref
+ */
+ void setNoHref( bool );
+
+ /**
+ * The shape of the active area. The coordinates are given by
+ * \c coords . See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-shape">
+ * shape attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString shape() const;
+
+ /**
+ * see shape
+ */
+ void setShape( const DOMString & );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * Frame to render the resource in. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">
+ * target attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * see target
+ */
+ void setTarget( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLImageElementImpl;
+
+/**
+ * Embedded image. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-IMG">
+ * IMG element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLImageElement : public HTMLElement
+{
+public:
+ HTMLImageElement();
+ HTMLImageElement(const HTMLImageElement &other);
+ HTMLImageElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLImageElement(HTMLImageElementImpl *impl);
+public:
+
+ HTMLImageElement & operator = (const HTMLImageElement &other);
+ HTMLImageElement & operator = (const Node &other);
+
+ ~HTMLImageElement();
+
+ /**
+ * The name of the element (for backwards compatibility).
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Aligns this object (vertically or horizontally) with respect to
+ * its surrounding text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-align-IMG">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Alternate text for user agents not rendering the normal content
+ * of this element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-alt">
+ * alt attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString alt() const;
+
+ /**
+ * see alt
+ */
+ void setAlt( const DOMString & );
+
+ /**
+ * Width of border around image. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-border-IMG">
+ * border attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString getBorder() const;
+
+ /**
+ * see border
+ */
+ void setBorder( const DOMString& );
+
+
+ /**
+ * @deprecated
+ */
+ long border() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setBorder( long ) KDE_DEPRECATED;
+
+ /**
+ * Override height. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-height-IMG">
+ * height attribute definition </a> in HTML 4.0.
+ *
+ */
+ long height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( long );
+
+ /**
+ * Horizontal space to the left and right of this image. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-hspace">
+ * hspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long hspace() const;
+
+ /**
+ * see hspace
+ */
+ void setHspace( long );
+
+ /**
+ * Use server-side image map. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-ismap">
+ * ismap attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool isMap() const;
+
+ /**
+ * see isMap
+ */
+ void setIsMap( bool );
+
+ /**
+ * URI designating a long description of this image or frame. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-longdesc-IMG">
+ * longdesc attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString longDesc() const;
+
+ /**
+ * see longDesc
+ */
+ void setLongDesc( const DOMString & );
+
+ /**
+ * URI designating the source of this image. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-src-IMG">
+ * src attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString src() const;
+
+ /**
+ * see src
+ */
+ void setSrc( const DOMString & );
+
+ /**
+ * Use client-side image map. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-usemap">
+ * usemap attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString useMap() const;
+
+ /**
+ * see useMap
+ */
+ void setUseMap( const DOMString & );
+
+ /**
+ * Vertical space above and below this image. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-vspace">
+ * vspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long vspace() const;
+
+ /**
+ * see vspace
+ */
+ void setVspace( long );
+
+ /**
+ * Override width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-width-IMG">
+ * width attribute definition </a> in HTML 4.0.
+ *
+ */
+ long width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( long );
+
+ /**
+ * Nonstandard extension to DOM::ImgElement
+ */
+ long x() const;
+ long y() const;
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLMapElementImpl;
+class HTMLCollection;
+class DOMString;
+
+/**
+ * Client-side image map. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-MAP">
+ * MAP element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLMapElement : public HTMLElement
+{
+public:
+ HTMLMapElement();
+ HTMLMapElement(const HTMLMapElement &other);
+ HTMLMapElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLMapElement(HTMLMapElementImpl *impl);
+public:
+
+ HTMLMapElement & operator = (const HTMLMapElement &other);
+ HTMLMapElement & operator = (const Node &other);
+
+ ~HTMLMapElement();
+
+ /**
+ * The list of areas defined for the image map.
+ *
+ */
+ HTMLCollection areas() const;
+
+ /**
+ * Names the map (for use with \c usemap ). See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-name-MAP">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_inline.cpp b/tdehtml/dom/html_inline.cpp
new file mode 100644
index 000000000..568761685
--- /dev/null
+++ b/tdehtml/dom/html_inline.cpp
@@ -0,0 +1,434 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@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.
+ *
+ */
+// --------------------------------------------------------------------------
+
+#include "dom/dom_doc.h"
+#include "dom/html_inline.h"
+#include "html/html_inlineimpl.h"
+#include "html/html_baseimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLAnchorElement::HTMLAnchorElement() : HTMLElement()
+{
+}
+
+HTMLAnchorElement::HTMLAnchorElement(const HTMLAnchorElement &other) : HTMLElement(other)
+{
+}
+
+HTMLAnchorElement::HTMLAnchorElement(HTMLAnchorElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLAnchorElement &HTMLAnchorElement::operator = (const Node &other)
+{
+ assignOther( other, ID_A );
+ return *this;
+}
+
+HTMLAnchorElement &HTMLAnchorElement::operator = (const HTMLAnchorElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLAnchorElement::~HTMLAnchorElement()
+{
+}
+
+DOMString HTMLAnchorElement::accessKey() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ACCESSKEY);
+}
+
+void HTMLAnchorElement::setAccessKey( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ACCESSKEY, value);
+}
+
+DOMString HTMLAnchorElement::charset() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHARSET);
+}
+
+void HTMLAnchorElement::setCharset( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHARSET, value);
+}
+
+DOMString HTMLAnchorElement::coords() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COORDS);
+}
+
+void HTMLAnchorElement::setCoords( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_COORDS, value);
+}
+
+DOMString HTMLAnchorElement::href() const
+{
+ if(!impl) return DOMString();
+ DOMString href = static_cast<ElementImpl*>(impl)->getAttribute(ATTR_HREF);
+ return !href.isNull() ? impl->getDocument()->completeURL(href.string()) : href;
+}
+
+void HTMLAnchorElement::setHref( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREF, value);
+}
+
+DOMString HTMLAnchorElement::hreflang() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HREFLANG);
+}
+
+void HTMLAnchorElement::setHreflang( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HREFLANG, value);
+}
+
+DOMString HTMLAnchorElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLAnchorElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLAnchorElement::rel() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_REL);
+}
+
+void HTMLAnchorElement::setRel( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_REL, value);
+}
+
+DOMString HTMLAnchorElement::rev() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_REV);
+}
+
+void HTMLAnchorElement::setRev( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_REV, value);
+}
+
+DOMString HTMLAnchorElement::shape() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SHAPE);
+}
+
+void HTMLAnchorElement::setShape( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SHAPE, value);
+}
+
+long HTMLAnchorElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TABINDEX).toInt();
+}
+
+void HTMLAnchorElement::setTabIndex( long _tabIndex )
+{
+ if(impl) {
+ DOMString value(TQString::number(_tabIndex));
+ ((ElementImpl *)impl)->setAttribute(ATTR_TABINDEX,value);
+ }
+}
+
+DOMString HTMLAnchorElement::target() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TARGET);
+}
+
+void HTMLAnchorElement::setTarget( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TARGET, value);
+}
+
+DOMString HTMLAnchorElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLAnchorElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+void HTMLAnchorElement::blur( )
+{
+ if(impl && impl->getDocument()->focusNode()==impl)
+ impl->getDocument()->setFocusNode(0);
+}
+
+void HTMLAnchorElement::focus( )
+{
+ if(impl)
+ impl->getDocument()->setFocusNode(static_cast<ElementImpl*>(impl));
+}
+
+void HTMLAnchorElement::click( )
+{
+ if(impl) ((HTMLAnchorElement *)impl)->click();
+}
+
+
+// --------------------------------------------------------------------------
+
+HTMLBRElement::HTMLBRElement() : HTMLElement()
+{
+}
+
+HTMLBRElement::HTMLBRElement(const HTMLBRElement &other) : HTMLElement(other)
+{
+}
+
+HTMLBRElement::HTMLBRElement(HTMLBRElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLBRElement &HTMLBRElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BR );
+ return *this;
+}
+
+HTMLBRElement &HTMLBRElement::operator = (const HTMLBRElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLBRElement::~HTMLBRElement()
+{
+}
+
+DOMString HTMLBRElement::clear() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CLEAR);
+}
+
+void HTMLBRElement::setClear( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CLEAR, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLFontElement::HTMLFontElement() : HTMLElement()
+{
+}
+
+HTMLFontElement::HTMLFontElement(const HTMLFontElement &other) : HTMLElement(other)
+{
+}
+
+HTMLFontElement::HTMLFontElement(HTMLFontElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLFontElement &HTMLFontElement::operator = (const Node &other)
+{
+ assignOther( other, ID_FONT );
+ return *this;
+}
+
+HTMLFontElement &HTMLFontElement::operator = (const HTMLFontElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLFontElement::~HTMLFontElement()
+{
+}
+
+DOMString HTMLFontElement::color() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COLOR);
+}
+
+void HTMLFontElement::setColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_COLOR, value);
+}
+
+DOMString HTMLFontElement::face() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_FACE);
+}
+
+void HTMLFontElement::setFace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_FACE, value);
+}
+
+DOMString HTMLFontElement::size() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SIZE);
+}
+
+void HTMLFontElement::setSize( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SIZE, value);
+}
+
+
+// --------------------------------------------------------------------------
+
+HTMLModElement::HTMLModElement() : HTMLElement()
+{
+}
+
+HTMLModElement::HTMLModElement(const HTMLModElement &other) : HTMLElement(other)
+{
+}
+
+HTMLModElement::HTMLModElement(HTMLElementImpl *_impl)
+ : HTMLElement()
+{
+ if (_impl && (_impl->id() == ID_INS || _impl->id() == ID_DEL))
+ impl = _impl;
+ else
+ impl = 0;
+ if ( impl ) impl->ref();
+}
+
+HTMLModElement &HTMLModElement::operator = (const Node &other)
+{
+ if (other.handle() != handle()) {
+ if( other.elementId() != ID_INS &&
+ other.elementId() != ID_DEL )
+ {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+ }
+ return *this;
+}
+
+HTMLModElement &HTMLModElement::operator = (const HTMLModElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLModElement::~HTMLModElement()
+{
+}
+
+DOMString HTMLModElement::cite() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CITE);
+}
+
+void HTMLModElement::setCite( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CITE, value);
+}
+
+DOMString HTMLModElement::dateTime() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_DATETIME);
+}
+
+void HTMLModElement::setDateTime( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_DATETIME, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLQuoteElement::HTMLQuoteElement() : HTMLElement()
+{
+}
+
+HTMLQuoteElement::HTMLQuoteElement(const HTMLQuoteElement &other) : HTMLElement(other)
+{
+}
+
+HTMLQuoteElement::HTMLQuoteElement(HTMLGenericElementImpl *_impl)
+ : HTMLElement()
+{
+ if (_impl && _impl->id() == ID_Q)
+ impl = _impl;
+ else
+ impl = 0;
+ if ( impl ) impl->ref();
+}
+
+HTMLQuoteElement &HTMLQuoteElement::operator = (const Node &other)
+{
+ assignOther( other, ID_Q );
+ return *this;
+}
+
+HTMLQuoteElement &HTMLQuoteElement::operator = (const HTMLQuoteElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLQuoteElement::~HTMLQuoteElement()
+{
+}
+
+DOMString HTMLQuoteElement::cite() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CITE);
+}
+
+void HTMLQuoteElement::setCite( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CITE, value);
+}
+
diff --git a/tdehtml/dom/html_inline.h b/tdehtml/dom/html_inline.h
new file mode 100644
index 000000000..f92ed6917
--- /dev/null
+++ b/tdehtml/dom/html_inline.h
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_INLINE_H
+#define HTML_INLINE_H
+
+#include <dom/html_element.h>
+
+#include <tdelibs_export.h>
+
+namespace DOM {
+class HTMLGenericElementImpl;
+class HTMLAnchorElementImpl;
+class DOMString;
+
+/**
+ * The anchor element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#edef-A"> A
+ * element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLAnchorElement : public HTMLElement
+{
+public:
+ HTMLAnchorElement();
+ HTMLAnchorElement(const HTMLAnchorElement &other);
+ HTMLAnchorElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLAnchorElement(HTMLAnchorElementImpl *impl);
+public:
+
+ HTMLAnchorElement & operator = (const HTMLAnchorElement &other);
+ HTMLAnchorElement & operator = (const Node &other);
+
+ ~HTMLAnchorElement();
+
+ /**
+ * A single character access key to give access to the form
+ * control. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-accesskey">
+ * accesskey attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString accessKey() const;
+
+ /**
+ * see accessKey
+ */
+ void setAccessKey( const DOMString & );
+
+ /**
+ * The character encoding of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-charset">
+ * charset attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString charset() const;
+
+ /**
+ * see charset
+ */
+ void setCharset( const DOMString & );
+
+ /**
+ * Comma-separated list of lengths, defining an active region
+ * geometry. See also \c shape for the shape of the
+ * region. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-coords">
+ * coords attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString coords() const;
+
+ /**
+ * see coords
+ */
+ void setCoords( const DOMString & );
+
+ /**
+ * The URI of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-href">
+ * href attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString href() const;
+
+ /**
+ * see href
+ */
+ void setHref( const DOMString & );
+
+ /**
+ * Language code of the linked resource. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-hreflang">
+ * hreflang attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString hreflang() const;
+
+ /**
+ * see hreflang
+ */
+ void setHreflang( const DOMString & );
+
+ /**
+ * Anchor name. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-name-A">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Forward link type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-rel">
+ * rel attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rel() const;
+
+ /**
+ * see rel
+ */
+ void setRel( const DOMString & );
+
+ /**
+ * Reverse link type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-rev">
+ * rev attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rev() const;
+
+ /**
+ * see rev
+ */
+ void setRev( const DOMString & );
+
+ /**
+ * The shape of the active area. The coordinates are given by
+ * \c coords . See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-shape">
+ * shape attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString shape() const;
+
+ /**
+ * see shape
+ */
+ void setShape( const DOMString & );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * Frame to render the resource in. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">
+ * target attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString target() const;
+
+ /**
+ * see target
+ */
+ void setTarget( const DOMString & );
+
+ /**
+ * Advisory content type. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/links.html#adef-type-A">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * Removes keyboard focus from this element.
+ *
+ * @return
+ *
+ */
+ void blur ( );
+
+ /**
+ * Gives keyboard focus to this element.
+ *
+ * @return
+ *
+ */
+ void focus ( );
+
+ /**
+ * Simulate a mouse-click.
+ * NOTE: this method is not part of the DOM
+ * @since 3.5.7
+ */
+ void click ( );
+
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLBRElementImpl;
+
+/**
+ * Force a line break. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-BR"> BR
+ * element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLBRElement : public HTMLElement
+{
+public:
+ HTMLBRElement();
+ HTMLBRElement(const HTMLBRElement &other);
+ HTMLBRElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLBRElement(HTMLBRElementImpl *impl);
+public:
+
+ HTMLBRElement & operator = (const HTMLBRElement &other);
+ HTMLBRElement & operator = (const Node &other);
+
+ ~HTMLBRElement();
+
+ /**
+ * Control flow of text around floats. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-clear">
+ * clear attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString clear() const;
+
+ /**
+ * see clear
+ */
+ void setClear( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLFontElementImpl;
+class DOMString;
+
+/**
+ * Local change to font. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#edef-FONT">
+ * FONT element definition </a> in HTML 4.0. This element is
+ * deprecated in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLFontElement : public HTMLElement
+{
+public:
+ HTMLFontElement();
+ HTMLFontElement(const HTMLFontElement &other);
+ HTMLFontElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLFontElement(HTMLFontElementImpl *impl);
+public:
+
+ HTMLFontElement & operator = (const HTMLFontElement &other);
+ HTMLFontElement & operator = (const Node &other);
+
+ ~HTMLFontElement();
+
+ /**
+ * Font color. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-color-FONT">
+ * color attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString color() const;
+
+ /**
+ * see color
+ */
+ void setColor( const DOMString & );
+
+ /**
+ * Font face identifier. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-face-FONT">
+ * face attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString face() const;
+
+ /**
+ * see face
+ */
+ void setFace( const DOMString & );
+
+ /**
+ * Font size. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-size-FONT">
+ * size attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString size() const;
+
+ /**
+ * see size
+ */
+ void setSize( const DOMString & );
+};
+
+class HTMLModElementImpl;
+class DOMString;
+
+/**
+ * Notice of modification to part of a document. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-ins">
+ * INS </a> and <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-del">
+ * DEL </a> element definitions in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLModElement : public HTMLElement
+{
+public:
+ HTMLModElement();
+ HTMLModElement(const HTMLModElement &other);
+ HTMLModElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLModElement(HTMLElementImpl *impl);
+public:
+
+ HTMLModElement & operator = (const HTMLModElement &other);
+ HTMLModElement & operator = (const Node &other);
+
+ ~HTMLModElement();
+
+ /**
+ * A URI designating a document that describes the reason for the
+ * change. See the <a href="http://www.w3.org/TR/REC-html40/">
+ * cite attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cite() const;
+
+ /**
+ * see cite
+ */
+ void setCite( const DOMString & );
+
+ /**
+ * The date and time of the change. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#adef-datetime">
+ * datetime attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString dateTime() const;
+
+ /**
+ * see dateTime
+ */
+ void setDateTime( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLQuoteElementImpl;
+
+/**
+ * For the \c Q and \c BLOCKQUOTE elements.
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#edef-Q"> Q
+ * element definition </a> in HTML 4.0.
+ *
+ * Note: The DOM is not quite consistent here. They also define the
+ * HTMLBlockQuoteElement interface, to represent the \c BLOCKQUOTE
+ * element. To resolve ambiquities, we use this one for the \c Q
+ * element only.
+ */
+class KHTML_EXPORT HTMLQuoteElement : public HTMLElement
+{
+public:
+ HTMLQuoteElement();
+ HTMLQuoteElement(const HTMLQuoteElement &other);
+ HTMLQuoteElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLQuoteElement(HTMLGenericElementImpl *impl);
+public:
+
+ HTMLQuoteElement & operator = (const HTMLQuoteElement &other);
+ HTMLQuoteElement & operator = (const Node &other);
+
+ ~HTMLQuoteElement();
+
+ /**
+ * A URI designating a document that designates a source document
+ * or message. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/text.html#adef-cite-Q">
+ * cite attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cite() const;
+
+ /**
+ * see cite
+ */
+ void setCite( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_list.cpp b/tdehtml/dom/html_list.cpp
new file mode 100644
index 000000000..8d66fe3fc
--- /dev/null
+++ b/tdehtml/dom/html_list.cpp
@@ -0,0 +1,354 @@
+/**
+ * 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 "dom/html_list.h"
+#include "html/html_listimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLDListElement::HTMLDListElement() : HTMLElement()
+{
+}
+
+HTMLDListElement::HTMLDListElement(const HTMLDListElement &other) : HTMLElement(other)
+{
+}
+
+HTMLDListElement::HTMLDListElement(HTMLDListElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLDListElement &HTMLDListElement::operator = (const Node &other)
+{
+ assignOther( other, ID_DL );
+ return *this;
+}
+
+HTMLDListElement &HTMLDListElement::operator = (const HTMLDListElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLDListElement::~HTMLDListElement()
+{
+}
+
+bool HTMLDListElement::compact() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_COMPACT).isNull();
+}
+
+void HTMLDListElement::setCompact( bool _compact )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _compact )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_COMPACT, str);
+ }
+}
+
+// --------------------------------------------------------------------------
+
+HTMLDirectoryElement::HTMLDirectoryElement() : HTMLElement()
+{
+}
+
+HTMLDirectoryElement::HTMLDirectoryElement(const HTMLDirectoryElement &other) : HTMLElement(other)
+{
+}
+
+HTMLDirectoryElement::HTMLDirectoryElement(HTMLDirectoryElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLDirectoryElement &HTMLDirectoryElement::operator = (const Node &other)
+{
+ assignOther( other, ID_DIR );
+ return *this;
+}
+
+HTMLDirectoryElement &HTMLDirectoryElement::operator = (const HTMLDirectoryElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLDirectoryElement::~HTMLDirectoryElement()
+{
+}
+
+bool HTMLDirectoryElement::compact() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_COMPACT).isNull();
+}
+
+void HTMLDirectoryElement::setCompact( bool _compact )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _compact )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_COMPACT, str);
+ }
+}
+
+// --------------------------------------------------------------------------
+
+HTMLLIElement::HTMLLIElement() : HTMLElement()
+{
+}
+
+HTMLLIElement::HTMLLIElement(const HTMLLIElement &other) : HTMLElement(other)
+{
+}
+
+HTMLLIElement::HTMLLIElement(HTMLLIElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLLIElement &HTMLLIElement::operator = (const Node &other)
+{
+ assignOther( other, ID_LI );
+ return *this;
+}
+
+HTMLLIElement &HTMLLIElement::operator = (const HTMLLIElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLLIElement::~HTMLLIElement()
+{
+}
+
+DOMString HTMLLIElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLLIElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+long HTMLLIElement::value() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALUE).toInt();
+}
+
+void HTMLLIElement::setValue( long _value )
+{
+ if(impl) {
+ DOMString value(TQString::number(_value));
+ ((ElementImpl *)impl)->setAttribute(ATTR_VALUE,value);
+ }
+}
+
+// --------------------------------------------------------------------------
+
+HTMLMenuElement::HTMLMenuElement() : HTMLElement()
+{
+}
+
+HTMLMenuElement::HTMLMenuElement(const HTMLMenuElement &other) : HTMLElement(other)
+{
+}
+
+HTMLMenuElement::HTMLMenuElement(HTMLMenuElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLMenuElement &HTMLMenuElement::operator = (const Node &other)
+{
+ assignOther( other, ID_MENU );
+ return *this;
+}
+
+HTMLMenuElement &HTMLMenuElement::operator = (const HTMLMenuElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLMenuElement::~HTMLMenuElement()
+{
+}
+
+bool HTMLMenuElement::compact() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_COMPACT).isNull();
+}
+
+void HTMLMenuElement::setCompact( bool _compact )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _compact )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_COMPACT, str);
+ }
+}
+
+// --------------------------------------------------------------------------
+
+HTMLOListElement::HTMLOListElement() : HTMLElement()
+{
+}
+
+HTMLOListElement::HTMLOListElement(const HTMLOListElement &other) : HTMLElement(other)
+{
+}
+
+HTMLOListElement::HTMLOListElement(HTMLOListElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLOListElement &HTMLOListElement::operator = (const Node &other)
+{
+ assignOther( other, ID_OL );
+ return *this;
+}
+
+HTMLOListElement &HTMLOListElement::operator = (const HTMLOListElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLOListElement::~HTMLOListElement()
+{
+}
+
+bool HTMLOListElement::compact() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_COMPACT).isNull();
+}
+
+void HTMLOListElement::setCompact( bool _compact )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _compact )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_COMPACT, str);
+ }
+}
+
+long HTMLOListElement::start() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_START).toInt();
+}
+
+void HTMLOListElement::setStart( long _start )
+{
+
+ if(impl) {
+ DOMString value(TQString::number(_start));
+ ((ElementImpl *)impl)->setAttribute(ATTR_START,value);
+ }
+}
+
+DOMString HTMLOListElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLOListElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLUListElement::HTMLUListElement() : HTMLElement()
+{
+}
+
+HTMLUListElement::HTMLUListElement(const HTMLUListElement &other) : HTMLElement(other)
+{
+}
+
+HTMLUListElement::HTMLUListElement(HTMLUListElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLUListElement &HTMLUListElement::operator = (const Node &other)
+{
+ assignOther( other, ID_UL );
+ return *this;
+}
+
+HTMLUListElement &HTMLUListElement::operator = (const HTMLUListElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLUListElement::~HTMLUListElement()
+{
+}
+
+bool HTMLUListElement::compact() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_COMPACT).isNull();
+}
+
+void HTMLUListElement::setCompact( bool _compact )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _compact )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_COMPACT, str);
+ }
+}
+
+DOMString HTMLUListElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLUListElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
diff --git a/tdehtml/dom/html_list.h b/tdehtml/dom/html_list.h
new file mode 100644
index 000000000..34c081cb5
--- /dev/null
+++ b/tdehtml/dom/html_list.h
@@ -0,0 +1,341 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_LIST_H
+#define HTML_LIST_H
+
+#include <dom/html_element.h>
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class HTMLDListElementImpl;
+class HTMLUListElementImpl;
+class HTMLOListElementImpl;
+class HTMLDirectoryElementImpl;
+class HTMLMenuElementImpl;
+class HTMLLIElementImpl;
+
+class DOMString;
+
+/**
+ * Definition list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-DL">
+ * DL element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLDListElement : public HTMLElement
+{
+public:
+ HTMLDListElement();
+ HTMLDListElement(const HTMLDListElement &other);
+ HTMLDListElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLDListElement(HTMLDListElementImpl *impl);
+public:
+
+ HTMLDListElement & operator = (const HTMLDListElement &other);
+ HTMLDListElement & operator = (const Node &other);
+
+ ~HTMLDListElement();
+
+ /**
+ * Reduce spacing between list items. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-compact">
+ * compact attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool compact() const;
+
+ /**
+ * see compact
+ */
+ void setCompact( bool );
+};
+
+// --------------------------------------------------------------------------
+
+/**
+ * Directory list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-DIR">
+ * DIR element definition </a> in HTML 4.0. This element is deprecated
+ * in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLDirectoryElement : public HTMLElement
+{
+public:
+ HTMLDirectoryElement();
+ HTMLDirectoryElement(const HTMLDirectoryElement &other);
+ HTMLDirectoryElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLDirectoryElement(HTMLDirectoryElementImpl *impl);
+public:
+
+ HTMLDirectoryElement & operator = (const HTMLDirectoryElement &other);
+ HTMLDirectoryElement & operator = (const Node &other);
+
+ ~HTMLDirectoryElement();
+
+ /**
+ * Reduce spacing between list items. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-compact">
+ * compact attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool compact() const;
+
+ /**
+ * see compact
+ */
+ void setCompact( bool );
+};
+
+// --------------------------------------------------------------------------
+
+/**
+ * List item. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-LI">
+ * LI element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLLIElement : public HTMLElement
+{
+public:
+ HTMLLIElement();
+ HTMLLIElement(const HTMLLIElement &other);
+ HTMLLIElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+
+protected:
+ HTMLLIElement(HTMLLIElementImpl *impl);
+public:
+
+ HTMLLIElement & operator = (const HTMLLIElement &other);
+ HTMLLIElement & operator = (const Node &other);
+
+ ~HTMLLIElement();
+
+ /**
+ * List item bullet style. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-type-LI">
+ * type attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * Reset sequence number when used in \c OL See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-value-LI">
+ * value attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long value() const;
+
+ /**
+ * see value
+ */
+ void setValue( long );
+};
+
+// --------------------------------------------------------------------------
+
+/**
+ * Menu list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-MENU">
+ * MENU element definition </a> in HTML 4.0. This element is
+ * deprecated in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLMenuElement : public HTMLElement
+{
+public:
+ HTMLMenuElement();
+ HTMLMenuElement(const HTMLMenuElement &other);
+ HTMLMenuElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+
+protected:
+ HTMLMenuElement(HTMLMenuElementImpl *impl);
+public:
+
+ HTMLMenuElement & operator = (const HTMLMenuElement &other);
+ HTMLMenuElement & operator = (const Node &other);
+
+ ~HTMLMenuElement();
+
+ /**
+ * Reduce spacing between list items. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-compact">
+ * compact attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool compact() const;
+
+ /**
+ * see compact
+ */
+ void setCompact( bool );
+};
+
+// --------------------------------------------------------------------------
+
+/**
+ * Ordered list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-OL">
+ * OL element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLOListElement : public HTMLElement
+{
+public:
+ HTMLOListElement();
+ HTMLOListElement(const HTMLOListElement &other);
+ HTMLOListElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLOListElement(HTMLOListElementImpl *impl);
+public:
+
+ HTMLOListElement & operator = (const HTMLOListElement &other);
+ HTMLOListElement & operator = (const Node &other);
+
+ ~HTMLOListElement();
+
+ /**
+ * Reduce spacing between list items. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-compact">
+ * compact attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool compact() const;
+
+ /**
+ * see compact
+ */
+ void setCompact( bool );
+
+ /**
+ * Starting sequence number. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-start">
+ * start attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long start() const;
+
+ /**
+ * see start
+ */
+ void setStart( long );
+
+ /**
+ * Numbering style. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-type-OL">
+ * type attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+
+/**
+ * Unordered list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#edef-UL">
+ * UL element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLUListElement : public HTMLElement
+{
+public:
+ HTMLUListElement();
+ HTMLUListElement(const HTMLUListElement &other);
+ HTMLUListElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLUListElement(HTMLUListElementImpl *impl);
+public:
+
+ HTMLUListElement & operator = (const HTMLUListElement &other);
+ HTMLUListElement & operator = (const Node &other);
+
+ ~HTMLUListElement();
+
+ /**
+ * Reduce spacing between list items. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-compact">
+ * compact attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ bool compact() const;
+
+ /**
+ * see compact
+ */
+ void setCompact( bool );
+
+ /**
+ * Bullet style. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/lists.html#adef-type-UL">
+ * type attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_misc.cpp b/tdehtml/dom/html_misc.cpp
new file mode 100644
index 000000000..fb975b7cf
--- /dev/null
+++ b/tdehtml/dom/html_misc.cpp
@@ -0,0 +1,214 @@
+/**
+ * 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 "dom/html_misc.h"
+#include "html/html_miscimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLBaseFontElement::HTMLBaseFontElement() : HTMLElement()
+{
+}
+
+HTMLBaseFontElement::HTMLBaseFontElement(const HTMLBaseFontElement &other) : HTMLElement(other)
+{
+}
+
+HTMLBaseFontElement::HTMLBaseFontElement(HTMLBaseFontElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLBaseFontElement &HTMLBaseFontElement::operator = (const Node &other)
+{
+ assignOther( other, ID_BASEFONT );
+ return *this;
+}
+
+HTMLBaseFontElement &HTMLBaseFontElement::operator = (const HTMLBaseFontElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLBaseFontElement::~HTMLBaseFontElement()
+{
+}
+
+DOMString HTMLBaseFontElement::color() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COLOR);
+}
+
+void HTMLBaseFontElement::setColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_COLOR, value);
+}
+
+DOMString HTMLBaseFontElement::face() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_FACE);
+}
+
+void HTMLBaseFontElement::setFace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_FACE, value);
+}
+
+DOMString HTMLBaseFontElement::size() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SIZE);
+}
+
+void HTMLBaseFontElement::setSize( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SIZE, value);
+}
+
+long HTMLBaseFontElement::getSize() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SIZE).toInt();
+}
+
+void HTMLBaseFontElement::setSize( long _value )
+{
+ if ( impl )
+ {
+ DOMString value( TQString::number( _value ) );
+ ((ElementImpl *)impl)->setAttribute(ATTR_SIZE, value);
+ }
+}
+
+
+// --------------------------------------------------------------------------
+
+HTMLCollection::HTMLCollection()
+ : impl(0)
+{
+}
+
+HTMLCollection::HTMLCollection(const HTMLCollection &other)
+{
+ impl = other.impl;
+ if(impl) impl->ref();
+}
+
+HTMLCollection::HTMLCollection(NodeImpl *base, int type)
+{
+ impl = new HTMLCollectionImpl(base, type);
+ impl->ref();
+}
+
+HTMLCollection &HTMLCollection::operator = (const HTMLCollection &other)
+{
+ if(impl != other.impl) {
+ if(impl) impl->deref();
+ impl = other.impl;
+ if(impl) impl->ref();
+ }
+ return *this;
+}
+
+HTMLCollection::~HTMLCollection()
+{
+ if(impl) impl->deref();
+}
+
+unsigned long HTMLCollection::length() const
+{
+ if(!impl) return 0;
+ return ((HTMLCollectionImpl *)impl)->length();
+}
+
+Node HTMLCollection::item( unsigned long index ) const
+{
+ if(!impl) return 0;
+ return ((HTMLCollectionImpl *)impl)->item( index );
+}
+
+Node HTMLCollection::namedItem( const DOMString &name ) const
+{
+ if(!impl) return 0;
+ return ((HTMLCollectionImpl *)impl)->namedItem( name );
+}
+
+Node HTMLCollection::base() const
+{
+ if ( !impl )
+ return 0;
+
+ return static_cast<HTMLCollectionImpl*>( impl )->m_refNode;
+}
+
+Node HTMLCollection::firstItem() const
+{
+ if ( !impl )
+ return 0;
+ return static_cast<HTMLCollectionImpl*>( impl )->firstItem();
+}
+
+Node HTMLCollection::nextItem() const
+{
+ if ( !impl )
+ return 0;
+ return static_cast<HTMLCollectionImpl*>( impl )->nextItem();
+}
+
+Node HTMLCollection::nextNamedItem( const DOMString &name ) const
+{
+ if ( !impl )
+ return 0;
+ return static_cast<HTMLCollectionImpl*>( impl )->nextNamedItem( name );
+}
+
+HTMLCollectionImpl *HTMLCollection::handle() const
+{
+ return impl;
+}
+
+bool HTMLCollection::isNull() const
+{
+ return (impl == 0);
+}
+
+
+// -----------------------------------------------------------------------------
+
+HTMLFormCollection::HTMLFormCollection(NodeImpl *base)
+ : HTMLCollection()
+{
+ impl = new HTMLFormCollectionImpl(base);
+ impl->ref();
+}
+
+
+// -----------------------------------------------------------------------------
+HTMLMappedNameCollection::HTMLMappedNameCollection(NodeImpl *base, int type, const DOMString &name )
+{
+ impl = new HTMLMappedNameCollectionImpl(base, type, name);
+ impl->ref();
+}
diff --git a/tdehtml/dom/html_misc.h b/tdehtml/dom/html_misc.h
new file mode 100644
index 000000000..643e5caf6
--- /dev/null
+++ b/tdehtml/dom/html_misc.h
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_MISC_H
+#define HTML_MISC_H
+
+#include <dom/html_element.h>
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class HTMLBaseFontElementImpl;
+class DOMString;
+class HTMLCollectionImpl;
+
+/**
+ * Base font. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#edef-BASEFONT">
+ * BASEFONT element definition </a> in HTML 4.0. This element is
+ * deprecated in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLBaseFontElement : public HTMLElement
+{
+public:
+ HTMLBaseFontElement();
+ HTMLBaseFontElement(const HTMLBaseFontElement &other);
+ HTMLBaseFontElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLBaseFontElement(HTMLBaseFontElementImpl *impl);
+public:
+
+ HTMLBaseFontElement & operator = (const HTMLBaseFontElement &other);
+ HTMLBaseFontElement & operator = (const Node &other);
+
+ ~HTMLBaseFontElement();
+
+ /**
+ * Font color. See the <a href="http://www.w3.org/TR/REC-html40/">
+ * color attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString color() const;
+
+ /**
+ * see color
+ */
+ void setColor( const DOMString & );
+
+ /**
+ * Font face identifier. See the <a
+ * href="http://www.w3.org/TR/REC-html40/"> face attribute
+ * definition </a> in HTML 4.0. This attribute is deprecated in
+ * HTML 4.0.
+ *
+ */
+ DOMString face() const;
+
+ /**
+ * see face
+ */
+ void setFace( const DOMString & );
+
+ /**
+ * Computed Font size. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-size-BASEFONT">
+ * size attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long getSize() const;
+
+ /**
+ * see size
+ */
+ void setSize( long );
+
+ /**
+ * @deprecated
+ */
+ DOMString size() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setSize( const DOMString & ) KDE_DEPRECATED;
+};
+
+// --------------------------------------------------------------------------
+
+/**
+ * An \c HTMLCollection is a list of nodes. An individual
+ * node may be accessed by either ordinal index or the node's
+ * \c name or \c id attributes. Note: Collections in
+ * the HTML DOM are assumed to be live meaning that they are
+ * automatically updated when the underlying document is changed.
+ *
+ */
+class KHTML_EXPORT HTMLCollection
+{
+ friend class HTMLDocument;
+ friend class HTMLSelectElement;
+ friend class HTMLImageElement;
+ friend class HTMLMapElement;
+ friend class HTMLTableElement;
+ friend class HTMLTableRowElement;
+ friend class HTMLTableSectionElement;
+ friend class HTMLLayerElement;
+ friend class HTMLElement;
+
+public:
+ HTMLCollection();
+ HTMLCollection(const HTMLCollection &other);
+protected:
+ HTMLCollection(NodeImpl *base, int type);
+public:
+
+ HTMLCollection & operator = (const HTMLCollection &other);
+
+ ~HTMLCollection();
+
+ /**
+ * This attribute specifies the length or size of the list.
+ *
+ */
+ unsigned long length() const;
+
+ /**
+ * This method retrieves a node specified by ordinal index. Nodes
+ * are numbered in tree order (depth-first traversal order).
+ *
+ * @param index The index of the node to be fetched. The index
+ * origin is 0.
+ *
+ * @return The \c Node at the corresponding position
+ * upon success. A value of \c null is returned if the
+ * index is out of range.
+ *
+ */
+ Node item ( unsigned long index ) const;
+
+ /**
+ * This method retrieves a \c Node using a name. It
+ * first searches for a \c Node with a matching
+ * \c id attribute. If it doesn't find one, it then searches
+ * for a \c Node with a matching \c name
+ * attribute, but only on those elements that are allowed a name
+ * attribute.
+ *
+ * @param name The name of the \c Node to be fetched.
+ *
+ * @return The \c Node with a \c name or
+ * \c id attribute whose value corresponds to the
+ * specified string. Upon failure (e.g., no node with this name
+ * exists), returns \c null .
+ *
+ */
+ Node namedItem ( const DOMString &name ) const;
+
+ /**
+ * @internal
+ * not part of the DOM
+ */
+ Node base() const;
+ HTMLCollectionImpl *handle() const;
+ bool isNull() const;
+ // Fast iteration
+ Node firstItem() const;
+ Node nextItem() const;
+ // In case of multiple items named the same way
+ Node nextNamedItem( const DOMString &name ) const;
+
+protected:
+ HTMLCollectionImpl *impl;
+};
+
+class KHTML_EXPORT HTMLFormCollection : public HTMLCollection
+{
+ friend class HTMLFormElement;
+protected:
+ HTMLFormCollection(NodeImpl *base);
+};
+
+/**
+ @internal. Not part of the public API
+*/
+class KHTML_EXPORT HTMLMappedNameCollection : public HTMLCollection
+{
+public:
+ HTMLMappedNameCollection(NodeImpl *base, int type, const DOMString &name );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/dom/html_object.cpp b/tdehtml/dom/html_object.cpp
new file mode 100644
index 000000000..65ec2f34e
--- /dev/null
+++ b/tdehtml/dom/html_object.cpp
@@ -0,0 +1,535 @@
+/**
+ * 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 "dom/dom_doc.h"
+#include "dom/html_object.h"
+#include "html/html_objectimpl.h"
+#include "misc/htmlhashes.h"
+
+HTMLAppletElement::HTMLAppletElement() : HTMLElement()
+{
+}
+
+HTMLAppletElement::HTMLAppletElement(const HTMLAppletElement &other)
+ : HTMLElement(other)
+{
+}
+
+HTMLAppletElement::HTMLAppletElement(HTMLAppletElementImpl *impl)
+ : HTMLElement(impl)
+{
+}
+
+HTMLAppletElement &HTMLAppletElement::operator = (const Node &other)
+{
+ assignOther( other, ID_APPLET );
+ return *this;
+}
+
+HTMLAppletElement &HTMLAppletElement::operator = (const HTMLAppletElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLAppletElement::~HTMLAppletElement()
+{
+}
+
+DOMString HTMLAppletElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLAppletElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLAppletElement::alt() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALT);
+}
+
+void HTMLAppletElement::setAlt( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALT, value);
+}
+
+DOMString HTMLAppletElement::archive() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ARCHIVE);
+}
+
+void HTMLAppletElement::setArchive( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ARCHIVE, value);
+}
+
+DOMString HTMLAppletElement::code() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CODE);
+}
+
+void HTMLAppletElement::setCode( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CODE, value);
+}
+
+DOMString HTMLAppletElement::codeBase() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CODEBASE);
+}
+
+void HTMLAppletElement::setCodeBase( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CODEBASE, value);
+}
+
+DOMString HTMLAppletElement::height() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HEIGHT);
+}
+
+void HTMLAppletElement::setHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEIGHT, value);
+}
+
+DOMString HTMLAppletElement::hspace() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HSPACE);
+}
+
+void HTMLAppletElement::setHspace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HSPACE, value);
+}
+
+long HTMLAppletElement::getHspace() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HSPACE).toInt();
+}
+
+void HTMLAppletElement::setHspace( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HSPACE, TQString::number(value));
+}
+
+DOMString HTMLAppletElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLAppletElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLAppletElement::object() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_OBJECT);
+}
+
+void HTMLAppletElement::setObject( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_OBJECT, value);
+}
+
+DOMString HTMLAppletElement::vspace() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VSPACE);
+}
+
+void HTMLAppletElement::setVspace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VSPACE, value);
+}
+
+long HTMLAppletElement::getVspace() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VSPACE).toInt();
+}
+
+void HTMLAppletElement::setVspace( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VSPACE, TQString::number(value));
+}
+
+
+DOMString HTMLAppletElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLAppletElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLObjectElement::HTMLObjectElement() : HTMLElement()
+{
+}
+
+HTMLObjectElement::HTMLObjectElement(const HTMLObjectElement &other) : HTMLElement(other)
+{
+}
+
+HTMLObjectElement::HTMLObjectElement(HTMLObjectElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLObjectElement &HTMLObjectElement::operator = (const Node &other)
+{
+ assignOther( other, ID_OBJECT );
+ return *this;
+}
+
+HTMLObjectElement &HTMLObjectElement::operator = (const HTMLObjectElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLObjectElement::~HTMLObjectElement()
+{
+}
+
+HTMLFormElement HTMLObjectElement::form() const
+{
+ if(!impl) return 0;
+ return ((HTMLObjectElementImpl *)impl)->form();
+}
+
+DOMString HTMLObjectElement::code() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CODE);
+}
+
+void HTMLObjectElement::setCode( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CODE, value);
+}
+
+DOMString HTMLObjectElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLObjectElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLObjectElement::archive() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ARCHIVE);
+}
+
+void HTMLObjectElement::setArchive( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ARCHIVE, value);
+}
+
+DOMString HTMLObjectElement::border() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BORDER);
+}
+
+void HTMLObjectElement::setBorder( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BORDER, value);
+}
+
+DOMString HTMLObjectElement::codeBase() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CODEBASE);
+}
+
+void HTMLObjectElement::setCodeBase( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CODEBASE, value);
+}
+
+DOMString HTMLObjectElement::codeType() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CODETYPE);
+}
+
+void HTMLObjectElement::setCodeType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CODETYPE, value);
+}
+
+DOMString HTMLObjectElement::data() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_DATA);
+}
+
+void HTMLObjectElement::setData( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_DATA, value);
+}
+
+bool HTMLObjectElement::declare() const
+{
+ if(!impl) return 0;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_DECLARE).isNull();
+}
+
+void HTMLObjectElement::setDeclare( bool _declare )
+{
+ if(impl)
+ {
+ DOMString str;
+ if( _declare )
+ str = "";
+ ((ElementImpl *)impl)->setAttribute(ATTR_DECLARE, str);
+ }
+}
+
+DOMString HTMLObjectElement::height() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HEIGHT);
+}
+
+void HTMLObjectElement::setHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEIGHT, value);
+}
+
+DOMString HTMLObjectElement::hspace() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HSPACE);
+}
+
+void HTMLObjectElement::setHspace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HSPACE, value);
+}
+
+long HTMLObjectElement::getHspace() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HSPACE).toInt();
+}
+
+void HTMLObjectElement::setHspace( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HSPACE, TQString::number(value));
+}
+
+DOMString HTMLObjectElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLObjectElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLObjectElement::standby() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_STANDBY);
+}
+
+void HTMLObjectElement::setStandby( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_STANDBY, value);
+}
+
+long HTMLObjectElement::tabIndex() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TABINDEX).toInt();
+}
+
+void HTMLObjectElement::setTabIndex( long _tabIndex )
+{
+ if(impl) {
+ DOMString value(TQString::number(_tabIndex));
+ ((ElementImpl *)impl)->setAttribute(ATTR_TABINDEX,value);
+ }
+}
+
+DOMString HTMLObjectElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLObjectElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+DOMString HTMLObjectElement::useMap() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_USEMAP);
+}
+
+void HTMLObjectElement::setUseMap( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_USEMAP, value);
+}
+
+DOMString HTMLObjectElement::vspace() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VSPACE);
+}
+
+void HTMLObjectElement::setVspace( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VSPACE, value);
+}
+
+long HTMLObjectElement::getVspace() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VSPACE).toInt();
+}
+
+void HTMLObjectElement::setVspace( long value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VSPACE, TQString::number(value));
+}
+
+DOMString HTMLObjectElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLObjectElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+Document HTMLObjectElement::contentDocument() const
+{
+ if (impl) return static_cast<HTMLObjectElementImpl*>(impl)->contentDocument();
+ return Document();
+}
+
+// --------------------------------------------------------------------------
+
+HTMLParamElement::HTMLParamElement() : HTMLElement()
+{
+}
+
+HTMLParamElement::HTMLParamElement(const HTMLParamElement &other) : HTMLElement(other)
+{
+}
+
+HTMLParamElement::HTMLParamElement(HTMLParamElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLParamElement &HTMLParamElement::operator = (const Node &other)
+{
+ assignOther( other, ID_PARAM );
+ return *this;
+}
+
+HTMLParamElement &HTMLParamElement::operator = (const HTMLParamElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLParamElement::~HTMLParamElement()
+{
+}
+
+DOMString HTMLParamElement::name() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_NAME);
+}
+
+void HTMLParamElement::setName( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_NAME, value);
+}
+
+DOMString HTMLParamElement::type() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_TYPE);
+}
+
+void HTMLParamElement::setType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_TYPE, value);
+}
+
+DOMString HTMLParamElement::value() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALUE);
+}
+
+void HTMLParamElement::setValue( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALUE, value);
+}
+
+DOMString HTMLParamElement::valueType() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALUETYPE);
+}
+
+void HTMLParamElement::setValueType( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALUETYPE, value);
+}
+
diff --git a/tdehtml/dom/html_object.h b/tdehtml/dom/html_object.h
new file mode 100644
index 000000000..9195a40f7
--- /dev/null
+++ b/tdehtml/dom/html_object.h
@@ -0,0 +1,630 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+
+// --------------------------------------------------------------------------
+
+#ifndef HTML_OBJECT_H
+#define HTML_OBJECT_H
+
+#include <dom/html_element.h>
+#include <dom/html_form.h>
+#include <kdemacros.h>
+
+namespace DOM {
+
+class HTMLAppletElementImpl;
+
+/**
+ * An embedded Java applet. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-APPLET">
+ * APPLET element definition </a> in HTML 4.0. This element is
+ * deprecated in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLAppletElement : public HTMLElement
+{
+public:
+ HTMLAppletElement();
+ HTMLAppletElement(const HTMLAppletElement &other);
+ HTMLAppletElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLAppletElement(HTMLAppletElementImpl *impl);
+public:
+
+ HTMLAppletElement & operator = (const HTMLAppletElement &other);
+ HTMLAppletElement & operator = (const Node &other);
+
+ ~HTMLAppletElement();
+
+ /**
+ * Aligns this object (vertically or horizontally) with respect to
+ * its surrounding text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-align-IMG">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Alternate text for user agents not rendering the normal content
+ * of this element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-alt">
+ * alt attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString alt() const;
+
+ /**
+ * see alt
+ */
+ void setAlt( const DOMString & );
+
+ /**
+ * Comma-separated archive list. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-archive-APPLET">
+ * archive attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString archive() const;
+
+ /**
+ * see archive
+ */
+ void setArchive( const DOMString & );
+
+ /**
+ * Applet class file. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-code">
+ * code attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString code() const;
+
+ /**
+ * see code
+ */
+ void setCode( const DOMString & );
+
+ /**
+ * Optional base URI for applet. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-codebase-APPLET">
+ * codebase attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString codeBase() const;
+
+ /**
+ * see codeBase
+ */
+ void setCodeBase( const DOMString &value );
+
+ /**
+ * Override height. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-height-APPLET">
+ * height attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( const DOMString & );
+
+ /**
+ * Horizontal space, in pixels, to the left and right of this image, applet,
+ * or object. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-hspace">
+ * hspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long getHspace() const;
+
+ /**
+ * see hspace
+ */
+ void setHspace( long );
+
+ /**
+ * @deprecated
+ */
+ DOMString hspace() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setHspace( const DOMString &value ) KDE_DEPRECATED;
+
+ /**
+ * The name of the applet. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-name-APPLET">
+ * name attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Serialized applet file. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-object">
+ * object attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString object() const;
+
+ /**
+ * see object
+ */
+ void setObject( const DOMString & );
+
+ /**
+ * Vertical space, in pixels, above and below this image, applet, or object.
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-vspace">
+ * vspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long getVspace() const;
+
+ /**
+ * see vspace
+ */
+ void setVspace( long );
+
+ /**
+ * @deprecated
+ */
+ DOMString vspace() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setVspace( const DOMString & ) KDE_DEPRECATED;
+
+ /**
+ * Override width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-width-APPLET">
+ * width attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLObjectElementImpl;
+
+/**
+ * Generic embedded object. Note. In principle, all properties on the
+ * object element are read-write but in some environments some
+ * properties may be read-only once the underlying object is
+ * instantiated. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-OBJECT">
+ * OBJECT element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLObjectElement : public HTMLElement
+{
+public:
+ HTMLObjectElement();
+ HTMLObjectElement(const HTMLObjectElement &other);
+ HTMLObjectElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLObjectElement(HTMLObjectElementImpl *impl);
+public:
+
+ HTMLObjectElement & operator = (const HTMLObjectElement &other);
+ HTMLObjectElement & operator = (const Node &other);
+
+ ~HTMLObjectElement();
+
+ /**
+ * Returns the \c FORM element containing this
+ * control. Returns null if this control is not within the context
+ * of a form.
+ *
+ */
+ HTMLFormElement form() const;
+
+ /**
+ * Applet class file. See the \c code attribute for
+ * HTMLAppletElement.
+ *
+ */
+ DOMString code() const;
+
+ /**
+ * see code
+ */
+ void setCode( const DOMString & );
+
+ /**
+ * Aligns this object (vertically or horizontally) with respect to
+ * its surrounding text. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-align-IMG">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Space-separated list of archives. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-archive-OBJECT">
+ * archive attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString archive() const;
+
+ /**
+ * see archive
+ */
+ void setArchive( const DOMString & );
+
+ /**
+ * Width of border around the object. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-border">
+ * border attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString border() const;
+
+ /**
+ * see border
+ */
+ void setBorder( const DOMString & );
+
+ /**
+ * Base URI for \c classid , \c data , and
+ * \c archive attributes. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-codebase-OBJECT">
+ * codebase attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString codeBase() const;
+
+ /**
+ * see codeBase
+ */
+ void setCodeBase( const DOMString & );
+
+ /**
+ * Content type for data downloaded via \c classid
+ * attribute. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-codetype">
+ * codetype attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString codeType() const;
+
+ /**
+ * see codeType
+ */
+ void setCodeType( const DOMString & );
+
+ /**
+ * A URI specifying the location of the object's data. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-data">
+ * data attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString data() const;
+
+ /**
+ * see data
+ */
+ void setData( const DOMString & );
+
+ /**
+ * Declare (for future reference), but do not instantiate, this
+ * object. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-declare">
+ * declare attribute definition </a> in HTML 4.0.
+ *
+ */
+ bool declare() const;
+
+ /**
+ * see declare
+ */
+ void setDeclare( bool );
+
+ /**
+ * Override height. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-height-IMG">
+ * height attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( const DOMString & );
+
+ /**
+ * Horizontal space, in pixels, to the left and right of this image, applet,
+ * or object. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-hspace">
+ * hspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long getHspace() const;
+
+ /**
+ * see hspace
+ */
+ void setHspace( long );
+
+ /**
+ * @deprecated
+ */
+ DOMString hspace() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setHspace( const DOMString & ) KDE_DEPRECATED;
+
+ /**
+ * Form control or object name when submitted with a form. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-name-INPUT">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Message to render while loading the object. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-standby">
+ * standby attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString standby() const;
+
+ /**
+ * see standby
+ */
+ void setStandby( const DOMString & );
+
+ /**
+ * Index that represents the element's position in the tabbing
+ * order. See the <a
+ * href="http://www.w3.org/TR/REC-html40/interact/forms.html#adef-tabindex">
+ * tabindex attribute definition </a> in HTML 4.0.
+ *
+ */
+ long tabIndex() const;
+
+ /**
+ * see tabIndex
+ */
+ void setTabIndex( long );
+
+ /**
+ * Content type for data downloaded via \c data
+ * attribute. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-type-OBJECT">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * Use client-side image map. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-usemap">
+ * usemap attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString useMap() const;
+
+ /**
+ * see useMap
+ */
+ void setUseMap( const DOMString & );
+
+ /**
+ * Vertical space, in pixels, above and below this image, applet, or object.
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-vspace">
+ * vspace attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ long getVspace() const;
+
+ /**
+ * see vspace
+ */
+ void setVspace( long );
+
+ /**
+ * @deprecated
+ */
+ DOMString vspace() const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ */
+ void setVspace( const DOMString & ) KDE_DEPRECATED;
+
+ /**
+ * Override width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-width-IMG">
+ * width attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+
+ /**
+ * Introduced in DOM Level 2
+ *
+ * Returns the document this iframe contains, if there is any and
+ * it is available, a Null document otherwise. The attribute is
+ * read-only.
+ *
+ * @return The content Document if available.
+ */
+ Document contentDocument() const;
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLParamElementImpl;
+
+/**
+ * Parameters fed to the \c OBJECT element. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#edef-PARAM">
+ * PARAM element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLParamElement : public HTMLElement
+{
+public:
+ HTMLParamElement();
+ HTMLParamElement(const HTMLParamElement &other);
+ HTMLParamElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLParamElement(HTMLParamElementImpl *impl);
+public:
+
+ HTMLParamElement & operator = (const HTMLParamElement &other);
+ HTMLParamElement & operator = (const Node &other);
+
+ ~HTMLParamElement();
+
+ /**
+ * The name of a run-time parameter. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-name-PARAM">
+ * name attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString name() const;
+
+ /**
+ * see name
+ */
+ void setName( const DOMString & );
+
+ /**
+ * Content type for the \c value attribute when
+ * \c valuetype has the value "ref". See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-type-PARAM">
+ * type attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString type() const;
+
+ /**
+ * see type
+ */
+ void setType( const DOMString & );
+
+ /**
+ * The value of a run-time parameter. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-value-PARAM">
+ * value attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString value() const;
+
+ /**
+ * see value
+ */
+ void setValue( const DOMString & );
+
+ /**
+ * Information about the meaning of the \c value
+ * attribute value. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/objects.html#adef-valuetype">
+ * valuetype attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString valueType() const;
+
+ /**
+ * see valueType
+ */
+ void setValueType( const DOMString & );
+};
+
+} // namespace
+
+#endif
diff --git a/tdehtml/dom/html_table.cpp b/tdehtml/dom/html_table.cpp
new file mode 100644
index 000000000..b42c4fcd1
--- /dev/null
+++ b/tdehtml/dom/html_table.cpp
@@ -0,0 +1,868 @@
+/**
+ * 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 "dom/html_misc.h"
+#include "dom/html_table.h"
+#include "dom/dom_exception.h"
+
+#include "html/html_miscimpl.h"
+#include "html/html_tableimpl.h"
+#include "misc/htmlhashes.h"
+
+using namespace DOM;
+
+HTMLTableCaptionElement::HTMLTableCaptionElement() : HTMLElement()
+{
+}
+
+HTMLTableCaptionElement::HTMLTableCaptionElement(const HTMLTableCaptionElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableCaptionElement::HTMLTableCaptionElement(HTMLTableCaptionElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableCaptionElement &HTMLTableCaptionElement::operator = (const Node &other)
+{
+ assignOther( other, ID_CAPTION );
+ return *this;
+}
+
+HTMLTableCaptionElement &HTMLTableCaptionElement::operator = (const HTMLTableCaptionElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableCaptionElement::~HTMLTableCaptionElement()
+{
+}
+
+DOMString HTMLTableCaptionElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableCaptionElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTableCellElement::HTMLTableCellElement() : HTMLElement()
+{
+}
+
+HTMLTableCellElement::HTMLTableCellElement(const HTMLTableCellElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableCellElement::HTMLTableCellElement(HTMLTableCellElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableCellElement &HTMLTableCellElement::operator = (const Node &other)
+{
+ if( other.elementId() != ID_TD &&
+ other.elementId() != ID_TH )
+ {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+ return *this;
+}
+
+HTMLTableCellElement &HTMLTableCellElement::operator = (const HTMLTableCellElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableCellElement::~HTMLTableCellElement()
+{
+}
+
+long HTMLTableCellElement::cellIndex() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableCellElementImpl *)impl)->cellIndex();
+}
+
+void HTMLTableCellElement::setCellIndex( long /*_cellIndex*/ )
+{
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+}
+
+DOMString HTMLTableCellElement::abbr() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ABBR);
+}
+
+void HTMLTableCellElement::setAbbr( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ABBR, value);
+}
+
+DOMString HTMLTableCellElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableCellElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLTableCellElement::axis() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_AXIS);
+}
+
+void HTMLTableCellElement::setAxis( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_AXIS, value);
+}
+
+DOMString HTMLTableCellElement::bgColor() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BGCOLOR);
+}
+
+void HTMLTableCellElement::setBgColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BGCOLOR, value);
+}
+
+DOMString HTMLTableCellElement::ch() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAR);
+}
+
+void HTMLTableCellElement::setCh( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAR, value);
+}
+
+DOMString HTMLTableCellElement::chOff() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAROFF);
+}
+
+void HTMLTableCellElement::setChOff( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAROFF, value);
+}
+
+long HTMLTableCellElement::colSpan() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_COLSPAN).toInt();
+}
+
+void HTMLTableCellElement::setColSpan( long _colSpan )
+{
+ if(impl) {
+ DOMString value(TQString::number(_colSpan));
+ ((ElementImpl *)impl)->setAttribute(ATTR_COLSPAN,value);
+ }
+}
+
+DOMString HTMLTableCellElement::headers() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HEADERS);
+}
+
+void HTMLTableCellElement::setHeaders( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEADERS, value);
+}
+
+DOMString HTMLTableCellElement::height() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_HEIGHT);
+}
+
+void HTMLTableCellElement::setHeight( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_HEIGHT, value);
+}
+
+bool HTMLTableCellElement::noWrap() const
+{
+ if(!impl) return false;
+ return !((ElementImpl *)impl)->getAttribute(ATTR_NOWRAP).isNull();
+}
+
+void HTMLTableCellElement::setNoWrap( bool _noWrap )
+{
+ if(impl)
+ ((ElementImpl *)impl)->setAttribute(ATTR_NOWRAP, _noWrap ? "" : 0);
+}
+
+long HTMLTableCellElement::rowSpan() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ROWSPAN).toInt();
+}
+
+void HTMLTableCellElement::setRowSpan( long _rowSpan )
+{
+ if(impl) {
+ DOMString value(TQString::number(_rowSpan));
+ ((ElementImpl *)impl)->setAttribute(ATTR_ROWSPAN,value);
+ }
+}
+
+DOMString HTMLTableCellElement::scope() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SCOPE);
+}
+
+void HTMLTableCellElement::setScope( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SCOPE, value);
+}
+
+DOMString HTMLTableCellElement::vAlign() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALIGN);
+}
+
+void HTMLTableCellElement::setVAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALIGN, value);
+}
+
+DOMString HTMLTableCellElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLTableCellElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTableColElement::HTMLTableColElement() : HTMLElement()
+{
+}
+
+HTMLTableColElement::HTMLTableColElement(const HTMLTableColElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableColElement::HTMLTableColElement(HTMLTableColElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableColElement &HTMLTableColElement::operator = (const Node &other)
+{
+ if( other.elementId() != ID_COL &&
+ other.elementId() != ID_COLGROUP )
+ {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+ return *this;
+}
+
+HTMLTableColElement &HTMLTableColElement::operator = (const HTMLTableColElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableColElement::~HTMLTableColElement()
+{
+}
+
+DOMString HTMLTableColElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableColElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLTableColElement::ch() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAR);
+}
+
+void HTMLTableColElement::setCh( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAR, value);
+}
+
+DOMString HTMLTableColElement::chOff() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAROFF);
+}
+
+void HTMLTableColElement::setChOff( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAROFF, value);
+}
+
+long HTMLTableColElement::span() const
+{
+ if(!impl) return 0;
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SPAN).toInt();
+}
+
+void HTMLTableColElement::setSpan( long _span )
+{
+ if(impl) {
+ DOMString value(TQString::number(_span));
+ ((ElementImpl *)impl)->setAttribute(ATTR_SPAN,value);
+ }
+}
+
+DOMString HTMLTableColElement::vAlign() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALIGN);
+}
+
+void HTMLTableColElement::setVAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALIGN, value);
+}
+
+DOMString HTMLTableColElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLTableColElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTableElement::HTMLTableElement() : HTMLElement()
+{
+}
+
+HTMLTableElement::HTMLTableElement(const HTMLTableElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableElement::HTMLTableElement(HTMLTableElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableElement &HTMLTableElement::operator = (const Node &other)
+{
+ assignOther( other, ID_TABLE );
+ return *this;
+}
+
+HTMLTableElement &HTMLTableElement::operator = (const HTMLTableElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableElement::~HTMLTableElement()
+{
+}
+
+HTMLTableCaptionElement HTMLTableElement::caption() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->caption();
+}
+
+void HTMLTableElement::setCaption( const HTMLTableCaptionElement &_caption )
+{
+ if(impl)
+ ((HTMLTableElementImpl *)impl)
+ ->setCaption( ((HTMLTableCaptionElementImpl *)_caption.impl) );
+}
+
+HTMLTableSectionElement HTMLTableElement::tHead() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->tHead();
+}
+
+void HTMLTableElement::setTHead( const HTMLTableSectionElement &_tHead )
+{
+
+ if(impl)
+ ((HTMLTableElementImpl *)impl)
+ ->setTHead( ((HTMLTableSectionElementImpl *)_tHead.impl) );
+}
+
+HTMLTableSectionElement HTMLTableElement::tFoot() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->tFoot();
+}
+
+void HTMLTableElement::setTFoot( const HTMLTableSectionElement &_tFoot )
+{
+
+ if(impl)
+ ((HTMLTableElementImpl *)impl)
+ ->setTFoot( ((HTMLTableSectionElementImpl *)_tFoot.impl) );
+}
+
+HTMLCollection HTMLTableElement::rows() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::TABLE_ROWS);
+}
+
+HTMLCollection HTMLTableElement::tBodies() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::TABLE_TBODIES);
+}
+
+DOMString HTMLTableElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLTableElement::bgColor() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BGCOLOR);
+}
+
+void HTMLTableElement::setBgColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BGCOLOR, value);
+}
+
+DOMString HTMLTableElement::border() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BORDER);
+}
+
+void HTMLTableElement::setBorder( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BORDER, value);
+}
+
+DOMString HTMLTableElement::cellPadding() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CELLPADDING);
+}
+
+void HTMLTableElement::setCellPadding( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CELLPADDING, value);
+}
+
+DOMString HTMLTableElement::cellSpacing() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CELLSPACING);
+}
+
+void HTMLTableElement::setCellSpacing( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CELLSPACING, value);
+}
+
+DOMString HTMLTableElement::frame() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_FRAME);
+}
+
+void HTMLTableElement::setFrame( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_FRAME, value);
+}
+
+DOMString HTMLTableElement::rules() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_RULES);
+}
+
+void HTMLTableElement::setRules( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_RULES, value);
+}
+
+DOMString HTMLTableElement::summary() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_SUMMARY);
+}
+
+void HTMLTableElement::setSummary( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_SUMMARY, value);
+}
+
+DOMString HTMLTableElement::width() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_WIDTH);
+}
+
+void HTMLTableElement::setWidth( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_WIDTH, value);
+}
+
+HTMLElement HTMLTableElement::createTHead( )
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->createTHead( );
+}
+
+void HTMLTableElement::deleteTHead( )
+{
+ if(impl)
+ ((HTMLTableElementImpl *)impl)->deleteTHead( );
+}
+
+HTMLElement HTMLTableElement::createTFoot( )
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->createTFoot( );
+}
+
+void HTMLTableElement::deleteTFoot( )
+{
+ if(impl)
+ ((HTMLTableElementImpl *)impl)->deleteTFoot( );
+}
+
+HTMLElement HTMLTableElement::createCaption( )
+{
+ if(!impl) return 0;
+ return ((HTMLTableElementImpl *)impl)->createCaption( );
+}
+
+void HTMLTableElement::deleteCaption( )
+{
+ if(impl)
+ ((HTMLTableElementImpl *)impl)->deleteCaption( );
+}
+
+HTMLElement HTMLTableElement::insertRow( long index )
+{
+ if(!impl) return 0;
+ int exceptioncode = 0;
+ HTMLElementImpl* ret = ((HTMLTableElementImpl *)impl)->insertRow( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return ret;
+}
+
+void HTMLTableElement::deleteRow( long index )
+{
+ int exceptioncode = 0;
+ if(impl)
+ ((HTMLTableElementImpl *)impl)->deleteRow( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTableRowElement::HTMLTableRowElement() : HTMLElement()
+{
+}
+
+HTMLTableRowElement::HTMLTableRowElement(const HTMLTableRowElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableRowElement::HTMLTableRowElement(HTMLTableRowElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableRowElement &HTMLTableRowElement::operator = (const Node &other)
+{
+ assignOther( other, ID_TR );
+ return *this;
+}
+
+HTMLTableRowElement &HTMLTableRowElement::operator = (const HTMLTableRowElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableRowElement::~HTMLTableRowElement()
+{
+}
+
+long HTMLTableRowElement::rowIndex() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableRowElementImpl *)impl)->rowIndex();
+}
+
+void HTMLTableRowElement::setRowIndex( long /*_rowIndex*/ )
+{
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+}
+
+long HTMLTableRowElement::sectionRowIndex() const
+{
+ if(!impl) return 0;
+ return ((HTMLTableRowElementImpl *)impl)->sectionRowIndex();
+}
+
+void HTMLTableRowElement::setSectionRowIndex( long /*_sectionRowIndex*/ )
+{
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+}
+
+HTMLCollection HTMLTableRowElement::cells() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::TR_CELLS);
+}
+
+void HTMLTableRowElement::setCells( const HTMLCollection & /*_cells*/ )
+{
+ throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR);
+}
+
+DOMString HTMLTableRowElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableRowElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLTableRowElement::bgColor() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_BGCOLOR);
+}
+
+void HTMLTableRowElement::setBgColor( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_BGCOLOR, value);
+}
+
+DOMString HTMLTableRowElement::ch() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAR);
+}
+
+void HTMLTableRowElement::setCh( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAR, value);
+}
+
+DOMString HTMLTableRowElement::chOff() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAROFF);
+}
+
+void HTMLTableRowElement::setChOff( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAROFF, value);
+}
+
+DOMString HTMLTableRowElement::vAlign() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALIGN);
+}
+
+void HTMLTableRowElement::setVAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALIGN, value);
+}
+
+HTMLElement HTMLTableRowElement::insertCell( long index )
+{
+ if(!impl) return 0;
+ int exceptioncode = 0;
+ HTMLElementImpl* ret = ((HTMLTableRowElementImpl *)impl)->insertCell( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return ret;
+}
+
+void HTMLTableRowElement::deleteCell( long index )
+{
+ int exceptioncode = 0;
+ if(impl)
+ ((HTMLTableRowElementImpl *)impl)->deleteCell( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
+// --------------------------------------------------------------------------
+
+HTMLTableSectionElement::HTMLTableSectionElement() : HTMLElement()
+{
+}
+
+HTMLTableSectionElement::HTMLTableSectionElement(const HTMLTableSectionElement &other) : HTMLElement(other)
+{
+}
+
+HTMLTableSectionElement::HTMLTableSectionElement(HTMLTableSectionElementImpl *impl) : HTMLElement(impl)
+{
+}
+
+HTMLTableSectionElement &HTMLTableSectionElement::operator = (const Node &other)
+{
+ if(other.elementId() != ID_TBODY &&
+ other.elementId() != ID_THEAD &&
+ other.elementId() != ID_TFOOT )
+ {
+ if ( impl ) impl->deref();
+ impl = 0;
+ } else {
+ Node::operator = (other);
+ }
+ return *this;
+}
+
+HTMLTableSectionElement &HTMLTableSectionElement::operator = (const HTMLTableSectionElement &other)
+{
+ HTMLElement::operator = (other);
+ return *this;
+}
+
+HTMLTableSectionElement::~HTMLTableSectionElement()
+{
+}
+
+DOMString HTMLTableSectionElement::align() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_ALIGN);
+}
+
+void HTMLTableSectionElement::setAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_ALIGN, value);
+}
+
+DOMString HTMLTableSectionElement::ch() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAR);
+}
+
+void HTMLTableSectionElement::setCh( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAR, value);
+}
+
+DOMString HTMLTableSectionElement::chOff() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_CHAROFF);
+}
+
+void HTMLTableSectionElement::setChOff( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_CHAROFF, value);
+}
+
+DOMString HTMLTableSectionElement::vAlign() const
+{
+ if(!impl) return DOMString();
+ return ((ElementImpl *)impl)->getAttribute(ATTR_VALIGN);
+}
+
+void HTMLTableSectionElement::setVAlign( const DOMString &value )
+{
+ if(impl) ((ElementImpl *)impl)->setAttribute(ATTR_VALIGN, value);
+}
+
+HTMLCollection HTMLTableSectionElement::rows() const
+{
+ if(!impl) return HTMLCollection();
+ return HTMLCollection(impl, HTMLCollectionImpl::TSECTION_ROWS);
+}
+
+HTMLElement HTMLTableSectionElement::insertRow( long index )
+{
+ if(!impl) return 0;
+ int exceptioncode = 0;
+ HTMLElementImpl* ret = ((HTMLTableSectionElementImpl *)impl)->insertRow( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+ return ret;
+}
+
+void HTMLTableSectionElement::deleteRow( long index )
+{
+ int exceptioncode = 0;
+ if(impl)
+ ((HTMLTableSectionElementImpl *)impl)->deleteRow( index, exceptioncode );
+ if (exceptioncode)
+ throw DOMException(exceptioncode);
+}
+
diff --git a/tdehtml/dom/html_table.h b/tdehtml/dom/html_table.h
new file mode 100644
index 000000000..6b9a2d99d
--- /dev/null
+++ b/tdehtml/dom/html_table.h
@@ -0,0 +1,997 @@
+/*
+ * 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.
+ *
+ * This file includes excerpts from the Document Object Model (DOM)
+ * Level 1 Specification (Recommendation)
+ * http://www.w3.org/TR/REC-DOM-Level-1/
+ * Copyright © World Wide Web Consortium , (Massachusetts Institute of
+ * Technology , Institut National de Recherche en Informatique et en
+ * Automatique , Keio University ). All Rights Reserved.
+ *
+ */
+#ifndef HTML_TABLE_H
+#define HTML_TABLE_H
+
+// --------------------------------------------------------------------------
+#include <dom/html_element.h>
+#include <tdelibs_export.h>
+
+namespace DOM {
+
+class HTMLTableCaptionElementImpl;
+class DOMString;
+
+/**
+ * Table caption See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#edef-CAPTION">
+ * CAPTION element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTableCaptionElement : public HTMLElement
+{
+ friend class HTMLTableElement;
+
+public:
+ HTMLTableCaptionElement();
+ HTMLTableCaptionElement(const HTMLTableCaptionElement &other);
+ HTMLTableCaptionElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLTableCaptionElement(HTMLTableCaptionElementImpl *impl);
+public:
+
+ HTMLTableCaptionElement & operator = (const HTMLTableCaptionElement &other);
+ HTMLTableCaptionElement & operator = (const Node &other);
+
+ ~HTMLTableCaptionElement();
+
+ /**
+ * Caption alignment with respect to the table. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-CAPTION">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTableCellElementImpl;
+
+/**
+ * The object used to represent the \c TH and \c TD
+ * elements. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#edef-TD">
+ * TD element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTableCellElement : public HTMLElement
+{
+ friend class HTMLTableElement;
+
+public:
+ HTMLTableCellElement();
+ HTMLTableCellElement(const HTMLTableCellElement &other);
+ HTMLTableCellElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLTableCellElement(HTMLTableCellElementImpl *impl);
+public:
+
+ HTMLTableCellElement & operator = (const HTMLTableCellElement &other);
+ HTMLTableCellElement & operator = (const Node &other);
+
+ ~HTMLTableCellElement();
+
+ /**
+ * The index of this cell in the row.
+ *
+ */
+ long cellIndex() const;
+
+ /**
+ * see cellIndex
+ *
+ * This function is obsolete - the cellIndex property is actually supposed to be read-only
+ * (http://www.w3.org/DOM/updates/REC-DOM-Level-1-19981001-errata.html)
+ */
+ void setCellIndex( long );
+
+ /**
+ * Abbreviation for header cells. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-abbr">
+ * abbr attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString abbr() const;
+
+ /**
+ * see abbr
+ */
+ void setAbbr( const DOMString & );
+
+ /**
+ * Horizontal alignment of data in cell. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-TD">
+ * align attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Names group of related headers. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-axis">
+ * axis attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString axis() const;
+
+ /**
+ * see axis
+ */
+ void setAxis( const DOMString & );
+
+ /**
+ * Cell background color. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-bgcolor">
+ * bgcolor attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString bgColor() const;
+
+ /**
+ * see bgColor
+ */
+ void setBgColor( const DOMString & );
+
+ /**
+ * Alignment character for cells in a column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-char">
+ * char attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString ch() const;
+
+ /**
+ * see ch
+ */
+ void setCh( const DOMString & );
+
+ /**
+ * Offset of alignment character. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-charoff">
+ * charoff attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString chOff() const;
+
+ /**
+ * see chOff
+ */
+ void setChOff( const DOMString & );
+
+ /**
+ * Number of columns spanned by cell. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-colspan">
+ * colspan attribute definition </a> in HTML 4.0.
+ *
+ */
+ long colSpan() const;
+
+ /**
+ * see colSpan
+ */
+ void setColSpan( long );
+
+ /**
+ * List of \c id attribute values for header cells.
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-headers">
+ * headers attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString headers() const;
+
+ /**
+ * see headers
+ */
+ void setHeaders( const DOMString & );
+
+ /**
+ * Cell height. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-height-TH">
+ * height attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString height() const;
+
+ /**
+ * see height
+ */
+ void setHeight( const DOMString & );
+
+ /**
+ * Suppress word wrapping. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-nowrap">
+ * nowrap attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ bool noWrap() const;
+
+ /**
+ * see noWrap
+ */
+ void setNoWrap( bool );
+
+ /**
+ * Number of rows spanned by cell. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-rowspan">
+ * rowspan attribute definition </a> in HTML 4.0.
+ *
+ */
+ long rowSpan() const;
+
+ /**
+ * see rowSpan
+ */
+ void setRowSpan( long );
+
+ /**
+ * Scope covered by header cells. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-scope">
+ * scope attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString scope() const;
+
+ /**
+ * see scope
+ */
+ void setScope( const DOMString & );
+
+ /**
+ * Vertical alignment of data in cell. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-valign">
+ * valign attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString vAlign() const;
+
+ /**
+ * see vAlign
+ */
+ void setVAlign( const DOMString & );
+
+ /**
+ * Cell width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-width-TH">
+ * width attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTableColElementImpl;
+
+/**
+ * Regroups the \c COL and \c COLGROUP
+ * elements. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#edef-COL">
+ * COL element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTableColElement : public HTMLElement
+{
+ friend class HTMLTableElement;
+
+public:
+ HTMLTableColElement();
+ HTMLTableColElement(const HTMLTableColElement &other);
+ HTMLTableColElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+protected:
+ HTMLTableColElement(HTMLTableColElementImpl *impl);
+public:
+
+ HTMLTableColElement & operator = (const HTMLTableColElement &other);
+ HTMLTableColElement & operator = (const Node &other);
+
+ ~HTMLTableColElement();
+
+ /**
+ * Horizontal alignment of cell data in column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-TD">
+ * align attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Alignment character for cells in a column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-char">
+ * char attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString ch() const;
+
+ /**
+ * see ch
+ */
+ void setCh( const DOMString & );
+
+ /**
+ * Offset of alignment character. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-charoff">
+ * charoff attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString chOff() const;
+
+ /**
+ * see chOff
+ */
+ void setChOff( const DOMString & );
+
+ /**
+ * Indicates the number of columns in a group or affected by a
+ * grouping. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-span-COL">
+ * span attribute definition </a> in HTML 4.0.
+ *
+ */
+ long span() const;
+
+ /**
+ * see span
+ */
+ void setSpan( long );
+
+ /**
+ * Vertical alignment of cell data in column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-valign">
+ * valign attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString vAlign() const;
+
+ /**
+ * see vAlign
+ */
+ void setVAlign( const DOMString & );
+
+ /**
+ * Default column width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-width-COL">
+ * width attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTableElementImpl;
+class HTMLCollection;
+class HTMLTableSectionElement;
+class HTMLTableCaptionElement;
+class HTMLElement;
+class DOMString;
+
+/**
+ * The create* and delete* methods on the table allow authors to
+ * construct and modify tables. HTML 4.0 specifies that only one of
+ * each of the \c CAPTION , \c THEAD , and
+ * \c TFOOT elements may exist in a table. Therefore, if
+ * one exists, and the createTHead() or createTFoot() method is
+ * called, the method returns the existing THead or TFoot element. See
+ * the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#edef-TABLE">
+ * TABLE element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTableElement : public HTMLElement
+{
+public:
+ HTMLTableElement();
+ HTMLTableElement(const HTMLTableElement &other);
+ HTMLTableElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+
+protected:
+ HTMLTableElement(HTMLTableElementImpl *impl);
+public:
+
+ HTMLTableElement & operator = (const HTMLTableElement &other);
+ HTMLTableElement & operator = (const Node &other);
+
+ ~HTMLTableElement();
+
+ /**
+ * Returns the table's \c CAPTION , or void if none
+ * exists.
+ *
+ */
+ HTMLTableCaptionElement caption() const;
+
+ /**
+ * see caption
+ */
+ void setCaption( const HTMLTableCaptionElement & );
+
+ /**
+ * Returns the table's \c THEAD , or \c null
+ * if none exists.
+ *
+ */
+ HTMLTableSectionElement tHead() const;
+
+ /**
+ * see tHead
+ */
+ void setTHead( const HTMLTableSectionElement & );
+
+ /**
+ * Returns the table's \c TFOOT , or \c null
+ * if none exists.
+ *
+ */
+ HTMLTableSectionElement tFoot() const;
+
+ /**
+ * see tFoot
+ */
+ void setTFoot( const HTMLTableSectionElement & );
+
+ /**
+ * Returns a collection of all the rows in the table, including
+ * all in \c THEAD , \c TFOOT , all
+ * \c TBODY elements.
+ *
+ */
+ HTMLCollection rows() const;
+
+ /**
+ * Returns a collection of the table bodies (including implicit ones).
+ *
+ */
+ HTMLCollection tBodies() const;
+
+ /**
+ * Specifies the table's position with respect to the rest of the
+ * document. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-TABLE">
+ * align attribute definition </a> in HTML 4.0. This attribute is
+ * deprecated in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Cell background color. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-bgcolor">
+ * bgcolor attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString bgColor() const;
+
+ /**
+ * see bgColor
+ */
+ void setBgColor( const DOMString & );
+
+ /**
+ * The width of the border around the table. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-border-TABLE">
+ * border attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString border() const;
+
+ /**
+ * see border
+ */
+ void setBorder( const DOMString & );
+
+ /**
+ * Specifies the horizontal and vertical space between cell
+ * content and cell borders. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-cellpadding">
+ * cellpadding attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cellPadding() const;
+
+ /**
+ * see cellPadding
+ */
+ void setCellPadding( const DOMString & );
+
+ /**
+ * Specifies the horizontal and vertical separation between cells.
+ * See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-cellspacing">
+ * cellspacing attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString cellSpacing() const;
+
+ /**
+ * see cellSpacing
+ */
+ void setCellSpacing( const DOMString & );
+
+ /**
+ * Specifies which external table borders to render. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-frame">
+ * frame attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString frame() const;
+
+ /**
+ * see frame
+ */
+ void setFrame( const DOMString & );
+
+ /**
+ * Specifies which internal table borders to render. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-rules">
+ * rules attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString rules() const;
+
+ /**
+ * see rules
+ */
+ void setRules( const DOMString & );
+
+ /**
+ * Supplementary description about the purpose or structure of a
+ * table. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-summary">
+ * summary attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString summary() const;
+
+ /**
+ * see summary
+ */
+ void setSummary( const DOMString & );
+
+ /**
+ * Specifies the desired table width. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-width-TABLE">
+ * width attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString width() const;
+
+ /**
+ * see width
+ */
+ void setWidth( const DOMString & );
+
+ /**
+ * Create a table header row or return an existing one.
+ *
+ * @return A new table header element ( \c THEAD ).
+ *
+ */
+ HTMLElement createTHead ( );
+
+ /**
+ * Delete the header from the table, if one exists.
+ *
+ * @return
+ *
+ */
+ void deleteTHead ( );
+
+ /**
+ * Create a table footer row or return an existing one.
+ *
+ * @return A footer element ( \c TFOOT ).
+ *
+ */
+ HTMLElement createTFoot ( );
+
+ /**
+ * Delete the footer from the table, if one exists.
+ *
+ * @return
+ *
+ */
+ void deleteTFoot ( );
+
+ /**
+ * Create a new table caption object or return an existing one.
+ *
+ * @return A \c CAPTION element.
+ *
+ */
+ HTMLElement createCaption ( );
+
+ /**
+ * Delete the table caption, if one exists.
+ *
+ * @return
+ *
+ */
+ void deleteCaption ( );
+
+ /**
+ * Insert a new empty row in the table.
+ * The new row is inserted immediately before and in the same section
+ * as the current indexth row in the table. If index is -1 or equal
+ * to the number of rows, the new row is appended. In addition, when
+ * the table is empty the row is inserted into a TBODY which is created
+ * and inserted into the table.
+ * Note. A table row cannot
+ * be empty according to HTML 4.0 Recommendation.
+ *
+ * @param index The row number where to insert a new row.
+ * The index starts from 0 and is relative to the logical order
+ * (not document order) of all the rows contained inside the table.
+ *
+ * @return The newly created row.
+ *
+ */
+ HTMLElement insertRow ( long index );
+
+ /**
+ * Delete a table row.
+ *
+ * @param index The index of the row to be deleted.
+ * This index starts from 0 and is relative to the logical order
+ * (not document order) of all the rows contained inside the table.
+ * If the index is -1 the last row in the table is deleted.
+ *
+ * @return
+ *
+ */
+ void deleteRow ( long index );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTableRowElementImpl;
+class HTMLCollection;
+class HTMLElement;
+class DOMString;
+
+/**
+ * A row in a table. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#edef-TR">
+ * TR element definition </a> in HTML 4.0.
+ *
+ */
+class KHTML_EXPORT HTMLTableRowElement : public HTMLElement
+{
+ friend class HTMLTableElement;
+
+public:
+ HTMLTableRowElement();
+ HTMLTableRowElement(const HTMLTableRowElement &other);
+ HTMLTableRowElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+
+protected:
+ HTMLTableRowElement(HTMLTableRowElementImpl *impl);
+public:
+
+ HTMLTableRowElement & operator = (const HTMLTableRowElement &other);
+ HTMLTableRowElement & operator = (const Node &other);
+
+ ~HTMLTableRowElement();
+
+ /**
+ * The index of this row, relative to the entire table.
+ * This is in logical order and not in document order.
+ * The rowIndex does take into account sections
+ * (THEAD, TFOOT or TBODY) within the table,
+ * placing THEAD rows first in the index, followed by
+ * TBODY rows, followed by TFOOT rows.
+ */
+ long rowIndex() const;
+
+ /**
+ * see rowIndex
+ *
+ * This function is obsolete - the rowIndex property is actually supposed to be read-only
+ * (http://www.w3.org/DOM/updates/REC-DOM-Level-1-19981001-errata.html)
+ */
+ void setRowIndex( long );
+
+ /**
+ * The index of this row, relative to the current section (
+ * \c THEAD , \c TFOOT , or \c TBODY
+ * ).
+ *
+ */
+ long sectionRowIndex() const;
+
+ /**
+ * see sectionRowIndex
+ *
+ * This function is obsolete - the sectionRowIndex property is actually supposed to be read-only
+ * (http://www.w3.org/DOM/updates/REC-DOM-Level-1-19981001-errata.html)
+ */
+ void setSectionRowIndex( long );
+
+ /**
+ * The collection of cells in this row.
+ *
+ */
+ HTMLCollection cells() const;
+
+ /**
+ * see cells
+ *
+ * This function is obsolete - the cells property is actually supposed to be read-only
+ * (http://www.w3.org/DOM/updates/REC-DOM-Level-1-19981001-errata.html)
+ */
+ void setCells( const HTMLCollection & );
+
+ /**
+ * Horizontal alignment of data within cells of this row. See the
+ * <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-align-TD">
+ * align attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Background color for rows. See the <a
+ * href="http://www.w3.org/TR/REC-html40/present/graphics.html#adef-bgcolor">
+ * bgcolor attribute definition </a> in HTML 4.0. This attribute
+ * is deprecated in HTML 4.0.
+ *
+ */
+ DOMString bgColor() const;
+
+ /**
+ * see bgColor
+ */
+ void setBgColor( const DOMString & );
+
+ /**
+ * Alignment character for cells in a column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-char">
+ * char attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString ch() const;
+
+ /**
+ * see ch
+ */
+ void setCh( const DOMString & );
+
+ /**
+ * Offset of alignment character. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-charoff">
+ * charoff attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString chOff() const;
+
+ /**
+ * see chOff
+ */
+ void setChOff( const DOMString & );
+
+ /**
+ * Vertical alignment of data within cells of this row. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-valign">
+ * valign attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString vAlign() const;
+
+ /**
+ * see vAlign
+ */
+ void setVAlign( const DOMString & );
+
+ /**
+ * Insert an empty \c TD cell into this row.
+ * If index is -1 or equal to the number of cells, the new
+ * cell is appended.
+ *
+ * @param index The place to insert the cell.
+ *
+ * @return The newly created cell.
+ *
+ */
+ HTMLElement insertCell ( long index );
+
+ /**
+ * Delete a cell from the current row.
+ *
+ * @param index The index of the cell to delete, starting from 0.
+ * If the index is -1 the last cell in the row is deleted.
+ *
+ * @return
+ *
+ */
+ void deleteCell ( long index );
+};
+
+// --------------------------------------------------------------------------
+
+class HTMLTableSectionElementImpl;
+class HTMLCollection;
+class HTMLElement;
+class DOMString;
+
+/**
+ * The \c THEAD , \c TFOOT , and \c TBODY
+ * elements.
+ *
+ */
+class KHTML_EXPORT HTMLTableSectionElement : public HTMLElement
+{
+ friend class HTMLTableElement;
+
+public:
+ HTMLTableSectionElement();
+ HTMLTableSectionElement(const HTMLTableSectionElement &other);
+ HTMLTableSectionElement(const Node &other) : HTMLElement()
+ {(*this)=other;}
+
+
+protected:
+ HTMLTableSectionElement(HTMLTableSectionElementImpl *impl);
+public:
+
+ HTMLTableSectionElement & operator = (const HTMLTableSectionElement &other);
+ HTMLTableSectionElement & operator = (const Node &other);
+
+ ~HTMLTableSectionElement();
+
+ /**
+ * Horizontal alignment of data in cells. See the \c align
+ * attribute for HTMLTheadElement for details.
+ *
+ */
+ DOMString align() const;
+
+ /**
+ * see align
+ */
+ void setAlign( const DOMString & );
+
+ /**
+ * Alignment character for cells in a column. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-char">
+ * char attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString ch() const;
+
+ /**
+ * see ch
+ */
+ void setCh( const DOMString & );
+
+ /**
+ * Offset of alignment character. See the <a
+ * href="http://www.w3.org/TR/REC-html40/struct/tables.html#adef-charoff">
+ * charoff attribute definition </a> in HTML 4.0.
+ *
+ */
+ DOMString chOff() const;
+
+ /**
+ * see chOff
+ */
+ void setChOff( const DOMString & );
+
+ /**
+ * Vertical alignment of data in cells. See the \c valign
+ * attribute for HTMLTheadElement for details.
+ *
+ */
+ DOMString vAlign() const;
+
+ /**
+ * see vAlign
+ */
+ void setVAlign( const DOMString & );
+
+ /**
+ * The collection of rows in this table section.
+ *
+ */
+ HTMLCollection rows() const;
+
+ /**
+ * Insert a row into this section.
+ * The new row is inserted immediately before the current indexth
+ * row in this section. If index is -1 or equal to the number of rows
+ * in this sectino, the new row is appended.
+ *
+ * @param index The row number where to insert a new row.
+ *
+ * @return The newly created row.
+ *
+ */
+ HTMLElement insertRow ( long index );
+
+ /**
+ * Delete a row from this section.
+ *
+ * @param index The index of the row to be deleted,
+ * or -1 to delete the last row. This index starts from 0 and is relative only
+ * to the rows contained inside this section, not all the rows in the table.
+ *
+ */
+ void deleteRow ( long index );
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/domtreeview.cpp b/tdehtml/domtreeview.cpp
new file mode 100644
index 000000000..7482c7b81
--- /dev/null
+++ b/tdehtml/domtreeview.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ domtreeview.cpp
+ -------------------
+
+ copyright : (C) 2001 - The Kafka Team
+ email : kde-kafka@master.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "tdehtml_part.h"
+#include "domtreeview.moc"
+#include "xml/dom_nodeimpl.h"
+
+DOMTreeView::DOMTreeView(TQWidget *parent, KHTMLPart *currentpart, const char * name) : KListView(parent, name)
+{
+ setCaption(name);
+ setRootIsDecorated(true);
+ addColumn("Name");
+ addColumn("Value");
+ addColumn("Renderer");
+ setSorting(-1);
+ part = currentpart;
+ connect(part, TQT_SIGNAL(nodeActivated(const DOM::Node &)), this, TQT_SLOT(showTree(const DOM::Node &)));
+ connect(this, TQT_SIGNAL(clicked(TQListViewItem *)), this, TQT_SLOT(slotItemClicked(TQListViewItem *)));
+ m_nodedict.setAutoDelete(true);
+}
+
+DOMTreeView::~DOMTreeView()
+{
+ disconnect(part);
+}
+
+void DOMTreeView::showTree(const DOM::Node &pNode)
+{
+ if(pNode.isNull() || document != pNode.ownerDocument())
+ {
+ clear();
+ m_itemdict.clear();
+ m_nodedict.clear();
+ if(pNode.isNull())
+ return;
+ else if(pNode.ownerDocument().isNull())
+ recursive(0, pNode);
+ else
+ recursive(0, pNode.ownerDocument());
+ }
+ setCurrentItem(m_itemdict[pNode.handle()]);
+ ensureItemVisible(m_itemdict[pNode.handle()]);
+}
+
+void DOMTreeView::recursive(const DOM::Node &pNode, const DOM::Node &node)
+{
+ TQListViewItem *cur_item;
+ if(pNode.ownerDocument() != document)
+ {
+ TQString val = node.nodeValue().string();
+ if ( val.length() > 20 )
+ val.truncate( 20 );
+ cur_item = new TQListViewItem(static_cast<TQListView *>(this), node.nodeName().string(), val );
+ document = pNode.ownerDocument();
+ }
+ else {
+ TQString val = node.nodeValue().string();
+ if ( val.length() > 20 )
+ val.truncate( 20 );
+ cur_item = new TQListViewItem(m_itemdict[pNode.handle()], node.nodeName().string(), val);
+ }
+
+ if(node.handle())
+ {
+ m_itemdict.insert(node.handle(), cur_item);
+ m_nodedict.insert(cur_item, new DOM::Node(node));
+ }
+
+ DOM::Node cur_child = node.lastChild();
+ while(!cur_child.isNull())
+ {
+ recursive(node, cur_child);
+ cur_child = cur_child.previousSibling();
+ }
+}
+
+void DOMTreeView::slotItemClicked(TQListViewItem *cur_item)
+{
+ DOM::Node *handle = m_nodedict[cur_item];
+ if(handle) {
+ emit part->setActiveNode(*handle);
+ }
+}
diff --git a/tdehtml/domtreeview.h b/tdehtml/domtreeview.h
new file mode 100644
index 000000000..ef3d45c44
--- /dev/null
+++ b/tdehtml/domtreeview.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ domtreeview.cpp
+ -------------------
+
+ copyright : (C) 2001 - The Kafka Team
+ email : kde-kafka@master.kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOMTREEVIEW_H
+#define DOMTREEVIEW_H
+
+#include <klistview.h>
+#include <kdebug.h>
+#include <tqlistview.h>
+#include <tqptrdict.h>
+#include "dom/dom_core.h"
+
+class DOMTreeView : public KListView
+{
+ Q_OBJECT
+ public:
+ DOMTreeView(TQWidget *parent, KHTMLPart *part, const char * name = 0);
+ ~DOMTreeView();
+
+ void recursive(const DOM::Node &pNode, const DOM::Node &node);
+
+ signals:
+ void sigNodeClicked(const DOM::Node &);
+
+ public slots:
+ void showTree(const DOM::Node &pNode);
+
+ protected slots:
+ void slotItemClicked(TQListViewItem *);
+
+ private:
+ TQPtrDict<TQListViewItem> m_itemdict;
+ TQPtrDict<DOM::Node> m_nodedict;
+ DOM::Node document;
+
+ KHTMLPart *part;
+
+};
+
+#endif
diff --git a/tdehtml/ecma/AUTHORS b/tdehtml/ecma/AUTHORS
new file mode 100644
index 000000000..2a129330d
--- /dev/null
+++ b/tdehtml/ecma/AUTHORS
@@ -0,0 +1,4 @@
+Harri Porten <porten@kde.org>
+Peter Kelly <pmk@post.com>
+Dirk Mueller <mueller@kde.org>
+Daniel Molkentin <molkentin@kde.org>
diff --git a/tdehtml/ecma/CMakeLists.txt b/tdehtml/ecma/CMakeLists.txt
new file mode 100644
index 000000000..eddd99f1e
--- /dev/null
+++ b/tdehtml/ecma/CMakeLists.txt
@@ -0,0 +1,61 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/kjs
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdefx
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/kio/bookmarks
+ ${CMAKE_SOURCE_DIR}/kjs
+ ${CMAKE_SOURCE_DIR}/tdewallet/client
+ ${CMAKE_SOURCE_DIR}/tdeutils
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### kjs_html-static ###########################
+
+set( target kjs_html )
+
+set( ${target}_SRCS
+ kjs_binding.cpp kjs_dom.cpp kjs_html.cpp kjs_window.cpp
+ kjs_navigator.cpp kjs_proxy.cpp kjs_css.cpp
+ kjs_range.cpp kjs_traversal.cpp kjs_events.cpp
+ kjs_views.cpp kjs_debugwin.cpp kjs_mozilla.cpp
+ xmlhttprequest.cpp xmlserializer.cpp domparser.cpp
+)
+
+set( ${target}_LUTS
+ kjs_dom.cpp kjs_html.cpp kjs_css.cpp kjs_events.cpp
+ kjs_navigator.cpp kjs_mozilla.cpp kjs_range.cpp
+ kjs_traversal.cpp kjs_views.cpp kjs_window.cpp
+ xmlhttprequest.cpp xmlserializer.cpp domparser.cpp
+)
+
+tde_add_luts( ${${target}_LUTS} )
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
+
diff --git a/tdehtml/ecma/Makefile.am b/tdehtml/ecma/Makefile.am
new file mode 100644
index 000000000..d69ff807b
--- /dev/null
+++ b/tdehtml/ecma/Makefile.am
@@ -0,0 +1,90 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1999 Harri Porten (porten@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.
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/kio -I$(top_srcdir)/kio/bookmarks -I$(top_srcdir)/tdehtml -I$(top_srcdir)/tdehtml/java -I$(top_srcdir)/tdewallet/client -I$(top_srcdir)/tdeutils -I$(top_builddir)/kjs $(all_includes)
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+noinst_LTLIBRARIES = libkjs_html.la
+
+noinst_HEADERS = kjs_html.h kjs_dom.h kjs_window.h kjs_navigator.h \
+ kjs_binding.h kjs_proxy.h kjs_css.h kjs_range.h \
+ kjs_traversal.h kjs_events.h kjs_views.h kjs_debugwin.h
+
+libkjs_html_la_SOURCES = kjs_binding.cpp kjs_dom.cpp kjs_html.cpp kjs_window.cpp \
+ kjs_navigator.cpp kjs_proxy.cpp \
+ kjs_css.cpp kjs_range.cpp kjs_traversal.cpp kjs_events.cpp \
+ kjs_views.cpp kjs_debugwin.cpp kjs_mozilla.cpp xmlhttprequest.cpp \
+ xmlserializer.cpp domparser.cpp
+#libkjs_html_la_LDFLAGS = -module -avoid-version $(all_libraries)
+libkjs_html_la_LIBADD = $(top_builddir)/kjs/libkjs.la # ../libtdehtml.la
+libkjs_html_la_METASOURCES = AUTO
+
+LUT_FILES = kjs_dom.lut.h kjs_html.lut.h kjs_css.lut.h kjs_events.lut.h kjs_navigator.lut.h \
+ kjs_mozilla.lut.h kjs_range.lut.h kjs_traversal.lut.h kjs_views.lut.h kjs_window.lut.h
+
+CREATE_HASH_TABLE = $(top_srcdir)/kjs/create_hash_table
+
+kjs_dom.lut.h : $(srcdir)/kjs_dom.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_dom.cpp > $@
+kjs_dom.lo: kjs_dom.lut.h
+kjs_html.lut.h : $(srcdir)/kjs_html.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_html.cpp > $@
+kjs_html.lo: kjs_html.lut.h
+kjs_css.lut.h : $(srcdir)/kjs_css.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_css.cpp > $@
+kjs_css.lo: kjs_css.lut.h
+kjs_events.lut.h : $(srcdir)/kjs_events.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_events.cpp > $@
+kjs_events.lo: kjs_events.lut.h
+kjs_navigator.lut.h : $(srcdir)/kjs_navigator.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_navigator.cpp > $@
+kjs_navigator.lo: kjs_navigator.lut.h
+kjs_mozilla.lut.h : $(srcdir)/kjs_mozilla.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_mozilla.cpp > $@
+kjs_mozilla.lo: kjs_mozilla.lut.h
+kjs_range.lut.h : $(srcdir)/kjs_range.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_range.cpp > $@
+kjs_range.lo: kjs_range.lut.h
+kjs_traversal.lut.h : $(srcdir)/kjs_traversal.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_traversal.cpp > $@
+kjs_traversal.lo: kjs_traversal.lut.h
+kjs_views.lut.h : $(srcdir)/kjs_views.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_views.cpp > $@
+kjs_views.lo: kjs_views.lut.h
+kjs_window.lut.h : $(srcdir)/kjs_window.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/kjs_window.cpp > $@
+kjs_window.lo: kjs_window.lut.h
+xmlhttprequest.lut.h : $(srcdir)/xmlhttprequest.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/xmlhttprequest.cpp > $@
+xmlhttprequest.lo: xmlhttprequest.lut.h
+xmlserializer.lut.h : $(srcdir)/xmlserializer.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/xmlserializer.cpp > $@
+xmlserializer.lo: xmlserializer.lut.h
+domparser.lut.h : $(srcdir)/domparser.cpp $(CREATE_HASH_TABLE)
+ $(PERL) $(CREATE_HASH_TABLE) $(srcdir)/domparser.cpp > $@
+domparser.lo: domparser.lut.h
+
+
+CLEANFILES = $(LUT_FILES)
+
+# interactive test program
+#check_PROGRAMS = testecma
+#testecma_SOURCES = testecma.cpp
+#testecma_LDADD = ../libtdehtml.la $(top_builddir)/kjs/libkjs.la
+
diff --git a/tdehtml/ecma/README b/tdehtml/ecma/README
new file mode 100644
index 000000000..4c341699a
--- /dev/null
+++ b/tdehtml/ecma/README
@@ -0,0 +1,21 @@
+This module contains the ECMAScript a.k.a. JavaScript language bindings for
+the KHTML Part.
+
+The module is loaded into KHTML's address space on demand.
+
+To test the non-HTML DOM functions you may compile a little interactive
+interpreter called 'testecma' with 'make check' (see testecma.cpp for
+further details).
+
+Harri Porten <porten@kde.org>
+
+========================================================================
+Appendix A: Web sites with useful tests
+
+http://oucsace.cs.ohiou.edu/~ywang/JavaScript
+http://www.xs4all.nl/~ppk/js/index.html?version5.html
+
+Appendix B: References for HTML JavaScript bindings
+
+http://msdn.microsoft.com/workshop/author/dhtml/reference/objects.asp
+http://docs.sun.com/source/816-6408-10/
diff --git a/tdehtml/ecma/THANKS b/tdehtml/ecma/THANKS
new file mode 100644
index 000000000..b21dce741
--- /dev/null
+++ b/tdehtml/ecma/THANKS
@@ -0,0 +1,9 @@
+Vadim Plessky <lucy-ples@mtu-net.ru> for dissecting an endless number
+of bug reports and therefore taking quite some load of our shoulders.
+
+Ferdinand Gassauer <f.gassauer@aon.at> for numerous useful bug reports
+and keeping track of them later.
+
+David Faure <faure@kde.org> for taking some time off from Konqueror
+and making a lotto site working fixing bugs along the way.
+
diff --git a/tdehtml/ecma/TODO b/tdehtml/ecma/TODO
new file mode 100644
index 000000000..16a7152c5
--- /dev/null
+++ b/tdehtml/ecma/TODO
@@ -0,0 +1,12 @@
+Has to be done
+==============
+- frame[] correct search and sorting order (DONE ?)
+- optional error message output
+- change KParts::WindowArgs && friends
+ that we can detect if a locationbar is on/or not
+
+Could be done
+=============
+- Make the graphical debugger useable
+- Improve internal structures to give a really useful
+ output on errors (i.e. improve backtrance capabilities)
diff --git a/tdehtml/ecma/domparser.cpp b/tdehtml/ecma/domparser.cpp
new file mode 100644
index 000000000..672754a45
--- /dev/null
+++ b/tdehtml/ecma/domparser.cpp
@@ -0,0 +1,112 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2005 Anders Carlsson (andersca@mac.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "domparser.h"
+#include "domparser.lut.h"
+
+#include "kjs_dom.h"
+#include "kjs_window.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+
+#include "html/html_documentimpl.h"
+
+using DOM::DocumentImpl;
+
+////////////////////// DOMParser Object ////////////////////////
+
+/* Source for DOMParserProtoTable.
+@begin DOMParserProtoTable 1
+ parseFromString DOMParser::ParseFromString DontDelete|Function 2
+@end
+*/
+
+
+namespace KJS {
+
+KJS_DEFINE_PROTOTYPE(DOMParserProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMParserProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMParser", DOMParserProto, DOMParserProtoFunc)
+
+
+DOMParserConstructorImp::DOMParserConstructorImp(ExecState *, DOM::DocumentImpl *d)
+ : doc(d)
+{
+}
+
+bool DOMParserConstructorImp::implementsConstruct() const
+{
+ return true;
+}
+
+Object DOMParserConstructorImp::construct(ExecState *exec, const List &)
+{
+ return Object(new DOMParser(exec, doc.get()));
+}
+
+const ClassInfo DOMParser::info = { "DOMParser", 0, 0 /* &DOMParserTable*/, 0 };
+
+
+DOMParser::DOMParser(ExecState *exec, DOM::DocumentImpl *d)
+ : DOMObject(DOMParserProto::self(exec)), doc(d)
+{
+// setPrototype(DOMParserProto::self(exec));
+}
+
+
+Value DOMParserProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ if (!thisObj.inherits(&DOMParser::info)) {
+ Object err = Error::create(exec,TypeError);
+ exec->setException(err);
+ return err;
+ }
+
+ DOMParser *parser = static_cast<DOMParser *>(thisObj.imp());
+
+ switch (id) {
+ case DOMParser::ParseFromString:
+ {
+ if (args.size() != 2) {
+ return Undefined();
+ }
+
+ TQString str = args[0].toString(exec).qstring();
+ TQString contentType = args[1].toString(exec).qstring().stripWhiteSpace();
+
+ if (contentType == "text/xml" || contentType == "application/xml" || contentType == "application/xhtml+xml") {
+ DocumentImpl *docImpl = parser->doc->implementation()->createDocument();
+
+ docImpl->open();
+ docImpl->write(str);
+ docImpl->finishParsing();
+ docImpl->close();
+
+ return getDOMNode(exec, docImpl);
+ }
+ }
+ }
+
+ return Undefined();
+}
+
+} // end namespace
+
+
diff --git a/tdehtml/ecma/domparser.h b/tdehtml/ecma/domparser.h
new file mode 100644
index 000000000..13a880837
--- /dev/null
+++ b/tdehtml/ecma/domparser.h
@@ -0,0 +1,58 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2005 Anders Carlsson (andersca@mac.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DOMPARSER_H
+#define DOMPARSER_H
+
+#include <tqguardedptr.h>
+#include <kjs/object.h>
+#include <kjs/interpreter.h>
+#include <misc/shared.h>
+
+#include "kjs_dom.h"
+
+namespace KJS {
+
+ class DOMParserConstructorImp : public ObjectImp {
+ public:
+ DOMParserConstructorImp(ExecState *, DOM::DocumentImpl *d);
+ virtual bool implementsConstruct() const;
+ virtual Object construct(ExecState *exec, const List &args);
+private:
+ tdehtml::SharedPtr<DOM::DocumentImpl> doc;
+ };
+
+ class DOMParser : public DOMObject {
+ public:
+ DOMParser(ExecState *, DOM::DocumentImpl *d);
+ virtual bool toBoolean(ExecState *) const { return true; }
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { ParseFromString };
+
+ private:
+ TQGuardedPtr<DOM::DocumentImpl> doc;
+
+ friend class DOMParserProtoFunc;
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/jsk.html b/tdehtml/ecma/jsk.html
new file mode 100644
index 000000000..917c083e8
--- /dev/null
+++ b/tdehtml/ecma/jsk.html
@@ -0,0 +1,113 @@
+<html>
+<!--
+Javascript Konsole (c) 2001 Till Krech <till@snafu.de>
+Dieser Code unterliegt den Bedingungen der Gnu Public License Version 2.
+-->
+<head>
+<title>Javascript Konsole</title>
+<style type="text/css">
+code {
+ color:#444488;
+}
+em {
+ font-weight: bold;
+}
+</style>
+<script language="JavaScript">
+
+function do_eval() {
+ var fo = document.forms.fo;
+ fo.restyp.value = "";
+ fo.field.value = "";
+ var fo = document.fo;
+ var expr = fo.zeile.value;
+ var result = eval(expr);
+ fo.restyp.value = typeof(result);
+ var tuedel = "";
+ if (typeof(result) == "string") {
+ tuedel = '"';
+ }
+ fo.field.value = tuedel + result + tuedel;
+}
+
+function do_properties() {
+ var fo = document.forms.fo;
+ fo.restyp.value = "";
+ fo.field.value = "";
+ var fo = document.fo;
+ var expr = fo.zeile.value;
+ var result = eval(expr);
+ var i;
+ fo.restyp.value = typeof(result);
+ var fieldvalue = "";
+ if (typeof(result) != "undefined") {
+ for (i in result) {
+ var tuedel = "";
+ var propval = result[i];
+ if (typeof(propval) == "string") {
+ tuedel = '"';
+ }
+ fieldvalue +=
+ i
+ + " [" + typeof(propval) + "] = "
+ + tuedel + propval + tuedel + "\n";
+ }
+ fo.field.value = fieldvalue;
+ }
+}
+
+
+</script>
+</head>
+<body bgcolor="#dddddd">
+<h1>JavaScript Konsole</h1>
+<form name="fo">
+<table bgcolor="#cccccc" cellspacing="1" cellpadding="8">
+ <tr bgcolor="#ffeeee"><th height="40" align="right">Expression</th><td><input name="zeile" type="text" size="60"></td></tr>
+ <tr bgcolor="#eeeeee"><th align="right">Result Type</th><td><input name="restyp" readonly type="text" size="60"></td></tr>
+ <tr bgcolor="#eeeeee"><th align="right">Result(s)</th><td><textarea readonly name="field" rows="10" cols="60"></textarea></td></tr>
+<tr bgcolor="#ffeeee"><td>&nbsp;</td><td>
+ <input type="button" value="list properties" onclick="do_properties()">
+ <input type="button" value="evaluate" onclick="do_eval()">
+ <input type="reset" value="clear fields"
+</td></tr>
+</table>
+</form>
+<h2>Explanation</h2>
+<h3>Operation</h3>
+<blockquote>
+When <em>evaluate</em> is pressed, the given expression is evaluated and the result is displayed in the result(s) field.
+In case of <em>list properties</em> being pressed, the result of the expression is taken as an object
+and the objects properties are displayed with their type and value in the the result(s) field.
+</blockquote>
+<h3>Expression</h3>
+<blockquote>
+Expression must be a valid javascript expression, e.g.<br><code>window</code>
+<br>or<br><code>document.body.innerHTML</code><br>or<br>
+<code>"Today: " + (new Date()).toString()</code><br>
+or<br>
+<code>"Cablecar".match(/ab.*c/)</code>
+<br>It is also possible to assign a value,
+e.g.<br><code>document.getElementsByTagName('H1').item(0).innerText="Hello World"</code><br>
+You may execute these examples by pasting them into the expression field.
+</blockquote>
+<h3>Result Type</h3>
+<blockquote>
+The type of the result of the given expression.
+</blockquote>
+<h3>Result(s)</h3>
+<blockquote>
+The result of the expression is implicitly converted to a primitive type by the javascript interpreter,
+if <em>evaluate</em> was pressed. When <em>list properties</em> was pressed, a <code>for (var i in obj)</code> loop
+is executed to list the properties. These object properties are in turn evaluated and their types and values
+are displayed.
+</blockquote>
+<p>
+<a href="mailto:till@snafu.de?subject=JavaScript%20Konsole">Till Krech</a>
+</p>
+<p>
+<br>
+</p>
+
+</body>
+</html>
diff --git a/tdehtml/ecma/kjs_binding.cpp b/tdehtml/ecma/kjs_binding.cpp
new file mode 100644
index 000000000..09961fbb5
--- /dev/null
+++ b/tdehtml/ecma/kjs_binding.cpp
@@ -0,0 +1,467 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001-2003 David Faure (faure@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_binding.h"
+#include "kjs_dom.h"
+
+#include "dom/dom_exception.h"
+#include "dom/dom2_range.h"
+#include "xml/dom2_eventsimpl.h"
+#include "tdehtmlpart_p.h"
+
+#include <kdebug.h>
+#include <tdeparts/browserextension.h>
+
+#include <assert.h>
+
+using namespace KJS;
+
+/* TODO:
+ * The catch all (...) clauses below shouldn't be necessary.
+ * But they helped to view for example www.faz.net in an stable manner.
+ * Those unknown exceptions should be treated as severe bugs and be fixed.
+ *
+ * these may be CSS exceptions - need to check - pmk
+ */
+
+Value DOMObject::get(ExecState *exec, const Identifier &p) const
+{
+ Value result;
+ try {
+ result = tryGet(exec,p);
+ }
+ catch (DOM::DOMException e) {
+ // ### translate code into readable string ?
+ // ### oh, and s/QString/i18n or I18N_NOOP (the code in kjs uses I18N_NOOP... but where is it translated ?)
+ // and where does it appear to the user ?
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM exception %1").arg(e.code)).local8Bit());
+ exec->setException( err );
+ result = Undefined();
+ }
+ catch (...) {
+ kdError(6070) << "Unknown exception in DOMObject::get()" << endl;
+ result = String("Unknown exception");
+ }
+
+ return result;
+}
+
+void DOMObject::put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr)
+{
+ try {
+ tryPut(exec, propertyName, value, attr);
+ }
+ catch (DOM::DOMException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM exception %1").arg(e.code)).local8Bit());
+ exec->setException(err);
+ }
+ catch (...) {
+ kdError(6070) << "Unknown exception in DOMObject::put()" << endl;
+ }
+}
+
+void DOMObject::tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr)
+{
+ static_cast<ScriptInterpreter*>(exec->dynamicInterpreter())->customizedDOMObject(this);
+ ObjectImp::put(exec,propertyName,value,attr);
+}
+
+UString DOMObject::toString(ExecState *) const
+{
+ return "[object " + className() + "]";
+}
+
+Boolean DOMObject::hasInstance(ExecState *exec, const Value &value)
+{
+ if (value.type() != ObjectType)
+ return Boolean(false);
+
+ Value prot = get(exec,prototypePropertyName);
+ if (prot.type() != ObjectType && prot.type() != NullType) {
+ Object err = Error::create(exec, TypeError, "Invalid prototype encountered "
+ "in instanceof operation.");
+ exec->setException(err);
+ return Boolean(false);
+ }
+
+ Object v = Object(static_cast<ObjectImp*>(value.imp()));
+ while ((v = Object::dynamicCast(v.prototype())).imp()) {
+ if (v.imp() == prot.imp())
+ return Boolean(true);
+ }
+ return Boolean(false);
+}
+
+
+Value DOMFunction::get(ExecState *exec, const Identifier &propertyName) const
+{
+ try {
+ return tryGet(exec, propertyName);
+ }
+ catch (DOM::DOMException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM exception %1").arg(e.code)).local8Bit());
+ exec->setException(err);
+ return Undefined();
+ }
+ catch (...) {
+ kdError(6070) << "Unknown exception in DOMFunction::get()" << endl;
+ return String("Unknown exception");
+ }
+}
+
+Value DOMFunction::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ try {
+ return tryCall(exec, thisObj, args);
+ }
+ // pity there's no way to distinguish between these in JS code
+ // ### Look into setting prototypes of these & the use of instanceof so the exception
+ // type can be determined. See what other browsers do.
+ catch (DOM::DOMException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM Exception %1").arg(e.code)).local8Bit());
+ err.put(exec, "code", Number(e.code));
+ exec->setException(err);
+ return Undefined();
+ }
+ catch (DOM::RangeException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM Range Exception %1").arg(e.code)).local8Bit());
+ err.put(exec, "code", Number(e.code));
+ exec->setException(err);
+ return Undefined();
+ }
+ catch (DOM::CSSException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("CSS Exception %1").arg(e.code)).local8Bit());
+ err.put(exec, "code", Number(e.code));
+ exec->setException(err);
+ return Undefined();
+ }
+ catch (DOM::EventException e) {
+ Object err = Error::create(exec, GeneralError, TQString(TQString("DOM Event Exception %1").arg(e.code)).local8Bit());
+ err.put(exec, "code", Number(e.code));
+ exec->setException(err);
+ return Undefined();
+ }
+ catch (...) {
+ kdError(6070) << "Unknown exception in DOMFunction::call()" << endl;
+ Object err = Error::create(exec, GeneralError, "Unknown exception");
+ exec->setException(err);
+ return Undefined();
+ }
+}
+
+typedef TQPtrList<ScriptInterpreter> InterpreterList;
+static InterpreterList *interpreterList;
+
+ScriptInterpreter::ScriptInterpreter( const Object &global, tdehtml::ChildFrame* frame )
+ : Interpreter( global ), m_frame( frame ), m_domObjects(1021),
+ m_evt( 0L ), m_inlineCode(false), m_timerCallback(false)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "ScriptInterpreter::ScriptInterpreter " << this << " for part=" << m_frame << endl;
+#endif
+ if ( !interpreterList )
+ interpreterList = new InterpreterList;
+ interpreterList->append( this );
+}
+
+ScriptInterpreter::~ScriptInterpreter()
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "ScriptInterpreter::~ScriptInterpreter " << this << " for part=" << m_frame << endl;
+#endif
+ assert( interpreterList && interpreterList->contains( this ) );
+ interpreterList->remove( this );
+ if ( interpreterList->isEmpty() ) {
+ delete interpreterList;
+ interpreterList = 0;
+ }
+}
+
+void ScriptInterpreter::forgetDOMObject( void* objectHandle )
+{
+ if( !interpreterList ) return;
+
+ TQPtrListIterator<ScriptInterpreter> it( *interpreterList );
+ while ( it.current() ) {
+ (*it)->deleteDOMObject( objectHandle );
+ ++it;
+ }
+}
+
+void ScriptInterpreter::mark()
+{
+ Interpreter::mark();
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "ScriptInterpreter::mark " << this << " marking " << m_customizedDomObjects.count() << " DOM objects" << endl;
+#endif
+ TQPtrDictIterator<void> it( m_customizedDomObjects );
+ for( ; it.current(); ++it )
+ static_cast<DOMObject*>(it.currentKey())->mark();
+}
+
+KParts::ReadOnlyPart* ScriptInterpreter::part() const {
+ return m_frame->m_part;
+}
+
+bool ScriptInterpreter::isWindowOpenAllowed() const
+{
+ if ( m_evt )
+ {
+ int id = m_evt->handle()->id();
+ bool eventOk = ( // mouse events
+ id == DOM::EventImpl::CLICK_EVENT ||
+ id == DOM::EventImpl::MOUSEUP_EVENT || id == DOM::EventImpl::MOUSEDOWN_EVENT ||
+ id == DOM::EventImpl::KHTML_ECMA_CLICK_EVENT || id == DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT ||
+ // keyboard events
+ id == DOM::EventImpl::KEYDOWN_EVENT || id == DOM::EventImpl::KEYPRESS_EVENT ||
+ id == DOM::EventImpl::KEYUP_EVENT ||
+ // other accepted events
+ id == DOM::EventImpl::SELECT_EVENT || id == DOM::EventImpl::CHANGE_EVENT ||
+ id == DOM::EventImpl::SUBMIT_EVENT );
+ kdDebug(6070) << "Window.open, smart policy: id=" << id << " eventOk=" << eventOk << endl;
+ if (eventOk)
+ return true;
+ } else // no event
+ {
+ if ( m_inlineCode && !m_timerCallback )
+ {
+ // This is the <a href="javascript:window.open('...')> case -> we let it through
+ return true;
+ kdDebug(6070) << "Window.open, smart policy, no event, inline code -> ok" << endl;
+ }
+ else // This is the <script>window.open(...)</script> case or a timer callback -> block it
+ kdDebug(6070) << "Window.open, smart policy, no event, <script> tag -> refused" << endl;
+ }
+ return false;
+}
+
+
+UString::UString(const TQString &d)
+{
+ unsigned int len = d.length();
+ UChar *dat = new UChar[len];
+ memcpy(dat, d.unicode(), len * sizeof(UChar));
+ rep = UString::Rep::create(dat, len);
+}
+
+UString::UString(const DOM::DOMString &d)
+{
+ if (d.isNull()) {
+ // we do a conversion here as null DOMStrings shouldn't cross
+ // the boundary to kjs. They should either be empty strings
+ // or explicitly converted to KJS::Null via getString().
+ attach(&Rep::empty);
+ return;
+ }
+
+ unsigned int len = d.length();
+ UChar *dat = new UChar[len];
+ memcpy(dat, d.unicode(), len * sizeof(UChar));
+ rep = UString::Rep::create(dat, len);
+}
+
+DOM::DOMString UString::string() const
+{
+ return DOM::DOMString((TQChar*) data(), size());
+}
+
+TQString UString::qstring() const
+{
+ return TQString((TQChar*) data(), size());
+}
+
+TQConstString UString::qconststring() const
+{
+ return TQConstString((TQChar*) data(), size());
+}
+
+DOM::DOMString Identifier::string() const
+{
+ return DOM::DOMString((TQChar*) data(), size());
+}
+
+TQString Identifier::qstring() const
+{
+ return TQString((TQChar*) data(), size());
+}
+
+DOM::Node KJS::toNode(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMNode::info))
+ return DOM::Node();
+
+ const DOMNode *dobj = static_cast<const DOMNode*>(obj.imp());
+ return dobj->toNode();
+}
+
+Value KJS::getString(DOM::DOMString s)
+{
+ if (s.isNull())
+ return Null();
+ else
+ return String(s);
+}
+
+TQVariant KJS::ValueToVariant(ExecState* exec, const Value &val) {
+ TQVariant res;
+ switch (val.type()) {
+ case BooleanType:
+ res = TQVariant(val.toBoolean(exec), 0);
+ break;
+ case NumberType:
+ res = TQVariant(val.toNumber(exec));
+ break;
+ case StringType:
+ res = TQVariant(val.toString(exec).qstring());
+ break;
+ default:
+ // everything else will be 'invalid'
+ break;
+ }
+ return res;
+}
+
+class EmbedLiveConnect : public ObjectImp
+{
+ friend Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const TQString & name, const int type, const TQString & value, int id);
+ EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id);
+public:
+ ~EmbedLiveConnect();
+
+ virtual Value get(ExecState *, const Identifier & prop) const;
+ virtual void put(ExecState * exec, const Identifier &prop, const Value & value, int=None);
+ virtual Value call(ExecState * exec, Object &, const List &args);
+ virtual bool implementsCall() const;
+ virtual bool toBoolean(ExecState *) const;
+ virtual Value toPrimitive(ExecState *exec, Type) const;
+ virtual UString toString(ExecState *) const;
+
+private:
+ EmbedLiveConnect(const EmbedLiveConnect &);
+ TQGuardedPtr<KParts::LiveConnectExtension> m_liveconnect;
+ UString name;
+ KParts::LiveConnectExtension::Type objtype;
+ unsigned long objid;
+};
+
+Value KJS::getLiveConnectValue(KParts::LiveConnectExtension *lc, const TQString & name, const int type, const TQString & value, int id)
+{
+ KParts::LiveConnectExtension::Type t=(KParts::LiveConnectExtension::Type)type;
+ switch(t) {
+ case KParts::LiveConnectExtension::TypeBool: {
+ bool ok;
+ int i = value.toInt(&ok);
+ if (ok)
+ return Boolean(i);
+ return Boolean(!strcasecmp(value.latin1(), "true"));
+ }
+ case KParts::LiveConnectExtension::TypeObject:
+ case KParts::LiveConnectExtension::TypeFunction:
+ return Value(new EmbedLiveConnect(lc, name, t, id));
+ case KParts::LiveConnectExtension::TypeNumber: {
+ bool ok;
+ int i = value.toInt(&ok);
+ if (ok)
+ return Number(i);
+ else
+ return Number(value.toDouble(&ok));
+ }
+ case KParts::LiveConnectExtension::TypeString:
+ return String(value);
+ case KParts::LiveConnectExtension::TypeVoid:
+ default:
+ return Undefined();
+ }
+}
+
+/* only with gcc > 3.4 KDE_NO_EXPORT */
+EmbedLiveConnect::EmbedLiveConnect(KParts::LiveConnectExtension *lc, UString n, KParts::LiveConnectExtension::Type t, int id)
+ : m_liveconnect (lc), name(n), objtype(t), objid(id)
+{}
+
+/* only with gcc > 3.4 KDE_NO_EXPORT */
+EmbedLiveConnect::~EmbedLiveConnect() {
+ if (m_liveconnect)
+ m_liveconnect->unregister(objid);
+}
+
+KDE_NO_EXPORT
+Value EmbedLiveConnect::get(ExecState *, const Identifier & prop) const
+{
+ if (m_liveconnect) {
+ KParts::LiveConnectExtension::Type rettype;
+ TQString retval;
+ unsigned long retobjid;
+ if (m_liveconnect->get(objid, prop.qstring(), rettype, retobjid, retval))
+ return getLiveConnectValue(m_liveconnect, prop.qstring(), rettype, retval, retobjid);
+ }
+ return Undefined();
+}
+
+KDE_NO_EXPORT
+void EmbedLiveConnect::put(ExecState * exec, const Identifier &prop, const Value & value, int)
+{
+ if (m_liveconnect)
+ m_liveconnect->put(objid, prop.qstring(), value.toString(exec).qstring());
+}
+
+KDE_NO_EXPORT
+bool EmbedLiveConnect::implementsCall() const {
+ return objtype == KParts::LiveConnectExtension::TypeFunction;
+}
+
+KDE_NO_EXPORT
+Value EmbedLiveConnect::call(ExecState *exec, Object&, const List &args)
+{
+ if (m_liveconnect) {
+ TQStringList qargs;
+ for (ListIterator i = args.begin(); i != args.end(); ++i)
+ qargs.append((*i).toString(exec).qstring());
+ KParts::LiveConnectExtension::Type rtype;
+ TQString rval;
+ unsigned long robjid;
+ if (m_liveconnect->call(objid, name.qstring(), qargs, rtype, robjid, rval))
+ return getLiveConnectValue(m_liveconnect, name.qstring(), rtype, rval, robjid);
+ }
+ return Undefined();
+}
+
+KDE_NO_EXPORT
+bool EmbedLiveConnect::toBoolean(ExecState *) const {
+ return true;
+}
+
+KDE_NO_EXPORT
+Value EmbedLiveConnect::toPrimitive(ExecState *exec, Type) const {
+ return String(toString(exec));
+}
+
+KDE_NO_EXPORT
+UString EmbedLiveConnect::toString(ExecState *) const {
+ TQString str;
+ const char *type = objtype == KParts::LiveConnectExtension::TypeFunction ? "Function" : "Object";
+ str.sprintf("[object %s ref=%d]", type, (int) objid);
+ return UString(str);
+}
diff --git a/tdehtml/ecma/kjs_binding.h b/tdehtml/ecma/kjs_binding.h
new file mode 100644
index 000000000..9b69284ba
--- /dev/null
+++ b/tdehtml/ecma/kjs_binding.h
@@ -0,0 +1,409 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_BINDING_H_
+#define _KJS_BINDING_H_
+
+#include <kjs/interpreter.h>
+#include <kjs/function_object.h> /// for FunctionPrototypeImp
+
+#include <dom/dom_node.h>
+#include <tqvariant.h>
+#include <tqptrdict.h>
+#include <kurl.h>
+#include <kjs/lookup.h>
+
+namespace KParts {
+ class ReadOnlyPart;
+ class LiveConnectExtension;
+}
+
+namespace tdehtml {
+ class ChildFrame;
+}
+
+namespace KJS {
+
+ /**
+ * Base class for all objects in this binding - get() and put() run
+ * tryGet() and tryPut() respectively, and catch exceptions if they
+ * occur.
+ */
+ class DOMObject : public ObjectImp {
+ public:
+ DOMObject(const Object &proto) : ObjectImp(proto) {}
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
+ { return ObjectImp::get(exec, propertyName); }
+ virtual bool implementsHasInstance() const { return true; }
+ virtual Boolean hasInstance(ExecState *exec, const Value &value);
+ virtual void put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr = None);
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr = None);
+
+ virtual UString toString(ExecState *exec) const;
+ };
+
+ /**
+ * Base class for all functions in this binding - get() and call() run
+ * tryGet() and tryCall() respectively, and catch exceptions if they
+ * occur.
+ */
+ class DOMFunction : public InternalFunctionImp {
+ public:
+ DOMFunction(ExecState* exec) : InternalFunctionImp(
+ static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ ) {}
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
+ { return ObjectImp::get(exec, propertyName); }
+
+ virtual bool implementsCall() const { return true; }
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args)
+ { return ObjectImp::call(exec, thisObj, args); }
+ virtual bool toBoolean(ExecState *) const { return true; }
+ };
+
+ /**
+ * We inherit from Interpreter, to save a pointer to the HTML part
+ * that the interpreter runs for.
+ * The interpreter also stores the DOM object - >KJS::DOMObject cache.
+ */
+ class KDE_EXPORT ScriptInterpreter : public Interpreter
+ {
+ public:
+ ScriptInterpreter( const Object &global, tdehtml::ChildFrame* frame );
+ virtual ~ScriptInterpreter();
+
+ DOMObject* getDOMObject( void* objectHandle ) const {
+ return m_domObjects[objectHandle];
+ }
+ void putDOMObject( void* objectHandle, DOMObject* obj ) {
+ m_domObjects.insert( objectHandle, obj );
+ }
+ void customizedDOMObject( DOMObject* obj ) {
+ m_customizedDomObjects.replace( obj, this );
+ }
+ bool deleteDOMObject( void* objectHandle ) {
+ DOMObject* obj = m_domObjects.take( objectHandle );
+ if (obj) {
+ m_customizedDomObjects.remove( obj );
+ return true;
+ }
+ else
+ return false;
+ }
+ void clear() {
+ m_customizedDomObjects.clear();
+ m_domObjects.clear();
+ }
+ /**
+ * Static method. Makes all interpreters forget about the object
+ */
+ static void forgetDOMObject( void* objectHandle );
+
+ /**
+ * Mark objects in the DOMObject cache.
+ */
+ virtual void mark();
+ KParts::ReadOnlyPart* part() const;
+
+ virtual int rtti() { return 1; }
+
+ /**
+ * Set the event that is triggering the execution of a script, if any
+ */
+ void setCurrentEvent( DOM::Event *evt ) { m_evt = evt; }
+ void setInlineCode( bool inlineCode ) { m_inlineCode = inlineCode; }
+ void setProcessingTimerCallback( bool timerCallback ) { m_timerCallback = timerCallback; }
+ /**
+ * "Smart" window.open policy
+ */
+ bool isWindowOpenAllowed() const;
+
+ private:
+ tdehtml::ChildFrame* m_frame;
+ TQPtrDict<DOMObject> m_domObjects;
+ TQPtrDict<void> m_customizedDomObjects; //Objects which had custom properties set,
+ //and should not be GC'd. key is DOMObject*
+ DOM::Event *m_evt;
+ bool m_inlineCode;
+ bool m_timerCallback;
+ };
+ /**
+ * Retrieve from cache, or create, a KJS object around a DOM object
+ */
+ template<class DOMObj, class KJSDOMObj>
+ inline Value cacheDOMObject(ExecState *exec, DOMObj domObj)
+ {
+ DOMObject *ret;
+ if (domObj.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(domObj.handle())))
+ return Value(ret);
+ else {
+ ret = new KJSDOMObj(exec, domObj);
+ interp->putDOMObject(domObj.handle(),ret);
+ return Value(ret);
+ }
+ }
+
+ /**
+ * Convert an object to a Node. Returns a null Node if not possible.
+ */
+ DOM::Node toNode(const Value&);
+ /**
+ * Get a String object, or Null() if s is null
+ */
+ Value getString(DOM::DOMString s);
+
+ /**
+ * Convery a KJS value into a QVariant
+ */
+ TQVariant ValueToVariant(ExecState* exec, const Value& val);
+
+ /**
+ * We need a modified version of lookupGet because
+ * we call tryGet instead of get, in DOMObjects.
+ */
+ template <class FuncImp, class ThisImp, class ParentImp>
+ inline Value DOMObjectLookupGet(ExecState *exec, const Identifier &propertyName,
+ const HashTable* table, const ThisImp* thisObj)
+ {
+ const HashEntry* entry = Lookup::findEntry(table, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::tryGet(exec, propertyName);
+
+ if (entry->attr & Function) {
+ return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
+ }
+ return thisObj->getValueProperty(exec, entry->value);
+ }
+
+ /**
+ * Simplified version of DOMObjectLookupGet in case there are no
+ * functions, only "values".
+ */
+ template <class ThisImp, class ParentImp>
+ inline Value DOMObjectLookupGetValue(ExecState *exec, const Identifier &propertyName,
+ const HashTable* table, const ThisImp* thisObj)
+ {
+ const HashEntry* entry = Lookup::findEntry(table, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::tryGet(exec, propertyName);
+
+ if (entry->attr & Function)
+ fprintf(stderr, "Function bit set! Shouldn't happen in lookupValue!\n" );
+ return thisObj->getValueProperty(exec, entry->value);
+ }
+
+ /**
+ * We need a modified version of lookupPut because
+ * we call tryPut instead of put, in DOMObjects.
+ */
+ template <class ThisImp, class ParentImp>
+ inline void DOMObjectLookupPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr,
+ const HashTable* table, ThisImp* thisObj)
+ {
+ const HashEntry* entry = Lookup::findEntry(table, propertyName);
+
+ if (!entry) // not found: forward to parent
+ thisObj->ParentImp::tryPut(exec, propertyName, value, attr);
+ else if (entry->attr & Function) // function: put as override property
+ thisObj->ObjectImp::put(exec, propertyName, value, attr);
+ else if (entry->attr & ReadOnly) // readonly! Can't put!
+#ifdef KJS_VERBOSE
+ fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
+#else
+ ; // do nothing
+#endif
+ else
+ thisObj->putValueProperty(exec, entry->value, value, attr);
+ }
+
+// Versions of prototype functions that properly support instanceof,
+// and are compatible with trunk.
+#define KJS_DEFINE_PROTOTYPE_IMP(ClassProto,ProtoCode) \
+ class ClassProto : public ObjectImp { \
+ friend Object cacheGlobalObject<ClassProto>(ExecState *exec, const Identifier &propertyName); \
+ public: \
+ static Object self(ExecState *exec); \
+ virtual const ClassInfo *classInfo() const { return &info; } \
+ static const ClassInfo info; \
+ Value get(ExecState *exec, const Identifier &propertyName) const; \
+ protected: \
+ ClassProto( ExecState *exec ) \
+ : ObjectImp( ProtoCode ) {} \
+ \
+ static Identifier* s_name; \
+ static Identifier* name(); \
+ };
+
+#define KJS_DEFINE_PROTOTYPE(ClassProto) \
+ KJS_DEFINE_PROTOTYPE_IMP(ClassProto, exec->interpreter()->builtinObjectPrototype())
+
+#define KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(ClassProto, ClassProtoProto) \
+ KJS_DEFINE_PROTOTYPE_IMP(ClassProto, ClassProtoProto::self(exec))
+
+#define KJS_EMPTY_PROTOTYPE_IMP(ClassName, ClassProto, ProtoCode) \
+ class ClassProto : public ObjectImp { \
+ friend Object cacheGlobalObject<ClassProto>(ExecState *exec, const Identifier &propertyName); \
+ public: \
+ static Object self(ExecState *exec) { \
+ return cacheGlobalObject<ClassProto>(exec, *name()); \
+ } \
+ virtual const ClassInfo *classInfo() const { return &info; } \
+ static const ClassInfo info; \
+ protected: \
+ ClassProto( ExecState *exec ) \
+ : ObjectImp( ProtoCode ) {} \
+ \
+ static Identifier* s_name; \
+ static Identifier* name() { \
+ if (!s_name) s_name = new Identifier("[[" ClassName ".prototype]]"); \
+ return s_name; \
+ }\
+ }; \
+ Identifier* ClassProto::s_name = 0; \
+ const ClassInfo ClassProto::info = { ClassName, 0, 0, 0 };
+
+#define KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE(ClassName, ClassProto, ClassProtoProto) \
+ KJS_EMPTY_PROTOTYPE_IMP(ClassName, ClassProto, ClassProtoProto::self(exec))
+
+//### this doesn't implement hasProperty, but stuff in lookup.h didn't
+//either (just did the forward)
+#define KJS_IMPLEMENT_PROTOTYPE(ClassName, ClassProto, ClassFunc) \
+ const ClassInfo ClassProto::info = { ClassName, 0, &ClassProto##Table, 0 }; \
+ Identifier* ClassProto::s_name = 0; \
+ Object ClassProto::self(ExecState *exec) \
+ { \
+ return cacheGlobalObject<ClassProto>(exec, *name()); \
+ } \
+ Value ClassProto::get(ExecState *exec, const Identifier &propertyName) const \
+ { \
+ /*fprintf( stderr, "%sProto::get(%s) [in macro, no parent]\n", info.className, propertyName.ascii());*/ \
+ return lookupGetFunction<ClassFunc,ObjectImp>(exec, propertyName, &ClassProto##Table, this ); \
+ } \
+ Identifier* ClassProto::name() \
+ { \
+ if (!s_name) s_name = new Identifier("[[" ClassName ".prototype]]"); \
+ return s_name; \
+ }
+
+ // Modified version of IMPLEMENT_PROTOFUNC, to use DOMFunction and tryCall
+#define IMPLEMENT_PROTOFUNC_DOM(ClassFunc) \
+ class ClassFunc : public DOMFunction { \
+ public: \
+ ClassFunc(ExecState *exec, int i, int len) \
+ : DOMFunction( exec ), id(i) { \
+ Value protect(this); \
+ put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \
+ } \
+ /** You need to implement that one */ \
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); \
+ private: \
+ int id; \
+ };
+
+ Value getLiveConnectValue(KParts::LiveConnectExtension *lc, const TQString & name, const int type, const TQString & value, int id);
+
+
+// This is used to create pseudo-constructor objects, like Mozillaish
+// Element, HTMLDocument, etc., which do not act like real constructors,
+// but do have the prototype property pointing to prototype of "instances"
+#define DEFINE_PSEUDO_CONSTRUCTOR(ClassName) \
+ class ClassName : public DOMObject { \
+ public: \
+ ClassName(ExecState *); \
+ virtual const ClassInfo* classInfo() const { return &info; } \
+ static const ClassInfo info; \
+ static Object self(ExecState *exec); \
+ };
+
+#define IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProto) \
+ const ClassInfo Class::info = { ClassName, 0, 0, 0 }; \
+ Class::Class(ExecState* exec): DOMObject(ParentProto) {\
+ Object proto = ProtoClass::self(exec); \
+ putDirect(prototypePropertyName, proto.imp(), DontDelete|ReadOnly); \
+ }\
+ Object Class::self(ExecState *exec) { \
+ return Object(cacheGlobalObject<Class>(exec, "[[" ClassName ".constructor]]")); \
+ }
+
+#define IMPLEMENT_PSEUDO_CONSTRUCTOR(Class,ClassName,ProtoClass) \
+ IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,exec->lexicalInterpreter()->builtinObjectPrototype())
+
+#define IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(Class,ClassName,ProtoClass,ParentProtoClass) \
+ IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProtoClass::self(exec))
+
+// This declares a constant table, which merely maps everything in its
+// table to its token value. Can be used as a prototype
+#define DEFINE_CONSTANT_TABLE(Class) \
+ class Class : public DOMObject { \
+ public: \
+ Class(ExecState *exec): DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {} \
+ \
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;\
+ Value getValueProperty(ExecState * /*exec*/, int token) const; \
+ virtual const ClassInfo* classInfo() const { return &info; } \
+ static const ClassInfo info; \
+ static Object self(ExecState *exec);\
+ static Identifier* s_name; \
+ static Identifier* name(); \
+ };
+
+// Emits an implementation of a constant table
+#define IMPLEMENT_CONSTANT_TABLE(Class,ClassName) \
+ Value Class::tryGet(ExecState *exec, const Identifier &propertyName) const { \
+ return DOMObjectLookupGetValue<Class, DOMObject>(exec, propertyName, &Class##Table, this);\
+ } \
+ Value Class::getValueProperty(ExecState * /*exec*/, int token) const { \
+ /* We use the token as the value to return directly*/ \
+ return Number((unsigned int)token); \
+ } \
+ Object Class::self(ExecState *exec) { \
+ return cacheGlobalObject<Class>(exec, *name()); \
+ } \
+ Identifier* Class::s_name = 0; \
+ Identifier* Class::name() { \
+ if (!s_name) s_name = new Identifier("[[" ClassName ".constant_table]]"); \
+ return s_name; \
+ } \
+ const ClassInfo Class::info = { ClassName, 0, &Class##Table, 0 };
+
+
+// Hide some of the stuff in lookup.h..
+#undef PUBLIC_DEFINE_PROTOTYPE
+#undef DEFINE_PROTOTYPE
+#undef IMPLEMENT_PROTOTYPE
+#undef PUBLIC_IMPLEMENT_PROTOTYPE
+#undef IMPLEMENT_PROTOTYPE_WITH_PARENT
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_css.cpp b/tdehtml/ecma/kjs_css.cpp
new file mode 100644
index 000000000..b42f9dd02
--- /dev/null
+++ b/tdehtml/ecma/kjs_css.cpp
@@ -0,0 +1,1302 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_css.h"
+#include "kjs_css.lut.h"
+
+#include <dom/html_head.h> // for HTMLStyleElement
+
+#include <css/css_base.h>
+#include "kjs_dom.h"
+
+
+#include <kdebug.h>
+
+namespace KJS {
+
+static TQString cssPropertyName( const Identifier &p, bool& hadPixelPrefix )
+{
+ TQString prop = p.qstring();
+ int i = prop.length();
+ while ( --i ) {
+ char c = prop[i].latin1();
+ if ( c >= 'A' && c <= 'Z' )
+ prop.insert( i, '-' );
+ }
+
+ prop = prop.lower();
+ hadPixelPrefix = false;
+
+ if (prop.startsWith("css-")) {
+ prop = prop.mid(4);
+ } else if (prop.startsWith("pixel-")) {
+ prop = prop.mid(6);
+ hadPixelPrefix = true;
+ } else if (prop.startsWith("pos-")) {
+ prop = prop.mid(4);
+ hadPixelPrefix = true;
+ }
+
+ return prop;
+}
+
+/*
+@begin DOMCSSStyleDeclarationProtoTable 7
+ getPropertyValue DOMCSSStyleDeclaration::GetPropertyValue DontDelete|Function 1
+ getPropertyCSSValue DOMCSSStyleDeclaration::GetPropertyCSSValue DontDelete|Function 1
+ removeProperty DOMCSSStyleDeclaration::RemoveProperty DontDelete|Function 1
+ getPropertyPriority DOMCSSStyleDeclaration::GetPropertyPriority DontDelete|Function 1
+ setProperty DOMCSSStyleDeclaration::SetProperty DontDelete|Function 3
+ item DOMCSSStyleDeclaration::Item DontDelete|Function 1
+# IE names for it (#36063)
+ getAttribute DOMCSSStyleDeclaration::GetPropertyValue DontDelete|Function 1
+ removeAttribute DOMCSSStyleDeclaration::RemoveProperty DontDelete|Function 1
+ setAttribute DOMCSSStyleDeclaration::SetProperty DontDelete|Function 3
+@end
+@begin DOMCSSStyleDeclarationTable 3
+ cssText DOMCSSStyleDeclaration::CssText DontDelete
+ length DOMCSSStyleDeclaration::Length DontDelete|ReadOnly
+ parentRule DOMCSSStyleDeclaration::ParentRule DontDelete|ReadOnly
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMCSSStyleDeclarationProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSStyleDeclarationProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMCSSStyleDeclaration", DOMCSSStyleDeclarationProto, DOMCSSStyleDeclarationProtoFunc)
+
+IMPLEMENT_PSEUDO_CONSTRUCTOR(CSSStyleDeclarationPseudoCtor, "DOMCSSStyleDeclaration",DOMCSSStyleDeclarationProto)
+
+const ClassInfo DOMCSSStyleDeclaration::info = { "CSSStyleDeclaration", 0, &DOMCSSStyleDeclarationTable, 0 };
+
+DOMCSSStyleDeclaration::DOMCSSStyleDeclaration(ExecState *exec, const DOM::CSSStyleDeclaration& s)
+ : DOMObject(DOMCSSStyleDeclarationProto::self(exec)), styleDecl(s)
+{ }
+
+DOMCSSStyleDeclaration::~DOMCSSStyleDeclaration()
+{
+ ScriptInterpreter::forgetDOMObject(styleDecl.handle());
+}
+
+bool DOMCSSStyleDeclaration::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ bool hadPixelPrefix;
+ TQString cssprop = cssPropertyName(p, hadPixelPrefix);
+ if (DOM::getPropertyID(cssprop.latin1(), cssprop.length()))
+ return true;
+
+ return ObjectImp::hasProperty(exec, p);
+}
+
+Value DOMCSSStyleDeclaration::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMCSSStyleDeclaration::tryGet " << propertyName.qstring() << endl;
+#endif
+ const HashEntry* entry = Lookup::findEntry(&DOMCSSStyleDeclarationTable, propertyName);
+ if (entry)
+ switch (entry->value) {
+ case CssText:
+ return String(styleDecl.cssText());
+ case Length:
+ return Number(styleDecl.length());
+ case ParentRule:
+ return getDOMCSSRule(exec,styleDecl.parentRule());
+ default:
+ break;
+ }
+
+ // Look in the prototype (for functions) before assuming it's a name
+ Object proto = Object::dynamicCast(prototype());
+ if (proto.isValid() && proto.hasProperty(exec,propertyName))
+ return proto.get(exec,propertyName);
+
+ bool ok;
+ long unsigned int u = propertyName.toULong(&ok);
+ if (ok)
+ return String(DOM::CSSStyleDeclaration(styleDecl).item(u));
+
+ // pixelTop returns "CSS Top" as number value in unit pixels
+ // posTop returns "CSS top" as number value in unit pixels _if_ its a
+ // positioned element. if it is not a positioned element, return 0
+ // from MSIE documentation ### IMPLEMENT THAT (Dirk)
+ bool asNumber;
+ TQString p = cssPropertyName(propertyName, asNumber);
+
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMCSSStyleDeclaration: converting to css property name: " << p << ( asNumber ? "px" : "" ) << endl;
+#endif
+
+ if (asNumber) {
+ DOM::CSSValue v = styleDecl.getPropertyCSSValue(p);
+ if ( !v.isNull() && v.cssValueType() == DOM::CSSValue::CSS_PRIMITIVE_VALUE)
+ return Number(static_cast<DOM::CSSPrimitiveValue>(v).getFloatValue(DOM::CSSPrimitiveValue::CSS_PX));
+ }
+
+ DOM::DOMString str = const_cast<DOM::CSSStyleDeclaration &>( styleDecl ).getPropertyValue(p);
+ if (!str.isNull())
+ return String(str);
+
+ // see if we know this css property, return empty then
+ if (DOM::getPropertyID(p.latin1(), p.length()))
+ return String(DOM::DOMString(""));
+
+ return DOMObject::tryGet(exec, propertyName);
+}
+
+
+void DOMCSSStyleDeclaration::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr )
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMCSSStyleDeclaration::tryPut " << propertyName.qstring() << endl;
+#endif
+ if (propertyName == "cssText") {
+ styleDecl.setCssText(value.toString(exec).string());
+ }
+ else {
+ bool pxSuffix;
+ TQString prop = cssPropertyName(propertyName, pxSuffix);
+ TQString propvalue = value.toString(exec).qstring();
+
+ if (pxSuffix)
+ propvalue += "px";
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMCSSStyleDeclaration: prop=" << prop << " propvalue=" << propvalue << endl;
+#endif
+ // Look whether the property is known.d In that case add it as a CSS property.
+ if (DOM::getPropertyID(prop.latin1(), prop.length())) {
+ if (propvalue.isEmpty())
+ styleDecl.removeProperty(prop);
+ else {
+ int important = propvalue.find("!important", 0, false);
+ if (important == -1)
+ styleDecl.setProperty(prop, DOM::DOMString(propvalue), "");
+ else
+ styleDecl.setProperty(prop, DOM::DOMString(propvalue.left(important - 1)), "important");
+ }
+ }
+ else
+ // otherwise add it as a JS property
+ DOMObject::tryPut( exec, propertyName, value, attr );
+ }
+}
+
+Value DOMCSSStyleDeclarationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSStyleDeclaration, thisObj );
+ DOM::CSSStyleDeclaration styleDecl = static_cast<DOMCSSStyleDeclaration *>(thisObj.imp())->toStyleDecl();
+ String str = args[0].toString(exec);
+ DOM::DOMString s = str.value().string();
+
+ switch (id) {
+ case DOMCSSStyleDeclaration::GetPropertyValue:
+ return String(styleDecl.getPropertyValue(s));
+ case DOMCSSStyleDeclaration::GetPropertyCSSValue:
+ return getDOMCSSValue(exec,styleDecl.getPropertyCSSValue(s));
+ case DOMCSSStyleDeclaration::RemoveProperty:
+ return String(styleDecl.removeProperty(s));
+ case DOMCSSStyleDeclaration::GetPropertyPriority:
+ return String(styleDecl.getPropertyPriority(s));
+ case DOMCSSStyleDeclaration::SetProperty:
+ styleDecl.setProperty(args[0].toString(exec).string(),
+ args[1].toString(exec).string(),
+ args[2].toString(exec).string());
+ return Undefined();
+ case DOMCSSStyleDeclaration::Item:
+ return String(styleDecl.item(args[0].toInteger(exec)));
+ default:
+ return Undefined();
+ }
+}
+
+Value getDOMCSSStyleDeclaration(ExecState *exec, const DOM::CSSStyleDeclaration& s)
+{
+ return cacheDOMObject<DOM::CSSStyleDeclaration, KJS::DOMCSSStyleDeclaration>(exec, s);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMStyleSheet::info = { "StyleSheet", 0, &DOMStyleSheetTable, 0 };
+/*
+@begin DOMStyleSheetTable 7
+ type DOMStyleSheet::Type DontDelete|ReadOnly
+ disabled DOMStyleSheet::Disabled DontDelete
+ ownerNode DOMStyleSheet::OwnerNode DontDelete|ReadOnly
+ parentStyleSheet DOMStyleSheet::ParentStyleSheet DontDelete|ReadOnly
+ href DOMStyleSheet::Href DontDelete|ReadOnly
+ title DOMStyleSheet::Title DontDelete|ReadOnly
+ media DOMStyleSheet::Media DontDelete|ReadOnly
+@end
+*/
+
+DOMStyleSheet::DOMStyleSheet(ExecState* exec, const DOM::StyleSheet& ss)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), styleSheet(ss)
+{
+}
+
+DOMStyleSheet::~DOMStyleSheet()
+{
+ ScriptInterpreter::forgetDOMObject(styleSheet.handle());
+}
+
+Value DOMStyleSheet::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<DOMStyleSheet,DOMObject>(exec,propertyName,&DOMStyleSheetTable,this);
+}
+
+Value DOMStyleSheet::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Type:
+ return String(styleSheet.type());
+ case Disabled:
+ return Boolean(styleSheet.disabled());
+ case OwnerNode:
+ return getDOMNode(exec,styleSheet.ownerNode());
+ case ParentStyleSheet:
+ return getDOMStyleSheet(exec,styleSheet.parentStyleSheet());
+ case Href:
+ return String(styleSheet.href());
+ case Title:
+ return String(styleSheet.title());
+ case Media:
+ return getDOMMediaList(exec, styleSheet.media());
+ }
+ return Value();
+}
+
+void DOMStyleSheet::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ if (propertyName == "disabled") {
+ styleSheet.setDisabled(value.toBoolean(exec));
+ }
+ else
+ DOMObject::tryPut(exec, propertyName, value, attr);
+}
+
+Value getDOMStyleSheet(ExecState *exec, const DOM::StyleSheet& ss)
+{
+ DOMObject *ret;
+ if (ss.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(ss.handle())))
+ return Value(ret);
+ else {
+ if (ss.isCSSStyleSheet()) {
+ DOM::CSSStyleSheet cs;
+ cs = ss;
+ ret = new DOMCSSStyleSheet(exec,cs);
+ }
+ else
+ ret = new DOMStyleSheet(exec,ss);
+ interp->putDOMObject(ss.handle(),ret);
+ return Value(ret);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMStyleSheetList::info = { "StyleSheetList", 0, &DOMStyleSheetListTable, 0 };
+
+/*
+@begin DOMStyleSheetListTable 2
+ length DOMStyleSheetList::Length DontDelete|ReadOnly
+ item DOMStyleSheetList::Item DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMStyleSheetListFunc) // not really a proto, but doesn't matter
+
+DOMStyleSheetList::DOMStyleSheetList(ExecState *exec, const DOM::StyleSheetList& ssl, const DOM::Document& doc)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), styleSheetList(ssl), m_doc(doc)
+{
+}
+
+DOMStyleSheetList::~DOMStyleSheetList()
+{
+ ScriptInterpreter::forgetDOMObject(styleSheetList.handle());
+}
+
+Value DOMStyleSheetList::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMStyleSheetList::tryGet " << p.qstring() << endl;
+#endif
+ if (p == lengthPropertyName)
+ return Number(styleSheetList.length());
+ else if (p == "item")
+ return lookupOrCreateFunction<DOMStyleSheetListFunc>(exec,p,this,DOMStyleSheetList::Item,1,DontDelete|Function);
+
+ // Retrieve stylesheet by index
+ bool ok;
+ long unsigned int u = p.toULong(&ok);
+ if (ok)
+ return getDOMStyleSheet(exec, DOM::StyleSheetList(styleSheetList).item(u));
+
+ // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag
+ // (this is consistent with all the other collections)
+#if 0
+ // Bad implementation because DOM::StyleSheet doesn't inherit DOM::Node
+ // so we can't use DOMNamedNodesCollection.....
+ // We could duplicate it for stylesheets though - worth it ?
+ // Other problem of this implementation: it doesn't look for the ID attribute!
+ DOM::NameNodeListImpl namedList( m_doc.documentElement().handle(), p.string() );
+ int len = namedList.length();
+ if ( len ) {
+ TQValueList<DOM::Node> styleSheets;
+ for ( int i = 0 ; i < len ; ++i ) {
+ DOM::HTMLStyleElement elem = DOM::Node(namedList.item(i));
+ if (!elem.isNull())
+ styleSheets.append(elem.sheet());
+ }
+ if ( styleSheets.count() == 1 ) // single result
+ return getDOMStyleSheet(exec, styleSheets[0]);
+ else if ( styleSheets.count() > 1 ) {
+ return new DOMNamedItemsCollection(exec,styleSheets);
+ }
+ }
+#endif
+ // ### Bad implementation because returns a single element (are IDs always unique?)
+ // and doesn't look for name attribute (see implementation above).
+ // But unicity of stylesheet ids is good practice anyway ;)
+ DOM::DOMString pstr = p.string();
+ DOM::HTMLStyleElement styleElem = m_doc.getElementById( pstr );
+ if (!styleElem.isNull())
+ return getDOMStyleSheet(exec, styleElem.sheet());
+
+ return DOMObject::tryGet(exec, p);
+}
+
+Value KJS::DOMStyleSheetList::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ // This code duplication is necessary, DOMStyleSheetList isn't a DOMFunction
+ Value val;
+ try {
+ val = tryCall(exec, thisObj, args);
+ }
+ // pity there's no way to distinguish between these in JS code
+ catch (...) {
+ Object err = Error::create(exec, GeneralError, "Exception from DOMStyleSheetList");
+ exec->setException(err);
+ }
+ return val;
+}
+
+Value DOMStyleSheetList::tryCall(ExecState *exec, Object & /*thisObj*/, const List &args)
+{
+ if (args.size() == 1) {
+ // support for styleSheets(<index>) and styleSheets(<name>)
+ return tryGet( exec, Identifier(args[0].toString(exec)) );
+ }
+ return Undefined();
+}
+
+Value getDOMStyleSheetList(ExecState *exec, const DOM::StyleSheetList& ssl, const DOM::Document& doc)
+{
+ // Can't use the cacheDOMObject macro because of the doc argument
+ DOMObject *ret;
+ if (ssl.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(ssl.handle())))
+ return Value(ret);
+ else {
+ ret = new DOMStyleSheetList(exec, ssl, doc);
+ interp->putDOMObject(ssl.handle(),ret);
+ return Value(ret);
+ }
+}
+
+Value DOMStyleSheetListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMStyleSheetList, thisObj );
+ DOM::StyleSheetList styleSheetList = static_cast<DOMStyleSheetList *>(thisObj.imp())->toStyleSheetList();
+ if (id == DOMStyleSheetList::Item)
+ return getDOMStyleSheet(exec, styleSheetList.item(args[0].toInteger(exec)));
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMMediaList::info = { "MediaList", 0, &DOMMediaListTable, 0 };
+
+/*
+@begin DOMMediaListTable 2
+ mediaText DOMMediaList::MediaText DontDelete|ReadOnly
+ length DOMMediaList::Length DontDelete|ReadOnly
+@end
+@begin DOMMediaListProtoTable 3
+ item DOMMediaList::Item DontDelete|Function 1
+ deleteMedium DOMMediaList::DeleteMedium DontDelete|Function 1
+ appendMedium DOMMediaList::AppendMedium DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMMediaListProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMMediaListProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMMediaList", DOMMediaListProto, DOMMediaListProtoFunc)
+
+DOMMediaList::DOMMediaList(ExecState *exec, const DOM::MediaList& ml)
+ : DOMObject(DOMMediaListProto::self(exec)), mediaList(ml) { }
+
+DOMMediaList::~DOMMediaList()
+{
+ ScriptInterpreter::forgetDOMObject(mediaList.handle());
+}
+
+Value DOMMediaList::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if (p == "mediaText")
+ return String(mediaList.mediaText());
+ else if (p == lengthPropertyName)
+ return Number(mediaList.length());
+
+ bool ok;
+ long unsigned int u = p.toULong(&ok);
+ if (ok)
+ return String(mediaList.item(u));
+
+ return DOMObject::tryGet(exec, p);
+}
+
+void DOMMediaList::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ if (propertyName == "mediaText")
+ mediaList.setMediaText(value.toString(exec).string());
+ else
+ DOMObject::tryPut(exec, propertyName, value, attr);
+}
+
+Value getDOMMediaList(ExecState *exec, const DOM::MediaList& ml)
+{
+ return cacheDOMObject<DOM::MediaList, KJS::DOMMediaList>(exec, ml);
+}
+
+Value KJS::DOMMediaListProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMMediaList, thisObj );
+ DOM::MediaList mediaList = static_cast<DOMMediaList *>(thisObj.imp())->toMediaList();
+ switch (id) {
+ case DOMMediaList::Item:
+ return String(mediaList.item(args[0].toInteger(exec)));
+ case DOMMediaList::DeleteMedium:
+ mediaList.deleteMedium(args[0].toString(exec).string());
+ return Undefined();
+ case DOMMediaList::AppendMedium:
+ mediaList.appendMedium(args[0].toString(exec).string());
+ return Undefined();
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCSSStyleSheet::info = { "CSSStyleSheet", 0, &DOMCSSStyleSheetTable, 0 };
+
+/*
+@begin DOMCSSStyleSheetTable 2
+ ownerRule DOMCSSStyleSheet::OwnerRule DontDelete|ReadOnly
+ cssRules DOMCSSStyleSheet::CssRules DontDelete|ReadOnly
+# MSIE extension
+ rules DOMCSSStyleSheet::Rules DontDelete|ReadOnly
+@end
+@begin DOMCSSStyleSheetProtoTable 2
+ insertRule DOMCSSStyleSheet::InsertRule DontDelete|Function 2
+ deleteRule DOMCSSStyleSheet::DeleteRule DontDelete|Function 1
+# IE extensions
+ addRule DOMCSSStyleSheet::AddRule DontDelete|Function 3
+ removeRule DOMCSSStyleSheet::RemoveRule DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMCSSStyleSheetProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSStyleSheetProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMCSSStyleSheet",DOMCSSStyleSheetProto,DOMCSSStyleSheetProtoFunc) // warning, use _WITH_PARENT if DOMStyleSheet gets a proto
+
+DOMCSSStyleSheet::DOMCSSStyleSheet(ExecState *exec, const DOM::CSSStyleSheet& ss)
+ : DOMStyleSheet(DOMCSSStyleSheetProto::self(exec),ss) { }
+
+DOMCSSStyleSheet::~DOMCSSStyleSheet()
+{
+}
+
+Value DOMCSSStyleSheet::tryGet(ExecState *exec, const Identifier &p) const
+{
+ DOM::CSSStyleSheet cssStyleSheet = static_cast<DOM::CSSStyleSheet>(styleSheet);
+ if (p == "ownerRule")
+ return getDOMCSSRule(exec,cssStyleSheet.ownerRule());
+ else if (p == "cssRules" || p == "rules" /* MSIE extension */)
+ return getDOMCSSRuleList(exec,cssStyleSheet.cssRules());
+ return DOMStyleSheet::tryGet(exec,p);
+}
+
+Value DOMCSSStyleSheetProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSStyleSheet, thisObj );
+ DOM::CSSStyleSheet styleSheet = static_cast<DOMCSSStyleSheet *>(thisObj.imp())->toCSSStyleSheet();
+
+ switch (id) {
+ case DOMCSSStyleSheet::InsertRule:
+ return Number(styleSheet.insertRule(args[0].toString(exec).string(),(long unsigned int)args[1].toInteger(exec)));
+ case DOMCSSStyleSheet::DeleteRule:
+ styleSheet.deleteRule(args[0].toInteger(exec));
+ return Undefined();
+ // IE extensions
+ case DOMCSSStyleSheet::AddRule: {
+ //Unpassed/-1 means append. Since insertRule is picky (throws exceptions)
+ //we adjust it to the desired length
+ unsigned long index = args[2].toInteger(exec);
+ unsigned long length = styleSheet.cssRules().length();
+ if (args[2].type() == UndefinedType) index = length;
+ if (index > length) index = length;
+ DOM::DOMString str = args[0].toString(exec).string() + " { " + args[1].toString(exec).string() + " } ";
+ return Number(styleSheet.insertRule(str,index));
+ }
+ case DOMCSSStyleSheet::RemoveRule: {
+ int index = args.size() > 0 ? args[0].toInteger(exec) : 0 /*first one*/;
+ styleSheet.deleteRule(index);
+ return Undefined();
+ }
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCSSRuleList::info = { "CSSRuleList", 0, &DOMCSSRuleListTable, 0 };
+/*
+@begin DOMCSSRuleListTable 3
+ length DOMCSSRuleList::Length DontDelete|ReadOnly
+ item DOMCSSRuleList::Item DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSRuleListFunc) // not really a proto, but doesn't matter
+
+DOMCSSRuleList::DOMCSSRuleList(ExecState* exec, const DOM::CSSRuleList& rl)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), cssRuleList(rl)
+{
+}
+
+DOMCSSRuleList::~DOMCSSRuleList()
+{
+ ScriptInterpreter::forgetDOMObject(cssRuleList.handle());
+}
+
+Value DOMCSSRuleList::tryGet(ExecState *exec, const Identifier &p) const
+{
+ Value result;
+ if (p == lengthPropertyName)
+ return Number(cssRuleList.length());
+ else if (p == "item")
+ return lookupOrCreateFunction<DOMCSSRuleListFunc>(exec,p,this,DOMCSSRuleList::Item,1,DontDelete|Function);
+
+ bool ok;
+ long unsigned int u = p.toULong(&ok);
+ if (ok)
+ return getDOMCSSRule(exec,DOM::CSSRuleList(cssRuleList).item(u));
+
+ return DOMObject::tryGet(exec,p);
+}
+
+Value DOMCSSRuleListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSRuleList, thisObj );
+ DOM::CSSRuleList cssRuleList = static_cast<DOMCSSRuleList *>(thisObj.imp())->toCSSRuleList();
+ switch (id) {
+ case DOMCSSRuleList::Item:
+ return getDOMCSSRule(exec,cssRuleList.item(args[0].toInteger(exec)));
+ default:
+ return Undefined();
+ }
+}
+
+Value getDOMCSSRuleList(ExecState *exec, const DOM::CSSRuleList& rl)
+{
+ return cacheDOMObject<DOM::CSSRuleList, KJS::DOMCSSRuleList>(exec, rl);
+}
+
+// -------------------------------------------------------------------------
+
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSRuleFunc) // Not a proto, but doesn't matter
+
+DOMCSSRule::DOMCSSRule(ExecState* exec, const DOM::CSSRule& r)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), cssRule(r)
+{
+}
+
+DOMCSSRule::~DOMCSSRule()
+{
+ ScriptInterpreter::forgetDOMObject(cssRule.handle());
+}
+
+const ClassInfo DOMCSSRule::info = { "CSSRule", 0, &DOMCSSRuleTable, 0 };
+const ClassInfo DOMCSSRule::style_info = { "CSSStyleRule", &DOMCSSRule::info, &DOMCSSStyleRuleTable, 0 };
+const ClassInfo DOMCSSRule::media_info = { "CSSMediaRule", &DOMCSSRule::info, &DOMCSSMediaRuleTable, 0 };
+const ClassInfo DOMCSSRule::fontface_info = { "CSSFontFaceRule", &DOMCSSRule::info, &DOMCSSFontFaceRuleTable, 0 };
+const ClassInfo DOMCSSRule::page_info = { "CSSPageRule", &DOMCSSRule::info, &DOMCSSPageRuleTable, 0 };
+const ClassInfo DOMCSSRule::import_info = { "CSSImportRule", &DOMCSSRule::info, &DOMCSSImportRuleTable, 0 };
+const ClassInfo DOMCSSRule::charset_info = { "CSSCharsetRule", &DOMCSSRule::info, &DOMCSSCharsetRuleTable, 0 };
+
+const ClassInfo* DOMCSSRule::classInfo() const
+{
+ switch (cssRule.type()) {
+ case DOM::CSSRule::STYLE_RULE:
+ return &style_info;
+ case DOM::CSSRule::MEDIA_RULE:
+ return &media_info;
+ case DOM::CSSRule::FONT_FACE_RULE:
+ return &fontface_info;
+ case DOM::CSSRule::PAGE_RULE:
+ return &page_info;
+ case DOM::CSSRule::IMPORT_RULE:
+ return &import_info;
+ case DOM::CSSRule::CHARSET_RULE:
+ return &charset_info;
+ case DOM::CSSRule::UNKNOWN_RULE:
+ default:
+ return &info;
+ }
+}
+/*
+@begin DOMCSSRuleTable 4
+ type DOMCSSRule::Type DontDelete|ReadOnly
+ cssText DOMCSSRule::CssText DontDelete|ReadOnly
+ parentStyleSheet DOMCSSRule::ParentStyleSheet DontDelete|ReadOnly
+ parentRule DOMCSSRule::ParentRule DontDelete|ReadOnly
+@end
+@begin DOMCSSStyleRuleTable 2
+ selectorText DOMCSSRule::Style_SelectorText DontDelete
+ style DOMCSSRule::Style_Style DontDelete|ReadOnly
+@end
+@begin DOMCSSMediaRuleTable 4
+ media DOMCSSRule::Media_Media DontDelete|ReadOnly
+ cssRules DOMCSSRule::Media_CssRules DontDelete|ReadOnly
+ insertRule DOMCSSRule::Media_InsertRule DontDelete|Function 2
+ deleteRule DOMCSSRule::Media_DeleteRule DontDelete|Function 1
+@end
+@begin DOMCSSFontFaceRuleTable 1
+ style DOMCSSRule::FontFace_Style DontDelete|ReadOnly
+@end
+@begin DOMCSSPageRuleTable 2
+ selectorText DOMCSSRule::Page_SelectorText DontDelete
+ style DOMCSSRule::Page_Style DontDelete|ReadOnly
+@end
+@begin DOMCSSImportRuleTable 3
+ href DOMCSSRule::Import_Href DontDelete|ReadOnly
+ media DOMCSSRule::Import_Media DontDelete|ReadOnly
+ styleSheet DOMCSSRule::Import_StyleSheet DontDelete|ReadOnly
+@end
+@begin DOMCSSCharsetRuleTable 1
+ encoding DOMCSSRule::Charset_Encoding DontDelete
+@end
+*/
+Value DOMCSSRule::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMCSSRule::tryGet " << propertyName.qstring() << endl;
+#endif
+ const HashTable* table = classInfo()->propHashTable; // get the right hashtable
+ const HashEntry* entry = Lookup::findEntry(table, propertyName);
+ if (entry) {
+ if (entry->attr & Function)
+ return lookupOrCreateFunction<DOMCSSRuleFunc>(exec, propertyName, this, entry->value, entry->params, entry->attr);
+ return getValueProperty(exec, entry->value);
+ }
+
+ // Base CSSRule stuff or parent class forward, as usual
+ return DOMObjectLookupGet<DOMCSSRuleFunc, DOMCSSRule, DOMObject>(exec, propertyName, &DOMCSSRuleTable, this);
+}
+
+Value DOMCSSRule::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Type:
+ return Number(cssRule.type());
+ case CssText:
+ return String(cssRule.cssText());
+ case ParentStyleSheet:
+ return getDOMStyleSheet(exec,cssRule.parentStyleSheet());
+ case ParentRule:
+ return getDOMCSSRule(exec,cssRule.parentRule());
+
+ // for DOM::CSSRule::STYLE_RULE:
+ case Style_SelectorText:
+ return String(static_cast<DOM::CSSStyleRule>(cssRule).selectorText());
+ case Style_Style:
+ return getDOMCSSStyleDeclaration(exec,static_cast<DOM::CSSStyleRule>(cssRule).style());
+
+ // for DOM::CSSRule::MEDIA_RULE:
+ case Media_Media:
+ return getDOMMediaList(exec,static_cast<DOM::CSSMediaRule>(cssRule).media());
+ case Media_CssRules:
+ return getDOMCSSRuleList(exec,static_cast<DOM::CSSMediaRule>(cssRule).cssRules());
+
+ // for DOM::CSSRule::FONT_FACE_RULE:
+ case FontFace_Style:
+ return getDOMCSSStyleDeclaration(exec,static_cast<DOM::CSSFontFaceRule>(cssRule).style());
+
+ // for DOM::CSSRule::PAGE_RULE:
+ case Page_SelectorText:
+ return String(static_cast<DOM::CSSPageRule>(cssRule).selectorText());
+ case Page_Style:
+ return getDOMCSSStyleDeclaration(exec,static_cast<DOM::CSSPageRule>(cssRule).style());
+
+ // for DOM::CSSRule::IMPORT_RULE:
+ case Import_Href:
+ return String(static_cast<DOM::CSSImportRule>(cssRule).href());
+ case Import_Media:
+ return getDOMMediaList(exec,static_cast<DOM::CSSImportRule>(cssRule).media());
+ case Import_StyleSheet:
+ return getDOMStyleSheet(exec,static_cast<DOM::CSSImportRule>(cssRule).styleSheet());
+
+ // for DOM::CSSRule::CHARSET_RULE:
+ case Charset_Encoding:
+ return String(static_cast<DOM::CSSCharsetRule>(cssRule).encoding());
+
+ default:
+ kdDebug(6070) << "WARNING: DOMCSSRule::getValueProperty unhandled token " << token << endl;
+ }
+ return Undefined();
+}
+
+void DOMCSSRule::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ const HashTable* table = classInfo()->propHashTable; // get the right hashtable
+ const HashEntry* entry = Lookup::findEntry(table, propertyName);
+ if (entry) {
+ if (entry->attr & Function) // function: put as override property
+ {
+ ObjectImp::put(exec, propertyName, value, attr);
+ return;
+ }
+ else if ((entry->attr & ReadOnly) == 0) // let DOMObjectLookupPut print the warning if not
+ {
+ putValueProperty(exec, entry->value, value, attr);
+ return;
+ }
+ }
+ DOMObjectLookupPut<DOMCSSRule, DOMObject>(exec, propertyName, value, attr, &DOMCSSRuleTable, this);
+}
+
+void DOMCSSRule::putValueProperty(ExecState *exec, int token, const Value& value, int)
+{
+ switch (token) {
+ // for DOM::CSSRule::STYLE_RULE:
+ case Style_SelectorText:
+ static_cast<DOM::CSSStyleRule>(cssRule).setSelectorText(value.toString(exec).string());
+ return;
+
+ // for DOM::CSSRule::PAGE_RULE:
+ case Page_SelectorText:
+ static_cast<DOM::CSSPageRule>(cssRule).setSelectorText(value.toString(exec).string());
+ return;
+
+ // for DOM::CSSRule::CHARSET_RULE:
+ case Charset_Encoding:
+ static_cast<DOM::CSSCharsetRule>(cssRule).setEncoding(value.toString(exec).string());
+ return;
+
+ default:
+ kdDebug(6070) << "WARNING: DOMCSSRule::putValueProperty unhandled token " << token << endl;
+ }
+}
+
+Value DOMCSSRuleFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSRule, thisObj );
+ DOM::CSSRule cssRule = static_cast<DOMCSSRule *>(thisObj.imp())->toCSSRule();
+
+ if (cssRule.type() == DOM::CSSRule::MEDIA_RULE) {
+ DOM::CSSMediaRule rule = static_cast<DOM::CSSMediaRule>(cssRule);
+ if (id == DOMCSSRule::Media_InsertRule)
+ return Number(rule.insertRule(args[0].toString(exec).string(),args[1].toInteger(exec)));
+ else if (id == DOMCSSRule::Media_DeleteRule)
+ rule.deleteRule(args[0].toInteger(exec));
+ }
+
+ return Undefined();
+}
+
+Value getDOMCSSRule(ExecState *exec, const DOM::CSSRule& r)
+{
+ return cacheDOMObject<DOM::CSSRule, KJS::DOMCSSRule>(exec, r);
+}
+
+// -------------------------------------------------------------------------
+
+
+DOM::CSSRule toCSSRule(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMCSSRule::info))
+ return DOM::CSSRule();
+
+ const DOMCSSRule *dobj = static_cast<const DOMCSSRule*>(obj.imp());
+ return dobj->toCSSRule();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo CSSRuleConstructor::info = { "CSSRuleConstructor", 0, &CSSRuleConstructorTable, 0 };
+/*
+@begin CSSRuleConstructorTable 7
+ UNKNOWN_RULE CSSRuleConstructor::UNKNOWN_RULE DontDelete|ReadOnly
+ STYLE_RULE CSSRuleConstructor::STYLE_RULE DontDelete|ReadOnly
+ CHARSET_RULE CSSRuleConstructor::CHARSET_RULE DontDelete|ReadOnly
+ IMPORT_RULE CSSRuleConstructor::IMPORT_RULE DontDelete|ReadOnly
+ MEDIA_RULE CSSRuleConstructor::MEDIA_RULE DontDelete|ReadOnly
+ FONT_FACE_RULE CSSRuleConstructor::FONT_FACE_RULE DontDelete|ReadOnly
+ PAGE_RULE CSSRuleConstructor::PAGE_RULE DontDelete|ReadOnly
+@end
+*/
+
+CSSRuleConstructor::CSSRuleConstructor(ExecState *exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value CSSRuleConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<CSSRuleConstructor,DOMObject>(exec,p,&CSSRuleConstructorTable,this);
+}
+
+Value CSSRuleConstructor::getValueProperty(ExecState *, int token) const
+{
+ switch (token) {
+ case UNKNOWN_RULE:
+ return Number(DOM::CSSRule::UNKNOWN_RULE);
+ case STYLE_RULE:
+ return Number(DOM::CSSRule::STYLE_RULE);
+ case CHARSET_RULE:
+ return Number(DOM::CSSRule::CHARSET_RULE);
+ case IMPORT_RULE:
+ return Number(DOM::CSSRule::IMPORT_RULE);
+ case MEDIA_RULE:
+ return Number(DOM::CSSRule::MEDIA_RULE);
+ case FONT_FACE_RULE:
+ return Number(DOM::CSSRule::FONT_FACE_RULE);
+ case PAGE_RULE:
+ return Number(DOM::CSSRule::PAGE_RULE);
+ }
+ return Value();
+}
+
+Value getCSSRuleConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<CSSRuleConstructor>( exec, "[[cssRule.constructor]]" );
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCSSValue::info = { "CSSValue", 0, &DOMCSSValueTable, 0 };
+
+/*
+@begin DOMCSSValueTable 2
+ cssText DOMCSSValue::CssText DontDelete|ReadOnly
+ cssValueType DOMCSSValue::CssValueType DontDelete|ReadOnly
+@end
+*/
+
+DOMCSSValue::DOMCSSValue(ExecState* exec, const DOM::CSSValue& val)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), cssValue(val)
+{
+}
+
+DOMCSSValue::~DOMCSSValue()
+{
+ ScriptInterpreter::forgetDOMObject(cssValue.handle());
+}
+
+Value DOMCSSValue::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if (p == "cssText")
+ return String(cssValue.cssText());
+ else if (p == "cssValueType")
+ return Number(cssValue.cssValueType());
+ return DOMObject::tryGet(exec,p);
+}
+
+void DOMCSSValue::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ if (propertyName == "cssText")
+ cssValue.setCssText(value.toString(exec).string());
+ else
+ DOMObject::tryPut(exec, propertyName, value, attr);
+}
+
+Value getDOMCSSValue(ExecState *exec, const DOM::CSSValue& v)
+{
+ DOMObject *ret;
+ if (v.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(v.handle())))
+ return Value(ret);
+ else {
+ if (v.isCSSValueList())
+ ret = new DOMCSSValueList(exec,v);
+ else if (v.isCSSPrimitiveValue())
+ ret = new DOMCSSPrimitiveValue(exec,v);
+ else
+ ret = new DOMCSSValue(exec,v);
+ interp->putDOMObject(v.handle(),ret);
+ return Value(ret);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo CSSValueConstructor::info = { "CSSValueConstructor", 0, &CSSValueConstructorTable, 0 };
+/*
+@begin CSSValueConstructorTable 5
+ CSS_INHERIT CSSValueConstructor::CSS_INHERIT DontDelete|ReadOnly
+ CSS_PRIMITIVE_VALUE CSSValueConstructor::CSS_PRIMITIVE_VALUE DontDelete|ReadOnly
+ CSS_VALUE_LIST CSSValueConstructor::CSS_VALUE_LIST DontDelete|ReadOnly
+ CSS_CUSTOM CSSValueConstructor::CSS_CUSTOM DontDelete|ReadOnly
+@end
+*/
+
+CSSValueConstructor::CSSValueConstructor(ExecState *exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value CSSValueConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<CSSValueConstructor,DOMObject>(exec,p,&CSSValueConstructorTable,this);
+}
+
+Value CSSValueConstructor::getValueProperty(ExecState *, int token) const
+{
+ switch (token) {
+ case CSS_INHERIT:
+ return Number(DOM::CSSValue::CSS_INHERIT);
+ case CSS_PRIMITIVE_VALUE:
+ return Number(DOM::CSSValue::CSS_PRIMITIVE_VALUE);
+ case CSS_VALUE_LIST:
+ return Number(DOM::CSSValue::CSS_VALUE_LIST);
+ case CSS_CUSTOM:
+ return Number(DOM::CSSValue::CSS_CUSTOM);
+ }
+ return Value();
+}
+
+Value getCSSValueConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<CSSValueConstructor>( exec, "[[cssValue.constructor]]" );
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCSSPrimitiveValue::info = { "CSSPrimitiveValue", 0, &DOMCSSPrimitiveValueTable, 0 };
+/*
+@begin DOMCSSPrimitiveValueTable 1
+ primitiveType DOMCSSPrimitiveValue::PrimitiveType DontDelete|ReadOnly
+@end
+@begin DOMCSSPrimitiveValueProtoTable 3
+ setFloatValue DOMCSSPrimitiveValue::SetFloatValue DontDelete|Function 2
+ getFloatValue DOMCSSPrimitiveValue::GetFloatValue DontDelete|Function 1
+ setStringValue DOMCSSPrimitiveValue::SetStringValue DontDelete|Function 2
+ getStringValue DOMCSSPrimitiveValue::GetStringValue DontDelete|Function 0
+ getCounterValue DOMCSSPrimitiveValue::GetCounterValue DontDelete|Function 0
+ getRectValue DOMCSSPrimitiveValue::GetRectValue DontDelete|Function 0
+ getRGBColorValue DOMCSSPrimitiveValue::GetRGBColorValue DontDelete|Function 0
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMCSSPrimitiveValueProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSPrimitiveValueProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMCSSPrimitiveValue",DOMCSSPrimitiveValueProto,DOMCSSPrimitiveValueProtoFunc)
+
+DOMCSSPrimitiveValue::DOMCSSPrimitiveValue(ExecState *exec, const DOM::CSSPrimitiveValue& v)
+ : DOMCSSValue(DOMCSSPrimitiveValueProto::self(exec), v) { }
+
+Value DOMCSSPrimitiveValue::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if (p=="primitiveType")
+ return Number(static_cast<DOM::CSSPrimitiveValue>(cssValue).primitiveType());
+ return DOMObject::tryGet(exec,p);
+}
+
+Value DOMCSSPrimitiveValueProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSPrimitiveValue, thisObj );
+ DOM::CSSPrimitiveValue val = static_cast<DOMCSSPrimitiveValue *>(thisObj.imp())->toCSSPrimitiveValue();
+ switch (id) {
+ case DOMCSSPrimitiveValue::SetFloatValue:
+ val.setFloatValue(args[0].toInteger(exec),args[1].toNumber(exec));
+ return Undefined();
+ case DOMCSSPrimitiveValue::GetFloatValue:
+ return Number(val.getFloatValue(args[0].toInteger(exec)));
+ case DOMCSSPrimitiveValue::SetStringValue:
+ val.setStringValue(args[0].toInteger(exec),args[1].toString(exec).string());
+ return Undefined();
+ case DOMCSSPrimitiveValue::GetStringValue:
+ return String(val.getStringValue());
+ case DOMCSSPrimitiveValue::GetCounterValue:
+ return getDOMCounter(exec,val.getCounterValue());
+ case DOMCSSPrimitiveValue::GetRectValue:
+ return getDOMRect(exec,val.getRectValue());
+ case DOMCSSPrimitiveValue::GetRGBColorValue:
+ return getDOMRGBColor(exec,val.getRGBColorValue());
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo CSSPrimitiveValueConstructor::info = { "CSSPrimitiveValueConstructor", 0, &CSSPrimitiveValueConstructorTable, 0 };
+
+/*
+@begin CSSPrimitiveValueConstructorTable 27
+ CSS_UNKNOWN DOM::CSSPrimitiveValue::CSS_UNKNOWN DontDelete|ReadOnly
+ CSS_NUMBER DOM::CSSPrimitiveValue::CSS_NUMBER DontDelete|ReadOnly
+ CSS_PERCENTAGE DOM::CSSPrimitiveValue::CSS_PERCENTAGE DontDelete|ReadOnly
+ CSS_EMS DOM::CSSPrimitiveValue::CSS_EMS DontDelete|ReadOnly
+ CSS_EXS DOM::CSSPrimitiveValue::CSS_EXS DontDelete|ReadOnly
+ CSS_PX DOM::CSSPrimitiveValue::CSS_PX DontDelete|ReadOnly
+ CSS_CM DOM::CSSPrimitiveValue::CSS_CM DontDelete|ReadOnly
+ CSS_MM DOM::CSSPrimitiveValue::CSS_MM DontDelete|ReadOnly
+ CSS_IN DOM::CSSPrimitiveValue::CSS_IN DontDelete|ReadOnly
+ CSS_PT DOM::CSSPrimitiveValue::CSS_PT DontDelete|ReadOnly
+ CSS_PC DOM::CSSPrimitiveValue::CSS_PC DontDelete|ReadOnly
+ CSS_DEG DOM::CSSPrimitiveValue::CSS_DEG DontDelete|ReadOnly
+ CSS_RAD DOM::CSSPrimitiveValue::CSS_RAD DontDelete|ReadOnly
+ CSS_GRAD DOM::CSSPrimitiveValue::CSS_GRAD DontDelete|ReadOnly
+ CSS_MS DOM::CSSPrimitiveValue::CSS_MS DontDelete|ReadOnly
+ CSS_S DOM::CSSPrimitiveValue::CSS_S DontDelete|ReadOnly
+ CSS_HZ DOM::CSSPrimitiveValue::CSS_HZ DontDelete|ReadOnly
+ CSS_KHZ DOM::CSSPrimitiveValue::CSS_KHZ DontDelete|ReadOnly
+ CSS_DIMENSION DOM::CSSPrimitiveValue::CSS_DIMENSION DontDelete|ReadOnly
+ CSS_STRING DOM::CSSPrimitiveValue::CSS_STRING DontDelete|ReadOnly
+ CSS_URI DOM::CSSPrimitiveValue::CSS_URI DontDelete|ReadOnly
+ CSS_IDENT DOM::CSSPrimitiveValue::CSS_IDENT DontDelete|ReadOnly
+ CSS_ATTR DOM::CSSPrimitiveValue::CSS_ATTR DontDelete|ReadOnly
+ CSS_COUNTER DOM::CSSPrimitiveValue::CSS_COUNTER DontDelete|ReadOnly
+ CSS_RECT DOM::CSSPrimitiveValue::CSS_RECT DontDelete|ReadOnly
+ CSS_RGBCOLOR DOM::CSSPrimitiveValue::CSS_RGBCOLOR DontDelete|ReadOnly
+@end
+*/
+
+Value CSSPrimitiveValueConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<CSSPrimitiveValueConstructor,CSSValueConstructor>(exec,p,&CSSPrimitiveValueConstructorTable,this);
+}
+
+Value CSSPrimitiveValueConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getCSSPrimitiveValueConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<CSSPrimitiveValueConstructor>( exec, "[[cssPrimitiveValue.constructor]]" );
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCSSValueList::info = { "CSSValueList", 0, &DOMCSSValueListTable, 0 };
+
+/*
+@begin DOMCSSValueListTable 3
+ length DOMCSSValueList::Length DontDelete|ReadOnly
+ item DOMCSSValueList::Item DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMCSSValueListFunc) // not really a proto, but doesn't matter
+
+DOMCSSValueList::DOMCSSValueList(ExecState *exec, const DOM::CSSValueList& v)
+ : DOMCSSValue(exec, v) { }
+
+Value DOMCSSValueList::tryGet(ExecState *exec, const Identifier &p) const
+{
+ Value result;
+ DOM::CSSValueList valueList = static_cast<DOM::CSSValueList>(cssValue);
+
+ if (p == lengthPropertyName)
+ return Number(valueList.length());
+ else if (p == "item")
+ return lookupOrCreateFunction<DOMCSSValueListFunc>(exec,p,this,DOMCSSValueList::Item,1,DontDelete|Function);
+
+ bool ok;
+ long unsigned int u = p.toULong(&ok);
+ if (ok)
+ return getDOMCSSValue(exec,valueList.item(u));
+
+ return DOMCSSValue::tryGet(exec,p);
+}
+
+Value DOMCSSValueListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCSSValueList, thisObj );
+ DOM::CSSValueList valueList = static_cast<DOMCSSValueList *>(thisObj.imp())->toValueList();
+ switch (id) {
+ case DOMCSSValueList::Item:
+ return getDOMCSSValue(exec,valueList.item(args[0].toInteger(exec)));
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMRGBColor::info = { "RGBColor", 0, &DOMRGBColorTable, 0 };
+
+/*
+@begin DOMRGBColorTable 3
+ red DOMRGBColor::Red DontDelete|ReadOnly
+ green DOMRGBColor::Green DontDelete|ReadOnly
+ blue DOMRGBColor::Blue DontDelete|ReadOnly
+@end
+*/
+
+DOMRGBColor::DOMRGBColor(ExecState* exec, const DOM::RGBColor& c)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), rgbColor(c)
+{
+}
+
+DOMRGBColor::~DOMRGBColor()
+{
+ //rgbColors.remove(rgbColor.handle());
+}
+
+Value DOMRGBColor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMRGBColor,DOMObject>(exec, p,
+ &DOMRGBColorTable,
+ this);
+}
+
+Value DOMRGBColor::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Red:
+ return getDOMCSSValue(exec, rgbColor.red());
+ case Green:
+ return getDOMCSSValue(exec, rgbColor.green());
+ case Blue:
+ return getDOMCSSValue(exec, rgbColor.blue());
+ default:
+ return Value();
+ }
+}
+
+Value getDOMRGBColor(ExecState *exec, const DOM::RGBColor& c)
+{
+ // ### implement equals for RGBColor since they're not refcounted objects
+ return Value(new DOMRGBColor(exec, c));
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMRect::info = { "Rect", 0, &DOMRectTable, 0 };
+/*
+@begin DOMRectTable 4
+ top DOMRect::Top DontDelete|ReadOnly
+ right DOMRect::Right DontDelete|ReadOnly
+ bottom DOMRect::Bottom DontDelete|ReadOnly
+ left DOMRect::Left DontDelete|ReadOnly
+@end
+*/
+
+DOMRect::DOMRect(ExecState *exec, const DOM::Rect& r)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), rect(r)
+{
+}
+
+DOMRect::~DOMRect()
+{
+ ScriptInterpreter::forgetDOMObject(rect.handle());
+}
+
+Value DOMRect::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMRect,DOMObject>(exec, p,
+ &DOMRectTable, this);
+}
+
+Value DOMRect::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Top:
+ return getDOMCSSValue(exec, rect.top());
+ case Right:
+ return getDOMCSSValue(exec, rect.right());
+ case Bottom:
+ return getDOMCSSValue(exec, rect.bottom());
+ case Left:
+ return getDOMCSSValue(exec, rect.left());
+ default:
+ return Value();
+ }
+}
+
+Value getDOMRect(ExecState *exec, const DOM::Rect& r)
+{
+ return cacheDOMObject<DOM::Rect, KJS::DOMRect>(exec, r);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCounter::info = { "Counter", 0, &DOMCounterTable, 0 };
+/*
+@begin DOMCounterTable 3
+ identifier DOMCounter::identifier DontDelete|ReadOnly
+ listStyle DOMCounter::listStyle DontDelete|ReadOnly
+ separator DOMCounter::separator DontDelete|ReadOnly
+@end
+*/
+DOMCounter::DOMCounter(ExecState *exec, const DOM::Counter& c)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), counter(c)
+{
+}
+
+DOMCounter::~DOMCounter()
+{
+ ScriptInterpreter::forgetDOMObject(counter.handle());
+}
+
+Value DOMCounter::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMCounter,DOMObject>(exec, p,
+ &DOMCounterTable, this);
+}
+
+Value DOMCounter::getValueProperty(ExecState *, int token) const
+{
+ switch (token) {
+ case identifier:
+ return String(counter.identifier());
+ case listStyle:
+ return String(counter.listStyle());
+ case separator:
+ return String(counter.separator());
+ default:
+ return Value();
+ }
+}
+
+Value getDOMCounter(ExecState *exec, const DOM::Counter& c)
+{
+ return cacheDOMObject<DOM::Counter, KJS::DOMCounter>(exec, c);
+}
+
+} //namespace KJS
diff --git a/tdehtml/ecma/kjs_css.h b/tdehtml/ecma/kjs_css.h
new file mode 100644
index 000000000..2b7d14712
--- /dev/null
+++ b/tdehtml/ecma/kjs_css.h
@@ -0,0 +1,304 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_CSS_H_
+#define _KJS_CSS_H_
+
+#include <dom/dom_node.h>
+#include <dom/dom_doc.h>
+#include <kjs/object.h>
+#include <dom/css_value.h>
+#include <dom/css_stylesheet.h>
+#include <dom/css_rule.h>
+#include "kjs_binding.h"
+
+namespace KJS {
+
+ class DOMCSSStyleDeclaration : public DOMObject {
+ public:
+ DOMCSSStyleDeclaration(ExecState *exec, const DOM::CSSStyleDeclaration& s);
+ virtual ~DOMCSSStyleDeclaration();
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo *classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { CssText, Length, ParentRule,
+ GetPropertyValue, GetPropertyCSSValue, RemoveProperty, GetPropertyPriority,
+ SetProperty, Item };
+ DOM::CSSStyleDeclaration toStyleDecl() const { return styleDecl; }
+ protected:
+ DOM::CSSStyleDeclaration styleDecl;
+ };
+
+ DEFINE_PSEUDO_CONSTRUCTOR(CSSStyleDeclarationPseudoCtor)
+
+ Value getDOMCSSStyleDeclaration(ExecState *exec, const DOM::CSSStyleDeclaration& n);
+
+ class DOMStyleSheet : public DOMObject {
+ public:
+ // Build a DOMStyleSheet
+ DOMStyleSheet(ExecState *, const DOM::StyleSheet& ss);
+ // Constructor for inherited classes
+ DOMStyleSheet(const Object& proto, const DOM::StyleSheet& ss) : DOMObject(proto), styleSheet(ss) { }
+ virtual ~DOMStyleSheet();
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual bool toBoolean(ExecState *) const { return true; }
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Type, Disabled, OwnerNode, ParentStyleSheet, Href, Title, Media };
+ protected:
+ DOM::StyleSheet styleSheet;
+ };
+
+ Value getDOMStyleSheet(ExecState *exec, const DOM::StyleSheet& ss);
+
+ class DOMStyleSheetList : public DOMObject {
+ public:
+ DOMStyleSheetList(ExecState *, const DOM::StyleSheetList& ssl, const DOM::Document& doc);
+ virtual ~DOMStyleSheetList();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+ Value tryCall(ExecState *exec, Object &thisObj, const List &args);
+ virtual bool implementsCall() const { return true; }
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ virtual bool toBoolean(ExecState* ) const { return true; }
+ static const ClassInfo info;
+ DOM::StyleSheetList toStyleSheetList() const { return styleSheetList; }
+ enum { Item, Length };
+ private:
+ DOM::StyleSheetList styleSheetList;
+ DOM::Document m_doc;
+ };
+
+ // The document is only used for get-stylesheet-by-name (make optional if necessary)
+ Value getDOMStyleSheetList(ExecState *exec, const DOM::StyleSheetList& ss, const DOM::Document& doc);
+
+ class DOMMediaList : public DOMObject {
+ public:
+ DOMMediaList(ExecState *, const DOM::MediaList& ml);
+ virtual ~DOMMediaList();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ virtual bool toBoolean(ExecState* ) const { return true; }
+ static const ClassInfo info;
+ enum { MediaText, Length,
+ Item, DeleteMedium, AppendMedium };
+ DOM::MediaList toMediaList() const { return mediaList; }
+ private:
+ DOM::MediaList mediaList;
+ };
+
+ Value getDOMMediaList(ExecState *exec, const DOM::MediaList& ss);
+
+ class DOMCSSStyleSheet : public DOMStyleSheet {
+ public:
+ DOMCSSStyleSheet(ExecState *exec, const DOM::CSSStyleSheet& ss);
+ virtual ~DOMCSSStyleSheet();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { OwnerRule, CssRules, Rules,
+ InsertRule, DeleteRule, AddRule, RemoveRule };
+ DOM::CSSStyleSheet toCSSStyleSheet() const { return static_cast<DOM::CSSStyleSheet>(styleSheet); }
+ };
+
+ class DOMCSSRuleList : public DOMObject {
+ public:
+ DOMCSSRuleList(ExecState *, const DOM::CSSRuleList& rl);
+ virtual ~DOMCSSRuleList();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Item, Length };
+ DOM::CSSRuleList toCSSRuleList() const { return cssRuleList; }
+ protected:
+ DOM::CSSRuleList cssRuleList;
+ };
+
+ Value getDOMCSSRuleList(ExecState *exec, const DOM::CSSRuleList& rl);
+
+ class DOMCSSRule : public DOMObject {
+ public:
+ DOMCSSRule(ExecState *, const DOM::CSSRule& r);
+ virtual ~DOMCSSRule();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
+ virtual const ClassInfo* classInfo() const;
+ static const ClassInfo info;
+ static const ClassInfo style_info, media_info, fontface_info, page_info, import_info, charset_info;
+ enum { ParentStyleSheet, Type, CssText, ParentRule,
+ Style_SelectorText, Style_Style,
+ Media_Media, Media_InsertRule, Media_DeleteRule, Media_CssRules,
+ FontFace_Style, Page_SelectorText, Page_Style,
+ Import_Href, Import_Media, Import_StyleSheet, Charset_Encoding };
+ DOM::CSSRule toCSSRule() const { return cssRule; }
+ protected:
+ DOM::CSSRule cssRule;
+ };
+
+ Value getDOMCSSRule(ExecState *exec, const DOM::CSSRule& r);
+
+ /**
+ * Convert an object to a CSSRule. Returns a null CSSRule if not possible.
+ */
+ DOM::CSSRule toCSSRule(const Value&);
+
+ // Constructor for CSSRule - currently only used for some global values
+ class CSSRuleConstructor : public DOMObject {
+ public:
+ CSSRuleConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { UNKNOWN_RULE, STYLE_RULE, CHARSET_RULE, IMPORT_RULE, MEDIA_RULE, FONT_FACE_RULE, PAGE_RULE };
+ };
+
+ Value getCSSRuleConstructor(ExecState *exec);
+
+ class DOMCSSValue : public DOMObject {
+ public:
+ DOMCSSValue(ExecState *, const DOM::CSSValue& v);
+ DOMCSSValue(const Object& proto, const DOM::CSSValue& v) : DOMObject(proto), cssValue(v) { }
+ virtual ~DOMCSSValue();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { CssText, CssValueType };
+ protected:
+ DOM::CSSValue cssValue;
+ };
+
+ Value getDOMCSSValue(ExecState *exec, const DOM::CSSValue& v);
+
+ // Constructor for CSSValue - currently only used for some global values
+ class CSSValueConstructor : public DOMObject {
+ public:
+ CSSValueConstructor(ExecState *exec);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { CSS_VALUE_LIST, CSS_PRIMITIVE_VALUE, CSS_CUSTOM, CSS_INHERIT };
+ };
+
+ Value getCSSValueConstructor(ExecState *exec);
+
+ class DOMCSSPrimitiveValue : public DOMCSSValue {
+ public:
+ DOMCSSPrimitiveValue(ExecState *exec, const DOM::CSSPrimitiveValue& v);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ DOM::CSSPrimitiveValue toCSSPrimitiveValue() const { return static_cast<DOM::CSSPrimitiveValue>(cssValue); }
+ enum { PrimitiveType, SetFloatValue, GetFloatValue, SetStringValue, GetStringValue,
+ GetCounterValue, GetRectValue, GetRGBColorValue };
+ };
+
+ // Constructor for CSSPrimitiveValue - currently only used for some global values
+ class CSSPrimitiveValueConstructor : public CSSValueConstructor {
+ public:
+ CSSPrimitiveValueConstructor(ExecState *exec) : CSSValueConstructor(exec) { }
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ Value getCSSPrimitiveValueConstructor(ExecState *exec);
+
+ class DOMCSSValueList : public DOMCSSValue {
+ public:
+ DOMCSSValueList(ExecState *exec, const DOM::CSSValueList& v);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Item, Length };
+ DOM::CSSValueList toValueList() const { return static_cast<DOM::CSSValueList>(cssValue); }
+ };
+
+ class DOMRGBColor : public DOMObject {
+ public:
+ DOMRGBColor(ExecState*, const DOM::RGBColor& c);
+ ~DOMRGBColor();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Red, Green, Blue };
+ protected:
+ DOM::RGBColor rgbColor;
+ };
+
+ Value getDOMRGBColor(ExecState *exec, const DOM::RGBColor& c);
+
+ class DOMRect : public DOMObject {
+ public:
+ DOMRect(ExecState *, const DOM::Rect& r);
+ ~DOMRect();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Top, Right, Bottom, Left };
+ protected:
+ DOM::Rect rect;
+ };
+
+ Value getDOMRect(ExecState *exec, const DOM::Rect& r);
+
+ class DOMCounter : public DOMObject {
+ public:
+ DOMCounter(ExecState *, const DOM::Counter& c);
+ ~DOMCounter();
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { identifier, listStyle, separator };
+ protected:
+ DOM::Counter counter;
+ };
+
+ Value getDOMCounter(ExecState *exec, const DOM::Counter& c);
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_debugwin.cpp b/tdehtml/ecma/kjs_debugwin.cpp
new file mode 100644
index 000000000..4830c1108
--- /dev/null
+++ b/tdehtml/ecma/kjs_debugwin.cpp
@@ -0,0 +1,1139 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001,2003 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_debugwin.h"
+#include "kjs_proxy.h"
+
+#ifdef KJS_DEBUGGER
+
+#include <assert.h>
+#include <stdlib.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtextedit.h>
+#include <tqlistbox.h>
+#include <tqmultilineedit.h>
+#include <tqapplication.h>
+#include <tqsplitter.h>
+#include <tqcombobox.h>
+#include <tqbitmap.h>
+#include <tqwidgetlist.h>
+#include <tqlabel.h>
+#include <tqdatastream.h>
+#include <tqcstring.h>
+#include <tqpainter.h>
+#include <tqscrollbar.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kmessagebox.h>
+#include <kguiitem.h>
+#include <kpopupmenu.h>
+#include <kmenubar.h>
+#include <kaction.h>
+#include <kactioncollection.h>
+#include <kglobalsettings.h>
+#include <kshortcut.h>
+#include <kconfig.h>
+#include <kconfigbase.h>
+#include <kapplication.h>
+#include <dcop/dcopclient.h>
+#include <kstringhandler.h>
+
+#include "kjs_dom.h"
+#include "kjs_binding.h"
+#include "tdehtml_part.h"
+#include "tdehtmlview.h"
+#include "tdehtml_pagecache.h"
+#include "tdehtml_settings.h"
+#include "tdehtml_factory.h"
+#include "misc/decoder.h"
+#include <kjs/ustring.h>
+#include <kjs/object.h>
+#include <kjs/function.h>
+#include <kjs/interpreter.h>
+
+using namespace KJS;
+using namespace tdehtml;
+
+SourceDisplay::SourceDisplay(KJSDebugWin *debugWin, TQWidget *parent, const char *name)
+ : TQScrollView(parent,name), m_currentLine(-1), m_sourceFile(0), m_debugWin(debugWin),
+ m_font(TDEGlobalSettings::fixedFont())
+{
+ verticalScrollBar()->setLineStep(TQFontMetrics(m_font).height());
+ viewport()->setBackgroundMode(TQt::NoBackground);
+ m_breakpointIcon = TDEGlobal::iconLoader()->loadIcon("stop",KIcon::Small);
+}
+
+SourceDisplay::~SourceDisplay()
+{
+ if (m_sourceFile) {
+ m_sourceFile->deref();
+ m_sourceFile = 0L;
+ }
+}
+
+void SourceDisplay::setSource(SourceFile *sourceFile)
+{
+ if ( sourceFile )
+ sourceFile->ref();
+ if (m_sourceFile)
+ m_sourceFile->deref();
+ m_sourceFile = sourceFile;
+ if ( m_sourceFile )
+ m_sourceFile->ref();
+
+ if (!m_sourceFile || !m_debugWin->isVisible()) {
+ return;
+ }
+
+ TQString code = sourceFile->getCode();
+ const TQChar *chars = code.unicode();
+ uint len = code.length();
+ TQChar newLine('\n');
+ TQChar cr('\r');
+ TQChar tab('\t');
+ TQString tabstr(" ");
+ TQString line;
+ m_lines.clear();
+ int width = 0;
+ TQFontMetrics metrics(m_font);
+
+ for (uint pos = 0; pos < len; pos++) {
+ TQChar c = chars[pos];
+ if (c == cr) {
+ if (pos < len-1 && chars[pos+1] == newLine)
+ continue;
+ else
+ c = newLine;
+ }
+ if (c == newLine) {
+ m_lines.append(line);
+ int lineWidth = metrics.width(line);
+ if (lineWidth > width)
+ width = lineWidth;
+ line = "";
+ }
+ else if (c == tab) {
+ line += tabstr;
+ }
+ else {
+ line += c;
+ }
+ }
+ if (line.length()) {
+ m_lines.append(line);
+ int lineWidth = metrics.width(line);
+ if (lineWidth > width)
+ width = lineWidth;
+ }
+
+ int linenoDisplayWidth = metrics.width("888888");
+ resizeContents(linenoDisplayWidth+4+width,metrics.height()*m_lines.count());
+ update();
+ sourceFile->deref();
+}
+
+void SourceDisplay::setCurrentLine(int lineno, bool doCenter)
+{
+ m_currentLine = lineno;
+
+ if (doCenter && m_currentLine >= 0) {
+ TQFontMetrics metrics(m_font);
+ int height = metrics.height();
+ center(0,height*m_currentLine+height/2);
+ }
+
+ updateContents();
+}
+
+void SourceDisplay::contentsMousePressEvent(TQMouseEvent *e)
+{
+ TQScrollView::mouseDoubleClickEvent(e);
+ TQFontMetrics metrics(m_font);
+ int lineno = e->y()/metrics.height();
+ emit lineDoubleClicked(lineno+1); // line numbers start from 1
+}
+
+void SourceDisplay::showEvent(TQShowEvent *)
+{
+ setSource(m_sourceFile);
+}
+
+void SourceDisplay::drawContents(TQPainter *p, int clipx, int clipy, int clipw, int cliph)
+{
+ if (!m_sourceFile) {
+ p->fillRect(clipx,clipy,clipw,cliph,palette().active().base());
+ return;
+ }
+
+ TQFontMetrics metrics(m_font);
+ int height = metrics.height();
+
+ int bottom = clipy + cliph;
+ int right = clipx + clipw;
+
+ int firstLine = clipy/height-1;
+ if (firstLine < 0)
+ firstLine = 0;
+ int lastLine = bottom/height+2;
+ if (lastLine > (int)m_lines.count())
+ lastLine = m_lines.count();
+
+ p->setFont(m_font);
+
+ int linenoWidth = metrics.width("888888");
+
+ for (int lineno = firstLine; lineno <= lastLine; lineno++) {
+ TQString linenoStr = TQString().sprintf("%d",lineno+1);
+
+
+ p->fillRect(0,height*lineno,linenoWidth,height,palette().active().mid());
+
+ p->setPen(palette().active().text());
+ p->drawText(0,height*lineno,linenoWidth,height,Qt::AlignRight,linenoStr);
+
+ TQColor bgColor;
+ TQColor textColor;
+
+ if (lineno == m_currentLine) {
+ bgColor = palette().active().highlight();
+ textColor = palette().active().highlightedText();
+ }
+ else if (m_debugWin->haveBreakpoint(m_sourceFile,lineno+1,lineno+1)) {
+ bgColor = palette().active().text();
+ textColor = palette().active().base();
+ p->drawPixmap(2,height*lineno+height/2-m_breakpointIcon.height()/2,m_breakpointIcon);
+ }
+ else {
+ bgColor = palette().active().base();
+ textColor = palette().active().text();
+ }
+
+ p->fillRect(linenoWidth,height*lineno,right-linenoWidth,height,bgColor);
+ p->setPen(textColor);
+ p->drawText(linenoWidth+4,height*lineno,contentsWidth()-linenoWidth-4,height,
+ Qt::AlignLeft,m_lines[lineno]);
+ }
+
+ int remainingTop = height*(lastLine+1);
+ p->fillRect(0,remainingTop,linenoWidth,bottom-remainingTop,palette().active().mid());
+
+ p->fillRect(linenoWidth,remainingTop,
+ right-linenoWidth,bottom-remainingTop,palette().active().base());
+}
+
+//-------------------------------------------------------------------------
+
+KJSDebugWin * KJSDebugWin::kjs_html_debugger = 0;
+
+TQString SourceFile::getCode()
+{
+ if (interpreter) {
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart*>(static_cast<ScriptInterpreter*>(interpreter)->part());
+ if (part && url == part->url().url() && KHTMLPageCache::self()->isValid(part->cacheId())) {
+ Decoder *decoder = part->createDecoder();
+ TQByteArray data;
+ TQDataStream stream(data,IO_WriteOnly);
+ KHTMLPageCache::self()->saveData(part->cacheId(),&stream);
+ TQString str;
+ if (data.size() == 0)
+ str = "";
+ else
+ str = decoder->decode(data.data(),data.size()) + decoder->flush();
+ delete decoder;
+ return str;
+ }
+ }
+
+ return code;
+}
+
+//-------------------------------------------------------------------------
+
+SourceFragment::SourceFragment(int sid, int bl, int el, SourceFile *sf)
+{
+ sourceId = sid;
+ baseLine = bl;
+ errorLine = el;
+ sourceFile = sf;
+ sourceFile->ref();
+}
+
+SourceFragment::~SourceFragment()
+{
+ sourceFile->deref();
+ sourceFile = 0L;
+}
+
+//-------------------------------------------------------------------------
+
+KJSErrorDialog::KJSErrorDialog(TQWidget *parent, const TQString& errorMessage, bool showDebug)
+ : KDialogBase(parent,0,true,i18n("JavaScript Error"),
+ showDebug ? KDialogBase::Ok|KDialogBase::User1 : KDialogBase::Ok,
+ KDialogBase::Ok,false,KGuiItem("&Debug","gear"))
+{
+ TQWidget *page = new TQWidget(this);
+ setMainWidget(page);
+
+ TQLabel *iconLabel = new TQLabel("",page);
+ iconLabel->setPixmap(TDEGlobal::iconLoader()->loadIcon("messagebox_critical",
+ KIcon::NoGroup,KIcon::SizeMedium,
+ KIcon::DefaultState,0,true));
+
+ TQWidget *contents = new TQWidget(page);
+ TQLabel *label = new TQLabel(errorMessage,contents);
+ m_dontShowAgainCb = new TQCheckBox(i18n("&Do not show this message again"),contents);
+
+ TQVBoxLayout *vl = new TQVBoxLayout(contents,0,spacingHint());
+ vl->addWidget(label);
+ vl->addWidget(m_dontShowAgainCb);
+
+ TQHBoxLayout *topLayout = new TQHBoxLayout(page,0,spacingHint());
+ topLayout->addWidget(iconLabel);
+ topLayout->addWidget(contents);
+ topLayout->addStretch(10);
+
+ m_debugSelected = false;
+}
+
+KJSErrorDialog::~KJSErrorDialog()
+{
+}
+
+void KJSErrorDialog::slotUser1()
+{
+ m_debugSelected = true;
+ close();
+}
+
+//-------------------------------------------------------------------------
+EvalMultiLineEdit::EvalMultiLineEdit(TQWidget *parent)
+ : TQMultiLineEdit(parent) {
+}
+
+void EvalMultiLineEdit::keyPressEvent(TQKeyEvent * e)
+{
+ if (e->key() == Qt::Key_Return) {
+ if (hasSelectedText()) {
+ m_code = selectedText();
+ } else {
+ int para, index;
+ getCursorPosition(&para, &index);
+ m_code = text(para);
+ }
+ end();
+ }
+ TQMultiLineEdit::keyPressEvent(e);
+}
+//-------------------------------------------------------------------------
+KJSDebugWin::KJSDebugWin(TQWidget *parent, const char *name)
+ : KMainWindow(parent, name, (WFlags)WType_TopLevel), TDEInstance("kjs_debugger")
+{
+ m_breakpoints = 0;
+ m_breakpointCount = 0;
+
+ m_curSourceFile = 0;
+ m_mode = Continue;
+ m_nextSourceUrl = "";
+ m_nextSourceBaseLine = 1;
+ m_execs = 0;
+ m_execsCount = 0;
+ m_execsAlloc = 0;
+ m_steppingDepth = 0;
+
+ m_stopIcon = TDEGlobal::iconLoader()->loadIcon("stop",KIcon::Small);
+ m_emptyIcon = TQPixmap(m_stopIcon.width(),m_stopIcon.height());
+ TQBitmap emptyMask(m_stopIcon.width(),m_stopIcon.height(),true);
+ m_emptyIcon.setMask(emptyMask);
+
+ setCaption(i18n("JavaScript Debugger"));
+
+ TQWidget *mainWidget = new TQWidget(this);
+ setCentralWidget(mainWidget);
+
+ TQVBoxLayout *vl = new TQVBoxLayout(mainWidget,5);
+
+ // frame list & code
+ TQSplitter *hsplitter = new TQSplitter(Qt::Vertical,mainWidget);
+ TQSplitter *vsplitter = new TQSplitter(hsplitter);
+ TQFont font(TDEGlobalSettings::fixedFont());
+
+ TQWidget *contextContainer = new TQWidget(vsplitter);
+
+ TQLabel *contextLabel = new TQLabel(i18n("Call stack"),contextContainer);
+ TQWidget *contextListContainer = new TQWidget(contextContainer);
+ m_contextList = new TQListBox(contextListContainer);
+ m_contextList->setMinimumSize(100,200);
+ connect(m_contextList,TQT_SIGNAL(highlighted(int)),this,TQT_SLOT(slotShowFrame(int)));
+
+ TQHBoxLayout *clistLayout = new TQHBoxLayout(contextListContainer);
+ clistLayout->addWidget(m_contextList);
+ clistLayout->addSpacing(KDialog::spacingHint());
+
+ TQVBoxLayout *contextLayout = new TQVBoxLayout(contextContainer);
+ contextLayout->addWidget(contextLabel);
+ contextLayout->addSpacing(KDialog::spacingHint());
+ contextLayout->addWidget(contextListContainer);
+
+ // source selection & display
+ TQWidget *sourceSelDisplay = new TQWidget(vsplitter);
+ TQVBoxLayout *ssdvl = new TQVBoxLayout(sourceSelDisplay);
+
+ m_sourceSel = new TQComboBox(toolBar());
+ connect(m_sourceSel,TQT_SIGNAL(activated(int)),this,TQT_SLOT(slotSourceSelected(int)));
+
+ m_sourceDisplay = new SourceDisplay(this,sourceSelDisplay);
+ ssdvl->addWidget(m_sourceDisplay);
+ connect(m_sourceDisplay,TQT_SIGNAL(lineDoubleClicked(int)),TQT_SLOT(slotToggleBreakpoint(int)));
+
+ TQValueList<int> vsplitSizes;
+ vsplitSizes.insert(vsplitSizes.end(),120);
+ vsplitSizes.insert(vsplitSizes.end(),480);
+ vsplitter->setSizes(vsplitSizes);
+
+ // evaluate
+
+ TQWidget *evalContainer = new TQWidget(hsplitter);
+
+ TQLabel *evalLabel = new TQLabel(i18n("JavaScript console"),evalContainer);
+ m_evalEdit = new EvalMultiLineEdit(evalContainer);
+ m_evalEdit->setWordWrap(TQMultiLineEdit::NoWrap);
+ m_evalEdit->setFont(font);
+ connect(m_evalEdit,TQT_SIGNAL(returnPressed()),TQT_SLOT(slotEval()));
+ m_evalDepth = 0;
+
+ TQVBoxLayout *evalLayout = new TQVBoxLayout(evalContainer);
+ evalLayout->addSpacing(KDialog::spacingHint());
+ evalLayout->addWidget(evalLabel);
+ evalLayout->addSpacing(KDialog::spacingHint());
+ evalLayout->addWidget(m_evalEdit);
+
+ TQValueList<int> hsplitSizes;
+ hsplitSizes.insert(hsplitSizes.end(),400);
+ hsplitSizes.insert(hsplitSizes.end(),200);
+ hsplitter->setSizes(hsplitSizes);
+
+ vl->addWidget(hsplitter);
+
+ // actions
+ KPopupMenu *debugMenu = new KPopupMenu(this);
+ menuBar()->insertItem("&Debug",debugMenu);
+
+ m_actionCollection = new KActionCollection(this);
+ m_actionCollection->setInstance(this);
+
+ // Venkman use F12, KDevelop F10
+ KShortcut scNext = KShortcut(KKeySequence(KKey(Qt::Key_F12)));
+ scNext.append(KKeySequence(KKey(Qt::Key_F10)));
+ m_nextAction = new KAction(i18n("Next breakpoint","&Next"),"dbgnext",scNext,TQT_TQOBJECT(this),TQT_SLOT(slotNext()),
+ m_actionCollection,"next");
+ m_stepAction = new KAction(i18n("&Step"),"dbgstep",KShortcut(Qt::Key_F11),TQT_TQOBJECT(this),TQT_SLOT(slotStep()),
+ m_actionCollection,"step");
+ // Venkman use F5, Kdevelop F9
+ KShortcut scCont = KShortcut(KKeySequence(KKey(Qt::Key_F5)));
+ scCont.append(KKeySequence(KKey(Qt::Key_F9)));
+ m_continueAction = new KAction(i18n("&Continue"),"dbgrun",scCont,TQT_TQOBJECT(this),TQT_SLOT(slotContinue()),
+ m_actionCollection,"cont");
+ m_stopAction = new KAction(i18n("St&op"),"stop",KShortcut(Qt::Key_F4),TQT_TQOBJECT(this),TQT_SLOT(slotStop()),
+ m_actionCollection,"stop");
+ m_breakAction = new KAction(i18n("&Break at Next Statement"),"dbgrunto",KShortcut(Qt::Key_F8),TQT_TQOBJECT(this),TQT_SLOT(slotBreakNext()),
+ m_actionCollection,"breaknext");
+
+
+ m_nextAction->setToolTip(i18n("Next breakpoint","Next"));
+ m_stepAction->setToolTip(i18n("Step"));
+ m_continueAction->setToolTip(i18n("Continue"));
+ m_stopAction->setToolTip(i18n("Stop"));
+ m_breakAction->setToolTip("Break at next Statement");
+
+ m_nextAction->setEnabled(false);
+ m_stepAction->setEnabled(false);
+ m_continueAction->setEnabled(false);
+ m_stopAction->setEnabled(false);
+ m_breakAction->setEnabled(true);
+
+ m_nextAction->plug(debugMenu);
+ m_stepAction->plug(debugMenu);
+ m_continueAction->plug(debugMenu);
+// m_stopAction->plug(debugMenu); ### disabled until DebuggerImp::stop() works reliably
+ m_breakAction->plug(debugMenu);
+
+ m_nextAction->plug(toolBar());
+ m_stepAction->plug(toolBar());
+ m_continueAction->plug(toolBar());
+// m_stopAction->plug(toolBar()); ###
+ m_breakAction->plug(toolBar());
+
+ toolBar()->insertWidget(1,300,m_sourceSel);
+ toolBar()->setItemAutoSized(1);
+
+ updateContextList();
+ setMinimumSize(300,200);
+ resize(600,450);
+
+}
+
+KJSDebugWin::~KJSDebugWin()
+{
+ free(m_breakpoints);
+ free(m_execs);
+}
+
+KJSDebugWin *KJSDebugWin::createInstance()
+{
+ assert(!kjs_html_debugger);
+ kjs_html_debugger = new KJSDebugWin();
+ return kjs_html_debugger;
+}
+
+void KJSDebugWin::destroyInstance()
+{
+ assert(kjs_html_debugger);
+ kjs_html_debugger->hide();
+ delete kjs_html_debugger;
+}
+
+void KJSDebugWin::slotNext()
+{
+ m_mode = Next;
+ leaveSession();
+}
+
+void KJSDebugWin::slotStep()
+{
+ m_mode = Step;
+ leaveSession();
+}
+
+void KJSDebugWin::slotContinue()
+{
+ m_mode = Continue;
+ leaveSession();
+}
+
+void KJSDebugWin::slotStop()
+{
+ m_mode = Stop;
+ while (!m_execStates.isEmpty())
+ leaveSession();
+}
+
+void KJSDebugWin::slotBreakNext()
+{
+ m_mode = Step;
+}
+
+void KJSDebugWin::slotToggleBreakpoint(int lineno)
+{
+ if (m_sourceSel->currentItem() < 0)
+ return;
+
+ SourceFile *sourceFile = m_sourceSelFiles.at(m_sourceSel->currentItem());
+
+ // Find the source fragment containing the selected line (if any)
+ int sourceId = -1;
+ int highestBaseLine = -1;
+ TQMap<int,SourceFragment*>::Iterator it;
+
+ for (it = m_sourceFragments.begin(); it != m_sourceFragments.end(); ++it) {
+ SourceFragment *sourceFragment = it.data();
+ if (sourceFragment &&
+ sourceFragment->sourceFile == sourceFile &&
+ sourceFragment->baseLine <= lineno &&
+ sourceFragment->baseLine > highestBaseLine) {
+
+ sourceId = sourceFragment->sourceId;
+ highestBaseLine = sourceFragment->baseLine;
+ }
+ }
+
+ if (sourceId < 0)
+ return;
+
+ // Update the source code display with the appropriate icon
+ int fragmentLineno = lineno-highestBaseLine+1;
+ if (!setBreakpoint(sourceId,fragmentLineno)) // was already set
+ deleteBreakpoint(sourceId,fragmentLineno);
+
+ m_sourceDisplay->updateContents();
+}
+
+void KJSDebugWin::slotShowFrame(int frameno)
+{
+ if (frameno < 0 || frameno >= m_execsCount)
+ return;
+
+ Context ctx = m_execs[frameno]->context();
+ setSourceLine(ctx.sourceId(),ctx.curStmtFirstLine());
+}
+
+void KJSDebugWin::slotSourceSelected(int sourceSelIndex)
+{
+ // A source file has been selected from the drop-down list - display the file
+ if (sourceSelIndex < 0 || sourceSelIndex >= (int)m_sourceSel->count())
+ return;
+ SourceFile *sourceFile = m_sourceSelFiles.at(sourceSelIndex);
+ displaySourceFile(sourceFile,true);
+
+ // If the currently selected context is in the current source file, then hilight
+ // the line it's on.
+ if (m_contextList->currentItem() >= 0) {
+ Context ctx = m_execs[m_contextList->currentItem()]->context();
+ if (m_sourceFragments[ctx.sourceId()]->sourceFile == m_sourceSelFiles.at(sourceSelIndex))
+ setSourceLine(ctx.sourceId(),ctx.curStmtFirstLine());
+ }
+}
+
+void KJSDebugWin::slotEval()
+{
+ // Work out which execution state to use. If we're currently in a debugging session,
+ // use the current context - otherwise, use the global execution state from the interpreter
+ // corresponding to the currently displayed source file.
+ ExecState *exec;
+ Object thisobj;
+ if (m_execStates.isEmpty()) {
+ if (m_sourceSel->currentItem() < 0)
+ return;
+ SourceFile *sourceFile = m_sourceSelFiles.at(m_sourceSel->currentItem());
+ if (!sourceFile->interpreter)
+ return;
+ exec = sourceFile->interpreter->globalExec();
+ thisobj = exec->interpreter()->globalObject();
+ }
+ else {
+ exec = m_execStates.top();
+ thisobj = exec->context().thisValue();
+ }
+
+ // Evaluate the js code from m_evalEdit
+ UString code(m_evalEdit->code());
+ TQString msg;
+
+ KJSCPUGuard guard;
+ guard.start();
+
+ Interpreter *interp = exec->interpreter();
+
+ Object obj = Object::dynamicCast(interp->globalObject().get(exec, "eval"));
+ List args;
+ args.append(String(code));
+
+ m_evalDepth++;
+ Value retval = obj.call(exec, thisobj, args);
+ m_evalDepth--;
+ guard.stop();
+
+ // Print the return value or exception message to the console
+ if (exec->hadException()) {
+ Value exc = exec->exception();
+ exec->clearException();
+ msg = "Exception: " + exc.toString(interp->globalExec()).qstring();
+ }
+ else {
+ msg = retval.toString(interp->globalExec()).qstring();
+ }
+
+ m_evalEdit->insert(msg+"\n");
+ updateContextList();
+}
+
+void KJSDebugWin::closeEvent(TQCloseEvent *e)
+{
+ while (!m_execStates.isEmpty()) // ### not sure if this will work
+ leaveSession();
+ return TQWidget::closeEvent(e);
+}
+
+bool KJSDebugWin::eventFilter(TQObject *o, TQEvent *e)
+{
+ switch (e->type()) {
+ case TQEvent::MouseButtonPress:
+ case TQEvent::MouseButtonRelease:
+ case TQEvent::MouseButtonDblClick:
+ case TQEvent::MouseMove:
+ case TQEvent::KeyPress:
+ case TQEvent::KeyRelease:
+ case TQEvent::Destroy:
+ case TQEvent::Close:
+ case TQEvent::Quit:
+ while (o->parent())
+ o = TQT_TQOBJECT(o->parent());
+ if (TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(this))
+ return TQWidget::eventFilter(o,e);
+ else
+ return true;
+ break;
+ default:
+ return TQWidget::eventFilter(o,e);
+ }
+}
+
+void KJSDebugWin::disableOtherWindows()
+{
+ TQWidgetList *widgets = TQApplication::allWidgets();
+ TQWidgetListIt it(*widgets);
+ for (; it.current(); ++it)
+ it.current()->installEventFilter(this);
+}
+
+void KJSDebugWin::enableOtherWindows()
+{
+ TQWidgetList *widgets = TQApplication::allWidgets();
+ TQWidgetListIt it(*widgets);
+ for (; it.current(); ++it)
+ it.current()->removeEventFilter(this);
+}
+
+bool KJSDebugWin::sourceParsed(KJS::ExecState *exec, int sourceId,
+ const KJS::UString &source, int errorLine)
+{
+ // Work out which source file this fragment is in
+ SourceFile *sourceFile = 0;
+ if (!m_nextSourceUrl.isEmpty())
+ sourceFile = getSourceFile(exec->interpreter(),m_nextSourceUrl);
+
+ int index;
+ if (!sourceFile) {
+ index = m_sourceSel->count();
+ if (!m_nextSourceUrl.isEmpty()) {
+
+ TQString code = source.qstring();
+ KParts::ReadOnlyPart *part = static_cast<ScriptInterpreter*>(exec->interpreter())->part();
+ if (m_nextSourceUrl == part->url().url()) {
+ // Only store the code here if it's not from the part's html page... in that
+ // case we can get it from KHTMLPageCache
+ code = TQString::null;
+ }
+
+ sourceFile = new SourceFile(m_nextSourceUrl,code,exec->interpreter());
+ setSourceFile(exec->interpreter(),m_nextSourceUrl,sourceFile);
+ m_sourceSelFiles.append(sourceFile);
+ m_sourceSel->insertItem(m_nextSourceUrl);
+ }
+ else {
+ // Sourced passed from somewhere else (possibly an eval call)... we don't know the url,
+ // but we still know the interpreter
+ sourceFile = new SourceFile("(unknown)",source.qstring(),exec->interpreter());
+ m_sourceSelFiles.append(sourceFile);
+ m_sourceSel->insertItem(TQString::number(index) += "-???");
+ }
+ }
+ else {
+ // Ensure that each source file to be displayed is associated with
+ // an appropriate interpreter
+ if (!sourceFile->interpreter)
+ sourceFile->interpreter = exec->interpreter();
+ for (index = 0; index < m_sourceSel->count(); index++) {
+ if (m_sourceSelFiles.at(index) == sourceFile)
+ break;
+ }
+ assert(index < m_sourceSel->count());
+ }
+
+ SourceFragment *sf = new SourceFragment(sourceId,m_nextSourceBaseLine,errorLine,sourceFile);
+ m_sourceFragments[sourceId] = sf;
+
+ if (m_sourceSel->currentItem() < 0)
+ m_sourceSel->setCurrentItem(index);
+
+ if (m_sourceSel->currentItem() == index) {
+ displaySourceFile(sourceFile,true);
+ }
+
+ m_nextSourceBaseLine = 1;
+ m_nextSourceUrl = "";
+
+ return (m_mode != Stop);
+}
+
+bool KJSDebugWin::sourceUnused(KJS::ExecState *exec, int sourceId)
+{
+ // Verify that there aren't any contexts on the stack using the given sourceId
+ // This should never be the case because this function is only called when
+ // the interpreter has deleted all Node objects for the source.
+ for (int e = 0; e < m_execsCount; e++)
+ assert(m_execs[e]->context().sourceId() != sourceId);
+
+ // Now remove the fragment (and the SourceFile, if it was the last fragment in that file)
+ SourceFragment *fragment = m_sourceFragments[sourceId];
+ if (fragment) {
+ m_sourceFragments.erase(sourceId);
+
+ SourceFile *sourceFile = fragment->sourceFile;
+ if (sourceFile->hasOneRef()) {
+ for (int i = 0; i < m_sourceSel->count(); i++) {
+ if (m_sourceSelFiles.at(i) == sourceFile) {
+ m_sourceSel->removeItem(i);
+ m_sourceSelFiles.remove(i);
+ break;
+ }
+ }
+ removeSourceFile(exec->interpreter(),sourceFile->url);
+ }
+ delete fragment;
+ }
+
+ return (m_mode != Stop);
+}
+
+bool KJSDebugWin::exception(ExecState *exec, const Value &value, bool inTryCatch)
+{
+ assert(value.isValid());
+
+ // Ignore exceptions that will be caught by the script
+ if (inTryCatch)
+ return true;
+
+ KParts::ReadOnlyPart *part = static_cast<ScriptInterpreter*>(exec->interpreter())->part();
+ KHTMLPart *tdehtmlpart = ::tqqt_cast<KHTMLPart*>(part);
+ if (tdehtmlpart && !tdehtmlpart->settings()->isJavaScriptErrorReportingEnabled())
+ return true;
+
+ TQWidget *dlgParent = (m_evalDepth == 0) ? (TQWidget*)part->widget() : (TQWidget*)this;
+
+ TQString exceptionMsg = value.toString(exec).qstring();
+
+ // Syntax errors are a special case. For these we want to display the url & lineno,
+ // which isn't included in the exception messeage. So we work it out from the values
+ // passed to sourceParsed()
+ Object valueObj = Object::dynamicCast(value);
+ Object syntaxError = exec->interpreter()->builtinSyntaxError();
+ if (valueObj.isValid() && valueObj.get(exec,"constructor").imp() == syntaxError.imp()) {
+ Value sidValue = valueObj.get(exec,"sid");
+ if (sidValue.isA(NumberType)) { // sid is not set for Function() constructor
+ int sourceId = (int)sidValue.toNumber(exec);
+ assert(m_sourceFragments[sourceId]);
+ exceptionMsg = i18n("Parse error at %1 line %2")
+ .arg(m_sourceFragments[sourceId]->sourceFile->url)
+ .arg(m_sourceFragments[sourceId]->baseLine+m_sourceFragments[sourceId]->errorLine-1);
+ }
+ }
+
+ bool dontShowAgain = false;
+ if (m_execsCount == 0) {
+ // An exception occurred and we're not currently executing any code... this can
+ // happen in some cases e.g. a parse error, or native code accessing funcitons like
+ // Object::put()
+ TQString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1")
+ .arg(exceptionMsg);
+ KJSErrorDialog dlg(dlgParent,msg,false);
+ dlg.exec();
+ dontShowAgain = dlg.dontShowAgain();
+ }
+ else {
+ Context ctx = m_execs[m_execsCount-1]->context();
+ SourceFragment *sourceFragment = m_sourceFragments[ctx.sourceId()];
+ TQString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1 line %2:\n%3")
+ .arg(KStringHandler::rsqueeze( sourceFragment->sourceFile->url,80),
+ TQString::number( sourceFragment->baseLine+ctx.curStmtFirstLine()-1),
+ exceptionMsg);
+
+ KJSErrorDialog dlg(dlgParent,msg,true);
+ dlg.exec();
+ dontShowAgain = dlg.dontShowAgain();
+
+ if (dlg.debugSelected()) {
+ m_mode = Next;
+ m_steppingDepth = m_execsCount-1;
+ enterSession(exec);
+ }
+ }
+
+ if (dontShowAgain) {
+ TDEConfig *config = kapp->config();
+ TDEConfigGroupSaver saver(config,TQString::fromLatin1("Java/JavaScript Settings"));
+ config->writeEntry("ReportJavaScriptErrors",TQVariant(false,0));
+ config->sync();
+ TQByteArray data;
+ kapp->dcopClient()->send( "konqueror*", "KonquerorIface", "reparseConfiguration()", data );
+ }
+
+ return (m_mode != Stop);
+}
+
+bool KJSDebugWin::atStatement(KJS::ExecState *exec)
+{
+ assert(m_execsCount > 0);
+ assert(m_execs[m_execsCount-1] == exec);
+ checkBreak(exec);
+ return (m_mode != Stop);
+}
+
+bool KJSDebugWin::enterContext(ExecState *exec)
+{
+ if (m_execsCount >= m_execsAlloc) {
+ m_execsAlloc += 10;
+ m_execs = (ExecState**)realloc(m_execs,m_execsAlloc*sizeof(ExecState*));
+ }
+ m_execs[m_execsCount++] = exec;
+
+ if (m_mode == Step)
+ m_steppingDepth = m_execsCount-1;
+
+ checkBreak(exec);
+ return (m_mode != Stop);
+}
+
+bool KJSDebugWin::exitContext(ExecState *exec, const Completion &/*completion*/)
+{
+ assert(m_execsCount > 0);
+ assert(m_execs[m_execsCount-1] == exec);
+
+ checkBreak(exec);
+
+ m_execsCount--;
+ if (m_steppingDepth > m_execsCount-1)
+ m_steppingDepth = m_execsCount-1;
+ if (m_execsCount == 0)
+ updateContextList();
+
+ return (m_mode != Stop);
+}
+
+void KJSDebugWin::displaySourceFile(SourceFile *sourceFile, bool forceRefresh)
+{
+ if (m_curSourceFile == sourceFile && !forceRefresh)
+ return;
+ sourceFile->ref();
+ m_sourceDisplay->setSource(sourceFile);
+ if (m_curSourceFile)
+ m_curSourceFile->deref();
+ m_curSourceFile = sourceFile;
+}
+
+void KJSDebugWin::setSourceLine(int sourceId, int lineno)
+{
+ SourceFragment *source = m_sourceFragments[sourceId];
+ if (!source)
+ return;
+
+ SourceFile *sourceFile = source->sourceFile;
+ if (m_curSourceFile != source->sourceFile) {
+ for (int i = 0; i < m_sourceSel->count(); i++)
+ if (m_sourceSelFiles.at(i) == sourceFile)
+ m_sourceSel->setCurrentItem(i);
+ displaySourceFile(sourceFile,false);
+ }
+ m_sourceDisplay->setCurrentLine(source->baseLine+lineno-2);
+}
+
+void KJSDebugWin::setNextSourceInfo(TQString url, int baseLine)
+{
+ m_nextSourceUrl = url;
+ m_nextSourceBaseLine = baseLine;
+}
+
+void KJSDebugWin::sourceChanged(Interpreter *interpreter, TQString url)
+{
+ SourceFile *sourceFile = getSourceFile(interpreter,url);
+ if (sourceFile && m_curSourceFile == sourceFile)
+ displaySourceFile(sourceFile,true);
+}
+
+void KJSDebugWin::clearInterpreter(Interpreter *interpreter)
+{
+ TQMap<int,SourceFragment*>::Iterator it;
+
+ for (it = m_sourceFragments.begin(); it != m_sourceFragments.end(); ++it)
+ if (it.data() && it.data()->sourceFile->interpreter == interpreter)
+ it.data()->sourceFile->interpreter = 0;
+}
+
+SourceFile *KJSDebugWin::getSourceFile(Interpreter *interpreter, TQString url)
+{
+ TQString key = TQString("%1|%2").arg((long)interpreter).arg(url);
+ return m_sourceFiles[key];
+}
+
+void KJSDebugWin::setSourceFile(Interpreter *interpreter, TQString url, SourceFile *sourceFile)
+{
+ TQString key = TQString("%1|%2").arg((long)interpreter).arg(url);
+ sourceFile->ref();
+ if (SourceFile* oldFile = m_sourceFiles[key])
+ oldFile->deref();
+ m_sourceFiles[key] = sourceFile;
+}
+
+void KJSDebugWin::removeSourceFile(Interpreter *interpreter, TQString url)
+{
+ TQString key = TQString("%1|%2").arg((long)interpreter).arg(url);
+ if (SourceFile* oldFile = m_sourceFiles[key])
+ oldFile->deref();
+ m_sourceFiles.remove(key);
+}
+
+void KJSDebugWin::checkBreak(ExecState *exec)
+{
+ if (m_breakpointCount > 0) {
+ Context ctx = m_execs[m_execsCount-1]->context();
+ if (haveBreakpoint(ctx.sourceId(),ctx.curStmtFirstLine(),ctx.curStmtLastLine())) {
+ m_mode = Next;
+ m_steppingDepth = m_execsCount-1;
+ }
+ }
+
+ if ((m_mode == Step || m_mode == Next) && m_steppingDepth == m_execsCount-1)
+ enterSession(exec);
+}
+
+void KJSDebugWin::enterSession(ExecState *exec)
+{
+ // This "enters" a new debugging session, i.e. enables usage of the debugging window
+ // It re-enters the qt event loop here, allowing execution of other parts of the
+ // program to continue while the script is stopped. We have to be a bit careful here,
+ // i.e. make sure the user can't quit the app, and disable other event handlers which
+ // could interfere with the debugging session.
+ if (!isVisible())
+ show();
+
+ m_mode = Continue;
+
+ if (m_execStates.isEmpty()) {
+ disableOtherWindows();
+ m_nextAction->setEnabled(true);
+ m_stepAction->setEnabled(true);
+ m_continueAction->setEnabled(true);
+ m_stopAction->setEnabled(true);
+ m_breakAction->setEnabled(false);
+ }
+ m_execStates.push(exec);
+
+ updateContextList();
+
+ tqApp->enter_loop(); // won't return until leaveSession() is called
+}
+
+void KJSDebugWin::leaveSession()
+{
+ // Disables debugging for this window and returns to execute the rest of the script
+ // (or aborts execution, if the user pressed stop). When this returns, the program
+ // will exit the qt event loop, i.e. return to whatever processing was being done
+ // before the debugger was stopped.
+ assert(!m_execStates.isEmpty());
+
+ m_execStates.pop();
+
+ if (m_execStates.isEmpty()) {
+ m_nextAction->setEnabled(false);
+ m_stepAction->setEnabled(false);
+ m_continueAction->setEnabled(false);
+ m_stopAction->setEnabled(false);
+ m_breakAction->setEnabled(true);
+ m_sourceDisplay->setCurrentLine(-1);
+ enableOtherWindows();
+ }
+
+ tqApp->exit_loop();
+}
+
+void KJSDebugWin::updateContextList()
+{
+ disconnect(m_contextList,TQT_SIGNAL(highlighted(int)),this,TQT_SLOT(slotShowFrame(int)));
+
+ m_contextList->clear();
+ for (int i = 0; i < m_execsCount; i++)
+ m_contextList->insertItem(contextStr(m_execs[i]->context()));
+
+ if (m_execsCount > 0) {
+ m_contextList->setSelected(m_execsCount-1, true);
+ Context ctx = m_execs[m_execsCount-1]->context();
+ setSourceLine(ctx.sourceId(),ctx.curStmtFirstLine());
+ }
+
+ connect(m_contextList,TQT_SIGNAL(highlighted(int)),this,TQT_SLOT(slotShowFrame(int)));
+}
+
+TQString KJSDebugWin::contextStr(const Context &ctx)
+{
+ TQString str = "";
+ SourceFragment *sourceFragment = m_sourceFragments[ctx.sourceId()];
+ TQString url = sourceFragment->sourceFile->url;
+ int fileLineno = sourceFragment->baseLine+ctx.curStmtFirstLine()-1;
+
+ switch (ctx.codeType()) {
+ case GlobalCode:
+ str = TQString("Global code at %1:%2").arg(url).arg(fileLineno);
+ break;
+ case EvalCode:
+ str = TQString("Eval code at %1:%2").arg(url).arg(fileLineno);
+ break;
+ case FunctionCode:
+ if (!ctx.functionName().isNull())
+ str = TQString("%1() at %2:%3").arg(ctx.functionName().qstring()).arg(url).arg(fileLineno);
+ else
+ str = TQString("Anonymous function at %1:%2").arg(url).arg(fileLineno);
+ break;
+ }
+
+ return str;
+}
+
+bool KJSDebugWin::setBreakpoint(int sourceId, int lineno)
+{
+ if (haveBreakpoint(sourceId,lineno,lineno))
+ return false;
+
+ m_breakpointCount++;
+ m_breakpoints = static_cast<Breakpoint*>(realloc(m_breakpoints,
+ m_breakpointCount*sizeof(Breakpoint)));
+ m_breakpoints[m_breakpointCount-1].sourceId = sourceId;
+ m_breakpoints[m_breakpointCount-1].lineno = lineno;
+
+ return true;
+}
+
+bool KJSDebugWin::deleteBreakpoint(int sourceId, int lineno)
+{
+ for (int i = 0; i < m_breakpointCount; i++) {
+ if (m_breakpoints[i].sourceId == sourceId && m_breakpoints[i].lineno == lineno) {
+
+ memmove(m_breakpoints+i,m_breakpoints+i+1,(m_breakpointCount-i-1)*sizeof(Breakpoint));
+ m_breakpointCount--;
+ m_breakpoints = static_cast<Breakpoint*>(realloc(m_breakpoints,
+ m_breakpointCount*sizeof(Breakpoint)));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool KJSDebugWin::haveBreakpoint(SourceFile *sourceFile, int line0, int line1)
+{
+ for (int i = 0; i < m_breakpointCount; i++) {
+ int sourceId = m_breakpoints[i].sourceId;
+ int lineno = m_breakpoints[i].lineno;
+ if (m_sourceFragments.contains(sourceId) &&
+ m_sourceFragments[sourceId]->sourceFile == sourceFile) {
+ int absLineno = m_sourceFragments[sourceId]->baseLine+lineno-1;
+ if (absLineno >= line0 && absLineno <= line1)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#include "kjs_debugwin.moc"
+
+#endif // KJS_DEBUGGER
diff --git a/tdehtml/ecma/kjs_debugwin.h b/tdehtml/ecma/kjs_debugwin.h
new file mode 100644
index 000000000..dc2368ac2
--- /dev/null
+++ b/tdehtml/ecma/kjs_debugwin.h
@@ -0,0 +1,285 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001,2003 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_DEBUGGER_H_
+#define _KJS_DEBUGGER_H_
+
+#include <tqglobal.h>
+
+#define KJS_DEBUGGER
+
+#ifdef KJS_DEBUGGER
+
+#include <tqwidget.h>
+#include <tqmultilineedit.h>
+#include <tqpixmap.h>
+#include <tqptrlist.h>
+#include <tqptrstack.h>
+#include <tqcheckbox.h>
+#include <kdialogbase.h>
+#include <kmainwindow.h>
+#include <tqscrollview.h>
+
+#include <kjs/debugger.h>
+
+#include "dom/dom_misc.h"
+
+class TQListBox;
+class TQComboBox;
+class KActionCollection;
+class KAction;
+
+namespace KJS {
+ class FunctionImp;
+ class List;
+ class Interpreter;
+ class KJSDebugWin;
+
+ class SourceFile : public DOM::DomShared
+ {
+ public:
+ SourceFile(TQString u, TQString c, Interpreter *interp)
+ : url(u), code(c), interpreter(interp) {}
+ TQString getCode();
+ TQString url;
+ TQString code;
+ Interpreter *interpreter;
+ };
+
+ /**
+ * @internal
+ *
+ * When kjs parses some code, it generates a source code fragment (or just "source").
+ * This is referenced by its source id in future calls to functions such as atLine()
+ * and callEvent(). We keep a record of all source fragments parsed in order to display
+ * then to the user.
+ *
+ * For .js files, the source fragment will be the entire file. For js code included
+ * in html files, however, there may be multiple source fragments within the one file
+ * (e.g. multiple SCRIPT tags or onclick="..." attributes)
+ *
+ * In the case where a single file has multiple source fragments, the source objects
+ * for these fragments will all point to the same SourceFile for their code.
+ */
+ class SourceFragment
+ {
+ public:
+ SourceFragment(int sid, int bl, int el, SourceFile *sf);
+ ~SourceFragment();
+
+ int sourceId;
+ int baseLine;
+ int errorLine;
+ SourceFile *sourceFile;
+ private:
+ SourceFragment(const SourceFragment& other);
+ SourceFragment& operator = (const SourceFragment& other);
+ };
+
+ class KJSErrorDialog : public KDialogBase {
+ Q_OBJECT
+ public:
+ KJSErrorDialog(TQWidget *parent, const TQString& errorMessage, bool showDebug);
+ virtual ~KJSErrorDialog();
+
+ bool debugSelected() const { return m_debugSelected; }
+ bool dontShowAgain() const { return m_dontShowAgainCb->isChecked(); }
+
+ protected slots:
+ virtual void slotUser1();
+
+ private:
+ TQCheckBox *m_dontShowAgainCb;
+ bool m_debugSelected;
+ };
+
+ class EvalMultiLineEdit : public TQMultiLineEdit {
+ Q_OBJECT
+ public:
+ EvalMultiLineEdit(TQWidget *parent);
+ const TQString & code() const { return m_code; }
+ protected:
+ void keyPressEvent(TQKeyEvent * e);
+ private:
+ TQString m_code;
+ };
+
+ class SourceDisplay : public TQScrollView {
+ Q_OBJECT
+ public:
+ SourceDisplay(KJSDebugWin *debugWin, TQWidget *parent, const char *name = 0);
+ ~SourceDisplay();
+
+ void setSource(SourceFile *sourceFile);
+ void setCurrentLine(int lineno, bool doCenter = true);
+
+ signals:
+ void lineDoubleClicked(int lineno);
+
+ protected:
+ virtual void contentsMousePressEvent(TQMouseEvent *e);
+ virtual void showEvent(TQShowEvent *);
+ virtual void drawContents(TQPainter *p, int clipx, int clipy, int clipw, int cliph);
+
+ TQString m_source;
+ int m_currentLine;
+ SourceFile *m_sourceFile;
+ TQStringList m_lines;
+
+ KJSDebugWin *m_debugWin;
+ TQFont m_font;
+ TQPixmap m_breakpointIcon;
+ };
+
+ /**
+ * @internal
+ *
+ * KJSDebugWin represents the debugger window that is visible to the user. It contains
+ * a stack frame list, a code viewer and a source fragment selector, plus buttons
+ * to control execution including next, step and continue.
+ *
+ * There is only one debug window per program. This can be obtained by calling #instance
+ */
+ class KJSDebugWin : public KMainWindow, public Debugger, public TDEInstance
+ {
+ Q_OBJECT
+ friend class SourceDisplay;
+ public:
+ KJSDebugWin(TQWidget *parent=0, const char *name=0);
+ virtual ~KJSDebugWin();
+
+ static KJSDebugWin *createInstance();
+ static void destroyInstance();
+ static KJSDebugWin *debugWindow() { return kjs_html_debugger; }
+
+ enum Mode { Disabled = 0, // No break on any statements
+ Next = 1, // Will break on next statement in current context
+ Step = 2, // Will break on next statement in current or deeper context
+ Continue = 3, // Will continue until next breakpoint
+ Stop = 4 // The script will stop execution completely,
+ // as soon as possible
+ };
+
+ void setSourceLine(int sourceId, int lineno);
+ void setNextSourceInfo(TQString url, int baseLine);
+ void sourceChanged(Interpreter *interpreter, TQString url);
+ bool inSession() const { return !m_execStates.isEmpty(); }
+ void setMode(Mode m) { m_mode = m; }
+ void clearInterpreter(Interpreter *interpreter);
+ ExecState *getExecState() const { return m_execStates.top(); }
+
+ // functions overridden from KJS:Debugger
+ bool sourceParsed(ExecState *exec, int sourceId,
+ const UString &source, int errorLine);
+ bool sourceUnused(ExecState * exec, int sourceId);
+ bool exception(ExecState *exec, const Value &value, bool inTryCatch);
+ bool atStatement(ExecState *exec);
+ bool enterContext(ExecState *exec);
+ bool exitContext(ExecState *exec, const Completion &completion);
+
+ public slots:
+ void slotNext();
+ void slotStep();
+ void slotContinue();
+ void slotStop();
+ void slotBreakNext();
+ void slotToggleBreakpoint(int lineno);
+ void slotShowFrame(int frameno);
+ void slotSourceSelected(int sourceSelIndex);
+ void slotEval();
+
+ protected:
+
+ void closeEvent(TQCloseEvent *e);
+ bool eventFilter(TQObject *obj, TQEvent *evt);
+ void disableOtherWindows();
+ void enableOtherWindows();
+
+ private:
+
+ SourceFile *getSourceFile(Interpreter *interpreter, TQString url);
+ void setSourceFile(Interpreter *interpreter, TQString url, SourceFile *sourceFile);
+ void removeSourceFile(Interpreter *interpreter, TQString url);
+
+ void checkBreak(ExecState *exec);
+ void enterSession(ExecState *exec);
+ void leaveSession();
+ void displaySourceFile(SourceFile *sourceFile, bool forceRefresh);
+ void updateContextList();
+
+ TQString contextStr(const Context &ctx);
+
+ struct Breakpoint {
+ int sourceId;
+ int lineno;
+ };
+ Breakpoint *m_breakpoints;
+ int m_breakpointCount;
+ bool setBreakpoint(int sourceId, int lineno);
+ bool deleteBreakpoint(int sourceId, int lineno);
+ bool haveBreakpoint(SourceFile *sourceFile, int line0, int line1);
+ bool haveBreakpoint(int sourceId, int line0, int line1) const {
+ for (int i = 0; i < m_breakpointCount; i++) {
+ if (m_breakpoints[i].sourceId == sourceId &&
+ m_breakpoints[i].lineno >= line0 &&
+ m_breakpoints[i].lineno <= line1)
+ return true;
+ }
+ return false;
+ }
+
+ SourceFile *m_curSourceFile;
+ Mode m_mode;
+ TQString m_nextSourceUrl;
+ int m_nextSourceBaseLine;
+ TQPtrStack<ExecState> m_execStates;
+ ExecState **m_execs;
+ int m_execsCount;
+ int m_execsAlloc;
+ int m_steppingDepth;
+
+ TQMap<TQString,SourceFile*> m_sourceFiles; /* maps url->SourceFile */
+ TQMap<int,SourceFragment*> m_sourceFragments; /* maps SourceId->SourceFragment */
+ TQPtrList<SourceFile> m_sourceSelFiles; /* maps combobox index->SourceFile */
+
+ KActionCollection *m_actionCollection;
+ TQPixmap m_stopIcon;
+ TQPixmap m_emptyIcon;
+ SourceDisplay *m_sourceDisplay;
+ TQListBox *m_contextList;
+
+ KAction *m_stepAction;
+ KAction *m_nextAction;
+ KAction *m_continueAction;
+ KAction *m_stopAction;
+ KAction *m_breakAction;
+
+ TQComboBox *m_sourceSel;
+ EvalMultiLineEdit *m_evalEdit;
+ int m_evalDepth;
+
+ static KJSDebugWin *kjs_html_debugger;
+ };
+
+} // namespace
+
+#endif // KJS_DEBUGGER
+
+#endif // _KJS_DEBUGGER_H_
diff --git a/tdehtml/ecma/kjs_dom.cpp b/tdehtml/ecma/kjs_dom.cpp
new file mode 100644
index 000000000..71e91d7ef
--- /dev/null
+++ b/tdehtml/ecma/kjs_dom.cpp
@@ -0,0 +1,1849 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <tdehtmlview.h>
+#include "xml/dom2_eventsimpl.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_layer.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmltags.h" // ID_*
+#include "misc/htmlattrs.h" // ATTR_*
+#include "html/html_baseimpl.h"
+#include <kdebug.h>
+#include <tdehtml_part.h>
+
+#include "kjs_dom.h"
+#include "kjs_html.h"
+#include "kjs_css.h"
+#include "kjs_range.h"
+#include "kjs_traversal.h"
+#include "kjs_events.h"
+#include "kjs_views.h"
+#include "kjs_window.h"
+#include "dom/dom_exception.h"
+#include "kjs_dom.lut.h"
+#include "tdehtmlpart_p.h"
+
+namespace KJS {
+
+// -------------------------------------------------------------------------
+/* Source for DOMNodeConstantsTable.
+@begin DOMNodeConstantsTable 11
+ ELEMENT_NODE DOM::Node::ELEMENT_NODE DontDelete|ReadOnly
+ ATTRIBUTE_NODE DOM::Node::ATTRIBUTE_NODE DontDelete|ReadOnly
+ TEXT_NODE DOM::Node::TEXT_NODE DontDelete|ReadOnly
+ CDATA_SECTION_NODE DOM::Node::CDATA_SECTION_NODE DontDelete|ReadOnly
+ ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE DontDelete|ReadOnly
+ ENTITY_NODE DOM::Node::ENTITY_NODE DontDelete|ReadOnly
+ PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
+ COMMENT_NODE DOM::Node::COMMENT_NODE DontDelete|ReadOnly
+ DOCUMENT_NODE DOM::Node::DOCUMENT_NODE DontDelete|ReadOnly
+ DOCUMENT_TYPE_NODE DOM::Node::DOCUMENT_TYPE_NODE DontDelete|ReadOnly
+ DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE DontDelete|ReadOnly
+ NOTATION_NODE DOM::Node::NOTATION_NODE DontDelete|ReadOnly
+@end
+*/
+IMPLEMENT_CONSTANT_TABLE(DOMNodeConstants,"DOMNodeConstants")
+// -------------------------------------------------------------------------
+/* Source for DOMNodeProtoTable.
+@begin DOMNodeProtoTable 13
+ insertBefore DOMNode::InsertBefore DontDelete|Function 2
+ replaceChild DOMNode::ReplaceChild DontDelete|Function 2
+ removeChild DOMNode::RemoveChild DontDelete|Function 1
+ appendChild DOMNode::AppendChild DontDelete|Function 1
+ hasAttributes DOMNode::HasAttributes DontDelete|Function 0
+ hasChildNodes DOMNode::HasChildNodes DontDelete|Function 0
+ cloneNode DOMNode::CloneNode DontDelete|Function 1
+# DOM2
+ normalize DOMNode::Normalize DontDelete|Function 0
+ isSupported DOMNode::IsSupported DontDelete|Function 2
+# from the EventTarget interface
+ addEventListener DOMNode::AddEventListener DontDelete|Function 3
+ removeEventListener DOMNode::RemoveEventListener DontDelete|Function 3
+ dispatchEvent DOMNode::DispatchEvent DontDelete|Function 1
+# IE extensions
+ contains DOMNode::Contains DontDelete|Function 1
+ insertAdjacentHTML DOMNode::InsertAdjacentHTML DontDelete|Function 2
+# "DOM level 0" (from Gecko DOM reference; also in WinIE)
+ item DOMNode::Item DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMNodeProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMNode", DOMNodeProto, DOMNodeProtoFunc)
+
+const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
+
+DOMNode::DOMNode(ExecState *exec, const DOM::Node& n)
+ : DOMObject(DOMNodeProto::self(exec)), node(n)
+{
+}
+
+DOMNode::DOMNode(const Object& proto, const DOM::Node& n)
+ : DOMObject(proto), node(n)
+{
+}
+
+DOMNode::~DOMNode()
+{
+ ScriptInterpreter::forgetDOMObject(node.handle());
+}
+
+bool DOMNode::toBoolean(ExecState *) const
+{
+ return !node.isNull();
+}
+
+/* Source for DOMNodeTable.
+@begin DOMNodeTable 53
+ nodeName DOMNode::NodeName DontDelete|ReadOnly
+ nodeValue DOMNode::NodeValue DontDelete
+ nodeType DOMNode::NodeType DontDelete|ReadOnly
+ parentNode DOMNode::ParentNode DontDelete|ReadOnly
+ parentElement DOMNode::ParentElement DontDelete|ReadOnly
+ childNodes DOMNode::ChildNodes DontDelete|ReadOnly
+ firstChild DOMNode::FirstChild DontDelete|ReadOnly
+ lastChild DOMNode::LastChild DontDelete|ReadOnly
+ previousSibling DOMNode::PreviousSibling DontDelete|ReadOnly
+ nextSibling DOMNode::NextSibling DontDelete|ReadOnly
+ attributes DOMNode::Attributes DontDelete|ReadOnly
+ namespaceURI DOMNode::NamespaceURI DontDelete|ReadOnly
+# DOM2
+ prefix DOMNode::Prefix DontDelete
+ localName DOMNode::LocalName DontDelete|ReadOnly
+ ownerDocument DOMNode::OwnerDocument DontDelete|ReadOnly
+# DOM3
+ textContent DOMNode::TextContent DontDelete
+# Event handlers
+# IE also has: onactivate, onbefore*, oncontextmenu, oncontrolselect, oncut,
+# ondeactivate, ondrag*, ondrop, onfocusin, onfocusout, onhelp, onmousewheel,
+# onmove*, onpaste, onpropertychange, onreadystatechange, onresizeend/start,
+# onselectionchange, onstop
+ onabort DOMNode::OnAbort DontDelete
+ onblur DOMNode::OnBlur DontDelete
+ onchange DOMNode::OnChange DontDelete
+ onclick DOMNode::OnClick DontDelete
+ ondblclick DOMNode::OnDblClick DontDelete
+ ondragdrop DOMNode::OnDragDrop DontDelete
+ onerror DOMNode::OnError DontDelete
+ onfocus DOMNode::OnFocus DontDelete
+ onkeydown DOMNode::OnKeyDown DontDelete
+ onkeypress DOMNode::OnKeyPress DontDelete
+ onkeyup DOMNode::OnKeyUp DontDelete
+ onload DOMNode::OnLoad DontDelete
+ onmousedown DOMNode::OnMouseDown DontDelete
+ onmousemove DOMNode::OnMouseMove DontDelete
+ onmouseout DOMNode::OnMouseOut DontDelete
+ onmouseover DOMNode::OnMouseOver DontDelete
+ onmouseup DOMNode::OnMouseUp DontDelete
+ onmove DOMNode::OnMove DontDelete
+ onreset DOMNode::OnReset DontDelete
+ onresize DOMNode::OnResize DontDelete
+ onselect DOMNode::OnSelect DontDelete
+ onsubmit DOMNode::OnSubmit DontDelete
+ onunload DOMNode::OnUnload DontDelete
+# IE extensions
+ offsetLeft DOMNode::OffsetLeft DontDelete|ReadOnly
+ offsetTop DOMNode::OffsetTop DontDelete|ReadOnly
+ offsetWidth DOMNode::OffsetWidth DontDelete|ReadOnly
+ offsetHeight DOMNode::OffsetHeight DontDelete|ReadOnly
+ offsetParent DOMNode::OffsetParent DontDelete|ReadOnly
+ clientWidth DOMNode::ClientWidth DontDelete|ReadOnly
+ clientHeight DOMNode::ClientHeight DontDelete|ReadOnly
+ scrollLeft DOMNode::ScrollLeft DontDelete
+ scrollTop DOMNode::ScrollTop DontDelete
+ scrollWidth DOMNode::ScrollWidth DontDelete|ReadOnly
+ scrollHeight DOMNode::ScrollHeight DontDelete|ReadOnly
+ sourceIndex DOMNode::SourceIndex DontDelete|ReadOnly
+@end
+*/
+Value DOMNode::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMNode::tryGet " << propertyName.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMNode, DOMObject>(exec, propertyName, &DOMNodeTable, this);
+}
+
+static tdehtml::RenderObject* handleBodyRootQuirk(const DOM::Node& node, tdehtml::RenderObject* rend, int token)
+{
+ //This emulates the quirks of various height/width properties on the viewport and root. Note that it
+ //is (mostly) IE-compatible in quirks, and mozilla-compatible in strict.
+ if (!rend) return 0;
+
+ bool quirksMode = rend->style() && rend->style()->htmlHacks();
+
+ //There are a couple quirks here. One is that in quirks mode body is always forwarded to root...
+ //This is relevant for even the scrollTop/scrollLeft type properties.
+ if (quirksMode && node.handle()->id() == ID_BODY) {
+ while (rend->parent() && !rend->isRoot())
+ rend = rend->parent();
+ }
+
+ //Also, some properties of the root are really done in terms of the viewport.
+ //These are {offset/client}{Height/Width}. The offset versions do it only in
+ //quirks mode, the client always.
+ if (!rend->isRoot()) return rend; //Don't care about non-root things here!
+ bool needViewport = false;
+
+ switch (token) {
+ case DOMNode::OffsetHeight:
+ case DOMNode::OffsetWidth:
+ needViewport = quirksMode;
+ break;
+ case DOMNode::ClientHeight:
+ case DOMNode::ClientWidth:
+ needViewport = true;
+ break;
+ }
+
+ if (needViewport) {
+ //Scan up to find the new target
+ while (rend->parent())
+ rend = rend->parent();
+ }
+ return rend;
+}
+
+Value DOMNode::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case NodeName:
+ return String(node.nodeName());
+ case NodeValue:
+ return getString(node.nodeValue()); // initially null, per domts/level1/core/hc_documentcreateelement.html
+ case NodeType:
+ return Number((unsigned int)node.nodeType());
+ case ParentNode:
+ return getDOMNode(exec,node.parentNode());
+ case ParentElement: // IE only apparently
+ return getDOMNode(exec,node.parentNode());
+ case ChildNodes:
+ return getDOMNodeList(exec,node.childNodes());
+ case FirstChild:
+ return getDOMNode(exec,node.firstChild());
+ case LastChild:
+ return getDOMNode(exec,node.lastChild());
+ case PreviousSibling:
+ return getDOMNode(exec,node.previousSibling());
+ case NextSibling:
+ return getDOMNode(exec,node.nextSibling());
+ case Attributes:
+ return getDOMNamedNodeMap(exec,node.attributes());
+ case NamespaceURI:
+ return getString(node.namespaceURI()); // Moz returns null if not set (dom/namespaces.html)
+ case Prefix:
+ return getString(node.prefix()); // Moz returns null if not set (dom/namespaces.html)
+ case TextContent:
+ return getString(node.textContent()); //DOM3 says return null, but I really should test mozilla..
+ case LocalName:
+ return getString(node.localName()); // Moz returns null if not set (dom/namespaces.html)
+ case OwnerDocument:
+ return getDOMNode(exec,node.ownerDocument());
+ case OnAbort:
+ return getListener(DOM::EventImpl::ABORT_EVENT);
+ case OnBlur:
+ return getListener(DOM::EventImpl::BLUR_EVENT);
+ case OnChange:
+ return getListener(DOM::EventImpl::CHANGE_EVENT);
+ case OnClick:
+ return getListener(DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
+ case OnDblClick:
+ return getListener(DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
+ case OnDragDrop:
+ return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT);
+ case OnError:
+ return getListener(DOM::EventImpl::ERROR_EVENT);
+ case OnFocus:
+ return getListener(DOM::EventImpl::FOCUS_EVENT);
+ case OnKeyDown:
+ return getListener(DOM::EventImpl::KEYDOWN_EVENT);
+ case OnKeyPress:
+ return getListener(DOM::EventImpl::KEYPRESS_EVENT);
+ case OnKeyUp:
+ return getListener(DOM::EventImpl::KEYUP_EVENT);
+ case OnLoad:
+ return getListener(DOM::EventImpl::LOAD_EVENT);
+ case OnMouseDown:
+ return getListener(DOM::EventImpl::MOUSEDOWN_EVENT);
+ case OnMouseMove:
+ return getListener(DOM::EventImpl::MOUSEMOVE_EVENT);
+ case OnMouseOut:
+ return getListener(DOM::EventImpl::MOUSEOUT_EVENT);
+ case OnMouseOver:
+ return getListener(DOM::EventImpl::MOUSEOVER_EVENT);
+ case OnMouseUp:
+ return getListener(DOM::EventImpl::MOUSEUP_EVENT);
+ case OnMove:
+ return getListener(DOM::EventImpl::KHTML_MOVE_EVENT);
+ case OnReset:
+ return getListener(DOM::EventImpl::RESET_EVENT);
+ case OnResize:
+ return getListener(DOM::EventImpl::RESIZE_EVENT);
+ case OnSelect:
+ return getListener(DOM::EventImpl::SELECT_EVENT);
+ case OnSubmit:
+ return getListener(DOM::EventImpl::SUBMIT_EVENT);
+ case OnUnload:
+ return getListener(DOM::EventImpl::UNLOAD_EVENT);
+ case SourceIndex: {
+ // Retrieves the ordinal position of the object, in source order, as the object
+ // appears in the document's all collection
+ // i.e. document.all[n.sourceIndex] == n
+ DOM::Document doc = node.ownerDocument();
+ if (doc.isHTMLDocument()) {
+ DOM::HTMLCollection all = static_cast<DOM::HTMLDocument>(doc).all();
+ unsigned long i = 0;
+ DOM::Node n = all.firstItem();
+ for ( ; !n.isNull() && n != node; n = all.nextItem() )
+ ++i;
+ Q_ASSERT( !n.isNull() ); // node not in document.all !?
+ return Number(i);
+ }
+ }
+ default:
+ // no DOM standard, found in IE only
+
+ // Make sure our layout is up to date before we allow a query on these attributes.
+ DOM::DocumentImpl* docimpl = node.handle()->getDocument();
+ if (docimpl) {
+ docimpl->updateLayout();
+ }
+
+ tdehtml::RenderObject *rend = node.handle()->renderer();
+
+ //In quirks mode, may need to forward if to body.
+ rend = handleBodyRootQuirk(node, rend, token);
+
+ switch (token) {
+ case OffsetLeft:
+ return rend ? static_cast<Value>( Number( rend->offsetLeft() ) ) : Number(0);
+ case OffsetTop:
+ return rend ? static_cast<Value>( Number( rend->offsetTop() ) ) : Number(0);
+ case OffsetWidth:
+ return rend ? static_cast<Value>( Number( rend->offsetWidth() ) ) : Number(0);
+ case OffsetHeight:
+ return rend ? static_cast<Value>( Number( rend->offsetHeight() ) ) : Number(0);
+ case OffsetParent:
+ {
+ tdehtml::RenderObject* par = rend ? rend->offsetParent() : 0;
+ return getDOMNode( exec, par ? par->element() : 0 );
+ }
+ case ClientWidth:
+ return rend ? static_cast<Value>( Number( rend->clientWidth() ) ) : Number(0);
+ case ClientHeight:
+ return rend ? static_cast<Value>( Number( rend->clientHeight() ) ) : Number(0);
+ case ScrollWidth:
+ return rend ? static_cast<Value>( Number(rend->scrollWidth()) ) : Number(0);
+ case ScrollHeight:
+ return rend ? static_cast<Value>( Number(rend->scrollHeight()) ) : Number(0);
+ case ScrollLeft:
+ if (rend && rend->layer()) {
+ if (rend->isRoot() && !rend->style()->hidesOverflow())
+ return Number( node.ownerDocument().view() ? node.ownerDocument().view()->contentsX() : 0);
+ return Number( rend->layer()->scrollXOffset() );
+ }
+ return Number( 0 );
+ case ScrollTop:
+ if (rend && rend->layer()) {
+ if (rend->isRoot() && !rend->style()->hidesOverflow())
+ return Number( node.ownerDocument().view() ? node.ownerDocument().view()->contentsY() : 0);
+ return Number( rend->layer()->scrollYOffset() );
+ }
+ return Number( 0 );
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMNode::getValueProperty : " << token << endl;
+ break;
+ }
+ }
+ return Undefined();
+}
+
+
+void DOMNode::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMNode::tryPut " << propertyName.qstring() << endl;
+#endif
+ DOMObjectLookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr,
+ &DOMNodeTable, this );
+}
+
+void DOMNode::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
+{
+ switch (token) {
+ case NodeValue:
+ node.setNodeValue(value.toString(exec).string());
+ break;
+ case Prefix:
+ node.setPrefix(value.toString(exec).string());
+ break;
+ case TextContent:
+ node.setTextContent(value.toString(exec).string());
+ break;
+ case OnAbort:
+ setListener(exec,DOM::EventImpl::ABORT_EVENT,value);
+ break;
+ case OnBlur:
+ setListener(exec,DOM::EventImpl::BLUR_EVENT,value);
+ break;
+ case OnChange:
+ setListener(exec,DOM::EventImpl::CHANGE_EVENT,value);
+ break;
+ case OnClick:
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
+ break;
+ case OnDblClick:
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
+ break;
+ case OnDragDrop:
+ setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
+ break;
+ case OnError:
+ setListener(exec,DOM::EventImpl::ERROR_EVENT,value);
+ break;
+ case OnFocus:
+ setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
+ break;
+ case OnKeyDown:
+ setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
+ break;
+ case OnKeyPress:
+ setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
+ break;
+ case OnKeyUp:
+ setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
+ break;
+ case OnLoad:
+ setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
+ break;
+ case OnMouseDown:
+ setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
+ break;
+ case OnMouseMove:
+ setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
+ break;
+ case OnMouseOut:
+ setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
+ break;
+ case OnMouseOver:
+ setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
+ break;
+ case OnMouseUp:
+ setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
+ break;
+ case OnMove:
+ setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
+ break;
+ case OnReset:
+ setListener(exec,DOM::EventImpl::RESET_EVENT,value);
+ break;
+ case OnResize:
+ setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
+ break;
+ case OnSelect:
+ setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
+ break;
+ case OnSubmit:
+ setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
+ break;
+ case OnUnload:
+ setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
+ break;
+ default:
+ // Make sure our layout is up to date
+ DOM::DocumentImpl* docimpl = node.handle()->getDocument();
+ if (docimpl)
+ docimpl->updateLayout();
+
+ tdehtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
+
+ //In quirks mode, may need to forward.
+ rend = handleBodyRootQuirk(node, rend, token);
+
+ switch (token) {
+ case ScrollLeft:
+ if (rend && rend->layer()) {
+ if (rend->style()->hidesOverflow())
+ rend->layer()->scrollToXOffset(value.toInt32(exec));
+ else if (rend->isRoot()) {
+ TQScrollView* sview = node.ownerDocument().view();
+ if (sview)
+ sview->setContentsPos(value.toInt32(exec), sview->contentsY());
+ }
+ }
+ break;
+ case ScrollTop:
+ if (rend && rend->layer()) {
+ if (rend->style()->hidesOverflow())
+ rend->layer()->scrollToYOffset(value.toInt32(exec));
+ else if (rend->isRoot()) {
+ TQScrollView* sview = node.ownerDocument().view();
+ if (sview)
+ sview->setContentsPos(sview->contentsX(), value.toInt32(exec));
+ }
+ }
+ break;
+ default:
+ kdDebug(6070) << "WARNING: DOMNode::putValueProperty unhandled token " << token << endl;
+ }
+ }
+}
+
+Value DOMNode::toPrimitive(ExecState *exec, Type /*preferred*/) const
+{
+ if (node.isNull())
+ return Null();
+
+ return String(toString(exec));
+}
+
+UString DOMNode::toString(ExecState *) const
+{
+ if (node.isNull())
+ return "null";
+ UString s;
+
+ DOM::Element e = node;
+ if ( !e.isNull() ) {
+ s = static_cast<UString>(e.nodeName().string());
+ } else
+ s = className(); // fallback
+
+ return "[object " + s + "]";
+}
+
+void DOMNode::setListener(ExecState *exec, int eventId, const Value& func) const
+{
+ node.handle()->setHTMLEventListener(eventId,Window::retrieveActive(exec)->getJSEventListener(func,true));
+}
+
+Value DOMNode::getListener(int eventId) const
+{
+ DOM::EventListener *listener = node.handle()->getHTMLEventListener(eventId);
+ JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
+ if ( jsListener && jsListener->listenerObjImp() )
+ return jsListener->listenerObj();
+ else
+ return Null();
+}
+
+void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
+{
+}
+
+Value DOMNodeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( DOMNode, thisObj );
+ DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
+ switch (id) {
+ case DOMNode::HasAttributes:
+ return Boolean(node.hasAttributes());
+ case DOMNode::HasChildNodes:
+ return Boolean(node.hasChildNodes());
+ case DOMNode::CloneNode:
+ return getDOMNode(exec,node.cloneNode(args[0].toBoolean(exec)));
+ case DOMNode::Normalize:
+ node.normalize();
+ return Undefined();
+ case DOMNode::IsSupported:
+ return Boolean(node.isSupported(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMNode::AddEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ node.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
+ return Undefined();
+ }
+ case DOMNode::RemoveEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ node.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
+ return Undefined();
+ }
+ case DOMNode::DispatchEvent:
+ return Boolean(node.dispatchEvent(toEvent(args[0])));
+ case DOMNode::AppendChild:
+ return getDOMNode(exec,node.appendChild(toNode(args[0])));
+ case DOMNode::RemoveChild:
+ return getDOMNode(exec,node.removeChild(toNode(args[0])));
+ case DOMNode::InsertBefore:
+ return getDOMNode(exec,node.insertBefore(toNode(args[0]), toNode(args[1])));
+ case DOMNode::ReplaceChild:
+ return getDOMNode(exec,node.replaceChild(toNode(args[0]), toNode(args[1])));
+ case DOMNode::Contains:
+ {
+ DOM::Node other = toNode(args[0]);
+ if (!other.isNull() && node.nodeType()==DOM::Node::ELEMENT_NODE)
+ {
+ DOM::NodeBaseImpl *impl = static_cast<DOM::NodeBaseImpl *>(node.handle());
+ bool retval = other.handle()->isAncestor(impl);
+ return Boolean(retval);
+ }
+ return Undefined();
+ }
+ case DOMNode::InsertAdjacentHTML:
+ {
+ // see http://www.faqts.com/knowledge_base/view.phtml/aid/5756
+ // and http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertAdjacentHTML.asp
+ Range range = node.ownerDocument().createRange();
+
+ range.setStartBefore(node);
+
+ DocumentFragment docFrag = range.createContextualFragment(args[1].toString(exec).string());
+
+ DOMString where = args[0].toString(exec).string();
+
+ if (where == "beforeBegin" || where == "BeforeBegin")
+ node.parentNode().insertBefore(docFrag, node);
+ else if (where == "afterBegin" || where == "AfterBegin")
+ node.insertBefore(docFrag, node.firstChild());
+ else if (where == "beforeEnd" || where == "BeforeEnd")
+ return getDOMNode(exec, node.appendChild(docFrag));
+ else if (where == "afterEnd" || where == "AfterEnd")
+ if (!node.nextSibling().isNull())
+ node.parentNode().insertBefore(docFrag, node.nextSibling());
+ else
+ node.parentNode().appendChild(docFrag);
+
+ return Undefined();
+ }
+ case DOMNode::Item:
+ return getDOMNode(exec, node.childNodes().item(static_cast<unsigned long>(args[0].toNumber(exec))));
+ }
+
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+/*
+@begin DOMNodeListProtoTable 2
+ item DOMNodeList::Item DontDelete|Function 1
+# IE extension (IE treats DOMNodeList like an HTMLCollection)
+ namedItem DOMNodeList::NamedItem DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMNodeListProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMNodeListProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMNodeList", DOMNodeListProto, DOMNodeListProtoFunc)
+
+
+const ClassInfo DOMNodeList::info = { "NodeList", 0, 0, 0 };
+
+DOMNodeList::DOMNodeList(ExecState *exec, const DOM::NodeList& l)
+ : DOMObject(DOMNodeListProto::self(exec)), list(l) { }
+
+DOMNodeList::~DOMNodeList()
+{
+ ScriptInterpreter::forgetDOMObject(list.handle());
+}
+
+// We have to implement hasProperty since we don't use a hashtable for 'length'
+// ## this breaks "for (..in..)" though.
+bool DOMNodeList::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ if (p == lengthPropertyName)
+ return true;
+
+ if (ObjectImp::hasProperty(exec, p))
+ return true;
+
+ bool ok;
+ unsigned long pos = p.toULong(&ok);
+ if (ok && pos < list.length())
+ return true;
+
+ // ## missing: accept p if item id...
+ return false;
+}
+
+Value DOMNodeList::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMNodeList::tryGet " << p.ascii() << endl;
+#endif
+ if (p == lengthPropertyName)
+ return Number(list.length());
+
+ // Look in the prototype (for functions) before assuming it's an item's name
+ Object proto = Object::dynamicCast(prototype());
+ if (proto.isValid() && proto.hasProperty(exec,p))
+ return proto.get(exec,p);
+
+ Value result;
+
+ // array index ?
+ bool ok;
+ long unsigned int idx = p.toULong(&ok);
+ if (ok)
+ result = getDOMNode(exec,list.item(idx));
+ else {
+ // Find by ID
+ DOM::HTMLElement e;
+ unsigned long l = list.length();
+ bool found = false;
+
+ for ( unsigned long i = 0; i < l; i++ )
+ if ( ( e = list.item( i ) ).id() == p.string() ) {
+ result = getDOMNode(exec, list.item( i ) );
+ found = true;
+ break;
+ }
+
+ if ( !found )
+ result = ObjectImp::get(exec, p);
+ }
+
+ return result;
+}
+
+ReferenceList DOMNodeList::propList(ExecState *exec, bool recursive)
+{
+ ReferenceList properties = ObjectImp::propList(exec,recursive);
+
+ for (unsigned i = 0; i < list.length(); ++i) {
+ if (!ObjectImp::hasProperty(exec,Identifier::from(i))) {
+ properties.append(Reference(this, i));
+ }
+ }
+
+ if (!ObjectImp::hasProperty(exec, lengthPropertyName))
+ properties.append(Reference(this, lengthPropertyName));
+
+ return properties;
+}
+
+// Need to support both get and call, so that list[0] and list(0) work.
+Value DOMNodeList::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ // This code duplication is necessary, DOMNodeList isn't a DOMFunction
+ Value val;
+ try {
+ val = tryCall(exec, thisObj, args);
+ }
+ // pity there's no way to distinguish between these in JS code
+ catch (...) {
+ Object err = Error::create(exec, GeneralError, "Exception from DOMNodeList");
+ exec->setException(err);
+ }
+ return val;
+}
+
+Value DOMNodeList::tryCall(ExecState *exec, Object &, const List &args)
+{
+ // Do not use thisObj here. See HTMLCollection.
+ UString s = args[0].toString(exec);
+
+ // index-based lookup?
+ bool ok;
+ unsigned int u = s.toULong(&ok);
+ if (ok)
+ return getDOMNode(exec,list.item(u));
+
+ // try lookup by name
+ // ### NodeList::namedItem() would be cool to have
+ // ### do we need to support the same two arg overload as in HTMLCollection?
+ Value result = tryGet(exec, Identifier(s));
+
+ if (result.isValid())
+ return result;
+
+ return Undefined();
+}
+
+// Not a prototype class currently, but should probably be converted to one
+Value DOMNodeListProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMNodeList, thisObj );
+ DOM::NodeList list = static_cast<DOMNodeList *>(thisObj.imp())->nodeList();
+ switch (id) {
+ case KJS::DOMNodeList::Item:
+ return getDOMNode(exec, list.item(args[0].toInt32(exec)));
+ case KJS::DOMNodeList::NamedItem:
+ {
+ // Not a real namedItem implementation like the one HTMLCollection has.
+ // This is only an IE extension...
+ DOM::HTMLElement e;
+ unsigned long len = list.length();
+ DOM::DOMString s = args[0].toString(exec).string();
+
+ for ( unsigned long i = 0; i < len; i++ )
+ {
+ e = list.item( i );
+ if ( !e.isNull() && (
+ e.id() == s || static_cast<ElementImpl *>(e.handle())->getAttribute(ATTR_NAME) == s )
+ )
+ {
+ return getDOMNode(exec, e );
+ }
+ }
+ return Null(); // see HTMLCollection::NamedItem implementation
+ }
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+//### FIXME: link to the node prototype.
+const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, 0 };
+
+/* Source for DOMAttrTable.
+@begin DOMAttrTable 5
+ name DOMAttr::Name DontDelete|ReadOnly
+ specified DOMAttr::Specified DontDelete|ReadOnly
+ value DOMAttr::ValueProperty DontDelete
+ ownerElement DOMAttr::OwnerElement DontDelete|ReadOnly
+@end
+*/
+Value DOMAttr::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMAttr::tryGet " << propertyName.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMAttr,DOMNode>(exec, propertyName,
+ &DOMAttrTable, this );
+}
+
+Value DOMAttr::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Name:
+ return String(static_cast<DOM::Attr>(node).name());
+ case Specified:
+ return Boolean(static_cast<DOM::Attr>(node).specified());
+ case ValueProperty:
+ return String(static_cast<DOM::Attr>(node).value());
+ case OwnerElement: // DOM2
+ return getDOMNode(exec,static_cast<DOM::Attr>(node).ownerElement());
+ }
+ return Value(); // not reached
+}
+
+void DOMAttr::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMAttr::tryPut " << propertyName.qstring() << endl;
+#endif
+ DOMObjectLookupPut<DOMAttr,DOMNode>(exec, propertyName, value, attr,
+ &DOMAttrTable, this );
+}
+
+void DOMAttr::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
+{
+ switch (token) {
+ case ValueProperty:
+ static_cast<DOM::Attr>(node).setValue(value.toString(exec).string());
+ return;
+ default:
+ kdDebug(6070) << "WARNING: DOMAttr::putValueProperty unhandled token " << token << endl;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+/* Source for DOMDocumentProtoTable.
+@begin DOMDocumentProtoTable 23
+ createElement DOMDocument::CreateElement DontDelete|Function 1
+ createDocumentFragment DOMDocument::CreateDocumentFragment DontDelete|Function 1
+ createTextNode DOMDocument::CreateTextNode DontDelete|Function 1
+ createComment DOMDocument::CreateComment DontDelete|Function 1
+ createCDATASection DOMDocument::CreateCDATASection DontDelete|Function 1
+ createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
+ createAttribute DOMDocument::CreateAttribute DontDelete|Function 1
+ createEntityReference DOMDocument::CreateEntityReference DontDelete|Function 1
+ getElementsByTagName DOMDocument::GetElementsByTagName DontDelete|Function 1
+ importNode DOMDocument::ImportNode DontDelete|Function 2
+ createElementNS DOMDocument::CreateElementNS DontDelete|Function 2
+ createAttributeNS DOMDocument::CreateAttributeNS DontDelete|Function 2
+ getElementsByTagNameNS DOMDocument::GetElementsByTagNameNS DontDelete|Function 2
+ getElementById DOMDocument::GetElementById DontDelete|Function 1
+ createRange DOMDocument::CreateRange DontDelete|Function 0
+ createNodeIterator DOMDocument::CreateNodeIterator DontDelete|Function 3
+ createTreeWalker DOMDocument::CreateTreeWalker DontDelete|Function 4
+ createEvent DOMDocument::CreateEvent DontDelete|Function 1
+ getOverrideStyle DOMDocument::GetOverrideStyle DontDelete|Function 2
+ abort DOMDocument::Abort DontDelete|Function 0
+ load DOMDocument::Load DontDelete|Function 1
+ loadXML DOMDocument::LoadXML DontDelete|Function 2
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMDocumentProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(DocumentPseudoCtor, "Document", DOMDocumentProto)
+
+const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
+
+/* Source for DOMDocumentTable.
+@begin DOMDocumentTable 4
+ doctype DOMDocument::DocType DontDelete|ReadOnly
+ implementation DOMDocument::Implementation DontDelete|ReadOnly
+ characterSet DOMDocument::CharacterSet DontDelete|ReadOnly
+ documentElement DOMDocument::DocumentElement DontDelete|ReadOnly
+ styleSheets DOMDocument::StyleSheets DontDelete|ReadOnly
+ preferredStylesheetSet DOMDocument::PreferredStylesheetSet DontDelete|ReadOnly
+ selectedStylesheetSet DOMDocument::SelectedStylesheetSet DontDelete
+ readyState DOMDocument::ReadyState DontDelete|ReadOnly
+ defaultView DOMDocument::DefaultView DontDelete|ReadOnly
+ async DOMDocument::Async DontDelete
+@end
+*/
+
+DOMDocument::DOMDocument(ExecState *exec, const DOM::Document& d)
+ : DOMNode(DOMDocumentProto::self(exec), d) { }
+
+DOMDocument::DOMDocument(const Object& proto, const DOM::Document& d)
+ : DOMNode(proto, d) { }
+
+DOMDocument::~DOMDocument()
+{
+ ScriptInterpreter::forgetDOMObject(node.handle());
+}
+
+Value DOMDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMDocument::tryGet " << propertyName.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMDocument, DOMNode>(
+ exec, propertyName, &DOMDocumentTable, this);
+}
+
+Value DOMDocument::getValueProperty(ExecState *exec, int token) const
+{
+ DOM::Document doc = static_cast<DOM::Document>(node);
+
+ switch(token) {
+ case DocType:
+ return getDOMNode(exec,doc.doctype());
+ case Implementation:
+ return getDOMDOMImplementation(exec,doc.implementation());
+ case DocumentElement:
+ return getDOMNode(exec,doc.documentElement());
+ case CharacterSet: {
+ DOM::DocumentImpl* docImpl = static_cast<DOM::DocumentImpl*>(doc.handle());
+ if (docImpl->part())
+ return String(docImpl->part()->encoding());
+ else
+ return Undefined();
+ }
+ case StyleSheets:
+ //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
+ return getDOMStyleSheetList(exec, doc.styleSheets(), doc);
+ case DOMDocument::DefaultView: // DOM2
+ {
+ KHTMLView *view = node.handle()->getDocument()->view();
+ if (view)
+ return Window::retrieve(view->part());
+ return getDOMAbstractView(exec, doc.defaultView());
+ }
+ case PreferredStylesheetSet:
+ return String(doc.preferredStylesheetSet());
+ case SelectedStylesheetSet:
+ return String(doc.selectedStylesheetSet());
+ case ReadyState:
+ {
+ DOM::DocumentImpl* docimpl = node.handle()->getDocument();
+ if ( docimpl && docimpl->view() )
+ {
+ KHTMLPart* part = docimpl->view()->part();
+ if ( part ) {
+ if (part->d->m_bComplete) return String("complete");
+ if (docimpl->parsing()) return String("loading");
+ return String("loaded");
+ // What does the interactive value mean ?
+ // Missing support for "uninitialized"
+ }
+ }
+ return Undefined();
+ }
+ case Async:
+ return Boolean(doc.async());
+ default:
+ kdDebug(6070) << "WARNING: DOMDocument::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+void DOMDocument::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMDocument::tryPut " << propertyName.qstring() << endl;
+#endif
+ DOMObjectLookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this );
+}
+
+void DOMDocument::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
+{
+ DOM::Document doc = static_cast<DOM::Document>(node);
+ switch (token) {
+ case SelectedStylesheetSet: {
+ doc.setSelectedStylesheetSet(value.toString(exec).string());
+ break;
+ }
+ case Async: {
+ doc.setAsync(value.toBoolean(exec));
+ break;
+ }
+ }
+}
+
+Value DOMDocumentProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMDocument, thisObj );
+ DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
+ DOM::Document doc = static_cast<DOM::Document>(node);
+ String str = args[0].toString(exec);
+ DOM::DOMString s = str.value().string();
+
+ switch(id) {
+ case DOMDocument::CreateElement:
+ return getDOMNode(exec,doc.createElement(s));
+ case DOMDocument::CreateDocumentFragment:
+ return getDOMNode(exec,doc.createDocumentFragment());
+ case DOMDocument::CreateTextNode:
+ return getDOMNode(exec,doc.createTextNode(s));
+ case DOMDocument::CreateComment:
+ return getDOMNode(exec,doc.createComment(s));
+ case DOMDocument::CreateCDATASection:
+ return getDOMNode(exec,doc.createCDATASection(s)); /* TODO: okay ? */
+ case DOMDocument::CreateProcessingInstruction:
+ return getDOMNode(exec,doc.createProcessingInstruction(args[0].toString(exec).string(),
+ args[1].toString(exec).string()));
+ case DOMDocument::CreateAttribute:
+ return getDOMNode(exec,doc.createAttribute(s));
+ case DOMDocument::CreateEntityReference:
+ return getDOMNode(exec,doc.createEntityReference(args[0].toString(exec).string()));
+ case DOMDocument::GetElementsByTagName:
+ return getDOMNodeList(exec,doc.getElementsByTagName(s));
+ case DOMDocument::ImportNode: // DOM2
+ return getDOMNode(exec,doc.importNode(toNode(args[0]), args[1].toBoolean(exec)));
+ case DOMDocument::CreateElementNS: // DOM2
+ return getDOMNode(exec,doc.createElementNS(args[0].toString(exec).string(), args[1].toString(exec).string()));
+ case DOMDocument::CreateAttributeNS: // DOM2
+ return getDOMNode(exec,doc.createAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMDocument::GetElementsByTagNameNS: // DOM2
+ return getDOMNodeList(exec,doc.getElementsByTagNameNS(args[0].toString(exec).string(),
+ args[1].toString(exec).string()));
+ case DOMDocument::GetElementById:
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMDocument::GetElementById looking for " << args[0].toString(exec).string() << endl;
+#endif
+ return getDOMNode(exec,doc.getElementById(args[0].toString(exec).string()));
+ case DOMDocument::CreateRange:
+ return getDOMRange(exec,doc.createRange());
+ case DOMDocument::CreateNodeIterator:
+ if (args[2].isA(NullType)) {
+ DOM::NodeFilter filter;
+ return getDOMNodeIterator(exec,
+ doc.createNodeIterator(toNode(args[0]),
+ (long unsigned int)(args[1].toNumber(exec)),
+ filter,args[3].toBoolean(exec)));
+ }
+ else {
+ Object obj = Object::dynamicCast(args[2]);
+ if (obj.isValid())
+ {
+ DOM::CustomNodeFilter *customFilter = new JSNodeFilter(obj);
+ DOM::NodeFilter filter = DOM::NodeFilter::createCustom(customFilter);
+ return getDOMNodeIterator(exec,
+ doc.createNodeIterator(
+ toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
+ filter,args[3].toBoolean(exec)));
+ }// else?
+ }
+ case DOMDocument::CreateTreeWalker:
+ return getDOMTreeWalker(exec,doc.createTreeWalker(toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
+ toNodeFilter(args[2]),args[3].toBoolean(exec)));
+ case DOMDocument::CreateEvent:
+ return getDOMEvent(exec,doc.createEvent(s));
+ case DOMDocument::GetOverrideStyle: {
+ DOM::Node arg0 = toNode(args[0]);
+ if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
+ return Undefined(); // throw exception?
+ else
+ return getDOMCSSStyleDeclaration(exec,doc.getOverrideStyle(static_cast<DOM::Element>(arg0),args[1].toString(exec).string()));
+ }
+ case DOMDocument::Abort:
+ doc.abort();
+ break;
+ case DOMDocument::Load: {
+ Window* active = Window::retrieveActive(exec);
+ // Complete the URL using the "active part" (running interpreter). We do this for the security
+ // check and to make sure we load exactly the same url as we have verified to be safe
+ KHTMLPart *tdehtmlpart = ::tqqt_cast<KHTMLPart *>(active->part());
+ if (tdehtmlpart) {
+ // Security: only allow documents to be loaded from the same host
+ TQString dstUrl = tdehtmlpart->htmlDocument().completeURL(s).string();
+ KParts::ReadOnlyPart *part = static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part();
+ if (part->url().host() == KURL(dstUrl).host()) {
+ kdDebug(6070) << "JavaScript: access granted for document.load() of " << dstUrl << endl;
+ doc.load(dstUrl);
+ }
+ else {
+ kdDebug(6070) << "JavaScript: access denied for document.load() of " << dstUrl << endl;
+ }
+ }
+ break;
+ }
+ case DOMDocument::LoadXML:
+ doc.loadXML(s);
+ break;
+ default:
+ break;
+ }
+
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+/* Source for DOMElementProtoTable.
+@begin DOMElementProtoTable 17
+ getAttribute DOMElement::GetAttribute DontDelete|Function 1
+ setAttribute DOMElement::SetAttribute DontDelete|Function 2
+ removeAttribute DOMElement::RemoveAttribute DontDelete|Function 1
+ getAttributeNode DOMElement::GetAttributeNode DontDelete|Function 1
+ setAttributeNode DOMElement::SetAttributeNode DontDelete|Function 2
+ removeAttributeNode DOMElement::RemoveAttributeNode DontDelete|Function 1
+ getElementsByTagName DOMElement::GetElementsByTagName DontDelete|Function 1
+ hasAttribute DOMElement::HasAttribute DontDelete|Function 1
+ getAttributeNS DOMElement::GetAttributeNS DontDelete|Function 2
+ setAttributeNS DOMElement::SetAttributeNS DontDelete|Function 3
+ removeAttributeNS DOMElement::RemoveAttributeNS DontDelete|Function 2
+ getAttributeNodeNS DOMElement::GetAttributeNodeNS DontDelete|Function 2
+ setAttributeNodeNS DOMElement::SetAttributeNodeNS DontDelete|Function 1
+ getElementsByTagNameNS DOMElement::GetElementsByTagNameNS DontDelete|Function 2
+ hasAttributeNS DOMElement::HasAttributeNS DontDelete|Function 2
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMElementProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMElement", DOMElementProto, DOMElementProtoFunc)
+
+IMPLEMENT_PSEUDO_CONSTRUCTOR(ElementPseudoCtor, "Element", DOMElementProto)
+
+const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
+/* Source for DOMElementTable.
+@begin DOMElementTable 3
+ tagName DOMElement::TagName DontDelete|ReadOnly
+ style DOMElement::Style DontDelete|ReadOnly
+@end
+*/
+DOMElement::DOMElement(ExecState *exec, const DOM::Element& e)
+ : DOMNode(DOMElementProto::self(exec), e) { }
+
+DOMElement::DOMElement(const Object& proto, const DOM::Element& e)
+ : DOMNode(proto, e) { }
+
+Value DOMElement::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMElement::tryGet " << propertyName.qstring() << endl;
+#endif
+ DOM::Element element = static_cast<DOM::Element>(node);
+
+ const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
+ if (entry)
+ {
+ switch( entry->value ) {
+ case TagName:
+ return String(element.tagName());
+ case Style:
+ return getDOMCSSStyleDeclaration(exec,element.style());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMElement::tryGet : " << entry->value << endl;
+ break;
+ }
+ }
+ // We have to check in DOMNode before giving access to attributes, otherwise
+ // onload="..." would make onload return the string (attribute value) instead of
+ // the listener object (function).
+ if (DOMNode::hasProperty(exec, propertyName))
+ return DOMNode::tryGet(exec, propertyName);
+
+ DOM::DOMString attr = element.getAttribute( propertyName.string() );
+ // Give access to attributes
+ if ( !attr.isNull() )
+ return String( attr );
+
+ return Undefined();
+}
+
+Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMNode, thisObj ); // node should be enough here, given the cast
+ DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
+ DOM::Element element = static_cast<DOM::Element>(node);
+
+ switch(id) {
+ case DOMElement::GetAttribute:
+ /** In theory, we should not return null here, as per DOM. In practice, that
+ breaks websites
+ */
+ return getString(element.getAttribute(args[0].toString(exec).string()));
+ case DOMElement::SetAttribute:
+ element.setAttribute(args[0].toString(exec).string(),args[1].toString(exec).string());
+ return Undefined();
+ case DOMElement::RemoveAttribute:
+ element.removeAttribute(args[0].toString(exec).string());
+ return Undefined();
+ case DOMElement::GetAttributeNode:
+ return getDOMNode(exec,element.getAttributeNode(args[0].toString(exec).string()));
+ case DOMElement::SetAttributeNode:
+ return getDOMNode(exec,element.setAttributeNode(KJS::toNode(args[0])));
+ case DOMElement::RemoveAttributeNode:
+ return getDOMNode(exec,element.removeAttributeNode(KJS::toNode(args[0])));
+ case DOMElement::GetElementsByTagName:
+ return getDOMNodeList(exec,element.getElementsByTagName(args[0].toString(exec).string()));
+ case DOMElement::HasAttribute: // DOM2
+ return Boolean(element.hasAttribute(args[0].toString(exec).string()));
+ case DOMElement::GetAttributeNS: // DOM2
+ return String(element.getAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMElement::SetAttributeNS: // DOM2
+ element.setAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string());
+ return Undefined();
+ case DOMElement::RemoveAttributeNS: // DOM2
+ element.removeAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string());
+ return Undefined();
+ case DOMElement::GetAttributeNodeNS: // DOM2
+ return getDOMNode(exec,element.getAttributeNodeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMElement::SetAttributeNodeNS: // DOM2
+ return getDOMNode(exec,element.setAttributeNodeNS(KJS::toNode(args[0])));
+ case DOMElement::GetElementsByTagNameNS: // DOM2
+ return getDOMNodeList(exec,element.getElementsByTagNameNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMElement::HasAttributeNS: // DOM2
+ return Boolean(element.hasAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+/* Source for DOMDOMImplementationProtoTable.
+@begin DOMDOMImplementationProtoTable 5
+ hasFeature DOMDOMImplementation::HasFeature DontDelete|Function 2
+ createCSSStyleSheet DOMDOMImplementation::CreateCSSStyleSheet DontDelete|Function 2
+# DOM2
+ createDocumentType DOMDOMImplementation::CreateDocumentType DontDelete|Function 3
+ createDocument DOMDOMImplementation::CreateDocument DontDelete|Function 3
+ createHTMLDocument DOMDOMImplementation::CreateHTMLDocument DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMDOMImplementationProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMDOMImplementationProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMImplementation", DOMDOMImplementationProto, DOMDOMImplementationProtoFunc)
+
+const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", 0, 0, 0 };
+
+DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
+ : DOMObject(DOMDOMImplementationProto::self(exec)), implementation(i) { }
+
+DOMDOMImplementation::~DOMDOMImplementation()
+{
+ ScriptInterpreter::forgetDOMObject(implementation.handle());
+}
+
+Value DOMDOMImplementationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMDOMImplementation, thisObj );
+ DOM::DOMImplementation implementation = static_cast<DOMDOMImplementation *>( thisObj.imp() )->toImplementation();
+
+ switch(id) {
+ case DOMDOMImplementation::HasFeature:
+ return Boolean(implementation.hasFeature(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMDOMImplementation::CreateDocumentType: // DOM2
+ return getDOMNode(exec,implementation.createDocumentType(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string()));
+ case DOMDOMImplementation::CreateDocument: { // DOM2
+ // Initially set the URL to document of the creator... this is so that it resides in the same
+ // host/domain for security checks. The URL will be updated if Document.load() is called.
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart*>(static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part());
+ if (part) {
+ Document doc = implementation.createDocument(args[0].toString(exec).string(),args[1].toString(exec).string(),toNode(args[2]));
+ KURL url = static_cast<DocumentImpl*>(part->document().handle())->URL();
+ static_cast<DocumentImpl*>(doc.handle())->setURL(url.url());
+ return getDOMNode(exec,doc);
+ }
+ break;
+ }
+ case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2
+ return getDOMStyleSheet(exec,implementation.createCSSStyleSheet(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML
+ return getDOMNode(exec, implementation.createHTMLDocument(args[0].toString(exec).string()));
+ default:
+ break;
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, 0 };
+
+/* Source for DOMDocumentTypeTable.
+@begin DOMDocumentTypeTable 6
+ name DOMDocumentType::Name DontDelete|ReadOnly
+ entities DOMDocumentType::Entities DontDelete|ReadOnly
+ notations DOMDocumentType::Notations DontDelete|ReadOnly
+# DOM2
+ publicId DOMDocumentType::PublicId DontDelete|ReadOnly
+ systemId DOMDocumentType::SystemId DontDelete|ReadOnly
+ internalSubset DOMDocumentType::InternalSubset DontDelete|ReadOnly
+@end
+*/
+DOMDocumentType::DOMDocumentType(ExecState *exec, const DOM::DocumentType& dt)
+ : DOMNode( /*### no proto yet*/exec, dt ) { }
+
+Value DOMDocumentType::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMDocumentType::tryGet " << propertyName.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMDocumentType, DOMNode>(exec, propertyName, &DOMDocumentTypeTable, this);
+}
+
+Value DOMDocumentType::getValueProperty(ExecState *exec, int token) const
+{
+ DOM::DocumentType type = static_cast<DOM::DocumentType>(node);
+ switch (token) {
+ case Name:
+ return String(type.name());
+ case Entities:
+ return getDOMNamedNodeMap(exec,type.entities());
+ case Notations:
+ return getDOMNamedNodeMap(exec,type.notations());
+ case PublicId: // DOM2
+ return String(type.publicId());
+ case SystemId: // DOM2
+ return String(type.systemId());
+ case InternalSubset: // DOM2
+ return getString(type.internalSubset()); // can be null, see domts/level2/core/internalSubset01.html
+ default:
+ kdDebug(6070) << "WARNING: DOMDocumentType::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+/* Source for DOMNamedNodeMapProtoTable.
+@begin DOMNamedNodeMapProtoTable 7
+ getNamedItem DOMNamedNodeMap::GetNamedItem DontDelete|Function 1
+ setNamedItem DOMNamedNodeMap::SetNamedItem DontDelete|Function 1
+ removeNamedItem DOMNamedNodeMap::RemoveNamedItem DontDelete|Function 1
+ item DOMNamedNodeMap::Item DontDelete|Function 1
+# DOM2
+ getNamedItemNS DOMNamedNodeMap::GetNamedItemNS DontDelete|Function 2
+ setNamedItemNS DOMNamedNodeMap::SetNamedItemNS DontDelete|Function 1
+ removeNamedItemNS DOMNamedNodeMap::RemoveNamedItemNS DontDelete|Function 2
+@end
+@begin DOMNamedNodeMapTable 7
+ length DOMNamedNodeMap::Length DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMNamedNodeMapProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMNamedNodeMapProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto, DOMNamedNodeMapProtoFunc)
+
+const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, &DOMNamedNodeMapTable, 0 };
+
+DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
+ : DOMObject(DOMNamedNodeMapProto::self(exec)), map(m) { }
+
+DOMNamedNodeMap::~DOMNamedNodeMap()
+{
+ ScriptInterpreter::forgetDOMObject(map.handle());
+}
+
+bool DOMNamedNodeMap::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ // ## missing? array index
+ return DOMObject::hasProperty(exec, p);
+}
+
+Value DOMNamedNodeMap::tryGet(ExecState* exec, const Identifier &p) const
+{
+ if (p == lengthPropertyName)
+ return Number(map.length());
+
+ // array index ?
+ bool ok;
+ long unsigned int idx = p.toULong(&ok);
+ if (ok)
+ return getDOMNode(exec,map.item(idx));
+
+ // Anything else (including functions, defined in the prototype)
+ return DOMObject::tryGet(exec, p);
+}
+
+Value DOMNamedNodeMapProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMNamedNodeMap, thisObj );
+ DOM::NamedNodeMap map = static_cast<DOMNamedNodeMap *>(thisObj.imp())->toMap();
+
+ switch(id) {
+ case DOMNamedNodeMap::GetNamedItem:
+ return getDOMNode(exec, map.getNamedItem(args[0].toString(exec).string()));
+ case DOMNamedNodeMap::SetNamedItem:
+ return getDOMNode(exec, map.setNamedItem(KJS::toNode(args[0])));
+ case DOMNamedNodeMap::RemoveNamedItem:
+ return getDOMNode(exec, map.removeNamedItem(args[0].toString(exec).string()));
+ case DOMNamedNodeMap::Item:
+ return getDOMNode(exec, map.item(args[0].toInt32(exec)));
+ case DOMNamedNodeMap::GetNamedItemNS: // DOM2
+ return getDOMNode(exec, map.getNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ case DOMNamedNodeMap::SetNamedItemNS: // DOM2
+ return getDOMNode(exec, map.setNamedItemNS(toNode(args[0])));
+ case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
+ return getDOMNode(exec, map.removeNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
+ default:
+ break;
+ }
+
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+//### FIXME: proto
+const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, 0 };
+
+/* Source for DOMProcessingInstructionTable.
+@begin DOMProcessingInstructionTable 3
+ target DOMProcessingInstruction::Target DontDelete|ReadOnly
+ data DOMProcessingInstruction::Data DontDelete
+ sheet DOMProcessingInstruction::Sheet DontDelete|ReadOnly
+@end
+*/
+Value DOMProcessingInstruction::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<DOMProcessingInstruction, DOMNode>(exec, propertyName, &DOMProcessingInstructionTable, this);
+}
+
+Value DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Target:
+ return String(static_cast<DOM::ProcessingInstruction>(node).target());
+ case Data:
+ return String(static_cast<DOM::ProcessingInstruction>(node).data());
+ case Sheet:
+ return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
+ default:
+ kdDebug(6070) << "WARNING: DOMProcessingInstruction::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+void DOMProcessingInstruction::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ // Not worth using the hashtable for this one ;)
+ if (propertyName == "data")
+ static_cast<DOM::ProcessingInstruction>(node).setData(value.toString(exec).string());
+ else
+ DOMNode::tryPut(exec, propertyName,value,attr);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, 0 };
+
+/* Source for DOMNotationTable.
+@begin DOMNotationTable 2
+ publicId DOMNotation::PublicId DontDelete|ReadOnly
+ systemId DOMNotation::SystemId DontDelete|ReadOnly
+@end
+*/
+Value DOMNotation::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<DOMNotation, DOMNode>(exec, propertyName, &DOMNotationTable, this);
+}
+
+Value DOMNotation::getValueProperty(ExecState *, int token) const
+{
+ switch (token) {
+ case PublicId:
+ return String(static_cast<DOM::Notation>(node).publicId());
+ case SystemId:
+ return String(static_cast<DOM::Notation>(node).systemId());
+ default:
+ kdDebug(6070) << "WARNING: DOMNotation::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, 0, 0 };
+
+/* Source for DOMEntityTable.
+@begin DOMEntityTable 2
+ publicId DOMEntity::PublicId DontDelete|ReadOnly
+ systemId DOMEntity::SystemId DontDelete|ReadOnly
+ notationName DOMEntity::NotationName DontDelete|ReadOnly
+@end
+*/
+Value DOMEntity::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<DOMEntity, DOMNode>(exec, propertyName, &DOMEntityTable, this);
+}
+
+Value DOMEntity::getValueProperty(ExecState *, int token) const
+{
+ switch (token) {
+ case PublicId:
+ return String(static_cast<DOM::Entity>(node).publicId());
+ case SystemId:
+ return String(static_cast<DOM::Entity>(node).systemId());
+ case NotationName:
+ return String(static_cast<DOM::Entity>(node).notationName());
+ default:
+ kdDebug(6070) << "WARNING: DOMEntity::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+bool checkNodeSecurity(ExecState *exec, const DOM::Node& n)
+{
+ // Check to see if the currently executing interpreter is allowed to access the specified node
+ if (n.isNull())
+ return true;
+ KHTMLView *view = n.handle()->getDocument()->view();
+ Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
+ if ( !win || !win->isSafeScript(exec) )
+ return false;
+ return true;
+}
+
+Value getDOMNode(ExecState *exec, const DOM::Node& n)
+{
+ DOMObject *ret = 0;
+ if (n.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(n.handle())))
+ return Value(ret);
+
+ switch (n.nodeType()) {
+ case DOM::Node::ELEMENT_NODE:
+ if (static_cast<DOM::Element>(n).isHTMLElement())
+ ret = new HTMLElement(exec, static_cast<DOM::HTMLElement>(n));
+ else
+ ret = new DOMElement(exec, static_cast<DOM::Element>(n));
+ break;
+ case DOM::Node::ATTRIBUTE_NODE:
+ ret = new DOMAttr(exec, static_cast<DOM::Attr>(n));
+ break;
+ case DOM::Node::TEXT_NODE:
+ case DOM::Node::CDATA_SECTION_NODE:
+ ret = new DOMText(exec, static_cast<DOM::Text>(n));
+ break;
+ case DOM::Node::ENTITY_REFERENCE_NODE:
+ ret = new DOMNode(exec, n);
+ break;
+ case DOM::Node::ENTITY_NODE:
+ ret = new DOMEntity(exec, static_cast<DOM::Entity>(n));
+ break;
+ case DOM::Node::PROCESSING_INSTRUCTION_NODE:
+ ret = new DOMProcessingInstruction(exec, static_cast<DOM::ProcessingInstruction>(n));
+ break;
+ case DOM::Node::COMMENT_NODE:
+ ret = new DOMCharacterData(exec, static_cast<DOM::CharacterData>(n));
+ break;
+ case DOM::Node::DOCUMENT_NODE:
+ if (static_cast<DOM::Document>(n).isHTMLDocument())
+ ret = new HTMLDocument(exec, static_cast<DOM::HTMLDocument>(n));
+ else
+ ret = new DOMDocument(exec, static_cast<DOM::Document>(n));
+ break;
+ case DOM::Node::DOCUMENT_TYPE_NODE:
+ ret = new DOMDocumentType(exec, static_cast<DOM::DocumentType>(n));
+ break;
+ case DOM::Node::DOCUMENT_FRAGMENT_NODE:
+ ret = new DOMNode(exec, n);
+ break;
+ case DOM::Node::NOTATION_NODE:
+ ret = new DOMNotation(exec, static_cast<DOM::Notation>(n));
+ break;
+ default:
+ ret = new DOMNode(exec, n);
+ }
+ interp->putDOMObject(n.handle(),ret);
+
+ return Value(ret);
+}
+
+Value getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
+{
+ return Value(cacheDOMObject<DOM::NamedNodeMap, KJS::DOMNamedNodeMap>(exec, m));
+}
+
+Value getDOMNodeList(ExecState *exec, const DOM::NodeList& l)
+{
+ return Value(cacheDOMObject<DOM::NodeList, KJS::DOMNodeList>(exec, l));
+}
+
+Value getDOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
+{
+ return Value(cacheDOMObject<DOM::DOMImplementation, KJS::DOMDOMImplementation>(exec, i));
+}
+
+// -------------------------------------------------------------------------
+IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(NodeConstructor, "NodeConstructor", DOMNodeProto, DOMNodeConstants)
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
+
+/* Source for DOMExceptionConstructorTable.
+@begin DOMExceptionConstructorTable 15
+ INDEX_SIZE_ERR DOM::DOMException::INDEX_SIZE_ERR DontDelete|ReadOnly
+ DOMSTRING_SIZE_ERR DOM::DOMException::DOMSTRING_SIZE_ERR DontDelete|ReadOnly
+ HIERARCHY_REQUEST_ERR DOM::DOMException::HIERARCHY_REQUEST_ERR DontDelete|ReadOnly
+ WRONG_DOCUMENT_ERR DOM::DOMException::WRONG_DOCUMENT_ERR DontDelete|ReadOnly
+ INVALID_CHARACTER_ERR DOM::DOMException::INVALID_CHARACTER_ERR DontDelete|ReadOnly
+ NO_DATA_ALLOWED_ERR DOM::DOMException::NO_DATA_ALLOWED_ERR DontDelete|ReadOnly
+ NO_MODIFICATION_ALLOWED_ERR DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR DontDelete|ReadOnly
+ NOT_FOUND_ERR DOM::DOMException::NOT_FOUND_ERR DontDelete|ReadOnly
+ NOT_SUPPORTED_ERR DOM::DOMException::NOT_SUPPORTED_ERR DontDelete|ReadOnly
+ INUSE_ATTRIBUTE_ERR DOM::DOMException::INUSE_ATTRIBUTE_ERR DontDelete|ReadOnly
+ INVALID_STATE_ERR DOM::DOMException::INVALID_STATE_ERR DontDelete|ReadOnly
+ SYNTAX_ERR DOM::DOMException::SYNTAX_ERR DontDelete|ReadOnly
+ INVALID_MODIFICATION_ERR DOM::DOMException::INVALID_MODIFICATION_ERR DontDelete|ReadOnly
+ NAMESPACE_ERR DOM::DOMException::NAMESPACE_ERR DontDelete|ReadOnly
+ INVALID_ACCESS_ERR DOM::DOMException::INVALID_ACCESS_ERR DontDelete|ReadOnly
+@end
+*/
+
+DOMExceptionConstructor::DOMExceptionConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value DOMExceptionConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<DOMExceptionConstructor, DOMObject>(exec, propertyName, &DOMExceptionConstructorTable, this);
+}
+
+Value DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number((unsigned int)token);
+#if 0
+ switch (token) {
+ case INDEX_SIZE_ERR:
+ return Number((unsigned int)DOM::DOMException::INDEX_SIZE_ERR);
+ case DOMSTRING_SIZE_ERR:
+ return Number((unsigned int)DOM::DOMException::DOMSTRING_SIZE_ERR);
+ case HIERARCHY_REQUEST_ERR:
+ return Number((unsigned int)DOM::DOMException::HIERARCHY_REQUEST_ERR);
+ case WRONG_DOCUMENT_ERR:
+ return Number((unsigned int)DOM::DOMException::WRONG_DOCUMENT_ERR);
+ case INVALID_CHARACTER_ERR:
+ return Number((unsigned int)DOM::DOMException::INVALID_CHARACTER_ERR);
+ case NO_DATA_ALLOWED_ERR:
+ return Number((unsigned int)DOM::DOMException::NO_DATA_ALLOWED_ERR);
+ case NO_MODIFICATION_ALLOWED_ERR:
+ return Number((unsigned int)DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR);
+ case NOT_FOUND_ERR:
+ return Number((unsigned int)DOM::DOMException::NOT_FOUND_ERR);
+ case NOT_SUPPORTED_ERR:
+ return Number((unsigned int)DOM::DOMException::NOT_SUPPORTED_ERR);
+ case INUSE_ATTRIBUTE_ERR:
+ return Number((unsigned int)DOM::DOMException::INUSE_ATTRIBUTE_ERR);
+ case INVALID_STATE_ERR:
+ return Number((unsigned int)DOM::DOMException::INVALID_STATE_ERR);
+ case SYNTAX_ERR:
+ return Number((unsigned int)DOM::DOMException::SYNTAX_ERR);
+ case INVALID_MODIFICATION_ERR:
+ return Number((unsigned int)DOM::DOMException::INVALID_MODIFICATION_ERR);
+ case NAMESPACE_ERR:
+ return Number((unsigned int)DOM::DOMException::NAMESPACE_ERR);
+ case INVALID_ACCESS_ERR:
+ return Number((unsigned int)DOM::DOMException::INVALID_ACCESS_ERR);
+ default:
+ kdDebug(6070) << "WARNING: DOMExceptionConstructor::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+#endif
+}
+
+Object getDOMExceptionConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+/* Source for DOMNamedNodesCollection.
+@begin DOMNamedNodesCollectionTable 1
+ length KJS::DOMNamedNodesCollection::Length DontDelete|ReadOnly
+@end
+*/
+const ClassInfo KJS::DOMNamedNodesCollection::info = { "DOMNamedNodesCollection", 0, &DOMNamedNodesCollectionTable, 0 };
+
+// Such a collection is usually very short-lived, it only exists
+// for constructs like document.forms.<name>[1],
+// so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
+DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *exec, const TQValueList<DOM::Node>& nodes )
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()),
+ m_nodes(nodes)
+{
+ // Maybe we should ref (and deref in the dtor) the nodes, though ?
+}
+
+Value DOMNamedNodesCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ kdDebug(6070) << k_funcinfo << propertyName.ascii() << endl;
+ if (propertyName == lengthPropertyName)
+ return Number(m_nodes.count());
+ // index?
+ bool ok;
+ unsigned int u = propertyName.toULong(&ok);
+ if (ok && u < m_nodes.count()) {
+ DOM::Node node = m_nodes[u];
+ return getDOMNode(exec,node);
+ }
+ return DOMObject::tryGet(exec,propertyName);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMCharacterData::info = { "CharacterImp",
+ &DOMNode::info, &DOMCharacterDataTable, 0 };
+/*
+@begin DOMCharacterDataTable 2
+ data DOMCharacterData::Data DontDelete
+ length DOMCharacterData::Length DontDelete|ReadOnly
+@end
+@begin DOMCharacterDataProtoTable 7
+ substringData DOMCharacterData::SubstringData DontDelete|Function 2
+ appendData DOMCharacterData::AppendData DontDelete|Function 1
+ insertData DOMCharacterData::InsertData DontDelete|Function 2
+ deleteData DOMCharacterData::DeleteData DontDelete|Function 2
+ replaceData DOMCharacterData::ReplaceData DontDelete|Function 2
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMCharacterDataProto, DOMNodeProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMCharacterDataProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMCharacterData", DOMCharacterDataProto, DOMCharacterDataProtoFunc)
+
+DOMCharacterData::DOMCharacterData(ExecState *exec, const DOM::CharacterData& d)
+ : DOMNode(DOMCharacterDataProto::self(exec), d) {}
+
+DOMCharacterData::DOMCharacterData(const Object& proto, const DOM::CharacterData& d)
+ : DOMNode(proto, d) {}
+
+Value DOMCharacterData::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070)<<"DOMCharacterData::tryGet "<<p.string().string()<<endl;
+#endif
+ return DOMObjectLookupGetValue<DOMCharacterData,DOMNode>(exec,p,&DOMCharacterDataTable,this);
+}
+
+Value DOMCharacterData::getValueProperty(ExecState *, int token) const
+{
+ DOM::CharacterData data = static_cast<DOM::CharacterData>(node);
+ switch (token) {
+ case Data:
+ return String(data.data());
+ case Length:
+ return Number(data.length());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMCharacterData::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+void DOMCharacterData::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ if (propertyName == "data")
+ static_cast<DOM::CharacterData>(node).setData(value.toString(exec).string());
+ else
+ DOMNode::tryPut(exec, propertyName,value,attr);
+}
+
+Value DOMCharacterDataProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMCharacterData, thisObj );
+ DOM::CharacterData data = static_cast<DOMCharacterData *>(thisObj.imp())->toData();
+ switch(id) {
+ case DOMCharacterData::SubstringData:
+ return String(data.substringData(args[0].toInteger(exec),args[1].toInteger(exec)));
+ case DOMCharacterData::AppendData:
+ data.appendData(args[0].toString(exec).string());
+ return Undefined();
+ break;
+ case DOMCharacterData::InsertData:
+ data.insertData(args[0].toInteger(exec),args[1].toString(exec).string());
+ return Undefined();
+ break;
+ case DOMCharacterData::DeleteData:
+ data.deleteData(args[0].toInteger(exec),args[1].toInteger(exec));
+ return Undefined();
+ break;
+ case DOMCharacterData::ReplaceData:
+ data.replaceData(args[0].toInteger(exec),args[1].toInteger(exec),args[2].toString(exec).string());
+ return Undefined();
+ default:
+ break;
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMText::info = { "Text",
+ &DOMCharacterData::info, 0, 0 };
+/*
+@begin DOMTextProtoTable 1
+ splitText DOMText::SplitText DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMTextProto, DOMCharacterDataProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMTextProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMText", DOMTextProto, DOMTextProtoFunc)
+
+DOMText::DOMText(ExecState *exec, const DOM::Text& t)
+ : DOMCharacterData(DOMTextProto::self(exec), t) { }
+
+Value DOMText::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if (p.isEmpty())
+ return Undefined(); // ### TODO
+ else
+ return DOMCharacterData::tryGet(exec, p);
+}
+
+Value DOMTextProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMText, thisObj );
+ DOM::Text text = static_cast<DOMText *>(thisObj.imp())->toText();
+ switch(id) {
+ case DOMText::SplitText:
+ return getDOMNode(exec,text.splitText(args[0].toInteger(exec)));
+ default:
+ break;
+ }
+ return Undefined();
+}
+
+}
diff --git a/tdehtml/ecma/kjs_dom.h b/tdehtml/ecma/kjs_dom.h
new file mode 100644
index 000000000..b17488592
--- /dev/null
+++ b/tdehtml/ecma/kjs_dom.h
@@ -0,0 +1,299 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_DOM_H_
+#define _KJS_DOM_H_
+
+#include "dom/dom_node.h"
+#include "dom/dom_doc.h"
+#include "dom/dom_element.h"
+#include "dom/dom_xml.h"
+
+#include "ecma/kjs_binding.h"
+
+
+namespace KJS {
+
+ class DOMNode : public DOMObject {
+ public:
+ // Build a DOMNode
+ DOMNode(ExecState *exec, const DOM::Node& n);
+ // Constructor for inherited classes
+ DOMNode(const Object& proto, const DOM::Node& n);
+ ~DOMNode();
+ virtual bool toBoolean(ExecState *) const;
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
+ virtual DOM::Node toNode() const { return node; }
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ virtual Value toPrimitive(ExecState *exec, Type preferred = UndefinedType) const;
+ virtual UString toString(ExecState *exec) const;
+ void setListener(ExecState *exec, int eventId, const Value& func) const;
+ Value getListener(int eventId) const;
+ virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const;
+
+ enum { NodeName, NodeValue, NodeType, ParentNode, ParentElement,
+ ChildNodes, FirstChild, LastChild, PreviousSibling, NextSibling, Item,
+ Attributes, NamespaceURI, Prefix, LocalName, OwnerDocument, InsertBefore,
+ ReplaceChild, RemoveChild, AppendChild, HasAttributes, HasChildNodes,
+ CloneNode, Normalize, IsSupported, AddEventListener, RemoveEventListener,
+ DispatchEvent, Contains, InsertAdjacentHTML,
+ OnAbort, OnBlur, OnChange, OnClick, OnDblClick, OnDragDrop, OnError,
+ OnFocus, OnKeyDown, OnKeyPress, OnKeyUp, OnLoad, OnMouseDown,
+ OnMouseMove, OnMouseOut, OnMouseOver, OnMouseUp, OnMove, OnReset,
+ OnResize, OnSelect, OnSubmit, OnUnload,
+ OffsetLeft, OffsetTop, OffsetWidth, OffsetHeight, OffsetParent,
+ ClientWidth, ClientHeight, ScrollLeft, ScrollTop,
+ ScrollWidth, ScrollHeight, SourceIndex, TextContent };
+
+ protected:
+ DOM::Node node;
+ };
+
+ DEFINE_CONSTANT_TABLE(DOMNodeConstants)
+ KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMNodeProto, DOMNodeConstants)
+ DEFINE_PSEUDO_CONSTRUCTOR(NodeConstructor)
+
+ class DOMNodeList : public DOMObject {
+ public:
+ DOMNodeList(ExecState *, const DOM::NodeList& l);
+ ~DOMNodeList();
+ virtual bool hasProperty(ExecState *exec, const Identifier &p) const;
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List&args);
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args);
+ virtual bool implementsCall() const { return true; }
+ virtual ReferenceList propList(ExecState *exec, bool recursive);
+
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ virtual bool toBoolean(ExecState *) const { return true; }
+ static const ClassInfo info;
+ DOM::NodeList nodeList() const { return list; }
+ enum { Item, NamedItem };
+ private:
+ DOM::NodeList list;
+ };
+
+ class DOMDocument : public DOMNode {
+ public:
+ // Build a DOMDocument
+ DOMDocument(ExecState *exec, const DOM::Document& d);
+ // Constructor for inherited classes
+ DOMDocument(const Object& proto, const DOM::Document& d);
+ virtual ~DOMDocument();
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { DocType, Implementation, DocumentElement, CharacterSet,
+ // Functions
+ CreateElement, CreateDocumentFragment, CreateTextNode, CreateComment,
+ CreateCDATASection, CreateProcessingInstruction, CreateAttribute,
+ CreateEntityReference, GetElementsByTagName, ImportNode, CreateElementNS,
+ CreateAttributeNS, GetElementsByTagNameNS, GetElementById,
+ CreateRange, CreateNodeIterator, CreateTreeWalker, DefaultView,
+ CreateEvent, StyleSheets, GetOverrideStyle, Abort, Load, LoadXML,
+ PreferredStylesheetSet, SelectedStylesheetSet, ReadyState, Async };
+ };
+
+ KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMDocumentProto, DOMNodeProto)
+
+ DEFINE_PSEUDO_CONSTRUCTOR(DocumentPseudoCtor)
+
+ class DOMAttr : public DOMNode {
+ public:
+ DOMAttr(ExecState *exec, const DOM::Attr& a) : DOMNode(exec, a) { }
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ Value getValueProperty(ExecState *exec, int token) const;
+ void putValueProperty(ExecState *exec, int token, const Value& value, int attr);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Name, Specified, ValueProperty, OwnerElement };
+ };
+
+ class DOMElement : public DOMNode {
+ public:
+ // Build a DOMElement
+ DOMElement(ExecState *exec, const DOM::Element& e);
+ // Constructor for inherited classes
+ DOMElement(const Object& proto, const DOM::Element& e);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { TagName, Style,
+ GetAttribute, SetAttribute, RemoveAttribute, GetAttributeNode,
+ SetAttributeNode, RemoveAttributeNode, GetElementsByTagName,
+ GetAttributeNS, SetAttributeNS, RemoveAttributeNS, GetAttributeNodeNS,
+ SetAttributeNodeNS, GetElementsByTagNameNS, HasAttribute, HasAttributeNS };
+ };
+
+ KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMElementProto, DOMNodeProto)
+ DEFINE_PSEUDO_CONSTRUCTOR(ElementPseudoCtor)
+
+ class DOMDOMImplementation : public DOMObject {
+ public:
+ // Build a DOMDOMImplementation
+ DOMDOMImplementation(ExecState *, const DOM::DOMImplementation& i);
+ ~DOMDOMImplementation();
+ // no put - all functions
+ virtual const ClassInfo* classInfo() const { return &info; }
+ virtual bool toBoolean(ExecState *) const { return true; }
+ static const ClassInfo info;
+ enum { HasFeature, CreateDocumentType, CreateDocument, CreateCSSStyleSheet, CreateHTMLDocument };
+ DOM::DOMImplementation toImplementation() const { return implementation; }
+ private:
+ DOM::DOMImplementation implementation;
+ };
+
+ class DOMDocumentType : public DOMNode {
+ public:
+ // Build a DOMDocumentType
+ DOMDocumentType(ExecState *exec, const DOM::DocumentType& dt);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Name, Entities, Notations, PublicId, SystemId, InternalSubset };
+ };
+
+ class DOMNamedNodeMap : public DOMObject {
+ public:
+ DOMNamedNodeMap(ExecState *, const DOM::NamedNodeMap& m);
+ ~DOMNamedNodeMap();
+ virtual bool hasProperty(ExecState *exec, const Identifier &p) const;
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ virtual bool toBoolean(ExecState *) const { return true; }
+ static const ClassInfo info;
+ enum { GetNamedItem, SetNamedItem, RemoveNamedItem, Item, Length,
+ GetNamedItemNS, SetNamedItemNS, RemoveNamedItemNS };
+ DOM::NamedNodeMap toMap() const { return map; }
+ private:
+ DOM::NamedNodeMap map;
+ };
+
+ class DOMProcessingInstruction : public DOMNode {
+ public:
+ DOMProcessingInstruction(ExecState *exec, const DOM::ProcessingInstruction& pi) : DOMNode(exec, pi) { }
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Target, Data, Sheet };
+ };
+
+ class DOMNotation : public DOMNode {
+ public:
+ DOMNotation(ExecState *exec, const DOM::Notation& n) : DOMNode(exec, n) { }
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { PublicId, SystemId };
+ };
+
+ class DOMEntity : public DOMNode {
+ public:
+ DOMEntity(ExecState *exec, const DOM::Entity& e) : DOMNode(exec, e) { }
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { PublicId, SystemId, NotationName };
+ };
+
+ // Constructor for DOMException - constructor stuff not implemented yet
+ class DOMExceptionConstructor : public DOMObject {
+ public:
+ DOMExceptionConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ bool checkNodeSecurity(ExecState *exec, const DOM::Node& n);
+ KDE_EXPORT Value getDOMNode(ExecState *exec, const DOM::Node& n);
+ Value getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m);
+ Value getDOMNodeList(ExecState *exec, const DOM::NodeList& l);
+ Value getDOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i);
+ Object getDOMExceptionConstructor(ExecState *exec);
+
+ // Internal class, used for the collection return by e.g. document.forms.myinput
+ // when multiple nodes have the same name.
+ class DOMNamedNodesCollection : public DOMObject {
+ public:
+ DOMNamedNodesCollection(ExecState *exec, const TQValueList<DOM::Node>& nodes );
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ const TQValueList<DOM::Node>& nodes() const { return m_nodes; }
+ enum { Length };
+ private:
+ TQValueList<DOM::Node> m_nodes;
+ };
+
+ class DOMCharacterData : public DOMNode {
+ public:
+ // Build a DOMCharacterData
+ DOMCharacterData(ExecState *exec, const DOM::CharacterData& d);
+ // Constructor for inherited classes
+ DOMCharacterData(const Object& proto, const DOM::CharacterData& d);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ DOM::CharacterData toData() const { return static_cast<DOM::CharacterData>(node); }
+ enum { Data, Length,
+ SubstringData, AppendData, InsertData, DeleteData, ReplaceData };
+ };
+
+ class DOMText : public DOMCharacterData {
+ public:
+ DOMText(ExecState *exec, const DOM::Text& t);
+ virtual Value tryGet(ExecState *exec,const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ DOM::Text toText() const { return static_cast<DOM::Text>(node); }
+ enum { SplitText };
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_events.cpp b/tdehtml/ecma/kjs_events.cpp
new file mode 100644
index 000000000..7b6ff3cc1
--- /dev/null
+++ b/tdehtml/ecma/kjs_events.cpp
@@ -0,0 +1,993 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_window.h"
+#include "kjs_events.h"
+#include "kjs_events.lut.h"
+#include "kjs_views.h"
+#include "kjs_proxy.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "rendering/render_object.h"
+#include "rendering/render_canvas.h"
+#include "xml/dom2_eventsimpl.h"
+#include "tdehtml_part.h"
+
+#include <kdebug.h>
+
+using namespace DOM;
+
+namespace KJS {
+
+// -------------------------------------------------------------------------
+
+JSEventListener::JSEventListener(Object _listener, ObjectImp *_compareListenerImp, const Object &_win, bool _html)
+ : listener( _listener ), compareListenerImp( _compareListenerImp ), html( _html ), win( _win )
+{
+ //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
+ if (compareListenerImp) {
+ static_cast<Window*>(win.imp())->jsEventListeners.insert(compareListenerImp, this);
+ }
+}
+
+JSEventListener::~JSEventListener()
+{
+ if (compareListenerImp) {
+ static_cast<Window*>(win.imp())->jsEventListeners.remove(compareListenerImp);
+ }
+ //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
+}
+
+void JSEventListener::handleEvent(DOM::Event &evt)
+{
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow() && KJSDebugWin::debugWindow()->inSession())
+ return;
+#endif
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
+ KJSProxy *proxy = 0L;
+ if (part)
+ proxy = part->jScript();
+
+ if (proxy && listener.isValid() && listener.implementsCall()) {
+ ref();
+
+ KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
+ ExecState *exec = interpreter->globalExec();
+
+ List args;
+ args.append(getDOMEvent(exec,evt));
+
+ // Set "this" to the event's current target
+ Object thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));
+ if ( !thisObj.isValid() ) {
+ // Window events (window.onload/window.onresize etc.) must have 'this' set to the window.
+ // DocumentImpl::defaultEventHandler sets currentTarget to 0 to mean 'window'.
+ thisObj = win;
+ }
+
+ Window *window = static_cast<Window*>(win.imp());
+ // Set the event we're handling in the Window object
+ window->setCurrentEvent( &evt );
+ // ... and in the interpreter
+ interpreter->setCurrentEvent( &evt );
+
+ KJSCPUGuard guard;
+ guard.start();
+ Value retval = listener.call(exec, thisObj, args);
+ guard.stop();
+
+ window->setCurrentEvent( 0 );
+ interpreter->setCurrentEvent( 0 );
+ if ( exec->hadException() )
+ exec->clearException();
+ else if (html)
+ {
+ TQVariant ret = ValueToVariant(exec, retval);
+ if (ret.type() == TQVariant::Bool && ret.toBool() == false)
+ evt.preventDefault();
+ }
+ window->afterScriptExecution();
+ deref();
+ }
+}
+
+DOM::DOMString JSEventListener::eventListenerType()
+{
+ if (html)
+ return "_tdehtml_HTMLEventListener";
+ else
+ return "_tdehtml_JSEventListener";
+}
+
+Object JSEventListener::listenerObj() const
+{
+ return listener;
+}
+
+JSLazyEventListener::JSLazyEventListener(const TQString &_code, const TQString &_name, const Object &_win, DOM::NodeImpl* _originalNode)
+ : JSEventListener(Object(), 0, _win, true),
+ code(_code), name(_name),
+ parsed(false)
+{
+ // We don't retain the original node, because we assume it
+ // will stay alive as long as this handler object is around
+ // and we need to avoid a reference cycle. If JS transfers
+ // this handler to another node, parseCode will be called and
+ // then originalNode is no longer needed.
+
+ originalNode = _originalNode;
+}
+
+JSLazyEventListener::~JSLazyEventListener()
+{
+ if (listener.isValid()) {
+ static_cast<Window*>(win.imp())->jsEventListeners.remove(listener.imp());
+ }
+}
+
+void JSLazyEventListener::handleEvent(DOM::Event &evt)
+{
+ parseCode();
+ if (listener.isValid()) {
+ JSEventListener::handleEvent(evt);
+ }
+}
+
+
+Object JSLazyEventListener::listenerObj() const
+{
+ parseCode();
+ return listener;
+}
+
+void JSLazyEventListener::parseCode() const
+{
+ if (!parsed) {
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
+ KJSProxy *proxy = 0L;
+ if (part)
+ proxy = part->jScript();
+
+ if (proxy) {
+ KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
+ ExecState *exec = interpreter->globalExec();
+
+ //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
+ KJS::Object constr = interpreter->builtinFunction();
+ KJS::List args;
+
+ static KJS::String eventString("event");
+
+ args.append(eventString);
+ args.append(KJS::String(code));
+ listener = constr.construct(exec, args); // ### is globalExec ok ?
+
+ if (exec->hadException()) {
+ exec->clearException();
+
+ // failed to parse, so let's just make this listener a no-op
+ listener = Object();
+ } else if (!listener.inherits(&DeclaredFunctionImp::info)) {
+ listener = Object();// Error creating function
+ } else {
+ DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp*>(listener.imp());
+ declFunc->setName(Identifier(static_cast<UString>(name)));
+
+ if (originalNode)
+ {
+ // Add the event's home element to the scope
+ // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
+ ScopeChain scope = listener.scope();
+
+ Object thisObj = Object::dynamicCast(getDOMNode(exec, originalNode));
+
+ if (thisObj.isValid()) {
+ static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
+
+ listener.setScope(scope);
+ }
+ }
+ }
+ }
+
+ // no more need to keep the unparsed code around
+ code = TQString();
+
+ if (listener.isValid()) {
+ static_cast<Window*>(win.imp())->jsEventListeners.insert(listener.imp(),
+ (KJS::JSEventListener *)(this));
+ }
+
+ parsed = true;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMEvent::info = { "Event", 0, &DOMEventTable, 0 };
+/*
+@begin DOMEventTable 7
+ type DOMEvent::Type DontDelete|ReadOnly
+ target DOMEvent::Target DontDelete|ReadOnly
+ currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
+ srcElement DOMEvent::SrcElement DontDelete|ReadOnly
+ eventPhase DOMEvent::EventPhase DontDelete|ReadOnly
+ bubbles DOMEvent::Bubbles DontDelete|ReadOnly
+ cancelable DOMEvent::Cancelable DontDelete|ReadOnly
+ timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
+ returnValue DOMEvent::ReturnValue DontDelete
+ cancelBubble DOMEvent::CancelBubble DontDelete
+@end
+@begin DOMEventProtoTable 3
+ stopPropagation DOMEvent::StopPropagation DontDelete|Function 0
+ preventDefault DOMEvent::PreventDefault DontDelete|Function 0
+ initEvent DOMEvent::InitEvent DontDelete|Function 3
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMEvent", DOMEventProto, DOMEventProtoFunc)
+
+DOMEvent::DOMEvent(ExecState *exec, DOM::Event e)
+ : DOMObject(DOMEventProto::self(exec)), event(e) { }
+
+DOMEvent::DOMEvent(const Object &proto, DOM::Event e)
+ : DOMObject(proto), event(e) { }
+
+DOMEvent::~DOMEvent()
+{
+ ScriptInterpreter::forgetDOMObject(event.handle());
+}
+
+Value DOMEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug() << "KJS::DOMEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMEvent,DOMObject>(exec, p, &DOMEventTable, this );
+}
+
+Value DOMEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Type:
+ return String(event.type());
+ case Target:
+ case SrcElement: /*MSIE extension - "the object that fired the event"*/
+ return getDOMNode(exec,event.target());
+ case CurrentTarget:
+ return getDOMNode(exec,event.currentTarget());
+ case EventPhase:
+ return Number((unsigned int)event.eventPhase());
+ case Bubbles:
+ return Boolean(event.bubbles());
+ case Cancelable:
+ return Boolean(event.cancelable());
+ case TimeStamp:
+ return Number((long unsigned int)event.timeStamp()); // ### long long ?
+ case ReturnValue: // MSIE extension
+ // return false == cancel, so this returns the -opposite- of defaultPrevented
+ return Boolean(!event.handle()->defaultPrevented());
+ case CancelBubble: // MSIE extension
+ return Boolean(event.handle()->propagationStopped());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMEvent::defaultValue(ExecState *exec, KJS::Type hint) const
+{
+ if (event.handle()->id() == EventImpl::ERROR_EVENT && !event.handle()->message().isNull()) {
+ return String(event.handle()->message());
+ }
+ else
+ return DOMObject::defaultValue(exec,hint);
+}
+
+void DOMEvent::tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr)
+{
+ DOMObjectLookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
+ &DOMEventTable, this);
+}
+
+void DOMEvent::putValueProperty(ExecState *exec, int token, const Value& value, int)
+{
+ switch (token) {
+ case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
+ // returnValue=false means "default action of the event on the source object is canceled",
+ // which means preventDefault(true). Hence the '!'.
+ event.handle()->preventDefault(!value.toBoolean(exec));
+ break;
+ case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
+ event.handle()->stopPropagation(value.toBoolean(exec));
+ break;
+ default:
+ break;
+ }
+}
+
+Value DOMEventProtoFunc::tryCall(ExecState *exec, Object & thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMEvent, thisObj );
+ DOM::Event event = static_cast<DOMEvent *>( thisObj.imp() )->toEvent();
+ switch (id) {
+ case DOMEvent::StopPropagation:
+ event.stopPropagation();
+ return Undefined();
+ case DOMEvent::PreventDefault:
+ event.preventDefault();
+ return Undefined();
+ case DOMEvent::InitEvent:
+ event.initEvent(args[0].toString(exec).string(),args[1].toBoolean(exec),args[2].toBoolean(exec));
+ return Undefined();
+ };
+ return Undefined();
+}
+
+Value getDOMEvent(ExecState *exec, DOM::Event e)
+{
+ DOM::EventImpl *ei = e.handle();
+ if (!ei)
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ DOMObject *ret = interp->getDOMObject(ei);
+ if (!ret) {
+ if (ei->isTextInputEvent())
+ ret = new DOMTextEvent(exec, e);
+ else if (ei->isKeyboardEvent())
+ ret = new DOMKeyboardEvent(exec, e);
+ else if (ei->isMouseEvent())
+ ret = new DOMMouseEvent(exec, e);
+ else if (ei->isUIEvent())
+ ret = new DOMUIEvent(exec, e);
+ else if (ei->isMutationEvent())
+ ret = new DOMMutationEvent(exec, e);
+ else
+ ret = new DOMEvent(exec, e);
+
+ interp->putDOMObject(ei, ret);
+ }
+
+ return Value(ret);
+}
+
+DOM::Event toEvent(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMEvent::info))
+ return DOM::Event();
+
+ const DOMEvent *dobj = static_cast<const DOMEvent*>(obj.imp());
+ return dobj->toEvent();
+}
+
+// -------------------------------------------------------------------------
+/*
+@begin EventConstantsTable 23
+ CAPTURING_PHASE DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
+ AT_TARGET DOM::Event::AT_TARGET DontDelete|ReadOnly
+ BUBBLING_PHASE DOM::Event::BUBBLING_PHASE DontDelete|ReadOnly
+# Reverse-engineered from Netscape
+ MOUSEDOWN 1 DontDelete|ReadOnly
+ MOUSEUP 2 DontDelete|ReadOnly
+ MOUSEOVER 4 DontDelete|ReadOnly
+ MOUSEOUT 8 DontDelete|ReadOnly
+ MOUSEMOVE 16 DontDelete|ReadOnly
+ MOUSEDRAG 32 DontDelete|ReadOnly
+ CLICK 64 DontDelete|ReadOnly
+ DBLCLICK 128 DontDelete|ReadOnly
+ KEYDOWN 256 DontDelete|ReadOnly
+ KEYUP 512 DontDelete|ReadOnly
+ KEYPRESS 1024 DontDelete|ReadOnly
+ DRAGDROP 2048 DontDelete|ReadOnly
+ FOCUS 4096 DontDelete|ReadOnly
+ BLUR 8192 DontDelete|ReadOnly
+ SELECT 16384 DontDelete|ReadOnly
+ CHANGE 32768 DontDelete|ReadOnly
+@end
+*/
+DEFINE_CONSTANT_TABLE(EventConstants)
+IMPLEMENT_CONSTANT_TABLE(EventConstants, "EventConstants")
+
+IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(EventConstructor, "EventConstructor", DOMEventProto, EventConstants)
+// -------------------------------------------------------------------------
+
+
+const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", 0, &EventExceptionConstructorTable, 0 };
+/*
+@begin EventExceptionConstructorTable 1
+ UNSPECIFIED_EVENT_TYPE_ERR DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
+@end
+*/
+EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value EventExceptionConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<EventExceptionConstructor, DOMObject>(exec,p,&EventExceptionConstructorTable,this);
+}
+
+Value EventExceptionConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getEventExceptionConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, 0 };
+/*
+@begin DOMUIEventTable 7
+ view DOMUIEvent::View DontDelete|ReadOnly
+ detail DOMUIEvent::Detail DontDelete|ReadOnly
+ keyCode DOMUIEvent::KeyCode DontDelete|ReadOnly
+ charCode DOMUIEvent::CharCode DontDelete|ReadOnly
+ layerX DOMUIEvent::LayerX DontDelete|ReadOnly
+ layerY DOMUIEvent::LayerY DontDelete|ReadOnly
+ pageX DOMUIEvent::PageX DontDelete|ReadOnly
+ pageY DOMUIEvent::PageY DontDelete|ReadOnly
+ which DOMUIEvent::Which DontDelete|ReadOnly
+@end
+@begin DOMUIEventProtoTable 1
+ initUIEvent DOMUIEvent::InitUIEvent DontDelete|Function 5
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMUIEventProto, DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMUIEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMUIEvent", DOMUIEventProto, DOMUIEventProtoFunc)
+
+DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEvent ue) :
+ DOMEvent(DOMUIEventProto::self(exec), ue) {}
+
+DOMUIEvent::DOMUIEvent(const Object &proto, DOM::UIEvent ue) :
+ DOMEvent(proto, ue) {}
+
+DOMUIEvent::~DOMUIEvent()
+{
+}
+
+Value DOMUIEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMUIEvent,DOMEvent>(exec,p,&DOMUIEventTable,this);
+}
+
+Value DOMUIEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case View:
+ return getDOMAbstractView(exec,static_cast<DOM::UIEvent>(event).view());
+ case Detail:
+ return Number(static_cast<DOM::UIEvent>(event).detail());
+ case KeyCode:
+ // IE-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).keyCode());
+ case CharCode:
+ // IE-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).charCode());
+ case LayerX:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).layerX());
+ case LayerY:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).layerY());
+ case PageX:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).pageX());
+ case PageY:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).pageY());
+ case Which:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).which());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+Value DOMUIEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMUIEvent, thisObj );
+ DOM::UIEvent uiEvent = static_cast<DOMUIEvent *>(thisObj.imp())->toUIEvent();
+ switch (id) {
+ case DOMUIEvent::InitUIEvent: {
+ DOM::AbstractView v = toAbstractView(args[3]);
+ static_cast<DOM::UIEvent>(uiEvent).initUIEvent(args[0].toString(exec).string(),
+ args[1].toBoolean(exec),
+ args[2].toBoolean(exec),
+ v,
+ args[4].toInteger(exec));
+ }
+ return Undefined();
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, 0 };
+
+/*
+@begin DOMMouseEventTable 2
+ screenX DOMMouseEvent::ScreenX DontDelete|ReadOnly
+ screenY DOMMouseEvent::ScreenY DontDelete|ReadOnly
+ clientX DOMMouseEvent::ClientX DontDelete|ReadOnly
+ x DOMMouseEvent::X DontDelete|ReadOnly
+ clientY DOMMouseEvent::ClientY DontDelete|ReadOnly
+ y DOMMouseEvent::Y DontDelete|ReadOnly
+ offsetX DOMMouseEvent::OffsetX DontDelete|ReadOnly
+ offsetY DOMMouseEvent::OffsetY DontDelete|ReadOnly
+ ctrlKey DOMMouseEvent::CtrlKey DontDelete|ReadOnly
+ shiftKey DOMMouseEvent::ShiftKey DontDelete|ReadOnly
+ altKey DOMMouseEvent::AltKey DontDelete|ReadOnly
+ metaKey DOMMouseEvent::MetaKey DontDelete|ReadOnly
+ button DOMMouseEvent::Button DontDelete|ReadOnly
+ relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
+ fromElement DOMMouseEvent::FromElement DontDelete|ReadOnly
+ toElement DOMMouseEvent::ToElement DontDelete|ReadOnly
+@end
+@begin DOMMouseEventProtoTable 1
+ initMouseEvent DOMMouseEvent::InitMouseEvent DontDelete|Function 15
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMMouseEventProto, DOMUIEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMMouseEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMMouseEvent", DOMMouseEventProto, DOMMouseEventProtoFunc)
+
+DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEvent me) :
+ DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
+
+DOMMouseEvent::~DOMMouseEvent()
+{
+}
+
+Value DOMMouseEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMMouseEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMMouseEvent,DOMUIEvent>(exec,p,&DOMMouseEventTable,this);
+}
+
+Value DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case ScreenX:
+ return Number(static_cast<DOM::MouseEvent>(event).screenX());
+ case ScreenY:
+ return Number(static_cast<DOM::MouseEvent>(event).screenY());
+ case ClientX:
+ case X:
+ return Number(static_cast<DOM::MouseEvent>(event).clientX());
+ case ClientY:
+ case Y:
+ return Number(static_cast<DOM::MouseEvent>(event).clientY());
+ case OffsetX:
+ case OffsetY: // MSIE extension
+ {
+ DOM::Node node = event.target();
+ tdehtml::RenderObject *rend = 0;
+ if (node.handle()) {
+ node.handle()->getDocument()->updateRendering();
+ rend = node.handle()->renderer();
+ }
+ int x = static_cast<DOM::MouseEvent>(event).clientX();
+ int y = static_cast<DOM::MouseEvent>(event).clientY();
+ if ( rend ) {
+ int xPos, yPos;
+ if ( rend->absolutePosition( xPos, yPos ) ) {
+ //kdDebug() << "DOMMouseEvent::getValueProperty rend=" << rend << " xPos=" << xPos << " yPos=" << yPos << endl;
+ x -= xPos;
+ y -= yPos;
+ }
+ if ( rend->canvas() ) {
+ int cYPos, cXPos;
+ rend->canvas()->absolutePosition( cXPos, cYPos, true );
+ x += cXPos;
+ y += cYPos;
+ }
+ }
+ return Number( token == OffsetX ? x : y );
+ }
+ case CtrlKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).ctrlKey());
+ case ShiftKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).shiftKey());
+ case AltKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).altKey());
+ case MetaKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).metaKey());
+ case Button:
+ {
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat ) {
+ return Number(static_cast<DOM::MouseEvent>(event).button());
+ }
+ // Tricky. The DOM (and tdehtml) use 0 for LMB, 1 for MMB and 2 for RMB
+ // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
+ int domButton = static_cast<DOM::MouseEvent>(event).button();
+ int button = domButton==0 ? 1 : domButton==1 ? 4 : domButton==2 ? 2 : 0;
+ return Number( (unsigned int)button );
+ }
+ case ToElement:
+ // MSIE extension - "the object toward which the user is moving the mouse pointer"
+ if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
+ case FromElement:
+ // MSIE extension - "object from which activation
+ // or the mouse pointer is exiting during the event" (huh?)
+ if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
+ /* fall through */
+ case RelatedTarget:
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMMouseEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMMouseEvent, thisObj );
+ DOM::MouseEvent mouseEvent = static_cast<DOMMouseEvent *>(thisObj.imp())->toMouseEvent();
+ switch (id) {
+ case DOMMouseEvent::InitMouseEvent:
+ mouseEvent.initMouseEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toInteger(exec), // detailArg
+ args[5].toInteger(exec), // screenXArg
+ args[6].toInteger(exec), // screenYArg
+ args[7].toInteger(exec), // clientXArg
+ args[8].toInteger(exec), // clientYArg
+ args[9].toBoolean(exec), // ctrlKeyArg
+ args[10].toBoolean(exec), // altKeyArg
+ args[11].toBoolean(exec), // shiftKeyArg
+ args[12].toBoolean(exec), // metaKeyArg
+ args[13].toInteger(exec), // buttonArg
+ toNode(args[14])); // relatedTargetArg
+ return Undefined();
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, 0 };
+
+/*
+@begin DOMKeyEventBaseTable 5
+ keyVal DOMKeyEventBase::Key DontDelete|ReadOnly
+ virtKeyVal DOMKeyEventBase::VirtKey DontDelete|ReadOnly
+ ctrlKey DOMKeyEventBase::CtrlKey DontDelete|ReadOnly
+ altKey DOMKeyEventBase::AltKey DontDelete|ReadOnly
+ shiftKey DOMKeyEventBase::ShiftKey DontDelete|ReadOnly
+ altKey DOMKeyEventBase::AltKey DontDelete|ReadOnly
+@end
+*/
+
+DOMKeyEventBase::DOMKeyEventBase(const Object &proto, DOM::TextEvent ke) :
+ DOMUIEvent(proto, ke) {}
+
+DOMKeyEventBase::~DOMKeyEventBase()
+{}
+
+Value DOMKeyEventBase::tryGet(ExecState *exec,const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMKeyEventBase::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMKeyEventBase,DOMUIEvent>(exec,p,&DOMKeyEventBaseTable,this);
+}
+
+Value DOMKeyEventBase::getValueProperty(ExecState *, int token) const
+{
+ DOM::KeyEventBaseImpl* tevent = impl();
+ switch (token) {
+ case Key:
+ return Number(tevent->keyVal());
+ case VirtKey:
+ return Number(tevent->virtKeyVal());
+ // these modifier attributes actually belong into a KeyboardEvent interface,
+ // but we want them on "keypress" as well.
+ case CtrlKey:
+ return Boolean(tevent->ctrlKey());
+ case ShiftKey:
+ return Boolean(tevent->shiftKey());
+ case AltKey:
+ return Boolean(tevent->altKey());
+ case MetaKey:
+ return Boolean(tevent->metaKey());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, 0 };
+
+/*
+@begin DOMTextEventTable 1
+ data DOMTextEvent::Data DontDelete|ReadOnly
+@end
+@begin DOMTextEventProtoTable 1
+ initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
+ # Missing: initTextEventNS
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMTextEventProto, DOMUIEventProto) //Note: no proto in KeyBase
+IMPLEMENT_PROTOFUNC_DOM(DOMTextEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMTextEvent", DOMTextEventProto, DOMTextEventProtoFunc)
+
+DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEvent ke) :
+ DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
+
+DOMTextEvent::~DOMTextEvent()
+{
+}
+
+Value DOMTextEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMTextEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMTextEvent,DOMKeyEventBase>(exec,p,&DOMTextEventTable,this);
+}
+
+Value DOMTextEvent::getValueProperty(ExecState *, int token) const
+{
+ DOM::TextEventImpl* tevent = impl();
+ switch (token) {
+ case Data:
+ return String(tevent->data());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+Value DOMTextEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMTextEvent, thisObj );
+ DOM::TextEventImpl* keyEvent = static_cast<DOMTextEvent *>(thisObj.imp())->impl();
+ switch (id) {
+ case DOMTextEvent::InitTextEvent:
+ keyEvent->initTextEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toString(exec).string()); // dataArg
+
+ return Undefined();
+ }
+ return Undefined();
+}
+// -------------------------------------------------------------------------
+const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, 0 };
+
+/*
+@begin DOMKeyboardEventTable 2
+ keyIdentifier DOMKeyboardEvent::KeyIdentifier DontDelete|ReadOnly
+ keyLocation DOMKeyboardEvent::KeyLocation DontDelete|ReadOnly
+@end
+@begin DOMKeyboardEventProtoTable 2
+ initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
+ getModifierState DOMKeyboardEvent::GetModifierState DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMKeyboardEventProto, DOMUIEventProto) //Note: no proto in KeyBase
+IMPLEMENT_PROTOFUNC_DOM(DOMKeyboardEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc)
+
+DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::TextEvent ke) :
+ DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
+
+DOMKeyboardEvent::~DOMKeyboardEvent()
+{
+}
+
+Value DOMKeyboardEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMKeyboardEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMKeyboardEvent,DOMKeyEventBase>(exec,p,&DOMKeyboardEventTable,this);
+}
+
+Value DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
+{
+ DOM::KeyboardEventImpl* tevent = impl();
+ switch (token) {
+ case KeyIdentifier:
+ return String(tevent->keyIdentifier());
+ case KeyLocation:
+ return Number(tevent->keyLocation());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+Value DOMKeyboardEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMKeyboardEvent, thisObj );
+ DOM::KeyboardEventImpl* keyEvent = static_cast<DOMKeyboardEvent *>(thisObj.imp())->impl();
+ switch (id) {
+ case DOMKeyboardEvent::InitKeyboardEvent:
+ keyEvent->initKeyboardEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toString(exec).string(), // keyIdentifierArg
+ args[5].toInteger(exec), // keyLocationArg
+ args[6].toString(exec).string()); //modifiersList
+ break;
+ case DOMKeyboardEvent::GetModifierState:
+ return Boolean(keyEvent->getModifierState(args[0].toString(exec).string()));
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", 0, &KeyboardEventConstructorTable, 0 };
+/*
+@begin KeyboardEventConstructorTable 4
+ DOM_KEY_LOCATION_STANDARD DOM::KeyboardEventImpl::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
+ DOM_KEY_LOCATION_LEFT DOM::KeyboardEventImpl::DOM_KEY_LOCATION_LEFT DontDelete|ReadOnly
+ DOM_KEY_LOCATION_RIGHT DOM::KeyboardEventImpl::DOM_KEY_LOCATION_RIGHT DontDelete|ReadOnly
+ DOM_KEY_LOCATION_NUMPAD DOM::KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD DontDelete|ReadOnly
+@end
+*/
+KeyboardEventConstructor::KeyboardEventConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{}
+
+Value KeyboardEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<KeyboardEventConstructor,DOMObject>(exec,p,&KeyboardEventConstructorTable,this);
+}
+
+Value KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getKeyboardEventConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
+}
+
+
+// -------------------------------------------------------------------------
+const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0, &MutationEventConstructorTable, 0 };
+/*
+@begin MutationEventConstructorTable 3
+ MODIFICATION DOM::MutationEvent::MODIFICATION DontDelete|ReadOnly
+ ADDITION DOM::MutationEvent::ADDITION DontDelete|ReadOnly
+ REMOVAL DOM::MutationEvent::REMOVAL DontDelete|ReadOnly
+@end
+*/
+MutationEventConstructor::MutationEventConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value MutationEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<MutationEventConstructor,DOMObject>(exec,p,&MutationEventConstructorTable,this);
+}
+
+Value MutationEventConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getMutationEventConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, 0 };
+/*
+@begin DOMMutationEventTable 5
+ relatedNode DOMMutationEvent::RelatedNode DontDelete|ReadOnly
+ prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
+ newValue DOMMutationEvent::NewValue DontDelete|ReadOnly
+ attrName DOMMutationEvent::AttrName DontDelete|ReadOnly
+ attrChange DOMMutationEvent::AttrChange DontDelete|ReadOnly
+@end
+@begin DOMMutationEventProtoTable 1
+ initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMMutationEventProto, DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMMutationEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMMutationEvent", DOMMutationEventProto, DOMMutationEventProtoFunc)
+
+DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEvent me) :
+ DOMEvent(DOMMutationEventProto::self(exec), me) {}
+
+DOMMutationEvent::~DOMMutationEvent()
+{
+}
+
+Value DOMMutationEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMMutationEvent,DOMEvent>(exec,p,&DOMMutationEventTable,this);
+}
+
+Value DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case RelatedNode:
+ return getDOMNode(exec,static_cast<DOM::MutationEvent>(event).relatedNode());
+ case PrevValue:
+ return String(static_cast<DOM::MutationEvent>(event).prevValue());
+ case NewValue:
+ return String(static_cast<DOM::MutationEvent>(event).newValue());
+ case AttrName:
+ return String(static_cast<DOM::MutationEvent>(event).attrName());
+ case AttrChange:
+ return Number((unsigned int)static_cast<DOM::MutationEvent>(event).attrChange());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMMutationEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMMutationEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMMutationEvent, thisObj );
+ DOM::MutationEvent mutationEvent = static_cast<DOMMutationEvent *>(thisObj.imp())->toMutationEvent();
+ switch (id) {
+ case DOMMutationEvent::InitMutationEvent:
+ mutationEvent.initMutationEvent(args[0].toString(exec).string(), // typeArg,
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toNode(args[3]), // relatedNodeArg
+ args[4].toString(exec).string(), // prevValueArg
+ args[5].toString(exec).string(), // newValueArg
+ args[6].toString(exec).string(), // attrNameArg
+ args[7].toInteger(exec)); // attrChangeArg
+ return Undefined();
+ }
+ return Undefined();
+}
+
+} //namespace KJS
diff --git a/tdehtml/ecma/kjs_events.h b/tdehtml/ecma/kjs_events.h
new file mode 100644
index 000000000..e48276031
--- /dev/null
+++ b/tdehtml/ecma/kjs_events.h
@@ -0,0 +1,250 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_EVENTS_H_
+#define _KJS_EVENTS_H_
+
+#include "ecma/kjs_dom.h"
+#include "dom/dom2_events.h"
+#include "dom/dom_misc.h"
+#include "xml/dom2_eventsimpl.h"
+
+namespace KJS {
+
+ class Window;
+
+ class JSEventListener : public DOM::EventListener {
+ public:
+ /**
+ * @param _listener the function object, that will be called when the event is emitted
+ * @param _compareListenerImp Compare Listener implementation.
+ * @param _win Window object, for memory management and caching.
+ * @param _html \c true if it is HTML.
+ * Never create a JSEventListener directly, use Window::getJSEventListener.
+ */
+ JSEventListener(Object _listener, ObjectImp *_compareListenerImp, const Object &_win, bool _html = false);
+ virtual ~JSEventListener();
+ virtual void handleEvent(DOM::Event &evt);
+ virtual DOM::DOMString eventListenerType();
+ // Return the KJS function object executed when this event is emitted
+ virtual Object listenerObj() const;
+ ObjectImp *listenerObjImp() const { return listenerObj().imp(); }
+ // for Window::clear(). This is a bad hack though. The JSEventListener might not get deleted
+ // if it was added to a DOM node in another frame (#61467). But calling removeEventListener on
+ // all nodes we're listening to is quite difficult.
+ void clear() { listener = Object(); }
+ bool isHTMLEventListener() const { return html; }
+
+ protected:
+ mutable Object listener;
+ // Storing a different ObjectImp ptr is needed to support addEventListener(.. [Object] ..) calls
+ // In the real-life case (where a 'function' is passed to addEventListener) we can directly call
+ // the 'listener' object and can cache the 'listener.imp()'. If the event listener should be removed
+ // the implementation will call removeEventListener(.. [Function] ..), and we can lookup the event
+ // listener by the passed function's imp() ptr.
+ // In the only dom-approved way (passing an Object to add/removeEventListener), the 'listener'
+ // variable stores the function object 'passedListener.handleEvent'. But we need to cache
+ // the imp() ptr of the 'passedListener' function _object_, as the implementation will
+ // call removeEventListener(.. [Object ..] on removal, and now we can successfully lookup
+ // the correct event listener, as well as the 'listener.handleEvent' function, we need to call.
+ mutable ObjectImp *compareListenerImp;
+ bool html;
+ Object win;
+ };
+
+ class JSLazyEventListener : public JSEventListener {
+ public:
+ JSLazyEventListener(const TQString &_code, const TQString &_name, const Object &_win, DOM::NodeImpl* node);
+ ~JSLazyEventListener();
+ virtual void handleEvent(DOM::Event &evt);
+ Object listenerObj() const;
+ private:
+ void parseCode() const;
+
+ mutable TQString code;
+ mutable TQString name;
+ mutable bool parsed;
+ DOM::NodeImpl *originalNode;
+ };
+
+ // Constructor for Event - currently only used for some global vars
+ DEFINE_PSEUDO_CONSTRUCTOR(EventConstructor)
+
+ class DOMEvent : public DOMObject {
+ public:
+ // Build a DOMEvent
+ DOMEvent(ExecState *exec, DOM::Event e);
+ // Constructor for inherited classes
+ DOMEvent(const Object &proto, DOM::Event e);
+ ~DOMEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr = None);
+ virtual Value defaultValue(ExecState *exec, KJS::Type hint) const;
+ void putValueProperty(ExecState *exec, int token, const Value& value, int);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Type, Target, CurrentTarget, EventPhase, Bubbles,
+ Cancelable, TimeStamp, StopPropagation, PreventDefault, InitEvent,
+ // MS IE equivalents
+ SrcElement, ReturnValue, CancelBubble };
+ DOM::Event toEvent() const { return event; }
+ protected:
+ DOM::Event event;
+ };
+
+ Value getDOMEvent(ExecState *exec, DOM::Event e);
+
+ /**
+ * Convert an object to an Event. Returns a null Event if not possible.
+ */
+ DOM::Event toEvent(const Value&);
+
+ // Constructor object EventException
+ class EventExceptionConstructor : public DOMObject {
+ public:
+ EventExceptionConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ Value getEventExceptionConstructor(ExecState *exec);
+
+ class DOMUIEvent : public DOMEvent {
+ public:
+ // Build a DOMUIEvent
+ DOMUIEvent(ExecState *exec, DOM::UIEvent ue);
+ // Constructor for inherited classes
+ DOMUIEvent(const Object &proto, DOM::UIEvent ue);
+ ~DOMUIEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { View, Detail, KeyCode, CharCode, LayerX, LayerY, PageX, PageY, Which, InitUIEvent };
+ DOM::UIEvent toUIEvent() const { return static_cast<DOM::UIEvent>(event); }
+ };
+
+ class DOMMouseEvent : public DOMUIEvent {
+ public:
+ DOMMouseEvent(ExecState *exec, DOM::MouseEvent me);
+ ~DOMMouseEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { ScreenX, ScreenY, ClientX, X, ClientY, Y, OffsetX, OffsetY,
+ CtrlKey, ShiftKey, AltKey,
+ MetaKey, Button, RelatedTarget, FromElement, ToElement,
+ InitMouseEvent
+ };
+ DOM::MouseEvent toMouseEvent() const { return static_cast<DOM::MouseEvent>(event); }
+ };
+
+ class DOMKeyEventBase : public DOMUIEvent {
+ public:
+ DOMKeyEventBase(const Object &proto, DOM::TextEvent ke);
+ ~DOMKeyEventBase();
+
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Key, VirtKey, CtrlKey, ShiftKey, AltKey, MetaKey };
+ DOM::KeyEventBaseImpl* impl() const { return static_cast<DOM::KeyEventBaseImpl*>(event.handle()); }
+ };
+
+ class DOMTextEvent : public DOMKeyEventBase {
+ public:
+ DOMTextEvent(ExecState *exec, DOM::TextEvent ke);
+ ~DOMTextEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum {Data, InitTextEvent};
+ DOM::TextEventImpl* impl() const { return static_cast<DOM::TextEventImpl*>(event.handle()); }
+ };
+
+ class DOMKeyboardEvent : public DOMKeyEventBase {
+ public:
+ DOMKeyboardEvent(ExecState *exec, DOM::TextEvent ke);
+ ~DOMKeyboardEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum {KeyIdentifier, KeyLocation, GetModifierState, InitKeyboardEvent};
+ DOM::KeyboardEventImpl* impl() const { return static_cast<DOM::KeyboardEventImpl*>(event.handle()); }
+ };
+
+ // Constructor object KeyboardEvent
+ class KeyboardEventConstructor : public DOMObject {
+ public:
+ KeyboardEventConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ Value getKeyboardEventConstructor(ExecState *exec);
+
+ // Constructor object MutationEvent
+ class MutationEventConstructor : public DOMObject {
+ public:
+ MutationEventConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ Value getMutationEventConstructor(ExecState *exec);
+
+ class DOMMutationEvent : public DOMEvent {
+ public:
+ DOMMutationEvent(ExecState *exec, DOM::MutationEvent me);
+ ~DOMMutationEvent();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { AttrChange, RelatedNode, AttrName, PrevValue, NewValue,
+ InitMutationEvent };
+ DOM::MutationEvent toMutationEvent() const { return static_cast<DOM::MutationEvent>(event); }
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_html.cpp b/tdehtml/ecma/kjs_html.cpp
new file mode 100644
index 000000000..37fd70754
--- /dev/null
+++ b/tdehtml/ecma/kjs_html.cpp
@@ -0,0 +1,3946 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001-2003 David Faure (faure@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "misc/loader.h"
+#include "dom/html_block.h"
+#include "dom/html_head.h"
+#include "dom/html_image.h"
+#include "dom/html_inline.h"
+#include "dom/html_list.h"
+#include "dom/html_table.h"
+#include "dom/html_object.h"
+#include "dom/dom_exception.h"
+
+// ### HACK
+#include "html/html_baseimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_formimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_miscimpl.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <tdeparts/browserextension.h>
+
+#include "tdehtml_part.h"
+#include "tdehtmlview.h"
+
+#include "ecma/kjs_css.h"
+#include "ecma/kjs_events.h"
+#include "ecma/kjs_html.h"
+#include "ecma/kjs_window.h"
+#include "kjs_html.lut.h"
+
+#include "misc/htmltags.h"
+#include "misc/htmlattrs.h"
+#include "rendering/render_object.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_frames.h"
+#include "rendering/render_layer.h"
+
+#include "kmessagebox.h"
+#include <kstringhandler.h>
+#include <klocale.h>
+
+#include <kdebug.h>
+
+namespace KJS {
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLDocumentProto, DOMDocumentProto)
+IMPLEMENT_PROTOFUNC_DOM(HTMLDocFunction)
+KJS_IMPLEMENT_PROTOTYPE("HTMLDocument", HTMLDocumentProto, HTMLDocFunction)
+
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDocumentPseudoCtor, "HTMLDocument", HTMLDocumentProto)
+
+/* Source for HTMLDocumentProtoTable.
+@begin HTMLDocumentProtoTable 11
+ clear HTMLDocument::Clear DontDelete|Function 0
+ open HTMLDocument::Open DontDelete|Function 0
+ close HTMLDocument::Close DontDelete|Function 0
+ write HTMLDocument::Write DontDelete|Function 1
+ writeln HTMLDocument::WriteLn DontDelete|Function 1
+ getElementsByName HTMLDocument::GetElementsByName DontDelete|Function 1
+ getSelection HTMLDocument::GetSelection DontDelete|Function 1
+ captureEvents HTMLDocument::CaptureEvents DontDelete|Function 0
+ releaseEvents HTMLDocument::ReleaseEvents DontDelete|Function 0
+@end
+*/
+
+
+Value KJS::HTMLDocFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( HTMLDocument, thisObj );
+
+ DOM::HTMLDocument doc = static_cast<KJS::HTMLDocument *>(thisObj.imp())->toDocument();
+
+ switch (id) {
+ case HTMLDocument::Clear: // even IE doesn't support that one...
+ //doc.clear(); // TODO
+ return Undefined();
+ case HTMLDocument::Open:
+ if (args.size() >= 3) // IE extension for document.open: it means window.open if it has 3 args or more
+ {
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
+ if ( view && view->part() ) {
+ Window* win = Window::retrieveWindow(view->part());
+ if( win ) {
+ win->openWindow(exec, args);
+ }
+ }
+ }
+
+ doc.open();
+ return Undefined();
+ case HTMLDocument::Close:
+ // see tdehtmltests/ecma/tokenizer-script-recursion.html
+ doc.close();
+ return Undefined();
+ case HTMLDocument::Write:
+ case HTMLDocument::WriteLn: {
+ // DOM only specifies single string argument, but NS & IE allow multiple
+ // or no arguments
+ UString str = "";
+ for (int i = 0; i < args.size(); i++)
+ str += args[i].toString(exec);
+ if (id == HTMLDocument::WriteLn)
+ str += "\n";
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "document.write: " << str.string().string() << endl;
+#endif
+ doc.write(str.string());
+ return Undefined();
+ }
+ case HTMLDocument::GetElementsByName:
+ return getDOMNodeList(exec,doc.getElementsByName(args[0].toString(exec).string()));
+ case HTMLDocument::GetSelection: {
+ // NS4 and Mozilla specific. IE uses document.selection.createRange()
+ // http://docs.sun.com/source/816-6408-10/document.htm#1195981
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
+ if ( view && view->part() )
+ return String(view->part()->selectedText());
+ else
+ return Undefined();
+ }
+ case HTMLDocument::CaptureEvents:
+ case HTMLDocument::ReleaseEvents:
+ // Do nothing for now. These are NS-specific legacy calls.
+ break;
+ }
+
+ return Undefined();
+}
+
+const ClassInfo KJS::HTMLDocument::info =
+ { "HTMLDocument", &DOMDocument::info, &HTMLDocumentTable, 0 };
+/* Source for HTMLDocumentTable.
+@begin HTMLDocumentTable 31
+ title HTMLDocument::Title DontDelete
+ referrer HTMLDocument::Referrer DontDelete|ReadOnly
+ domain HTMLDocument::Domain DontDelete
+ URL HTMLDocument::URL DontDelete|ReadOnly
+ body HTMLDocument::Body DontDelete
+ location HTMLDocument::Location DontDelete
+ cookie HTMLDocument::Cookie DontDelete
+ images HTMLDocument::Images DontDelete|ReadOnly
+ applets HTMLDocument::Applets DontDelete|ReadOnly
+ links HTMLDocument::Links DontDelete|ReadOnly
+ forms HTMLDocument::Forms DontDelete|ReadOnly
+ anchors HTMLDocument::Anchors DontDelete|ReadOnly
+ scripts HTMLDocument::Scripts DontDelete|ReadOnly
+ all HTMLDocument::All DontDelete|ReadOnly
+ bgColor HTMLDocument::BgColor DontDelete
+ fgColor HTMLDocument::FgColor DontDelete
+ alinkColor HTMLDocument::AlinkColor DontDelete
+ linkColor HTMLDocument::LinkColor DontDelete
+ vlinkColor HTMLDocument::VlinkColor DontDelete
+ lastModified HTMLDocument::LastModified DontDelete|ReadOnly
+ height HTMLDocument::Height DontDelete|ReadOnly
+ width HTMLDocument::Width DontDelete|ReadOnly
+ dir HTMLDocument::Dir DontDelete
+ compatMode HTMLDocument::CompatMode DontDelete|ReadOnly
+#IE extension
+ frames HTMLDocument::Frames DontDelete|ReadOnly
+#NS4 extension
+ layers HTMLDocument::Layers DontDelete|ReadOnly
+#potentially obsolete array properties
+# plugins
+# tags
+#potentially obsolete properties
+# embeds
+# ids
+@end
+*/
+
+KJS::HTMLDocument::HTMLDocument(ExecState *exec, const DOM::HTMLDocument& d)
+ : DOMDocument(HTMLDocumentProto::self(exec), d) { }
+
+bool KJS::HTMLDocument::hasProperty(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ //kdDebug(6070) << "KJS::HTMLDocument::hasProperty " << p.qstring() << endl;
+#endif
+ DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
+ DOM::DocumentImpl* docImpl = static_cast<DOM::DocumentImpl*>(doc.handle());
+ KHTMLView *view = docImpl->view();
+ Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
+ if ( !win || !win->isSafeScript(exec) )
+ return false;
+
+
+ if ( docImpl->underDocNamedCache().contains( p.qstring() ) )
+ return true;
+
+ if ( view && view->part() )
+ {
+ KHTMLPart *kp = view->part()->findFrame( p.qstring() );
+ if (kp)
+ return true;
+ }
+
+ return DOMDocument::hasProperty(exec, p);
+}
+
+Value KJS::HTMLDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLDocument::tryGet " << propertyName.qstring() << endl;
+#endif
+
+ DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
+ DOM::DocumentImpl* docImpl = static_cast<DOM::DocumentImpl*>(doc.handle());
+ KHTMLView *view = docImpl->view();
+
+ Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
+ if ( !win || !win->isSafeScript(exec) )
+ return Undefined();
+
+ //Check for images, forms, objects, etc.
+ ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(propertyName.qstring());
+ if (info) {
+ //May be a false positive, but we can try to avoid doing it the hard way in
+ //simpler cases. The trickiness here is that the cache is kept under both
+ //name and id, but we sometimes ignore id for IE compat
+ DOM::DOMString propertyDOMString = propertyName.string();
+
+ if (info->nd && DOM::HTMLMappedNameCollectionImpl::matchesName(info->nd,
+ HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, propertyDOMString)) {
+ return getDOMNode(exec, info->nd);
+ } else {
+ //Can't tell it just like that, so better go through collection and count stuff. This is the slow path...
+ DOM::HTMLMappedNameCollection coll(docImpl, HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, propertyDOMString);
+
+ if (coll.length() == 1) {
+ DOM::Node node = coll.firstItem();
+ return getDOMNode(exec, node);
+ } else if (coll.length() > 1) {
+ return getHTMLCollection(exec, coll);
+ }
+ }
+ }
+
+ // Check for frames/iframes with name==propertyName
+ if ( view && view->part() )
+ {
+ // ###### TODO return a collection in case several frames have the same name
+ // (IE does that). Hard to do with findFrame :}
+ KHTMLPart *kp = view->part()->findFrame( propertyName.qstring() );
+ if (kp)
+ return Window::retrieve(kp);
+ }
+
+ const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
+ if (entry) {
+ switch (entry->value) {
+ case Title:
+ return String(doc.title());
+ case Referrer:
+ return String(doc.referrer());
+ case Domain:
+ return String(doc.domain());
+ case URL:
+ return String(doc.URL());
+ case Body:
+ return getDOMNode(exec,doc.body());
+ case Location:
+ if (win)
+ return Value(win->location());
+ else
+ return Undefined();
+ case Cookie:
+ return String(doc.cookie());
+ case Images:
+ return getHTMLCollection(exec,doc.images());
+ case Applets:
+ return getHTMLCollection(exec,doc.applets());
+ case Links:
+ return getHTMLCollection(exec,doc.links());
+ case Forms:
+ return getHTMLCollection(exec,doc.forms());
+ case Layers:
+ // ### Should not be hidden when we emulate Netscape4
+ return getHTMLCollection(exec,doc.layers(), true);
+ case Anchors:
+ return getHTMLCollection(exec,doc.anchors());
+ case Scripts:
+ return getHTMLCollection(exec,doc.scripts());
+ case All:
+ // Disable document.all when we try to be Netscape-compatible
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
+ return Undefined();
+ else
+ if ( exec->interpreter()->compatMode() == Interpreter::IECompat )
+ return getHTMLCollection(exec,doc.all());
+ else // enabled but hidden
+ return getHTMLCollection(exec,doc.all(), true);
+ case CompatMode:
+ return String(static_cast<HTMLDocumentImpl *>(doc.handle())->parseMode()
+ == DocumentImpl::Compat ? "BackCompat" : "CSS1Compat");
+ }
+ }
+ // Look for overrides
+ ValueImp * val = ObjectImp::getDirect(propertyName);
+ if (val)
+ return Value(val);
+
+ DOM::HTMLBodyElement body = doc.body();
+ if (entry) {
+ switch (entry->value) {
+ case BgColor:
+ return String(body.bgColor());
+ case FgColor:
+ return String(body.text());
+ case AlinkColor:
+ return String(body.aLink());
+ case LinkColor:
+ return String(body.link());
+ case VlinkColor:
+ return String(body.vLink());
+ case LastModified:
+ return String(doc.lastModified());
+ case Height: // NS-only, not available in IE
+ return Number(view ? view->contentsHeight() : 0);
+ case Width: // NS-only, not available in IE
+ return Number(view ? view->contentsWidth() : 0);
+ case Dir:
+ return String(body.dir());
+ case Frames:
+ if ( win )
+ return Value(win->frames(exec));
+ else
+ return Undefined();
+ }
+ }
+ return DOMDocument::tryGet(exec, propertyName);
+}
+
+void KJS::HTMLDocument::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLDocument::tryPut " << propertyName.qstring() << endl;
+#endif
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(node.handle())->view();
+
+ Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
+ if ( !win || !win->isSafeScript(exec) )
+ return;
+
+ DOMObjectLookupPut<HTMLDocument, DOMDocument>( exec, propertyName, value, attr, &HTMLDocumentTable, this );
+}
+
+void KJS::HTMLDocument::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
+{
+ DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
+
+ DOM::HTMLBodyElement body = doc.body();
+ DOM::DOMString val = value.toString(exec).string();
+
+ switch (token) {
+ case Title:
+ if (doc.title() != val) doc.setTitle(val);
+ break;
+ case Body: {
+ DOMNode *node = new DOMNode(exec, KJS::toNode(value));
+ // This is required to avoid leaking the node.
+ Value nodeValue(node);
+ doc.setBody(node->toNode());
+ break;
+ }
+ case Domain: { // not part of the DOM
+ DOM::HTMLDocumentImpl* docimpl = static_cast<DOM::HTMLDocumentImpl*>(doc.handle());
+ if (docimpl)
+ docimpl->setDomain(val);
+ break;
+ }
+ case Cookie:
+ doc.setCookie(val);
+ break;
+ case Location:
+ {
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
+ if ( view )
+ Window::retrieveWindow(view->part())->goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
+ break;
+ }
+ case BgColor:
+ if (body.bgColor() != val) body.setBgColor(val);
+ break;
+ case FgColor:
+ if (body.text() != val) body.setText(val);
+ break;
+ case AlinkColor:
+ if (body.aLink() != val) body.setALink(val);
+ break;
+ case LinkColor:
+ if (body.link() != val) body.setLink(val);
+ break;
+ case VlinkColor:
+ if (body.vLink() != val) body.setVLink(val);
+ break;
+ case Dir:
+ body.setDir(val);
+ break;
+ default:
+ kdDebug(6070) << "WARNING: HTMLDocument::putValueProperty unhandled token " << token << endl;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo KJS::HTMLElement::info = { "HTMLElement", &DOMElement::info, &HTMLElementTable, 0 };
+const ClassInfo KJS::HTMLElement::html_info = { "HTMLHtmlElement", &KJS::HTMLElement::info, &HTMLHtmlElementTable, 0 };
+const ClassInfo KJS::HTMLElement::head_info = { "HTMLHeadElement", &KJS::HTMLElement::info, &HTMLHeadElementTable, 0 };
+const ClassInfo KJS::HTMLElement::link_info = { "HTMLLinkElement", &KJS::HTMLElement::info, &HTMLLinkElementTable, 0 };
+const ClassInfo KJS::HTMLElement::title_info = { "HTMLTitleElement", &KJS::HTMLElement::info, &HTMLTitleElementTable, 0 };
+const ClassInfo KJS::HTMLElement::meta_info = { "HTMLMetaElement", &KJS::HTMLElement::info, &HTMLMetaElementTable, 0 };
+const ClassInfo KJS::HTMLElement::base_info = { "HTMLBaseElement", &KJS::HTMLElement::info, &HTMLBaseElementTable, 0 };
+const ClassInfo KJS::HTMLElement::isIndex_info = { "HTMLIsIndexElement", &KJS::HTMLElement::info, &HTMLIsIndexElementTable, 0 };
+const ClassInfo KJS::HTMLElement::style_info = { "HTMLStyleElement", &KJS::HTMLElement::info, &HTMLStyleElementTable, 0 };
+const ClassInfo KJS::HTMLElement::body_info = { "HTMLBodyElement", &KJS::HTMLElement::info, &HTMLBodyElementTable, 0 };
+const ClassInfo KJS::HTMLElement::form_info = { "HTMLFormElement", &KJS::HTMLElement::info, &HTMLFormElementTable, 0 };
+const ClassInfo KJS::HTMLElement::select_info = { "HTMLSelectElement", &KJS::HTMLElement::info, &HTMLSelectElementTable, 0 };
+const ClassInfo KJS::HTMLElement::optGroup_info = { "HTMLOptGroupElement", &KJS::HTMLElement::info, &HTMLOptGroupElementTable, 0 };
+const ClassInfo KJS::HTMLElement::option_info = { "HTMLOptionElement", &KJS::HTMLElement::info, &HTMLOptionElementTable, 0 };
+const ClassInfo KJS::HTMLElement::input_info = { "HTMLInputElement", &KJS::HTMLElement::info, &HTMLInputElementTable, 0 };
+const ClassInfo KJS::HTMLElement::textArea_info = { "HTMLTextAreaElement", &KJS::HTMLElement::info, &HTMLTextAreaElementTable, 0 };
+const ClassInfo KJS::HTMLElement::button_info = { "HTMLButtonElement", &KJS::HTMLElement::info, &HTMLButtonElementTable, 0 };
+const ClassInfo KJS::HTMLElement::label_info = { "HTMLLabelElement", &KJS::HTMLElement::info, &HTMLLabelElementTable, 0 };
+const ClassInfo KJS::HTMLElement::fieldSet_info = { "HTMLFieldSetElement", &KJS::HTMLElement::info, &HTMLFieldSetElementTable, 0 };
+const ClassInfo KJS::HTMLElement::legend_info = { "HTMLLegendElement", &KJS::HTMLElement::info, &HTMLLegendElementTable, 0 };
+const ClassInfo KJS::HTMLElement::ul_info = { "HTMLUListElement", &KJS::HTMLElement::info, &HTMLUListElementTable, 0 };
+const ClassInfo KJS::HTMLElement::ol_info = { "HTMLOListElement", &KJS::HTMLElement::info, &HTMLOListElementTable, 0 };
+const ClassInfo KJS::HTMLElement::dl_info = { "HTMLDListElement", &KJS::HTMLElement::info, &HTMLDListElementTable, 0 };
+const ClassInfo KJS::HTMLElement::dir_info = { "HTMLDirectoryElement", &KJS::HTMLElement::info, &HTMLDirectoryElementTable, 0 };
+const ClassInfo KJS::HTMLElement::menu_info = { "HTMLMenuElement", &KJS::HTMLElement::info, &HTMLMenuElementTable, 0 };
+const ClassInfo KJS::HTMLElement::li_info = { "HTMLLIElement", &KJS::HTMLElement::info, &HTMLLIElementTable, 0 };
+const ClassInfo KJS::HTMLElement::div_info = { "HTMLDivElement", &KJS::HTMLElement::info, &HTMLDivElementTable, 0 };
+const ClassInfo KJS::HTMLElement::p_info = { "HTMLParagraphElement", &KJS::HTMLElement::info, &HTMLParagraphElementTable, 0 };
+const ClassInfo KJS::HTMLElement::heading_info = { "HTMLHeadingElement", &KJS::HTMLElement::info, &HTMLHeadingElementTable, 0 };
+const ClassInfo KJS::HTMLElement::blockQuote_info = { "HTMLBlockQuoteElement", &KJS::HTMLElement::info, &HTMLBlockQuoteElementTable, 0 };
+const ClassInfo KJS::HTMLElement::q_info = { "HTMLQuoteElement", &KJS::HTMLElement::info, &HTMLQuoteElementTable, 0 };
+const ClassInfo KJS::HTMLElement::pre_info = { "HTMLPreElement", &KJS::HTMLElement::info, &HTMLPreElementTable, 0 };
+const ClassInfo KJS::HTMLElement::br_info = { "HTMLBRElement", &KJS::HTMLElement::info, &HTMLBRElementTable, 0 };
+const ClassInfo KJS::HTMLElement::baseFont_info = { "HTMLBaseFontElement", &KJS::HTMLElement::info, &HTMLBaseFontElementTable, 0 };
+const ClassInfo KJS::HTMLElement::font_info = { "HTMLFontElement", &KJS::HTMLElement::info, &HTMLFontElementTable, 0 };
+const ClassInfo KJS::HTMLElement::hr_info = { "HTMLHRElement", &KJS::HTMLElement::info, &HTMLHRElementTable, 0 };
+const ClassInfo KJS::HTMLElement::mod_info = { "HTMLModElement", &KJS::HTMLElement::info, &HTMLModElementTable, 0 };
+const ClassInfo KJS::HTMLElement::a_info = { "HTMLAnchorElement", &KJS::HTMLElement::info, &HTMLAnchorElementTable, 0 };
+const ClassInfo KJS::HTMLElement::img_info = { "HTMLImageElement", &KJS::HTMLElement::info, &HTMLImageElementTable, 0 };
+const ClassInfo KJS::HTMLElement::object_info = { "HTMLObjectElement", &KJS::HTMLElement::info, &HTMLObjectElementTable, 0 };
+const ClassInfo KJS::HTMLElement::param_info = { "HTMLParamElement", &KJS::HTMLElement::info, &HTMLParamElementTable, 0 };
+const ClassInfo KJS::HTMLElement::applet_info = { "HTMLAppletElement", &KJS::HTMLElement::info, &HTMLAppletElementTable, 0 };
+const ClassInfo KJS::HTMLElement::map_info = { "HTMLMapElement", &KJS::HTMLElement::info, &HTMLMapElementTable, 0 };
+const ClassInfo KJS::HTMLElement::area_info = { "HTMLAreaElement", &KJS::HTMLElement::info, &HTMLAreaElementTable, 0 };
+const ClassInfo KJS::HTMLElement::script_info = { "HTMLScriptElement", &KJS::HTMLElement::info, &HTMLScriptElementTable, 0 };
+const ClassInfo KJS::HTMLElement::table_info = { "HTMLTableElement", &KJS::HTMLElement::info, &HTMLTableElementTable, 0 };
+const ClassInfo KJS::HTMLElement::caption_info = { "HTMLTableCaptionElement", &KJS::HTMLElement::info, &HTMLTableCaptionElementTable, 0 };
+const ClassInfo KJS::HTMLElement::col_info = { "HTMLTableColElement", &KJS::HTMLElement::info, &HTMLTableColElementTable, 0 };
+const ClassInfo KJS::HTMLElement::tablesection_info = { "HTMLTableSectionElement", &KJS::HTMLElement::info, &HTMLTableSectionElementTable, 0 };
+const ClassInfo KJS::HTMLElement::tr_info = { "HTMLTableRowElement", &KJS::HTMLElement::info, &HTMLTableRowElementTable, 0 };
+const ClassInfo KJS::HTMLElement::tablecell_info = { "HTMLTableCellElement", &KJS::HTMLElement::info, &HTMLTableCellElementTable, 0 };
+const ClassInfo KJS::HTMLElement::frameSet_info = { "HTMLFrameSetElement", &KJS::HTMLElement::info, &HTMLFrameSetElementTable, 0 };
+const ClassInfo KJS::HTMLElement::frame_info = { "HTMLFrameElement", &KJS::HTMLElement::info, &HTMLFrameElementTable, 0 };
+const ClassInfo KJS::HTMLElement::iFrame_info = { "HTMLIFrameElement", &KJS::HTMLElement::info, &HTMLIFrameElementTable, 0 };
+const ClassInfo KJS::HTMLElement::marquee_info = { "HTMLMarqueeElement", &KJS::HTMLElement::info, 0, 0 };
+const ClassInfo KJS::HTMLElement::layer_info = { "HTMLLayerElement", &KJS::HTMLElement::info, &HTMLLayerElementTable, 0 };
+
+static Object prototypeForID(ExecState* exec, DOM::NodeImpl::Id id);
+
+KJS::HTMLElement::HTMLElement(ExecState *exec, const DOM::HTMLElement& e) :
+ DOMElement(prototypeForID(exec, e.elementId()), e) { }
+
+const ClassInfo* KJS::HTMLElement::classInfo() const
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+ switch (element.elementId()) {
+ case ID_HTML:
+ return &html_info;
+ case ID_HEAD:
+ return &head_info;
+ case ID_LINK:
+ return &link_info;
+ case ID_TITLE:
+ return &title_info;
+ case ID_META:
+ return &meta_info;
+ case ID_BASE:
+ return &base_info;
+ case ID_ISINDEX:
+ return &isIndex_info;
+ case ID_STYLE:
+ return &style_info;
+ case ID_BODY:
+ return &body_info;
+ case ID_FORM:
+ return &form_info;
+ case ID_SELECT:
+ return &select_info;
+ case ID_OPTGROUP:
+ return &optGroup_info;
+ case ID_OPTION:
+ return &option_info;
+ case ID_INPUT:
+ return &input_info;
+ case ID_TEXTAREA:
+ return &textArea_info;
+ case ID_BUTTON:
+ return &button_info;
+ case ID_LABEL:
+ return &label_info;
+ case ID_FIELDSET:
+ return &fieldSet_info;
+ case ID_LEGEND:
+ return &legend_info;
+ case ID_UL:
+ return &ul_info;
+ case ID_OL:
+ return &ol_info;
+ case ID_DL:
+ return &dl_info;
+ case ID_DIR:
+ return &dir_info;
+ case ID_MENU:
+ return &menu_info;
+ case ID_LI:
+ return &li_info;
+ case ID_DIV:
+ return &div_info;
+ case ID_P:
+ return &p_info;
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ return &heading_info;
+ case ID_BLOCKQUOTE:
+ return &blockQuote_info;
+ case ID_Q:
+ return &q_info;
+ case ID_PRE:
+ return &pre_info;
+ case ID_BR:
+ return &br_info;
+ case ID_BASEFONT:
+ return &baseFont_info;
+ case ID_FONT:
+ return &font_info;
+ case ID_HR:
+ return &hr_info;
+ case ID_INS:
+ case ID_DEL:
+ return &mod_info;
+ case ID_A:
+ return &a_info;
+ case ID_IMG:
+ return &img_info;
+ case ID_OBJECT:
+ return &object_info;
+ case ID_PARAM:
+ return &param_info;
+ case ID_APPLET:
+ return &applet_info;
+ case ID_MAP:
+ return &map_info;
+ case ID_AREA:
+ return &area_info;
+ case ID_SCRIPT:
+ return &script_info;
+ case ID_TABLE:
+ return &table_info;
+ case ID_CAPTION:
+ return &caption_info;
+ case ID_COL:
+ case ID_COLGROUP:
+ return &col_info;
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT:
+ return &tablesection_info;
+ case ID_TR:
+ return &tr_info;
+ case ID_TH:
+ case ID_TD:
+ return &tablecell_info;
+ case ID_FRAMESET:
+ return &frameSet_info;
+ case ID_FRAME:
+ return &frame_info;
+ case ID_IFRAME:
+ return &iFrame_info;
+ case ID_MARQUEE:
+ return &marquee_info;
+ case ID_LAYER:
+ return &layer_info;
+ default:
+ return &info;
+ }
+}
+/*
+@begin HTMLElementTable 11
+ id KJS::HTMLElement::ElementId DontDelete
+ title KJS::HTMLElement::ElementTitle DontDelete
+ lang KJS::HTMLElement::ElementLang DontDelete
+ dir KJS::HTMLElement::ElementDir DontDelete
+### isn't this "class" in the HTML spec?
+ className KJS::HTMLElement::ElementClassName DontDelete
+ innerHTML KJS::HTMLElement::ElementInnerHTML DontDelete
+ innerText KJS::HTMLElement::ElementInnerText DontDelete
+ document KJS::HTMLElement::ElementDocument DontDelete|ReadOnly
+# IE extension
+ children KJS::HTMLElement::ElementChildren DontDelete|ReadOnly
+ all KJS::HTMLElement::ElementAll DontDelete|ReadOnly
+@end
+@begin HTMLElementProtoTable 1
+ scrollIntoView KJS::HTMLElement::ElementScrollIntoView DontDelete|Function 0
+@end
+@begin HTMLHtmlElementTable 1
+ version KJS::HTMLElement::HtmlVersion DontDelete
+@end
+@begin HTMLHeadElementTable 1
+ profile KJS::HTMLElement::HeadProfile DontDelete
+@end
+@begin HTMLLinkElementTable 11
+ disabled KJS::HTMLElement::LinkDisabled DontDelete
+ charset KJS::HTMLElement::LinkCharset DontDelete
+ href KJS::HTMLElement::LinkHref DontDelete
+ hreflang KJS::HTMLElement::LinkHrefLang DontDelete
+ media KJS::HTMLElement::LinkMedia DontDelete
+ rel KJS::HTMLElement::LinkRel DontDelete
+ rev KJS::HTMLElement::LinkRev DontDelete
+ target KJS::HTMLElement::LinkTarget DontDelete
+ type KJS::HTMLElement::LinkType DontDelete
+ sheet KJS::HTMLElement::LinkSheet DontDelete|ReadOnly
+@end
+@begin HTMLTitleElementTable 1
+ text KJS::HTMLElement::TitleText DontDelete
+@end
+@begin HTMLMetaElementTable 4
+ content KJS::HTMLElement::MetaContent DontDelete
+ httpEquiv KJS::HTMLElement::MetaHttpEquiv DontDelete
+ name KJS::HTMLElement::MetaName DontDelete
+ scheme KJS::HTMLElement::MetaScheme DontDelete
+@end
+@begin HTMLBaseElementTable 2
+ href KJS::HTMLElement::BaseHref DontDelete
+ target KJS::HTMLElement::BaseTarget DontDelete
+@end
+@begin HTMLIsIndexElementTable 2
+ form KJS::HTMLElement::IsIndexForm DontDelete|ReadOnly
+ prompt KJS::HTMLElement::IsIndexPrompt DontDelete
+@end
+@begin HTMLStyleElementTable 4
+ disabled KJS::HTMLElement::StyleDisabled DontDelete
+ media KJS::HTMLElement::StyleMedia DontDelete
+ type KJS::HTMLElement::StyleType DontDelete
+ sheet KJS::HTMLElement::StyleSheet DontDelete|ReadOnly
+@end
+@begin HTMLBodyElementTable 8
+ aLink KJS::HTMLElement::BodyALink DontDelete
+ background KJS::HTMLElement::BodyBackground DontDelete
+ bgColor KJS::HTMLElement::BodyBgColor DontDelete
+ link KJS::HTMLElement::BodyLink DontDelete
+ text KJS::HTMLElement::BodyText DontDelete
+ vLink KJS::HTMLElement::BodyVLink DontDelete
+# IE extension
+ onload KJS::HTMLElement::BodyOnLoad DontDelete
+@end
+@begin HTMLBodyElementProtoTable 2
+# Mozilla'ish extension. Ideally we would want to support this on all elements.
+# Not hard, but not an immediate need.
+ focus KJS::HTMLElement::BodyFocus DontDelete|Function 0
+@end
+@begin HTMLFormElementTable 11
+# Also supported, by name/index
+ elements KJS::HTMLElement::FormElements DontDelete|ReadOnly
+ length KJS::HTMLElement::FormLength DontDelete|ReadOnly
+ name KJS::HTMLElement::FormName DontDelete
+ acceptCharset KJS::HTMLElement::FormAcceptCharset DontDelete
+ action KJS::HTMLElement::FormAction DontDelete
+ encoding KJS::HTMLElement::FormEncType DontDelete
+ enctype KJS::HTMLElement::FormEncType DontDelete
+ method KJS::HTMLElement::FormMethod DontDelete
+ target KJS::HTMLElement::FormTarget DontDelete
+@end
+@begin HTMLFormElementProtoTable 2
+ submit KJS::HTMLElement::FormSubmit DontDelete|Function 0
+ reset KJS::HTMLElement::FormReset DontDelete|Function 0
+@end
+@begin HTMLSelectElementTable 11
+# Also supported, by index
+ type KJS::HTMLElement::SelectType DontDelete|ReadOnly
+ selectedIndex KJS::HTMLElement::SelectSelectedIndex DontDelete
+ value KJS::HTMLElement::SelectValue DontDelete
+ length KJS::HTMLElement::SelectLength DontDelete
+ form KJS::HTMLElement::SelectForm DontDelete|ReadOnly
+ options KJS::HTMLElement::SelectOptions DontDelete|ReadOnly
+ disabled KJS::HTMLElement::SelectDisabled DontDelete
+ multiple KJS::HTMLElement::SelectMultiple DontDelete
+ name KJS::HTMLElement::SelectName DontDelete
+ size KJS::HTMLElement::SelectSize DontDelete
+ tabIndex KJS::HTMLElement::SelectTabIndex DontDelete
+@end
+@begin HTMLSelectElementProtoTable 4
+ add KJS::HTMLElement::SelectAdd DontDelete|Function 2
+ remove KJS::HTMLElement::SelectRemove DontDelete|Function 1
+ blur KJS::HTMLElement::SelectBlur DontDelete|Function 0
+ focus KJS::HTMLElement::SelectFocus DontDelete|Function 0
+@end
+@begin HTMLOptGroupElementTable 2
+ disabled KJS::HTMLElement::OptGroupDisabled DontDelete
+ label KJS::HTMLElement::OptGroupLabel DontDelete
+@end
+@begin HTMLOptionElementTable 8
+ form KJS::HTMLElement::OptionForm DontDelete|ReadOnly
+ defaultSelected KJS::HTMLElement::OptionDefaultSelected DontDelete
+ text KJS::HTMLElement::OptionText DontDelete
+ index KJS::HTMLElement::OptionIndex DontDelete|ReadOnly
+ disabled KJS::HTMLElement::OptionDisabled DontDelete
+ label KJS::HTMLElement::OptionLabel DontDelete
+ selected KJS::HTMLElement::OptionSelected DontDelete
+ value KJS::HTMLElement::OptionValue DontDelete
+@end
+@begin HTMLInputElementTable 25
+ defaultValue KJS::HTMLElement::InputDefaultValue DontDelete
+ defaultChecked KJS::HTMLElement::InputDefaultChecked DontDelete
+ form KJS::HTMLElement::InputForm DontDelete|ReadOnly
+ accept KJS::HTMLElement::InputAccept DontDelete
+ accessKey KJS::HTMLElement::InputAccessKey DontDelete
+ align KJS::HTMLElement::InputAlign DontDelete
+ alt KJS::HTMLElement::InputAlt DontDelete
+ checked KJS::HTMLElement::InputChecked DontDelete
+ indeterminate KJS::HTMLElement::InputIndeterminate DontDelete
+ status KJS::HTMLElement::InputChecked DontDelete
+ disabled KJS::HTMLElement::InputDisabled DontDelete
+ maxLength KJS::HTMLElement::InputMaxLength DontDelete
+ name KJS::HTMLElement::InputName DontDelete
+ readOnly KJS::HTMLElement::InputReadOnly DontDelete
+ size KJS::HTMLElement::InputSize DontDelete
+ src KJS::HTMLElement::InputSrc DontDelete
+ tabIndex KJS::HTMLElement::InputTabIndex DontDelete
+ type KJS::HTMLElement::InputType DontDelete
+ useMap KJS::HTMLElement::InputUseMap DontDelete
+ value KJS::HTMLElement::InputValue DontDelete
+ selectionStart KJS::HTMLElement::InputSelectionStart DontDelete
+ selectionEnd KJS::HTMLElement::InputSelectionEnd DontDelete
+@end
+@begin HTMLInputElementProtoTable 5
+ blur KJS::HTMLElement::InputBlur DontDelete|Function 0
+ focus KJS::HTMLElement::InputFocus DontDelete|Function 0
+ select KJS::HTMLElement::InputSelect DontDelete|Function 0
+ click KJS::HTMLElement::InputClick DontDelete|Function 0
+ setSelectionRange KJS::HTMLElement::InputSetSelectionRange DontDelete|Function 2
+@end
+@begin HTMLTextAreaElementTable 13
+ defaultValue KJS::HTMLElement::TextAreaDefaultValue DontDelete
+ form KJS::HTMLElement::TextAreaForm DontDelete|ReadOnly
+ accessKey KJS::HTMLElement::TextAreaAccessKey DontDelete
+ cols KJS::HTMLElement::TextAreaCols DontDelete
+ disabled KJS::HTMLElement::TextAreaDisabled DontDelete
+ name KJS::HTMLElement::TextAreaName DontDelete
+ readOnly KJS::HTMLElement::TextAreaReadOnly DontDelete
+ rows KJS::HTMLElement::TextAreaRows DontDelete
+ tabIndex KJS::HTMLElement::TextAreaTabIndex DontDelete
+ type KJS::HTMLElement::TextAreaType DontDelete|ReadOnly
+ value KJS::HTMLElement::TextAreaValue DontDelete
+ selectionStart KJS::HTMLElement::TextAreaSelectionStart DontDelete
+ selectionEnd KJS::HTMLElement::TextAreaSelectionEnd DontDelete
+ textLength KJS::HTMLElement::TextAreaTextLength DontDelete|ReadOnly
+@end
+@begin HTMLTextAreaElementProtoTable 4
+ blur KJS::HTMLElement::TextAreaBlur DontDelete|Function 0
+ focus KJS::HTMLElement::TextAreaFocus DontDelete|Function 0
+ select KJS::HTMLElement::TextAreaSelect DontDelete|Function 0
+ setSelectionRange KJS::HTMLElement::TextAreaSetSelectionRange DontDelete|Function 2
+@end
+@begin HTMLButtonElementTable 9
+ form KJS::HTMLElement::ButtonForm DontDelete|ReadOnly
+ accessKey KJS::HTMLElement::ButtonAccessKey DontDelete
+ disabled KJS::HTMLElement::ButtonDisabled DontDelete
+ name KJS::HTMLElement::ButtonName DontDelete
+ tabIndex KJS::HTMLElement::ButtonTabIndex DontDelete
+ type KJS::HTMLElement::ButtonType DontDelete|ReadOnly
+ value KJS::HTMLElement::ButtonValue DontDelete
+@end
+@begin HTMLButtonElementProtoTable 2
+ blur KJS::HTMLElement::ButtonBlur DontDelete|Function 0
+ focus KJS::HTMLElement::ButtonFocus DontDelete|Function 0
+@end
+@begin HTMLLabelElementTable 3
+ form KJS::HTMLElement::LabelForm DontDelete|ReadOnly
+ accessKey KJS::HTMLElement::LabelAccessKey DontDelete
+ htmlFor KJS::HTMLElement::LabelHtmlFor DontDelete
+@end
+@begin HTMLFieldSetElementTable 1
+ form KJS::HTMLElement::FieldSetForm DontDelete|ReadOnly
+@end
+@begin HTMLLegendElementTable 3
+ form KJS::HTMLElement::LegendForm DontDelete|ReadOnly
+ accessKey KJS::HTMLElement::LegendAccessKey DontDelete
+ align KJS::HTMLElement::LegendAlign DontDelete
+@end
+@begin HTMLUListElementTable 2
+ compact KJS::HTMLElement::UListCompact DontDelete
+ type KJS::HTMLElement::UListType DontDelete
+@end
+@begin HTMLOListElementTable 3
+ compact KJS::HTMLElement::OListCompact DontDelete
+ start KJS::HTMLElement::OListStart DontDelete
+ type KJS::HTMLElement::OListType DontDelete
+@end
+@begin HTMLDListElementTable 1
+ compact KJS::HTMLElement::DListCompact DontDelete
+@end
+@begin HTMLDirectoryElementTable 1
+ compact KJS::HTMLElement::DirectoryCompact DontDelete
+@end
+@begin HTMLMenuElementTable 1
+ compact KJS::HTMLElement::MenuCompact DontDelete
+@end
+@begin HTMLLIElementTable 2
+ type KJS::HTMLElement::LIType DontDelete
+ value KJS::HTMLElement::LIValue DontDelete
+@end
+@begin HTMLDivElementTable 1
+ align KJS::HTMLElement::DivAlign DontDelete
+@end
+@begin HTMLParagraphElementTable 1
+ align KJS::HTMLElement::ParagraphAlign DontDelete
+@end
+@begin HTMLHeadingElementTable 1
+ align KJS::HTMLElement::HeadingAlign DontDelete
+@end
+@begin HTMLBlockQuoteElementTable 1
+ cite KJS::HTMLElement::BlockQuoteCite DontDelete
+@end
+@begin HTMLQuoteElementTable 1
+ cite KJS::HTMLElement::QuoteCite DontDelete
+@end
+@begin HTMLPreElementTable 1
+ width KJS::HTMLElement::PreWidth DontDelete
+@end
+@begin HTMLBRElementTable 1
+ clear KJS::HTMLElement::BRClear DontDelete
+@end
+@begin HTMLBaseFontElementTable 3
+ color KJS::HTMLElement::BaseFontColor DontDelete
+ face KJS::HTMLElement::BaseFontFace DontDelete
+ size KJS::HTMLElement::BaseFontSize DontDelete
+@end
+@begin HTMLFontElementTable 3
+ color KJS::HTMLElement::FontColor DontDelete
+ face KJS::HTMLElement::FontFace DontDelete
+ size KJS::HTMLElement::FontSize DontDelete
+@end
+@begin HTMLHRElementTable 4
+ align KJS::HTMLElement::HRAlign DontDelete
+ noShade KJS::HTMLElement::HRNoShade DontDelete
+ size KJS::HTMLElement::HRSize DontDelete
+ width KJS::HTMLElement::HRWidth DontDelete
+@end
+@begin HTMLModElementTable 2
+ cite KJS::HTMLElement::ModCite DontDelete
+ dateTime KJS::HTMLElement::ModDateTime DontDelete
+@end
+@begin HTMLAnchorElementTable 23
+ accessKey KJS::HTMLElement::AnchorAccessKey DontDelete
+ charset KJS::HTMLElement::AnchorCharset DontDelete
+ coords KJS::HTMLElement::AnchorCoords DontDelete
+ href KJS::HTMLElement::AnchorHref DontDelete
+ hreflang KJS::HTMLElement::AnchorHrefLang DontDelete
+ hash KJS::HTMLElement::AnchorHash DontDelete|ReadOnly
+ host KJS::HTMLElement::AnchorHost DontDelete|ReadOnly
+ hostname KJS::HTMLElement::AnchorHostname DontDelete|ReadOnly
+ name KJS::HTMLElement::AnchorName DontDelete
+ pathname KJS::HTMLElement::AnchorPathName DontDelete|ReadOnly
+ port KJS::HTMLElement::AnchorPort DontDelete|ReadOnly
+ protocol KJS::HTMLElement::AnchorProtocol DontDelete|ReadOnly
+ rel KJS::HTMLElement::AnchorRel DontDelete
+ rev KJS::HTMLElement::AnchorRev DontDelete
+ search KJS::HTMLElement::AnchorSearch DontDelete
+ shape KJS::HTMLElement::AnchorShape DontDelete
+ tabIndex KJS::HTMLElement::AnchorTabIndex DontDelete
+ target KJS::HTMLElement::AnchorTarget DontDelete
+ text KJS::HTMLElement::AnchorText DontDelete|ReadOnly
+ type KJS::HTMLElement::AnchorType DontDelete
+@end
+@begin HTMLAnchorElementProtoTable 3
+ blur KJS::HTMLElement::AnchorBlur DontDelete|Function 0
+ focus KJS::HTMLElement::AnchorFocus DontDelete|Function 0
+ click KJS::HTMLElement::AnchorClick DontDelete|Function 0
+@end
+@begin HTMLImageElementTable 15
+ name KJS::HTMLElement::ImageName DontDelete
+ align KJS::HTMLElement::ImageAlign DontDelete
+ alt KJS::HTMLElement::ImageAlt DontDelete
+ border KJS::HTMLElement::ImageBorder DontDelete
+ complete KJS::HTMLElement::ImageComplete DontDelete|ReadOnly
+ height KJS::HTMLElement::ImageHeight DontDelete
+ hspace KJS::HTMLElement::ImageHspace DontDelete
+ isMap KJS::HTMLElement::ImageIsMap DontDelete
+ longDesc KJS::HTMLElement::ImageLongDesc DontDelete
+ src KJS::HTMLElement::ImageSrc DontDelete
+ useMap KJS::HTMLElement::ImageUseMap DontDelete
+ vspace KJS::HTMLElement::ImageVspace DontDelete
+ width KJS::HTMLElement::ImageWidth DontDelete
+ x KJS::HTMLElement::ImageX DontDelete|ReadOnly
+ y KJS::HTMLElement::ImageY DontDelete|ReadOnly
+@end
+@begin HTMLObjectElementTable 20
+ form KJS::HTMLElement::ObjectForm DontDelete|ReadOnly
+ code KJS::HTMLElement::ObjectCode DontDelete
+ align KJS::HTMLElement::ObjectAlign DontDelete
+ archive KJS::HTMLElement::ObjectArchive DontDelete
+ border KJS::HTMLElement::ObjectBorder DontDelete
+ codeBase KJS::HTMLElement::ObjectCodeBase DontDelete
+ codeType KJS::HTMLElement::ObjectCodeType DontDelete
+ contentDocument KJS::HTMLElement::ObjectContentDocument DontDelete|ReadOnly
+ data KJS::HTMLElement::ObjectData DontDelete
+ declare KJS::HTMLElement::ObjectDeclare DontDelete
+ height KJS::HTMLElement::ObjectHeight DontDelete
+ hspace KJS::HTMLElement::ObjectHspace DontDelete
+ name KJS::HTMLElement::ObjectName DontDelete
+ standby KJS::HTMLElement::ObjectStandby DontDelete
+ tabIndex KJS::HTMLElement::ObjectTabIndex DontDelete
+ type KJS::HTMLElement::ObjectType DontDelete
+ useMap KJS::HTMLElement::ObjectUseMap DontDelete
+ vspace KJS::HTMLElement::ObjectVspace DontDelete
+ width KJS::HTMLElement::ObjectWidth DontDelete
+@end
+@begin HTMLParamElementTable 4
+ name KJS::HTMLElement::ParamName DontDelete
+ type KJS::HTMLElement::ParamType DontDelete
+ value KJS::HTMLElement::ParamValue DontDelete
+ valueType KJS::HTMLElement::ParamValueType DontDelete
+@end
+@begin HTMLAppletElementTable 11
+ align KJS::HTMLElement::AppletAlign DontDelete
+ alt KJS::HTMLElement::AppletAlt DontDelete
+ archive KJS::HTMLElement::AppletArchive DontDelete
+ code KJS::HTMLElement::AppletCode DontDelete
+ codeBase KJS::HTMLElement::AppletCodeBase DontDelete
+ height KJS::HTMLElement::AppletHeight DontDelete
+ hspace KJS::HTMLElement::AppletHspace DontDelete
+ name KJS::HTMLElement::AppletName DontDelete
+ object KJS::HTMLElement::AppletObject DontDelete
+ vspace KJS::HTMLElement::AppletVspace DontDelete
+ width KJS::HTMLElement::AppletWidth DontDelete
+@end
+@begin HTMLMapElementTable 2
+ areas KJS::HTMLElement::MapAreas DontDelete|ReadOnly
+ name KJS::HTMLElement::MapName DontDelete
+@end
+@begin HTMLAreaElementTable 15
+ accessKey KJS::HTMLElement::AreaAccessKey DontDelete
+ alt KJS::HTMLElement::AreaAlt DontDelete
+ coords KJS::HTMLElement::AreaCoords DontDelete
+ href KJS::HTMLElement::AreaHref DontDelete
+ hash KJS::HTMLElement::AreaHash DontDelete|ReadOnly
+ host KJS::HTMLElement::AreaHost DontDelete|ReadOnly
+ hostname KJS::HTMLElement::AreaHostName DontDelete|ReadOnly
+ pathname KJS::HTMLElement::AreaPathName DontDelete|ReadOnly
+ port KJS::HTMLElement::AreaPort DontDelete|ReadOnly
+ protocol KJS::HTMLElement::AreaProtocol DontDelete|ReadOnly
+ search KJS::HTMLElement::AreaSearch DontDelete|ReadOnly
+ noHref KJS::HTMLElement::AreaNoHref DontDelete
+ shape KJS::HTMLElement::AreaShape DontDelete
+ tabIndex KJS::HTMLElement::AreaTabIndex DontDelete
+ target KJS::HTMLElement::AreaTarget DontDelete
+@end
+@begin HTMLScriptElementTable 7
+ text KJS::HTMLElement::ScriptText DontDelete
+ htmlFor KJS::HTMLElement::ScriptHtmlFor DontDelete
+ event KJS::HTMLElement::ScriptEvent DontDelete
+ charset KJS::HTMLElement::ScriptCharset DontDelete
+ defer KJS::HTMLElement::ScriptDefer DontDelete
+ src KJS::HTMLElement::ScriptSrc DontDelete
+ type KJS::HTMLElement::ScriptType DontDelete
+@end
+@begin HTMLTableElementTable 23
+ caption KJS::HTMLElement::TableCaption DontDelete
+ tHead KJS::HTMLElement::TableTHead DontDelete
+ tFoot KJS::HTMLElement::TableTFoot DontDelete
+ rows KJS::HTMLElement::TableRows DontDelete|ReadOnly
+ tBodies KJS::HTMLElement::TableTBodies DontDelete|ReadOnly
+ align KJS::HTMLElement::TableAlign DontDelete
+ bgColor KJS::HTMLElement::TableBgColor DontDelete
+ border KJS::HTMLElement::TableBorder DontDelete
+ cellPadding KJS::HTMLElement::TableCellPadding DontDelete
+ cellSpacing KJS::HTMLElement::TableCellSpacing DontDelete
+ frame KJS::HTMLElement::TableFrame DontDelete
+ rules KJS::HTMLElement::TableRules DontDelete
+ summary KJS::HTMLElement::TableSummary DontDelete
+ width KJS::HTMLElement::TableWidth DontDelete
+@end
+@begin HTMLTableElementProtoTable 8
+ createTHead KJS::HTMLElement::TableCreateTHead DontDelete|Function 0
+ deleteTHead KJS::HTMLElement::TableDeleteTHead DontDelete|Function 0
+ createTFoot KJS::HTMLElement::TableCreateTFoot DontDelete|Function 0
+ deleteTFoot KJS::HTMLElement::TableDeleteTFoot DontDelete|Function 0
+ createCaption KJS::HTMLElement::TableCreateCaption DontDelete|Function 0
+ deleteCaption KJS::HTMLElement::TableDeleteCaption DontDelete|Function 0
+ insertRow KJS::HTMLElement::TableInsertRow DontDelete|Function 1
+ deleteRow KJS::HTMLElement::TableDeleteRow DontDelete|Function 1
+@end
+@begin HTMLTableCaptionElementTable 1
+ align KJS::HTMLElement::TableCaptionAlign DontDelete
+@end
+@begin HTMLTableColElementTable 7
+ align KJS::HTMLElement::TableColAlign DontDelete
+ ch KJS::HTMLElement::TableColCh DontDelete
+ chOff KJS::HTMLElement::TableColChOff DontDelete
+ span KJS::HTMLElement::TableColSpan DontDelete
+ vAlign KJS::HTMLElement::TableColVAlign DontDelete
+ width KJS::HTMLElement::TableColWidth DontDelete
+@end
+@begin HTMLTableSectionElementTable 7
+ align KJS::HTMLElement::TableSectionAlign DontDelete
+ ch KJS::HTMLElement::TableSectionCh DontDelete
+ chOff KJS::HTMLElement::TableSectionChOff DontDelete
+ vAlign KJS::HTMLElement::TableSectionVAlign DontDelete
+ rows KJS::HTMLElement::TableSectionRows DontDelete|ReadOnly
+@end
+@begin HTMLTableSectionElementProtoTable 2
+ insertRow KJS::HTMLElement::TableSectionInsertRow DontDelete|Function 1
+ deleteRow KJS::HTMLElement::TableSectionDeleteRow DontDelete|Function 1
+@end
+@begin HTMLTableRowElementTable 11
+ rowIndex KJS::HTMLElement::TableRowRowIndex DontDelete|ReadOnly
+ sectionRowIndex KJS::HTMLElement::TableRowSectionRowIndex DontDelete|ReadOnly
+ cells KJS::HTMLElement::TableRowCells DontDelete|ReadOnly
+ align KJS::HTMLElement::TableRowAlign DontDelete
+ bgColor KJS::HTMLElement::TableRowBgColor DontDelete
+ ch KJS::HTMLElement::TableRowCh DontDelete
+ chOff KJS::HTMLElement::TableRowChOff DontDelete
+ vAlign KJS::HTMLElement::TableRowVAlign DontDelete
+@end
+@begin HTMLTableRowElementProtoTable 2
+ insertCell KJS::HTMLElement::TableRowInsertCell DontDelete|Function 1
+ deleteCell KJS::HTMLElement::TableRowDeleteCell DontDelete|Function 1
+@end
+@begin HTMLTableCellElementTable 15
+ cellIndex KJS::HTMLElement::TableCellCellIndex DontDelete|ReadOnly
+ abbr KJS::HTMLElement::TableCellAbbr DontDelete
+ align KJS::HTMLElement::TableCellAlign DontDelete
+ axis KJS::HTMLElement::TableCellAxis DontDelete
+ bgColor KJS::HTMLElement::TableCellBgColor DontDelete
+ ch KJS::HTMLElement::TableCellCh DontDelete
+ chOff KJS::HTMLElement::TableCellChOff DontDelete
+ colSpan KJS::HTMLElement::TableCellColSpan DontDelete
+ headers KJS::HTMLElement::TableCellHeaders DontDelete
+ height KJS::HTMLElement::TableCellHeight DontDelete
+ noWrap KJS::HTMLElement::TableCellNoWrap DontDelete
+ rowSpan KJS::HTMLElement::TableCellRowSpan DontDelete
+ scope KJS::HTMLElement::TableCellScope DontDelete
+ vAlign KJS::HTMLElement::TableCellVAlign DontDelete
+ width KJS::HTMLElement::TableCellWidth DontDelete
+@end
+@begin HTMLFrameSetElementTable 2
+ cols KJS::HTMLElement::FrameSetCols DontDelete
+ rows KJS::HTMLElement::FrameSetRows DontDelete
+@end
+@begin HTMLLayerElementTable 6
+ top KJS::HTMLElement::LayerTop DontDelete
+ left KJS::HTMLElement::LayerLeft DontDelete
+ visibility KJS::HTMLElement::LayerVisibility DontDelete
+ bgColor KJS::HTMLElement::LayerBgColor DontDelete
+ document KJS::HTMLElement::LayerDocument DontDelete|ReadOnly
+ clip KJS::HTMLElement::LayerClip DontDelete|ReadOnly
+ layers KJS::HTMLElement::LayerLayers DontDelete|ReadOnly
+@end
+@begin HTMLFrameElementTable 13
+ contentDocument KJS::HTMLElement::FrameContentDocument DontDelete|ReadOnly
+ contentWindow KJS::HTMLElement::FrameContentWindow DontDelete|ReadOnly
+ frameBorder KJS::HTMLElement::FrameFrameBorder DontDelete
+ longDesc KJS::HTMLElement::FrameLongDesc DontDelete
+ marginHeight KJS::HTMLElement::FrameMarginHeight DontDelete
+ marginWidth KJS::HTMLElement::FrameMarginWidth DontDelete
+ name KJS::HTMLElement::FrameName DontDelete
+ noResize KJS::HTMLElement::FrameNoResize DontDelete
+ scrolling KJS::HTMLElement::FrameScrolling DontDelete
+ src KJS::HTMLElement::FrameSrc DontDelete
+ location KJS::HTMLElement::FrameLocation DontDelete
+# IE extension
+ width KJS::HTMLElement::FrameWidth DontDelete|ReadOnly
+ height KJS::HTMLElement::FrameHeight DontDelete|ReadOnly
+@end
+@begin HTMLIFrameElementTable 12
+ align KJS::HTMLElement::IFrameAlign DontDelete
+ contentDocument KJS::HTMLElement::IFrameContentDocument DontDelete|ReadOnly
+ contentWindow KJS::HTMLElement::IFrameContentWindow DontDelete|ReadOnly
+ frameBorder KJS::HTMLElement::IFrameFrameBorder DontDelete
+ height KJS::HTMLElement::IFrameHeight DontDelete
+ longDesc KJS::HTMLElement::IFrameLongDesc DontDelete
+ marginHeight KJS::HTMLElement::IFrameMarginHeight DontDelete
+ marginWidth KJS::HTMLElement::IFrameMarginWidth DontDelete
+ name KJS::HTMLElement::IFrameName DontDelete
+ scrolling KJS::HTMLElement::IFrameScrolling DontDelete
+ src KJS::HTMLElement::IFrameSrc DontDelete
+ width KJS::HTMLElement::IFrameWidth DontDelete
+@end
+
+@begin HTMLMarqueeElementProtoTable 2
+ start KJS::HTMLElement::MarqueeStart DontDelete|Function 0
+ stop KJS::HTMLElement::MarqueeStop DontDelete|Function 0
+@end
+
+*/
+
+static KParts::LiveConnectExtension *getLiveConnectExtension(const DOM::HTMLElement & element)
+{
+ DOM::HTMLDocument doc = element.ownerDocument();
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
+ if (view && element.handle())
+ return view->part()->liveConnectExtension(static_cast<tdehtml::RenderPart*>(element.handle()->renderer()));
+ return 0L;
+}
+
+Value KJS::HTMLElement::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLElement::tryGet " << propertyName.qstring() << " thisTag=" << element.tagName().string() << endl;
+#endif
+ // First look at dynamic properties
+ switch (element.elementId()) {
+ case ID_FORM: {
+ DOM::HTMLFormElement form = element;
+ // Check if we're retrieving an element (by index or by name)
+ bool ok;
+ uint u = propertyName.toULong(&ok);
+
+ if (ok)
+ return getDOMNode(exec,form.elements().item(u));
+ KJS::HTMLCollection coll(exec, form.elements());
+ Value namedItems = coll.getNamedItems(exec, propertyName);
+ if (namedItems.type() != UndefinedType)
+ return namedItems;
+ }
+ break;
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ bool ok;
+ uint u = propertyName.toULong(&ok);
+ if (ok)
+ return getDOMNode(exec,select.options().item(u)); // not specified by DOM(?) but supported in netscape/IE
+ }
+ break;
+ case ID_APPLET:
+ case ID_OBJECT:
+ case ID_EMBED: {
+ KParts::LiveConnectExtension *lc = getLiveConnectExtension(element);
+ TQString rvalue;
+ KParts::LiveConnectExtension::Type rtype;
+ unsigned long robjid;
+ if (lc && lc->get(0, propertyName.qstring(), rtype, robjid, rvalue))
+ return getLiveConnectValue(lc, propertyName.qstring(), rtype, rvalue, robjid);
+ }
+ break;
+ default:
+ break;
+ }
+
+ const HashTable* table = classInfo()->propHashTable; // get the right hashtable
+ const HashEntry* entry = table ? Lookup::findEntry(table, propertyName) : 0;
+ if (entry) {
+ if (entry->attr & Function)
+ return lookupOrCreateFunction<KJS::HTMLElementFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
+ return getValueProperty(exec, entry->value);
+ }
+
+ // Base HTMLElement stuff or parent class forward, as usual
+ return DOMObjectLookupGet<KJS::HTMLElementFunction, KJS::HTMLElement, DOMElement>(exec, propertyName, &KJS::HTMLElementTable, this);
+}
+
+Value KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+ switch (element.elementId()) {
+ case ID_HTML: {
+ DOM::HTMLHtmlElement html = element;
+ if (token == HtmlVersion) return String(html.version());
+ }
+ break;
+ case ID_HEAD: {
+ DOM::HTMLHeadElement head = element;
+ if (token == HeadProfile) return String(head.profile());
+ }
+ break;
+ case ID_LINK: {
+ DOM::HTMLLinkElement link = element;
+ switch (token) {
+ case LinkDisabled: return Boolean(link.disabled());
+ case LinkCharset: return String(link.charset());
+ case LinkHref: return String(link.href());
+ case LinkHrefLang: return String(link.hreflang());
+ case LinkMedia: return String(link.media());
+ case LinkRel: return String(link.rel());
+ case LinkRev: return String(link.rev());
+ case LinkTarget: return String(link.target());
+ case LinkType: return String(link.type());
+ case LinkSheet: return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
+ }
+ }
+ break;
+ case ID_TITLE: {
+ DOM::HTMLTitleElement title = element;
+ switch (token) {
+ case TitleText: return String(title.text());
+ }
+ }
+ break;
+ case ID_META: {
+ DOM::HTMLMetaElement meta = element;
+ switch (token) {
+ case MetaContent: return String(meta.content());
+ case MetaHttpEquiv: return String(meta.httpEquiv());
+ case MetaName: return String(meta.name());
+ case MetaScheme: return String(meta.scheme());
+ }
+ }
+ break;
+ case ID_BASE: {
+ DOM::HTMLBaseElement base = element;
+ switch (token) {
+ case BaseHref: return String(base.href());
+ case BaseTarget: return String(base.target());
+ }
+ }
+ break;
+ case ID_ISINDEX: {
+ DOM::HTMLIsIndexElement isindex = element;
+ switch (token) {
+ case IsIndexForm: return getDOMNode(exec,isindex.form()); // type HTMLFormElement
+ case IsIndexPrompt: return String(isindex.prompt());
+ }
+ }
+ break;
+ case ID_STYLE: {
+ DOM::HTMLStyleElement style = element;
+ switch (token) {
+ case StyleDisabled: return Boolean(style.disabled());
+ case StyleMedia: return String(style.media());
+ case StyleType: return String(style.type());
+ case StyleSheet: return getDOMStyleSheet(exec,style.sheet());
+ }
+ }
+ break;
+ case ID_BODY: {
+ DOM::HTMLBodyElement body = element;
+ switch (token) {
+ case BodyALink: return String(body.aLink());
+ case BodyBackground: return String(body.background());
+ case BodyBgColor: return String(body.bgColor());
+ case BodyLink: return String(body.link());
+ case BodyText: return String(body.text());
+ case BodyVLink: return String(body.vLink());
+ case BodyOnLoad: {
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(node.ownerDocument().handle());
+ if (!doc || !checkNodeSecurity(exec, node))
+ return Undefined();
+ DOMNode* kjsDocNode = new DOMNode(exec, doc);
+ // Need to create a Value wrapper to avoid leaking the KJS::DOMNode
+ Value nodeValue(kjsDocNode);
+ return kjsDocNode->getListener( DOM::EventImpl::LOAD_EVENT );
+ }
+ }
+ }
+ break;
+
+ case ID_FORM: {
+ DOM::HTMLFormElement form = element;
+ switch (token) {
+ case FormElements: return getHTMLCollection(exec,form.elements());
+ case FormLength: return Number(form.length());
+ case FormName: return String(form.name()); // NOT getString (IE gives empty string)
+ case FormAcceptCharset: return String(form.acceptCharset());
+ case FormAction: return String(form.action());
+ case FormEncType: return String(form.enctype());
+ case FormMethod: return String(form.method());
+ case FormTarget: return String(form.target());
+ }
+ }
+ break;
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ switch (token) {
+ case SelectType: return String(select.type());
+ case SelectSelectedIndex: return Number(select.selectedIndex());
+ case SelectValue: return String(select.value());
+ case SelectLength: return Number(select.length());
+ case SelectForm: return getDOMNode(exec,select.form()); // type HTMLFormElement
+ case SelectOptions: return getSelectHTMLCollection(exec, select.options(), select); // type HTMLCollection
+ case SelectDisabled: return Boolean(select.disabled());
+ case SelectMultiple: return Boolean(select.multiple());
+ case SelectName: return String(select.name());
+ case SelectSize: return Number(select.size());
+ case SelectTabIndex: return Number(select.tabIndex());
+ }
+ }
+ break;
+ case ID_OPTGROUP: {
+ DOM::HTMLOptGroupElement optgroup = element;
+ switch (token) {
+ case OptGroupDisabled: return Boolean(optgroup.disabled());
+ case OptGroupLabel: return String(optgroup.label());
+ }
+ }
+ break;
+ case ID_OPTION: {
+ DOM::HTMLOptionElement option = element;
+ switch (token) {
+ case OptionForm: return getDOMNode(exec,option.form()); // type HTMLFormElement
+ case OptionDefaultSelected: return Boolean(option.defaultSelected());
+ case OptionText: return String(option.text());
+ case OptionIndex: return Number(option.index());
+ case OptionDisabled: return Boolean(option.disabled());
+ case OptionLabel: return String(option.label());
+ case OptionSelected: return Boolean(option.selected());
+ case OptionValue: return String(option.value());
+ }
+ }
+ break;
+ case ID_INPUT: {
+ DOM::HTMLInputElement input = element;
+ switch (token) {
+ case InputDefaultValue: return String(input.defaultValue());
+ case InputDefaultChecked: return Boolean(input.defaultChecked());
+ case InputForm: return getDOMNode(exec,input.form()); // type HTMLFormElement
+ case InputAccept: return String(input.accept());
+ case InputAccessKey: return String(input.accessKey());
+ case InputAlign: return String(input.align());
+ case InputAlt: return String(input.alt());
+ case InputChecked: return Boolean(input.checked());
+ case InputIndeterminate: return Boolean(input.indeterminate());
+ case InputDisabled: return Boolean(input.disabled());
+ case InputMaxLength: return Number(input.maxLength());
+ case InputName: return String(input.name()); // NOT getString (IE gives empty string)
+ case InputReadOnly: return Boolean(input.readOnly());
+ case InputSize: return Number(input.getSize());
+ case InputSrc: return String(input.src());
+ case InputTabIndex: return Number(input.tabIndex());
+ case InputType: return String(input.type());
+ case InputUseMap: return String(input.useMap());
+ case InputValue: return String(input.value());
+ case InputSelectionStart: {
+ long val = input.selectionStart();
+ if (val != -1)
+ return Number(val);
+ else
+ return Undefined();
+ }
+ case InputSelectionEnd: {
+ long val = input.selectionEnd();
+ if (val != -1)
+ return Number(val);
+ else
+ return Undefined();
+ }
+ }
+ }
+ break;
+ case ID_TEXTAREA: {
+ DOM::HTMLTextAreaElement textarea = element;
+ switch (token) {
+ case TextAreaDefaultValue: return String(textarea.defaultValue());
+ case TextAreaForm: return getDOMNode(exec,textarea.form()); // type HTMLFormElement
+ case TextAreaAccessKey: return String(textarea.accessKey());
+ case TextAreaCols: return Number(textarea.cols());
+ case TextAreaDisabled: return Boolean(textarea.disabled());
+ case TextAreaName: return String(textarea.name());
+ case TextAreaReadOnly: return Boolean(textarea.readOnly());
+ case TextAreaRows: return Number(textarea.rows());
+ case TextAreaTabIndex: return Number(textarea.tabIndex());
+ case TextAreaType: return String(textarea.type());
+ case TextAreaValue: return String(textarea.value());
+ case TextAreaSelectionStart: return Number(textarea.selectionStart());
+ case TextAreaSelectionEnd: return Number(textarea.selectionEnd());
+ case TextAreaTextLength: return Number(textarea.textLength());
+ }
+ }
+ break;
+ case ID_BUTTON: {
+ DOM::HTMLButtonElement button = element;
+ switch (token) {
+ case ButtonForm: return getDOMNode(exec,button.form()); // type HTMLFormElement
+ case ButtonAccessKey: return String(button.accessKey());
+ case ButtonDisabled: return Boolean(button.disabled());
+ case ButtonName: return String(button.name());
+ case ButtonTabIndex: return Number(button.tabIndex());
+ case ButtonType: return String(button.type());
+ case ButtonValue: return String(button.value());
+ }
+ }
+ break;
+ case ID_LABEL: {
+ DOM::HTMLLabelElement label = element;
+ switch (token) {
+ case LabelForm: return getDOMNode(exec,label.form()); // type HTMLFormElement
+ case LabelAccessKey: return String(label.accessKey());
+ case LabelHtmlFor: return String(label.htmlFor());
+ }
+ }
+ break;
+ case ID_FIELDSET: {
+ DOM::HTMLFieldSetElement fieldSet = element;
+ switch (token) {
+ case FieldSetForm: return getDOMNode(exec,fieldSet.form()); // type HTMLFormElement
+ }
+ }
+ break;
+ case ID_LEGEND: {
+ DOM::HTMLLegendElement legend = element;
+ switch (token) {
+ case LegendForm: return getDOMNode(exec,legend.form()); // type HTMLFormElement
+ case LegendAccessKey: return String(legend.accessKey());
+ case LegendAlign: return String(legend.align());
+ }
+ }
+ break;
+ case ID_UL: {
+ DOM::HTMLUListElement uList = element;
+ switch (token) {
+ case UListCompact: return Boolean(uList.compact());
+ case UListType: return String(uList.type());
+ }
+ }
+ break;
+ case ID_OL: {
+ DOM::HTMLOListElement oList = element;
+ switch (token) {
+ case OListCompact: return Boolean(oList.compact());
+ case OListStart: return Number(oList.start());
+ case OListType: return String(oList.type());
+ }
+ }
+ break;
+ case ID_DL: {
+ DOM::HTMLDListElement dList = element;
+ switch (token) {
+ case DListCompact: return Boolean(dList.compact());
+ }
+ }
+ break;
+ case ID_DIR: {
+ DOM::HTMLDirectoryElement directory = element;
+ switch (token) {
+ case DirectoryCompact: return Boolean(directory.compact());
+ }
+ }
+ break;
+ case ID_MENU: {
+ DOM::HTMLMenuElement menu = element;
+ switch (token) {
+ case MenuCompact: return Boolean(menu.compact());
+ }
+ }
+ break;
+ case ID_LI: {
+ DOM::HTMLLIElement li = element;
+ switch (token) {
+ case LIType: return String(li.type());
+ case LIValue: return Number(li.value());
+ }
+ }
+ break;
+ case ID_DIV: {
+ DOM::HTMLDivElement div = element;
+ switch (token) {
+ case DivAlign: return String(div.align());
+ }
+ }
+ break;
+ case ID_P: {
+ DOM::HTMLParagraphElement paragraph = element;
+ switch (token) {
+ case ParagraphAlign: return String(paragraph.align());
+ }
+ }
+ break;
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6: {
+ DOM::HTMLHeadingElement heading = element;
+ switch (token) {
+ case HeadingAlign: return String(heading.align());
+ }
+ }
+ break;
+ case ID_BLOCKQUOTE: {
+ DOM::HTMLBlockquoteElement blockquote = element;
+ switch (token) {
+ case BlockQuoteCite: return String(blockquote.cite());
+ }
+ }
+ case ID_Q: {
+ DOM::HTMLQuoteElement quote = element;
+ switch (token) {
+ case QuoteCite: return String(quote.cite());
+ }
+ }
+ case ID_PRE: {
+ DOM::HTMLPreElement pre = element;
+ switch (token) {
+ case PreWidth: return Number(pre.width());
+ }
+ }
+ break;
+ case ID_BR: {
+ DOM::HTMLBRElement br = element;
+ switch (token) {
+ case BRClear: return String(br.clear());
+ }
+ }
+ break;
+ case ID_BASEFONT: {
+ DOM::HTMLBaseFontElement baseFont = element;
+ switch (token) {
+ case BaseFontColor: return String(baseFont.color());
+ case BaseFontFace: return String(baseFont.face());
+ case BaseFontSize: return Number(baseFont.getSize());
+ }
+ }
+ break;
+ case ID_FONT: {
+ DOM::HTMLFontElement font = element;
+ switch (token) {
+ case FontColor: return String(font.color());
+ case FontFace: return String(font.face());
+ case FontSize: return String(font.size());
+ }
+ }
+ break;
+ case ID_HR: {
+ DOM::HTMLHRElement hr = element;
+ switch (token) {
+ case HRAlign: return String(hr.align());
+ case HRNoShade: return Boolean(hr.noShade());
+ case HRSize: return String(hr.size());
+ case HRWidth: return String(hr.width());
+ }
+ }
+ break;
+ case ID_INS:
+ case ID_DEL: {
+ DOM::HTMLModElement mod = element;
+ switch (token) {
+ case ModCite: return String(mod.cite());
+ case ModDateTime: return String(mod.dateTime());
+ }
+ }
+ break;
+ case ID_A: {
+ DOM::HTMLAnchorElement anchor = element;
+ switch (token) {
+ case AnchorAccessKey: return String(anchor.accessKey());
+ case AnchorCharset: return String(anchor.charset());
+ case AnchorCoords: return String(anchor.coords());
+ case AnchorHref: return String(anchor.href());
+ case AnchorHrefLang: return String(anchor.hreflang());
+ case AnchorHash: return String('#'+KURL(anchor.href().string()).ref());
+ case AnchorHost: return String(KURL(anchor.href().string()).host());
+ case AnchorHostname: {
+ KURL url(anchor.href().string());
+ kdDebug(6070) << "anchor::hostname uses:" <<url.url()<<endl;
+ if (url.port()==0)
+ return String(url.host());
+ else
+ return String(url.host() + ":" + TQString::number(url.port()));
+ }
+ case AnchorPathName: return String(KURL(anchor.href().string()).path());
+ case AnchorPort: return String(TQString::number(KURL(anchor.href().string()).port()));
+ case AnchorProtocol: return String(KURL(anchor.href().string()).protocol()+":");
+ case AnchorSearch: { KURL u(anchor.href().string());
+ TQString q = u.query();
+ if (q.length() == 1)
+ return String();
+ return String(q); }
+ case AnchorName: return String(anchor.name());
+ case AnchorRel: return String(anchor.rel());
+ case AnchorRev: return String(anchor.rev());
+ case AnchorShape: return String(anchor.shape());
+ case AnchorTabIndex: return Number(anchor.tabIndex());
+ case AnchorTarget: return String(anchor.target());
+ // Not specified in http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/a.asp
+ // Mozilla returns the inner text.
+ case AnchorText: return String(anchor.innerText());
+ case AnchorType: return String(anchor.type());
+ }
+ }
+ break;
+ case ID_IMG: {
+ DOM::HTMLImageElement image = element;
+ switch (token) {
+ case ImageName: return String(image.name()); // NOT getString (IE gives empty string)
+ case ImageAlign: return String(image.align());
+ case ImageAlt: return String(image.alt());
+ case ImageBorder: return String(image.getBorder());
+ case ImageComplete: return Boolean(static_cast<DOM::HTMLImageElementImpl*>( image.handle() )->complete());
+ case ImageHeight: return Number(image.height());
+ case ImageHspace: return Number(image.hspace());
+ case ImageIsMap: return Boolean(image.isMap());
+ case ImageLongDesc: return String(image.longDesc());
+ case ImageSrc: return String(image.src());
+ case ImageUseMap: return String(image.useMap());
+ case ImageVspace: return Number(image.vspace());
+ case ImageWidth: return Number(image.width());
+ case ImageX: return Number(image.x());
+ case ImageY: return Number(image.y());
+ }
+ }
+ break;
+ case ID_OBJECT: {
+ DOM::HTMLObjectElement object = element;
+ switch (token) {
+ case ObjectForm: return getDOMNode(exec,object.form()); // type HTMLFormElement
+ case ObjectCode: return String(object.code());
+ case ObjectAlign: return String(object.align());
+ case ObjectArchive: return String(object.archive());
+ case ObjectBorder: return String(object.border());
+ case ObjectCodeBase: return String(object.codeBase());
+ case ObjectCodeType: return String(object.codeType());
+ case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ?
+ getDOMNode(exec, object.contentDocument()) : Undefined();
+ case ObjectData: return String(object.data());
+ case ObjectDeclare: return Boolean(object.declare());
+ case ObjectHeight: return String(object.height());
+ case ObjectHspace: return Number(object.getHspace());
+ case ObjectName: return String(object.name());
+ case ObjectStandby: return String(object.standby());
+ case ObjectTabIndex: return Number(object.tabIndex());
+ case ObjectType: return String(object.type());
+ case ObjectUseMap: return String(object.useMap());
+ case ObjectVspace: return Number(object.getVspace());
+ case ObjectWidth: return String(object.width());
+ }
+ }
+ break;
+ case ID_PARAM: {
+ DOM::HTMLParamElement param = element;
+ switch (token) {
+ case ParamName: return String(param.name());
+ case ParamType: return String(param.type());
+ case ParamValue: return String(param.value());
+ case ParamValueType: return String(param.valueType());
+ }
+ }
+ break;
+ case ID_APPLET: {
+ DOM::HTMLAppletElement applet = element;
+ switch (token) {
+ case AppletAlign: return String(applet.align());
+ case AppletAlt: return String(applet.alt());
+ case AppletArchive: return String(applet.archive());
+ case AppletCode: return String(applet.code());
+ case AppletCodeBase: return String(applet.codeBase());
+ case AppletHeight: return String(applet.height());
+ case AppletHspace: return Number(applet.getHspace());
+ case AppletName: return String(applet.name());
+ case AppletObject: return String(applet.object());
+ case AppletVspace: return Number(applet.getVspace());
+ case AppletWidth: return String(applet.width());
+ }
+ }
+ break;
+ case ID_MAP: {
+ DOM::HTMLMapElement map = element;
+ switch (token) {
+ case MapAreas: return getHTMLCollection(exec, map.areas()); // type HTMLCollection
+ case MapName: return String(map.name());
+ }
+ }
+ break;
+ case ID_AREA: {
+ DOM::HTMLAreaElement area = element;
+ switch (token) {
+ case AreaAccessKey: return String(area.accessKey());
+ case AreaAlt: return String(area.alt());
+ case AreaCoords: return String(area.coords());
+ // Group everything that needs href
+ case AreaHref:
+ case AreaHash:
+ case AreaHost:
+ case AreaHostName:
+ case AreaPathName:
+ case AreaPort:
+ case AreaProtocol:
+ case AreaSearch:
+ {
+ DOM::Document doc = area.ownerDocument();
+ DOM::DOMString href = area.href();
+ KURL url;
+ if ( !href.isNull() ) {
+ url = doc.completeURL( href ).string();
+ if ( href.isEmpty() )
+ url.setFileName( TQString::null ); // href="" clears the filename (in IE)
+ }
+ switch(token) {
+ case AreaHref:
+ return String(url.url());
+ case AreaHash: return String(url.isEmpty() ? "" : '#'+url.ref());
+ case AreaHost: return String(url.host());
+ case AreaHostName: {
+ if (url.port()==0)
+ return String(url.host());
+ else
+ return String(url.host() + ":" + TQString::number(url.port()));
+ }
+ case AreaPathName: {
+ return String(url.path());
+ }
+ case AreaPort: return String(TQString::number(url.port()));
+ case AreaProtocol: return String(url.isEmpty() ? "" : url.protocol()+":");
+ case AreaSearch: return String(url.query());
+ }
+ }
+ case AreaNoHref: return Boolean(area.noHref());
+ case AreaShape: return String(area.shape());
+ case AreaTabIndex: return Number(area.tabIndex());
+ case AreaTarget: return String(area.target());
+ }
+ }
+ break;
+ case ID_SCRIPT: {
+ DOM::HTMLScriptElement script = element;
+ switch (token) {
+ case ScriptText: return String(script.text());
+ case ScriptHtmlFor: return String(script.htmlFor());
+ case ScriptEvent: return String(script.event());
+ case ScriptCharset: return String(script.charset());
+ case ScriptDefer: return Boolean(script.defer());
+ case ScriptSrc: return String(script.src());
+ case ScriptType: return String(script.type());
+ }
+ }
+ break;
+ case ID_TABLE: {
+ DOM::HTMLTableElement table = element;
+ switch (token) {
+ case TableCaption: return getDOMNode(exec,table.caption()); // type HTMLTableCaptionElement
+ case TableTHead: return getDOMNode(exec,table.tHead()); // type HTMLTableSectionElement
+ case TableTFoot: return getDOMNode(exec,table.tFoot()); // type HTMLTableSectionElement
+ case TableRows: return getHTMLCollection(exec,table.rows()); // type HTMLCollection
+ case TableTBodies: return getHTMLCollection(exec,table.tBodies()); // type HTMLCollection
+ case TableAlign: return String(table.align());
+ case TableBgColor: return String(table.bgColor());
+ case TableBorder: return String(table.border());
+ case TableCellPadding: return String(table.cellPadding());
+ case TableCellSpacing: return String(table.cellSpacing());
+ case TableFrame: return String(table.frame());
+ case TableRules: return String(table.rules());
+ case TableSummary: return String(table.summary());
+ case TableWidth: return String(table.width());
+ }
+ }
+ break;
+ case ID_CAPTION: {
+ DOM::HTMLTableCaptionElement tableCaption = element;
+ switch (token) {
+ case TableCaptionAlign: return String(tableCaption.align());
+ }
+ }
+ break;
+ case ID_COL:
+ case ID_COLGROUP: {
+ DOM::HTMLTableColElement tableCol = element;
+ switch (token) {
+ case TableColAlign: return String(tableCol.align());
+ case TableColCh: return String(tableCol.ch());
+ case TableColChOff: return String(tableCol.chOff());
+ case TableColSpan: return Number(tableCol.span());
+ case TableColVAlign: return String(tableCol.vAlign());
+ case TableColWidth: return String(tableCol.width());
+ }
+ }
+ break;
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT: {
+ DOM::HTMLTableSectionElement tableSection = element;
+ switch (token) {
+ case TableSectionAlign: return String(tableSection.align());
+ case TableSectionCh: return String(tableSection.ch());
+ case TableSectionChOff: return String(tableSection.chOff());
+ case TableSectionVAlign: return String(tableSection.vAlign());
+ case TableSectionRows: return getHTMLCollection(exec,tableSection.rows()); // type HTMLCollection
+ }
+ }
+ break;
+ case ID_TR: {
+ DOM::HTMLTableRowElement tableRow = element;
+ switch (token) {
+ case TableRowRowIndex: return Number(tableRow.rowIndex());
+ case TableRowSectionRowIndex: return Number(tableRow.sectionRowIndex());
+ case TableRowCells: return getHTMLCollection(exec,tableRow.cells()); // type HTMLCollection
+ case TableRowAlign: return String(tableRow.align());
+ case TableRowBgColor: return String(tableRow.bgColor());
+ case TableRowCh: return String(tableRow.ch());
+ case TableRowChOff: return String(tableRow.chOff());
+ case TableRowVAlign: return String(tableRow.vAlign());
+ }
+ }
+ break;
+ case ID_TH:
+ case ID_TD: {
+ DOM::HTMLTableCellElement tableCell = element;
+ switch (token) {
+ case TableCellCellIndex: return Number(tableCell.cellIndex());
+ case TableCellAbbr: return String(tableCell.abbr());
+ case TableCellAlign: return String(tableCell.align());
+ case TableCellAxis: return String(tableCell.axis());
+ case TableCellBgColor: return String(tableCell.bgColor());
+ case TableCellCh: return String(tableCell.ch());
+ case TableCellChOff: return String(tableCell.chOff());
+ case TableCellColSpan: return Number(tableCell.colSpan());
+ case TableCellHeaders: return String(tableCell.headers());
+ case TableCellHeight: return String(tableCell.height());
+ case TableCellNoWrap: return Boolean(tableCell.noWrap());
+ case TableCellRowSpan: return Number(tableCell.rowSpan());
+ case TableCellScope: return String(tableCell.scope());
+ case TableCellVAlign: return String(tableCell.vAlign());
+ case TableCellWidth: return String(tableCell.width());
+ }
+ }
+ break;
+ case ID_FRAMESET: {
+ DOM::HTMLFrameSetElement frameSet = element;
+ switch (token) {
+ case FrameSetCols: return String(frameSet.cols());
+ case FrameSetRows: return String(frameSet.rows());
+ }
+ }
+ break;
+ case ID_LAYER: {
+ DOM::HTMLLayerElement layerElement = element;
+ switch (token) {
+ case LayerTop: return Number(layerElement.top());
+ case LayerLeft: return Number(layerElement.left());
+ case LayerVisibility: return getString(layerElement.visibility());
+ case LayerBgColor: return getString(layerElement.bgColor());
+ /*case LayerClip: return getLayerClip(exec, layerElement); */
+ case LayerDocument: return Undefined();
+ case LayerLayers: return getHTMLCollection(exec,layerElement.layers());
+ }
+ }
+ break;
+ case ID_FRAME: {
+ DOM::HTMLFrameElement frameElement = element;
+ switch (token) {
+ case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ?
+ getDOMNode(exec, frameElement.contentDocument()) : Undefined();
+ case FrameContentWindow: {
+ KHTMLPart* part = static_cast<DOM::HTMLFrameElementImpl*>(frameElement.handle())->contentPart();
+ if (part) {
+ Window *w = Window::retrieveWindow(part);
+ if (w)
+ return Value(w);
+ }
+ return Undefined();
+ }
+ case FrameFrameBorder: return String(frameElement.frameBorder());
+ case FrameLongDesc: return String(frameElement.longDesc());
+ case FrameMarginHeight: return String(frameElement.marginHeight());
+ case FrameMarginWidth: return String(frameElement.marginWidth());
+ case FrameName: return String(frameElement.name());
+ case FrameNoResize: return Boolean(frameElement.noResize());
+ case FrameScrolling: return String(frameElement.scrolling());
+ case FrameSrc:
+ case FrameLocation: return String(frameElement.src());
+ // IE only
+ case FrameWidth:
+ case FrameHeight:
+ {
+ frameElement.handle()->getDocument()->updateLayout();
+ tdehtml::RenderObject* r = frameElement.handle()->renderer();
+ return Number( r ? (token == FrameWidth ? r->width() : r->height()) : 0 );
+ }
+ }
+ }
+ break;
+ case ID_IFRAME: {
+ DOM::HTMLIFrameElement iFrame = element;
+ switch (token) {
+ case IFrameAlign: return String(iFrame.align());
+ case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ?
+ getDOMNode(exec, iFrame.contentDocument()) : Undefined();
+ case IFrameContentWindow: {
+ KHTMLPart* part = static_cast<DOM::HTMLIFrameElementImpl*>(iFrame.handle())->contentPart();
+ if (part) {
+ Window *w = Window::retrieveWindow(part);
+ if (w)
+ return Value(w);
+ }
+ return Undefined();
+ }
+ case IFrameFrameBorder: return String(iFrame.frameBorder());
+ case IFrameHeight: return String(iFrame.height());
+ case IFrameLongDesc: return String(iFrame.longDesc());
+ case IFrameMarginHeight: return String(iFrame.marginHeight());
+ case IFrameMarginWidth: return String(iFrame.marginWidth());
+ case IFrameName: return String(iFrame.name());
+ case IFrameScrolling: return String(iFrame.scrolling());
+ case IFrameSrc: return String(iFrame.src());
+ case IFrameWidth: return String(iFrame.width());
+ }
+ break;
+ }
+ } // xemacs (or arnt) could be a bit smarter when it comes to indenting switch()es ;)
+ // its not arnt to blame - its the original Stroustrup style we like :) (Dirk)
+
+ // generic properties
+ switch (token) {
+ case ElementId:
+ return String(element.id()); // String is wrong here. Other browsers return empty string if no id specified.
+ case ElementTitle:
+ return String(element.title());
+ case ElementLang:
+ return String(element.lang());
+ case ElementDir:
+ return String(element.dir());
+ case ElementClassName:
+ return String(element.className());
+ case ElementInnerHTML:
+ return String(element.innerHTML());
+ case ElementInnerText:
+ return String(element.innerText());
+ case ElementDocument:
+ return getDOMNode(exec,element.ownerDocument());
+ case ElementChildren:
+ return getHTMLCollection(exec,element.children());
+ case ElementAll:
+ // Disable element.all when we try to be Netscape-compatible
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
+ return Undefined();
+ else
+ if ( exec->interpreter()->compatMode() == Interpreter::IECompat )
+ return getHTMLCollection(exec,element.all());
+ else // Enabled but hidden by default
+ return getHTMLCollection(exec,element.all(), true);
+ // ### what about style? or is this used instead for DOM2 stylesheets?
+ }
+ kdError() << "HTMLElement::getValueProperty unhandled token " << token << endl;
+ return Undefined();
+}
+
+bool KJS::HTMLElement::hasProperty(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ //kdDebug(6070) << "HTMLElement::hasProperty " << propertyName.qstring() << endl;
+#endif
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+ // First look at dynamic properties - keep this in sync with tryGet
+ switch (element.elementId()) {
+ case ID_FORM: {
+ DOM::HTMLFormElement form = element;
+ // Check if we're retrieving an element (by index or by name)
+ bool ok;
+ uint u = propertyName.toULong(&ok);
+ if (ok && !(form.elements().item(u).isNull()))
+ return true;
+ DOM::Node testnode = form.elements().namedItem(propertyName.string());
+ if (!testnode.isNull())
+ return true;
+ }
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ bool ok;
+ uint u = propertyName.toULong(&ok);
+ if (ok && !(select.options().item(u).isNull()))
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return DOMElement::hasProperty(exec, propertyName);
+}
+
+UString KJS::HTMLElement::toString(ExecState *exec) const
+{
+ if (node.elementId() == ID_A)
+ return UString(static_cast<const DOM::HTMLAnchorElement&>(node).href());
+ else if (node.elementId() == ID_APPLET) {
+ KParts::LiveConnectExtension *lc = getLiveConnectExtension(node);
+ TQStringList qargs;
+ TQString retvalue;
+ KParts::LiveConnectExtension::Type rettype;
+ unsigned long retobjid;
+ if (lc && lc->call(0, "hashCode", qargs, rettype, retobjid, retvalue)) {
+ TQString str("[object APPLET ref=");
+ return UString(str + retvalue + TQString("]"));
+ }
+ } else if (node.elementId() == ID_IMG) {
+ DOM::HTMLImageElement image(node);
+ if (!image.alt().isEmpty())
+ return UString(image.alt()) + " " + DOMElement::toString(exec);
+ }
+ return DOMElement::toString(exec);
+}
+
+static void getForm(DOM::HTMLFormElement* form, const DOM::HTMLElement& element)
+{
+ switch (element.elementId()) {
+ case ID_ISINDEX: {
+ DOM::HTMLIsIndexElement isindex = element;
+ *form = isindex.form();
+ break;
+ }
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ *form = select.form();
+ break;
+ }
+ case ID_OPTION: {
+ DOM::HTMLOptionElement option = element;
+ *form = option.form();
+ break;
+ }
+ case ID_INPUT: {
+ DOM::HTMLInputElement input = element;
+ *form = input.form();
+ break;
+ }
+ case ID_TEXTAREA: {
+ DOM::HTMLTextAreaElement textarea = element;
+ *form = textarea.form();
+ break;
+ }
+ case ID_LABEL: {
+ DOM::HTMLLabelElement label = element;
+ *form = label.form();
+ break;
+ }
+ case ID_FIELDSET: {
+ DOM::HTMLFieldSetElement fieldset = element;
+ *form = fieldset.form();
+ break;
+ }
+ case ID_LEGEND: {
+ DOM::HTMLLegendElement legend = element;
+ *form = legend.form();
+ break;
+ }
+ case ID_OBJECT: {
+ DOM::HTMLObjectElement object = element;
+ *form = object.form();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void KJS::HTMLElement::pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const
+{
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+
+ // The document is put on first, fall back to searching it only after the element and form.
+ scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element.ownerDocument()).imp()));
+
+ // The form is next, searched before the document, but after the element itself.
+ DOM::HTMLFormElement formElt;
+
+ // First try to obtain the form from the element itself. We do this to deal with
+ // the malformed case where <form>s aren't in our parent chain (e.g., when they were inside
+ // <table> or <tbody>.
+ getForm(&formElt, element);
+ if (!formElt.isNull())
+ scope.push(static_cast<ObjectImp *>(getDOMNode(exec, formElt).imp()));
+ else {
+ DOM::Node form = element.parentNode();
+ while (!form.isNull() && form.elementId() != ID_FORM)
+ form = form.parentNode();
+
+ if (!form.isNull())
+ scope.push(static_cast<ObjectImp *>(getDOMNode(exec, form).imp()));
+ }
+
+ // The element is on top, searched first.
+ scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element).imp()));
+}
+
+HTMLElementFunction::HTMLElementFunction(ExecState *exec, int i, int len)
+ : DOMFunction(exec), id(i)
+{
+ Value protect(this);
+ put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum);
+}
+
+Value KJS::HTMLElementFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( HTMLElement, thisObj );
+
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLElementFunction::tryCall " << endl;
+#endif
+ DOM::HTMLElement element = static_cast<KJS::HTMLElement *>(thisObj.imp())->toElement();
+
+ switch (element.elementId()) {
+ case ID_FORM: {
+ DOM::HTMLFormElement form = element;
+ if (id == KJS::HTMLElement::FormSubmit) {
+
+
+ DOM::HTMLDocument doc = element.ownerDocument();
+ KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
+ KHTMLSettings::KJSWindowOpenPolicy policy = KHTMLSettings::KJSWindowOpenAllow;
+ if (view)
+ policy = view->part()->settings()->windowOpenPolicy(view->part()->url().host());
+
+ bool block = false;
+
+ if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
+ block = true;
+
+ // if this is a form without a target, or a special target, don't block
+ TQString trg = form.target().lower().string();
+ if( trg.isEmpty() || trg == "_top" || trg == "_self" ||
+ trg == "_parent")
+ block = false;
+
+ TQString caption;
+
+ // if there is a frame with the target name, don't block
+ if ( view && view->part() ) {
+ if (!view->part()->url().host().isEmpty())
+ caption = view->part()->url().host() + " - ";
+ // search all (possibly nested) framesets
+ KHTMLPart *currentPart = view->part()->parentPart();
+ while( currentPart != 0L ) {
+ if( currentPart->frameExists( form.target().string() ) )
+ block = false;
+ currentPart = currentPart->parentPart();
+ }
+ }
+
+ if ( block && policy == KHTMLSettings::KJSWindowOpenAsk && view ) {
+ if (view && view->part())
+ emit view->part()->browserExtension()->requestFocus(view->part());
+ caption += i18n( "Confirmation: JavaScript Popup" );
+ if ( KMessageBox::questionYesNo(view, form.action().isEmpty() ?
+ i18n( "This site is submitting a form which will open up a new browser "
+ "window via JavaScript.\n"
+ "Do you want to allow the form to be submitted?" ) :
+ i18n( "<qt>This site is submitting a form which will open <p>%1</p> in a new browser window via JavaScript.<br />"
+ "Do you want to allow the form to be submitted?</qt>").arg(KStringHandler::csqueeze(form.action().string(), 100)),
+ caption, i18n("Allow"), i18n("Do Not Allow") ) == KMessageBox::Yes )
+ block = false;
+
+ } else if ( block && policy == KHTMLSettings::KJSWindowOpenSmart ) {
+ if( static_cast<KJS::ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed() ) {
+ // This submission has been triggered by the user
+ block = false;
+ }
+ }
+ }
+
+ if( !block )
+ form.submit();
+
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::FormReset) {
+ form.reset();
+ return Undefined();
+ }
+ }
+ break;
+ case ID_BODY: {
+ if (id == KJS::HTMLElement::BodyFocus) {
+ // Just blur everything. Not perfect, but good enough for now
+ if (DOM::NodeImpl* impl = element.handle()) {
+ impl->getDocument()->setFocusNode(0);
+ }
+ }
+ }
+ break;
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ if (id == KJS::HTMLElement::SelectAdd) {
+ select.add(KJS::toNode(args[0]),KJS::toNode(args[1]));
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::SelectRemove) {
+ select.remove(int(args[0].toNumber(exec)));
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::SelectBlur) {
+ select.blur();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::SelectFocus) {
+ select.focus();
+ return Undefined();
+ }
+ }
+ break;
+ case ID_INPUT: {
+ DOM::HTMLInputElement input = element;
+ if (id == KJS::HTMLElement::InputBlur) {
+ input.blur();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::InputFocus) {
+ input.focus();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::InputSelect) {
+ input.select();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::InputClick) {
+ input.click();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::InputSetSelectionRange) {
+ input.setSelectionRange(args[0].toNumber(exec), args[1].toNumber(exec));
+ return Undefined();
+ }
+ }
+ break;
+ case ID_BUTTON: {
+ DOM::HTMLButtonElement button = element;
+ if (id == KJS::HTMLElement::ButtonBlur) {
+ button.blur();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::ButtonFocus) {
+ button.focus();
+ return Undefined();
+ }
+ }
+ break;
+ case ID_TEXTAREA: {
+ DOM::HTMLTextAreaElement textarea = element;
+ if (id == KJS::HTMLElement::TextAreaBlur) {
+ textarea.blur();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TextAreaFocus) {
+ textarea.focus();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TextAreaSelect) {
+ textarea.select();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TextAreaSetSelectionRange) {
+ textarea.setSelectionRange(args[0].toNumber(exec), args[1].toNumber(exec));
+ return Undefined();
+ }
+
+ }
+ break;
+ case ID_A: {
+ DOM::HTMLAnchorElement anchor = element;
+ if (id == KJS::HTMLElement::AnchorBlur) {
+ anchor.blur();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::AnchorFocus) {
+ anchor.focus();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::AnchorClick) {
+ static_cast<DOM::HTMLAnchorElementImpl*>(anchor.handle())->click();
+ return Undefined();
+ }
+ }
+ break;
+ case ID_TABLE: {
+ DOM::HTMLTableElement table = element;
+ if (id == KJS::HTMLElement::TableCreateTHead)
+ return getDOMNode(exec,table.createTHead());
+ else if (id == KJS::HTMLElement::TableDeleteTHead) {
+ table.deleteTHead();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TableCreateTFoot)
+ return getDOMNode(exec,table.createTFoot());
+ else if (id == KJS::HTMLElement::TableDeleteTFoot) {
+ table.deleteTFoot();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TableCreateCaption)
+ return getDOMNode(exec,table.createCaption());
+ else if (id == KJS::HTMLElement::TableDeleteCaption) {
+ table.deleteCaption();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::TableInsertRow)
+ return getDOMNode(exec,table.insertRow(args[0].toInteger(exec)));
+ else if (id == KJS::HTMLElement::TableDeleteRow) {
+ table.deleteRow(args[0].toInteger(exec));
+ return Undefined();
+ }
+ }
+ break;
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT: {
+ DOM::HTMLTableSectionElement tableSection = element;
+ if (id == KJS::HTMLElement::TableSectionInsertRow)
+ return getDOMNode(exec,tableSection.insertRow(args[0].toInteger(exec)));
+ else if (id == KJS::HTMLElement::TableSectionDeleteRow) {
+ tableSection.deleteRow(args[0].toInteger(exec));
+ return Undefined();
+ }
+ }
+ break;
+ case ID_TR: {
+ DOM::HTMLTableRowElement tableRow = element;
+ if (id == KJS::HTMLElement::TableRowInsertCell)
+ return getDOMNode(exec,tableRow.insertCell(args[0].toInteger(exec)));
+ else if (id == KJS::HTMLElement::TableRowDeleteCell) {
+ tableRow.deleteCell(args[0].toInteger(exec));
+ return Undefined();
+ }
+ break;
+ }
+ case ID_MARQUEE: {
+ if (id == KJS::HTMLElement::MarqueeStart && element.handle()->renderer() &&
+ element.handle()->renderer()->layer() &&
+ element.handle()->renderer()->layer()->marquee()) {
+ element.handle()->renderer()->layer()->marquee()->start();
+ return Undefined();
+ }
+ else if (id == KJS::HTMLElement::MarqueeStop && element.handle()->renderer() &&
+ element.handle()->renderer()->layer() &&
+ element.handle()->renderer()->layer()->marquee()) {
+ element.handle()->renderer()->layer()->marquee()->stop();
+ return Undefined();
+ }
+ break;
+ }
+ }
+
+ if (id == HTMLElement::ElementScrollIntoView) {
+ bool alignToTop = true;
+ if (args.size() > 0)
+ alignToTop = args[0].toBoolean(exec);
+ static_cast<HTMLElementImpl*>(element.handle())->scrollIntoView(alignToTop);
+ return Undefined();
+ }
+
+ return Undefined();
+}
+
+void KJS::HTMLElement::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+#ifdef KJS_VERBOSE
+ DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
+#endif
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLElement::tryPut " << propertyName.qstring()
+ << " thisTag=" << element.tagName().string()
+ << " str=" << str.string() << endl;
+#endif
+ // First look at dynamic properties
+ switch (element.elementId()) {
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ bool ok;
+ /*uint u =*/ propertyName.toULong(&ok);
+ if (ok) {
+ Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
+ if ( coll.isValid() )
+ coll.put(exec,propertyName,value);
+ return;
+ }
+ break;
+ }
+ case ID_APPLET:
+ case ID_OBJECT:
+ case ID_EMBED: {
+ KParts::LiveConnectExtension *lc = getLiveConnectExtension(element);
+ if (lc && lc->put(0, propertyName.qstring(), value.toString(exec).qstring()))
+ return;
+ break;
+ }
+ default:
+ break;
+ }
+
+ const HashTable* table = classInfo()->propHashTable; // get the right hashtable
+ const HashEntry* entry = table ? Lookup::findEntry(table, propertyName) : 0;
+ if (entry) {
+ if (entry->attr & Function) // function: put as override property
+ {
+ ObjectImp::put(exec, propertyName, value, attr);
+ return;
+ }
+ else if ((entry->attr & ReadOnly) == 0) // let DOMObjectLookupPut print the warning if not
+ {
+ putValueProperty(exec, entry->value, value, attr);
+ return;
+ }
+ }
+ DOMObjectLookupPut<KJS::HTMLElement, DOMElement>(exec, propertyName, value, attr, &KJS::HTMLElementTable, this);
+}
+
+void KJS::HTMLElement::putValueProperty(ExecState *exec, int token, const Value& value, int)
+{
+ DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
+ DOMNode *kjsNode = new DOMNode(exec, KJS::toNode(value));
+ // Need to create a Value wrapper to avoid leaking the KJS::DOMNode
+ Value nodeValue(kjsNode);
+ DOM::Node n = kjsNode->toNode();
+ DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLElement::putValueProperty "
+ << " thisTag=" << element.tagName().string()
+ << " token=" << token << endl;
+#endif
+
+ switch (element.elementId()) {
+ case ID_HTML: {
+ DOM::HTMLHtmlElement html = element;
+ switch (token) {
+ case HtmlVersion: { html.setVersion(str); return; }
+ }
+ }
+ break;
+ case ID_HEAD: {
+ DOM::HTMLHeadElement head = element;
+ switch (token) {
+ case HeadProfile: { head.setProfile(str); return; }
+ }
+ }
+ break;
+ case ID_LINK: {
+ DOM::HTMLLinkElement link = element;
+ switch (token) {
+ case LinkDisabled: { link.setDisabled(value.toBoolean(exec)); return; }
+ case LinkCharset: { link.setCharset(str); return; }
+ case LinkHref: { link.setHref(str); return; }
+ case LinkHrefLang: { link.setHreflang(str); return; }
+ case LinkMedia: { link.setMedia(str); return; }
+ case LinkRel: { link.setRel(str); return; }
+ case LinkRev: { link.setRev(str); return; }
+ case LinkTarget: { link.setTarget(str); return; }
+ case LinkType: { link.setType(str); return; }
+ }
+ }
+ break;
+ case ID_TITLE: {
+ DOM::HTMLTitleElement title = element;
+ switch (token) {
+ case TitleText: { title.setText(str); return; }
+ }
+ }
+ break;
+ case ID_META: {
+ DOM::HTMLMetaElement meta = element;
+ switch (token) {
+ case MetaContent: { meta.setContent(str); return; }
+ case MetaHttpEquiv: { meta.setHttpEquiv(str); return; }
+ case MetaName: { meta.setName(str); return; }
+ case MetaScheme: { meta.setScheme(str); return; }
+ }
+ }
+ break;
+ case ID_BASE: {
+ DOM::HTMLBaseElement base = element;
+ switch (token) {
+ case BaseHref: { base.setHref(str); return; }
+ case BaseTarget: { base.setTarget(str); return; }
+ }
+ }
+ break;
+ case ID_ISINDEX: {
+ DOM::HTMLIsIndexElement isindex = element;
+ switch (token) {
+ // read-only: form
+ case IsIndexPrompt: { isindex.setPrompt(str); return; }
+ }
+ }
+ break;
+ case ID_STYLE: {
+ DOM::HTMLStyleElement style = element;
+ switch (token) {
+ case StyleDisabled: { style.setDisabled(value.toBoolean(exec)); return; }
+ case StyleMedia: { style.setMedia(str); return; }
+ case StyleType: { style.setType(str); return; }
+ }
+ }
+ break;
+ case ID_BODY: {
+ DOM::HTMLBodyElement body = element;
+ switch (token) {
+ case BodyALink: { body.setALink(str); return; }
+ case BodyBackground: { body.setBackground(str); return; }
+ case BodyBgColor: { body.setBgColor(str); return; }
+ case BodyLink: { body.setLink(str); return; }
+ case BodyText: { body.setText(str); return; }
+ case BodyVLink: { body.setVLink(str); return; }
+ case BodyOnLoad:
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(node.ownerDocument().handle());
+ if (doc && checkNodeSecurity(exec, node))
+ {
+ DOMNode* kjsDocNode = new DOMNode(exec, doc);
+ // Need to create a Value wrapper to avoid leaking the KJS::DOMNode
+ Value nodeValue(kjsDocNode);
+ kjsDocNode->setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
+ }
+ return;
+ }
+ }
+ break;
+ case ID_FORM: {
+ DOM::HTMLFormElement form = element;
+ switch (token) {
+ // read-only: elements
+ // read-only: length
+ case FormName: { form.setName(str); return; }
+ case FormAcceptCharset: { form.setAcceptCharset(str); return; }
+ case FormAction: { form.setAction(str.string()); return; }
+ case FormEncType: { form.setEnctype(str); return; }
+ case FormMethod: { form.setMethod(str); return; }
+ case FormTarget: { form.setTarget(str); return; }
+ }
+ }
+ break;
+ case ID_SELECT: {
+ DOM::HTMLSelectElement select = element;
+ switch (token) {
+ // read-only: type
+ case SelectSelectedIndex: { select.setSelectedIndex(value.toInteger(exec)); return; }
+ case SelectValue: { select.setValue(str); return; }
+ case SelectLength: { // read-only according to the NS spec, but webpages need it writeable
+ Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
+ if ( coll.isValid() )
+ coll.put(exec,"length",value);
+ return;
+ }
+ // read-only: form
+ // read-only: options
+ case SelectDisabled: { select.setDisabled(value.toBoolean(exec)); return; }
+ case SelectMultiple: { select.setMultiple(value.toBoolean(exec)); return; }
+ case SelectName: { select.setName(str); return; }
+ case SelectSize: { select.setSize(value.toInteger(exec)); return; }
+ case SelectTabIndex: { select.setTabIndex(value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_OPTGROUP: {
+ DOM::HTMLOptGroupElement optgroup = element;
+ switch (token) {
+ case OptGroupDisabled: { optgroup.setDisabled(value.toBoolean(exec)); return; }
+ case OptGroupLabel: { optgroup.setLabel(str); return; }
+ }
+ }
+ break;
+ case ID_OPTION: {
+ DOM::HTMLOptionElement option = element;
+ switch (token) {
+ // read-only: form
+ case OptionDefaultSelected: { option.setDefaultSelected(value.toBoolean(exec)); return; }
+ // read-only: text <--- According to the DOM, but JavaScript and JScript both allow changes.
+ // So, we'll do it here and not add it to our DOM headers.
+ case OptionText: { DOM::NodeList nl(option.childNodes());
+ for (unsigned int i = 0; i < nl.length(); i++) {
+ if (nl.item(i).nodeType() == DOM::Node::TEXT_NODE) {
+ static_cast<DOM::Text>(nl.item(i)).setData(str);
+ return;
+ }
+ }
+ // No child text node found, creating one
+ DOM::Text t = option.ownerDocument().createTextNode(str);
+ try { option.appendChild(t); }
+ catch(DOM::DOMException& e) {
+ // #### exec->setException ?
+ }
+
+ return;
+ }
+ // read-only: index
+ case OptionDisabled: { option.setDisabled(value.toBoolean(exec)); return; }
+ case OptionLabel: { option.setLabel(str); return; }
+ case OptionSelected: { option.setSelected(value.toBoolean(exec)); return; }
+ case OptionValue: { option.setValue(str); return; }
+ }
+ }
+ break;
+ case ID_INPUT: {
+ DOM::HTMLInputElement input = element;
+ switch (token) {
+ case InputDefaultValue: { input.setDefaultValue(str); return; }
+ case InputDefaultChecked: { input.setDefaultChecked(value.toBoolean(exec)); return; }
+ // read-only: form
+ case InputAccept: { input.setAccept(str); return; }
+ case InputAccessKey: { input.setAccessKey(str); return; }
+ case InputAlign: { input.setAlign(str); return; }
+ case InputAlt: { input.setAlt(str); return; }
+ case InputChecked: { input.setChecked(value.toBoolean(exec)); return; }
+ case InputIndeterminate: { input.setIndeterminate(value.toBoolean(exec)); return; }
+ case InputDisabled: { input.setDisabled(value.toBoolean(exec)); return; }
+ case InputMaxLength: { input.setMaxLength(value.toInteger(exec)); return; }
+ case InputName: { input.setName(str); return; }
+ case InputReadOnly: { input.setReadOnly(value.toBoolean(exec)); return; }
+ case InputSize: { input.setSize(value.toInteger(exec)); return; }
+ case InputSrc: { input.setSrc(str); return; }
+ case InputTabIndex: { input.setTabIndex(value.toInteger(exec)); return; }
+ case InputType: { input.setType(str); return; }
+ case InputUseMap: { input.setUseMap(str); return; }
+ case InputValue: { input.setValue(str); return; }
+ case InputSelectionStart: { input.setSelectionStart(value.toInteger(exec)); return; }
+ case InputSelectionEnd: { input.setSelectionEnd (value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_TEXTAREA: {
+ DOM::HTMLTextAreaElement textarea = element;
+ switch (token) {
+ case TextAreaDefaultValue: { textarea.setDefaultValue(str); return; }
+ // read-only: form
+ case TextAreaAccessKey: { textarea.setAccessKey(str); return; }
+ case TextAreaCols: { textarea.setCols(value.toInteger(exec)); return; }
+ case TextAreaDisabled: { textarea.setDisabled(value.toBoolean(exec)); return; }
+ case TextAreaName: { textarea.setName(str); return; }
+ case TextAreaReadOnly: { textarea.setReadOnly(value.toBoolean(exec)); return; }
+ case TextAreaRows: { textarea.setRows(value.toInteger(exec)); return; }
+ case TextAreaTabIndex: { textarea.setTabIndex(value.toInteger(exec)); return; }
+ // read-only: type
+ case TextAreaValue: { textarea.setValue(str); return; }
+ case TextAreaSelectionStart: { textarea.setSelectionStart(value.toInteger(exec)); return; }
+ case TextAreaSelectionEnd: { textarea.setSelectionEnd (value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_BUTTON: {
+ DOM::HTMLButtonElement button = element;
+ switch (token) {
+ // read-only: form
+ case ButtonAccessKey: { button.setAccessKey(str); return; }
+ case ButtonDisabled: { button.setDisabled(value.toBoolean(exec)); return; }
+ case ButtonName: { button.setName(str); return; }
+ case ButtonTabIndex: { button.setTabIndex(value.toInteger(exec)); return; }
+ // read-only: type
+ case ButtonValue: { button.setValue(str); return; }
+ }
+ }
+ break;
+ case ID_LABEL: {
+ DOM::HTMLLabelElement label = element;
+ switch (token) {
+ // read-only: form
+ case LabelAccessKey: { label.setAccessKey(str); return; }
+ case LabelHtmlFor: { label.setHtmlFor(str); return; }
+ }
+ }
+ break;
+// case ID_FIELDSET: {
+// DOM::HTMLFieldSetElement fieldSet = element;
+// // read-only: form
+// }
+// break;
+ case ID_LEGEND: {
+ DOM::HTMLLegendElement legend = element;
+ switch (token) {
+ // read-only: form
+ case LegendAccessKey: { legend.setAccessKey(str); return; }
+ case LegendAlign: { legend.setAlign(str); return; }
+ }
+ }
+ break;
+ case ID_UL: {
+ DOM::HTMLUListElement uList = element;
+ switch (token) {
+ case UListCompact: { uList.setCompact(value.toBoolean(exec)); return; }
+ case UListType: { uList.setType(str); return; }
+ }
+ }
+ break;
+ case ID_OL: {
+ DOM::HTMLOListElement oList = element;
+ switch (token) {
+ case OListCompact: { oList.setCompact(value.toBoolean(exec)); return; }
+ case OListStart: { oList.setStart(value.toInteger(exec)); return; }
+ case OListType: { oList.setType(str); return; }
+ }
+ }
+ break;
+ case ID_DL: {
+ DOM::HTMLDListElement dList = element;
+ switch (token) {
+ case DListCompact: { dList.setCompact(value.toBoolean(exec)); return; }
+ }
+ }
+ break;
+ case ID_DIR: {
+ DOM::HTMLDirectoryElement directory = element;
+ switch (token) {
+ case DirectoryCompact: { directory.setCompact(value.toBoolean(exec)); return; }
+ }
+ }
+ break;
+ case ID_MENU: {
+ DOM::HTMLMenuElement menu = element;
+ switch (token) {
+ case MenuCompact: { menu.setCompact(value.toBoolean(exec)); return; }
+ }
+ }
+ break;
+ case ID_LI: {
+ DOM::HTMLLIElement li = element;
+ switch (token) {
+ case LIType: { li.setType(str); return; }
+ case LIValue: { li.setValue(value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_DIV: {
+ DOM::HTMLDivElement div = element;
+ switch (token) {
+ case DivAlign: { div.setAlign(str); return; }
+ }
+ }
+ break;
+ case ID_P: {
+ DOM::HTMLParagraphElement paragraph = element;
+ switch (token) {
+ case ParagraphAlign: { paragraph.setAlign(str); return; }
+ }
+ }
+ break;
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6: {
+ DOM::HTMLHeadingElement heading = element;
+ switch (token) {
+ case HeadingAlign: { heading.setAlign(str); return; }
+ }
+ }
+ break;
+ case ID_BLOCKQUOTE: {
+ DOM::HTMLBlockquoteElement blockquote = element;
+ switch (token) {
+ case BlockQuoteCite: { blockquote.setCite(str); return; }
+ }
+ }
+ break;
+ case ID_Q: {
+ DOM::HTMLQuoteElement quote = element;
+ switch (token) {
+ case QuoteCite: { quote.setCite(str); return; }
+ }
+ }
+ break;
+ case ID_PRE: {
+ DOM::HTMLPreElement pre = element;
+ switch (token) {
+ case PreWidth: { pre.setWidth(value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_BR: {
+ DOM::HTMLBRElement br = element;
+ switch (token) {
+ case BRClear: { br.setClear(str); return; }
+ }
+ }
+ break;
+ case ID_BASEFONT: {
+ DOM::HTMLBaseFontElement baseFont = element;
+ switch (token) {
+ case BaseFontColor: { baseFont.setColor(str); return; }
+ case BaseFontFace: { baseFont.setFace(str); return; }
+ case BaseFontSize: { baseFont.setSize(value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_FONT: {
+ DOM::HTMLFontElement font = element;
+ switch (token) {
+ case FontColor: { font.setColor(str); return; }
+ case FontFace: { font.setFace(str); return; }
+ case FontSize: { font.setSize(str); return; }
+ }
+ }
+ break;
+ case ID_HR: {
+ DOM::HTMLHRElement hr = element;
+ switch (token) {
+ case HRAlign: { hr.setAlign(str); return; }
+ case HRNoShade: { hr.setNoShade(value.toBoolean(exec)); return; }
+ case HRSize: { hr.setSize(str); return; }
+ case HRWidth: { hr.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_INS:
+ case ID_DEL: {
+ DOM::HTMLModElement mod = element;
+ switch (token) {
+ case ModCite: { mod.setCite(str); return; }
+ case ModDateTime: { mod.setDateTime(str); return; }
+ }
+ }
+ break;
+ case ID_A: {
+ DOM::HTMLAnchorElement anchor = element;
+ switch (token) {
+ case AnchorAccessKey: { anchor.setAccessKey(str); return; }
+ case AnchorCharset: { anchor.setCharset(str); return; }
+ case AnchorCoords: { anchor.setCoords(str); return; }
+ case AnchorHref: { anchor.setHref(str); return; }
+ case AnchorHrefLang: { anchor.setHreflang(str); return; }
+ case AnchorSearch: { KURL href(anchor.href().string());
+ TQString q = str.isEmpty() ? TQString() : str.string();
+ href.setQuery(q);
+ anchor.setHref(href.url()); return; }
+ case AnchorName: { anchor.setName(str); return; }
+ case AnchorRel: { anchor.setRel(str); return; }
+ case AnchorRev: { anchor.setRev(str); return; }
+ case AnchorShape: { anchor.setShape(str); return; }
+ case AnchorTabIndex: { anchor.setTabIndex(value.toInteger(exec)); return; }
+ case AnchorTarget: { anchor.setTarget(str); return; }
+ case AnchorType: { anchor.setType(str); return; }
+ }
+ }
+ break;
+ case ID_IMG: {
+ DOM::HTMLImageElement image = element;
+ switch (token) {
+ case ImageName: { image.setName(str); return; }
+ case ImageAlign: { image.setAlign(str); return; }
+ case ImageAlt: { image.setAlt(str); return; }
+ case ImageBorder: { image.setBorder(str); return; }
+ case ImageHeight: { image.setHeight(value.toInteger(exec)); return; }
+ case ImageHspace: { image.setHspace(value.toInteger(exec)); return; }
+ case ImageIsMap: { image.setIsMap(value.toBoolean(exec)); return; }
+ case ImageLongDesc: { image.setLongDesc(str); return; }
+ case ImageSrc: { image.setSrc(str); return; }
+ case ImageUseMap: { image.setUseMap(str); return; }
+ case ImageVspace: { image.setVspace(value.toInteger(exec)); return; }
+ case ImageWidth: { image.setWidth(value.toInteger(exec)); return; }
+ }
+ }
+ break;
+ case ID_OBJECT: {
+ DOM::HTMLObjectElement object = element;
+ switch (token) {
+ // read-only: form
+ case ObjectCode: { object.setCode(str); return; }
+ case ObjectAlign: { object.setAlign(str); return; }
+ case ObjectArchive: { object.setArchive(str); return; }
+ case ObjectBorder: { object.setBorder(str); return; }
+ case ObjectCodeBase: { object.setCodeBase(str); return; }
+ case ObjectCodeType: { object.setCodeType(str); return; }
+ // read-only: ObjectContentDocument
+ case ObjectData: { object.setData(str); return; }
+ case ObjectDeclare: { object.setDeclare(value.toBoolean(exec)); return; }
+ case ObjectHeight: { object.setHeight(str); return; }
+ case ObjectHspace: { object.setHspace(value.toInteger(exec)); return; }
+ case ObjectName: { object.setName(str); return; }
+ case ObjectStandby: { object.setStandby(str); return; }
+ case ObjectTabIndex: { object.setTabIndex(value.toInteger(exec)); return; }
+ case ObjectType: { object.setType(str); return; }
+ case ObjectUseMap: { object.setUseMap(str); return; }
+ case ObjectVspace: { object.setVspace(value.toInteger(exec)); return; }
+ case ObjectWidth: { object.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_PARAM: {
+ DOM::HTMLParamElement param = element;
+ switch (token) {
+ case ParamName: { param.setName(str); return; }
+ case ParamType: { param.setType(str); return; }
+ case ParamValue: { param.setValue(str); return; }
+ case ParamValueType: { param.setValueType(str); return; }
+ }
+ }
+ break;
+ case ID_APPLET: {
+ DOM::HTMLAppletElement applet = element;
+ switch (token) {
+ case AppletAlign: { applet.setAlign(str); return; }
+ case AppletAlt: { applet.setAlt(str); return; }
+ case AppletArchive: { applet.setArchive(str); return; }
+ case AppletCode: { applet.setCode(str); return; }
+ case AppletCodeBase: { applet.setCodeBase(str); return; }
+ case AppletHeight: { applet.setHeight(str); return; }
+ case AppletHspace: { applet.setHspace(value.toInteger(exec)); return; }
+ case AppletName: { applet.setName(str); return; }
+ case AppletObject: { applet.setObject(str); return; }
+ case AppletVspace: { applet.setVspace(value.toInteger(exec)); return; }
+ case AppletWidth: { applet.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_MAP: {
+ DOM::HTMLMapElement map = element;
+ switch (token) {
+ // read-only: areas
+ case MapName: { map.setName(str); return; }
+ }
+ }
+ break;
+ case ID_AREA: {
+ DOM::HTMLAreaElement area = element;
+ switch (token) {
+ case AreaAccessKey: { area.setAccessKey(str); return; }
+ case AreaAlt: { area.setAlt(str); return; }
+ case AreaCoords: { area.setCoords(str); return; }
+ case AreaHref: { area.setHref(str); return; }
+ case AreaNoHref: { area.setNoHref(value.toBoolean(exec)); return; }
+ case AreaShape: { area.setShape(str); return; }
+ case AreaTabIndex: { area.setTabIndex(value.toInteger(exec)); return; }
+ case AreaTarget: { area.setTarget(str); return; }
+ }
+ }
+ break;
+ case ID_SCRIPT: {
+ DOM::HTMLScriptElement script = element;
+ switch (token) {
+ case ScriptText: { script.setText(str); return; }
+ case ScriptHtmlFor: { script.setHtmlFor(str); return; }
+ case ScriptEvent: { script.setEvent(str); return; }
+ case ScriptCharset: { script.setCharset(str); return; }
+ case ScriptDefer: { script.setDefer(value.toBoolean(exec)); return; }
+ case ScriptSrc: { script.setSrc(str); return; }
+ case ScriptType: { script.setType(str); return; }
+ }
+ }
+ break;
+ case ID_TABLE: {
+ DOM::HTMLTableElement table = element;
+ switch (token) {
+ case TableCaption: { table.setCaption(n); return; } // type HTMLTableCaptionElement
+ case TableTHead: { table.setTHead(n); return; } // type HTMLTableSectionElement
+ case TableTFoot: { table.setTFoot(n); return; } // type HTMLTableSectionElement
+ // read-only: rows
+ // read-only: tbodies
+ case TableAlign: { table.setAlign(str); return; }
+ case TableBgColor: { table.setBgColor(str); return; }
+ case TableBorder: { table.setBorder(str); return; }
+ case TableCellPadding: { table.setCellPadding(str); return; }
+ case TableCellSpacing: { table.setCellSpacing(str); return; }
+ case TableFrame: { table.setFrame(str); return; }
+ case TableRules: { table.setRules(str); return; }
+ case TableSummary: { table.setSummary(str); return; }
+ case TableWidth: { table.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_CAPTION: {
+ DOM::HTMLTableCaptionElement tableCaption = element;
+ switch (token) {
+ case TableCaptionAlign: { tableCaption.setAlign(str); return; }
+ }
+ }
+ break;
+ case ID_COL:
+ case ID_COLGROUP: {
+ DOM::HTMLTableColElement tableCol = element;
+ switch (token) {
+ case TableColAlign: { tableCol.setAlign(str); return; }
+ case TableColCh: { tableCol.setCh(str); return; }
+ case TableColChOff: { tableCol.setChOff(str); return; }
+ case TableColSpan: { tableCol.setSpan(value.toInteger(exec)); return; }
+ case TableColVAlign: { tableCol.setVAlign(str); return; }
+ case TableColWidth: { tableCol.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT: {
+ DOM::HTMLTableSectionElement tableSection = element;
+ switch (token) {
+ case TableSectionAlign: { tableSection.setAlign(str); return; }
+ case TableSectionCh: { tableSection.setCh(str); return; }
+ case TableSectionChOff: { tableSection.setChOff(str); return; }
+ case TableSectionVAlign: { tableSection.setVAlign(str); return; }
+ // read-only: rows
+ }
+ }
+ break;
+ case ID_TR: {
+ DOM::HTMLTableRowElement tableRow = element;
+ switch (token) {
+ // read-only: rowIndex
+ // read-only: sectionRowIndex
+ // read-only: cells
+ case TableRowAlign: { tableRow.setAlign(str); return; }
+ case TableRowBgColor: { tableRow.setBgColor(str); return; }
+ case TableRowCh: { tableRow.setCh(str); return; }
+ case TableRowChOff: { tableRow.setChOff(str); return; }
+ case TableRowVAlign: { tableRow.setVAlign(str); return; }
+ }
+ }
+ break;
+ case ID_TH:
+ case ID_TD: {
+ DOM::HTMLTableCellElement tableCell = element;
+ switch (token) {
+ // read-only: cellIndex
+ case TableCellAbbr: { tableCell.setAbbr(str); return; }
+ case TableCellAlign: { tableCell.setAlign(str); return; }
+ case TableCellAxis: { tableCell.setAxis(str); return; }
+ case TableCellBgColor: { tableCell.setBgColor(str); return; }
+ case TableCellCh: { tableCell.setCh(str); return; }
+ case TableCellChOff: { tableCell.setChOff(str); return; }
+ case TableCellColSpan: { tableCell.setColSpan(value.toInteger(exec)); return; }
+ case TableCellHeaders: { tableCell.setHeaders(str); return; }
+ case TableCellHeight: { tableCell.setHeight(str); return; }
+ case TableCellNoWrap: { tableCell.setNoWrap(value.toBoolean(exec)); return; }
+ case TableCellRowSpan: { tableCell.setRowSpan(value.toInteger(exec)); return; }
+ case TableCellScope: { tableCell.setScope(str); return; }
+ case TableCellVAlign: { tableCell.setVAlign(str); return; }
+ case TableCellWidth: { tableCell.setWidth(str); return; }
+ }
+ }
+ break;
+ case ID_FRAMESET: {
+ DOM::HTMLFrameSetElement frameSet = element;
+ switch (token) {
+ case FrameSetCols: { frameSet.setCols(str); return; }
+ case FrameSetRows: { frameSet.setRows(str); return; }
+ }
+ }
+ break;
+ case ID_LAYER: {
+ DOM::HTMLLayerElement layerElement = element;
+ switch (token) {
+ case LayerTop: { layerElement.setTop(value.toInteger(exec)); return; }
+ case LayerLeft: { layerElement.setLeft(value.toInteger(exec)); return; }
+ case LayerVisibility: { layerElement.setVisibility(str); return; }
+ case LayerBgColor: { layerElement.setBgColor(str); return; }
+ // read-only: layers, clip
+ }
+ }
+ break;
+ case ID_FRAME: {
+ DOM::HTMLFrameElement frameElement = element;
+ switch (token) {
+ // read-only: FrameContentDocument:
+ case FrameFrameBorder: { frameElement.setFrameBorder(str); return; }
+ case FrameLongDesc: { frameElement.setLongDesc(str); return; }
+ case FrameMarginHeight: { frameElement.setMarginHeight(str); return; }
+ case FrameMarginWidth: { frameElement.setMarginWidth(str); return; }
+ case FrameName: { frameElement.setName(str); return; }
+ case FrameNoResize: { frameElement.setNoResize(value.toBoolean(exec)); return; }
+ case FrameScrolling: { frameElement.setScrolling(str); return; }
+ case FrameSrc: { frameElement.setSrc(str); return; }
+ case FrameLocation: {
+ static_cast<DOM::HTMLFrameElementImpl *>(frameElement.handle())->setLocation(str);
+ return;
+ }
+ }
+ }
+ break;
+ case ID_IFRAME: {
+ DOM::HTMLIFrameElement iFrame = element;
+ switch (token) {
+ case IFrameAlign: { iFrame.setAlign(str); return; }
+ // read-only: IFrameContentDocument
+ case IFrameFrameBorder: { iFrame.setFrameBorder(str); return; }
+ case IFrameHeight: { iFrame.setHeight(str); return; }
+ case IFrameLongDesc: { iFrame.setLongDesc(str); return; }
+ case IFrameMarginHeight: { iFrame.setMarginHeight(str); return; }
+ case IFrameMarginWidth: { iFrame.setMarginWidth(str); return; }
+ case IFrameName: { iFrame.setName(str); return; }
+ case IFrameScrolling: { iFrame.setScrolling(str); return; }
+ case IFrameSrc: { iFrame.setSrc(str); return; }
+ case IFrameWidth: { iFrame.setWidth(str); return; }
+ }
+ break;
+ }
+ }
+
+ // generic properties
+ switch (token) {
+ case ElementId:
+ element.setId(str);
+ return;
+ case ElementTitle:
+ element.setTitle(str);
+ return;
+ case ElementLang:
+ element.setLang(str);
+ return;
+ case ElementDir:
+ element.setDir(str);
+ return;
+ case ElementClassName:
+ element.setClassName(str);
+ return;
+ case ElementInnerHTML:
+ element.setInnerHTML(str);
+ return;
+ case ElementInnerText:
+ element.setInnerText(str);
+ return;
+ default:
+ kdDebug(6070) << "WARNING: KJS::HTMLElement::putValueProperty unhandled token " << token << " thisTag=" << element.tagName().string() << " str=" << str.string() << endl;
+ }
+}
+
+//Prototype mess for this...
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLElementProto, DOMElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLElement", HTMLElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLElementPseudoCtor, "HTMLElement", HTMLElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHtmlElement", HTMLHtmlElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHtmlElementPseudoCtor, "HTMLHtmlElement", HTMLHtmlElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHeadElement", HTMLHeadElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHeadElementPseudoCtor, "HTMLHeadElement", HTMLHeadElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLinkElement", HTMLLinkElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLinkElementPseudoCtor, "HTMLLinkElement", HTMLLinkElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTitleElement", HTMLTitleElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTitleElementPseudoCtor, "HTMLTitleElement", HTMLTitleElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMetaElement", HTMLMetaElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMetaElementPseudoCtor, "HTMLMetaElement", HTMLMetaElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBaseElement", HTMLBaseElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBaseElementPseudoCtor, "HTMLBaseElement", HTMLBaseElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLIsIndexElement", HTMLIsIndexElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLIsIndexElementPseudoCtor, "HTMLIsIndexElement", HTMLIsIndexElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLStyleElement", HTMLStyleElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLStyleElementPseudoCtor, "HTMLStyleElement", HTMLStyleElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLBodyElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLBodyElement", HTMLBodyElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBodyElementPseudoCtor, "HTMLBodyElement", HTMLBodyElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLFormElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLFormElement", HTMLFormElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFormElementPseudoCtor, "HTMLFormElement", HTMLFormElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLSelectElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLSelectElement", HTMLSelectElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLSelectElementPseudoCtor, "HTMLSelectElement", HTMLSelectElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOptGroupElement", HTMLOptGroupElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOptGroupElementPseudoCtor, "HTMLOptGroupElement", HTMLOptGroupElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOptionElement", HTMLOptionElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOptionElementPseudoCtor, "HTMLOptionElement", HTMLOptionElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLInputElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLInputElement", HTMLInputElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLInputElementPseudoCtor, "HTMLInputElement", HTMLInputElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTextAreaElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLTextAreaElement", HTMLTextAreaElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTextAreaElementPseudoCtor, "HTMLTextAreaElement", HTMLTextAreaElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLButtonElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLButtonElement", HTMLButtonElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLButtonElementPseudoCtor, "HTMLButtonElement", HTMLButtonElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLabelElement", HTMLLabelElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLabelElementPseudoCtor, "HTMLLabelElement", HTMLLabelElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFieldSetElement", HTMLFieldSetElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFieldSetElementPseudoCtor, "HTMLFieldSetElement", HTMLFieldSetElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLegendElement", HTMLLegendElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLegendElementPseudoCtor, "HTMLLegendElement", HTMLLegendElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLUListElement", HTMLUListElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLUListElementPseudoCtor, "HTMLUListElement", HTMLUListElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLOListElement", HTMLOListElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLOListElementPseudoCtor, "HTMLOListElement", HTMLOListElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDListElement", HTMLDListElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDListElementPseudoCtor, "HTMLDListElement", HTMLDListElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDirectoryElement", HTMLDirectoryElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDirectoryElementPseudoCtor, "HTMLDirectoryElement", HTMLDirectoryElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMenuElement", HTMLMenuElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMenuElementPseudoCtor, "HTMLMenuElement", HTMLMenuElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLIElement", HTMLLIElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLIElementPseudoCtor, "HTMLLIElement", HTMLLIElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLDivElement", HTMLDivElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLDivElementPseudoCtor, "HTMLDivElement", HTMLDivElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLParagraphElement", HTMLParagraphElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLParagraphElementPseudoCtor, "HTMLParagraphElement", HTMLParagraphElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHeadingElement", HTMLHeadingElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHeadingElementPseudoCtor, "HTMLHeadingElement", HTMLHeadingElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBlockQuoteElement", HTMLBlockQuoteElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBlockQuoteElementPseudoCtor, "HTMLBlockQuoteElement", HTMLBlockQuoteElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLQuoteElement", HTMLQuoteElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLQuoteElementPseudoCtor, "HTMLQuoteElement", HTMLQuoteElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLPreElement", HTMLPreElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLPreElementPseudoCtor, "HTMLPreElement", HTMLPreElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBRElement", HTMLBRElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBRElementPseudoCtor, "HTMLBRElement", HTMLBRElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLBaseFontElement", HTMLBaseFontElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLBaseFontElementPseudoCtor, "HTMLBaseFontElement", HTMLBaseFontElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFontElement", HTMLFontElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFontElementPseudoCtor, "HTMLFontElement", HTMLFontElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLHRElement", HTMLHRElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLHRElementPseudoCtor, "HTMLHRElement", HTMLHRElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLModElement", HTMLModElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLModElementPseudoCtor, "HTMLModElement", HTMLModElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLAnchorElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLAnchorElement", HTMLAnchorElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAnchorElementPseudoCtor, "HTMLAnchorElement", HTMLAnchorElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLImageElement", HTMLImageElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLImageElementPseudoCtor, "HTMLImageElement", HTMLImageElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLObjectElement", HTMLObjectElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLObjectElementPseudoCtor, "HTMLObjectElement", HTMLObjectElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLParamElement", HTMLParamElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLParamElementPseudoCtor, "HTMLParamElement", HTMLParamElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLAppletElement", HTMLAppletElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAppletElementPseudoCtor, "HTMLAppletElement", HTMLAppletElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLMapElement", HTMLMapElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMapElementPseudoCtor, "HTMLMapElement", HTMLMapElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLAreaElement", HTMLAreaElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLAreaElementPseudoCtor, "HTMLAreaElement", HTMLAreaElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLScriptElement", HTMLScriptElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLScriptElementPseudoCtor, "HTMLScriptElement", HTMLScriptElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLTableElement", HTMLTableElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableElementPseudoCtor, "HTMLTableElement", HTMLTableElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableCaptionElement", HTMLTableCaptionElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableCaptionElementPseudoCtor, "HTMLTableCaptionElement", HTMLTableCaptionElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableColElement", HTMLTableColElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableColElementPseudoCtor, "HTMLTableColElement", HTMLTableColElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableSectionElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLTableSectionElement", HTMLTableSectionElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableSectionElementPseudoCtor, "HTMLTableSectionElement", HTMLTableSectionElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLTableRowElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLTableRowElement", HTMLTableRowElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableRowElementPseudoCtor, "HTMLTableRowElement", HTMLTableRowElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLTableCellElement", HTMLTableCellElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLTableCellElementPseudoCtor, "HTMLTableCellElement", HTMLTableCellElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFrameSetElement", HTMLFrameSetElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFrameSetElementPseudoCtor, "HTMLFrameSetElement", HTMLFrameSetElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLLayerElement", HTMLLayerElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLLayerElementPseudoCtor, "HTMLLayerElement", HTMLLayerElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLFrameElement", HTMLFrameElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLFrameElementPseudoCtor, "HTMLFrameElement", HTMLFrameElementProto)
+
+KJS_EMPTY_PROTOTYPE_WITH_PROTOTYPE("HTMLIFrameElement", HTMLIFrameElementProto, HTMLElementProto)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLIFrameElementPseudoCtor, "HTMLIFrameElement", HTMLIFrameElementProto)
+
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLMarqueeElementProto, HTMLElementProto)
+KJS_IMPLEMENT_PROTOTYPE("HTMLMarqueeElement", HTMLMarqueeElementProto, HTMLElementFunction)
+IMPLEMENT_PSEUDO_CONSTRUCTOR(HTMLMarqueeElementPseudoCtor, "HTMLMarqueeElement", HTMLMarqueeElementProto)
+
+static Object prototypeForID(ExecState* exec, DOM::NodeImpl::Id id) {
+ switch (id) {
+ case ID_HTML:
+ return HTMLHtmlElementProto::self(exec);
+ case ID_HEAD:
+ return HTMLHeadElementProto::self(exec);
+ case ID_LINK:
+ return HTMLLinkElementProto::self(exec);
+ case ID_TITLE:
+ return HTMLTitleElementProto::self(exec);
+ case ID_META:
+ return HTMLMetaElementProto::self(exec);
+ case ID_BASE:
+ return HTMLBaseElementProto::self(exec);
+ case ID_ISINDEX:
+ return HTMLIsIndexElementProto::self(exec);
+ case ID_STYLE:
+ return HTMLStyleElementProto::self(exec);
+ case ID_BODY:
+ return HTMLBodyElementProto::self(exec);
+ case ID_FORM:
+ return HTMLFormElementProto::self(exec);
+ case ID_SELECT:
+ return HTMLSelectElementProto::self(exec);
+ case ID_OPTGROUP:
+ return HTMLOptGroupElementProto::self(exec);
+ case ID_OPTION:
+ return HTMLOptionElementProto::self(exec);
+ case ID_INPUT:
+ return HTMLInputElementProto::self(exec);
+ case ID_TEXTAREA:
+ return HTMLTextAreaElementProto::self(exec);
+ case ID_BUTTON:
+ return HTMLButtonElementProto::self(exec);
+ case ID_LABEL:
+ return HTMLLabelElementProto::self(exec);
+ case ID_FIELDSET:
+ return HTMLFieldSetElementProto::self(exec);
+ case ID_LEGEND:
+ return HTMLLegendElementProto::self(exec);
+ case ID_UL:
+ return HTMLUListElementProto::self(exec);
+ case ID_OL:
+ return HTMLOListElementProto::self(exec);
+ case ID_DL:
+ return HTMLDListElementProto::self(exec);
+ case ID_DIR:
+ return HTMLDirectoryElementProto::self(exec);
+ case ID_MENU:
+ return HTMLMenuElementProto::self(exec);
+ case ID_LI:
+ return HTMLLIElementProto::self(exec);
+ case ID_DIV:
+ return HTMLDivElementProto::self(exec);
+ case ID_P:
+ return HTMLParagraphElementProto::self(exec);
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ return HTMLHeadingElementProto::self(exec);
+ case ID_BLOCKQUOTE:
+ return HTMLBlockQuoteElementProto::self(exec);
+ case ID_Q:
+ return HTMLQuoteElementProto::self(exec);
+ case ID_PRE:
+ return HTMLPreElementProto::self(exec);
+ case ID_BR:
+ return HTMLBRElementProto::self(exec);
+ case ID_BASEFONT:
+ return HTMLBaseFontElementProto::self(exec);
+ case ID_FONT:
+ return HTMLFontElementProto::self(exec);
+ case ID_HR:
+ return HTMLHRElementProto::self(exec);
+ case ID_INS:
+ case ID_DEL:
+ return HTMLModElementProto::self(exec);
+ case ID_A:
+ return HTMLAnchorElementProto::self(exec);
+ case ID_IMG:
+ return HTMLImageElementProto::self(exec);
+ case ID_OBJECT:
+ return HTMLObjectElementProto::self(exec);
+ case ID_PARAM:
+ return HTMLParamElementProto::self(exec);
+ case ID_APPLET:
+ return HTMLAppletElementProto::self(exec);
+ case ID_MAP:
+ return HTMLMapElementProto::self(exec);
+ case ID_AREA:
+ return HTMLAreaElementProto::self(exec);
+ case ID_SCRIPT:
+ return HTMLScriptElementProto::self(exec);
+ case ID_TABLE:
+ return HTMLTableElementProto::self(exec);
+ case ID_CAPTION:
+ return HTMLTableCaptionElementProto::self(exec);
+ case ID_COL:
+ case ID_COLGROUP:
+ return HTMLTableColElementProto::self(exec);
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT:
+ return HTMLTableSectionElementProto::self(exec);
+ case ID_TR:
+ return HTMLTableRowElementProto::self(exec);
+ case ID_TD:
+ case ID_TH:
+ return HTMLTableCellElementProto::self(exec);
+ case ID_FRAMESET:
+ return HTMLFrameSetElementProto::self(exec);
+ case ID_LAYER:
+ return HTMLLayerElementProto::self(exec);
+ case ID_FRAME:
+ return HTMLFrameElementProto::self(exec);
+ case ID_IFRAME:
+ return HTMLIFrameElementProto::self(exec);
+ case ID_MARQUEE:
+ return HTMLMarqueeElementProto::self(exec);
+ default:
+ return HTMLElementProto::self(exec);
+ }
+}
+
+// -------------------------------------------------------------------------
+/* Source for HTMLCollectionProtoTable.
+@begin HTMLCollectionProtoTable 3
+ item HTMLCollection::Item DontDelete|Function 1
+ namedItem HTMLCollection::NamedItem DontDelete|Function 1
+ tags HTMLCollection::Tags DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(HTMLCollectionProto)
+IMPLEMENT_PROTOFUNC_DOM(HTMLCollectionProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("HTMLCollection", HTMLCollectionProto,HTMLCollectionProtoFunc)
+
+const ClassInfo KJS::HTMLCollection::info = { "HTMLCollection", 0, 0, 0 };
+
+KJS::HTMLCollection::HTMLCollection(ExecState *exec, const DOM::HTMLCollection& c)
+ : DOMObject(HTMLCollectionProto::self(exec)), collection(c), hidden(false) {}
+
+KJS::HTMLCollection::HTMLCollection(const KJS::Object& proto, const DOM::HTMLCollection& c)
+ : DOMObject(proto), collection(c), hidden(false) {}
+
+KJS::HTMLCollection::~HTMLCollection()
+{
+ ScriptInterpreter::forgetDOMObject(collection.handle());
+}
+
+bool KJS::HTMLCollection::toBoolean(ExecState *) const {
+ return !hidden;
+}
+
+// We have to implement hasProperty since we don't use a hashtable for 'selectedIndex' and 'length',
+// and for indices in "for (..in..)"
+bool KJS::HTMLCollection::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ if (p == lengthPropertyName)
+ return true;
+ if ( collection.handle()->getType() == HTMLCollectionImpl::SELECT_OPTIONS &&
+ ( p == "selectedIndex" || p == "value" ) )
+ return true;
+
+ bool ok;
+ unsigned long pos = p.toULong(&ok);
+ if (ok && pos < collection.length())
+ return true;
+
+ return DOMObject::hasProperty(exec, p);
+}
+
+ReferenceList KJS::HTMLCollection::propList(ExecState *exec, bool recursive)
+{
+ ReferenceList properties = ObjectImp::propList(exec,recursive);
+
+ for (unsigned i = 0; i < collection.length(); ++i) {
+ if (!ObjectImp::hasProperty(exec,Identifier::from(i))) {
+ properties.append(Reference(this, i));
+ }
+ }
+
+ if (!ObjectImp::hasProperty(exec, lengthPropertyName))
+ properties.append(Reference(this, lengthPropertyName));
+
+ return properties;
+}
+
+Value KJS::HTMLCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLCollection::tryGet " << propertyName.ascii() << endl;
+#endif
+ if (propertyName == lengthPropertyName)
+ {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << " collection length is " << collection.length() << endl;
+#endif
+ return Number(collection.length());
+ }
+
+ if (collection.handle()->getType() == HTMLCollectionImpl::SELECT_OPTIONS) {
+ DOM::HTMLSelectElement parentSelect = collection.base();
+ if ( parentSelect.isNull() )
+ return Undefined();
+ if (propertyName == "selectedIndex") {
+ // NON-STANDARD options.selectedIndex
+ return Number(parentSelect.selectedIndex());
+ } else if ( propertyName == "value" ) {
+ // NON-STANDARD options.value
+ return String(parentSelect.value());
+ }
+ }
+
+ // Look in the prototype (for functions) before assuming it's an item's name
+ Object proto = Object::dynamicCast(prototype());
+ if (proto.isValid() && proto.hasProperty(exec,propertyName))
+ return proto.get(exec,propertyName);
+
+ // name or index ?
+ bool ok;
+ unsigned int u = propertyName.toULong(&ok);
+ if (ok) {
+ if ( u < collection.length() ) {
+ DOM::Node node = collection.item(u);
+ return getDOMNode(exec,node);
+ } else
+ return Undefined();
+ }
+ else
+ return getNamedItems(exec,propertyName);
+}
+
+// HTMLCollections are strange objects, they support both get and call,
+// so that document.forms.item(0) and document.forms(0) both work.
+Value KJS::HTMLCollection::call(ExecState *exec, Object &thisObj, const List &args)
+{
+ // This code duplication is necessary, HTMLCollection isn't a DOMFunction
+ Value val;
+ try {
+ val = tryCall(exec, thisObj, args);
+ }
+ // pity there's no way to distinguish between these in JS code
+ catch (...) {
+ Object err = Error::create(exec, GeneralError, "Exception from HTMLCollection");
+ exec->setException(err);
+ }
+ return val;
+}
+
+Value KJS::HTMLCollection::tryCall(ExecState *exec, Object &, const List &args)
+{
+ // Do not use thisObj here. It can be the HTMLDocument, in the document.forms(i) case.
+ /*if( thisObj.imp() != this )
+ {
+ kdDebug(6070) << "WARNING: thisObj.imp() != this in HTMLCollection::tryCall" << endl;
+ KJS::printInfo(exec,"KJS::HTMLCollection::tryCall thisObj",thisObj,-1);
+ KJS::printInfo(exec,"KJS::HTMLCollection::tryCall this",Value(this),-1);
+ }*/
+ // Also, do we need the TypeError test here ?
+
+ if (args.size() == 1) {
+ // support for document.all(<index>) etc.
+ bool ok;
+ UString s = args[0].toString(exec);
+ unsigned int u = s.toULong(&ok);
+ if (ok) {
+ DOM::Element element = collection.item(u);
+ return getDOMNode(exec,element);
+ }
+ // support for document.images('<name>') etc.
+ return getNamedItems(exec,Identifier(s));
+ }
+ else if (args.size() >= 1) // the second arg, if set, is the index of the item we want
+ {
+ bool ok;
+ UString s = args[0].toString(exec);
+ unsigned int u = args[1].toString(exec).toULong(&ok);
+ if (ok)
+ {
+ DOM::DOMString pstr = s.string();
+ DOM::Node node = collection.namedItem(pstr);
+ while (!node.isNull()) {
+ if (!u)
+ return getDOMNode(exec,node);
+ node = collection.nextNamedItem(pstr);
+ --u;
+ }
+ }
+ }
+ return Undefined();
+}
+
+Value KJS::HTMLCollection::getNamedItems(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLCollection::getNamedItems " << propertyName.ascii() << endl;
+#endif
+
+ DOM::DOMString pstr = propertyName.string();
+
+ TQValueList<DOM::NodeImpl*> matches = collection.handle()->namedItems(pstr);
+
+ if (!matches.isEmpty()) {
+ if (matches.size() == 1) {
+ DOM::Node node(matches[0]);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "returning single node" << endl;
+#endif
+ return getDOMNode(exec,node);
+ }
+ else {
+ // multiple items, return a collection
+ TQValueList<DOM::Node> nodes;
+ for (TQValueList<DOM::NodeImpl*>::const_iterator i = matches.begin();
+ i != matches.end(); ++i)
+ nodes.append(DOM::Node(*i));
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "returning list of " << nodes.count() << " nodes" << endl;
+#endif
+ return Value(new DOMNamedNodesCollection(exec, nodes));
+ }
+ }
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "not found" << endl;
+#endif
+ return Undefined();
+}
+
+Value KJS::HTMLCollectionProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::HTMLCollection, thisObj );
+ DOM::HTMLCollection coll = static_cast<KJS::HTMLCollection *>(thisObj.imp())->toCollection();
+
+ switch (id) {
+ case KJS::HTMLCollection::Item:
+ {
+ // support for item(<index>) (DOM)
+ bool ok;
+ UString s = args[0].toString(exec);
+ unsigned int u = s.toULong(&ok);
+ if (ok) {
+ return getDOMNode(exec,coll.item(u));
+ }
+ // support for item('<name>') (IE only)
+ kdWarning() << "non-standard HTMLCollection.item('" << s.ascii() << "') called, use namedItem instead" << endl;
+ return getDOMNode(exec,coll.namedItem(s.string()));
+ }
+ case KJS::HTMLCollection::Tags:
+ {
+ DOM::DOMString tagName = args[0].toString(exec).string();
+ DOM::NodeList list;
+ // getElementsByTagName exists in Document and in Element, pick up the right one
+ if ( coll.base().nodeType() == DOM::Node::DOCUMENT_NODE )
+ {
+ DOM::Document doc = coll.base();
+ list = doc.getElementsByTagName(tagName);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLCollectionProtoFunc::tryCall document.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
+#endif
+ } else
+ {
+ DOM::Element e = coll.base();
+ list = e.getElementsByTagName(tagName);
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLCollectionProtoFunc::tryCall element.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
+#endif
+ }
+ return getDOMNodeList(exec, list);
+ }
+ case KJS::HTMLCollection::NamedItem:
+ {
+ Value val = static_cast<HTMLCollection *>(thisObj.imp())->getNamedItems(exec, Identifier(args[0].toString(exec)));
+ // Must return null when asking for a named item that isn't in the collection
+ // (DOM2 testsuite, HTMLCollection12 test)
+ if ( val.type() == KJS::UndefinedType )
+ return Null();
+ else
+ return val;
+ }
+ default:
+ return Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+/* Source for HTMLSelectCollectionProtoTable.
+@begin HTMLSelectCollectionProtoTable 1
+ add HTMLSelectCollection::Add DontDelete|Function 2
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(HTMLSelectCollectionProto, HTMLCollectionProto)
+IMPLEMENT_PROTOFUNC_DOM(HTMLSelectCollectionProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("HTMLOptionsCollection", HTMLSelectCollectionProto, HTMLSelectCollectionProtoFunc)
+
+const ClassInfo KJS::HTMLSelectCollection::info = { "HTMLOptionsCollection", &HTMLCollection::info, 0, 0 };
+
+KJS::HTMLSelectCollection::HTMLSelectCollection(ExecState *exec, const DOM::HTMLCollection& c,
+ const DOM::HTMLSelectElement& e)
+ : HTMLCollection(HTMLSelectCollectionProto::self(exec), c), element(e) { }
+
+Value KJS::HTMLSelectCollection::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if (p == "selectedIndex")
+ return Number(element.selectedIndex());
+
+ return HTMLCollection::tryGet(exec, p);
+}
+
+void KJS::HTMLSelectCollection::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KJS::HTMLSelectCollection::tryPut " << propertyName.qstring() << endl;
+#endif
+ if ( propertyName == "selectedIndex" ) {
+ element.setSelectedIndex( value.toInteger( exec ) );
+ return;
+ }
+ // resize ?
+ else if (propertyName == lengthPropertyName) {
+ unsigned newLen;
+ bool converted = value.toUInt32(newLen);
+
+ if (!converted) {
+ return;
+ }
+
+ long diff = element.length() - newLen;
+
+ if (diff < 0) { // add dummy elements
+ do {
+ element.add(element.ownerDocument().createElement("OPTION"), DOM::HTMLElement());
+ } while (++diff);
+ }
+ else // remove elements
+ while (diff-- > 0)
+ element.remove(newLen + diff);
+
+ return;
+ }
+ // an index ?
+ bool ok;
+ unsigned int u = propertyName.toULong(&ok);
+ if (!ok)
+ return;
+
+ if (value.isA(NullType) || value.isA(UndefinedType)) {
+ // null and undefined delete. others, too ?
+ element.remove(u);
+ return;
+ }
+
+ // is v an option element ?
+ DOM::Node node = KJS::toNode(value);
+ if (node.isNull() || node.elementId() != ID_OPTION)
+ return;
+
+ DOM::HTMLOptionElement option = static_cast<DOM::HTMLOptionElement>(node);
+ if ( option.ownerDocument() != element.ownerDocument() )
+ option = static_cast<DOM::HTMLOptionElement>(element.ownerDocument().importNode(option, true));
+ long diff = long(u) - element.length();
+ DOM::HTMLElement before;
+ // out of array bounds ? first insert empty dummies
+ if (diff > 0) {
+ while (diff--) {
+ element.add(element.ownerDocument().createElement("OPTION"), before);
+ }
+ // replace an existing entry ?
+ } else if (diff < 0) {
+ before = element.options().item(u+1);
+ element.remove(u);
+ }
+ // finally add the new element
+ element.add(option, before);
+}
+
+
+Value KJS::HTMLSelectCollectionProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::HTMLSelectCollection, thisObj );
+ DOM::HTMLSelectElement element = static_cast<KJS::HTMLSelectCollection *>(thisObj.imp())->toElement();
+
+ switch (id) {
+ case KJS::HTMLSelectCollection::Add:
+ {
+ //Non-standard select.options.add.
+ //The first argument is the item, 2nd is offset.
+ //IE and Mozilla are both quite picky here, too...
+ DOM::Node node = KJS::toNode(args[0]);
+ if (node.isNull() || node.elementId() != ID_OPTION) {
+ Object err = Error::create(exec, GeneralError, "Invalid argument to HTMLOptionsCollection::add");
+ exec->setException(err);
+ return Undefined();
+ }
+
+ DOM::HTMLOptionElement option = static_cast<DOM::HTMLOptionElement>(node);
+ if ( option.ownerDocument() != element.ownerDocument() ) //### remove this once auto-adopt works...
+ option = static_cast<DOM::HTMLOptionElement>(element.ownerDocument().importNode(option, true));
+
+ int pos = 0;
+ //By default append, if not specified or null..
+ if (args[1].isA(UndefinedType))
+ pos = element.length();
+ else
+ pos = (int)args[1].toNumber(exec);
+
+ if (pos < 0) {
+ Object err = Error::create(exec, GeneralError, "Invalid index argument to HTMLOptionsCollection::add");
+ exec->setException(err);
+ return Undefined();
+ }
+
+ if (pos >= element.length()) {
+ //Append
+ element.add(option, DOM::Node());
+ } else {
+ //Find what to prepend before..
+ DOM::HTMLSelectElementImpl* impl = static_cast<HTMLSelectElementImpl*>(element.handle());
+ TQMemArray<HTMLGenericFormElementImpl*> items = impl->listItems();
+ int dummy;
+ impl->insertBefore(option.handle(), items.at(pos), dummy);
+ }
+ return Undefined();
+ break;
+ }
+ default:
+ break;
+ }
+ return Undefined();
+}
+
+
+////////////////////// Option Object ////////////////////////
+
+OptionConstructorImp::OptionConstructorImp(ExecState *exec, const DOM::Document &d)
+ : ObjectImp(), doc(d)
+{
+ // ## isn't there some redundancy between ObjectImp::_proto and the "prototype" property ?
+ //put(exec,"prototype", ...,DontEnum|DontDelete|ReadOnly);
+
+ // no. of arguments for constructor
+ // ## is 4 correct ? 0 to 4, it seems to be
+ put(exec,lengthPropertyName, Number(4), ReadOnly|DontDelete|DontEnum);
+}
+
+bool OptionConstructorImp::implementsConstruct() const
+{
+ return true;
+}
+
+Object OptionConstructorImp::construct(ExecState *exec, const List &args)
+{
+ DOM::Element el = doc.createElement("OPTION");
+ DOM::HTMLOptionElement opt = static_cast<DOM::HTMLOptionElement>(el);
+ int sz = args.size();
+ DOM::Text t = doc.createTextNode("");
+ try { opt.appendChild(t); }
+ catch(DOM::DOMException& e) {
+ // #### exec->setException ?
+ }
+ if (sz > 0)
+ t.setData(args[0].toString(exec).string()); // set the text
+ if (sz > 1)
+ opt.setValue(args[1].toString(exec).string());
+ if (sz > 2)
+ opt.setDefaultSelected(args[2].toBoolean(exec));
+ if (sz > 3)
+ opt.setSelected(args[3].toBoolean(exec));
+
+ return Object::dynamicCast(getDOMNode(exec,opt));
+}
+
+////////////////////// Image Object ////////////////////////
+
+//Like in other browsers, we merely make a new HTMLImageElement
+//not in tree for this.
+ImageConstructorImp::ImageConstructorImp(ExecState *, const DOM::Document &d)
+ : ObjectImp(), doc(d)
+{
+}
+
+bool ImageConstructorImp::implementsConstruct() const
+{
+ return true;
+}
+
+Object ImageConstructorImp::construct(ExecState *exec, const List &list)
+{
+ bool widthSet = false, heightSet = false;
+ int width = 0, height = 0;
+ if (list.size() > 0) {
+ widthSet = true;
+ Value w = list.at(0);
+ width = w.toInt32(exec);
+ }
+ if (list.size() > 1) {
+ heightSet = true;
+ Value h = list.at(1);
+ height = h.toInt32(exec);
+ }
+
+ HTMLImageElement image(doc.createElement("image"));
+
+ if (widthSet)
+ image.setWidth(width);
+
+ if (heightSet)
+ image.setHeight(height);
+
+ return Object::dynamicCast(getDOMNode(exec,image));
+}
+
+Value getHTMLCollection(ExecState *exec, const DOM::HTMLCollection& c, bool hide)
+{
+ Value coll = cacheDOMObject<DOM::HTMLCollection, KJS::HTMLCollection>(exec, c);
+ if (hide) {
+ KJS::HTMLCollection *impl = static_cast<KJS::HTMLCollection*>(coll.imp());
+ impl->hide();
+ }
+ return coll;
+}
+
+Value getSelectHTMLCollection(ExecState *exec, const DOM::HTMLCollection& c, const DOM::HTMLSelectElement& e)
+{
+ DOMObject *ret;
+ if (c.isNull())
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ if ((ret = interp->getDOMObject(c.handle())))
+ return Value(ret);
+ else {
+ ret = new HTMLSelectCollection(exec, c, e);
+ interp->putDOMObject(c.handle(),ret);
+ return Value(ret);
+ }
+}
+
+} //namespace KJS
diff --git a/tdehtml/ecma/kjs_html.h b/tdehtml/ecma/kjs_html.h
new file mode 100644
index 000000000..53da38462
--- /dev/null
+++ b/tdehtml/ecma/kjs_html.h
@@ -0,0 +1,294 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999 Harri Porten (porten@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_HTML_H_
+#define _KJS_HTML_H_
+
+#include "dom/html_document.h"
+#include "dom/html_base.h"
+#include "dom/html_misc.h"
+#include "dom/html_form.h"
+#include "misc/loader_client.h"
+
+#include "ecma/kjs_binding.h"
+#include "ecma/kjs_dom.h"
+#include "xml/dom_nodeimpl.h" // for NodeImpl::Id
+
+namespace KJS {
+
+ class HTMLElement;
+
+ class HTMLDocument : public DOMDocument {
+ public:
+ HTMLDocument(ExecState *exec, const DOM::HTMLDocument& d);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
+ virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Title, Referrer, Domain, URL, Body, Location, Cookie,
+ Images, Applets, Links, Forms, Layers, Anchors, Scripts, All, Clear, Open, Close,
+ Write, WriteLn, GetElementsByName, GetSelection, CaptureEvents, ReleaseEvents,
+ BgColor, FgColor, AlinkColor, LinkColor, VlinkColor, LastModified,
+ Height, Width, Dir, Frames, CompatMode };
+ DOM::Document toDocument() const { return static_cast<DOM::Document>( node ); }
+ };
+
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLDocumentPseudoCtor)
+
+ class HTMLElement : public DOMElement {
+ public:
+ HTMLElement(ExecState *exec, const DOM::HTMLElement& e);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int);
+ virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
+ virtual UString toString(ExecState *exec) const;
+ virtual void pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const;
+ virtual const ClassInfo* classInfo() const;
+ static const ClassInfo info;
+
+ static const ClassInfo html_info, head_info, link_info, title_info,
+ meta_info, base_info, isIndex_info, style_info, body_info, form_info,
+ select_info, optGroup_info, option_info, input_info, textArea_info,
+ button_info, label_info, fieldSet_info, legend_info, ul_info, ol_info,
+ dl_info, dir_info, menu_info, li_info, div_info, p_info, heading_info,
+ blockQuote_info, q_info, pre_info, br_info, baseFont_info, font_info,
+ hr_info, mod_info, a_info, img_info, object_info, param_info,
+ applet_info, map_info, area_info, script_info, table_info,
+ caption_info, col_info, tablesection_info, tr_info,
+ tablecell_info, frameSet_info, frame_info, iFrame_info, marquee_info, layer_info;
+
+ enum { HtmlVersion, HeadProfile, LinkHref, LinkRel, LinkMedia,
+ LinkCharset, LinkDisabled, LinkHrefLang, LinkRev, LinkTarget, LinkType,
+ LinkSheet, TitleText, MetaName, MetaHttpEquiv, MetaContent, MetaScheme,
+ BaseHref, BaseTarget, IsIndexForm, IsIndexPrompt, StyleDisabled,
+ StyleSheet, StyleType, StyleMedia, BodyBackground, BodyVLink, BodyText,
+ BodyLink, BodyALink, BodyBgColor, BodyOnLoad, BodyFocus,
+ FormAction, FormEncType, FormElements, FormLength, FormAcceptCharset,
+ FormReset, FormTarget, FormName, FormMethod, FormSubmit, SelectAdd,
+ SelectTabIndex, SelectValue, SelectSelectedIndex, SelectLength,
+ SelectRemove, SelectForm, SelectBlur, SelectType, SelectOptions,
+ SelectDisabled, SelectMultiple, SelectName, SelectSize, SelectFocus,
+ OptGroupDisabled, OptGroupLabel, OptionIndex, OptionSelected,
+ OptionForm, OptionText, OptionDefaultSelected, OptionDisabled,
+ OptionLabel, OptionValue, InputBlur, InputReadOnly, InputAccept,
+ InputSize, InputDefaultValue, InputTabIndex, InputValue, InputType,
+ InputFocus, InputMaxLength, InputDefaultChecked, InputDisabled,
+ InputChecked, InputIndeterminate, InputForm, InputAccessKey, InputAlign, InputAlt,
+ InputName, InputSrc, InputUseMap, InputSelect, InputClick,
+ InputSelectionStart, InputSelectionEnd, InputSetSelectionRange,
+ TextAreaAccessKey, TextAreaName, TextAreaDefaultValue, TextAreaSelect,
+ TextAreaCols, TextAreaDisabled, TextAreaForm, TextAreaType,
+ TextAreaTabIndex, TextAreaReadOnly, TextAreaRows, TextAreaValue,
+ TextAreaBlur, TextAreaFocus, TextAreaSelectionStart, TextAreaSelectionEnd, TextAreaSetSelectionRange,
+ TextAreaTextLength, ButtonBlur, ButtonFocus, ButtonForm, ButtonTabIndex, ButtonName,
+ ButtonDisabled, ButtonAccessKey, ButtonType, ButtonValue, LabelHtmlFor,
+ LabelForm, LabelAccessKey, FieldSetForm, LegendForm, LegendAccessKey,
+ LegendAlign, UListType, UListCompact, OListStart, OListCompact,
+ OListType, DListCompact, DirectoryCompact, MenuCompact, LIType,
+ LIValue, DivAlign, ParagraphAlign, HeadingAlign, BlockQuoteCite,
+ QuoteCite, PreWidth, BRClear, BaseFontColor, BaseFontSize,
+ BaseFontFace, FontColor, FontSize, FontFace, HRWidth, HRNoShade,
+ HRAlign, HRSize, ModCite, ModDateTime, AnchorShape, AnchorRel,
+ AnchorAccessKey, AnchorCoords, AnchorHref, AnchorProtocol, AnchorHost,
+ AnchorCharset, AnchorHrefLang, AnchorHostname, AnchorType, AnchorFocus,
+ AnchorPort, AnchorPathName, AnchorHash, AnchorSearch, AnchorName,
+ AnchorRev, AnchorTabIndex, AnchorTarget, AnchorText, AnchorBlur, AnchorClick,
+ ImageName, ImageAlign, ImageHspace, ImageVspace, ImageUseMap, ImageAlt,
+ ImageLowSrc, ImageWidth, ImageIsMap, ImageBorder, ImageHeight,
+ ImageLongDesc, ImageSrc, ImageX, ImageY, ImageComplete, ObjectHspace, ObjectHeight, ObjectAlign,
+ ObjectBorder, ObjectCode, ObjectType, ObjectVspace, ObjectArchive,
+ ObjectDeclare, ObjectForm, ObjectCodeBase, ObjectCodeType, ObjectData,
+ ObjectName, ObjectStandby, ObjectTabIndex, ObjectUseMap, ObjectWidth, ObjectContentDocument,
+ ParamName, ParamType, ParamValueType, ParamValue, AppletArchive,
+ AppletAlt, AppletCode, AppletWidth, AppletAlign, AppletCodeBase,
+ AppletName, AppletHeight, AppletHspace, AppletObject, AppletVspace,
+ MapAreas, MapName, AreaHash, AreaHref, AreaTarget, AreaPort, AreaShape,
+ AreaCoords, AreaAlt, AreaAccessKey, AreaNoHref, AreaHost, AreaProtocol,
+ AreaHostName, AreaPathName, AreaSearch, AreaTabIndex, ScriptEvent,
+ ScriptType, ScriptHtmlFor, ScriptText, ScriptSrc, ScriptCharset,
+ ScriptDefer, TableSummary, TableTBodies, TableTHead, TableCellPadding,
+ TableDeleteCaption, TableCreateCaption, TableCaption, TableWidth,
+ TableCreateTFoot, TableAlign, TableTFoot, TableDeleteRow,
+ TableCellSpacing, TableRows, TableBgColor, TableBorder, TableFrame,
+ TableRules, TableCreateTHead, TableDeleteTHead, TableDeleteTFoot,
+ TableInsertRow, TableCaptionAlign, TableColCh, TableColChOff,
+ TableColAlign, TableColSpan, TableColVAlign, TableColWidth,
+ TableSectionCh, TableSectionDeleteRow, TableSectionChOff,
+ TableSectionRows, TableSectionAlign, TableSectionVAlign,
+ TableSectionInsertRow, TableRowSectionRowIndex, TableRowRowIndex,
+ TableRowChOff, TableRowCells, TableRowVAlign, TableRowCh,
+ TableRowAlign, TableRowBgColor, TableRowDeleteCell, TableRowInsertCell,
+ TableCellColSpan, TableCellNoWrap, TableCellAbbr, TableCellHeight,
+ TableCellWidth, TableCellCellIndex, TableCellChOff, TableCellBgColor,
+ TableCellCh, TableCellVAlign, TableCellRowSpan, TableCellHeaders,
+ TableCellAlign, TableCellAxis, TableCellScope, FrameSetCols,
+ FrameSetRows, FrameSrc, FrameLocation, FrameFrameBorder, FrameScrolling,
+ FrameMarginWidth, FrameLongDesc, FrameMarginHeight, FrameName,
+ FrameContentDocument, FrameContentWindow,
+ FrameNoResize, FrameWidth, FrameHeight, IFrameLongDesc, IFrameAlign,
+ IFrameFrameBorder, IFrameSrc, IFrameName, IFrameHeight,
+ IFrameMarginHeight, IFrameMarginWidth, IFrameScrolling, IFrameWidth,
+ IFrameContentDocument, IFrameContentWindow,
+ MarqueeStart, MarqueeStop,
+ LayerTop, LayerLeft, LayerVisibility, LayerBgColor, LayerClip, LayerDocument, LayerLayers,
+ ElementInnerHTML, ElementTitle, ElementId, ElementDir, ElementLang,
+ ElementClassName, ElementInnerText, ElementDocument,
+ ElementChildren, ElementAll, ElementScrollIntoView };
+
+ DOM::HTMLElement toElement() const { return static_cast<DOM::HTMLElement>(node); }
+ };
+
+ class HTMLElementFunction : public DOMFunction {
+ public:
+ HTMLElementFunction(ExecState *exec, int i, int len);
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args);
+ private:
+ int id;
+ };
+
+ class HTMLCollection : public DOMObject {
+ public:
+ HTMLCollection(ExecState *exec, const DOM::HTMLCollection& c);
+ HTMLCollection(const KJS::Object& proto, const DOM::HTMLCollection& c);
+ ~HTMLCollection();
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List&args);
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args);
+ virtual bool implementsCall() const { return true; }
+ virtual bool toBoolean(ExecState *) const;
+ virtual bool hasProperty(ExecState *exec, const Identifier &p) const;
+ virtual ReferenceList propList(ExecState *exec, bool recursive);
+ enum { Item, NamedItem, Tags };
+ Value getNamedItems(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ DOM::HTMLCollection toCollection() const { return collection; }
+ virtual void hide() { hidden = true; }
+ protected:
+ DOM::HTMLCollection collection;
+ bool hidden;
+ };
+
+ class HTMLSelectCollection : public HTMLCollection {
+ public:
+ enum { Add };
+ HTMLSelectCollection(ExecState *exec, const DOM::HTMLCollection& c, const DOM::HTMLSelectElement& e);
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+
+ DOM::HTMLSelectElement toElement() const { return element; }
+ private:
+ DOM::HTMLSelectElement element;
+ };
+
+ ////////////////////// Option Object ////////////////////////
+
+ class OptionConstructorImp : public ObjectImp {
+ public:
+ OptionConstructorImp(ExecState *exec, const DOM::Document &d);
+ virtual bool implementsConstruct() const;
+ virtual Object construct(ExecState *exec, const List &args);
+ private:
+ DOM::Document doc;
+ };
+
+ ////////////////////// Image Object ////////////////////////
+
+ class ImageConstructorImp : public ObjectImp {
+ public:
+ ImageConstructorImp(ExecState *exec, const DOM::Document &d);
+ virtual bool implementsConstruct() const;
+ virtual Object construct(ExecState *exec, const List &args);
+ private:
+ DOM::Document doc;
+ };
+
+ Value getHTMLCollection(ExecState *exec, const DOM::HTMLCollection& c, bool hide=false);
+ Value getSelectHTMLCollection(ExecState *exec, const DOM::HTMLCollection& c, const DOM::HTMLSelectElement& e);
+
+
+ //All the pseudo constructors..
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLHtmlElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLHeadElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLLinkElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTitleElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLMetaElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLBaseElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLIsIndexElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLStyleElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLBodyElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLFormElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLSelectElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLOptGroupElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLOptionElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLInputElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTextAreaElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLButtonElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLLabelElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLFieldSetElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLLegendElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLUListElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLOListElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLDListElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLDirectoryElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLMenuElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLLIElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLDivElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLParagraphElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLHeadingElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLBlockQuoteElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLQuoteElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLPreElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLBRElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLBaseFontElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLFontElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLHRElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLModElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLAnchorElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLImageElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLObjectElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLParamElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLAppletElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLMapElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLAreaElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLScriptElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableCaptionElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableColElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableSectionElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableRowElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLTableCellElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLFrameSetElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLLayerElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLFrameElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLIFrameElementPseudoCtor)
+ DEFINE_PSEUDO_CONSTRUCTOR(HTMLMarqueeElementPseudoCtor)
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_mozilla.cpp b/tdehtml/ecma/kjs_mozilla.cpp
new file mode 100644
index 000000000..216fde26e
--- /dev/null
+++ b/tdehtml/ecma/kjs_mozilla.cpp
@@ -0,0 +1,94 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2003 George Staikos (staikos@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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kjs_mozilla.h"
+#include "kjs/lookup.h"
+#include "kjs_binding.h"
+#include "tdehtml_part.h"
+#include "kjs_mozilla.lut.h"
+
+using namespace KJS;
+
+namespace KJS {
+
+const ClassInfo MozillaSidebarExtension::info = { "sidebar", 0, &MozillaSidebarExtensionTable, 0 };
+/*
+@begin MozillaSidebarExtensionTable 1
+ addPanel MozillaSidebarExtension::addPanel DontDelete|Function 0
+@end
+*/
+}
+IMPLEMENT_PROTOFUNC_DOM(MozillaSidebarExtensionFunc)
+
+MozillaSidebarExtension::MozillaSidebarExtension(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), m_part(p) { }
+
+Value MozillaSidebarExtension::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "MozillaSidebarExtension::get " << propertyName.ascii() << endl;
+#endif
+ return lookupGet<MozillaSidebarExtensionFunc,MozillaSidebarExtension,ObjectImp>(exec,propertyName,&MozillaSidebarExtensionTable,this);
+}
+
+Value MozillaSidebarExtension::getValueProperty(ExecState *exec, int token) const
+{
+ Q_UNUSED(exec);
+ switch (token) {
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in MozillaSidebarExtension::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value MozillaSidebarExtensionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::MozillaSidebarExtension, thisObj );
+ MozillaSidebarExtension *mse = static_cast<MozillaSidebarExtension*>(thisObj.imp());
+
+ KHTMLPart *part = mse->part();
+ if (!part)
+ return Undefined();
+
+ // addPanel() id == 0
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (ext) {
+ TQString url, name;
+ if (args.size() == 1) { // I've seen this, don't know if it's legal.
+ name = TQString::null;
+ url = args[0].toString(exec).qstring();
+ } else if (args.size() == 2 || args.size() == 3) {
+ name = args[0].toString(exec).qstring();
+ url = args[1].toString(exec).qstring();
+ // 2 is the "CURL" which I don't understand and don't think we need.
+ } else {
+ return Boolean(false);
+ }
+ emit ext->addWebSideBar(KURL( url ), name);
+ return Boolean(true);
+ }
+
+ return Undefined();
+}
+
+
diff --git a/tdehtml/ecma/kjs_mozilla.h b/tdehtml/ecma/kjs_mozilla.h
new file mode 100644
index 000000000..220094f63
--- /dev/null
+++ b/tdehtml/ecma/kjs_mozilla.h
@@ -0,0 +1,44 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 George Staikos (staikos@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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_MOZILLA_H_
+#define _KJS_MOZILLA_H_
+
+#include <kjs/object.h>
+
+class KHTMLPart;
+
+namespace KJS {
+
+ class MozillaSidebarExtension : public ObjectImp {
+ public:
+ MozillaSidebarExtension(ExecState *exec, KHTMLPart *p);
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { addPanel };
+ KHTMLPart *part() const { return m_part; }
+ private:
+ KHTMLPart *m_part;
+ };
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_navigator.cpp b/tdehtml/ecma/kjs_navigator.cpp
new file mode 100644
index 000000000..222ef7902
--- /dev/null
+++ b/tdehtml/ecma/kjs_navigator.cpp
@@ -0,0 +1,670 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (c) 2000 Daniel Molkentin (molkentin@kde.org)
+ * Copyright (c) 2000 Stefan Schimanski (schimmi@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <klocale.h>
+
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <kio/kprotocolmanager.h>
+#include <kio/kmimetype.h>
+#include <kio/kservice.h>
+#include <kio/ktrader.h>
+#include "kjs_navigator.h"
+#include "kjs/lookup.h"
+#include "kjs_binding.h"
+#include "tdehtml_part.h"
+#include <sys/utsname.h>
+#include "kjs_navigator.lut.h"
+
+using namespace KJS;
+
+namespace KJS {
+
+ // All objects that need plugin info must inherit from PluginBase
+ // Its ctor and dtor take care of the refcounting on the static lists.
+ class PluginBase : public ObjectImp {
+ public:
+ PluginBase(ExecState *exec, bool loadPluginInfo);
+ virtual ~PluginBase();
+
+ struct MimeClassInfo;
+ struct PluginInfo;
+
+ struct MimeClassInfo {
+ TQString type;
+ TQString desc;
+ TQString suffixes;
+ PluginInfo *plugin;
+ };
+
+ struct PluginInfo {
+ TQString name;
+ TQString file;
+ TQString desc;
+ TQPtrList<MimeClassInfo> mimes;
+ };
+
+ static TQPtrList<PluginInfo> *plugins;
+ static TQPtrList<MimeClassInfo> *mimes;
+
+ private:
+ static int m_refCount;
+ };
+
+
+ class Plugins : public PluginBase {
+ public:
+ Plugins(ExecState *exec, bool pluginsEnabled)
+ : PluginBase(exec, pluginsEnabled),
+ m_pluginsEnabled(pluginsEnabled) {};
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ Value pluginByName( ExecState* exec, const TQString& name ) const;
+ bool pluginsEnabled() const { return m_pluginsEnabled; };
+ private:
+ bool m_pluginsEnabled;
+ };
+
+
+ class MimeTypes : public PluginBase {
+ public:
+ MimeTypes(ExecState *exec, bool pluginsEnabled)
+ : PluginBase(exec, pluginsEnabled),
+ m_pluginsEnabled(pluginsEnabled) {};
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ Value getValueProperty(ExecState *exec, int token) const;
+ Value mimeTypeByName( ExecState* exec, const TQString& name ) const;
+ bool pluginsEnabled() const { return m_pluginsEnabled; };
+ private:
+ bool m_pluginsEnabled;
+ };
+
+
+ class Plugin : public PluginBase {
+ public:
+ Plugin( ExecState *exec, PluginBase::PluginInfo *info )
+ : PluginBase( exec, true )
+ { m_info = info; };
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ Value mimeByName(ExecState* exec, const TQString& name ) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ PluginBase::PluginInfo *pluginInfo() const { return m_info; }
+ private:
+ PluginBase::PluginInfo *m_info;
+ };
+
+
+ class MimeType : public PluginBase {
+ public:
+ MimeType( ExecState *exec, PluginBase::MimeClassInfo *info )
+ : PluginBase( exec, true )
+ { m_info = info; };
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ Value getValueProperty(ExecState *exec, int token) const;
+ private:
+ PluginBase::MimeClassInfo *m_info;
+ };
+
+}
+
+
+TQPtrList<PluginBase::PluginInfo> *KJS::PluginBase::plugins = 0;
+TQPtrList<PluginBase::MimeClassInfo> *KJS::PluginBase::mimes = 0;
+int KJS::PluginBase::m_refCount = 0;
+
+const ClassInfo Navigator::info = { "Navigator", 0, &NavigatorTable, 0 };
+/*
+@begin NavigatorTable 12
+ appCodeName Navigator::AppCodeName DontDelete|ReadOnly
+ appName Navigator::AppName DontDelete|ReadOnly
+ appVersion Navigator::AppVersion DontDelete|ReadOnly
+ language Navigator::Language DontDelete|ReadOnly
+ userAgent Navigator::UserAgent DontDelete|ReadOnly
+ userLanguage Navigator::UserLanguage DontDelete|ReadOnly
+ browserLanguage Navigator::BrowserLanguage DontDelete|ReadOnly
+ platform Navigator::Platform DontDelete|ReadOnly
+ cpuClass Navigator::CpuClass DontDelete|ReadOnly
+ plugins Navigator::_Plugins DontDelete|ReadOnly
+ mimeTypes Navigator::_MimeTypes DontDelete|ReadOnly
+ product Navigator::Product DontDelete|ReadOnly
+ vendor Navigator::Vendor DontDelete|ReadOnly
+ productSub Navigator::ProductSub DontDelete|ReadOnly
+ cookieEnabled Navigator::CookieEnabled DontDelete|ReadOnly
+ javaEnabled Navigator::JavaEnabled DontDelete|Function 0
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(NavigatorFunc)
+
+Navigator::Navigator(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), m_part(p) { }
+
+Value Navigator::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Navigator::get " << propertyName.ascii() << endl;
+#endif
+ return lookupGet<NavigatorFunc,Navigator,ObjectImp>(exec,propertyName,&NavigatorTable,this);
+}
+
+Value Navigator::getValueProperty(ExecState *exec, int token) const
+{
+ KURL url = m_part->url();
+ TQString userAgent = url.host();
+ if (userAgent.isEmpty())
+ userAgent = "localhost";
+ userAgent = KProtocolManager::userAgentForHost(userAgent);
+ switch (token) {
+ case AppCodeName:
+ return String("Mozilla");
+ case AppName:
+ // If we find "Mozilla" but not "(compatible, ...)" we are a real Netscape
+ if (userAgent.find(TQString::fromLatin1("Mozilla")) >= 0 &&
+ userAgent.find(TQString::fromLatin1("compatible")) == -1)
+ {
+ //kdDebug() << "appName -> Mozilla" << endl;
+ return String("Netscape");
+ }
+ if (userAgent.find(TQString::fromLatin1("Microsoft")) >= 0 ||
+ userAgent.find(TQString::fromLatin1("MSIE")) >= 0)
+ {
+ //kdDebug() << "appName -> IE" << endl;
+ return String("Microsoft Internet Explorer");
+ }
+ //kdDebug() << "appName -> Konqueror" << endl;
+ return String("Konqueror");
+ case AppVersion:
+ // We assume the string is something like Mozilla/version (properties)
+ return String(userAgent.mid(userAgent.find('/') + 1));
+ case Product:
+ // We are pretending to be Mozilla or Safari
+ if (userAgent.find(TQString::fromLatin1("Mozilla")) >= 0 &&
+ userAgent.find(TQString::fromLatin1("compatible")) == -1)
+ {
+ return String("Gecko");
+ }
+ // When spoofing as IE, we use Undefined().
+ if (userAgent.find(TQString::fromLatin1("Microsoft")) >= 0 ||
+ userAgent.find(TQString::fromLatin1("MSIE")) >= 0)
+ {
+ return Undefined();
+ }
+ // We are acting straight
+ return String("Konqueror/tdehtml");
+ case ProductSub:
+ {
+ int ix = userAgent.find("Gecko");
+ if (ix >= 0 && userAgent.length() >= (uint)ix+14 && userAgent.unicode()[ix+5] == TQChar('/') &&
+ userAgent.find(TQRegExp("\\d{8}"), ix+6) == ix+6)
+ {
+ // We have Gecko/<productSub> in the UA string
+ return String(userAgent.mid(ix+6, 8));
+ }
+ else if (ix >= 0)
+ {
+ return String("20040107");
+ }
+ }
+ return Undefined();
+ case Vendor:
+ return String("KDE");
+ case BrowserLanguage:
+ case Language:
+ case UserLanguage:
+ return String(TDEGlobal::locale()->language());
+ case UserAgent:
+ return String(userAgent);
+ case Platform:
+ // yet another evil hack, but necessary to spoof some sites...
+ if ( (userAgent.find(TQString::fromLatin1("Win"),0,false)>=0) )
+ return String(TQString::fromLatin1("Win32"));
+ else if ( (userAgent.find(TQString::fromLatin1("Macintosh"),0,false)>=0) ||
+ (userAgent.find(TQString::fromLatin1("Mac_PowerPC"),0,false)>=0) )
+ return String(TQString::fromLatin1("MacPPC"));
+ else
+ {
+ struct utsname name;
+ int ret = uname(&name);
+ if ( ret >= 0 )
+ return String(TQString(TQString::fromLatin1("%1 %1 X11").arg(name.sysname).arg(name.machine)));
+ else // can't happen
+ return String(TQString(TQString::fromLatin1("Unix X11")));
+ }
+ case CpuClass:
+ {
+ struct utsname name;
+ int ret = uname(&name);
+ if ( ret >= 0 )
+ return String(name.machine);
+ else // can't happen
+ return String("x86");
+ }
+ case _Plugins:
+ return Value(new Plugins(exec, m_part->pluginsEnabled()));
+ case _MimeTypes:
+ return Value(new MimeTypes(exec, m_part->pluginsEnabled()));
+ case CookieEnabled:
+ return Boolean(true); /// ##### FIXME
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+/*******************************************************************/
+
+PluginBase::PluginBase(ExecState *exec, bool loadPluginInfo)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype() )
+{
+ if ( loadPluginInfo && !plugins ) {
+ plugins = new TQPtrList<PluginInfo>;
+ mimes = new TQPtrList<MimeClassInfo>;
+ plugins->setAutoDelete( true );
+ mimes->setAutoDelete( true );
+
+ // read in using KTrader
+ KTrader::OfferList offers = KTrader::self()->query("Browser/View");
+ KTrader::OfferList::iterator it;
+ for ( it = offers.begin(); it != offers.end(); ++it ) {
+
+ TQVariant pluginsinfo = (**it).property( "X-TDE-BrowserView-PluginsInfo" );
+ if ( !pluginsinfo.isValid() ) {
+ // <backwards compatible>
+ if ((**it).library() == TQString("libnsplugin"))
+ pluginsinfo = TQVariant("nsplugins/pluginsinfo");
+ else
+ // </backwards compatible>
+ continue;
+ }
+ // read configuration
+ TDEConfig kc( locate ("data", pluginsinfo.toString()) );
+ unsigned num = (unsigned int) kc.readNumEntry("number");
+ for ( unsigned n = 0; n < num; n++ ) {
+ kc.setGroup( TQString::number(n) );
+ PluginInfo *plugin = new PluginInfo;
+
+ plugin->name = kc.readEntry("name");
+ plugin->file = kc.readPathEntry("file");
+ plugin->desc = kc.readEntry("description");
+
+ plugins->append( plugin );
+
+ // get mime types from string
+ TQStringList types = TQStringList::split( ';', kc.readEntry("mime") );
+ TQStringList::Iterator type;
+ for ( type=types.begin(); type!=types.end(); ++type ) {
+
+ // get mime information
+ TQStringList tokens = TQStringList::split(':', *type, true);
+ if ( tokens.count() < 3 ) // we need 3 items
+ continue;
+
+ MimeClassInfo *mime = new MimeClassInfo;
+ TQStringList::Iterator token = tokens.begin();
+ mime->type = (*token).lower();
+ //kdDebug(6070) << "mime->type=" << mime->type << endl;
+ ++token;
+
+ mime->suffixes = *token;
+ ++token;
+
+ mime->desc = *token;
+ ++token;
+
+ mime->plugin = plugin;
+
+ mimes->append( mime );
+ plugin->mimes.append( mime );
+
+ }
+ }
+ }
+ }
+
+ m_refCount++;
+}
+
+PluginBase::~PluginBase()
+{
+ m_refCount--;
+ if ( m_refCount==0 ) {
+ delete plugins;
+ delete mimes;
+ plugins = 0;
+ mimes = 0;
+ }
+}
+
+
+/*******************************************************************/
+
+const ClassInfo Plugins::info = { "PluginArray", 0, &PluginsTable, 0 };
+/*
+@begin PluginsTable 4
+ length Plugins_Length DontDelete|ReadOnly
+ refresh Plugins_Refresh DontDelete|Function 0
+ item Plugins_Item DontDelete|Function 1
+ namedItem Plugins_NamedItem DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(PluginsFunc)
+
+Value Plugins::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Plugins::get " << propertyName.qstring() << endl;
+#endif
+ if (!pluginsEnabled()) {
+ if (propertyName == lengthPropertyName )
+ return Number(0);
+ } else {
+ if ( propertyName == lengthPropertyName )
+ return Number(plugins->count());
+
+ // plugins[#]
+ bool ok;
+ unsigned int i = propertyName.toULong(&ok);
+ if( ok && i<plugins->count() )
+ return Value( new Plugin( exec, plugins->at(i) ) );
+
+ // plugin[name]
+ Value val = pluginByName( exec, propertyName.qstring() );
+ if (!val.isA(UndefinedType))
+ return val;
+ }
+
+ return lookupGet<PluginsFunc,Plugins,ObjectImp>(exec,propertyName,&PluginsTable,this);
+}
+
+Value Plugins::pluginByName( ExecState* exec, const TQString& name ) const
+{
+ Q_ASSERT(plugins);
+ for ( PluginInfo *pl = plugins->first(); pl!=0; pl = plugins->next() ) {
+ if ( pl->name == name )
+ return Value( new Plugin( exec, pl ) );
+ }
+ return Undefined();
+}
+
+Value Plugins::getValueProperty(ExecState* /*exec*/, int token) const
+{
+ kdDebug(6070) << "WARNING: Unhandled token in Plugins::getValueProperty : " << token << endl;
+ return Undefined();
+}
+
+Value PluginsFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::Plugins, thisObj );
+ KJS::Plugins* base = static_cast<KJS::Plugins *>(thisObj.imp());
+ if (!base->pluginsEnabled()) {
+ if (id == Plugins_Refresh || //## TODO
+ id == Plugins_Item ||
+ id == Plugins_NamedItem)
+ return Undefined();
+ } else {
+ switch( id ) {
+ case Plugins_Refresh:
+ return Undefined(); //## TODO
+ case Plugins_Item:
+ {
+ bool ok;
+ unsigned int i = args[0].toString(exec).toArrayIndex(&ok);
+ if( ok && i<base->plugins->count() )
+ return Value( new Plugin( exec, base->plugins->at(i) ) );
+ return Undefined();
+ }
+ case Plugins_NamedItem:
+ UString s = args[0].toString(exec);
+ return base->pluginByName( exec, s.qstring() );
+ }
+ }
+ kdDebug(6070) << "WARNING: Unhandled token in PluginsFunc::tryCall : " << id << endl;
+ return Undefined();
+}
+
+/*******************************************************************/
+
+const ClassInfo MimeTypes::info = { "MimeTypeArray", 0, &MimeTypesTable, 0 };
+/*
+@begin MimeTypesTable 3
+ length MimeTypes_Length DontDelete|ReadOnly
+ item MimeTypes_Item DontDelete|Function 1
+ namedItem MimeTypes_NamedItem DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(MimeTypesFunc)
+
+Value MimeTypes::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "MimeTypes::get " << propertyName.qstring() << endl;
+#endif
+ if (!pluginsEnabled()) {
+ if (propertyName == lengthPropertyName )
+ return Number(0);
+ } else {
+ if( propertyName==lengthPropertyName )
+ return Number( mimes->count() );
+
+ // mimeTypes[#]
+ bool ok;
+ unsigned int i = propertyName.toULong(&ok);
+ if( ok && i<mimes->count() )
+ return Value( new MimeType( exec, mimes->at(i) ) );
+
+ // mimeTypes[name]
+ Value val = mimeTypeByName( exec, propertyName.qstring() );
+ if (!val.isA(UndefinedType))
+ return val;
+ }
+
+ return lookupGet<MimeTypesFunc,MimeTypes,ObjectImp>(exec,propertyName,&MimeTypesTable,this);
+}
+
+Value MimeTypes::mimeTypeByName( ExecState* exec, const TQString& name ) const
+{
+ //kdDebug(6070) << "MimeTypes[" << name << "]" << endl;
+ Q_ASSERT(mimes);
+ for ( MimeClassInfo *m = mimes->first(); m!=0; m = mimes->next() ) {
+ if ( m->type == name )
+ return Value( new MimeType( exec, m ) );
+ }
+ return Undefined();
+}
+
+Value MimeTypes::getValueProperty(ExecState* /*exec*/, int token) const
+{
+ kdDebug(6070) << "WARNING: Unhandled token in MimeTypes::getValueProperty : " << token << endl;
+ return Undefined();
+}
+
+Value MimeTypesFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::MimeTypes, thisObj );
+ KJS::MimeTypes* base = static_cast<KJS::MimeTypes *>(thisObj.imp());
+ if (!base->pluginsEnabled()) {
+ if (id == MimeTypes_Item ||
+ id == MimeTypes_NamedItem)
+ return Undefined();
+ } else {
+ switch( id ) {
+ case MimeTypes_Item:
+ {
+ bool ok;
+ unsigned int i = args[0].toString(exec).toArrayIndex(&ok);
+ if( ok && i<base->mimes->count() )
+ return Value( new MimeType( exec, base->mimes->at(i) ) );
+ return Undefined();
+ }
+ case MimeTypes_NamedItem:
+ UString s = args[0].toString(exec);
+ return base->mimeTypeByName( exec, s.qstring() );
+ }
+ }
+ kdDebug(6070) << "WARNING: Unhandled token in MimeTypesFunc::tryCall : " << id << endl;
+ return Undefined();
+}
+
+/************************************************************************/
+const ClassInfo Plugin::info = { "Plugin", 0, &PluginTable, 0 };
+/*
+@begin PluginTable 7
+ name Plugin_Name DontDelete|ReadOnly
+ filename Plugin_FileName DontDelete|ReadOnly
+ description Plugin_Description DontDelete|ReadOnly
+ length Plugin_Length DontDelete|ReadOnly
+ item Plugin_Item DontDelete|Function 1
+ namedItem Plugin_NamedItem DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(PluginFunc)
+
+Value Plugin::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Plugin::get " << propertyName.qstring() << endl;
+#endif
+ if ( propertyName == lengthPropertyName )
+ return Number( m_info->mimes.count() );
+
+ // plugin[#]
+ bool ok;
+ unsigned int i = propertyName.toULong(&ok);
+ //kdDebug(6070) << "Plugin::get plugin[" << i << "]" << endl;
+ if( ok && i<m_info->mimes.count() )
+ {
+ //kdDebug(6070) << "returning mimetype " << m_info->mimes.at(i)->type << endl;
+ return Value(new MimeType(exec, m_info->mimes.at(i)));
+ }
+
+ // plugin["name"]
+ Value val = mimeByName( exec, propertyName.qstring() );
+ if (!val.isA(UndefinedType))
+ return val;
+
+ return lookupGet<PluginFunc,Plugin,ObjectImp>(exec, propertyName, &PluginTable, this );
+}
+
+Value Plugin::mimeByName(ExecState* exec, const TQString& name) const
+{
+ for ( PluginBase::MimeClassInfo *m = m_info->mimes.first();
+ m != 0; m = m_info->mimes.next() ) {
+ if ( m->type == name )
+ return Value(new MimeType(exec, m));
+ }
+ return Undefined();
+}
+
+Value Plugin::getValueProperty(ExecState* /*exec*/, int token) const
+{
+ switch( token ) {
+ case Plugin_Name:
+ return String( m_info->name );
+ case Plugin_FileName:
+ return String( m_info->file );
+ case Plugin_Description:
+ return String( m_info->desc );
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in Plugin::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+Value PluginFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::Plugin, thisObj );
+ KJS::Plugin* plugin = static_cast<KJS::Plugin *>(thisObj.imp());
+ switch( id ) {
+ case Plugin_Item:
+ {
+ bool ok;
+ unsigned int i = args[0].toString(exec).toArrayIndex(&ok);
+ if( ok && i< plugin->pluginInfo()->mimes.count() )
+ return Value( new MimeType( exec, plugin->pluginInfo()->mimes.at(i) ) );
+ return Undefined();
+ }
+ case Plugin_NamedItem:
+ {
+ UString s = args[0].toString(exec);
+ return plugin->mimeByName( exec, s.qstring() );
+ }
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in PluginFunc::tryCall : " << id << endl;
+ return Undefined();
+ }
+}
+
+/*****************************************************************************/
+
+const ClassInfo MimeType::info = { "MimeType", 0, &MimeTypeTable, 0 };
+/*
+@begin MimeTypeTable 4
+ description MimeType_Description DontDelete|ReadOnly
+ enabledPlugin MimeType_EnabledPlugin DontDelete|ReadOnly
+ suffixes MimeType_Suffixes DontDelete|ReadOnly
+ type MimeType_Type DontDelete|ReadOnly
+@end
+*/
+
+Value MimeType::get(ExecState *exec, const Identifier &propertyName) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "MimeType::get " << propertyName.qstring() << endl;
+#endif
+ return lookupGetValue<MimeType,ObjectImp>(exec, propertyName, &MimeTypeTable, this );
+}
+
+Value MimeType::getValueProperty(ExecState* exec, int token) const
+{
+ switch( token ) {
+ case MimeType_Type:
+ return String( m_info->type );
+ case MimeType_Suffixes:
+ return String( m_info->suffixes );
+ case MimeType_Description:
+ return String( m_info->desc );
+ case MimeType_EnabledPlugin:
+ return Value(new Plugin(exec, m_info->plugin));
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in MimeType::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+
+Value NavigatorFunc::tryCall(ExecState *exec, Object &thisObj, const List &)
+{
+ KJS_CHECK_THIS( KJS::Navigator, thisObj );
+ Navigator *nav = static_cast<Navigator *>(thisObj.imp());
+ // javaEnabled()
+ return Boolean(nav->part()->javaEnabled());
+}
diff --git a/tdehtml/ecma/kjs_navigator.h b/tdehtml/ecma/kjs_navigator.h
new file mode 100644
index 000000000..ccd1ba63b
--- /dev/null
+++ b/tdehtml/ecma/kjs_navigator.h
@@ -0,0 +1,53 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_NAVIGATOR_H_
+#define _KJS_NAVIGATOR_H_
+
+#include <kjs/object.h>
+
+class KHTMLPart;
+
+namespace KJS {
+
+ class Navigator : public ObjectImp {
+ public:
+ Navigator(ExecState *exec, KHTMLPart *p);
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { AppCodeName, AppName, AppVersion, Language, UserAgent, UserLanguage, Platform,
+ _Plugins, _MimeTypes, Product, ProductSub, Vendor, CookieEnabled, JavaEnabled,
+ BrowserLanguage, CpuClass };
+ KHTMLPart *part() const { return m_part; }
+ private:
+ KHTMLPart *m_part;
+ };
+
+ // Hashtable enums
+ enum { Plugins_Refresh, Plugins_Length, Plugins_Item, Plugins_NamedItem };
+ enum { MimeTypes_Length, MimeTypes_Item, MimeTypes_NamedItem };
+ enum { Plugin_Name, Plugin_FileName, Plugin_Description, Plugin_Length, Plugin_Item, Plugin_NamedItem };
+ enum { MimeType_Type, MimeType_Description, MimeType_EnabledPlugin, MimeType_Suffixes };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_proxy.cpp b/tdehtml/ecma/kjs_proxy.cpp
new file mode 100644
index 000000000..cc7afa00a
--- /dev/null
+++ b/tdehtml/ecma/kjs_proxy.cpp
@@ -0,0 +1,411 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001,2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2001-2003 David Faure (faure@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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG)
+
+#include <valgrind/memcheck.h>
+#define VALGRIND_SUPPORT
+
+#endif
+
+
+#include "kjs_proxy.h"
+
+#include "kjs_window.h"
+#include "kjs_events.h"
+#include "kjs_debugwin.h"
+#include "xml/dom_nodeimpl.h"
+#include "tdehtmlpart_p.h"
+#include <tdehtml_part.h>
+#include <kprotocolmanager.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <assert.h>
+#include <kjs/function.h>
+
+using namespace KJS;
+
+extern "C" {
+ KJSProxy *kjs_html_init(tdehtml::ChildFrame *childframe);
+}
+
+namespace KJS {
+
+class KJSProxyImpl : public KJSProxy {
+public:
+ KJSProxyImpl(tdehtml::ChildFrame *frame);
+ virtual ~KJSProxyImpl();
+ virtual TQVariant evaluate(TQString filename, int baseLine, const TQString &, const DOM::Node &n,
+ Completion *completion = 0);
+ virtual void clear();
+ virtual DOM::EventListener *createHTMLEventHandler(TQString sourceUrl, TQString name, TQString code, DOM::NodeImpl *node);
+ virtual void finishedWithEvent(const DOM::Event &event);
+ virtual KJS::Interpreter *interpreter();
+
+ virtual void setDebugEnabled(bool enabled);
+ virtual void showDebugWindow(bool show=true);
+ virtual bool paused() const;
+ virtual void dataReceived();
+
+ void initScript();
+ void applyUserAgent();
+
+private:
+ KJS::ScriptInterpreter* m_script;
+ bool m_debugEnabled;
+#ifndef NDEBUG
+ static int s_count;
+#endif
+};
+
+} // namespace KJS
+
+#ifndef NDEBUG
+int KJSProxyImpl::s_count = 0;
+#endif
+
+KJSProxyImpl::KJSProxyImpl(tdehtml::ChildFrame *frame)
+{
+ m_script = 0;
+ m_frame = frame;
+ m_debugEnabled = false;
+#ifndef NDEBUG
+ s_count++;
+#endif
+}
+
+KJSProxyImpl::~KJSProxyImpl()
+{
+ if ( m_script ) {
+ //kdDebug() << "KJSProxyImpl::~KJSProxyImpl clearing global object " << m_script->globalObject().imp() << endl;
+ // This allows to delete the global-object properties, like all the protos
+ static_cast<ObjectImp*>(m_script->globalObject().imp())->deleteAllProperties( m_script->globalExec() );
+ //kdDebug() << "KJSProxyImpl::~KJSProxyImpl garbage collecting" << endl;
+ while (KJS::Interpreter::collect())
+ ;
+ //kdDebug() << "KJSProxyImpl::~KJSProxyImpl deleting interpreter " << m_script << endl;
+ delete m_script;
+ //kdDebug() << "KJSProxyImpl::~KJSProxyImpl garbage collecting again" << endl;
+ // Garbage collect - as many times as necessary
+ // (we could delete an object which was holding another object, so
+ // the deref() will happen too late for deleting the impl of the 2nd object).
+ while (KJS::Interpreter::collect())
+ ;
+ }
+
+#ifndef NDEBUG
+ s_count--;
+ // If it was the last interpreter, we should have nothing left
+#ifdef KJS_DEBUG_MEM
+ if ( s_count == 0 )
+ Interpreter::finalCheck();
+#endif
+#endif
+}
+
+TQVariant KJSProxyImpl::evaluate(TQString filename, int baseLine,
+ const TQString&str, const DOM::Node &n, Completion *completion) {
+ // evaluate code. Returns the JS return value or an invalid QVariant
+ // if there was none, an error occurred or the type couldn't be converted.
+
+ initScript();
+ // inlineCode is true for <a href="javascript:doSomething()">
+ // and false for <script>doSomething()</script>. Check if it has the
+ // expected value in all cases.
+ // See smart window.open policy for where this is used.
+ bool inlineCode = filename.isNull();
+ //kdDebug(6070) << "KJSProxyImpl::evaluate inlineCode=" << inlineCode << endl;
+
+#ifdef KJS_DEBUGGER
+ if (inlineCode)
+ filename = "(unknown file)";
+ if (KJSDebugWin::debugWindow()) {
+ KJSDebugWin::debugWindow()->attach(m_script);
+ KJSDebugWin::debugWindow()->setNextSourceInfo(filename,baseLine);
+ // KJSDebugWin::debugWindow()->setMode(KJSDebugWin::Step);
+ }
+#else
+ Q_UNUSED(baseLine);
+#endif
+
+ m_script->setInlineCode(inlineCode);
+ Window* window = Window::retrieveWindow( m_frame->m_part );
+ KJS::Value thisNode = n.isNull() ? Window::retrieve( m_frame->m_part ) : getDOMNode(m_script->globalExec(),n);
+
+ UString code( str );
+
+ KJSCPUGuard guard;
+ guard.start();
+ Completion comp = m_script->evaluate(code, thisNode);
+ guard.stop();
+
+ bool success = ( comp.complType() == Normal ) || ( comp.complType() == ReturnValue );
+
+ if (completion)
+ *completion = comp;
+
+#ifdef KJS_DEBUGGER
+ // KJSDebugWin::debugWindow()->setCode(TQString::null);
+#endif
+
+ window->afterScriptExecution();
+
+ // let's try to convert the return value
+ if (success && comp.value().isValid())
+ return ValueToVariant( m_script->globalExec(), comp.value());
+ else
+ {
+ if ( comp.complType() == Throw )
+ {
+ UString msg = comp.value().toString(m_script->globalExec());
+ kdDebug(6070) << "WARNING: Script threw exception: " << msg.qstring() << endl;
+ }
+ return TQVariant();
+ }
+}
+
+// Implementation of the debug() function
+class TestFunctionImp : public ObjectImp {
+public:
+ TestFunctionImp() : ObjectImp() {}
+ virtual bool implementsCall() const { return true; }
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+};
+
+Value TestFunctionImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ fprintf(stderr,"--> %s\n",args[0].toString(exec).ascii());
+ return Undefined();
+}
+
+void KJSProxyImpl::clear() {
+ // clear resources allocated by the interpreter, and make it ready to be used by another page
+ // We have to keep it, so that the Window object for the part remains the same.
+ // (we used to delete and re-create it, previously)
+ if (m_script) {
+#ifdef KJS_DEBUGGER
+ // ###
+ KJSDebugWin *debugWin = KJSDebugWin::debugWindow();
+ if (debugWin) {
+ if (debugWin->getExecState() &&
+ debugWin->getExecState()->interpreter() == m_script)
+ debugWin->slotStop();
+ debugWin->clearInterpreter(m_script);
+ }
+#endif
+ m_script->clear();
+
+ Window *win = static_cast<Window *>(m_script->globalObject().imp());
+ if (win) {
+ win->clear( m_script->globalExec() );
+ // re-add "debug", clear() removed it
+ m_script->globalObject().put(m_script->globalExec(),
+ "debug", Value(new TestFunctionImp()), Internal);
+ if ( win->part() )
+ applyUserAgent();
+ }
+
+ // Really delete everything that can be, so that the DOM nodes get deref'ed
+ //kdDebug() << k_funcinfo << "all done -> collecting" << endl;
+ while (KJS::Interpreter::collect())
+ ;
+ }
+}
+
+DOM::EventListener *KJSProxyImpl::createHTMLEventHandler(TQString sourceUrl, TQString name, TQString code, DOM::NodeImpl *node)
+{
+ initScript();
+
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow()) {
+ KJSDebugWin::debugWindow()->attach(m_script);
+ KJSDebugWin::debugWindow()->setNextSourceInfo(sourceUrl,m_handlerLineno);
+ }
+#else
+ Q_UNUSED(sourceUrl);
+#endif
+
+ return KJS::Window::retrieveWindow(m_frame->m_part)->getJSLazyEventListener(code,name,node);
+}
+
+void KJSProxyImpl::finishedWithEvent(const DOM::Event &event)
+{
+ // This is called when the DOM implementation has finished with a particular event. This
+ // is the case in sitations where an event has been created just for temporary usage,
+ // e.g. an image load or mouse move. Once the event has been dispatched, it is forgotten
+ // by the DOM implementation and so does not need to be cached still by the interpreter
+ ScriptInterpreter::forgetDOMObject(event.handle());
+}
+
+KJS::Interpreter *KJSProxyImpl::interpreter()
+{
+ if (!m_script)
+ initScript();
+ return m_script;
+}
+
+void KJSProxyImpl::setDebugEnabled(bool enabled)
+{
+#ifdef KJS_DEBUGGER
+ m_debugEnabled = enabled;
+ //if (m_script)
+ // m_script->setDebuggingEnabled(enabled);
+ // NOTE: this is consistent across all KJSProxyImpl instances, as we only
+ // ever have 1 debug window
+ if (!enabled && KJSDebugWin::debugWindow()) {
+ KJSDebugWin::destroyInstance();
+ }
+ else if (enabled && !KJSDebugWin::debugWindow()) {
+ KJSDebugWin::createInstance();
+ initScript();
+ KJSDebugWin::debugWindow()->attach(m_script);
+ }
+#else
+ Q_UNUSED(enabled);
+#endif
+}
+
+void KJSProxyImpl::showDebugWindow(bool /*show*/)
+{
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow())
+ KJSDebugWin::debugWindow()->show();
+#else
+ //Q_UNUSED(show);
+#endif
+}
+
+bool KJSProxyImpl::paused() const
+{
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow())
+ return KJSDebugWin::debugWindow()->inSession();
+#endif
+ return false;
+}
+
+void KJSProxyImpl::dataReceived()
+{
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow() && m_frame->m_part)
+ KJSDebugWin::debugWindow()->sourceChanged(m_script,m_frame->m_part->url().url());
+#endif
+}
+
+void KJSProxyImpl::initScript()
+{
+ if (m_script)
+ return;
+
+ // Build the global object - which is a Window instance
+ Object globalObject( new Window(m_frame) );
+
+ // Create a KJS interpreter for this part
+ m_script = new KJS::ScriptInterpreter(globalObject, m_frame);
+ static_cast<ObjectImp*>(globalObject.imp())->setPrototype(m_script->builtinObjectPrototype());
+
+#ifdef KJS_DEBUGGER
+ //m_script->setDebuggingEnabled(m_debugEnabled);
+#endif
+ //m_script->enableDebug();
+ globalObject.put(m_script->globalExec(),
+ "debug", Value(new TestFunctionImp()), Internal);
+ applyUserAgent();
+}
+
+void KJSProxyImpl::applyUserAgent()
+{
+ assert( m_script );
+ TQString host = m_frame->m_part->url().isLocalFile() ? "localhost" : m_frame->m_part->url().host();
+ TQString userAgent = KProtocolManager::userAgentForHost(host);
+ if (userAgent.find(TQString::fromLatin1("Microsoft")) >= 0 ||
+ userAgent.find(TQString::fromLatin1("MSIE")) >= 0)
+ {
+ m_script->setCompatMode(Interpreter::IECompat);
+#ifdef KJS_VERBOSE
+ kdDebug() << "Setting IE compat mode" << endl;
+#endif
+ }
+ else
+ // If we find "Mozilla" but not "(compatible, ...)" we are a real Netscape
+ if (userAgent.find(TQString::fromLatin1("Mozilla")) >= 0 &&
+ userAgent.find(TQString::fromLatin1("compatible")) == -1 &&
+ userAgent.find(TQString::fromLatin1("KHTML")) == -1)
+ {
+ m_script->setCompatMode(Interpreter::NetscapeCompat);
+#ifdef KJS_VERBOSE
+ kdDebug() << "Setting NS compat mode" << endl;
+#endif
+ }
+}
+
+// Helper method, so that all classes which need jScript() don't need to be added
+// as friend to KHTMLPart
+KJSProxy * KJSProxy::proxy( KHTMLPart *part )
+{
+ return part->jScript();
+}
+
+// initialize HTML module
+KJSProxy *kjs_html_init(tdehtml::ChildFrame *childframe)
+{
+ return new KJSProxyImpl(childframe);
+}
+
+void KJSCPUGuard::start(unsigned int ms, unsigned int i_ms)
+{
+#ifdef VALGRIND_SUPPORT
+ if (RUNNING_ON_VALGRIND) {
+ ms *= 50;
+ i_ms *= 50;
+ }
+#endif
+
+ oldAlarmHandler = signal(SIGVTALRM, alarmHandler);
+ itimerval tv = {
+ { i_ms / 1000, (i_ms % 1000) * 1000 },
+ { ms / 1000, (ms % 1000) * 1000 }
+ };
+ setitimer(ITIMER_VIRTUAL, &tv, &oldtv);
+}
+
+void KJSCPUGuard::stop()
+{
+ setitimer(ITIMER_VIRTUAL, &oldtv, 0L);
+ signal(SIGVTALRM, oldAlarmHandler);
+}
+
+bool KJSCPUGuard::confirmTerminate() {
+ kdDebug(6070) << "alarmhandler" << endl;
+ return KMessageBox::warningYesNo(0L, i18n("A script on this page is causing KHTML to freeze. If it continues to run, other applications may become less responsive.\nDo you want to abort the script?"), i18n("JavaScript"), i18n("&Abort"), KStdGuiItem::cont(), "kjscupguard_alarmhandler") == KMessageBox::Yes;
+}
+
+void KJSCPUGuard::alarmHandler(int) {
+ ExecState::requestTerminate();
+ ExecState::confirmTerminate = KJSCPUGuard::confirmTerminate;
+}
diff --git a/tdehtml/ecma/kjs_proxy.h b/tdehtml/ecma/kjs_proxy.h
new file mode 100644
index 000000000..5ea2d5bf6
--- /dev/null
+++ b/tdehtml/ecma/kjs_proxy.h
@@ -0,0 +1,91 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_PROXY_H_
+#define _KJS_PROXY_H_
+
+#include <tqvariant.h>
+#include <tqstring.h>
+#include <sys/time.h>
+
+class KHTMLPart;
+
+namespace DOM {
+ class Node;
+ class NodeImpl;
+ class EventListener;
+ class Event;
+}
+
+namespace KJS {
+ class List;
+ class Interpreter;
+ class Completion;
+ class KJSDebugWin;
+}
+
+namespace tdehtml {
+ class ChildFrame;
+}
+
+/**
+ * @internal
+ *
+ * @short Proxy class serving as interface when being dlopen'ed.
+ */
+class KJSProxy {
+public:
+ KJSProxy() { m_handlerLineno = 0; }
+ virtual ~KJSProxy() { }
+ virtual TQVariant evaluate(TQString filename, int baseLine, const TQString &, const DOM::Node &n,
+ KJS::Completion *completion = 0) = 0;
+ virtual void clear() = 0;
+ virtual DOM::EventListener *createHTMLEventHandler(TQString sourceUrl, TQString name, TQString code, DOM::NodeImpl* node) = 0;
+ virtual void finishedWithEvent(const DOM::Event &event) = 0;
+ virtual KJS::Interpreter *interpreter() = 0;
+
+ virtual void setDebugEnabled(bool enabled) = 0;
+ virtual void showDebugWindow(bool show=true) = 0;
+ virtual bool paused() const = 0;
+ virtual void dataReceived() = 0;
+
+ void setEventHandlerLineno(int lineno) { m_handlerLineno = lineno; }
+
+ tdehtml::ChildFrame *m_frame;
+ int m_handlerLineno;
+
+ // Helper method, to access the private KHTMLPart::jScript()
+ static KJSProxy *proxy( KHTMLPart *part );
+};
+
+class KJSCPUGuard {
+public:
+ KJSCPUGuard() {}
+ void start(unsigned int msec=5000, unsigned int i_msec=10000);
+ void stop();
+private:
+ void (*oldAlarmHandler)(int);
+ static void alarmHandler(int);
+ static bool confirmTerminate();
+ itimerval oldtv;
+};
+
+#endif
diff --git a/tdehtml/ecma/kjs_range.cpp b/tdehtml/ecma/kjs_range.cpp
new file mode 100644
index 000000000..bf148ffe8
--- /dev/null
+++ b/tdehtml/ecma/kjs_range.cpp
@@ -0,0 +1,233 @@
+
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_range.h"
+#include "kjs_range.lut.h"
+#include <kdebug.h>
+
+namespace KJS {
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMRange::info = { "Range", 0, &DOMRangeTable, 0 };
+/*
+@begin DOMRangeTable 7
+ startContainer DOMRange::StartContainer DontDelete|ReadOnly
+ startOffset DOMRange::StartOffset DontDelete|ReadOnly
+ endContainer DOMRange::EndContainer DontDelete|ReadOnly
+ endOffset DOMRange::EndOffset DontDelete|ReadOnly
+ collapsed DOMRange::Collapsed DontDelete|ReadOnly
+ commonAncestorContainer DOMRange::CommonAncestorContainer DontDelete|ReadOnly
+@end
+@begin DOMRangeProtoTable 17
+setStart DOMRange::SetStart DontDelete|Function 2
+ setEnd DOMRange::SetEnd DontDelete|Function 2
+ setStartBefore DOMRange::SetStartBefore DontDelete|Function 1
+ setStartAfter DOMRange::SetStartAfter DontDelete|Function 1
+ setEndBefore DOMRange::SetEndBefore DontDelete|Function 1
+ setEndAfter DOMRange::SetEndAfter DontDelete|Function 1
+ collapse DOMRange::Collapse DontDelete|Function 1
+ selectNode DOMRange::SelectNode DontDelete|Function 1
+ selectNodeContents DOMRange::SelectNodeContents DontDelete|Function 1
+ compareBoundaryPoints DOMRange::CompareBoundaryPoints DontDelete|Function 2
+ deleteContents DOMRange::DeleteContents DontDelete|Function 0
+ extractContents DOMRange::ExtractContents DontDelete|Function 0
+ cloneContents DOMRange::CloneContents DontDelete|Function 0
+ insertNode DOMRange::InsertNode DontDelete|Function 1
+ surroundContents DOMRange::SurroundContents DontDelete|Function 1
+ cloneRange DOMRange::CloneRange DontDelete|Function 0
+ toString DOMRange::ToString DontDelete|Function 0
+ detach DOMRange::Detach DontDelete|Function 0
+ createContextualFragment DOMRange::CreateContextualFragment DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMRangeProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMRangeProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMRange",DOMRangeProto,DOMRangeProtoFunc)
+
+DOMRange::DOMRange(ExecState *exec, DOM::Range r)
+ : DOMObject(DOMRangeProto::self(exec)), range(r) {}
+
+DOMRange::~DOMRange()
+{
+ ScriptInterpreter::forgetDOMObject(range.handle());
+}
+
+Value DOMRange::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMRange,DOMObject>(exec,p,&DOMRangeTable,this);
+}
+
+Value DOMRange::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case StartContainer:
+ return getDOMNode(exec,range.startContainer());
+ case StartOffset:
+ return Number(range.startOffset());
+ case EndContainer:
+ return getDOMNode(exec,range.endContainer());
+ case EndOffset:
+ return Number(range.endOffset());
+ case Collapsed:
+ return Boolean(range.collapsed());
+ case CommonAncestorContainer: {
+ DOM::Range range2 = range; // avoid const error
+ return getDOMNode(exec,range2.commonAncestorContainer());
+ }
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMRange::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMRangeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMRange, thisObj );
+ DOM::Range range = static_cast<DOMRange *>(thisObj.imp())->toRange();
+ Value result;
+
+ switch (id) {
+ case DOMRange::SetStart:
+ range.setStart(toNode(args[0]),args[1].toInteger(exec));
+ result = Undefined();
+ break;
+ case DOMRange::SetEnd:
+ range.setEnd(toNode(args[0]),args[1].toInteger(exec));
+ result = Undefined();
+ break;
+ case DOMRange::SetStartBefore:
+ range.setStartBefore(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::SetStartAfter:
+ range.setStartAfter(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::SetEndBefore:
+ range.setEndBefore(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::SetEndAfter:
+ range.setEndAfter(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::Collapse:
+ range.collapse(args[0].toBoolean(exec));
+ result = Undefined();
+ break;
+ case DOMRange::SelectNode:
+ range.selectNode(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::SelectNodeContents:
+ range.selectNodeContents(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::CompareBoundaryPoints:
+ result = Number(range.compareBoundaryPoints(static_cast<DOM::Range::CompareHow>(args[0].toInteger(exec)),toRange(args[1])));
+ break;
+ case DOMRange::DeleteContents:
+ range.deleteContents();
+ result = Undefined();
+ break;
+ case DOMRange::ExtractContents:
+ result = getDOMNode(exec,range.extractContents());
+ break;
+ case DOMRange::CloneContents:
+ result = getDOMNode(exec,range.cloneContents());
+ break;
+ case DOMRange::InsertNode:
+ range.insertNode(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::SurroundContents:
+ range.surroundContents(toNode(args[0]));
+ result = Undefined();
+ break;
+ case DOMRange::CloneRange:
+ result = getDOMRange(exec,range.cloneRange());
+ break;
+ case DOMRange::ToString:
+ result = String(range.toString());
+ break;
+ case DOMRange::Detach:
+ range.detach();
+ result = Undefined();
+ break;
+ case DOMRange::CreateContextualFragment:
+ Value value = args[0];
+ DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
+ result = getDOMNode(exec, range.createContextualFragment(str));
+ break;
+ };
+
+ return result;
+}
+
+Value getDOMRange(ExecState *exec, DOM::Range r)
+{
+ return cacheDOMObject<DOM::Range, KJS::DOMRange>(exec, r);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo RangeConstructor::info = { "RangeConstructor", 0, &RangeConstructorTable, 0 };
+/*
+@begin RangeConstructorTable 5
+ START_TO_START DOM::Range::START_TO_START DontDelete|ReadOnly
+ START_TO_END DOM::Range::START_TO_END DontDelete|ReadOnly
+ END_TO_END DOM::Range::END_TO_END DontDelete|ReadOnly
+ END_TO_START DOM::Range::END_TO_START DontDelete|ReadOnly
+@end
+*/
+
+RangeConstructor::RangeConstructor(ExecState *exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()) { }
+
+Value RangeConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<RangeConstructor,DOMObject>(exec,p,&RangeConstructorTable,this);
+}
+
+Value RangeConstructor::getValueProperty(ExecState *, int token) const
+{
+ return Number(token);
+}
+
+Value getRangeConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<RangeConstructor>(exec, "[[range.constructor]]");
+}
+
+
+DOM::Range toRange(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMRange::info))
+ return DOM::Range();
+
+ const DOMRange *dobj = static_cast<const DOMRange*>(obj.imp());
+ return dobj->toRange();
+}
+
+} //namespace KJS
diff --git a/tdehtml/ecma/kjs_range.h b/tdehtml/ecma/kjs_range.h
new file mode 100644
index 000000000..fbf47020f
--- /dev/null
+++ b/tdehtml/ecma/kjs_range.h
@@ -0,0 +1,71 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_RANGE_H_
+#define _KJS_RANGE_H_
+
+#include "ecma/kjs_dom.h"
+#include "dom/dom2_range.h"
+
+namespace KJS {
+
+ class DOMRange : public DOMObject {
+ public:
+ DOMRange(ExecState *exec, DOM::Range r);
+ ~DOMRange();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { StartContainer, StartOffset, EndContainer, EndOffset, Collapsed,
+ CommonAncestorContainer,
+ SetStart, SetEnd, SetStartBefore, SetStartAfter, SetEndBefore,
+ SetEndAfter, Collapse, SelectNode, SelectNodeContents,
+ CompareBoundaryPoints, DeleteContents, ExtractContents,
+ CloneContents, InsertNode, SurroundContents, CloneRange, ToString,
+ Detach, CreateContextualFragment };
+ DOM::Range toRange() const { return range; }
+ protected:
+ DOM::Range range;
+ };
+
+ // Constructor object Range
+ class RangeConstructor : public DOMObject {
+ public:
+ RangeConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ Value getDOMRange(ExecState *exec, DOM::Range r);
+ Value getRangeConstructor(ExecState *exec);
+
+ /**
+ * Convert an object to a Range. Returns a null Node if not possible.
+ */
+ DOM::Range toRange(const Value&);
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_traversal.cpp b/tdehtml/ecma/kjs_traversal.cpp
new file mode 100644
index 000000000..b8b9e824a
--- /dev/null
+++ b/tdehtml/ecma/kjs_traversal.cpp
@@ -0,0 +1,327 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_traversal.h"
+#include "kjs_traversal.lut.h"
+#include "kjs_proxy.h"
+#include <dom/dom_node.h>
+#include <xml/dom_nodeimpl.h>
+#include <xml/dom_docimpl.h>
+#include <tdehtmlview.h>
+#include <tdehtml_part.h>
+#include <kdebug.h>
+
+namespace KJS {
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMNodeIterator::info = { "NodeIterator", 0, &DOMNodeIteratorTable, 0 };
+/*
+@begin DOMNodeIteratorTable 5
+ root DOMNodeIterator::Root DontDelete|ReadOnly
+ whatToShow DOMNodeIterator::WhatToShow DontDelete|ReadOnly
+ filter DOMNodeIterator::Filter DontDelete|ReadOnly
+ expandEntityReferences DOMNodeIterator::ExpandEntityReferences DontDelete|ReadOnly
+@end
+@begin DOMNodeIteratorProtoTable 3
+ nextNode DOMNodeIterator::NextNode DontDelete|Function 0
+ previousNode DOMNodeIterator::PreviousNode DontDelete|Function 0
+ detach DOMNodeIterator::Detach DontDelete|Function 0
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMNodeIteratorProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMNodeIteratorProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMNodeIterator", DOMNodeIteratorProto,DOMNodeIteratorProtoFunc)
+
+DOMNodeIterator::DOMNodeIterator(ExecState *exec, DOM::NodeIterator ni)
+ : DOMObject(DOMNodeIteratorProto::self(exec)), nodeIterator(ni) {}
+
+DOMNodeIterator::~DOMNodeIterator()
+{
+ ScriptInterpreter::forgetDOMObject(nodeIterator.handle());
+}
+
+Value DOMNodeIterator::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMNodeIterator,DOMObject>(exec,p,&DOMNodeIteratorTable,this);
+}
+
+Value DOMNodeIterator::getValueProperty(ExecState *exec, int token) const
+{
+ DOM::NodeIterator ni(nodeIterator);
+ switch (token) {
+ case Root:
+ return getDOMNode(exec,ni.root());
+ case WhatToShow:
+ return Number(ni.whatToShow());
+ case Filter:
+ return getDOMNodeFilter(exec,ni.filter());
+ case ExpandEntityReferences:
+ return Boolean(ni.expandEntityReferences());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMNodeIterator::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMNodeIteratorProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &)
+{
+ KJS_CHECK_THIS( KJS::DOMNodeIterator, thisObj );
+ DOM::NodeIterator nodeIterator = static_cast<DOMNodeIterator *>(thisObj.imp())->toNodeIterator();
+ switch (id) {
+ case DOMNodeIterator::PreviousNode:
+ return getDOMNode(exec,nodeIterator.previousNode());
+ case DOMNodeIterator::NextNode:
+ return getDOMNode(exec,nodeIterator.nextNode());
+ case DOMNodeIterator::Detach:
+ nodeIterator.detach();
+ return Undefined();
+ }
+ return Undefined();
+}
+
+Value getDOMNodeIterator(ExecState *exec, DOM::NodeIterator ni)
+{
+ return cacheDOMObject<DOM::NodeIterator, DOMNodeIterator>(exec, ni);
+}
+
+
+// -------------------------------------------------------------------------
+
+const ClassInfo NodeFilterConstructor::info = { "NodeFilterConstructor", 0, &NodeFilterConstructorTable, 0 };
+/*
+@begin NodeFilterConstructorTable 17
+ FILTER_ACCEPT DOM::NodeFilter::FILTER_ACCEPT DontDelete|ReadOnly
+ FILTER_REJECT DOM::NodeFilter::FILTER_REJECT DontDelete|ReadOnly
+ FILTER_SKIP DOM::NodeFilter::FILTER_SKIP DontDelete|ReadOnly
+ SHOW_ALL DOM::NodeFilter::SHOW_ALL DontDelete|ReadOnly
+ SHOW_ELEMENT DOM::NodeFilter::SHOW_ELEMENT DontDelete|ReadOnly
+ SHOW_ATTRIBUTE DOM::NodeFilter::SHOW_ATTRIBUTE DontDelete|ReadOnly
+ SHOW_TEXT DOM::NodeFilter::SHOW_TEXT DontDelete|ReadOnly
+ SHOW_CDATA_SECTION DOM::NodeFilter::SHOW_CDATA_SECTION DontDelete|ReadOnly
+ SHOW_ENTITY_REFERENCE DOM::NodeFilter::SHOW_ENTITY_REFERENCE DontDelete|ReadOnly
+ SHOW_ENTITY DOM::NodeFilter::SHOW_ENTITY DontDelete|ReadOnly
+ SHOW_PROCESSING_INSTRUCTION DOM::NodeFilter::SHOW_PROCESSING_INSTRUCTION DontDelete|ReadOnly
+ SHOW_COMMENT DOM::NodeFilter::SHOW_COMMENT DontDelete|ReadOnly
+ SHOW_DOCUMENT DOM::NodeFilter::SHOW_DOCUMENT DontDelete|ReadOnly
+ SHOW_DOCUMENT_TYPE DOM::NodeFilter::SHOW_DOCUMENT_TYPE DontDelete|ReadOnly
+ SHOW_DOCUMENT_FRAGMENT DOM::NodeFilter::SHOW_DOCUMENT_FRAGMENT DontDelete|ReadOnly
+ SHOW_NOTATION DOM::NodeFilter::SHOW_NOTATION DontDelete|ReadOnly
+@end
+*/
+
+NodeFilterConstructor::NodeFilterConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value NodeFilterConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<NodeFilterConstructor,DOMObject>(exec,p,&NodeFilterConstructorTable,this);
+}
+
+Value NodeFilterConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getNodeFilterConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<NodeFilterConstructor>(exec, "[[nodeFilter.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMNodeFilter::info = { "NodeFilter", 0, 0, 0 };
+/*
+@begin DOMNodeFilterProtoTable 1
+ acceptNode DOMNodeFilter::AcceptNode DontDelete|Function 0
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMNodeFilterProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMNodeFilterProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMNodeFilter",DOMNodeFilterProto,DOMNodeFilterProtoFunc)
+
+DOMNodeFilter::DOMNodeFilter(ExecState *exec, DOM::NodeFilter nf)
+ : DOMObject(DOMNodeFilterProto::self(exec)), nodeFilter(nf) {}
+
+DOMNodeFilter::~DOMNodeFilter()
+{
+ ScriptInterpreter::forgetDOMObject(nodeFilter.handle());
+}
+
+Value DOMNodeFilterProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMNodeFilter, thisObj );
+ DOM::NodeFilter nodeFilter = static_cast<DOMNodeFilter *>(thisObj.imp())->toNodeFilter();
+ switch (id) {
+ case DOMNodeFilter::AcceptNode:
+ return Number(nodeFilter.acceptNode(toNode(args[0])));
+ }
+ return Undefined();
+}
+
+Value getDOMNodeFilter(ExecState *exec, DOM::NodeFilter nf)
+{
+ return cacheDOMObject<DOM::NodeFilter, DOMNodeFilter>(exec, nf);
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMTreeWalker::info = { "TreeWalker", 0, &DOMTreeWalkerTable, 0 };
+/*
+@begin DOMTreeWalkerTable 5
+ root DOMTreeWalker::Root DontDelete|ReadOnly
+ whatToShow DOMTreeWalker::WhatToShow DontDelete|ReadOnly
+ filter DOMTreeWalker::Filter DontDelete|ReadOnly
+ expandEntityReferences DOMTreeWalker::ExpandEntityReferences DontDelete|ReadOnly
+ currentNode DOMTreeWalker::CurrentNode DontDelete
+@end
+@begin DOMTreeWalkerProtoTable 7
+ parentNode DOMTreeWalker::ParentNode DontDelete|Function 0
+ firstChild DOMTreeWalker::FirstChild DontDelete|Function 0
+ lastChild DOMTreeWalker::LastChild DontDelete|Function 0
+ previousSibling DOMTreeWalker::PreviousSibling DontDelete|Function 0
+ nextSibling DOMTreeWalker::NextSibling DontDelete|Function 0
+ previousNode DOMTreeWalker::PreviousNode DontDelete|Function 0
+ nextNode DOMTreeWalker::NextNode DontDelete|Function 0
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMTreeWalkerProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMTreeWalkerProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMTreeWalker", DOMTreeWalkerProto,DOMTreeWalkerProtoFunc)
+
+DOMTreeWalker::DOMTreeWalker(ExecState *exec, DOM::TreeWalker tw)
+ : DOMObject(DOMTreeWalkerProto::self(exec)), treeWalker(tw) {}
+
+DOMTreeWalker::~DOMTreeWalker()
+{
+ ScriptInterpreter::forgetDOMObject(treeWalker.handle());
+}
+
+Value DOMTreeWalker::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMTreeWalker,DOMObject>(exec,p,&DOMTreeWalkerTable,this);
+}
+
+Value DOMTreeWalker::getValueProperty(ExecState *exec, int token) const
+{
+ DOM::TreeWalker tw(treeWalker);
+ switch (token) {
+ case Root:
+ return getDOMNode(exec,tw.root());
+ case WhatToShow:
+ return Number(tw.whatToShow());
+ case Filter:
+ return getDOMNodeFilter(exec,tw.filter());
+ case ExpandEntityReferences:
+ return Boolean(tw.expandEntityReferences());
+ case CurrentNode:
+ return getDOMNode(exec,tw.currentNode());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMTreeWalker::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+void DOMTreeWalker::tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr)
+{
+ if (propertyName == "currentNode") {
+ treeWalker.setCurrentNode(toNode(value));
+ }
+ else
+ ObjectImp::put(exec, propertyName, value, attr);
+}
+
+Value DOMTreeWalkerProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &)
+{
+ KJS_CHECK_THIS( KJS::DOMTreeWalker, thisObj );
+ DOM::TreeWalker treeWalker = static_cast<DOMTreeWalker *>(thisObj.imp())->toTreeWalker();
+ switch (id) {
+ case DOMTreeWalker::ParentNode:
+ return getDOMNode(exec,treeWalker.parentNode());
+ case DOMTreeWalker::FirstChild:
+ return getDOMNode(exec,treeWalker.firstChild());
+ case DOMTreeWalker::LastChild:
+ return getDOMNode(exec,treeWalker.lastChild());
+ case DOMTreeWalker::PreviousSibling:
+ return getDOMNode(exec,treeWalker.previousSibling());
+ case DOMTreeWalker::NextSibling:
+ return getDOMNode(exec,treeWalker.nextSibling());
+ case DOMTreeWalker::PreviousNode:
+ return getDOMNode(exec,treeWalker.previousSibling());
+ case DOMTreeWalker::NextNode:
+ return getDOMNode(exec,treeWalker.nextNode());
+ }
+ return Undefined();
+}
+
+Value getDOMTreeWalker(ExecState *exec, DOM::TreeWalker tw)
+{
+ return cacheDOMObject<DOM::TreeWalker, DOMTreeWalker>(exec, tw);
+}
+
+DOM::NodeFilter toNodeFilter(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMNodeFilter::info))
+ return DOM::NodeFilter();
+
+ const DOMNodeFilter *dobj = static_cast<const DOMNodeFilter*>(obj.imp());
+ return dobj->toNodeFilter();
+}
+
+// -------------------------------------------------------------------------
+
+JSNodeFilter::JSNodeFilter(Object & _filter) : DOM::CustomNodeFilter(), filter( _filter )
+{
+}
+
+JSNodeFilter::~JSNodeFilter()
+{
+}
+
+short JSNodeFilter::acceptNode(const DOM::Node &n)
+{
+ KHTMLView *view = static_cast<DOM::DocumentImpl *>( n.handle()->docPtr() )->view();
+ if (!view)
+ return DOM::NodeFilter::FILTER_REJECT;
+
+ KHTMLPart *part = view->part();
+ KJSProxy *proxy = part->jScript();
+ if (proxy) {
+ ExecState *exec = proxy->interpreter()->globalExec();
+ Object acceptNodeFunc = Object::dynamicCast( filter.get(exec, "acceptNode") );
+ if (!acceptNodeFunc.isNull() && acceptNodeFunc.implementsCall()) {
+ List args;
+ args.append(getDOMNode(exec,n));
+ Value result = acceptNodeFunc.call(exec,filter,args);
+ if (exec->hadException())
+ exec->clearException();
+ return result.toInteger(exec);
+ }
+ }
+
+ return DOM::NodeFilter::FILTER_REJECT;
+}
+
+} //namespace KJS
diff --git a/tdehtml/ecma/kjs_traversal.h b/tdehtml/ecma/kjs_traversal.h
new file mode 100644
index 000000000..fd7e064b1
--- /dev/null
+++ b/tdehtml/ecma/kjs_traversal.h
@@ -0,0 +1,108 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_TRAVERSAL_H_
+#define _KJS_TRAVERSAL_H_
+
+#include "ecma/kjs_dom.h"
+#include "dom/dom2_traversal.h"
+
+namespace KJS {
+
+ class DOMNodeIterator : public DOMObject {
+ public:
+ DOMNodeIterator(ExecState *exec, DOM::NodeIterator ni);
+ ~DOMNodeIterator();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Filter, Root, WhatToShow, ExpandEntityReferences,
+ NextNode, PreviousNode, Detach };
+ DOM::NodeIterator toNodeIterator() const { return nodeIterator; }
+ protected:
+ DOM::NodeIterator nodeIterator;
+ };
+
+ // Constructor object NodeFilter
+ class NodeFilterConstructor : public DOMObject {
+ public:
+ NodeFilterConstructor(ExecState *);
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ class DOMNodeFilter : public DOMObject {
+ public:
+ DOMNodeFilter(ExecState *exec, DOM::NodeFilter nf);
+ ~DOMNodeFilter();
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ virtual DOM::NodeFilter toNodeFilter() const { return nodeFilter; }
+ enum { AcceptNode };
+ protected:
+ DOM::NodeFilter nodeFilter;
+ };
+
+ class DOMTreeWalker : public DOMObject {
+ public:
+ DOMTreeWalker(ExecState *exec, DOM::TreeWalker tw);
+ ~DOMTreeWalker();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr = None);
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Root, WhatToShow, Filter, ExpandEntityReferences, CurrentNode,
+ ParentNode, FirstChild, LastChild, PreviousSibling, NextSibling,
+ PreviousNode, NextNode };
+ DOM::TreeWalker toTreeWalker() const { return treeWalker; }
+ protected:
+ DOM::TreeWalker treeWalker;
+ };
+
+ Value getDOMNodeIterator(ExecState *exec, DOM::NodeIterator ni);
+ Value getNodeFilterConstructor(ExecState *exec);
+ Value getDOMNodeFilter(ExecState *exec, DOM::NodeFilter nf);
+ Value getDOMTreeWalker(ExecState *exec, DOM::TreeWalker tw);
+
+ /**
+ * Convert an object to a NodeFilter. Returns a null Node if not possible.
+ */
+ DOM::NodeFilter toNodeFilter(const Value&);
+
+ class JSNodeFilter : public DOM::CustomNodeFilter {
+ public:
+ JSNodeFilter(Object & _filter);
+ virtual ~JSNodeFilter();
+ virtual short acceptNode (const DOM::Node &n);
+ protected:
+ Object filter;
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_views.cpp b/tdehtml/ecma/kjs_views.cpp
new file mode 100644
index 000000000..dbf354ce8
--- /dev/null
+++ b/tdehtml/ecma/kjs_views.cpp
@@ -0,0 +1,91 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ecma/kjs_views.h"
+#include "ecma/kjs_css.h"
+#include "ecma/kjs_window.h"
+#include "kjs_views.lut.h"
+
+using namespace KJS;
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMAbstractView::info = { "AbstractView", 0, &DOMAbstractViewTable, 0 };
+/*
+@begin DOMAbstractViewTable 2
+ document DOMAbstractView::Document DontDelete|ReadOnly
+ getComputedStyle DOMAbstractView::GetComputedStyle DontDelete|Function 2
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(DOMAbstractViewFunc)
+
+DOMAbstractView::DOMAbstractView(ExecState *exec, DOM::AbstractView av)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype()), abstractView(av) {}
+
+DOMAbstractView::~DOMAbstractView()
+{
+ ScriptInterpreter::forgetDOMObject(abstractView.handle());
+}
+
+Value DOMAbstractView::tryGet(ExecState *exec, const Identifier &p) const
+{
+ if ( p == "document" )
+ return getDOMNode(exec,abstractView.document());
+ else if ( p == "getComputedStyle" )
+ return lookupOrCreateFunction<DOMAbstractViewFunc>(exec,p,this,DOMAbstractView::GetComputedStyle,2,DontDelete|Function);
+ else
+ return DOMObject::tryGet(exec,p);
+}
+
+Value DOMAbstractViewFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMAbstractView, thisObj );
+ DOM::AbstractView abstractView = static_cast<DOMAbstractView *>(thisObj.imp())->toAbstractView();
+ switch (id) {
+ case DOMAbstractView::GetComputedStyle: {
+ DOM::Node arg0 = toNode(args[0]);
+ if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
+ return Undefined(); // throw exception?
+ else
+ return getDOMCSSStyleDeclaration(exec,abstractView.getComputedStyle(static_cast<DOM::Element>(arg0),
+ args[1].toString(exec).string()));
+ }
+ }
+ return Undefined();
+}
+
+Value KJS::getDOMAbstractView(ExecState *exec, DOM::AbstractView av)
+{
+ return cacheDOMObject<DOM::AbstractView, DOMAbstractView>(exec, av);
+}
+
+DOM::AbstractView KJS::toAbstractView (const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMAbstractView::info))
+ return DOM::AbstractView ();
+
+ // the Window object is considered for all practical purposes as a descendant of AbstractView
+ if (obj.inherits(&Window::info))
+ return static_cast<const Window *>(obj.imp())->toAbstractView();
+
+ const DOMAbstractView *dobj = static_cast<const DOMAbstractView *>(obj.imp());
+ return dobj->toAbstractView ();
+}
diff --git a/tdehtml/ecma/kjs_views.h b/tdehtml/ecma/kjs_views.h
new file mode 100644
index 000000000..11e103fde
--- /dev/null
+++ b/tdehtml/ecma/kjs_views.h
@@ -0,0 +1,53 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_VIEWS_H_
+#define _KJS_VIEWS_H_
+
+#include "ecma/kjs_dom.h"
+#include "dom/dom2_views.h"
+
+namespace KJS {
+
+
+ class DOMAbstractView : public DOMObject {
+ public:
+ DOMAbstractView(ExecState *, DOM::AbstractView av);
+ ~DOMAbstractView();
+ virtual Value tryGet(ExecState *exec,const Identifier &p) const;
+ // no put - all read-only
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ virtual DOM::AbstractView toAbstractView() const { return abstractView; }
+ enum { Document, GetComputedStyle };
+ protected:
+ DOM::AbstractView abstractView;
+ };
+
+ Value getDOMAbstractView(ExecState *exec, DOM::AbstractView av);
+
+ /**
+ * Convert an object to an AbstractView. Returns a null Node if not possible.
+ */
+ DOM::AbstractView toAbstractView(const Value&);
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/kjs_window.cpp b/tdehtml/ecma/kjs_window.cpp
new file mode 100644
index 000000000..767c7607f
--- /dev/null
+++ b/tdehtml/ecma/kjs_window.cpp
@@ -0,0 +1,2935 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000-2003 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001-2003 David Faure (faure@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "config.h"
+
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "tdehtmlpart_p.h"
+#include "tdehtml_settings.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmltags.h"
+#include "html/html_documentimpl.h"
+#include "rendering/render_frames.h"
+
+#include <tqstylesheet.h>
+#include <tqtimer.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+#include <tdeparts/browserinterface.h>
+#include <twin.h>
+
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <twinmodule.h> // schroder
+#endif
+
+#ifndef KONQ_EMBEDDED
+#include <kbookmarkmanager.h>
+#endif
+#include <kglobalsettings.h>
+#include <assert.h>
+#include <tqstyle.h>
+#include <tqobjectlist.h>
+#include <kstringhandler.h>
+
+#include "kjs_proxy.h"
+#include "kjs_window.h"
+#include "kjs_navigator.h"
+#include "kjs_mozilla.h"
+#include "kjs_html.h"
+#include "kjs_range.h"
+#include "kjs_traversal.h"
+#include "kjs_css.h"
+#include "kjs_events.h"
+#include "kjs_views.h"
+#include "xmlhttprequest.h"
+#include "xmlserializer.h"
+#include "domparser.h"
+
+using namespace KJS;
+
+namespace KJS {
+
+ class History : public ObjectImp {
+ friend class HistoryFunc;
+ public:
+ History(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Back, Forward, Go, Length };
+ private:
+ TQGuardedPtr<KHTMLPart> part;
+ };
+
+ class External : public ObjectImp {
+ friend class ExternalFunc;
+ public:
+ External(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { AddFavorite };
+ private:
+ TQGuardedPtr<KHTMLPart> part;
+ };
+
+ class FrameArray : public ObjectImp {
+ public:
+ FrameArray(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+ virtual bool implementsCall() const { return true; }
+ private:
+ TQGuardedPtr<KHTMLPart> part;
+ };
+
+#ifdef Q_WS_QWS
+ class KonquerorFunc : public DOMFunction {
+ public:
+ KonquerorFunc(ExecState *exec, const Konqueror* k, const char* name)
+ : DOMFunction(exec), konqueror(k), m_name(name) { }
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
+
+ private:
+ const Konqueror* konqueror;
+ TQCString m_name;
+ };
+#endif
+} // namespace KJS
+
+#include "kjs_window.lut.h"
+#include "rendering/render_replaced.h"
+
+////////////////////// Screen Object ////////////////////////
+namespace KJS {
+// table for screen object
+/*
+@begin ScreenTable 7
+ height Screen::Height DontEnum|ReadOnly
+ width Screen::Width DontEnum|ReadOnly
+ colorDepth Screen::ColorDepth DontEnum|ReadOnly
+ pixelDepth Screen::PixelDepth DontEnum|ReadOnly
+ availLeft Screen::AvailLeft DontEnum|ReadOnly
+ availTop Screen::AvailTop DontEnum|ReadOnly
+ availHeight Screen::AvailHeight DontEnum|ReadOnly
+ availWidth Screen::AvailWidth DontEnum|ReadOnly
+@end
+*/
+
+const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
+
+// We set the object prototype so that toString is implemented
+Screen::Screen(ExecState *exec)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
+
+Value Screen::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Screen::get " << p.qstring() << endl;
+#endif
+ return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
+}
+
+Value Screen::getValueProperty(ExecState *exec, int token) const
+{
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ KWinModule info(0, KWinModule::INFO_DESKTOP);
+#endif
+ TQWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
+ TQRect sg = TDEGlobalSettings::desktopGeometry(thisWidget);
+
+ switch( token ) {
+ case Height:
+ return Number(sg.height());
+ case Width:
+ return Number(sg.width());
+ case ColorDepth:
+ case PixelDepth: {
+ TQPaintDeviceMetrics m(TQApplication::desktop());
+ return Number(m.depth());
+ }
+ case AvailLeft: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ TQRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.x()-sg.x());
+#else
+ return Number(10);
+#endif
+ }
+ case AvailTop: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ TQRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.y()-sg.y());
+#else
+ return Number(10);
+#endif
+ }
+ case AvailHeight: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ TQRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.height());
+#else
+ return Number(100);
+#endif
+ }
+ case AvailWidth: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ TQRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.width());
+#else
+ return Number(100);
+#endif
+ }
+ default:
+ kdDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token << endl;
+ return Undefined();
+ }
+}
+
+////////////////////// Window Object ////////////////////////
+
+const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, 0 };
+
+/*
+@begin WindowTable 162
+ atob Window::AToB DontDelete|Function 1
+ btoa Window::BToA DontDelete|Function 1
+ closed Window::Closed DontDelete|ReadOnly
+ crypto Window::Crypto DontDelete|ReadOnly
+ defaultStatus Window::DefaultStatus DontDelete
+ defaultstatus Window::DefaultStatus DontDelete
+ status Window::Status DontDelete
+ document Window::Document DontDelete|ReadOnly
+ frameElement Window::FrameElement DontDelete|ReadOnly
+ frames Window::Frames DontDelete|ReadOnly
+ history Window::_History DontDelete|ReadOnly
+ external Window::_External DontDelete|ReadOnly
+ event Window::Event DontDelete|ReadOnly
+ innerHeight Window::InnerHeight DontDelete|ReadOnly
+ innerWidth Window::InnerWidth DontDelete|ReadOnly
+ length Window::Length DontDelete|ReadOnly
+ location Window::_Location DontDelete
+ name Window::Name DontDelete
+ navigator Window::_Navigator DontDelete|ReadOnly
+ clientInformation Window::ClientInformation DontDelete|ReadOnly
+ konqueror Window::_Konqueror DontDelete|ReadOnly
+ offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly
+ opener Window::Opener DontDelete|ReadOnly
+ outerHeight Window::OuterHeight DontDelete|ReadOnly
+ outerWidth Window::OuterWidth DontDelete|ReadOnly
+ pageXOffset Window::PageXOffset DontDelete|ReadOnly
+ pageYOffset Window::PageYOffset DontDelete|ReadOnly
+ parent Window::Parent DontDelete|ReadOnly
+ personalbar Window::Personalbar DontDelete|ReadOnly
+ screenX Window::ScreenX DontDelete|ReadOnly
+ screenY Window::ScreenY DontDelete|ReadOnly
+ scrollbars Window::Scrollbars DontDelete|ReadOnly
+ scroll Window::Scroll DontDelete|Function 2
+ scrollBy Window::ScrollBy DontDelete|Function 2
+ scrollTo Window::ScrollTo DontDelete|Function 2
+ scrollX Window::ScrollX DontDelete|ReadOnly
+ scrollY Window::ScrollY DontDelete|ReadOnly
+ moveBy Window::MoveBy DontDelete|Function 2
+ moveTo Window::MoveTo DontDelete|Function 2
+ resizeBy Window::ResizeBy DontDelete|Function 2
+ resizeTo Window::ResizeTo DontDelete|Function 2
+ self Window::Self DontDelete|ReadOnly
+ window Window::_Window DontDelete|ReadOnly
+ top Window::Top DontDelete|ReadOnly
+ screen Window::_Screen DontDelete|ReadOnly
+ alert Window::Alert DontDelete|Function 1
+ confirm Window::Confirm DontDelete|Function 1
+ prompt Window::Prompt DontDelete|Function 2
+ open Window::Open DontDelete|Function 3
+ setTimeout Window::SetTimeout DontDelete|Function 2
+ clearTimeout Window::ClearTimeout DontDelete|Function 1
+ focus Window::Focus DontDelete|Function 0
+ blur Window::Blur DontDelete|Function 0
+ close Window::Close DontDelete|Function 0
+ setInterval Window::SetInterval DontDelete|Function 2
+ clearInterval Window::ClearInterval DontDelete|Function 1
+ captureEvents Window::CaptureEvents DontDelete|Function 0
+ releaseEvents Window::ReleaseEvents DontDelete|Function 0
+ print Window::Print DontDelete|Function 0
+ addEventListener Window::AddEventListener DontDelete|Function 3
+ removeEventListener Window::RemoveEventListener DontDelete|Function 3
+# Normally found in prototype. Add to window object itself to make them
+# accessible in closed and cross-site windows
+ valueOf Window::ValueOf DontDelete|Function 0
+ toString Window::ToString DontDelete|Function 0
+# IE extension
+ navigate Window::Navigate DontDelete|Function 1
+# Mozilla extension
+ sidebar Window::SideBar DontDelete|ReadOnly
+ getComputedStyle Window::GetComputedStyle DontDelete|Function 2
+
+# Warning, when adding a function to this object you need to add a case in Window::get
+
+# Event handlers
+# IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
+# ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
+# It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
+ onabort Window::Onabort DontDelete
+ onblur Window::Onblur DontDelete
+ onchange Window::Onchange DontDelete
+ onclick Window::Onclick DontDelete
+ ondblclick Window::Ondblclick DontDelete
+ ondragdrop Window::Ondragdrop DontDelete
+ onerror Window::Onerror DontDelete
+ onfocus Window::Onfocus DontDelete
+ onkeydown Window::Onkeydown DontDelete
+ onkeypress Window::Onkeypress DontDelete
+ onkeyup Window::Onkeyup DontDelete
+ onload Window::Onload DontDelete
+ onmousedown Window::Onmousedown DontDelete
+ onmousemove Window::Onmousemove DontDelete
+ onmouseout Window::Onmouseout DontDelete
+ onmouseover Window::Onmouseover DontDelete
+ onmouseup Window::Onmouseup DontDelete
+ onmove Window::Onmove DontDelete
+ onreset Window::Onreset DontDelete
+ onresize Window::Onresize DontDelete
+ onselect Window::Onselect DontDelete
+ onsubmit Window::Onsubmit DontDelete
+ onunload Window::Onunload DontDelete
+
+# Constructors/constant tables
+ Node Window::Node DontDelete
+ Event Window::EventCtor DontDelete
+ Range Window::Range DontDelete
+ NodeFilter Window::NodeFilter DontDelete
+ DOMException Window::DOMException DontDelete
+ CSSRule Window::CSSRule DontDelete
+ MutationEvent Window::MutationEventCtor DontDelete
+ KeyboardEvent Window::KeyboardEventCtor DontDelete
+ EventException Window::EventExceptionCtor DontDelete
+ Image Window::Image DontDelete|ReadOnly
+ Option Window::Option DontDelete|ReadOnly
+ XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly
+ XMLSerializer Window::XMLSerializer DontDelete|ReadOnly
+ DOMParser Window::DOMParser DontDelete|ReadOnly
+
+# Mozilla dom emulation ones.
+ Element Window::ElementCtor DontDelete
+ Document Window::DocumentCtor DontDelete
+ #this one is an alias since we don't have a separate XMLDocument
+ XMLDocument Window::DocumentCtor DontDelete
+ HTMLElement Window::HTMLElementCtor DontDelete
+ HTMLDocument Window::HTMLDocumentCtor DontDelete
+ HTMLHtmlElement Window::HTMLHtmlElementCtor DontDelete
+ HTMLHeadElement Window::HTMLHeadElementCtor DontDelete
+ HTMLLinkElement Window::HTMLLinkElementCtor DontDelete
+ HTMLTitleElement Window::HTMLTitleElementCtor DontDelete
+ HTMLMetaElement Window::HTMLMetaElementCtor DontDelete
+ HTMLBaseElement Window::HTMLBaseElementCtor DontDelete
+ HTMLIsIndexElement Window::HTMLIsIndexElementCtor DontDelete
+ HTMLStyleElement Window::HTMLStyleElementCtor DontDelete
+ HTMLBodyElement Window::HTMLBodyElementCtor DontDelete
+ HTMLFormElement Window::HTMLFormElementCtor DontDelete
+ HTMLSelectElement Window::HTMLSelectElementCtor DontDelete
+ HTMLOptGroupElement Window::HTMLOptGroupElementCtor DontDelete
+ HTMLOptionElement Window::HTMLOptionElementCtor DontDelete
+ HTMLInputElement Window::HTMLInputElementCtor DontDelete
+ HTMLTextAreaElement Window::HTMLTextAreaElementCtor DontDelete
+ HTMLButtonElement Window::HTMLButtonElementCtor DontDelete
+ HTMLLabelElement Window::HTMLLabelElementCtor DontDelete
+ HTMLFieldSetElement Window::HTMLFieldSetElementCtor DontDelete
+ HTMLLegendElement Window::HTMLLegendElementCtor DontDelete
+ HTMLUListElement Window::HTMLUListElementCtor DontDelete
+ HTMLOListElement Window::HTMLOListElementCtor DontDelete
+ HTMLDListElement Window::HTMLDListElementCtor DontDelete
+ HTMLDirectoryElement Window::HTMLDirectoryElementCtor DontDelete
+ HTMLMenuElement Window::HTMLMenuElementCtor DontDelete
+ HTMLLIElement Window::HTMLLIElementCtor DontDelete
+ HTMLDivElement Window::HTMLDivElementCtor DontDelete
+ HTMLParagraphElement Window::HTMLParagraphElementCtor DontDelete
+ HTMLHeadingElement Window::HTMLHeadingElementCtor DontDelete
+ HTMLBlockQuoteElement Window::HTMLBlockQuoteElementCtor DontDelete
+ HTMLQuoteElement Window::HTMLQuoteElementCtor DontDelete
+ HTMLPreElement Window::HTMLPreElementCtor DontDelete
+ HTMLBRElement Window::HTMLBRElementCtor DontDelete
+ HTMLBaseFontElement Window::HTMLBaseFontElementCtor DontDelete
+ HTMLFontElement Window::HTMLFontElementCtor DontDelete
+ HTMLHRElement Window::HTMLHRElementCtor DontDelete
+ HTMLModElement Window::HTMLModElementCtor DontDelete
+ HTMLAnchorElement Window::HTMLAnchorElementCtor DontDelete
+ HTMLImageElement Window::HTMLImageElementCtor DontDelete
+ HTMLObjectElement Window::HTMLObjectElementCtor DontDelete
+ HTMLParamElement Window::HTMLParamElementCtor DontDelete
+ HTMLAppletElement Window::HTMLAppletElementCtor DontDelete
+ HTMLMapElement Window::HTMLMapElementCtor DontDelete
+ HTMLAreaElement Window::HTMLAreaElementCtor DontDelete
+ HTMLScriptElement Window::HTMLScriptElementCtor DontDelete
+ HTMLTableElement Window::HTMLTableElementCtor DontDelete
+ HTMLTableCaptionElement Window::HTMLTableCaptionElementCtor DontDelete
+ HTMLTableColElement Window::HTMLTableColElementCtor DontDelete
+ HTMLTableSectionElement Window::HTMLTableSectionElementCtor DontDelete
+ HTMLTableRowElement Window::HTMLTableRowElementCtor DontDelete
+ HTMLTableCellElement Window::HTMLTableCellElementCtor DontDelete
+ HTMLFrameSetElement Window::HTMLFrameSetElementCtor DontDelete
+ HTMLLayerElement Window::HTMLLayerElementCtor DontDelete
+ HTMLFrameElement Window::HTMLFrameElementCtor DontDelete
+ HTMLIFrameElement Window::HTMLIFrameElementCtor DontDelete
+ CSSStyleDeclaration Window::CSSStyleDeclarationCtor DontDelete
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
+
+Window::Window(tdehtml::ChildFrame *p)
+ : ObjectImp(/*no proto*/), m_frame(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0)
+{
+ winq = new WindowQObject(this);
+ //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
+}
+
+Window::~Window()
+{
+ delete winq;
+}
+
+Window *Window::retrieveWindow(KParts::ReadOnlyPart *p)
+{
+ Object obj = Object::dynamicCast( retrieve( p ) );
+#ifndef NDEBUG
+ // obj should never be null, except when javascript has been disabled in that part.
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(p);
+ if ( part && part->jScriptEnabled() )
+ {
+ assert( obj.isValid() );
+#ifndef QWS
+ assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
+#endif
+ }
+#endif
+ if ( !obj.isValid() ) // JS disabled
+ return 0;
+ return static_cast<KJS::Window*>(obj.imp());
+}
+
+Window *Window::retrieveActive(ExecState *exec)
+{
+ ValueImp *imp = exec->interpreter()->globalObject().imp();
+ assert( imp );
+#ifndef QWS
+ assert( dynamic_cast<KJS::Window*>(imp) );
+#endif
+ return static_cast<KJS::Window*>(imp);
+}
+
+Value Window::retrieve(KParts::ReadOnlyPart *p)
+{
+ assert(p);
+ KHTMLPart * part = ::tqqt_cast<KHTMLPart *>(p);
+ KJSProxy *proxy = 0L;
+ if (!part) {
+ part = ::tqqt_cast<KHTMLPart *>(p->parent());
+ if (part)
+ proxy = part->framejScript(p);
+ } else
+ proxy = part->jScript();
+ if (proxy) {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window::retrieve part=" << part << " '" << part->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
+#endif
+ return proxy->interpreter()->globalObject(); // the Global object is the "window"
+ } else {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
+#endif
+ return Undefined(); // This can happen with JS disabled on the domain of that window
+ }
+}
+
+Location *Window::location() const
+{
+ if (!loc)
+ const_cast<Window*>(this)->loc = new Location(m_frame);
+ return loc;
+}
+
+ObjectImp* Window::frames( ExecState* exec ) const
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (part)
+ return m_frames ? m_frames :
+ (const_cast<Window*>(this)->m_frames = new FrameArray(exec, part));
+ return 0L;
+}
+
+// reference our special objects during garbage collection
+void Window::mark()
+{
+ ObjectImp::mark();
+ if (screen && !screen->marked())
+ screen->mark();
+ if (history && !history->marked())
+ history->mark();
+ if (external && !external->marked())
+ external->mark();
+ if (m_frames && !m_frames->marked())
+ m_frames->mark();
+ //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
+ if (loc && !loc->marked())
+ loc->mark();
+ if (winq)
+ winq->mark();
+}
+
+bool Window::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ // we don't want any operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return ( p == "closed" );
+
+ if (ObjectImp::hasProperty(exec, p))
+ return true;
+
+ if (Lookup::findEntry(&WindowTable, p))
+ return true;
+
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return false;
+
+ TQString q = p.qstring();
+ if (part->findFramePart(p.qstring()))
+ return true;
+ // allow window[1] or parent[1] etc. (#56983)
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok) {
+ TQPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (i < len)
+ return true;
+ }
+
+ // allow shortcuts like 'Image1' instead of document.images.Image1
+ if (part->document().isHTMLDocument()) { // might be XML
+ DOM::HTMLDocument doc = part->htmlDocument();
+ // Keep in sync with tryGet
+
+ if (static_cast<DOM::DocumentImpl*>(doc.handle())->underDocNamedCache().get(p.qstring()))
+ return true;
+
+ return !doc.getElementById(p.string()).isNull();
+ }
+
+ return false;
+}
+
+UString Window::toString(ExecState *) const
+{
+ return "[object Window]";
+}
+
+Value Window::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
+#endif
+ // we want only limited operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
+ if (entry) {
+ switch (entry->value) {
+ case Closed:
+ return Boolean(true);
+ case _Location:
+ return Null();
+ case ValueOf:
+ case ToString:
+ return lookupOrCreateFunction<WindowFunc>(exec,p, this, entry->value,
+ entry->params, entry->attr);
+ default:
+ break;
+ }
+ }
+ return Undefined();
+ }
+
+ // Look for overrides first
+ ValueImp *val = getDirect(p);
+ if (val) {
+ //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
+ return isSafeScript(exec) ? Value(val) : Undefined();
+ }
+
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+
+ // properties that work on all windows
+ if (entry) {
+ // ReadOnlyPart first
+ switch(entry->value) {
+ case Closed:
+ return Boolean( false );
+ case _Location:
+ // No isSafeScript test here, we must be able to _set_ location.href (#49819)
+ return Value(location());
+ case _Window:
+ case Self:
+ return retrieve(m_frame->m_part);
+ default:
+ break;
+ }
+ if (!part)
+ return Undefined();
+ // KHTMLPart next
+ switch(entry->value) {
+ case Frames:
+ return Value(frames(exec));
+ case Opener:
+ if (!part->opener())
+ return Null(); // ### a null Window might be better, but == null
+ else // doesn't work yet
+ return retrieve(part->opener());
+ case Parent:
+ return retrieve(part->parentPart() ? part->parentPart() : (KHTMLPart*)part);
+ case Top: {
+ KHTMLPart *p = part;
+ while (p->parentPart())
+ p = p->parentPart();
+ return retrieve(p);
+ }
+ case Alert:
+ case Confirm:
+ case Prompt:
+ case Open:
+ case Close:
+ case Focus:
+ case Blur:
+ case AToB:
+ case BToA:
+ case GetComputedStyle:
+ case ValueOf:
+ case ToString:
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ default:
+ break;
+ }
+ } else if (!part) {
+ // not a KHTMLPart
+ TQString rvalue;
+ KParts::LiveConnectExtension::Type rtype;
+ unsigned long robjid;
+ if (m_frame->m_liveconnect &&
+ isSafeScript(exec) &&
+ m_frame->m_liveconnect->get(0, p.qstring(), rtype, robjid, rvalue))
+ return getLiveConnectValue(m_frame->m_liveconnect, p.qstring(), rtype, rvalue, robjid);
+ return Undefined();
+ }
+ // properties that only work on safe windows
+ if (isSafeScript(exec) && entry)
+ {
+ //kdDebug(6070) << "token: " << entry->value << endl;
+ switch( entry->value ) {
+ case Crypto:
+ return Undefined(); // ###
+ case DefaultStatus:
+ return String(UString(part->jsDefaultStatusBarText()));
+ case Status:
+ return String(UString(part->jsStatusBarText()));
+ case Document:
+ if (part->document().isNull()) {
+ kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
+ part->begin();
+ part->write("<HTML><BODY>");
+ part->end();
+ }
+ return getDOMNode(exec,part->document());
+ case FrameElement:
+ if (m_frame->m_frame)
+ return getDOMNode(exec,m_frame->m_frame->element());
+ else
+ return Undefined();
+ case Node:
+ return NodeConstructor::self(exec);
+ case Range:
+ return getRangeConstructor(exec);
+ case NodeFilter:
+ return getNodeFilterConstructor(exec);
+ case DOMException:
+ return getDOMExceptionConstructor(exec);
+ case CSSRule:
+ return getCSSRuleConstructor(exec);
+ case ElementCtor:
+ return ElementPseudoCtor::self(exec);
+ case HTMLElementCtor:
+ return HTMLElementPseudoCtor::self(exec);
+ case HTMLHtmlElementCtor:
+ return HTMLHtmlElementPseudoCtor::self(exec);
+ case HTMLHeadElementCtor:
+ return HTMLHeadElementPseudoCtor::self(exec);
+ case HTMLLinkElementCtor:
+ return HTMLLinkElementPseudoCtor::self(exec);
+ case HTMLTitleElementCtor:
+ return HTMLTitleElementPseudoCtor::self(exec);
+ case HTMLMetaElementCtor:
+ return HTMLMetaElementPseudoCtor::self(exec);
+ case HTMLBaseElementCtor:
+ return HTMLBaseElementPseudoCtor::self(exec);
+ case HTMLIsIndexElementCtor:
+ return HTMLIsIndexElementPseudoCtor::self(exec);
+ case HTMLStyleElementCtor:
+ return HTMLStyleElementPseudoCtor::self(exec);
+ case HTMLBodyElementCtor:
+ return HTMLBodyElementPseudoCtor::self(exec);
+ case HTMLFormElementCtor:
+ return HTMLFormElementPseudoCtor::self(exec);
+ case HTMLSelectElementCtor:
+ return HTMLSelectElementPseudoCtor::self(exec);
+ case HTMLOptGroupElementCtor:
+ return HTMLOptGroupElementPseudoCtor::self(exec);
+ case HTMLOptionElementCtor:
+ return HTMLOptionElementPseudoCtor::self(exec);
+ case HTMLInputElementCtor:
+ return HTMLInputElementPseudoCtor::self(exec);
+ case HTMLTextAreaElementCtor:
+ return HTMLTextAreaElementPseudoCtor::self(exec);
+ case HTMLButtonElementCtor:
+ return HTMLButtonElementPseudoCtor::self(exec);
+ case HTMLLabelElementCtor:
+ return HTMLLabelElementPseudoCtor::self(exec);
+ case HTMLFieldSetElementCtor:
+ return HTMLFieldSetElementPseudoCtor::self(exec);
+ case HTMLLegendElementCtor:
+ return HTMLLegendElementPseudoCtor::self(exec);
+ case HTMLUListElementCtor:
+ return HTMLUListElementPseudoCtor::self(exec);
+ case HTMLOListElementCtor:
+ return HTMLOListElementPseudoCtor::self(exec);
+ case HTMLDListElementCtor:
+ return HTMLDListElementPseudoCtor::self(exec);
+ case HTMLDirectoryElementCtor:
+ return HTMLDirectoryElementPseudoCtor::self(exec);
+ case HTMLMenuElementCtor:
+ return HTMLMenuElementPseudoCtor::self(exec);
+ case HTMLLIElementCtor:
+ return HTMLLIElementPseudoCtor::self(exec);
+ case HTMLDivElementCtor:
+ return HTMLDivElementPseudoCtor::self(exec);
+ case HTMLParagraphElementCtor:
+ return HTMLParagraphElementPseudoCtor::self(exec);
+ case HTMLHeadingElementCtor:
+ return HTMLHeadingElementPseudoCtor::self(exec);
+ case HTMLBlockQuoteElementCtor:
+ return HTMLBlockQuoteElementPseudoCtor::self(exec);
+ case HTMLQuoteElementCtor:
+ return HTMLQuoteElementPseudoCtor::self(exec);
+ case HTMLPreElementCtor:
+ return HTMLPreElementPseudoCtor::self(exec);
+ case HTMLBRElementCtor:
+ return HTMLBRElementPseudoCtor::self(exec);
+ case HTMLBaseFontElementCtor:
+ return HTMLBaseFontElementPseudoCtor::self(exec);
+ case HTMLFontElementCtor:
+ return HTMLFontElementPseudoCtor::self(exec);
+ case HTMLHRElementCtor:
+ return HTMLHRElementPseudoCtor::self(exec);
+ case HTMLModElementCtor:
+ return HTMLModElementPseudoCtor::self(exec);
+ case HTMLAnchorElementCtor:
+ return HTMLAnchorElementPseudoCtor::self(exec);
+ case HTMLImageElementCtor:
+ return HTMLImageElementPseudoCtor::self(exec);
+ case HTMLObjectElementCtor:
+ return HTMLObjectElementPseudoCtor::self(exec);
+ case HTMLParamElementCtor:
+ return HTMLParamElementPseudoCtor::self(exec);
+ case HTMLAppletElementCtor:
+ return HTMLAppletElementPseudoCtor::self(exec);
+ case HTMLMapElementCtor:
+ return HTMLMapElementPseudoCtor::self(exec);
+ case HTMLAreaElementCtor:
+ return HTMLAreaElementPseudoCtor::self(exec);
+ case HTMLScriptElementCtor:
+ return HTMLScriptElementPseudoCtor::self(exec);
+ case HTMLTableElementCtor:
+ return HTMLTableElementPseudoCtor::self(exec);
+ case HTMLTableCaptionElementCtor:
+ return HTMLTableCaptionElementPseudoCtor::self(exec);
+ case HTMLTableColElementCtor:
+ return HTMLTableColElementPseudoCtor::self(exec);
+ case HTMLTableSectionElementCtor:
+ return HTMLTableSectionElementPseudoCtor::self(exec);
+ case HTMLTableRowElementCtor:
+ return HTMLTableRowElementPseudoCtor::self(exec);
+ case HTMLTableCellElementCtor:
+ return HTMLTableCellElementPseudoCtor::self(exec);
+ case HTMLFrameSetElementCtor:
+ return HTMLFrameSetElementPseudoCtor::self(exec);
+ case HTMLLayerElementCtor:
+ return HTMLLayerElementPseudoCtor::self(exec);
+ case HTMLFrameElementCtor:
+ return HTMLFrameElementPseudoCtor::self(exec);
+ case HTMLIFrameElementCtor:
+ return HTMLIFrameElementPseudoCtor::self(exec);
+ case DocumentCtor:
+ return DocumentPseudoCtor::self(exec);
+ case HTMLDocumentCtor:
+ return HTMLDocumentPseudoCtor::self(exec);
+ case CSSStyleDeclarationCtor:
+ return CSSStyleDeclarationPseudoCtor::self(exec);
+ case EventCtor:
+ return EventConstructor::self(exec);
+ case MutationEventCtor:
+ return getMutationEventConstructor(exec);
+ case KeyboardEventCtor:
+ return getKeyboardEventConstructor(exec);
+ case EventExceptionCtor:
+ return getEventExceptionConstructor(exec);
+ case _History:
+ return Value(history ? history :
+ (const_cast<Window*>(this)->history = new History(exec,part)));
+
+ case _External:
+ return Value(external ? external :
+ (const_cast<Window*>(this)->external = new External(exec,part)));
+
+ case Event:
+ if (m_evt)
+ return getDOMEvent(exec,*m_evt);
+ else {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "WARNING: window(" << this << "," << part->name() << ").event, no event!" << endl;
+#endif
+ return Undefined();
+ }
+ case InnerHeight:
+ if (!part->view())
+ return Undefined();
+ tdehtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
+ return Number(part->view()->visibleHeight());
+ case InnerWidth:
+ if (!part->view())
+ return Undefined();
+ tdehtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
+ return Number(part->view()->visibleWidth());
+ case Length:
+ return Number(part->frames().count());
+ case Name:
+ return String(part->name());
+ case SideBar:
+ return Value(new MozillaSidebarExtension(exec, part));
+ case _Navigator:
+ case ClientInformation: {
+ // Store the navigator in the object so we get the same one each time.
+ Value nav( new Navigator(exec, part) );
+ const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
+ const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
+ return nav;
+ }
+#ifdef Q_WS_QWS
+ case _Konqueror: {
+ Value k( new Konqueror(part) );
+ const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
+ return k;
+ }
+#endif
+ case OffscreenBuffering:
+ return Boolean(true);
+ case OuterHeight:
+ case OuterWidth:
+ {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ if (!part->widget())
+ return Number(0);
+ KWin::WindowInfo inf = KWin::windowInfo(part->widget()->topLevelWidget()->winId());
+ return Number(entry->value == OuterHeight ?
+ inf.geometry().height() : inf.geometry().width());
+#else
+ return Number(entry->value == OuterHeight ?
+ part->view()->height() : part->view()->width());
+#endif
+ }
+ case PageXOffset:
+ return Number(part->view()->contentsX());
+ case PageYOffset:
+ return Number(part->view()->contentsY());
+ case Personalbar:
+ return Undefined(); // ###
+ case ScreenLeft:
+ case ScreenX: {
+ if (!part->view())
+ return Undefined();
+ TQRect sg = TDEGlobalSettings::desktopGeometry(part->view());
+ return Number(part->view()->mapToGlobal(TQPoint(0,0)).x() + sg.x());
+ }
+ case ScreenTop:
+ case ScreenY: {
+ if (!part->view())
+ return Undefined();
+ TQRect sg = TDEGlobalSettings::desktopGeometry(part->view());
+ return Number(part->view()->mapToGlobal(TQPoint(0,0)).y() + sg.y());
+ }
+ case ScrollX: {
+ if (!part->view())
+ return Undefined();
+ return Number(part->view()->contentsX());
+ }
+ case ScrollY: {
+ if (!part->view())
+ return Undefined();
+ return Number(part->view()->contentsY());
+ }
+ case Scrollbars:
+ return Undefined(); // ###
+ case _Screen:
+ return Value(screen ? screen :
+ (const_cast<Window*>(this)->screen = new Screen(exec)));
+ case Image:
+ return Value(new ImageConstructorImp(exec, part->document()));
+ case Option:
+ return Value(new OptionConstructorImp(exec, part->document()));
+ case XMLHttpRequest:
+ return Value(new XMLHttpRequestConstructorImp(exec, part->document()));
+ case XMLSerializer:
+ return Value(new XMLSerializerConstructorImp(exec));
+ case DOMParser:
+ return Value(new DOMParserConstructorImp(exec, part->xmlDocImpl()));
+ case Scroll: // compatibility
+ case ScrollBy:
+ case ScrollTo:
+ case MoveBy:
+ case MoveTo:
+ case ResizeBy:
+ case ResizeTo:
+ case CaptureEvents:
+ case ReleaseEvents:
+ case AddEventListener:
+ case RemoveEventListener:
+ case SetTimeout:
+ case ClearTimeout:
+ case SetInterval:
+ case ClearInterval:
+ case Print:
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ // IE extension
+ case Navigate:
+ // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses
+ // if (navigate) to test for IE (unlikely).
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
+ return Undefined();
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ case Onabort:
+ return getListener(exec,DOM::EventImpl::ABORT_EVENT);
+ case Onblur:
+ return getListener(exec,DOM::EventImpl::BLUR_EVENT);
+ case Onchange:
+ return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
+ case Onclick:
+ return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
+ case Ondblclick:
+ return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
+ case Ondragdrop:
+ return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
+ case Onerror:
+ return getListener(exec,DOM::EventImpl::ERROR_EVENT);
+ case Onfocus:
+ return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
+ case Onkeydown:
+ return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
+ case Onkeypress:
+ return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
+ case Onkeyup:
+ return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
+ case Onload:
+ return getListener(exec,DOM::EventImpl::LOAD_EVENT);
+ case Onmousedown:
+ return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
+ case Onmousemove:
+ return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
+ case Onmouseout:
+ return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
+ case Onmouseover:
+ return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
+ case Onmouseup:
+ return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
+ case Onmove:
+ return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
+ case Onreset:
+ return getListener(exec,DOM::EventImpl::RESET_EVENT);
+ case Onresize:
+ return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
+ case Onselect:
+ return getListener(exec,DOM::EventImpl::SELECT_EVENT);
+ case Onsubmit:
+ return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
+ case Onunload:
+ return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
+ }
+ }
+
+ // doing the remainder of ObjectImp::get() that is not covered by
+ // the getDirect() call above.
+ // #### guessed position. move further up or down?
+ Object proto = Object::dynamicCast(prototype());
+ assert(proto.isValid());
+ if (p == specialPrototypePropertyName)
+ return isSafeScript(exec) ? Value(proto) : Undefined();
+ Value val2 = proto.get(exec, p);
+ if (!val2.isA(UndefinedType)) {
+ return isSafeScript(exec) ? val2 : Undefined();
+ }
+
+ KParts::ReadOnlyPart *rop = part->findFramePart( p.qstring() );
+ if (rop)
+ return retrieve(rop);
+
+ // allow window[1] or parent[1] etc. (#56983)
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok) {
+ TQPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (i < len) {
+ KParts::ReadOnlyPart* frame = frames.at(i);
+ if (frame)
+ return Window::retrieve(frame);
+ }
+ }
+
+ //Check for images, forms, objects, etc.
+ if (isSafeScript(exec) && part->document().isHTMLDocument()) { // might be XML
+ DOM::DocumentImpl* docImpl = part->xmlDocImpl();
+ DOM::ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(p.qstring());
+ if (info) {
+ //May be a false positive, but we can try to avoid doing it the hard way in
+ //simpler cases. The trickiness here is that the cache is kept under both
+ //name and id, but we sometimes ignore id for IE compat
+ DOM::DOMString propertyDOMString = p.string();
+ if (info->nd && DOM::HTMLMappedNameCollectionImpl::matchesName(info->nd,
+ DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString)) {
+ return getDOMNode(exec, info->nd);
+ } else {
+ //Can't tell it just like that, so better go through collection and count stuff. This is the slow path...
+ DOM::HTMLMappedNameCollection coll(docImpl, DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString);
+
+ if (coll.length() == 1)
+ return getDOMNode(exec, coll.firstItem());
+ else if (coll.length() > 1)
+ return getHTMLCollection(exec, coll);
+ }
+ }
+ DOM::Element element = part->document().getElementById(p.string());
+ if ( !element.isNull() )
+ return getDOMNode(exec, element );
+ }
+
+ // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
+ // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
+#endif
+ return Undefined();
+}
+
+void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
+{
+ // we don't want any operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ // ### throw exception? allow setting of some props like location?
+ return;
+ }
+
+ // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
+ // If yes, save time and jump directly to ObjectImp.
+ if ( (attr != None && attr != DontDelete) ||
+ // Same thing if we have a local override (e.g. "var location")
+ ( isSafeScript( exec ) && ObjectImp::getDirect(propertyName) ) )
+ {
+ ObjectImp::put( exec, propertyName, value, attr );
+ return;
+ }
+
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
+ if (entry && !m_frame.isNull() && !m_frame->m_part.isNull())
+ {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
+#endif
+ switch( entry->value) {
+ case _Location:
+ goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
+ return;
+ default:
+ break;
+ }
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (part) {
+ switch( entry->value ) {
+ case Status: {
+ if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
+ == KHTMLSettings::KJSWindowStatusAllow) {
+ String s = value.toString(exec);
+ part->setJSStatusBarText(s.value().qstring());
+ }
+ return;
+ }
+ case DefaultStatus: {
+ if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
+ == KHTMLSettings::KJSWindowStatusAllow) {
+ String s = value.toString(exec);
+ part->setJSDefaultStatusBarText(s.value().qstring());
+ }
+ return;
+ }
+ case Onabort:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
+ return;
+ case Onblur:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
+ return;
+ case Onchange:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
+ return;
+ case Onclick:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
+ return;
+ case Ondblclick:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
+ return;
+ case Ondragdrop:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
+ return;
+ case Onerror:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::ERROR_EVENT,value);
+ return;
+ case Onfocus:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
+ return;
+ case Onkeydown:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
+ return;
+ case Onkeypress:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
+ return;
+ case Onkeyup:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
+ return;
+ case Onload:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
+ return;
+ case Onmousedown:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
+ return;
+ case Onmousemove:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
+ return;
+ case Onmouseout:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
+ return;
+ case Onmouseover:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
+ return;
+ case Onmouseup:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
+ return;
+ case Onmove:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
+ return;
+ case Onreset:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::RESET_EVENT,value);
+ return;
+ case Onresize:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
+ return;
+ case Onselect:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
+ return;
+ case Onsubmit:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
+ return;
+ case Onunload:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
+ return;
+ case Name:
+ if (isSafeScript(exec))
+ part->setName( value.toString(exec).qstring().local8Bit().data() );
+ return;
+ default:
+ break;
+ }
+ }
+ }
+ if (m_frame->m_liveconnect &&
+ isSafeScript(exec) &&
+ m_frame->m_liveconnect->put(0, propertyName.qstring(), value.toString(exec).qstring()))
+ return;
+ if (isSafeScript(exec)) {
+ //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
+ ObjectImp::put(exec, propertyName, value, attr);
+ }
+}
+
+bool Window::toBoolean(ExecState *) const
+{
+ return !m_frame.isNull() && !m_frame->m_part.isNull();
+}
+
+DOM::AbstractView Window::toAbstractView() const
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return DOM::AbstractView();
+ return part->document().defaultView();
+}
+
+void Window::scheduleClose()
+{
+ kdDebug(6070) << "Window::scheduleClose window.close() " << m_frame << endl;
+ Q_ASSERT(winq);
+ TQTimer::singleShot( 0, winq, TQT_SLOT( timeoutClose() ) );
+}
+
+void Window::closeNow()
+{
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
+ } else {
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part) {
+ kdDebug(6070) << "closeNow on non KHTML part" << endl;
+ } else {
+ //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
+ // We want to make sure that window.open won't find this part by name.
+ part->setName( 0 );
+ part->deleteLater();
+ part = 0;
+ }
+ }
+}
+
+void Window::afterScriptExecution()
+{
+ DOM::DocumentImpl::updateDocumentsRendering();
+ TQValueList<DelayedAction> delayedActions = m_delayed;
+ m_delayed.clear();
+ TQValueList<DelayedAction>::Iterator it = delayedActions.begin();
+ for ( ; it != delayedActions.end() ; ++it )
+ {
+ switch ((*it).actionId) {
+ case DelayedClose:
+ scheduleClose();
+ return; // stop here, in case of multiple actions
+ case DelayedGoHistory:
+ goHistory( (*it).param.toInt() );
+ break;
+ case NullAction:
+ // FIXME: anything needs to be done here? This is warning anyways.
+ break;
+ };
+ }
+}
+
+bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const
+{
+ if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access
+ kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
+ return false;
+ }
+ if (!activePart) {
+ kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
+ return false;
+ }
+ if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem.
+ return true;
+
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return true; // not a KHTMLPart
+
+ if ( part->document().isNull() )
+ return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
+
+ DOM::HTMLDocument thisDocument = part->htmlDocument();
+ if ( thisDocument.isNull() ) {
+ kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
+ return false;
+ }
+
+ KHTMLPart *activeKHTMLPart = ::tqqt_cast<KHTMLPart *>(activePart);
+ if (!activeKHTMLPart)
+ return true; // not a KHTMLPart
+
+ DOM::HTMLDocument actDocument = activeKHTMLPart->htmlDocument();
+ if ( actDocument.isNull() ) {
+ kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
+ return false;
+ }
+ DOM::DOMString actDomain = actDocument.domain();
+ DOM::DOMString thisDomain = thisDocument.domain();
+
+ if ( actDomain == thisDomain ) {
+#ifdef KJS_VERBOSE
+ //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
+#endif
+ return true;
+ }
+
+ kdDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
+ // TODO after 3.1: throw security exception (exec->setException())
+ return false;
+}
+
+void Window::setListener(ExecState *exec, int eventId, Value func)
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || !isSafeScript(exec))
+ return;
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
+ if (!doc)
+ return;
+
+ doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
+}
+
+Value Window::getListener(ExecState *exec, int eventId) const
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || !isSafeScript(exec))
+ return Undefined();
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
+ if (!doc)
+ return Undefined();
+
+ DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
+ if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
+ return static_cast<JSEventListener*>(listener)->listenerObj();
+ else
+ return Null();
+}
+
+
+JSEventListener *Window::getJSEventListener(const Value& val, bool html)
+{
+ // This function is so hot that it's worth coding it directly with imps.
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || val.type() != ObjectType)
+ return 0;
+
+ // It's ObjectType, so it must be valid.
+ Object listenerObject = Object::dynamicCast(val);
+ ObjectImp *listenerObjectImp = listenerObject.imp();
+
+ // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!)
+ if (!listenerObject.implementsCall() && part && part->jScript() && part->jScript()->interpreter())
+ {
+ Interpreter *interpreter = part->jScript()->interpreter();
+
+ // 'listener' probably is an EventListener object containing a 'handleEvent' function.
+ Value handleEventValue = listenerObject.get(interpreter->globalExec(), Identifier("handleEvent"));
+ Object handleEventObject = Object::dynamicCast(handleEventValue);
+
+ if(handleEventObject.isValid() && handleEventObject.implementsCall())
+ {
+ listenerObject = handleEventObject;
+ listenerObjectImp = handleEventObject.imp();
+ }
+ }
+
+ JSEventListener *existingListener = jsEventListeners[listenerObjectImp];
+ if (existingListener) {
+ if ( existingListener->isHTMLEventListener() != html )
+ // The existingListener will have the wrong type, so onclick= will behave like addEventListener or vice versa.
+ kdWarning() << "getJSEventListener: event listener already found but with html=" << !html << " - please report this, we thought it would never happen" << endl;
+ return existingListener;
+ }
+
+ // Note that the JSEventListener constructor adds it to our jsEventListeners list
+ return new JSEventListener(listenerObject, listenerObjectImp, Object(this), html);
+}
+
+JSLazyEventListener *Window::getJSLazyEventListener(const TQString& code, const TQString& name, DOM::NodeImpl *node)
+{
+ return new JSLazyEventListener(code, name, Object(this), node);
+}
+
+void Window::clear( ExecState *exec )
+{
+ delete winq;
+ winq = 0L;
+ // Get rid of everything, those user vars could hold references to DOM nodes
+ deleteAllProperties( exec );
+
+ // Break the dependency between the listeners and their object
+ TQPtrDictIterator<JSEventListener> it(jsEventListeners);
+ for (; it.current(); ++it)
+ it.current()->clear();
+ // Forget about the listeners (the DOM::NodeImpls will delete them)
+ jsEventListeners.clear();
+
+ if (m_frame) {
+ KJSProxy* proxy = m_frame->m_jscript;
+ if (proxy) // i.e. JS not disabled
+ {
+ winq = new WindowQObject(this);
+ // Now recreate a working global object for the next URL that will use us
+ KJS::Interpreter *interpreter = proxy->interpreter();
+ interpreter->initGlobalObject();
+ }
+ }
+}
+
+void Window::setCurrentEvent( DOM::Event *evt )
+{
+ m_evt = evt;
+ //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
+}
+
+void Window::goURL(ExecState* exec, const TQString& url, bool lockHistory)
+{
+ Window* active = Window::retrieveActive(exec);
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ KHTMLPart *active_part = ::tqqt_cast<KHTMLPart *>(active->part());
+ // Complete the URL using the "active part" (running interpreter)
+ if (active_part && part) {
+ if (url[0] == TQChar('#')) {
+ part->gotoAnchor(url.mid(1));
+ } else {
+ TQString dstUrl = active_part->htmlDocument().completeURL(url).string();
+ kdDebug(6070) << "Window::goURL dstUrl=" << dstUrl << endl;
+
+ // check if we're allowed to inject javascript
+ // SYNC check with tdehtml_part.cpp::slotRedirect!
+ if ( isSafeScript(exec) ||
+ dstUrl.find(TQString::fromLatin1("javascript:"), 0, false) != 0 )
+ part->scheduleRedirection(-1,
+ dstUrl,
+ lockHistory);
+ }
+ } else if (!part && !m_frame->m_part.isNull()) {
+ KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part);
+ if (b)
+ b->emit openURLRequest(m_frame->m_frame->element()->getDocument()->completeURL(url));
+ kdDebug() << "goURL for ROPart" << endl;
+ }
+}
+
+KParts::ReadOnlyPart *Window::part() const {
+ return m_frame.isNull() ? 0L : static_cast<KParts::ReadOnlyPart *>(m_frame->m_part);
+}
+
+void Window::delayedGoHistory( int steps )
+{
+ m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
+}
+
+void Window::goHistory( int steps )
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if(!part)
+ // TODO history readonlypart
+ return;
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if(!ext)
+ return;
+ KParts::BrowserInterface *iface = ext->browserInterface();
+
+ if ( !iface )
+ return;
+
+ iface->callMethod( "goHistory(int)", steps );
+ //emit ext->goHistory(steps);
+}
+
+void KJS::Window::resizeTo(TQWidget* tl, int width, int height)
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if(!part)
+ // TODO resizeTo readonlypart
+ return;
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (!ext) {
+ kdDebug(6070) << "Window::resizeTo found no browserExtension" << endl;
+ return;
+ }
+
+ // Security check: within desktop limits and bigger than 100x100 (per spec)
+ if ( width < 100 || height < 100 ) {
+ kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
+ return;
+ }
+
+ TQRect sg = TDEGlobalSettings::desktopGeometry(tl);
+
+ if ( width > sg.width() || height > sg.height() ) {
+ kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
+ return;
+ }
+
+ kdDebug(6070) << "resizing to " << width << "x" << height << endl;
+
+ emit ext->resizeTopLevelWidget( width, height );
+
+ // If the window is out of the desktop, move it up/left
+ // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
+ int right = tl->x() + tl->frameGeometry().width();
+ int bottom = tl->y() + tl->frameGeometry().height();
+ int moveByX = 0;
+ int moveByY = 0;
+ if ( right > sg.right() )
+ moveByX = - right + sg.right(); // always <0
+ if ( bottom > sg.bottom() )
+ moveByY = - bottom + sg.bottom(); // always <0
+ if ( moveByX || moveByY )
+ emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY );
+}
+
+Value Window::openWindow(ExecState *exec, const List& args)
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return Undefined();
+ KHTMLView *widget = part->view();
+ Value v = args[0];
+ TQString str;
+ if (v.isValid() && !v.isA(UndefinedType))
+ str = v.toString(exec).qstring();
+
+ // prepare arguments
+ KURL url;
+ if (!str.isEmpty())
+ {
+ KHTMLPart* p = ::tqqt_cast<KHTMLPart *>(Window::retrieveActive(exec)->m_frame->m_part);
+ if ( p )
+ url = p->htmlDocument().completeURL(str).string();
+ if ( !p ||
+ !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
+ return Undefined();
+ }
+
+ KHTMLSettings::KJSWindowOpenPolicy policy =
+ part->settings()->windowOpenPolicy(part->url().host());
+ if ( policy == KHTMLSettings::KJSWindowOpenAsk ) {
+ emit part->browserExtension()->requestFocus(part);
+ TQString caption;
+ if (!part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += i18n( "Confirmation: JavaScript Popup" );
+ if ( KMessageBox::questionYesNo(widget,
+ str.isEmpty() ?
+ i18n( "This site is requesting to open up a new browser "
+ "window via JavaScript.\n"
+ "Do you want to allow this?" ) :
+ i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />"
+ "Do you want to allow this?</qt>").arg(KStringHandler::csqueeze(url.htmlURL(), 100)),
+ caption, i18n("Allow"), i18n("Do Not Allow") ) == KMessageBox::Yes )
+ policy = KHTMLSettings::KJSWindowOpenAllow;
+ } else if ( policy == KHTMLSettings::KJSWindowOpenSmart )
+ {
+ // window.open disabled unless from a key/mouse event
+ if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
+ policy = KHTMLSettings::KJSWindowOpenAllow;
+ }
+
+ TQString frameName = args.size() > 1 ? args[1].toString(exec).qstring() : TQString("_blank");
+
+ v = args[2];
+ TQString features;
+ if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
+ features = v.toString(exec).qstring();
+ // Buggy scripts have ' at beginning and end, cut those
+ if (features.startsWith("\'") && features.endsWith("\'"))
+ features = features.mid(1, features.length()-2);
+ }
+
+ if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
+ if ( url.isEmpty() )
+ part->setSuppressedPopupIndicator(true, 0);
+ else {
+ part->setSuppressedPopupIndicator(true, part);
+ m_suppressedWindowInfo.append( SuppressedWindowInfo( url, frameName, features ) );
+ }
+ return Undefined();
+ } else {
+ return executeOpenWindow(exec, url, frameName, features);
+ }
+}
+
+Value Window::executeOpenWindow(ExecState *exec, const KURL& url, const TQString& frameName, const TQString& features)
+{
+ KHTMLPart *p = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
+ KHTMLView *widget = p->view();
+ KParts::WindowArgs winargs;
+
+ // scan feature argument
+ if (!features.isEmpty()) {
+ // specifying window params means false defaults
+ winargs.menuBarVisible = false;
+ winargs.toolBarsVisible = false;
+ winargs.statusBarVisible = false;
+ winargs.scrollBarsVisible = false;
+ TQStringList flist = TQStringList::split(',', features);
+ TQStringList::ConstIterator it = flist.begin();
+ while (it != flist.end()) {
+ TQString s = *it++;
+ TQString key, val;
+ int pos = s.find('=');
+ if (pos >= 0) {
+ key = s.left(pos).stripWhiteSpace().lower();
+ val = s.mid(pos + 1).stripWhiteSpace().lower();
+ TQRect screen = TDEGlobalSettings::desktopGeometry(widget->topLevelWidget());
+
+ if (key == "left" || key == "screenx") {
+ winargs.x = (int)val.toFloat() + screen.x();
+ if (winargs.x < screen.x() || winargs.x > screen.right())
+ winargs.x = screen.x(); // only safe choice until size is determined
+ } else if (key == "top" || key == "screeny") {
+ winargs.y = (int)val.toFloat() + screen.y();
+ if (winargs.y < screen.y() || winargs.y > screen.bottom())
+ winargs.y = screen.y(); // only safe choice until size is determined
+ } else if (key == "height") {
+ winargs.height = (int)val.toFloat() + 2*tqApp->style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) + 2;
+ if (winargs.height > screen.height()) // should actually check workspace
+ winargs.height = screen.height();
+ if (winargs.height < 100)
+ winargs.height = 100;
+ } else if (key == "width") {
+ winargs.width = (int)val.toFloat() + 2*tqApp->style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) + 2;
+ if (winargs.width > screen.width()) // should actually check workspace
+ winargs.width = screen.width();
+ if (winargs.width < 100)
+ winargs.width = 100;
+ } else {
+ goto boolargs;
+ }
+ continue;
+ } else {
+ // leaving away the value gives true
+ key = s.stripWhiteSpace().lower();
+ val = "1";
+ }
+ boolargs:
+ if (key == "menubar")
+ winargs.menuBarVisible = (val == "1" || val == "yes");
+ else if (key == "toolbar")
+ winargs.toolBarsVisible = (val == "1" || val == "yes");
+ else if (key == "location") // ### missing in WindowArgs
+ winargs.toolBarsVisible = (val == "1" || val == "yes");
+ else if (key == "status" || key == "statusbar")
+ winargs.statusBarVisible = (val == "1" || val == "yes");
+ else if (key == "scrollbars")
+ winargs.scrollBarsVisible = (val == "1" || val == "yes");
+ else if (key == "resizable")
+ winargs.resizable = (val == "1" || val == "yes");
+ else if (key == "fullscreen")
+ winargs.fullscreen = (val == "1" || val == "yes");
+ }
+ }
+
+ KParts::URLArgs uargs;
+ uargs.frameName = frameName;
+
+ if ( uargs.frameName.lower() == "_top" )
+ {
+ while ( p->parentPart() )
+ p = p->parentPart();
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "_parent" )
+ {
+ if ( p->parentPart() )
+ p = p->parentPart();
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "_self")
+ {
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "replace" )
+ {
+ Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/);
+ return Window::retrieve(p);
+ }
+ uargs.serviceType = "text/html";
+
+ // request window (new or existing if framename is set)
+ KParts::ReadOnlyPart *newPart = 0L;
+ emit p->browserExtension()->createNewWindow(KURL(), uargs,winargs,newPart);
+ if (newPart && ::tqqt_cast<KHTMLPart*>(newPart)) {
+ KHTMLPart *tdehtmlpart = static_cast<KHTMLPart*>(newPart);
+ //tqDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window);
+ tdehtmlpart->setOpener(p);
+ tdehtmlpart->setOpenedByJS(true);
+ if (tdehtmlpart->document().isNull()) {
+ tdehtmlpart->begin();
+ tdehtmlpart->write("<HTML><BODY>");
+ tdehtmlpart->end();
+ if ( p->docImpl() ) {
+ //kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
+ tdehtmlpart->docImpl()->setDomain( p->docImpl()->domain());
+ tdehtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
+ }
+ }
+ uargs.serviceType = TQString::null;
+ if (uargs.frameName.lower() == "_blank")
+ uargs.frameName = TQString::null;
+ if (!url.isEmpty())
+ emit tdehtmlpart->browserExtension()->openURLRequest(url,uargs);
+ return Window::retrieve(tdehtmlpart); // global object
+ } else
+ return Undefined();
+}
+
+void Window::forgetSuppressedWindows()
+{
+ m_suppressedWindowInfo.clear();
+}
+
+void Window::showSuppressedWindows()
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>( m_frame->m_part );
+ KJS::Interpreter *interpreter = part->jScript()->interpreter();
+ ExecState *exec = interpreter->globalExec();
+
+ TQValueList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
+ m_suppressedWindowInfo.clear();
+ TQValueList<SuppressedWindowInfo>::Iterator it = suppressedWindowInfo.begin();
+ for ( ; it != suppressedWindowInfo.end() ; ++it ) {
+ executeOpenWindow(exec, (*it).url, (*it).frameName, (*it).features);
+ }
+}
+
+Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( Window, thisObj );
+
+ // these should work no matter whether the window is already
+ // closed or not
+ if (id == Window::ValueOf || id == Window::ToString) {
+ return String("[object Window]");
+ }
+
+ Window *window = static_cast<Window *>(thisObj.imp());
+ TQString str, str2;
+
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(window->m_frame->m_part);
+ if (!part)
+ return Undefined();
+
+ KHTMLView *widget = part->view();
+ Value v = args[0];
+ UString s;
+ if (v.isValid() && !v.isA(UndefinedType)) {
+ s = v.toString(exec);
+ str = s.qstring();
+ }
+
+ TQString caption;
+ if (part && !part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += "JavaScript"; // TODO: i18n
+ // functions that work everywhere
+ switch(id) {
+ case Window::Alert:
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ KMessageBox::error(widget, TQStyleSheet::convertFromPlainText(str, TQStyleSheetItem::WhiteSpaceNormal), caption);
+ return Undefined();
+ case Window::Confirm:
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ return Boolean((KMessageBox::warningYesNo(widget, TQStyleSheet::convertFromPlainText(str), caption,
+ KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes));
+ case Window::Prompt:
+#ifndef KONQ_EMBEDDED
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ bool ok;
+ if (args.size() >= 2)
+ str2 = KInputDialog::getText(caption,
+ TQStyleSheet::convertFromPlainText(str),
+ args[1].toString(exec).qstring(), &ok, widget);
+ else
+ str2 = KInputDialog::getText(caption,
+ TQStyleSheet::convertFromPlainText(str),
+ TQString::null, &ok, widget);
+ if ( ok )
+ return String(str2);
+ else
+ return Null();
+#else
+ return Undefined();
+#endif
+ case Window::GetComputedStyle: {
+ if ( !part || !part->xmlDocImpl() )
+ return Undefined();
+ DOM::Node arg0 = toNode(args[0]);
+ if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
+ return Undefined(); // throw exception?
+ else
+ return getDOMCSSStyleDeclaration(exec, part->document().defaultView().getComputedStyle(static_cast<DOM::Element>(arg0),
+ args[1].toString(exec).string()));
+ }
+ case Window::Open:
+ return window->openWindow(exec, args);
+ case Window::Close: {
+ /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
+ The close method closes only windows opened by JavaScript using the open method.
+ If you attempt to close any other window, a confirm is generated, which
+ lets the user choose whether the window closes.
+ This is a security feature to prevent "mail bombs" containing self.close().
+ However, if the window has only one document (the current one) in its
+ session history, the close is allowed without any confirm. This is a
+ special case for one-off windows that need to open other windows and
+ then dispose of themselves.
+ */
+ bool doClose = false;
+ if (!part->openedByJS())
+ {
+ // To conform to the SPEC, we only ask if the window
+ // has more than one entry in the history (NS does that too).
+ History history(exec,part);
+
+ if ( history.get( exec, "length" ).toInt32(exec) <= 1 )
+ {
+ doClose = true;
+ }
+ else
+ {
+ // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
+ emit part->browserExtension()->requestFocus(part);
+ if ( KMessageBox::questionYesNo( window->part()->widget(),
+ i18n("Close window?"), i18n("Confirmation Required"),
+ KStdGuiItem::close(), KStdGuiItem::cancel() )
+ == KMessageBox::Yes )
+ doClose = true;
+ }
+ }
+ else
+ doClose = true;
+
+ if (doClose)
+ {
+ // If this is the current window (the one the interpreter runs in),
+ // then schedule a delayed close (so that the script terminates first).
+ // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
+ if ( Window::retrieveActive(exec) == window ) {
+ if (widget) {
+ // quit all dialogs of this view
+ // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
+ widget->closeChildDialogs();
+ }
+ //kdDebug() << "scheduling delayed close" << endl;
+ // We'll close the window at the end of the script execution
+ Window* w = const_cast<Window*>(window);
+ w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
+ } else {
+ //kdDebug() << "closing NOW" << endl;
+ (const_cast<Window*>(window))->closeNow();
+ }
+ }
+ return Undefined();
+ }
+ case Window::Navigate:
+ window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/);
+ return Undefined();
+ case Window::Focus: {
+ KHTMLSettings::KJSWindowFocusPolicy policy =
+ part->settings()->windowFocusPolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
+ widget->topLevelWidget()->raise();
+ KWin::deIconifyWindow( widget->topLevelWidget()->winId() );
+ widget->setActiveWindow();
+ emit part->browserExtension()->requestFocus(part);
+ }
+ return Undefined();
+ }
+ case Window::Blur:
+ // TODO
+ return Undefined();
+ case Window::BToA:
+ case Window::AToB: {
+ if (!s.is8Bit())
+ return Undefined();
+ TQByteArray in, out;
+ char *binData = s.ascii();
+ in.setRawData( binData, s.size() );
+ if (id == Window::AToB)
+ KCodecs::base64Decode( in, out );
+ else
+ KCodecs::base64Encode( in, out );
+ in.resetRawData( binData, s.size() );
+ UChar *d = new UChar[out.size()];
+ for (uint i = 0; i < out.size(); i++)
+ d[i].uc = (uchar) out[i];
+ UString ret(d, out.size(), false /*no copy*/);
+ return String(ret);
+ }
+
+ };
+
+
+ // now unsafe functions..
+ if (!window->isSafeScript(exec))
+ return Undefined();
+
+ switch (id) {
+ case Window::ScrollBy:
+ if(args.size() == 2 && widget)
+ widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
+ return Undefined();
+ case Window::Scroll:
+ case Window::ScrollTo:
+ if(args.size() == 2 && widget)
+ widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
+ return Undefined();
+ case Window::MoveBy: {
+ KHTMLSettings::KJSWindowMovePolicy policy =
+ part->settings()->windowMovePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
+ {
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (ext) {
+ TQWidget * tl = widget->topLevelWidget();
+ TQRect sg = TDEGlobalSettings::desktopGeometry(tl);
+
+ TQPoint dest = tl->pos() + TQPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
+ // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
+ if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
+ dest.x()+tl->width() <= sg.width()+sg.x() &&
+ dest.y()+tl->height() <= sg.height()+sg.y() )
+ emit ext->moveTopLevelWidget( dest.x(), dest.y() );
+ }
+ }
+ return Undefined();
+ }
+ case Window::MoveTo: {
+ KHTMLSettings::KJSWindowMovePolicy policy =
+ part->settings()->windowMovePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
+ {
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (ext) {
+ TQWidget * tl = widget->topLevelWidget();
+ TQRect sg = TDEGlobalSettings::desktopGeometry(tl);
+
+ TQPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
+ // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
+ if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
+ dest.x()+tl->width() <= sg.width()+sg.x() &&
+ dest.y()+tl->height() <= sg.height()+sg.y() )
+ emit ext->moveTopLevelWidget( dest.x(), dest.y() );
+ }
+ }
+ return Undefined();
+ }
+ case Window::ResizeBy: {
+ KHTMLSettings::KJSWindowResizePolicy policy =
+ part->settings()->windowResizePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowResizeAllow
+ && args.size() == 2 && widget)
+ {
+ TQWidget * tl = widget->topLevelWidget();
+ TQRect geom = tl->frameGeometry();
+ window->resizeTo( tl,
+ geom.width() + args[0].toInt32(exec),
+ geom.height() + args[1].toInt32(exec) );
+ }
+ return Undefined();
+ }
+ case Window::ResizeTo: {
+ KHTMLSettings::KJSWindowResizePolicy policy =
+ part->settings()->windowResizePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowResizeAllow
+ && args.size() == 2 && widget)
+ {
+ TQWidget * tl = widget->topLevelWidget();
+ window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
+ }
+ return Undefined();
+ }
+ case Window::SetTimeout:
+ case Window::SetInterval: {
+ bool singleShot;
+ int i; // timeout interval
+ if (args.size() == 0)
+ return Undefined();
+ if (args.size() > 1) {
+ singleShot = (id == Window::SetTimeout);
+ i = args[1].toInt32(exec);
+ } else {
+ // second parameter is missing. Emulate Mozilla behavior.
+ singleShot = true;
+ i = 4;
+ }
+ if (v.isA(StringType)) {
+ int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
+ return Number(r);
+ }
+ else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
+ Object func = Object::dynamicCast(v);
+ List funcArgs;
+ ListIterator it = args.begin();
+ int argno = 0;
+ while (it != args.end()) {
+ Value arg = it++;
+ if (argno++ >= 2)
+ funcArgs.append(arg);
+ }
+ if (args.size() < 2)
+ funcArgs.append(Number(i));
+ int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
+ return Number(r);
+ }
+ else
+ return Undefined();
+ }
+ case Window::ClearTimeout:
+ case Window::ClearInterval:
+ (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec));
+ return Undefined();
+ case Window::Print:
+ if ( widget ) {
+ // ### TODO emit onbeforeprint event
+ widget->print();
+ // ### TODO emit onafterprint event
+ }
+ case Window::CaptureEvents:
+ case Window::ReleaseEvents:
+ // Do nothing for now. These are NS-specific legacy calls.
+ break;
+ case Window::AddEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ if (listener) {
+ DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
+ docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
+ }
+ return Undefined();
+ }
+ case Window::RemoveEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ if (listener) {
+ DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
+ docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
+ }
+ return Undefined();
+ }
+
+ }
+ return Undefined();
+}
+
+////////////////////// ScheduledAction ////////////////////////
+
+// KDE 4: Make those parameters const ... &
+ScheduledAction::ScheduledAction(Object _func, List _args, DateTimeMS _nextTime, int _interval, bool _singleShot,
+ int _timerId)
+{
+ //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
+ func = static_cast<ObjectImp*>(_func.imp());
+ args = _args;
+ isFunction = true;
+ singleShot = _singleShot;
+ nextTime = _nextTime;
+ interval = _interval;
+ executing = false;
+ timerId = _timerId;
+}
+
+// KDE 4: Make it const TQString &
+ScheduledAction::ScheduledAction(TQString _code, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId)
+{
+ //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
+ //func = 0;
+ //args = 0;
+ func = 0;
+ code = _code;
+ isFunction = false;
+ singleShot = _singleShot;
+ nextTime = _nextTime;
+ interval = _interval;
+ executing = false;
+ timerId = _timerId;
+}
+
+bool ScheduledAction::execute(Window *window)
+{
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(window->m_frame->m_part);
+ if (!part || !part->jScriptEnabled())
+ return false;
+ ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
+
+ interpreter->setProcessingTimerCallback(true);
+
+ //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
+ if (isFunction) {
+ if (func->implementsCall()) {
+ // #### check this
+ Q_ASSERT( part );
+ if ( part )
+ {
+ KJS::Interpreter *interpreter = part->jScript()->interpreter();
+ ExecState *exec = interpreter->globalExec();
+ Q_ASSERT( window == interpreter->globalObject().imp() );
+ Object obj( window );
+ func->call(exec,obj,args); // note that call() creates its own execution state for the func call
+ if (exec->hadException())
+ exec->clearException();
+
+ // Update our document's rendering following the execution of the timeout callback.
+ part->document().updateRendering();
+ }
+ }
+ }
+ else {
+ part->executeScript(DOM::Node(), code);
+ }
+
+ interpreter->setProcessingTimerCallback(false);
+ return true;
+}
+
+void ScheduledAction::mark()
+{
+ if (func && !func->marked())
+ func->mark();
+ args.mark();
+}
+
+ScheduledAction::~ScheduledAction()
+{
+ //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
+}
+
+////////////////////// WindowQObject ////////////////////////
+
+WindowQObject::WindowQObject(Window *w)
+ : parent(w)
+{
+ //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
+ if ( !parent->m_frame )
+ kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl;
+ else
+ connect( parent->m_frame, TQT_SIGNAL( destroyed() ),
+ this, TQT_SLOT( parentDestroyed() ) );
+ pausedTime = 0;
+ lastTimerId = 0;
+ currentlyDispatching = false;
+}
+
+WindowQObject::~WindowQObject()
+{
+ //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
+ parentDestroyed(); // reuse same code
+}
+
+void WindowQObject::parentDestroyed()
+{
+ killTimers();
+
+ TQPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ delete it.current();
+ scheduledActions.clear();
+}
+
+int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
+{
+ int id = ++lastTimerId;
+ if (t < 10) t = 10;
+ DateTimeMS nextTime = DateTimeMS::now().addMSecs(-pausedTime + t);
+
+ ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
+ scheduledActions.append(action);
+ setNextTimer();
+ return id;
+}
+
+int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
+{
+ Object objFunc = Object::dynamicCast( func );
+ if (!objFunc.isValid())
+ return 0;
+ int id = ++lastTimerId;
+ if (t < 10) t = 10;
+
+ DateTimeMS nextTime = DateTimeMS::now().addMSecs(-pausedTime + t);
+ ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
+ scheduledActions.append(action);
+ setNextTimer();
+ return id;
+}
+
+void WindowQObject::clearTimeout(int timerId)
+{
+ TQPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it) {
+ ScheduledAction *action = it.current();
+ if (action->timerId == timerId) {
+ scheduledActions.removeRef(action);
+ if (!action->executing)
+ delete action;
+ return;
+ }
+ }
+}
+
+bool WindowQObject::hasTimers() const
+{
+ return scheduledActions.count();
+}
+
+void WindowQObject::mark()
+{
+ TQPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ it.current()->mark();
+}
+
+void WindowQObject::timerEvent(TQTimerEvent *)
+{
+ killTimers();
+
+ if (scheduledActions.isEmpty())
+ return;
+
+ currentlyDispatching = true;
+
+
+ DateTimeMS currentActual = DateTimeMS::now();
+ DateTimeMS currentAdjusted = currentActual.addMSecs(-pausedTime);
+
+ // Work out which actions are to be executed. We take a separate copy of
+ // this list since the main one may be modified during action execution
+ TQPtrList<ScheduledAction> toExecute;
+ TQPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ if (currentAdjusted >= it.current()->nextTime)
+ toExecute.append(it.current());
+
+ // ### verify that the window can't be closed (and action deleted) during execution
+ it = TQPtrListIterator<ScheduledAction>(toExecute);
+ for (; it.current(); ++it) {
+ ScheduledAction *action = it.current();
+ if (!scheduledActions.containsRef(action)) // removed by clearTimeout()
+ continue;
+
+ action->executing = true; // prevent deletion in clearTimeout()
+
+ if (parent->part()) {
+ bool ok = action->execute(parent);
+ if ( !ok ) // e.g. JS disabled
+ scheduledActions.removeRef( action );
+ }
+
+ if (action->singleShot) {
+ scheduledActions.removeRef(action);
+ }
+
+ action->executing = false;
+
+ if (!scheduledActions.containsRef(action))
+ delete action;
+ else
+ action->nextTime = action->nextTime.addMSecs(action->interval);
+ }
+
+ pausedTime += currentActual.msecsTo(DateTimeMS::now());
+
+ currentlyDispatching = false;
+
+ // Work out when next event is to occur
+ setNextTimer();
+}
+
+DateTimeMS DateTimeMS::addMSecs(int s) const
+{
+ DateTimeMS c = *this;
+ c.mTime = TQT_TQTIME_OBJECT(mTime.addMSecs(s));
+ if (s > 0)
+ {
+ if (c.mTime < mTime)
+ c.mDate = TQT_TQDATE_OBJECT(mDate.addDays(1));
+ }
+ else
+ {
+ if (c.mTime > mTime)
+ c.mDate = TQT_TQDATE_OBJECT(mDate.addDays(-1));
+ }
+ return c;
+}
+
+bool DateTimeMS::operator >(const DateTimeMS &other) const
+{
+ if (mDate > other.mDate)
+ return true;
+
+ if (mDate < other.mDate)
+ return false;
+
+ return mTime > other.mTime;
+}
+
+bool DateTimeMS::operator >=(const DateTimeMS &other) const
+{
+ if (mDate > other.mDate)
+ return true;
+
+ if (mDate < other.mDate)
+ return false;
+
+ return mTime >= other.mTime;
+}
+
+int DateTimeMS::msecsTo(const DateTimeMS &other) const
+{
+ int d = mDate.daysTo(other.mDate);
+ int ms = mTime.msecsTo(other.mTime);
+ return d*24*60*60*1000 + ms;
+}
+
+
+DateTimeMS DateTimeMS::now()
+{
+ DateTimeMS t;
+ TQTime before = TQTime::currentTime();
+ t.mDate = TQDate::currentDate();
+ t.mTime = TQTime::currentTime();
+ if (t.mTime < before)
+ t.mDate = TQDate::currentDate(); // prevent race condition in hacky way :)
+ return t;
+}
+
+void WindowQObject::setNextTimer()
+{
+ if (currentlyDispatching)
+ return; // Will schedule at the end
+
+ if (scheduledActions.isEmpty())
+ return;
+
+ TQPtrListIterator<ScheduledAction> it(scheduledActions);
+ DateTimeMS nextTime = it.current()->nextTime;
+ for (++it; it.current(); ++it)
+ if (nextTime > it.current()->nextTime)
+ nextTime = it.current()->nextTime;
+
+ DateTimeMS nextTimeActual = nextTime.addMSecs(pausedTime);
+ int nextInterval = DateTimeMS::now().msecsTo(nextTimeActual);
+ if (nextInterval < 0)
+ nextInterval = 0;
+ startTimer(nextInterval);
+}
+
+void WindowQObject::timeoutClose()
+{
+ parent->closeNow();
+}
+
+Value FrameArray::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
+#endif
+ if (part.isNull())
+ return Undefined();
+
+ TQPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (p == lengthPropertyName)
+ return Number(len);
+ else if (p== "location") // non-standard property, but works in NS and IE
+ {
+ Object obj = Object::dynamicCast( Window::retrieve( part ) );
+ if ( obj.isValid() )
+ return obj.get( exec, "location" );
+ return Undefined();
+ }
+
+ // check for the name or number
+ KParts::ReadOnlyPart *frame = part->findFramePart(p.qstring());
+ if (!frame) {
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok && i < len)
+ frame = frames.at(i);
+ }
+
+ // we are potentially fetching a reference to a another Window object here.
+ // i.e. we may be accessing objects from another interpreter instance.
+ // Therefore we have to be a bit careful with memory management.
+ if (frame) {
+ return Window::retrieve(frame);
+ }
+
+ // Fun IE quirk: name lookup in there is actually done by document.all
+ // hence, it can find non-frame things (and even let them hide frame ones!)
+ // We don't quite do that, but do this as a fallback.
+ DOM::DocumentImpl* doc = static_cast<DOM::DocumentImpl*>(part->document().handle());
+ if (doc) {
+ DOM::HTMLCollectionImpl docuAll(doc, DOM::HTMLCollectionImpl::DOC_ALL);
+ DOM::NodeImpl* node = docuAll.namedItem(p.string());
+ if (node) {
+ if (node->id() == ID_FRAME || node->id() == ID_IFRAME) {
+ //Return the Window object.
+ KHTMLPart* part = static_cast<DOM::HTMLFrameElementImpl*>(node)->contentPart();
+ if (part)
+ return Value(Window::retrieveWindow(part));
+ else
+ return Undefined();
+ } else {
+ //Just a regular node..
+ return getDOMNode(exec, node);
+ }
+ }
+ } else {
+ kdWarning(6070) << "Missing own document in FrameArray::get()" << endl;
+ }
+
+ return ObjectImp::get(exec, p);
+}
+
+Value FrameArray::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ //IE supports a subset of the get functionality as call...
+ //... basically, when the return is a window, it supports that, otherwise it
+ //errors out. We do a cheap-and-easy emulation of that, and just do the same
+ //thing as get does.
+ if (args.size() == 1)
+ return get(exec, Identifier(args[0].toString(exec)));
+
+ return Undefined();
+}
+
+
+////////////////////// Location Object ////////////////////////
+
+const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
+/*
+@begin LocationTable 11
+ hash Location::Hash DontDelete
+ host Location::Host DontDelete
+ hostname Location::Hostname DontDelete
+ href Location::Href DontDelete
+ pathname Location::Pathname DontDelete
+ port Location::Port DontDelete
+ protocol Location::Protocol DontDelete
+ search Location::Search DontDelete
+ [[==]] Location::EqualEqual DontDelete|ReadOnly
+ assign Location::Assign DontDelete|Function 1
+ toString Location::ToString DontDelete|Function 0
+ replace Location::Replace DontDelete|Function 1
+ reload Location::Reload DontDelete|Function 0
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
+Location::Location(tdehtml::ChildFrame *f) : m_frame(f)
+{
+ //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
+}
+
+Location::~Location()
+{
+ //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
+}
+
+KParts::ReadOnlyPart *Location::part() const {
+ return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
+}
+
+Value Location::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
+#endif
+
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return Undefined();
+
+ const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
+
+ // properties that work on all Location objects
+ if ( entry && entry->value == Replace )
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+
+ // XSS check
+ const Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( !window || !window->isSafeScript(exec) )
+ return Undefined();
+
+ KURL url = m_frame->m_part->url();
+ if (entry)
+ switch (entry->value) {
+ case Hash:
+ return String( url.ref().isNull() ? TQString("") : "#" + url.ref() );
+ case Host: {
+ UString str = url.host();
+ if (url.port())
+ str += ":" + TQString::number((int)url.port());
+ return String(str);
+ // Note: this is the IE spec. The NS spec swaps the two, it says
+ // "The hostname property is the concatenation of the host and port properties, separated by a colon."
+ // Bleh.
+ }
+ case Hostname:
+ return String( url.host() );
+ case Href:
+ if (url.isEmpty())
+ return String("about:blank");
+ else if (!url.hasPath())
+ return String( url.prettyURL()+"/" );
+ else
+ return String( url.prettyURL() );
+ case Pathname:
+ if (url.isEmpty())
+ return String("");
+ return String( url.path().isEmpty() ? TQString("/") : url.path() );
+ case Port:
+ return String( url.port() ? TQString::number((int)url.port()) : TQString::fromLatin1("") );
+ case Protocol:
+ return String( url.protocol()+":" );
+ case Search:
+ return String( url.query() );
+ case EqualEqual: // [[==]]
+ return String(toString(exec));
+ case ToString:
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ }
+ // Look for overrides
+ ValueImp * val = ObjectImp::getDirect(p);
+ if (val)
+ return Value(val);
+ if (entry && (entry->attr & Function))
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+
+ return Undefined();
+}
+
+void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
+#endif
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return;
+
+ const Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( !window )
+ return;
+
+ KURL url = m_frame->m_part->url();
+
+ const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
+
+ if (entry) {
+
+ // XSS check. Only new hrefs can be set from other sites
+ if (entry->value != Href && !window->isSafeScript(exec))
+ return;
+
+ TQString str = v.toString(exec).qstring();
+ switch (entry->value) {
+ case Href: {
+ KHTMLPart* p =::tqqt_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
+ if ( p )
+ url = p->htmlDocument().completeURL( str ).string();
+ else
+ url = str;
+ break;
+ }
+ case Hash:
+ // when the hash is already the same ignore it
+ if (str == url.ref()) return;
+ url.setRef(str);
+ break;
+ case Host: {
+ TQString host = str.left(str.find(":"));
+ TQString port = str.mid(str.find(":")+1);
+ url.setHost(host);
+ url.setPort(port.toUInt());
+ break;
+ }
+ case Hostname:
+ url.setHost(str);
+ break;
+ case Pathname:
+ url.setPath(str);
+ break;
+ case Port:
+ url.setPort(str.toUInt());
+ break;
+ case Protocol:
+ url.setProtocol(str);
+ break;
+ case Search:
+ url.setQuery(str);
+ break;
+ }
+ } else {
+ ObjectImp::put(exec, p, v, attr);
+ return;
+ }
+
+ Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
+}
+
+Value Location::toPrimitive(ExecState *exec, Type) const
+{
+ if (m_frame) {
+ Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( window && window->isSafeScript(exec) )
+ return String(toString(exec));
+ }
+ return Undefined();
+}
+
+UString Location::toString(ExecState *exec) const
+{
+ if (m_frame) {
+ Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( window && window->isSafeScript(exec) )
+ {
+ KURL url = m_frame->m_part->url();
+ if (url.isEmpty())
+ return "about:blank";
+ else if (!url.hasPath())
+ return url.prettyURL()+"/";
+ else
+ return url.prettyURL();
+ }
+ }
+ return "";
+}
+
+Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( Location, thisObj );
+ Location *location = static_cast<Location *>(thisObj.imp());
+ KParts::ReadOnlyPart *part = location->part();
+
+ if (!part) return Undefined();
+
+ Window* window = Window::retrieveWindow(part);
+
+ if ( !window->isSafeScript(exec) && id != Location::Replace)
+ return Undefined();
+
+ switch (id) {
+ case Location::Assign:
+ case Location::Replace:
+ Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(),
+ id == Location::Replace);
+ break;
+ case Location::Reload: {
+ KHTMLPart *tdehtmlpart = ::tqqt_cast<KHTMLPart *>(part);
+ if (tdehtmlpart)
+ tdehtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
+ else
+ part->openURL(part->url());
+ break;
+ }
+ case Location::ToString:
+ return String(location->toString(exec));
+ }
+ return Undefined();
+}
+
+////////////////////// External Object ////////////////////////
+
+const ClassInfo External::info = { "External", 0, 0, 0 };
+/*
+@begin ExternalTable 4
+ addFavorite External::AddFavorite DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(ExternalFunc)
+
+Value External::get(ExecState *exec, const Identifier &p) const
+{
+ return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this);
+}
+
+Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( External, thisObj );
+ External *external = static_cast<External *>(thisObj.imp());
+
+ KHTMLPart *part = external->part;
+ if (!part)
+ return Undefined();
+
+ KHTMLView *widget = part->view();
+
+ switch (id) {
+ case External::AddFavorite:
+ {
+#ifndef KONQ_EMBEDDED
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ part->xmlDocImpl()->updateRendering();
+ if (args.size() != 1 && args.size() != 2)
+ return Undefined();
+
+ TQString url = args[0].toString(exec).qstring();
+ TQString title;
+ if (args.size() == 2)
+ title = args[1].toString(exec).qstring();
+
+ // AK - don't do anything yet, for the moment i
+ // just wanted the base js handling code in cvs
+ return Undefined();
+
+ TQString question;
+ if ( title.isEmpty() )
+ question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?")
+ .arg(url);
+ else
+ question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?")
+ .arg(url).arg(title);
+
+ emit part->browserExtension()->requestFocus(part);
+
+ TQString caption;
+ if (!part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += i18n("JavaScript Attempted Bookmark Insert");
+
+ if (KMessageBox::warningYesNo(
+ widget, question, caption,
+ i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes)
+ {
+ KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
+ mgr->addBookmarkDialog(url,title);
+ }
+#else
+ return Undefined();
+#endif
+ break;
+ }
+ default:
+ return Undefined();
+ }
+
+ return Undefined();
+}
+
+////////////////////// History Object ////////////////////////
+
+const ClassInfo History::info = { "History", 0, 0, 0 };
+/*
+@begin HistoryTable 4
+ length History::Length DontDelete|ReadOnly
+ back History::Back DontDelete|Function 0
+ forward History::Forward DontDelete|Function 0
+ go History::Go DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
+
+Value History::get(ExecState *exec, const Identifier &p) const
+{
+ return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
+}
+
+Value History::getValueProperty(ExecState *, int token) const
+{
+ // if previous or next is implemented, make sure its not a major
+ // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
+ switch (token) {
+ case Length:
+ {
+ if ( !part )
+ return Number( 0 );
+
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if ( !ext )
+ return Number( 0 );
+
+ KParts::BrowserInterface *iface = ext->browserInterface();
+ if ( !iface )
+ return Number( 0 );
+
+ TQVariant length = iface->property( "historyLength" );
+
+ if ( length.type() != TQVariant::UInt )
+ return Number( 0 );
+
+ return Number( length.toUInt() );
+ }
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( History, thisObj );
+ History *history = static_cast<History *>(thisObj.imp());
+
+ Value v = args[0];
+ Number n;
+ if(v.isValid())
+ n = v.toInteger(exec);
+
+ int steps;
+ switch (id) {
+ case History::Back:
+ steps = -1;
+ break;
+ case History::Forward:
+ steps = 1;
+ break;
+ case History::Go:
+ steps = n.intValue();
+ break;
+ default:
+ return Undefined();
+ }
+
+ // Special case for go(0) from a frame -> reload only the frame
+ // go(i!=0) from a frame navigates into the history of the frame only,
+ // in both IE and NS (but not in Mozilla).... we can't easily do that
+ // in Konqueror...
+ if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
+ {
+ history->part->openURL( history->part->url() ); /// ## need args.reload=true?
+ } else
+ {
+ // Delay it.
+ // Testcase: history.back(); alert("hello");
+ Window* window = Window::retrieveWindow( history->part );
+ window->delayedGoHistory( steps );
+ }
+ return Undefined();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef Q_WS_QWS
+
+const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
+
+bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ if ( p.qstring().startsWith( "goHistory" ) ) return false;
+
+ return true;
+}
+
+Value Konqueror::get(ExecState *exec, const Identifier &p) const
+{
+ if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
+ return Undefined();
+
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if ( ext ) {
+ KParts::BrowserInterface *iface = ext->browserInterface();
+ if ( iface ) {
+ TQVariant prop = iface->property( p.qstring().latin1() );
+
+ if ( prop.isValid() ) {
+ switch( prop.type() ) {
+ case TQVariant::Int:
+ return Number( prop.toInt() );
+ case TQVariant::String:
+ return String( prop.toString() );
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Value( new KonquerorFunc(exec, this, p.qstring().latin1() ) );
+}
+
+Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
+{
+ KParts::BrowserExtension *ext = konqueror->part->browserExtension();
+
+ if (!ext)
+ return Undefined();
+
+ KParts::BrowserInterface *iface = ext->browserInterface();
+
+ if ( !iface )
+ return Undefined();
+
+ TQCString n = m_name.data();
+ n += "()";
+ iface->callMethod( n.data(), TQVariant() );
+
+ return Undefined();
+}
+
+UString Konqueror::toString(ExecState *) const
+{
+ return UString("[object Konqueror]");
+}
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+} //namespace KJS
+
+#include "kjs_window.moc"
diff --git a/tdehtml/ecma/kjs_window.h b/tdehtml/ecma/kjs_window.h
new file mode 100644
index 000000000..b9142f983
--- /dev/null
+++ b/tdehtml/ecma/kjs_window.h
@@ -0,0 +1,309 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@kde.org)
+ * Copyright (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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _KJS_WINDOW_H_
+#define _KJS_WINDOW_H_
+
+#include <tqobject.h>
+#include <tqguardedptr.h>
+#include <tqmap.h>
+#include <tqptrlist.h>
+#include <tqdatetime.h>
+
+#include "kjs_binding.h"
+#include "kjs_views.h"
+
+class TQTimer;
+class KHTMLView;
+class KHTMLPart;
+
+namespace KParts {
+ class ReadOnlyPart;
+}
+
+namespace tdehtml {
+ class ChildFrame;
+}
+
+namespace KJS {
+
+ class WindowFunc;
+ class WindowQObject;
+ class Location;
+ class History;
+ class External;
+ class FrameArray;
+ class JSEventListener;
+ class JSLazyEventListener;
+
+ class Screen : public ObjectImp {
+ public:
+ Screen(ExecState *exec);
+ enum {
+ Height, Width, ColorDepth, PixelDepth, AvailLeft, AvailTop, AvailHeight,
+ AvailWidth
+ };
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ private:
+ KHTMLView *view;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ };
+
+ class KDE_EXPORT Window : public ObjectImp {
+ friend TQGuardedPtr<KHTMLPart> getInstance();
+ friend class Location;
+ friend class WindowFunc;
+ friend class WindowQObject;
+ friend class ScheduledAction;
+ public:
+ Window(tdehtml::ChildFrame *p);
+ public:
+ ~Window();
+ /**
+ * Returns and registers a window object. In case there's already a Window
+ * for the specified part p this will be returned in order to have unique
+ * bindings.
+ */
+ static Value retrieve(KParts::ReadOnlyPart *p);
+ /**
+ * Returns the Window object for a given part
+ */
+ static Window *retrieveWindow(KParts::ReadOnlyPart *p);
+ /**
+ * returns a pointer to the Window object this javascript interpreting instance
+ * was called from.
+ */
+ static Window *retrieveActive(ExecState *exec);
+ KParts::ReadOnlyPart *part() const;
+ virtual void mark();
+ virtual bool hasProperty(ExecState *exec, const Identifier &p) const;
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
+ virtual bool toBoolean(ExecState *exec) const;
+ virtual DOM::AbstractView toAbstractView() const;
+ void scheduleClose();
+ void closeNow();
+ void delayedGoHistory(int steps);
+ void goHistory(int steps);
+ void goURL(ExecState* exec, const TQString& url, bool lockHistory);
+ Value openWindow(ExecState *exec, const List &args);
+ Value executeOpenWindow(ExecState *exec, const KURL& url, const TQString& frameName, const TQString& features);
+ void resizeTo(TQWidget* tl, int width, int height);
+ void afterScriptExecution();
+ bool isSafeScript(ExecState *exec) const {
+ KParts::ReadOnlyPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->interpreter() )->part();
+ if ( activePart == part() ) return true;
+ return checkIsSafeScript( activePart );
+ }
+ Location *location() const;
+ ObjectImp* frames( ExecState* exec ) const;
+ JSEventListener *getJSEventListener(const Value &val, bool html = false);
+ JSLazyEventListener *getJSLazyEventListener(const TQString &code, const TQString &name, DOM::NodeImpl* node);
+ void clear( ExecState *exec );
+ virtual UString toString(ExecState *exec) const;
+
+ // Set the current "event" object
+ void setCurrentEvent( DOM::Event *evt );
+
+ TQPtrDict<JSEventListener> jsEventListeners;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Closed, Crypto, DefaultStatus, Status, Document, Node, EventCtor, Range,
+ NodeFilter, DOMException, CSSRule, Frames, _History, _External, Event, InnerHeight,
+ InnerWidth, Length, _Location, Navigate, Name, _Navigator, _Konqueror, ClientInformation,
+ OffscreenBuffering, Opener, OuterHeight, OuterWidth, PageXOffset, PageYOffset,
+ Parent, Personalbar, ScreenX, ScreenY, Scrollbars, Scroll, ScrollBy,
+ ScreenTop, ScreenLeft, AToB, BToA, FrameElement, GetComputedStyle,
+ ScrollTo, ScrollX, ScrollY, MoveBy, MoveTo, ResizeBy, ResizeTo, Self, _Window, Top, _Screen,
+ Image, Option, Alert, Confirm, Prompt, Open, SetTimeout, ClearTimeout,
+ XMLHttpRequest, XMLSerializer, DOMParser,
+ Focus, Blur, Close, SetInterval, ClearInterval, CaptureEvents, ReleaseEvents,
+ Print, AddEventListener, RemoveEventListener, SideBar,
+ ValueOf, ToString,
+ Onabort, Onblur,
+ Onchange, Onclick, Ondblclick, Ondragdrop, Onerror, Onfocus,
+ Onkeydown, Onkeypress, Onkeyup, Onload, Onmousedown, Onmousemove,
+ Onmouseout, Onmouseover, Onmouseup, Onmove, Onreset, Onresize,
+ Onselect, Onsubmit, Onunload,
+ MutationEventCtor, KeyboardEventCtor, EventExceptionCtor,
+ ElementCtor, DocumentCtor, HTMLDocumentCtor,
+ HTMLElementCtor, HTMLHtmlElementCtor, HTMLHeadElementCtor, HTMLLinkElementCtor,
+ HTMLTitleElementCtor, HTMLMetaElementCtor, HTMLBaseElementCtor, HTMLIsIndexElementCtor,
+ HTMLStyleElementCtor, HTMLBodyElementCtor, HTMLFormElementCtor, HTMLSelectElementCtor,
+ HTMLOptGroupElementCtor, HTMLOptionElementCtor, HTMLInputElementCtor, HTMLTextAreaElementCtor,
+ HTMLButtonElementCtor, HTMLLabelElementCtor, HTMLFieldSetElementCtor, HTMLLegendElementCtor,
+ HTMLUListElementCtor, HTMLOListElementCtor, HTMLDListElementCtor, HTMLDirectoryElementCtor,
+ HTMLMenuElementCtor, HTMLLIElementCtor, HTMLDivElementCtor, HTMLParagraphElementCtor,
+ HTMLHeadingElementCtor, HTMLBlockQuoteElementCtor, HTMLQuoteElementCtor, HTMLPreElementCtor,
+ HTMLBRElementCtor, HTMLBaseFontElementCtor, HTMLFontElementCtor, HTMLHRElementCtor, HTMLModElementCtor,
+ HTMLAnchorElementCtor, HTMLImageElementCtor, HTMLObjectElementCtor, HTMLParamElementCtor,
+ HTMLAppletElementCtor, HTMLMapElementCtor, HTMLAreaElementCtor, HTMLScriptElementCtor,
+ HTMLTableElementCtor, HTMLTableCaptionElementCtor, HTMLTableColElementCtor,
+ HTMLTableSectionElementCtor, HTMLTableRowElementCtor, HTMLTableCellElementCtor,
+ HTMLFrameSetElementCtor, HTMLLayerElementCtor, HTMLFrameElementCtor, HTMLIFrameElementCtor,
+ CSSStyleDeclarationCtor};
+ WindowQObject *winq;
+
+ void forgetSuppressedWindows();
+ void showSuppressedWindows();
+
+ protected:
+ enum DelayedActionId { NullAction, DelayedClose, DelayedGoHistory };
+
+ Value getListener(ExecState *exec, int eventId) const;
+ void setListener(ExecState *exec, int eventId, Value func);
+ private:
+ struct DelayedAction;
+ friend struct DelayedAction;
+
+ bool checkIsSafeScript( KParts::ReadOnlyPart* activePart ) const;
+
+ TQGuardedPtr<tdehtml::ChildFrame> m_frame;
+ Screen *screen;
+ History *history;
+ External *external;
+ FrameArray *m_frames;
+ Location *loc;
+ DOM::Event *m_evt;
+
+ struct DelayedAction {
+ DelayedAction() : actionId(NullAction) {} // for QValueList
+ DelayedAction( DelayedActionId id, TQVariant p = TQVariant() ) : actionId(id), param(p) {}
+ DelayedActionId actionId;
+ TQVariant param; // just in case
+ };
+ TQValueList<DelayedAction> m_delayed;
+
+ struct SuppressedWindowInfo {
+ SuppressedWindowInfo() {} // for QValueList
+ SuppressedWindowInfo( KURL u, TQString fr, TQString fe ) : url(u), frameName(fr), features(fe) {}
+ KURL url;
+ TQString frameName;
+ TQString features;
+ };
+ TQValueList<SuppressedWindowInfo> m_suppressedWindowInfo;
+ };
+
+ /**
+ * like TQDateTime, but properly handles milliseconds
+ */
+ class DateTimeMS
+ {
+ TQDate mDate;
+ TQTime mTime;
+ public:
+ DateTimeMS addMSecs(int s) const;
+ bool operator >(const DateTimeMS &other) const;
+ bool operator >=(const DateTimeMS &other) const;
+
+ int msecsTo(const DateTimeMS &other) const;
+
+ static DateTimeMS now();
+ };
+
+ /**
+ * An action (either function or string) to be executed after a specified
+ * time interval, either once or repeatedly. Used for window.setTimeout()
+ * and window.setInterval()
+ */
+ class ScheduledAction {
+ public:
+ ScheduledAction(Object _func, List _args, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId);
+ ScheduledAction(TQString _code, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId);
+ ~ScheduledAction();
+ bool execute(Window *window);
+ void mark();
+
+ ObjectImp *func;
+ List args;
+ TQString code;
+ bool isFunction;
+ bool singleShot;
+
+ DateTimeMS nextTime;
+ int interval;
+ bool executing;
+ int timerId;
+ };
+
+ class KDE_EXPORT WindowQObject : public TQObject {
+ Q_OBJECT
+ public:
+ WindowQObject(Window *w);
+ ~WindowQObject();
+ int installTimeout(const Identifier &handler, int t, bool singleShot);
+ int installTimeout(const Value &func, List args, int t, bool singleShot);
+ void clearTimeout(int timerId);
+ void mark();
+ bool hasTimers() const;
+ public slots:
+ void timeoutClose();
+ protected slots:
+ void parentDestroyed();
+ protected:
+ void timerEvent(TQTimerEvent *e);
+ void setNextTimer();
+ private:
+ Window *parent;
+ TQPtrList<ScheduledAction> scheduledActions;
+ int pausedTime;
+ int lastTimerId;
+ bool currentlyDispatching;
+ };
+
+ class Location : public ObjectImp {
+ public:
+ ~Location();
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
+ virtual Value toPrimitive(ExecState *exec, Type preferred) const;
+ virtual UString toString(ExecState *exec) const;
+ enum { Hash, Href, Hostname, Host, Pathname, Port, Protocol, Search, EqualEqual,
+ Assign, Replace, Reload, ToString };
+ KParts::ReadOnlyPart *part() const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ private:
+ friend class Window;
+ Location(tdehtml::ChildFrame *f);
+ TQGuardedPtr<tdehtml::ChildFrame> m_frame;
+ };
+
+#ifdef Q_WS_QWS
+ class Konqueror : public ObjectImp {
+ friend class KonquerorFunc;
+ public:
+ Konqueror(KHTMLPart *p) : part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual bool hasProperty(ExecState *exec, const Identifier &p) const;
+ virtual UString toString(ExecState *exec) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ private:
+ KHTMLPart *part;
+ };
+#endif
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/testecma.cpp b/tdehtml/ecma/testecma.cpp
new file mode 100644
index 000000000..44cd7ecb0
--- /dev/null
+++ b/tdehtml/ecma/testecma.cpp
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000 Harri Porten (porten@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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * An interactive interpreter to test the ECMA Script language bindings
+ * for the DOM of KHTML.
+ * The 'document' property is preset to an instance of Document and serves
+ * as an entrypoint.
+ *
+ * Example session:
+ *
+ * KJS> text = document.createTextNode('foo');
+ * KJS> document.appendChild(text);
+ * KJS> debug(document.firstChild.nodeValue);
+ * ---> foo
+ */
+
+#include <stdio.h>
+#include <kjs/object.h>
+#include <kjs/interpreter.h>
+#include "dom/dom_doc.h"
+#include "dom/dom_string.h"
+#include "ecma/kjs_dom.h"
+
+
+using namespace KJS;
+
+int main(int, char **)
+{
+ KJScript kjs;
+ kjs.enableDebug();
+ DOM::Document doc;
+
+ DOMDocument *dd = new DOMDocument(&doc);
+ Global::current().put("document", KJSO(dd));
+
+ printf("Entering interactive mode.\n"
+ "You may access the DOM via the 'document' property.\n"
+ "Use debug() to print to the console. Press C-d or C-c to exit.\n\n");
+
+ char buffer[1000];
+ FILE *in = fdopen(0, "r");
+
+ while (1) {
+ printf("KJS> ");
+ if (!fgets(buffer, 999, in))
+ break;
+ kjs.evaluate(buffer);
+ }
+ printf("\n");
+}
diff --git a/tdehtml/ecma/xmlhttprequest.cpp b/tdehtml/ecma/xmlhttprequest.cpp
new file mode 100644
index 000000000..f3aec5492
--- /dev/null
+++ b/tdehtml/ecma/xmlhttprequest.cpp
@@ -0,0 +1,810 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "xmlhttprequest.h"
+#include "xmlhttprequest.lut.h"
+#include "kjs_window.h"
+#include "kjs_events.h"
+
+#include "dom/dom_doc.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_string.h"
+#include "misc/loader.h"
+#include "html/html_documentimpl.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include "tdehtml_part.h"
+#include "tdehtmlview.h"
+
+#include <kio/scheduler.h>
+#include <kio/job.h>
+#include <tqobject.h>
+#include <kdebug.h>
+
+#ifdef APPLE_CHANGES
+#include "KWQLoader.h"
+#else
+#include <kio/netaccess.h>
+using TDEIO::NetAccess;
+#endif
+
+#define BANNED_HTTP_HEADERS "authorization,proxy-authorization,"\
+ "content-length,host,connect,copy,move,"\
+ "delete,head,trace,put,propfind,proppatch,"\
+ "mkcol,lock,unlock,options,via,"\
+ "accept-charset,accept-encoding,expect,date,"\
+ "keep-alive,te,trailer,"\
+ "transfer-encoding,upgrade"
+
+using tdehtml::Decoder;
+
+namespace KJS {
+
+////////////////////// XMLHttpRequest Object ////////////////////////
+
+/* Source for XMLHttpRequestProtoTable.
+@begin XMLHttpRequestProtoTable 7
+ abort XMLHttpRequest::Abort DontDelete|Function 0
+ getAllResponseHeaders XMLHttpRequest::GetAllResponseHeaders DontDelete|Function 0
+ getResponseHeader XMLHttpRequest::GetResponseHeader DontDelete|Function 1
+ open XMLHttpRequest::Open DontDelete|Function 5
+ overrideMimeType XMLHttpRequest::OverrideMIMEType DontDelete|Function 1
+ send XMLHttpRequest::Send DontDelete|Function 1
+ setRequestHeader XMLHttpRequest::SetRequestHeader DontDelete|Function 2
+@end
+*/
+KJS_DEFINE_PROTOTYPE(XMLHttpRequestProto)
+IMPLEMENT_PROTOFUNC_DOM(XMLHttpRequestProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("XMLHttpRequest", XMLHttpRequestProto,XMLHttpRequestProtoFunc)
+
+
+XMLHttpRequestQObject::XMLHttpRequestQObject(XMLHttpRequest *_jsObject)
+{
+ jsObject = _jsObject;
+}
+
+#ifdef APPLE_CHANGES
+void XMLHttpRequestQObject::slotData( TDEIO::Job* job, const char *data, int size )
+{
+ jsObject->slotData(job, data, size);
+}
+#else
+void XMLHttpRequestQObject::slotData( TDEIO::Job* job, const TQByteArray &data )
+{
+ jsObject->slotData(job, data);
+}
+#endif
+
+void XMLHttpRequestQObject::slotFinished( TDEIO::Job* job )
+{
+ jsObject->slotFinished(job);
+}
+
+void XMLHttpRequestQObject::slotRedirection( TDEIO::Job* job, const KURL& url)
+{
+ jsObject->slotRedirection( job, url );
+}
+
+XMLHttpRequestConstructorImp::XMLHttpRequestConstructorImp(ExecState *, const DOM::Document &d)
+ : ObjectImp(), doc(d)
+{
+}
+
+bool XMLHttpRequestConstructorImp::implementsConstruct() const
+{
+ return true;
+}
+
+Object XMLHttpRequestConstructorImp::construct(ExecState *exec, const List &)
+{
+ return Object(new XMLHttpRequest(exec, doc));
+}
+
+const ClassInfo XMLHttpRequest::info = { "XMLHttpRequest", 0, &XMLHttpRequestTable, 0 };
+
+
+/* Source for XMLHttpRequestTable.
+@begin XMLHttpRequestTable 7
+ readyState XMLHttpRequest::ReadyState DontDelete|ReadOnly
+ responseText XMLHttpRequest::ResponseText DontDelete|ReadOnly
+ responseXML XMLHttpRequest::ResponseXML DontDelete|ReadOnly
+ status XMLHttpRequest::Status DontDelete|ReadOnly
+ statusText XMLHttpRequest::StatusText DontDelete|ReadOnly
+ onreadystatechange XMLHttpRequest::Onreadystatechange DontDelete
+ onload XMLHttpRequest::Onload DontDelete
+@end
+*/
+
+Value XMLHttpRequest::tryGet(ExecState *exec, const Identifier &propertyName) const
+{
+ return DOMObjectLookupGetValue<XMLHttpRequest,DOMObject>(exec, propertyName, &XMLHttpRequestTable, this);
+}
+
+Value XMLHttpRequest::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case ReadyState:
+ return Number(state);
+ case ResponseText:
+ return getString(DOM::DOMString(response));
+ case ResponseXML:
+ if (state != Completed) {
+ return Null();
+ }
+ if (!createdDocument) {
+ TQString mimeType = "text/xml";
+
+ if (!m_mimeTypeOverride.isEmpty()) {
+ mimeType = m_mimeTypeOverride;
+ } else {
+ Value header = getResponseHeader("Content-Type");
+ if (header.type() != UndefinedType) {
+ mimeType = TQStringList::split(";", header.toString(exec).qstring())[0].stripWhiteSpace();
+ }
+ }
+
+ if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "application/xhtml+xml") {
+ responseXML = DOM::Document(doc->implementation()->createDocument());
+
+ DOM::DocumentImpl *docImpl = static_cast<DOM::DocumentImpl *>(responseXML.handle());
+
+ docImpl->open();
+ docImpl->write(response);
+ docImpl->finishParsing();
+ docImpl->close();
+
+ typeIsXML = true;
+ } else {
+ typeIsXML = false;
+ }
+ createdDocument = true;
+ }
+
+ if (!typeIsXML) {
+ return Undefined();
+ }
+
+ return getDOMNode(exec,responseXML);
+ case Status:
+ return getStatus();
+ case StatusText:
+ return getStatusText();
+ case Onreadystatechange:
+ if (onReadyStateChangeListener && onReadyStateChangeListener->listenerObjImp()) {
+ return onReadyStateChangeListener->listenerObj();
+ } else {
+ return Null();
+ }
+ case Onload:
+ if (onLoadListener && onLoadListener->listenerObjImp()) {
+ return onLoadListener->listenerObj();
+ } else {
+ return Null();
+ }
+ default:
+ kdWarning() << "XMLHttpRequest::getValueProperty unhandled token " << token << endl;
+ return Value();
+ }
+}
+
+void XMLHttpRequest::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
+{
+ DOMObjectLookupPut<XMLHttpRequest,DOMObject>(exec, propertyName, value, attr, &XMLHttpRequestTable, this );
+}
+
+void XMLHttpRequest::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
+{
+ JSEventListener* newListener;
+ switch(token) {
+ case Onreadystatechange:
+ newListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
+ if (newListener != onReadyStateChangeListener) {
+ if (onReadyStateChangeListener) onReadyStateChangeListener->deref();
+ onReadyStateChangeListener = newListener;
+ if (onReadyStateChangeListener) onReadyStateChangeListener->ref();
+ }
+ break;
+ case Onload:
+ newListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
+ if (newListener != onLoadListener) {
+ if (onLoadListener) onLoadListener->deref();
+ onLoadListener = newListener;
+ if (onLoadListener) onLoadListener->ref();
+ }
+ break;
+ default:
+ kdWarning() << "XMLHttpRequest::putValue unhandled token " << token << endl;
+ }
+}
+
+XMLHttpRequest::XMLHttpRequest(ExecState *exec, const DOM::Document &d)
+ : DOMObject(XMLHttpRequestProto::self(exec)),
+ qObject(new XMLHttpRequestQObject(this)),
+ doc(static_cast<DOM::DocumentImpl*>(d.handle())),
+ async(true),
+ contentType(TQString::null),
+ job(0),
+ state(Uninitialized),
+ onReadyStateChangeListener(0),
+ onLoadListener(0),
+ decoder(0),
+ createdDocument(false),
+ aborted(false)
+{
+}
+
+XMLHttpRequest::~XMLHttpRequest()
+{
+ if (onReadyStateChangeListener)
+ onReadyStateChangeListener->deref();
+ if (onLoadListener)
+ onLoadListener->deref();
+ delete qObject;
+ qObject = 0;
+ delete decoder;
+ decoder = 0;
+}
+
+void XMLHttpRequest::changeState(XMLHttpRequestState newState)
+{
+ if (state != newState) {
+ state = newState;
+
+ ref();
+
+ if (onReadyStateChangeListener != 0 && doc->view() && doc->view()->part()) {
+ DOM::Event ev = doc->view()->part()->document().createEvent("HTMLEvents");
+ ev.initEvent("readystatechange", true, true);
+ onReadyStateChangeListener->handleEvent(ev);
+ }
+
+ if (state == Completed && onLoadListener != 0 && doc->view() && doc->view()->part()) {
+ DOM::Event ev = doc->view()->part()->document().createEvent("HTMLEvents");
+ ev.initEvent("load", true, true);
+ onLoadListener->handleEvent(ev);
+ }
+
+ deref();
+ }
+}
+
+bool XMLHttpRequest::urlMatchesDocumentDomain(const KURL& _url) const
+{
+ // No need to do work if _url is not valid...
+ if (!_url.isValid())
+ return false;
+
+ KURL documentURL(doc->URL());
+
+ // a local file can load anything
+ if (documentURL.protocol().lower() == "file") {
+ return true;
+ }
+
+ // but a remote document can only load from the same port on the server
+ if (documentURL.protocol().lower() == _url.protocol().lower() &&
+ documentURL.host().lower() == _url.host().lower() &&
+ documentURL.port() == _url.port()) {
+ return true;
+ }
+
+ return false;
+}
+
+void XMLHttpRequest::open(const TQString& _method, const KURL& _url, bool _async)
+{
+ abort();
+ aborted = false;
+
+ // clear stuff from possible previous load
+ requestHeaders.clear();
+ responseHeaders = TQString();
+ response = TQString();
+ createdDocument = false;
+ responseXML = DOM::Document();
+
+ changeState(Uninitialized);
+
+ if (aborted) {
+ return;
+ }
+
+ if (!urlMatchesDocumentDomain(_url)) {
+ return;
+ }
+
+
+ method = _method.lower();
+ url = _url;
+ async = _async;
+
+ changeState(Loading);
+}
+
+void XMLHttpRequest::send(const TQString& _body)
+{
+ aborted = false;
+
+ const TQString protocol = url.protocol().lower();
+ // Abandon the request when the protocol is other than "http",
+ // instead of blindly doing a TDEIO::get on other protocols like file:/.
+ if (!protocol.startsWith("http") && !protocol.startsWith("webdav"))
+ {
+ abort();
+ return;
+ }
+
+ if (method == "post") {
+
+ // FIXME: determine post encoding correctly by looking in headers
+ // for charset.
+ TQByteArray buf;
+ TQCString str = _body.utf8();
+ buf.duplicate(str.data(), str.size() - 1);
+
+ job = TDEIO::http_post( url, buf, false );
+ if(contentType.isNull())
+ job->addMetaData( "content-type", "Content-type: text/plain" );
+ else
+ job->addMetaData( "content-type", contentType );
+ }
+ else {
+ job = TDEIO::get( url, false, false );
+ }
+
+ if (!requestHeaders.isEmpty()) {
+ TQString rh;
+ TQMap<TQString, TQString>::ConstIterator begin = requestHeaders.begin();
+ TQMap<TQString, TQString>::ConstIterator end = requestHeaders.end();
+ for (TQMap<TQString, TQString>::ConstIterator i = begin; i != end; ++i) {
+ TQString key = i.key();
+ TQString value = i.data();
+ if (key == "accept") {
+ // The HTTP KIO slave supports an override this way
+ job->addMetaData("accept", value);
+ } else {
+ if (i != begin)
+ rh += "\r\n";
+ rh += key + ": " + value;
+ }
+ }
+
+ job->addMetaData("customHTTPHeader", rh);
+ }
+
+ job->addMetaData("PropagateHttpHeader", "true");
+
+ // Set the default referrer if one is not already supplied
+ // through setRequestHeader. NOTE: the user can still disable
+ // this feature at the protocol level (kio_http).
+ // ### does find() ever succeed? the headers are stored in lower case!
+ if (requestHeaders.find("Referer") == requestHeaders.end()) {
+ KURL documentURL(doc->URL());
+ documentURL.setPass(TQString::null);
+ documentURL.setUser(TQString::null);
+ job->addMetaData("referrer", documentURL.url());
+ // kdDebug() << "Adding referrer: " << documentURL << endl;
+ }
+
+ if (!async) {
+ TQByteArray data;
+ KURL finalURL;
+ TQString headers;
+
+#ifdef APPLE_CHANGES
+ data = KWQServeSynchronousRequest(tdehtml::Cache::loader(), doc->docLoader(), job, finalURL, headers);
+#else
+ TQMap<TQString, TQString> metaData;
+ if ( NetAccess::synchronousRun( job, 0, &data, &finalURL, &metaData ) ) {
+ headers = metaData[ "HTTP-Headers" ];
+ }
+#endif
+ job = 0;
+ processSyncLoadResults(data, finalURL, headers);
+ return;
+ }
+
+ qObject->connect( job, TQT_SIGNAL( result( TDEIO::Job* ) ),
+ TQT_SLOT( slotFinished( TDEIO::Job* ) ) );
+#ifdef APPLE_CHANGES
+ qObject->connect( job, TQT_SIGNAL( data( TDEIO::Job*, const char*, int ) ),
+ TQT_SLOT( slotData( TDEIO::Job*, const char*, int ) ) );
+#else
+ qObject->connect( job, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
+ TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray& ) ) );
+#endif
+ qObject->connect( job, TQT_SIGNAL(redirection(TDEIO::Job*, const KURL& ) ),
+ TQT_SLOT( slotRedirection(TDEIO::Job*, const KURL&) ) );
+
+#ifdef APPLE_CHANGES
+ KWQServeRequest(tdehtml::Cache::loader(), doc->docLoader(), job);
+#else
+ TDEIO::Scheduler::scheduleJob( job );
+#endif
+}
+
+void XMLHttpRequest::abort()
+{
+ if (job) {
+ job->kill();
+ job = 0;
+ }
+ delete decoder;
+ decoder = 0;
+ aborted = true;
+}
+
+void XMLHttpRequest::overrideMIMEType(const TQString& override)
+{
+ m_mimeTypeOverride = override;
+}
+
+void XMLHttpRequest::setRequestHeader(const TQString& _name, const TQString &value)
+{
+ TQString name = _name.lower().stripWhiteSpace();
+
+ // Content-type needs to be set seperately from the other headers
+ if(name == "content-type") {
+ contentType = "Content-type: " + value;
+ return;
+ }
+
+ // Sanitize the referrer header to protect against spoofing...
+ if(name == "referer") {
+ KURL referrerURL(value);
+ if (urlMatchesDocumentDomain(referrerURL))
+ requestHeaders[name] = referrerURL.url();
+ return;
+ }
+
+ // Sanitize the request headers below and handle them as if they are
+ // calls to open. Otherwise, we will end up ignoring them all together!
+ // TODO: Do something about "put" which kio_http sort of supports and
+ // the webDAV headers such as PROPFIND etc...
+ if (name == "get" || name == "post") {
+ KURL reqURL (doc->URL(), value.stripWhiteSpace());
+ open(name, reqURL, async);
+ return;
+ }
+
+ // Reject all banned headers. See BANNED_HTTP_HEADERS above.
+ // kdDebug() << "Banned HTTP Headers: " << BANNED_HTTP_HEADERS << endl;
+ TQStringList bannedHeaders = TQStringList::split(',',
+ TQString::fromLatin1(BANNED_HTTP_HEADERS));
+
+ if (bannedHeaders.contains(name))
+ return; // Denied
+
+ requestHeaders[name] = value.stripWhiteSpace();
+}
+
+Value XMLHttpRequest::getAllResponseHeaders() const
+{
+ if (responseHeaders.isEmpty()) {
+ return Undefined();
+ }
+
+ int endOfLine = responseHeaders.find("\n");
+
+ if (endOfLine == -1) {
+ return Undefined();
+ }
+
+ return String(responseHeaders.mid(endOfLine + 1) + "\n");
+}
+
+Value XMLHttpRequest::getResponseHeader(const TQString& name) const
+{
+ if (responseHeaders.isEmpty()) {
+ return Undefined();
+ }
+
+ TQRegExp headerLinePattern(name + ":", false);
+
+ int matchLength;
+ int headerLinePos = headerLinePattern.search(responseHeaders, 0);
+ matchLength = headerLinePattern.matchedLength();
+ while (headerLinePos != -1) {
+ if (headerLinePos == 0 || responseHeaders[headerLinePos-1] == '\n') {
+ break;
+ }
+
+ headerLinePos = headerLinePattern.search(responseHeaders, headerLinePos + 1);
+ matchLength = headerLinePattern.matchedLength();
+ }
+
+
+ if (headerLinePos == -1) {
+ return Undefined();
+ }
+
+ int endOfLine = responseHeaders.find("\n", headerLinePos + matchLength);
+
+ return String(responseHeaders.mid(headerLinePos + matchLength, endOfLine - (headerLinePos + matchLength)).stripWhiteSpace());
+}
+
+static Value httpStatus(const TQString& response, bool textStatus = false)
+{
+ if (response.isEmpty()) {
+ return Undefined();
+ }
+
+ int endOfLine = response.find("\n");
+ TQString firstLine = (endOfLine == -1) ? response : response.left(endOfLine);
+ int codeStart = firstLine.find(" ");
+ int codeEnd = firstLine.find(" ", codeStart + 1);
+
+ if (codeStart == -1 || codeEnd == -1) {
+ return Undefined();
+ }
+
+ if (textStatus) {
+ TQString statusText = firstLine.mid(codeEnd + 1, endOfLine - (codeEnd + 1)).stripWhiteSpace();
+ return String(statusText);
+ }
+
+ TQString number = firstLine.mid(codeStart + 1, codeEnd - (codeStart + 1));
+
+ bool ok = false;
+ int code = number.toInt(&ok);
+ if (!ok) {
+ return Undefined();
+ }
+
+ return Number(code);
+}
+
+Value XMLHttpRequest::getStatus() const
+{
+ return httpStatus(responseHeaders);
+}
+
+Value XMLHttpRequest::getStatusText() const
+{
+ return httpStatus(responseHeaders, true);
+}
+
+void XMLHttpRequest::processSyncLoadResults(const TQByteArray &data, const KURL &finalURL, const TQString &headers)
+{
+ if (!urlMatchesDocumentDomain(finalURL)) {
+ abort();
+ return;
+ }
+
+ responseHeaders = headers;
+ changeState(Loaded);
+ if (aborted) {
+ return;
+ }
+
+#ifdef APPLE_CHANGES
+ const char *bytes = (const char *)data.data();
+ int len = (int)data.size();
+
+ slotData(0, bytes, len);
+#else
+ slotData(0, data);
+#endif
+
+ if (aborted) {
+ return;
+ }
+
+ slotFinished(0);
+}
+
+void XMLHttpRequest::slotFinished(TDEIO::Job *)
+{
+ if (decoder) {
+ response += decoder->flush();
+ }
+
+ // make sure to forget about the job before emitting completed,
+ // since changeState triggers JS code, which might e.g. call abort.
+ job = 0;
+ changeState(Completed);
+
+ delete decoder;
+ decoder = 0;
+}
+
+void XMLHttpRequest::slotRedirection(TDEIO::Job*, const KURL& url)
+{
+ if (!urlMatchesDocumentDomain(url)) {
+ abort();
+ }
+}
+
+#ifdef APPLE_CHANGES
+void XMLHttpRequest::slotData( TDEIO::Job*, const char *data, int len )
+#else
+void XMLHttpRequest::slotData(TDEIO::Job*, const TQByteArray &_data)
+#endif
+{
+ if (state < Loaded ) {
+ responseHeaders = job->queryMetaData("HTTP-Headers");
+
+ // NOTE: Replace a 304 response with a 200! Both IE and Mozilla do this.
+ // Problem first reported through bug# 110272.
+ int codeStart = responseHeaders.find("304");
+ if ( codeStart != -1) {
+ int codeEnd = responseHeaders.find("\n", codeStart+3);
+ if (codeEnd != -1)
+ responseHeaders.replace(codeStart, (codeEnd-codeStart), "200 OK");
+ }
+
+ changeState(Loaded);
+ }
+
+#ifndef APPLE_CHANGES
+ const char *data = (const char *)_data.data();
+ int len = (int)_data.size();
+#endif
+
+ if ( decoder == NULL ) {
+ int pos = responseHeaders.find("content-type:", 0, false);
+
+ if ( pos > -1 ) {
+ pos += 13;
+ int index = responseHeaders.find('\n', pos);
+ TQString type = responseHeaders.mid(pos, (index-pos));
+ index = type.find (';');
+ if (index > -1)
+ encoding = TQString(type.mid( index+1 ).remove(TQRegExp("charset[ ]*=[ ]*", false))).stripWhiteSpace();
+ }
+
+ decoder = new Decoder;
+ if (!encoding.isNull())
+ decoder->setEncoding(encoding.latin1(), Decoder::EncodingFromHTTPHeader);
+ else {
+ // Per section 2 of W3C working draft spec, fall back to "UTF-8".
+ decoder->setEncoding("UTF-8", Decoder::DefaultEncoding);
+ }
+ }
+ if (len == 0)
+ return;
+
+ if (len == -1)
+ len = strlen(data);
+
+ TQString decoded = decoder->decode(data, len);
+
+ response += decoded;
+
+ if (!aborted) {
+ changeState(Interactive);
+ }
+}
+
+Value XMLHttpRequestProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ if (!thisObj.inherits(&XMLHttpRequest::info)) {
+ Object err = Error::create(exec,TypeError);
+ exec->setException(err);
+ return err;
+ }
+
+ XMLHttpRequest *request = static_cast<XMLHttpRequest *>(thisObj.imp());
+ switch (id) {
+ case XMLHttpRequest::Abort:
+ request->abort();
+ return Undefined();
+ case XMLHttpRequest::GetAllResponseHeaders:
+ if (args.size() != 0) {
+ return Undefined();
+ }
+
+ return request->getAllResponseHeaders();
+ case XMLHttpRequest::GetResponseHeader:
+ if (args.size() != 1) {
+ return Undefined();
+ }
+
+ return request->getResponseHeader(args[0].toString(exec).qstring());
+ case XMLHttpRequest::Open:
+ {
+ if (args.size() < 2 || args.size() > 5) {
+ return Undefined();
+ }
+
+ TQString method = args[0].toString(exec).qstring();
+ KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(Window::retrieveActive(exec)->part());
+ if (!part)
+ return Undefined();
+ KURL url = KURL(part->document().completeURL(args[1].toString(exec).qstring()).string());
+
+ bool async = true;
+ if (args.size() >= 3) {
+ async = args[2].toBoolean(exec);
+ }
+
+ if (args.size() >= 4) {
+ url.setUser(args[3].toString(exec).qstring());
+ }
+
+ if (args.size() >= 5) {
+ url.setPass(args[4].toString(exec).qstring());
+ }
+
+ request->open(method, url, async);
+
+ return Undefined();
+ }
+ case XMLHttpRequest::Send:
+ {
+ if (args.size() > 1) {
+ return Undefined();
+ }
+
+ if (request->state != Loading) {
+ return Undefined();
+ }
+
+ TQString body;
+ if (args.size() >= 1) {
+ Object obj = Object::dynamicCast(args[0]);
+ if (obj.isValid() && obj.inherits(&DOMDocument::info)) {
+ DOM::Node docNode = static_cast<KJS::DOMDocument *>(obj.imp())->toNode();
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(docNode.handle());
+
+ try {
+ body = doc->toString().string();
+ // FIXME: also need to set content type, including encoding!
+
+ } catch(DOM::DOMException& e) {
+ Object err = Error::create(exec, GeneralError, "Exception serializing document");
+ exec->setException(err);
+ }
+ } else {
+ body = args[0].toString(exec).qstring();
+ }
+ }
+
+ request->send(body);
+
+ return Undefined();
+ }
+ case XMLHttpRequest::SetRequestHeader:
+ if (args.size() != 2) {
+ return Undefined();
+ }
+
+ request->setRequestHeader(args[0].toString(exec).qstring(), args[1].toString(exec).qstring());
+
+ return Undefined();
+
+ case XMLHttpRequest::OverrideMIMEType:
+ if (args.size() < 1) {
+ Object err = Error::create(exec, SyntaxError, "Not enough arguments");
+ exec->setException(err);
+ return err;
+ }
+
+ request->overrideMIMEType(args[0].toString(exec).qstring());
+ return Undefined();
+ }
+
+ return Undefined();
+}
+
+} // end namespace
+
+
+#include "xmlhttprequest.moc"
diff --git a/tdehtml/ecma/xmlhttprequest.h b/tdehtml/ecma/xmlhttprequest.h
new file mode 100644
index 000000000..2dc89e227
--- /dev/null
+++ b/tdehtml/ecma/xmlhttprequest.h
@@ -0,0 +1,142 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _XMLHTTPREQUEST_H_
+#define _XMLHTTPREQUEST_H_
+
+#include "ecma/kjs_binding.h"
+#include "ecma/kjs_dom.h"
+#include "misc/decoder.h"
+#include "kio/jobclasses.h"
+
+namespace KJS {
+
+ class JSEventListener;
+ class XMLHttpRequestQObject;
+
+ // these exact numeric values are important because JS expects them
+ enum XMLHttpRequestState {
+ Uninitialized = 0,
+ Loading = 1,
+ Loaded = 2,
+ Interactive = 3,
+ Completed = 4
+ };
+
+ class XMLHttpRequestConstructorImp : public ObjectImp {
+ public:
+ XMLHttpRequestConstructorImp(ExecState *exec, const DOM::Document &d);
+ virtual bool implementsConstruct() const;
+ virtual Object construct(ExecState *exec, const List &args);
+ private:
+ DOM::Document doc;
+ };
+
+ class XMLHttpRequest : public DOMObject {
+ public:
+ XMLHttpRequest(ExecState *, const DOM::Document &d);
+ ~XMLHttpRequest();
+ virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual void tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr = None);
+ void putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/);
+ virtual bool toBoolean(ExecState *) const { return true; }
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Onload, Onreadystatechange, ReadyState, ResponseText, ResponseXML, Status, StatusText, Abort,
+ GetAllResponseHeaders, GetResponseHeader, Open, Send, SetRequestHeader,
+ OverrideMIMEType };
+
+ private:
+ friend class XMLHttpRequestProtoFunc;
+ friend class XMLHttpRequestQObject;
+
+ Value getStatusText() const;
+ Value getStatus() const;
+ bool urlMatchesDocumentDomain(const KURL&) const;
+
+ XMLHttpRequestQObject *qObject;
+
+#ifdef APPLE_CHANGES
+ void slotData( TDEIO::Job* job, const char *data, int size );
+#else
+ void slotData( TDEIO::Job* job, const TQByteArray &data );
+#endif
+ void slotFinished( TDEIO::Job* );
+ void slotRedirection( TDEIO::Job*, const KURL& );
+
+ void processSyncLoadResults(const TQByteArray &data, const KURL &finalURL, const TQString &headers);
+
+ void open(const TQString& _method, const KURL& _url, bool _async);
+ void send(const TQString& _body);
+ void abort();
+ void setRequestHeader(const TQString& name, const TQString &value);
+ void overrideMIMEType(const TQString& override);
+ Value getAllResponseHeaders() const;
+ Value getResponseHeader(const TQString& name) const;
+
+ void changeState(XMLHttpRequestState newState);
+
+ TQGuardedPtr<DOM::DocumentImpl> doc;
+
+ KURL url;
+ TQString method;
+ bool async;
+ TQMap<TQString,TQString> requestHeaders;
+ TQString m_mimeTypeOverride;
+ TQString contentType;
+
+ TDEIO::TransferJob * job;
+
+ XMLHttpRequestState state;
+ JSEventListener *onReadyStateChangeListener;
+ JSEventListener *onLoadListener;
+
+ tdehtml::Decoder *decoder;
+ TQString encoding;
+ TQString responseHeaders;
+
+ TQString response;
+ mutable bool createdDocument;
+ mutable bool typeIsXML;
+ mutable DOM::Document responseXML;
+
+ bool aborted;
+ };
+
+
+ class XMLHttpRequestQObject : public TQObject {
+ Q_OBJECT
+
+ public:
+ XMLHttpRequestQObject(XMLHttpRequest *_jsObject);
+
+ public slots:
+ void slotData( TDEIO::Job* job, const TQByteArray &data );
+ void slotFinished( TDEIO::Job* job );
+ void slotRedirection( TDEIO::Job* job, const KURL& url);
+
+ private:
+ XMLHttpRequest *jsObject;
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/ecma/xmlserializer.cpp b/tdehtml/ecma/xmlserializer.cpp
new file mode 100644
index 000000000..856f35e1f
--- /dev/null
+++ b/tdehtml/ecma/xmlserializer.cpp
@@ -0,0 +1,109 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "xmlserializer.h"
+#include "xmlserializer.lut.h"
+
+#include "dom/dom_exception.h"
+#include "dom/dom_doc.h"
+#include "xml/dom_docimpl.h"
+
+#include <kdebug.h>
+
+
+////////////////////// XMLSerializer Object ////////////////////////
+
+/* Source for XMLSerializerProtoTable.
+@begin XMLSerializerProtoTable 1
+ serializeToString XMLSerializer::SerializeToString DontDelete|Function 1
+@end
+*/
+
+namespace KJS {
+
+KJS_DEFINE_PROTOTYPE(XMLSerializerProto)
+IMPLEMENT_PROTOFUNC_DOM(XMLSerializerProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("XMLSerializer", XMLSerializerProto, XMLSerializerProtoFunc)
+
+XMLSerializerConstructorImp::XMLSerializerConstructorImp(ExecState *)
+ : ObjectImp()
+{
+}
+
+bool XMLSerializerConstructorImp::implementsConstruct() const
+{
+ return true;
+}
+
+Object XMLSerializerConstructorImp::construct(ExecState *exec, const List &)
+{
+ return Object(new XMLSerializer(exec));
+}
+
+const ClassInfo XMLSerializer::info = { "XMLSerializer", 0, 0, 0 };
+
+XMLSerializer::XMLSerializer(ExecState *exec)
+ : DOMObject(XMLSerializerProto::self(exec))
+{
+}
+
+Value XMLSerializerProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ if (!thisObj.inherits(&XMLSerializer::info)) {
+ Object err = Error::create(exec,TypeError);
+ exec->setException(err);
+ return err;
+ }
+
+ switch (id) {
+ case XMLSerializer::SerializeToString:
+ {
+ if (args.size() != 1) {
+ return Undefined();
+ }
+
+ if (!args[0].toObject(exec).inherits(&DOMNode::info)) {
+ return Undefined();
+ }
+
+ DOM::NodeImpl *node = static_cast<DOM::NodeImpl *>(static_cast<KJS::DOMNode *>(args[0].toObject(exec).imp())->toNode().handle());
+
+ if (!node) {
+ return Undefined();
+ }
+
+ TQString body;
+
+ try {
+ body = node->toString().string();
+ } catch(DOM::DOMException& e) {
+ Object err = Error::create(exec, GeneralError, "Exception serializing document");
+ exec->setException(err);
+ return err;
+ }
+
+ return getString(body);
+ }
+ }
+
+ return Undefined();
+}
+
+} // end namespace
diff --git a/tdehtml/ecma/xmlserializer.h b/tdehtml/ecma/xmlserializer.h
new file mode 100644
index 000000000..629d09afe
--- /dev/null
+++ b/tdehtml/ecma/xmlserializer.h
@@ -0,0 +1,54 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _XMLSERIALIZER_H_
+#define _XMLSERIALIZER_H_
+
+#include "ecma/kjs_binding.h"
+#include "ecma/kjs_dom.h"
+#include "misc/decoder.h"
+#include "kio/jobclasses.h"
+
+namespace KJS {
+
+ class JSEventListener;
+
+ class XMLSerializerConstructorImp : public ObjectImp {
+ public:
+ XMLSerializerConstructorImp(ExecState *);
+ virtual bool implementsConstruct() const;
+ virtual Object construct(ExecState *exec, const List &args);
+ };
+
+ class XMLSerializer : public DOMObject {
+ public:
+ XMLSerializer(ExecState *);
+ virtual bool toBoolean(ExecState *) const { return true; }
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { SerializeToString };
+
+ private:
+ friend class XMLSerializerProtoFunc;
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/html/AlwaysInline.h b/tdehtml/html/AlwaysInline.h
new file mode 100644
index 000000000..71fe82928
--- /dev/null
+++ b/tdehtml/html/AlwaysInline.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ *
+ * 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/Platform.h"
+
+
+#ifndef ALWAYS_INLINE
+#if COMPILER(GCC) && defined(NDEBUG) && __GNUC__ > 3
+#define ALWAYS_INLINE inline __attribute__ ((__always_inline__))
+#elif COMPILER(MSVC) && defined(NDEBUG)
+#define ALWAYS_INLINE __forceinline
+#else
+#define ALWAYS_INLINE inline
+#endif
+#endif
+
+#ifndef ALWAYS_INLINE_INTO
+#if COMPILER(GCC) && defined(NDEBUG) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4)
+#define ALWAYS_INLINE_INTO __attribute__ ((__flatten__))
+#else
+#define ALWAYS_INLINE_INTO
+#endif
+#endif
+
+
+#ifndef NEVER_INLINE
+#if COMPILER(GCC) && __GNUC__ > 3
+#define NEVER_INLINE __attribute__ ((__noinline__))
+#else
+#define NEVER_INLINE
+#endif
+#endif
diff --git a/tdehtml/html/CMakeLists.txt b/tdehtml/html/CMakeLists.txt
new file mode 100644
index 000000000..a7a3bf466
--- /dev/null
+++ b/tdehtml/html/CMakeLists.txt
@@ -0,0 +1,44 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/kio/kfile
+ ${CMAKE_SOURCE_DIR}/kio/kssl
+ ${CMAKE_SOURCE_DIR}/tdeutils
+ ${CMAKE_SOURCE_DIR}/tdewallet/client
+)
+
+##### tdehtmlhtml-static ###########################
+
+set( target tdehtmlhtml )
+
+set( ${target}_SRCS
+ 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
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
diff --git a/tdehtml/html/Makefile.am b/tdehtml/html/Makefile.am
new file mode 100644
index 000000000..0a3286243
--- /dev/null
+++ b/tdehtml/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 = libtdehtmlhtml.la
+libtdehtmlhtml_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
+
+libtdehtmlhtml_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)/tdehtml -I$(top_srcdir) \
+ -I$(top_srcdir)/tdewallet/client -I$(top_srcdir)/tdeutils \
+ $(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/tdehtml/html/Platform.h b/tdehtml/html/Platform.h
new file mode 100644
index 000000000..3cdd7177b
--- /dev/null
+++ b/tdehtml/html/Platform.h
@@ -0,0 +1,218 @@
+/* -*- mode: c++; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WTF_Platform_h
+#define WTF_Platform_h
+
+/* Force KDE build here in our tree... */
+#ifndef BUILDING_KDE__
+#define BUILDING_KDE__ 1
+#endif
+
+/* PLATFORM handles OS, operating environment, graphics API, and CPU */
+#define PLATFORM(WTF_FEATURE) (defined( WTF_PLATFORM_##WTF_FEATURE ) && WTF_PLATFORM_##WTF_FEATURE)
+#define COMPILER(WTF_FEATURE) (defined( WTF_COMPILER_##WTF_FEATURE ) && WTF_COMPILER_##WTF_FEATURE)
+#define HAVE(WTF_FEATURE) (defined( HAVE_##WTF_FEATURE ) && HAVE_##WTF_FEATURE)
+#define USE(WTF_FEATURE) (defined( WTF_USE_##WTF_FEATURE ) && WTF_USE_##WTF_FEATURE)
+#define ENABLE(WTF_FEATURE) (defined( ENABLE_##WTF_FEATURE ) && ENABLE_##WTF_FEATURE)
+
+/* Operating systems - low-level dependencies */
+
+/* PLATFORM(DARWIN) */
+/* Operating system level dependencies for Mac OS X / Darwin that should */
+/* be used regardless of operating environment */
+#ifdef __APPLE__
+#define WTF_PLATFORM_DARWIN 1
+#endif
+
+/* PLATFORM(WIN_OS) */
+/* Operating system level dependencies for Windows that should be used */
+/* regardless of operating environment */
+#if defined(WIN32) || defined(_WIN32)
+#define WTF_PLATFORM_WIN_OS 1
+#endif
+
+/* PLATFORM(UNIX) */
+/* Operating system level dependencies for Unix-like systems that */
+/* should be used regardless of operating environment */
+/* (includes PLATFORM(DARWIN)) */
+#if defined(__APPLE__) \
+ || defined(unix) \
+ || defined(__unix) \
+ || defined(__unix__) \
+ || defined (__NetBSD__) \
+ || defined(_AIX)
+#define WTF_PLATFORM_UNIX 1
+#endif
+
+/* PLATFORM(SOLARIS_OS) */
+/* Operating system level dependencies for Sun (Open)Solaris 10. */
+/* Studio 12 on Solaris defines __SunOS; gcc defines __sun__; */
+/* Both compilers define __sun and sun. */
+#if defined(__sun) || defined(sun)
+#define WTF_PLATFORM_SOLARIS_OS 1
+#endif
+
+/* Operating environments */
+
+/* I made the BUILDING_KDE__ macro up for the KDE build system to define */
+
+/* PLATFORM(KDE) */
+/* PLATFORM(MAC) */
+/* PLATFORM(WIN) */
+#if BUILDING_KDE__
+#define WTF_PLATFORM_KDE 1
+#elif PLATFORM(DARWIN)
+#define WTF_PLATFORM_MAC 1
+#elif PLATFORM(WIN_OS)
+#define WTF_PLATFORM_WIN 1
+#endif
+#if defined(BUILDING_GDK__)
+#define WTF_PLATFORM_GDK 1
+#endif
+
+
+/* CPU */
+
+/* PLATFORM(PPC) */
+#if defined(__ppc__) \
+ || defined(__PPC__) \
+ || defined(__powerpc__) \
+ || defined(__powerpc) \
+ || defined(__POWERPC__) \
+ || defined(_M_PPC) \
+ || defined(__PPC)
+#define WTF_PLATFORM_PPC 1
+#define WTF_PLATFORM_BIG_ENDIAN 1
+#endif
+
+/* PLATFORM(PPC64) */
+#if defined(__ppc64__) \
+ || defined(__PPC64__)
+#define WTF_PLATFORM_PPC64 1
+#define WTF_PLATFORM_BIG_ENDIAN 1
+#endif
+
+#if defined(arm)
+#define WTF_PLATFORM_ARM 1
+#if defined(__ARMEB__)
+#define WTF_PLATFORM_BIG_ENDIAN 1
+#elif !defined(__ARM_EABI__) && !defined(__ARMEB__)
+#define WTF_PLATFORM_MIDDLE_ENDIAN 1
+#endif
+#if !defined(__ARM_EABI__)
+#define WTF_PLATFORM_FORCE_PACK 1
+#endif
+#endif
+
+/* PLATFORM(X86) */
+#if defined(__i386__) \
+ || defined(i386) \
+ || defined(_M_IX86) \
+ || defined(_X86_) \
+ || defined(__THW_INTEL)
+#define WTF_PLATFORM_X86 1
+#endif
+
+/* PLATFORM(X86_64) */
+#if defined(__x86_64__) \
+ || defined(__ia64__)
+#define WTF_PLATFORM_X86_64 1
+#endif
+
+/* PLATFORM(SPARC) */
+#if defined(sparc)
+#define WTF_PLATFORM_SPARC 1
+#endif
+
+/* Compiler */
+
+/* COMPILER(CWP) */
+#if defined(__MWERKS__)
+#define WTF_COMPILER_CWP 1
+#endif
+
+/* COMPILER(MSVC) */
+#if defined(_MSC_VER)
+#define WTF_COMPILER_MSVC 1
+#endif
+
+/* COMPILER(GCC) */
+#if defined(__GNUC__)
+#define WTF_COMPILER_GCC 1
+#endif
+
+/* COMPILER(SUNPRO) */
+#if defined(__SUNPRO_CC)
+#define WTF_COMPILER_SUNPRO 1
+#endif
+
+/* COMPILER(BORLAND) */
+/* not really fully supported - is this relevant any more? */
+#if defined(__BORLANDC__)
+#define WTF_COMPILER_BORLAND 1
+#endif
+
+/* COMPILER(CYGWIN) */
+/* not really fully supported - is this relevant any more? */
+#if defined(__CYGWIN__)
+#define WTF_COMPILER_CYGWIN 1
+#endif
+
+/* multiple threads only supported on Mac for now */
+#if PLATFORM(MAC)
+#ifndef WTF_USE_MULTIPLE_THREADS
+#define WTF_USE_MULTIPLE_THREADS 1
+#endif
+#ifndef WTF_USE_BINDINGS
+#define WTF_USE_BINDINGS 1
+#endif
+#endif
+
+/* for Unicode, KDE uses Qt, everything else uses ICU */
+#if PLATFORM(KDE) || PLATFORM(QT)
+#define WTF_USE_QT4_UNICODE 1
+#elif PLATFORM(SYMBIAN)
+#define WTF_USE_SYMBIAN_UNICODE 1
+#else
+#define WTF_USE_ICU_UNICODE 1
+#endif
+
+#if PLATFORM(MAC)
+#define WTF_PLATFORM_CF 1
+#endif
+
+#if PLATFORM(WIN)
+#define WTF_USE_WININET 1
+#endif
+
+#if PLATFORM(GDK)
+#define WTF_USE_CURL 1
+#endif
+
+/* ENABLE macro defaults */
+
+#endif /* WTF_Platform_h */
diff --git a/tdehtml/html/RefPtr.h b/tdehtml/html/RefPtr.h
new file mode 100644
index 000000000..8754bbf94
--- /dev/null
+++ b/tdehtml/html/RefPtr.h
@@ -0,0 +1,202 @@
+// -*- mode: c++; c-basic-offset: 4 -*-
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * 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 WTF_RefPtr_h
+#define WTF_RefPtr_h
+
+#include <algorithm>
+#include "AlwaysInline.h"
+
+namespace WTF {
+
+ enum PlacementNewAdoptType { PlacementNewAdopt };
+
+ template <typename T> class PassRefPtr;
+
+ enum HashTableDeletedValueType { HashTableDeletedValue };
+
+ template <typename T> class RefPtr {
+ public:
+ RefPtr() : m_ptr(0) { }
+ RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); }
+ RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); }
+ // see comment in PassRefPtr.h for why this takes const reference
+ template <typename U> RefPtr(const PassRefPtr<U>&);
+
+ // Special constructor for cases where we overwrite an object in place.
+ RefPtr(PlacementNewAdoptType) { }
+
+ // Hash table deleted values, which are only constructed and never copied or destroyed.
+ RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+ bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
+ ~RefPtr() { if (T* ptr = m_ptr) ptr->deref(); }
+
+ template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); }
+
+ T* get() const { return m_ptr; }
+
+ void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; }
+ PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
+
+ T& operator*() const { return *m_ptr; }
+ ALWAYS_INLINE T* operator->() const { return m_ptr; }
+
+ bool operator!() const { return !m_ptr; }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef T* RefPtr::*UnspecifiedBoolType;
+ operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
+
+ RefPtr& operator=(const RefPtr&);
+ RefPtr& operator=(T*);
+ RefPtr& operator=(const PassRefPtr<T>&);
+ template <typename U> RefPtr& operator=(const RefPtr<U>&);
+ template <typename U> RefPtr& operator=(const PassRefPtr<U>&);
+
+ void swap(RefPtr&);
+
+ private:
+ static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
+ T* m_ptr;
+ };
+
+ template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
+ : m_ptr(o.releaseRef())
+ {
+ }
+
+ template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
+ {
+ T* optr = o.get();
+ if (optr)
+ optr->ref();
+ T* ptr = m_ptr;
+ m_ptr = optr;
+ if (ptr)
+ ptr->deref();
+ return *this;
+ }
+
+ template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
+ {
+ T* optr = o.get();
+ if (optr)
+ optr->ref();
+ T* ptr = m_ptr;
+ m_ptr = optr;
+ if (ptr)
+ ptr->deref();
+ return *this;
+ }
+
+ template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
+ {
+ if (optr)
+ optr->ref();
+ T* ptr = m_ptr;
+ m_ptr = optr;
+ if (ptr)
+ ptr->deref();
+ return *this;
+ }
+
+ template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
+ {
+ T* ptr = m_ptr;
+ m_ptr = o.releaseRef();
+ if (ptr)
+ ptr->deref();
+ return *this;
+ }
+
+ template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
+ {
+ T* ptr = m_ptr;
+ m_ptr = o.releaseRef();
+ if (ptr)
+ ptr->deref();
+ return *this;
+ }
+
+ template <class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
+ {
+ std::swap(m_ptr, o.m_ptr);
+ }
+
+ template <class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
+ {
+ a.swap(b);
+ }
+
+ template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
+ {
+ return a.get() == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
+ {
+ return a.get() == b;
+ }
+
+ template <typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b)
+ {
+ return a == b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
+ {
+ return a.get() != b.get();
+ }
+
+ template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
+ {
+ return a.get() != b;
+ }
+
+ template <typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
+ {
+ return a != b.get();
+ }
+
+ template <typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
+ {
+ return RefPtr<T>(static_cast<T*>(p.get()));
+ }
+
+ template <typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p)
+ {
+ return RefPtr<T>(const_cast<T*>(p.get()));
+ }
+
+ template <typename T> inline T* getPtr(const RefPtr<T>& p)
+ {
+ return p.get();
+ }
+
+} // namespace WTF
+
+using WTF::RefPtr;
+using WTF::static_pointer_cast;
+using WTF::const_pointer_cast;
+
+#endif // WTF_RefPtr_h
diff --git a/tdehtml/html/doctypes.cpp b/tdehtml/html/doctypes.cpp
new file mode 100644
index 000000000..332ad18fd
--- /dev/null
+++ b/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 28 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 73 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 35 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 43 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 41 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 37 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 69 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 50 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 25 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 31 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 22 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 49 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 47 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 36 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 3//en//3.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 39 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 21 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 46 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 34 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 72 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2 final//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 23 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.1e//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 75 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.0 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eQuirks},
+#line 30 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 0//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 20 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict level 2//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 42 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html strict level 2//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 85 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html 3.0//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 89 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//webtechs//dtd mozilla html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 86 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 84 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.1//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 38 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3o//dtd w3 html strict 3.0//en//", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 17 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 32 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html level 1//en//2.0", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 26 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//ietf//dtd html 2.0 strict level 1//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 40 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 4.01 frameset//en", PubIDInfo::eQuirks, PubIDInfo::eAlmostStandards},
+#line 71 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd html 3.2 draft//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 74 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.0 frameset//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 80 "/opt/src/kde/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd html experimental 970421//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 51 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//netscape comm. corp.//dtd html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 78 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//w3c//dtd xhtml 1.0 transitional//en", PubIDInfo::eAlmostStandards, PubIDInfo::eAlmostStandards},
+#line 59 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//as//dtd html 3.0 aswedit + extensions//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 66 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"-//microsoft//dtd internet explorer 2.0 html//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+ {"",PubIDInfo::eAlmostStandards,PubIDInfo::eAlmostStandards},
+#line 55 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/html/doctypes.gperf"
+ {"+//silmaril//dtd html pro v0r11 19970101//en", PubIDInfo::eQuirks3, PubIDInfo::eQuirks3},
+#line 52 "/opt/src/kde/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdelibs/tdehtml/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/tdehtml/html/doctypes.gperf b/tdehtml/html/doctypes.gperf
new file mode 100644
index 000000000..97b10e258
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/dtd.cpp b/tdehtml/html/dtd.cpp
new file mode 100644
index 000000000..accc8b855
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/dtd.dtd b/tdehtml/html/dtd.dtd
new file mode 100644
index 000000000..d6a5ac8f0
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/dtd.h b/tdehtml/html/dtd.h
new file mode 100644
index 000000000..4192ce51c
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/html_baseimpl.cpp b/tdehtml/html/html_baseimpl.cpp
new file mode 100644
index 000000000..7ac3d93c9
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 tdehtml;
+
+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:
+ {
+ TQString url = tdehtml::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();
+ }
+ TQString 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) {
+ TQString s;
+ s.sprintf( "%d", w->marginWidth() );
+ addCSSLength(CSS_PROP_MARGIN_LEFT, s);
+ addCSSLength(CSS_PROP_MARGIN_RIGHT, s);
+ }
+ if(w && w->marginHeight() != -1) {
+ TQString 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 = TQScrollView::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(tdehtml::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 = TQScrollView::Auto;
+ else if( strcasecmp( attr->value(), "yes" ) == 0 )
+ scrolling = TQScrollView::AlwaysOn;
+ else if( strcasecmp( attr->value(), "no" ) == 0 )
+ scrolling = TQScrollView::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);
+ tdehtml::RenderFrame *renderFrame = static_cast<tdehtml::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() && ::tqqt_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() && ::tqqt_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<tdehtml::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/tdehtml/html/html_baseimpl.h b/tdehtml/html/html_baseimpl.h
new file mode 100644
index 000000000..0aff3e8e1
--- /dev/null
+++ b/tdehtml/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/tdehtmllayout.h"
+
+#include <tqscrollview.h>
+
+class KHTMLView;
+class KHTMLPart;
+
+namespace tdehtml {
+ 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 tdehtml::RenderFrame;
+ friend class tdehtml::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;
+ TQScrollView::ScrollBarMode scrolling;
+
+ bool frameBorder : 1;
+ bool frameBorderSet : 1;
+ bool noresize : 1;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLFrameSetElementImpl : public HTMLElementImpl
+{
+ friend class tdehtml::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:
+ tdehtml::Length* m_rows;
+ tdehtml::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/tdehtml/html/html_blockimpl.cpp b/tdehtml/html/html_blockimpl.cpp
new file mode 100644
index 000000000..3e4585c41
--- /dev/null
+++ b/tdehtml/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 tdehtml;
+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
+ // tdehtmltests/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(TQString::number(_s-2)));
+ }
+ else if (_s >= 0) {
+ addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString(TQString::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 TQString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLDivElementImpl::removeId(id);
+}
+
+void HTMLLayerElementImpl::addId (const TQString& 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/tdehtml/html/html_blockimpl.h b/tdehtml/html/html_blockimpl.h
new file mode 100644
index 000000000..f560583db
--- /dev/null
+++ b/tdehtml/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 TQString& id);
+ virtual void removeId(const TQString& id);
+private:
+ DOMString m_name;
+ bool fixed;
+ bool transparent;
+};
+
+} //namespace
+#endif
+
diff --git a/tdehtml/html/html_documentimpl.cpp b/tdehtml/html/html_documentimpl.cpp
new file mode 100644
index 000000000..3aa70c196
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "tdehtmlpart_p.h"
+#include "tdehtml_settings.h"
+#include "misc/htmlattrs.h"
+#include "misc/htmlhashes.h"
+
+#include "xml/xml_tokenizer.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include "tdehtml_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 <tqptrstack.h>
+
+// Turn off inlining to avoid warning with newer gcc.
+#undef __inline
+#define __inline
+#include "doctypes.cpp"
+#undef __inline
+
+template class TQPtrStack<DOM::NodeImpl>;
+
+using namespace DOM;
+using namespace tdehtml;
+
+
+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(), TQT_SIGNAL( removed( const TQString& )),
+ TQT_SLOT( slotHistoryChanged() ));
+*/
+ connect( KHTMLFactory::vLinks(), TQT_SIGNAL( inserted( const TQString& ) ),
+ TQT_SLOT( slotHistoryChanged() ));
+ connect( KHTMLFactory::vLinks(), TQT_SIGNAL( cleared()),
+ TQT_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();
+
+ TQCString replyType;
+ TQByteArray params, reply;
+ TQDataStream stream(params, IO_WriteOnly);
+ stream << URL().url() << windowId;
+ if (!kapp->dcopClient()->call("kcookiejar", "kcookiejar",
+ "findDOMCookies(TQString,long int)", params,
+ replyType, reply))
+ {
+ kdWarning(6010) << "Can't communicate with cookiejar!" << endl;
+ return DOMString();
+ }
+
+ TQDataStream stream2(reply, IO_ReadOnly);
+ if(replyType != "TQString") {
+ kdError(6010) << "DCOP function findDOMCookies(...) returns "
+ << replyType << ", expected TQString" << endl;
+ return DOMString();
+ }
+
+ TQString 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();
+
+ TQByteArray params;
+ TQDataStream stream(params, IO_WriteOnly);
+ TQCString 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(TQString,TQCString,long int)", params))
+ {
+ // Maybe it wasn't running (e.g. we're opening local html files)
+ TDEApplication::startServiceByDesktopName( "kcookiejar");
+ if (!kapp->dcopClient()->send("kcookiejar", "kcookiejar",
+ "addCookies(TQString,TQCString,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)
+{
+ TQString url = _url.string();
+ TQString s;
+ int pos = url.find('#');
+ //kdDebug(0) << "map pos of #:" << pos << endl;
+ s = TQString(_url.unicode() + pos + 1, _url.length() - pos - 1);
+
+ TQMapConstIterator<TQString,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 TQString& buffer, int index)
+{
+ while (true) {
+ TQChar 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 TQString& buffer, int offset)
+{
+ TQString startString(str);
+ if (offset + startString.length() > buffer.length())
+ return false;
+
+ TQString bufferString = buffer.mid(offset, startString.length()).lower();
+ TQString lowerStart = startString.lower();
+
+ return bufferString.startsWith(lowerStart);
+}
+
+static bool parseDocTypeDeclaration(const TQString& buffer,
+ int* resultFlags,
+ TQString& publicID,
+ TQString& 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;
+ TQChar 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).
+ TQChar 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);
+ TQChar 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);
+ TQChar 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);
+ }
+
+ TQChar nextChar = buffer[index];
+ if (nextChar == '[')
+ *resultFlags |= PARSEMODE_HAVE_INTERNAL;
+ else if (nextChar != '>')
+ return false;
+ }
+
+ return true;
+}
+
+void HTMLDocumentImpl::determineParseMode( const TQString &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.
+
+ TQString 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.
+ TQString 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/tdehtml/html/html_documentimpl.h b/tdehtml/html/html_documentimpl.h
new file mode 100644
index 000000000..0aea47b8b
--- /dev/null
+++ b/tdehtml/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 <tqmap.h>
+
+class KHTMLView;
+class TQString;
+
+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 tdehtml::Tokenizer *createTokenizer();
+
+ virtual bool childAllowed( NodeImpl *newChild );
+
+ virtual ElementImpl *createElement ( const DOMString &tagName, int* pExceptioncode );
+
+ HTMLMapElementImpl* getMap(const DOMString& url_);
+
+ virtual void determineParseMode( const TQString &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;
+ TQMap<TQString,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/tdehtml/html/html_elementimpl.cpp b/tdehtml/html/html_elementimpl.cpp
new file mode 100644
index 000000000..c18f19ea0
--- /dev/null
+++ b/tdehtml/html/html_elementimpl.cpp
@@ -0,0 +1,685 @@
+// -*- 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 "tdehtmlview.h"
+#include "tdehtml_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 tdehtml;
+
+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 TQChar* 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;
+ TQChar* 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( TQConstString(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 = "";
+
+ TQString ns = TQString::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 TQChar &c ) {
+ return ( c >= TQChar('0') && c <= TQChar('9') ) ||
+ ( c >= TQChar('a') && c <= TQChar('f') ) ||
+ ( c >= TQChar('A') && c <= TQChar('F') );
+}
+
+static inline int toHex( const TQChar &c ) {
+ return ( (c >= TQChar('0') && c <= TQChar('9'))
+ ? (c.unicode() - '0')
+ : ( ( c >= TQChar('a') && c <= TQChar('f') )
+ ? (c.unicode() - 'a' + 10)
+ : ( ( c >= TQChar('A') && c <= TQChar('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;
+
+ TQString 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
+// tqDebug("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;
+// tqDebug("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;
+// tqDebug("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] );
+// tqDebug( "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
+{
+ TQString result; //Use TQString to accumulate since DOMString is poor for appends
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ DOMString kid = child->toString();
+ result += TQConstString(kid.unicode(), kid.length()).string();
+ }
+ return result;
+}
+
+DOMString HTMLElementImpl::innerText() const
+{
+ TQString 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 += TQConstString(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 )
+{
+ // Works line innerText in Gecko
+ // ### test if needed for ID_SCRIPT as well.
+ if ( id() == ID_STYLE ) {
+ setInnerText(html, exceptioncode);
+ return;
+ }
+
+ 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 )
+{
+ //tqDebug("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/tdehtml/html/html_elementimpl.h b/tdehtml/html/html_elementimpl.h
new file mode 100644
index 000000000..f71ae9b23
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/html_formimpl.cpp b/tdehtml/html/html_formimpl.cpp
new file mode 100644
index 000000000..f8c566511
--- /dev/null
+++ b/tdehtml/html/html_formimpl.cpp
@@ -0,0 +1,2980 @@
+/*
+ * 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 "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "html/html_documentimpl.h"
+#include "tdehtml_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 "tdehtml_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 <tdewallet.h>
+#endif
+#include <netaccess.h>
+#include <kfileitem.h>
+#include <tqfile.h>
+#include <tqdir.h>
+#include <tqtextcodec.h>
+
+// for keygen
+#include <tqstring.h>
+#include <ksslkeygen.h>
+
+#include <assert.h>
+
+
+using namespace DOM;
+using namespace tdehtml;
+
+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 = "----------" + TDEApplication::randomString( 42 + 13 );
+ m_acceptcharset = "UNKNOWN";
+ m_malformed = false;
+}
+
+HTMLFormElementImpl::~HTMLFormElementImpl()
+{
+ if (getDocument() && getDocument()->view() && getDocument()->view()->part()) {
+ getDocument()->view()->part()->dequeueWallet(this);
+ }
+ TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
+ for (; it.current(); ++it)
+ it.current()->m_form = 0;
+ TQPtrListIterator<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;
+ TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements);
+ for (; it.current(); ++it)
+ if (it.current()->isEnumeratable())
+ ++len;
+
+ return len;
+}
+
+static TQCString encodeCString(const TQCString& 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 = "-._*";
+ TQCString 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';
+
+ //TQCString 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 TQString escapeUnencodeable(const TQTextCodec* codec, const TQString& s) {
+ TQString enc_string;
+ const int len = s.length();
+ for(int i=0; i <len; ++i) {
+ const TQChar c = s[i];
+ if (codec->canEncode(c))
+ enc_string.append(c);
+ else {
+ TQString ampersandEscape;
+ ampersandEscape.sprintf("&#%u;", c.unicode());
+ enc_string.append(ampersandEscape);
+ }
+ }
+ return enc_string;
+}
+
+inline static TQCString fixUpfromUnicode(const TQTextCodec* codec, const TQString& s)
+{
+ TQCString str = codec->fromUnicode(escapeUnencodeable(codec,s));
+ str.truncate(str.length());
+ return str;
+}
+
+TQByteArray HTMLFormElementImpl::formData(bool& ok)
+{
+#ifdef FORMS_DEBUG
+ kdDebug( 6030 ) << "form: formData()" << endl;
+#endif
+
+ TQByteArray form_data(0);
+ TQCString enc_string = ""; // used for non-multipart data
+
+ // find out the QTextcodec to use
+ const TQString str = m_acceptcharset.string();
+ const TQChar space(' ');
+ const unsigned int strLength = str.length();
+ for(unsigned int i=0; i < strLength; ++i) if(str[i].latin1() == ',') str[i] = space;
+ const TQStringList charsets = TQStringList::split(' ', str);
+ TQTextCodec* codec = 0;
+ KHTMLView *view = getDocument()->view();
+ {
+ TQStringList::ConstIterator it = charsets.begin();
+ const TQStringList::ConstIterator itEnd = charsets.end();
+
+ for ( ; it != itEnd; ++it )
+ {
+ TQString enc = (*it);
+ if(enc.contains("UNKNOWN"))
+ {
+ // use standard document encoding
+ enc = "ISO 8859-1";
+ if(view && view->part())
+ enc = view->part()->encoding();
+ }
+ if((codec = TDEGlobal::charsets()->codecForName(enc.latin1())))
+ break;
+ }
+ }
+ if(!codec)
+ codec = TQTextCodec::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 = TQTextCodec::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() == ' ' ? TQChar('-') : m_encCharset[i].lower();
+
+ TQStringList fileUploads, fileNotUploads;
+
+ for (TQPtrListIterator<HTMLGenericFormElementImpl> it(formElements); it.current(); ++it) {
+ HTMLGenericFormElementImpl* const current = it.current();
+ tdehtml::encodingList lst;
+
+ if (!current->disabled() && current->encoding(codec, lst, m_multipart))
+ {
+ //kdDebug(6030) << "adding name '" << current->name().string() << "'" << endl;
+ tdehtml::encodingList::ConstIterator it = lst.begin();
+ const tdehtml::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
+ {
+ TQCString 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;
+ TQString val = static_cast<HTMLInputElementImpl*>(current)->value().string().stripWhiteSpace();
+ if (!val.isEmpty() &&
+ TQDir::isRelativePath(val) &&
+ TQFile::exists(TDEGlobalSettings::documentPath() + val)) {
+ path.setPath(TDEGlobalSettings::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 TQByteArray();
+ }
+ }
+
+ 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 TQByteArray();
+ }
+ }
+
+ 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 = TQString::null;
+}
+
+static TQString calculateAutoFillKey(const HTMLFormElementImpl& e)
+{
+ KURL k(e.getDocument()->URL());
+ k.setRef(TQString::null);
+ k.setQuery(TQString::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 TQString name = e.getAttribute(ATTR_NAME).string().stripWhiteSpace();
+ const TQRegExp re("[;,!]");
+ const TQStringList url = TQStringList::split(re, k.url());
+ return url[0] + '#' + name;
+}
+
+void HTMLFormElementImpl::doAutoFill()
+{
+#ifndef KHTML_NO_WALLET
+ const TQString 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 TQString key = calculateAutoFillKey(*this);
+ if (!w->hasFolder(KWallet::Wallet::FormDataFolder())) {
+ return; // failed
+ }
+ w->setFolder(KWallet::Wallet::FormDataFolder());
+ TQMap<TQString, TQString> map;
+ if (w->readMap(key, map))
+ return; // failed, abort
+
+ for (TQPtrListIterator<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 (TQPtrListIterator<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 (TQPtrListIterator<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 TQByteArray 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 TQString 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());
+ TQMap<TQString, TQString> map;
+ if (!w->readMap(key, map)) {
+ TQMapConstIterator<TQString, TQString> it = map.begin();
+ const TQMapConstIterator<TQString, TQString> 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, TQMessageBox::Information,
+ i18n("Store passwords on this page?"),
+ TQStringList(), TQString::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(tdehtml::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 (TQPtrListIterator<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 TQString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLFormElementImpl::addId (const TQString& id)
+{
+ getDocument()->underDocNamedCache().add(id, this);
+ HTMLElementImpl::addId(id);
+}
+
+
+void HTMLFormElementImpl::radioClicked( HTMLGenericFormElementImpl *caller )
+{
+ for (TQPtrListIterator<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;
+
+ TQWidget* widget = static_cast<RenderWidget*>(m_render)->widget();
+ return widget && widget->focusPolicy() >= TQ_TabFocus;
+}
+
+class FocusHandleWidget : public TQWidget
+{
+public:
+ void focusNextPrev(bool n) {
+ if (!focusNextPrevChild(n) && inherits(TQTEXTEDIT_OBJECT_NAME_STRING))
+ TQWidget::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());
+ TQWidget* 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() ) {
+ TQKeyEvent* const k = static_cast<KeyEventBaseImpl *>(evt)->qKeyEvent();
+ if ( k && (k->key() == Qt::Key_Tab || k->key() == TQt::Key_BackTab) ) {
+ TQWidget* const widget = static_cast<RenderWidget*>(m_render)->widget();
+#ifdef USE_QT4
+ if (widget)
+ static_cast<FocusHandleWidget *>(widget)
+ ->focusNextPrev(k->key() == Qt::Key_Tab);
+#else // USE_QT4
+ TQFocusEvent::setReason( k->key() == Qt::Key_Tab ? TQFocusEvent::Tab : TQFocusEvent::Backtab );
+ if (widget)
+ static_cast<FocusHandleWidget *>(widget)
+ ->focusNextPrev(k->key() == Qt::Key_Tab);
+ TQFocusEvent::resetReason();
+#endif // USE_QT4
+ evt->setDefaultHandled();
+ }
+ }
+ }
+
+
+ if (view && evt->id() == EventImpl::DOMFOCUSOUT_EVENT && isEditable() && m_render && m_render->isWidget()) {
+ KHTMLPartBrowserExtension* const ext = static_cast<KHTMLPartBrowserExtension *>(view->part()->browserExtension());
+ TQWidget* 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()) {
+ TQKeyEvent* 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()
+{
+ TQMouseEvent me(TQEvent::MouseButtonRelease, TQPoint(0,0),Qt::LeftButton, 0);
+ dispatchMouseEvent(&me,EventImpl::CLICK_EVENT, 1);
+}
+
+bool HTMLButtonElementImpl::encoding(const TQTextCodec* codec, tdehtml::encodingList& encoding, bool /*multipart*/)
+{
+ if (m_type != SUBMIT || name().isEmpty() || !m_activeSubmit)
+ return false;
+
+ encoding += fixUpfromUnicode(codec, name().string());
+ const TQString enc_str = m_currValue.isNull() ? TQString("") : 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, "tdehtml_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 "";
+ }
+}
+
+TQString HTMLInputElementImpl::state( )
+{
+ switch (m_type) {
+ case PASSWORD:
+ return TQString::fromLatin1("."); // empty string, avoid restoring
+ case CHECKBOX:
+ case RADIO:
+ return TQString::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 TQString &state)
+{
+ switch (m_type) {
+ case CHECKBOX:
+ case RADIO:
+ setChecked((state == TQString::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()
+{
+ TQMouseEvent me(TQEvent::MouseButtonRelease, TQPoint(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 TQString value = m_value.string();
+ // remove newline stuff..
+ TQString nvalue;
+ unsigned int valueLength = value.length();
+ for (unsigned int i = 0; i < valueLength; ++i)
+ if (value[i] >= TQChar(' '))
+ 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 TQTextCodec* codec, tdehtml::encodingList& encoding, bool multipart)
+{
+ const TQString 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;
+ TQString astr(nme.isEmpty() ? TQString::fromLatin1("x") : nme + ".x");
+
+ encoding += fixUpfromUnicode(codec, astr);
+ astr.setNum(KMAX( clickX(), 0 ));
+ encoding += fixUpfromUnicode(codec, astr);
+ astr = nme.isEmpty() ? TQString::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)
+ {
+ TQString 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() != tdehtml::VISIBLE)
+ return false;
+
+ TQString local;
+ KURL fileurl;
+ TQString val = value().string();
+ if (!val.isEmpty() &&
+ TQDir::isRelativePath(val) &&
+ TQFile::exists(TDEGlobalSettings::documentPath() + val)) {
+ fileurl.setPath(TDEGlobalSettings::documentPath() + val);
+ } else {
+ fileurl = KURL::fromPathOrURL(val);
+ }
+
+ TDEIO::UDSEntry filestat;
+
+ // can't submit file in www-url-form encoded
+ TQWidget* const toplevel = static_cast<RenderSubmitButton*>(m_render)->widget()->topLevelWidget();
+ if (multipart) {
+ TQCString filearray( "" );
+ if ( TDEIO::NetAccess::stat(fileurl, filestat, toplevel)) {
+ const KFileItem fileitem(filestat, fileurl, true, false);
+ if ( fileitem.isFile() &&
+ TDEIO::NetAccess::download(fileurl, local, toplevel) ) {
+ TQFile 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();
+ }
+ TDEIO::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()) {
+ TQKeyEvent* 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 ) ) {
+ TQKeyEvent* 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;
+ TQMemArray<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
+ TQMemArray<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);
+
+ TQMemArray<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;
+ TQMemArray<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.
+ TQMemArray<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;
+ }
+}
+
+TQString HTMLSelectElementImpl::state( )
+{
+ TQString state;
+ TQMemArray<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 TQString &_state)
+{
+ recalcListItems();
+
+ TQString state = _state;
+ if(!state.isEmpty() && !state.contains('X') && !m_multiple && m_size <= 1) {
+ tqWarning("should not happen in restoreState!");
+ state[0] = 'X';
+ }
+
+ TQMemArray<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 TQTextCodec* codec, tdehtml::encodingList& encoded_values, bool)
+{
+ bool successful = false;
+ const TQCString enc_name = fixUpfromUnicode(codec, name().string());
+ TQMemArray<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
+{
+ TQMemArray<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
+{
+ TQMemArray<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<tdehtml::RenderSelect*>(m_render)->setOptionsChanged(true);
+ setChanged();
+}
+
+void HTMLSelectElementImpl::reset()
+{
+ TQMemArray<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
+ TQMemArray<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 TQStringList keys = KSSLKeyGen::supportedKeySizes();
+ TQStringList::ConstIterator i = keys.begin();
+ const TQStringList::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 TQTextCodec* codec, tdehtml::encodingList& encoded_values, bool)
+{
+ bool successful = false;
+ const TQCString 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 = (TQDialog::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...
+ TQMemArray<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";
+}
+
+TQString HTMLTextAreaElementImpl::state( )
+{
+ return value().string() + (m_unsubmittedFormChange ? 'M' : '.');
+}
+
+void HTMLTextAreaElementImpl::restoreState(const TQString &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 TQString expandLF(const TQString& s)
+{
+ // LF -> CRLF
+ unsigned crs = s.contains( '\n' );
+ if (crs == 0)
+ return s;
+ unsigned len = s.length();
+
+ TQString r;
+ r.reserve(len + crs + 1);
+ unsigned pos2 = 0;
+ for(unsigned pos = 0; pos < len; pos++)
+ {
+ TQChar 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 TQTextCodec* 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
+ TQString 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
+ TQPtrList<NodeImpl> toRemove;
+ NodeImpl *n;
+ for (n = firstChild(); n; n = n->nextSibling())
+ if (n->isTextNode())
+ toRemove.append(n);
+ TQPtrListIterator<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/tdehtml/html/html_formimpl.h b/tdehtml/html/html_formimpl.h
new file mode 100644
index 000000000..6a909368a
--- /dev/null
+++ b/tdehtml/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 <tqvaluelist.h>
+#include <tqptrlist.h>
+#include <tqcstring.h>
+#include <tqmemarray.h>
+
+class KHTMLView;
+class TQTextCodec;
+
+namespace tdehtml
+{
+ class RenderFormElement;
+ class RenderTextArea;
+ class RenderSelect;
+ class RenderLineEdit;
+ class RenderRadioButton;
+ class RenderFileButton;
+
+ typedef TQValueList<TQCString> 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 TQString& id);
+ virtual void removeId(const TQString& id);
+
+
+ long length() const;
+
+ TQByteArray 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();
+ TQPtrList<HTMLGenericFormElementImpl> formElements;
+ TQPtrList<HTMLImageElementImpl> imgElements;
+ DOMString m_target;
+ DOMString m_enctype;
+ TQString m_boundary;
+ DOMString m_acceptcharset;
+ TQString 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
+ TQMap<TQString, TQString> m_walletMap; // for wallet storage
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLGenericFormElementImpl : public HTMLElementImpl
+{
+ friend class HTMLFormElementImpl;
+ friend class tdehtml::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 TQTextCodec*, tdehtml::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 TQTextCodec*, tdehtml::encodingList&, bool);
+ void activate();
+ virtual void attach();
+ void click();
+ void blur();
+ void focus();
+
+protected:
+ DOMString m_value;
+ TQString 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 tdehtml::RenderLineEdit;
+ friend class tdehtml::RenderRadioButton;
+ friend class tdehtml::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 TQString state();
+ virtual void restoreState(const TQString &state);
+
+ void select();
+ void click();
+
+ virtual void parseAttribute(AttributeImpl *attr);
+
+ virtual void attach();
+ virtual bool encoding(const TQTextCodec*, tdehtml::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 tdehtml::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 TQString state();
+ virtual void restoreState(const TQString &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 TQTextCodec*, tdehtml::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();
+
+ TQMemArray<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 TQMemArray<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 TQTextCodec*, tdehtml::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 tdehtml::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 tdehtml::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 TQString state();
+ virtual void restoreState(const TQString &state);
+
+ void select ( );
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+ virtual bool encoding(const TQTextCodec*, tdehtml::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;
+ TQString 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/tdehtml/html/html_headimpl.cpp b/tdehtml/html/html_headimpl.cpp
new file mode 100644
index 000000000..2bc0ae99f
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 tdehtml;
+
+NodeImpl::Id HTMLBaseElementImpl::id() const
+{
+ return ID_BASE;
+}
+
+void HTMLBaseElementImpl::parseAttribute(AttributeImpl *attr)
+{
+ switch(attr->id())
+ {
+ case ATTR_HREF:
+ m_href = tdehtml::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( TQString::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( tdehtml::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
+ TQString rel = getAttribute(ATTR_REL).string().lower();
+ TQString 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;
+
+ TQString type = getAttribute(ATTR_TYPE).string().lower();
+ TQString 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();
+
+ TQString 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 TQString& )
+{
+ 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;
+
+ TQString url = getAttribute(ATTR_SRC).string();
+ if (!url.isEmpty()) {
+ TQString 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);
+
+ TQString URL = cs->url().string();
+ DOMString script = cs->script();
+ cs->deref(this);
+ m_cachedScript = 0;
+
+ evaluateScript(URL, script);
+}
+
+void HTMLScriptElementImpl::evaluateScript(const TQString &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/tdehtml/html/html_headimpl.h b/tdehtml/html/html_headimpl.h
new file mode 100644
index 000000000..ee9c2ad8b
--- /dev/null
+++ b/tdehtml/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 tdehtml {
+ 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 tdehtml::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 TQString &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();
+
+ tdehtml::CachedCSSStyleSheet *m_cachedSheet;
+ CSSStyleSheetImpl *m_sheet;
+ DOMString m_url;
+ TQString 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 tdehtml::CachedObjectClient
+{
+public:
+ HTMLScriptElementImpl(DocumentImpl *doc);
+ ~HTMLScriptElementImpl();
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void notifyFinished(tdehtml::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 TQString &, 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:
+ tdehtml::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;
+ TQString 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/tdehtml/html/html_imageimpl.cpp b/tdehtml/html/html_imageimpl.cpp
new file mode 100644
index 000000000..b1972aad4
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 <tqstring.h>
+#include <tqpoint.h>
+#include <tqregion.h>
+#include <tqptrstack.h>
+#include <tqimage.h>
+#include <tqpointarray.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+// -------------------------------------------------------------------------
+
+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(tdehtml::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 {
+ TQString url = getDocument()->completeURL( tdehtml::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() ) {
+ TQString 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 TQString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLImageElementImpl::addId (const TQString& 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();
+}
+
+TQImage HTMLImageElementImpl::currentImage() const
+{
+ RenderImage *r = static_cast<RenderImage*>(renderer());
+
+ if(r)
+ return r->pixmap().convertToImage();
+
+ return TQImage();
+}
+
+TQPixmap HTMLImageElementImpl::currentPixmap() const
+{
+ RenderImage *r = static_cast<RenderImage*>(renderer());
+
+ if(r)
+ return r->pixmap();
+
+ return TQPixmap();
+}
+
+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;
+ TQPtrStack<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:
+ TQString url = getDocument()->completeURL( tdehtml::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 = TQString(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(TQPoint(x_,y_)))
+ {
+ inside = true;
+ info.setInnerNode(this);
+ info.setURLElement(this);
+ }
+
+ return inside;
+}
+
+TQRect HTMLAreaElementImpl::getRect() const
+{
+ if (parentNode()->renderer()==0)
+ return TQRect();
+ int dx, dy;
+ if (!parentNode()->renderer()->absolutePosition(dx, dy))
+ return TQRect();
+ TQRegion region = getRegion(lastw,lasth);
+ region.translate(dx, dy);
+ return region.boundingRect();
+}
+
+TQRegion HTMLAreaElementImpl::getRegion(int width_, int height_) const
+{
+ TQRegion 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;
+ TQPointArray 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 = TQRegion(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 = TQRegion(m_coords[0].minWidth(width_)-r,
+ m_coords[1].minWidth(height_)-r, 2*r, 2*r,TQRegion::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 = TQRegion(x0,y0,x1-x0,y1-y0);
+ }
+ else if (shape==Default)
+ region = TQRegion(0,0,width_,height_);
+ // else
+ // return null region
+
+ return region;
+}
diff --git a/tdehtml/html/html_imageimpl.h b/tdehtml/html/html_imageimpl.h
new file mode 100644
index 000000000..f36e61295
--- /dev/null
+++ b/tdehtml/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/tdehtmllayout.h"
+#include "misc/loader_client.h"
+#include "rendering/render_object.h"
+
+#include <tqregion.h>
+
+namespace DOM {
+
+class DOMString;
+class HTMLFormElementImpl;
+
+class HTMLImageElementImpl
+ : public HTMLElementImpl, public tdehtml::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 TQString& id);
+ virtual void removeId(const TQString& 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.
+ */
+ TQImage currentImage() const;
+ /** Return the pixmap for this element.
+ * This will return undefined results if complete() is not true.
+ */
+ TQPixmap 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(tdehtml::CachedObject *finishedObj);
+ void dispatchLoadEvent();
+protected:
+ DOMString usemap;
+ bool ismap : 1;
+ bool loadEventSent : 1;
+ tdehtml::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_,
+ tdehtml::RenderObject::NodeInfo& info);
+
+ virtual TQRect getRect() const;
+
+ TQRegion cachedRegion() const { return region; }
+
+protected:
+ TQRegion getRegion(int width_, int height) const;
+ TQRegion region;
+ tdehtml::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_,
+ tdehtml::RenderObject::NodeInfo& info);
+private:
+
+ TQString name;
+};
+
+
+} //namespace
+
+#endif
diff --git a/tdehtml/html/html_inlineimpl.cpp b/tdehtml/html/html_inlineimpl.cpp
new file mode 100644
index 000000000..829b10f7b
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 tdehtml;
+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 tdehtml 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 );
+
+ TQString utarget;
+ TQString 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 = tdehtml::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() )
+ {
+ tdehtml::RenderImage *r = static_cast<tdehtml::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 += TQString("?%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 |= TQt::ControlButton;
+ if ( e->shiftKey() )
+ state |= TQt::ShiftButton;
+ if ( e->altKey() )
+ state |= TQt::AltButton;
+ if ( e->metaKey() )
+ state |= TQt::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(TQt::ShiftButton) )
+ state |= TQt::ShiftButton;
+ if ( k->checkModifier(TQt::AltButton) )
+ state |= TQt::AltButton;
+ if ( k->checkModifier(TQt::ControlButton) )
+ state |= TQt::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()
+{
+ TQMouseEvent me(TQEvent::MouseButtonRelease, TQPoint(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 TQChar* 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/tdehtml/html/html_inlineimpl.h b/tdehtml/html/html_inlineimpl.h
new file mode 100644
index 000000000..252e64e41
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/html_listimpl.cpp b/tdehtml/html/html_listimpl.cpp
new file mode 100644
index 000000000..1ad450f84
--- /dev/null
+++ b/tdehtml/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 tdehtml;
+
+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/tdehtml/html/html_listimpl.h b/tdehtml/html/html_listimpl.h
new file mode 100644
index 000000000..d4a9f4436
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/html_miscimpl.cpp b/tdehtml/html/html_miscimpl.cpp
new file mode 100644
index 000000000..58804bff5
--- /dev/null
+++ b/tdehtml/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; }
+
+ TQDict<TQValueList<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;
+}
+
+TQValueList<NodeImpl*> HTMLCollectionImpl::namedItems( const DOMString &name ) const
+{
+ TQString 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 (TQValueList<NodeImpl*>* info = cache->nameCache.find(key)) {
+ return *info;
+ }
+ else {
+ TQValueList<NodeImpl*>* newInfo = new TQValueList<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;
+ }
+
+ TQPtrList<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;
+ TQPtrList<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
+{
+ TQPtrList<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;
+
+ TQPtrList<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/tdehtml/html/html_miscimpl.h b/tdehtml/html/html_miscimpl.h
new file mode 100644
index 000000000..b28fef82a
--- /dev/null
+++ b/tdehtml/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 <tqvaluelist.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;
+
+ TQValueList<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/tdehtml/html/html_objectimpl.cpp b/tdehtml/html/html_objectimpl.cpp
new file mode 100644
index 000000000..b224ad687
--- /dev/null
+++ b/tdehtml/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 "tdehtml_part.h"
+#include "dom/dom_string.h"
+#include "misc/htmlhashes.h"
+#include "tdehtmlview.h"
+#include <tqstring.h>
+#include <tqvariant.h>
+#include <tqmap.h>
+#include <tqtimer.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 tdehtml;
+
+// -------------------------------------------------------------------------
+HTMLObjectBaseElementImpl::HTMLObjectBaseElementImpl(DocumentImpl *doc)
+ : HTMLElementImpl(doc)
+{
+ needWidgetUpdate = false;
+ m_renderAlternative = false;
+}
+
+void HTMLObjectBaseElementImpl::setServiceType(const TQString & 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();
+ TQString val = TQConstString( 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 TQString& id)
+{
+ getDocument()->underDocNamedCache().remove(id, this);
+ HTMLElementImpl::removeId(id);
+}
+
+void HTMLObjectBaseElementImpl::addId (const TQString& 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;
+ TQTimer::singleShot( 0, this, TQT_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 = tdehtml::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 = tdehtml::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;
+ TQWidget* widget = static_cast<RenderWidget*>( m_render )->widget();
+ if( widget && ::tqqt_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/tdehtml/html/html_objectimpl.h b/tdehtml/html/html_objectimpl.h
new file mode 100644
index 000000000..cc91935ca
--- /dev/null
+++ b/tdehtml/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 <tqobject.h>
+#include <tqstringlist.h>
+
+class KHTMLView;
+
+// -------------------------------------------------------------------------
+namespace DOM {
+
+class HTMLFormElementImpl;
+class DOMStringImpl;
+
+class HTMLObjectBaseElementImpl : public TQObject, 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 TQString &);
+
+ TQString url;
+ TQString classId;
+ TQString serviceType;
+ bool needWidgetUpdate;
+ bool m_renderAlternative;
+
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void addId(const TQString& id);
+ virtual void removeId(const TQString& 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:
+ tdehtml::VAlign valign;
+};
+
+// -------------------------------------------------------------------------
+
+class HTMLEmbedElementImpl : public HTMLObjectBaseElementImpl
+{
+public:
+ HTMLEmbedElementImpl(DocumentImpl *doc);
+ ~HTMLEmbedElementImpl();
+
+ virtual Id id() const;
+
+ virtual void parseAttribute(AttributeImpl *attr);
+ virtual void attach();
+
+ TQString 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);
+
+ TQString name() const { return m_name; }
+ TQString value() const { return m_value; }
+
+ protected:
+ TQString m_name;
+ TQString m_value;
+};
+
+} // namespace
+#endif
diff --git a/tdehtml/html/html_tableimpl.cpp b/tdehtml/html/html_tableimpl.cpp
new file mode 100644
index 000000000..3fc4ba757
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 tdehtml;
+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 = TQString::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()) {
+ TQString url = tdehtml::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()) {
+ TQString url = tdehtml::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/tdehtml/html/html_tableimpl.h b/tdehtml/html/html_tableimpl.h
new file mode 100644
index 000000000..76d81ce50
--- /dev/null
+++ b/tdehtml/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/tdehtml/html/htmlparser.cpp b/tdehtml/html/htmlparser.cpp
new file mode 100644
index 000000000..144a9addd
--- /dev/null
+++ b/tdehtml/html/htmlparser.cpp
@@ -0,0 +1,1731 @@
+/*
+ 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 "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "tdehtml_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 tdehtml;
+
+//----------------------------------------------------------------------------
+
+/**
+ * @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;
+ 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='" << TQConstString(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);
+ TQString 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);
+ insertNode(head.get());
+ 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.get();
+ }
+ 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( tdehtml::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())
+ {
+ TQString url = doc()->completeURL( tdehtml::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);
+ TQString 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.get(), body, exceptioncode);
+ if ( exceptioncode ) {
+#ifdef PARSER_DEBUG
+ kdDebug( 6035 ) << "creation of head failed!!!!" << endl;
+#endif
+ delete head.get();
+ 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, "tdehtml_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/tdehtml/html/htmlparser.h b/tdehtml/html/htmlparser.h
new file mode 100644
index 000000000..660ced9e9
--- /dev/null
+++ b/tdehtml/html/htmlparser.h
@@ -0,0 +1,192 @@
+/*
+ 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 <tqdatetime.h>
+#endif
+
+
+#include "dom/dom_string.h"
+#include "xml/dom_nodeimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/RefPtr.h"
+
+class KHTMLView;
+class HTMLStackElem;
+
+namespace DOM {
+ class HTMLDocumentImpl;
+ class DocumentImpl;
+ class HTMLElementImpl;
+ class NodeImpl;
+ class HTMLFormElementImpl;
+ class HTMLMapElementImpl;
+ class HTMLHeadElementImpl;
+ class DocumentFragmentImpl;
+}
+
+namespace tdehtml {
+
+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>
+ */
+ RefPtr<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
+ TQTime qt;
+#endif
+};
+
+} // namespace tdehtml
+
+#endif // HTMLPARSER_H
+
diff --git a/tdehtml/html/htmltokenizer.cpp b/tdehtml/html/htmltokenizer.cpp
new file mode 100644
index 000000000..83bfd4bd5
--- /dev/null
+++ b/tdehtml/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 "tdehtmlview.h"
+#include "tdehtml_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 <tqvariant.h>
+#include <kdebug.h>
+#include <stdlib.h>
+
+#include "kentities.c"
+
+using namespace tdehtml;
+
+static const TQChar commentStart [] = { '<','!','-','-', TQChar::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 ) (TQChar*) malloc( sizeof(TQChar)*( N ) )
+#define KHTML_REALLOC_QCHAR_VEC(P, N ) (TQChar*) realloc(P, sizeof(TQChar)*( 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 = TDEGlobal::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 = TDEGlobal::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() && TQConstString( 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 &&
+ !TQConstString( 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 == '&') {
+ TQChar *scriptCodeDest = scriptCode+scriptCodeSize;
+ ++src;
+ parseEntity(src,scriptCodeDest,true);
+ scriptCodeSize = scriptCodeDest-scriptCode;
+ }
+ else {
+ scriptCode[ scriptCodeSize++ ] = *src;
+ ++src;
+ }
+ }
+}
+
+void HTMLTokenizer::scriptHandler()
+{
+ TQString currentScriptSrc = scriptSrc;
+ scriptSrc = TQString::null;
+
+ processListing(TokenizerString(scriptCode, scriptCodeSize));
+ TQString 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, TQString::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 TQString& str, const TQString& scriptURL,
+ int baseLine)
+{
+ bool oldscript = script;
+ m_executingScript++;
+ script = false;
+ TQString 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
+ tqDebug("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, TQChar *&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--) {
+ TQChar 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 = TQChar(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 = TQChar(uc);
+ if(cBufferPos == 9) Entity = SearchSemicolon;
+ break;
+ }
+ case EntityName:
+ {
+ int ll = kMin(src.length(), 9-cBufferPos);
+ while(ll--) {
+ TQChar 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(TQString::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 = TQChar::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++;
+ tqDebug("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
+ tqDebug("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 = tdehtml::getTagID(ptr, len);
+ if (!tagID) {
+#ifdef TOKEN_DEBUG
+ TQCString tmp(ptr, len+1);
+ kdDebug( 6036 ) << "Unknown tag: \"" << tmp.data() << "\"" << endl;
+#endif
+ dest = buffer;
+ }
+ else
+ {
+#ifdef TOKEN_DEBUG
+ TQCString 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
+ tqDebug("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 = TQString::null;
+ }
+ else
+ tag = AttributeName;
+
+ cBufferPos = 0;
+ break;
+ }
+ atespace = true;
+ ++src;
+ }
+ break;
+ }
+ case AttributeName:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ tqDebug("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 = tdehtml::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 = tdehtml::getAttrID(cBuffer, cBufferPos-1);
+ }
+ if (!a)
+ attrName = TQString::fromLatin1(TQCString(cBuffer, cBufferPos+1).data());
+ }
+
+ dest = buffer;
+ *dest++ = a;
+#ifdef TOKEN_DEBUG
+ if (!a || (cBufferPos && *cBuffer == '!'))
+ kdDebug( 6036 ) << "Unknown attribute: *" << TQCString(cBuffer, cBufferPos+1).data() << "*" << endl;
+ else
+ kdDebug( 6036 ) << "Known attribute: " << TQCString(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 = TQString::fromLatin1(TQCString(cBuffer, cBufferPos+1).data());
+ dest = buffer;
+ *dest++ = 0;
+ tag = SearchEqual;
+ }
+ break;
+ }
+ case SearchEqual:
+ {
+#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
+ tqDebug("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 = TQString::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
+ tqDebug("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
+ tqDebug("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
+ tqDebug("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 = TQString::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(tdehtml::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.
+ */
+ TQString 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.
+ */
+ TQString 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++ = TQChar(' ');
+ 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++ = TQChar(' ');
+ 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( TQTimerEvent *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;
+ TQString food;
+ if (title || style || script)
+ food.setUnicode(scriptCode, scriptCodeSize);
+ else if (server) {
+ food = "<";
+ food += TQString(scriptCode, scriptCodeSize);
+ }
+ else {
+ pos = TQConstString(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) {
+ tqDebug( "unexpected token id: %d, str: *%s*", currToken.tid,TQConstString( 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
+ TQString name = TQString( getTagName(currToken.tid) );
+ TQString text;
+ if(currToken.text)
+ text = TQConstString(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
+ TQString 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/tdehtml/html/htmltokenizer.h b/tdehtml/html/htmltokenizer.h
new file mode 100644
index 000000000..5222647d4
--- /dev/null
+++ b/tdehtml/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 <tqstring.h>
+#include <tqobject.h>
+#include <tqptrqueue.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 tdehtml {
+ 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;
+ //tqDebug("new token, creating %08lx", attrs);
+ }
+ ~Token() {
+ if(attrs) attrs->deref();
+ if(text) text->deref();
+ }
+ void addAttribute(DocumentImpl* doc, TQChar* buffer, const TQString& 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 tdehtml::TokenizerString &str, bool appendData );
+ void end();
+ void finish();
+ void timerEvent( TQTimerEvent *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(tdehtml::TokenizerString list);
+
+ void parseComment(tdehtml::TokenizerString &str);
+ void parseServer(tdehtml::TokenizerString &str);
+ void parseText(tdehtml::TokenizerString &str);
+ void parseListing(tdehtml::TokenizerString &str);
+ void parseSpecial(tdehtml::TokenizerString &str);
+ void parseTag(tdehtml::TokenizerString &str);
+ void parseEntity(tdehtml::TokenizerString &str, TQChar *&dest, bool start = false);
+ void parseProcessingInstruction(tdehtml::TokenizerString &str);
+ void scriptHandler();
+ void scriptExecution(const TQString& script, const TQString& scriptURL = TQString::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(tdehtml::CachedObject *finishedObj);
+
+protected:
+ // Internal buffers
+ ///////////////////
+ TQChar *buffer;
+ TQChar *dest;
+
+ tdehtml::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;
+
+ TQChar 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
+ TQString attrName;
+
+ // Used to store the code of a srcipting sequence
+ TQChar *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>"
+ TQChar searchBuffer[ 10 ];
+ // Counts where we are in the string we are scanning for
+ int searchCount;
+ // The string we are searching for
+ const TQChar *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
+ TQString scriptSrc;
+ TQString 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;
+ TQPtrQueue<tdehtml::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;
+
+ tdehtml::TokenizerString src;
+
+ KCharsets *charsets;
+ KHTMLParser *parser;
+
+ KHTMLView *view;
+};
+
+} // namespace
+
+#endif // HTMLTOKENIZER
+
diff --git a/tdehtml/htmlpageinfo.ui b/tdehtml/htmlpageinfo.ui
new file mode 100644
index 000000000..5dd21cd6f
--- /dev/null
+++ b/tdehtml/htmlpageinfo.ui
@@ -0,0 +1,301 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KHTMLInfoDlg</class>
+<comment>A dialog to display the HTTP headers for a given page.</comment>
+<author>George Staikos &lt;staikos@kde.org&gt;</author>
+<widget class="TQDialog">
+ <property name="name">
+ <cstring>HTMLPageInfo</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>550</width>
+ <height>519</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Document Information</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>General</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>urlLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>URL:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_url</cstring>
+ </property>
+ </widget>
+ <widget class="KActiveLabel" row="0" column="1">
+ <property name="name">
+ <cstring>_title</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KActiveLabel" row="1" column="1">
+ <property name="name">
+ <cstring>_url</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="1">
+ <property name="name">
+ <cstring>_lastModified</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>titleLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Title:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_title</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>_lmLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Last modified:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_lastModified</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>_eLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Document encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_encoding</cstring>
+ </property>
+ </widget>
+ <widget class="KActiveLabel" row="3" column="1">
+ <property name="name">
+ <cstring>_encoding</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>HTTP Headers</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQListView">
+ <column>
+ <property name="text">
+ <string>Property</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>_headers</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode">
+ <enum>NoSelection</enum>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="KPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>_close</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>_close</sender>
+ <signal>clicked()</signal>
+ <receiver>HTMLPageInfo</receiver>
+ <slot>close()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>_close</tabstop>
+ <tabstop>_url</tabstop>
+ <tabstop>_headers</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kpushbutton.h</include>
+ <include location="global" impldecl="in declaration">tqlabel.h</include>
+ <include location="global" impldecl="in declaration">kactivelabel.h</include>
+ <include location="global" impldecl="in declaration">tqlistview.h</include>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kactivelabel.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/tdehtml/java/CMakeLists.txt b/tdehtml/java/CMakeLists.txt
new file mode 100644
index 000000000..994763c09
--- /dev/null
+++ b/tdehtml/java/CMakeLists.txt
@@ -0,0 +1,76 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+add_subdirectory( dummy )
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_BINARY_DIR}/kio/kssl
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kssl
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### configure #################################
+
+set( KJAVA_POLICYPATH "${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/kjava/-" )
+configure_file( kjava.policy.in kjava.policy @ONLY )
+
+
+##### install data ##############################
+
+install( FILES kjavaappletviewer.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
+install( FILES kjava.jar ${CMAKE_CURRENT_BINARY_DIR}/kjava.policy pluginsinfo DESTINATION ${DATA_INSTALL_DIR}/kjava )
+tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kjava/icons )
+
+
+##### kjava-static ##############################
+
+set( target kjava )
+
+set( ${target}_SRCS
+ kjavaapplet.cpp kjavaappletcontext.cpp kjavaappletserver.cpp
+ kjavaappletwidget.cpp kjavaprocess.cpp kjavadownloader.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC
+ SOURCES ${${target}_SRCS}
+ LINK ${TQT_LIBRARIES}
+)
+
+
+##### kjavaappletviewer #########################
+
+set( target kjavaappletviewer )
+
+set( ${target}_SRCS
+ kjavaapplet.cpp kjavaappletcontext.cpp
+ kjavaappletserver.cpp kjavaappletwidget.cpp kjavaprocess.cpp
+ kjavadownloader.cpp kjavaappletviewer.cpp
+)
+
+tde_add_kpart( ${target} AUTOMOC
+ SOURCES ${${target}_SRCS}
+ LINK tdeparts-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
diff --git a/tdehtml/java/ChangeLog b/tdehtml/java/ChangeLog
new file mode 100644
index 000000000..b276c27ac
--- /dev/null
+++ b/tdehtml/java/ChangeLog
@@ -0,0 +1,19 @@
+1999-12-14 Richard Moore <rich@ipso-facto.freeserve.co.uk>
+
+ * Added a delay when you reload a class so that a race is less
+ likely (yuck!)
+ * Added a destructor to kjaw
+ * Still has trouble though :-( It only seems to occur whn using
+ KWin, KWM has no problem.
+
+Tue Dec 7 23:32:21 GMT 1999
+
+ * Many improvements to string handling
+ * Moved to value based collections
+ * Addition of a d pointer for future binary compatability
+ * Added some accessor methods
+ * Improvements to kjavaprocess
+ * - Now handles system property settings
+ * - Detects death of the server
+ * - Supports bidirectional comms
+ * Applets and contexts are destroyed properly
diff --git a/tdehtml/java/KJAS_GRAMMAR.txt b/tdehtml/java/KJAS_GRAMMAR.txt
new file mode 100644
index 000000000..5632f8de8
--- /dev/null
+++ b/tdehtml/java/KJAS_GRAMMAR.txt
@@ -0,0 +1,82 @@
+This is documentation for the updated KJAS protocol.
+
+KJAS Grammar
+===============================================================================
+
+## Commands From KAppletWidget(C++) to KJAS(Java Process)
+<KJAS Command> -> <CMD Length><CMD>
+<CMD Length> -> <StringNum>
+<CMD> -> <createContext> |
+ <destroyContext> |
+ <createApplet> |
+ <destroyApplet> |
+ <startApplet> |
+ <stopApplet> |
+ <initApplet> |
+ <showURLInFrame> |
+ <showDocument> |
+ <showStatus> |
+ <resizeApplet> |
+ <getURLData> |
+ <URLData> |
+ <shutDownServer>
+
+<createContext> -> <1 byte equal to 1 when cast as int><SEP><ContextID><END>
+<destroyContext> -> <1 byte equal to 2 when cast as int><SEP><ContextID><END>
+
+<createApplet> -> <1 byte equal to 3 when cast as int><SEP><ContextID>
+ <SEP><AppletID><SEP><AppletName><SEP><ClassName><SEP>
+ <BaseURL><SEP><CodeBase><SEP><Archives>
+ <SEP><Width><SEP><Height><SEP><WindowTitle><SEP><ParamList>
+<destroyApplet> -> <1 byte equal to 4 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<startApplet> -> <1 byte equal to 5 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<stopApplet> -> <1 byte equal to 6 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+<initApplet> -> <1 byte equal to 7 when cast as int><SEP><ContextID>
+ <SEP><AppletID><END>
+
+
+## Commands from KJAS(Java Process) to KAppletWidget(C++)
+<showDocument> -> <1 byte equal to 8 when cast as int><SEP><ContextID>
+ <SEP><URL><END>
+<showURLInFrame> -> <1 byte equal to 9 when cast as int><SEP><ContextID>
+ <SEP><URL><SEP><targetFrame><END>
+<showStatus> -> <1 byte equal to 10 when cast as int><SEP><ContextID>
+ <SEP><string><END>
+<resizeApplet> -> <1 byte equal to 11 when cast as int><SEP><ContextID>
+ <SEP><AppletID><SEP><Width><SEP><Height><END>
+<getURLData> -> <1 byte equal to 12 when cast as int><SEP><ClassLoaderID>
+ <SEP><URL><END>
+<URLData> -> <1 byte equal to 13 when cast as int><SEP><ClassLoaderID>
+ <SEP><URL><SEP><DATA><END>
+
+<shutDownServer> -> <1 byte equal to 14 when cast as int><END>
+
+## basic data types
+<CMD Length> -> <StringNum>
+<ContextID> -> string
+<AppletID> -> string
+<AppletName> -> string
+<ParamList> -> <StringNum><SEP><ParamPairList>
+<ParamPairList> -> StringNum of ParamPair
+<ParamPair> -> <ParamName><SEP><ParamValue><SEP>
+<ClassName> -> string
+<BaseURL> -> <URL>
+<CodeBase> -> <URL>
+<Archives> -> string (list of jarfile names)
+<Width> -> string representation of integer
+<Height> -> string representation of integer
+<Title> -> string
+<ParamName> -> string
+<ParamValue> -> string
+<Host> -> string (must be a valid URL)
+<URL> -> string (must be a valid URL)
+<targetFrame> -> string
+<WindowTitle> -> string
+<END> -> <SEP>
+<SEP> -> Null character- 1 byte = 0
+<StringNum> -> padded string representation of integer, 8 characters long
+<ClassLoaderID> -> string
+<DATA> -> byte array
diff --git a/tdehtml/java/Makefile.am b/tdehtml/java/Makefile.am
new file mode 100644
index 000000000..a5e46a0d5
--- /dev/null
+++ b/tdehtml/java/Makefile.am
@@ -0,0 +1,37 @@
+KDE_CXXFLAGS = $(WOVERLOADED_VIRTUAL)
+
+noinst_LTLIBRARIES = libkjava.la
+libkjava_la_SOURCES = kjavaapplet.cpp kjavaappletcontext.cpp \
+ kjavaappletserver.cpp kjavaappletwidget.cpp kjavaprocess.cpp \
+ kjavadownloader.cpp
+
+noinst_HEADERS = kjavaappletwidget.h kqeventutil.h kxeventutil.h \
+ kjavaapplet.h kjavaappletcontext.h \
+ kjavaappletserver.h kjavaprocess.h kjavaappletviewer.h
+
+METASOURCES = AUTO
+
+libkjava_la_LDFLAGS = $(KDE_MT_LDFLAGS) -no-undefined
+libkjava_la_LIBADD = $(LIB_KPARTS)
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/tdehtml \
+ -I$(top_srcdir)/kio/kssl -I$(top_builddir)/kio/kssl \
+ $(all_includes)
+
+kjavadata_DATA = kjava.jar kjava.policy pluginsinfo
+kjavadatadir = $(kde_datadir)/kjava/
+
+kjavaiconsdir = $(kde_datadir)/kjava/icons
+kjavaicons_ICON = AUTO
+
+SUBDIRS = . tests dummy
+
+kde_module_LTLIBRARIES= kjavaappletviewer.la
+kjavaappletviewer_la_SOURCES= kjavaapplet.cpp kjavaappletcontext.cpp \
+ kjavaappletserver.cpp kjavaappletwidget.cpp kjavaprocess.cpp \
+ kjavadownloader.cpp kjavaappletviewer.cpp
+
+kjavaappletviewer_la_LDFLAGS= $(all_libraries) -module $(KDE_PLUGIN)
+kjavaappletviewer_la_LIBADD= $(LIB_KPARTS) $(LIB_QT) $(LIB_TDEUI) $(LIB_TDECORE) $(LIB_KFILE) $(top_builddir)/dcop/libDCOP.la
+
+kde_services_DATA= kjavaappletviewer.desktop
diff --git a/tdehtml/java/README b/tdehtml/java/README
new file mode 100644
index 000000000..5d64e742f
--- /dev/null
+++ b/tdehtml/java/README
@@ -0,0 +1,20 @@
+Wynn Wilkes- November 14, 2000
+I've just completed a large update that fixes a large number of bugs. The
+update also adds applet security. The security update requires a Java 2
+jvm.
+
+This is libkdejava, the KDE Java support library.
+
+Directory map:
+
+$CWD CPP sources for KDE binding to KJAS and some
+ additional utility classes.
+kjava-classes.zip An *uncompressed* ZIP file containing the .class files
+ for the KJAS server. The files must be uncompressed to
+ support some crappy JVMs.
+org/kde/kjas/server Java sources for KJAS server process
+
+You can find more information at http://developer.kde.org/language-bindings/java/
+
+Richard Moore.
+rich@kde.org
diff --git a/tdehtml/java/TODO b/tdehtml/java/TODO
new file mode 100644
index 000000000..3d707c898
--- /dev/null
+++ b/tdehtml/java/TODO
@@ -0,0 +1,22 @@
+Wynn Wilkes (November 14, 2000)
+As of now, KJAS requires a Java 2 platform for classloading
+and the default security manager. If anyone wants to implement
+a Java 1.1 security manager, please feel free and we can integrate
+both versions.
+
+- Get the keyboard focus issues fixed
+- Fix tdehtml_part to have one applet context per Document
+- add a context cache someplace so we can reload contexts-
+ this will keep us from having to restart the jvm over
+ and over- this is the biggest performance problem I think
+- fix tdehtml_part so it will start and stop applets??
+- Implement class loading via html proxies if one is set
+
+
+- Use of QGuardedPointer
+- LiveScript support
+- Custom applet types
+- Better support for Java 2
+ - Use a factory to create the classloader and security managers
+ - Use URLClassLoader- this is done
+- Support for KIO URLs
diff --git a/tdehtml/java/build.properties b/tdehtml/java/build.properties
new file mode 100644
index 000000000..c2c0016bc
--- /dev/null
+++ b/tdehtml/java/build.properties
@@ -0,0 +1,9 @@
+dest=.
+jar=kjava
+build=classes
+src=.
+includes=netscape/**,org/**
+excludes=*
+images=images
+debug=true
+debuglevel=lines,vars,source
diff --git a/tdehtml/java/build.xml b/tdehtml/java/build.xml
new file mode 100644
index 000000000..16b523588
--- /dev/null
+++ b/tdehtml/java/build.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+
+<project name="KJAS" basedir="." default="all">
+
+ <property file="build.properties"/>
+
+ <target name="init">
+ <mkdir dir="${build}" />
+ </target>
+
+ <target name="compile" depends="init">
+ <javac srcdir="${src}" destdir="${build}" includes="${includes}" excludes="${excludes}" deprecation="true" debug="${debug}" debuglevel="${debuglevel}" source="1.3" target="1.2"/>
+ </target>
+
+ <target name="images" depends="init">
+ <mkdir dir="${build}/images"/>
+ <copy todir="${build}/images">
+ <fileset dir="${images}">
+ <include name="*gif"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="jar" depends="init,images,compile">
+ <jar jarfile="${jar}.jar" compress="false" basedir="${build}" />
+ </target>
+
+ <target name="all" depends="jar" description="Build everything.">
+ <echo message="Application built." />
+ </target>
+
+ <target name="clean" depends="init" description="Clean all build products.">
+ <delete file="${jar}.jar" />
+ <delete dir="${build}" />
+ </target>
+
+ <target name="test-init" depends="">
+ <mkdir dir="tests/classes" />
+ </target>
+
+ <target name="test" depends="test-init" description="Build the test applets">
+ <javac srcdir="tests" destdir="tests/classes" debug="true" deprecation="true" source="1.3" target="1.2"/>
+ </target>
+
+ <target name="test-clean" depends="">
+ <delete dir="tests/classes" />
+ </target>
+
+</project>
diff --git a/tdehtml/java/configure.in.in b/tdehtml/java/configure.in.in
new file mode 100644
index 000000000..2ed75f6fe
--- /dev/null
+++ b/tdehtml/java/configure.in.in
@@ -0,0 +1,5 @@
+dnl don't remove
+dnl AC_OUTPUT(tdehtml/java/kjava.policy)
+KJAVA_POLICYPATH=${kde_datadir}/kjava/-
+KDE_EXPAND_MAKEVAR(KJAVA_POLICYPATH, KJAVA_POLICYPATH)
+AC_SUBST(KJAVA_POLICYPATH)
diff --git a/tdehtml/java/cr16-action-java.png b/tdehtml/java/cr16-action-java.png
new file mode 100644
index 000000000..dca85a129
--- /dev/null
+++ b/tdehtml/java/cr16-action-java.png
Binary files differ
diff --git a/tdehtml/java/dummy/CMakeLists.txt b/tdehtml/java/dummy/CMakeLists.txt
new file mode 100644
index 000000000..5828f4b83
--- /dev/null
+++ b/tdehtml/java/dummy/CMakeLists.txt
@@ -0,0 +1,30 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### kjava #####################################
+
+configure_file( ${CMAKE_SOURCE_DIR}/cmake/modules/template_dummy_cpp.cmake dummy.cpp COPYONLY )
+
+tde_add_library( kjava SHARED
+ SOURCES dummy.cpp
+ LINK ${TQT_LIBRARIES}
+ VERSION 1.0.0
+ DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/tdehtml/java/dummy/Makefile.am b/tdehtml/java/dummy/Makefile.am
new file mode 100644
index 000000000..5438da6ad
--- /dev/null
+++ b/tdehtml/java/dummy/Makefile.am
@@ -0,0 +1,13 @@
+
+lib_LTLIBRARIES = libkjava.la
+libkjava_la_SOURCES = dummy.cpp
+
+dummy.cpp:
+ echo "#ifdef _AIX" > $@
+ echo "namespace {" >> $@
+ echo "void *not_empty_file;" >> $@
+ echo "}" >> $@
+ echo "#endif" >> $@
+
+libkjava_la_LDFLAGS = -version-info 1:0
+
diff --git a/tdehtml/java/images/animbean.gif b/tdehtml/java/images/animbean.gif
new file mode 100644
index 000000000..a842be25d
--- /dev/null
+++ b/tdehtml/java/images/animbean.gif
Binary files differ
diff --git a/tdehtml/java/images/beanicon.png b/tdehtml/java/images/beanicon.png
new file mode 100644
index 000000000..d1632c16e
--- /dev/null
+++ b/tdehtml/java/images/beanicon.png
Binary files differ
diff --git a/tdehtml/java/images/brokenbean.gif b/tdehtml/java/images/brokenbean.gif
new file mode 100644
index 000000000..9f46dc355
--- /dev/null
+++ b/tdehtml/java/images/brokenbean.gif
Binary files differ
diff --git a/tdehtml/java/kjava.jar b/tdehtml/java/kjava.jar
new file mode 100644
index 000000000..afab6884b
--- /dev/null
+++ b/tdehtml/java/kjava.jar
Binary files differ
diff --git a/tdehtml/java/kjava.policy.in b/tdehtml/java/kjava.policy.in
new file mode 100644
index 000000000..72197bb2e
--- /dev/null
+++ b/tdehtml/java/kjava.policy.in
@@ -0,0 +1,8 @@
+grant codeBase "file:@KJAVA_POLICYPATH@"
+{
+ permission java.security.AllPermission;
+};
+grant {
+ permission java.AudioPermission "play";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.audio";
+};
diff --git a/tdehtml/java/kjavaapplet.cpp b/tdehtml/java/kjavaapplet.cpp
new file mode 100644
index 000000000..70a39afbc
--- /dev/null
+++ b/tdehtml/java/kjavaapplet.cpp
@@ -0,0 +1,288 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletcontext.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <tdeparts/browserextension.h>
+
+
+
+class KJavaAppletPrivate
+{
+public:
+ bool reallyExists;
+ TQString className;
+ TQString appName;
+ TQString baseURL;
+ TQString codeBase;
+ TQString archives;
+ TQSize size;
+ TQString windowName;
+ KJavaApplet::AppletState state;
+ bool failed;
+
+ KJavaAppletWidget* UIwidget;
+};
+
+
+KJavaApplet::KJavaApplet( KJavaAppletWidget* _parent,
+ KJavaAppletContext* _context )
+ : params()
+{
+ d = new KJavaAppletPrivate;
+
+ d->UIwidget = _parent;
+ d->state = UNKNOWN;
+ d->failed = false;
+
+ if( _context )
+ setAppletContext( _context );
+
+ d->reallyExists = false;
+}
+
+KJavaApplet::~KJavaApplet()
+{
+ if ( d->reallyExists )
+ context->destroy( this );
+
+ delete d;
+}
+
+bool KJavaApplet::isCreated()
+{
+ return d->reallyExists;
+}
+
+void KJavaApplet::setAppletContext( KJavaAppletContext* _context )
+{
+ context = _context;
+ context->registerApplet( this );
+}
+
+void KJavaApplet::setAppletClass( const TQString& _className )
+{
+ d->className = _className;
+}
+
+TQString& KJavaApplet::appletClass()
+{
+ return d->className;
+}
+
+TQString& KJavaApplet::parameter( const TQString& name )
+{
+ return params[ name ];
+}
+
+void KJavaApplet::setParameter( const TQString& name, const TQString& value )
+{
+ params.insert( name, value );
+}
+
+TQMap<TQString,TQString>& KJavaApplet::getParams()
+{
+ return params;
+}
+
+void KJavaApplet::setBaseURL( const TQString& baseURL )
+{
+ d->baseURL = baseURL;
+}
+
+TQString& KJavaApplet::baseURL()
+{
+ return d->baseURL;
+}
+
+void KJavaApplet::setCodeBase( const TQString& codeBase )
+{
+ d->codeBase = codeBase;
+}
+
+TQString& KJavaApplet::codeBase()
+{
+ return d->codeBase;
+}
+
+void KJavaApplet::setSize( TQSize size )
+{
+ d->size = size;
+}
+
+TQSize KJavaApplet::size()
+{
+ return d->size;
+}
+
+void KJavaApplet::setArchives( const TQString& _archives )
+{
+ d->archives = _archives;
+}
+
+TQString& KJavaApplet::archives()
+{
+ return d->archives;
+}
+
+void KJavaApplet::resizeAppletWidget( int width, int height )
+{
+ kdDebug(6100) << "KJavaApplet, id = " << id << ", ::resizeAppletWidget to " << width << ", " << height << endl;
+
+ TQStringList sl;
+ sl.push_back( TQString::number( 0 ) ); // applet itself has id 0
+ sl.push_back( TQString( "eval" ) ); // evaluate next script
+ sl.push_back( TQString::number( KParts::LiveConnectExtension::TypeString ) );
+ sl.push_back( TQString( "this.setAttribute('WIDTH',%1);this.setAttribute('HEIGHT',%2)" ).arg( width ).arg( height ) );
+ jsData( sl );
+}
+
+void KJavaApplet::setAppletName( const TQString& name )
+{
+ d->appName = name;
+}
+
+void KJavaApplet::setWindowName( const TQString& title )
+{
+ d->windowName = title;
+}
+
+TQString& KJavaApplet::getWindowName()
+{
+ return d->windowName;
+}
+
+TQString& KJavaApplet::appletName()
+{
+ return d->appName;
+}
+
+void KJavaApplet::create( )
+{
+ if ( !context->create( this ) )
+ setFailed();
+ d->reallyExists = true;
+}
+
+void KJavaApplet::init()
+{
+ context->init( this );
+}
+
+void KJavaApplet::start()
+{
+ context->start( this );
+}
+
+void KJavaApplet::stop()
+{
+ context->stop( this );
+}
+
+int KJavaApplet::appletId()
+{
+ return id;
+}
+
+void KJavaApplet::setAppletId( int _id )
+{
+ id = _id;
+}
+
+void KJavaApplet::stateChange( const int newStateInt ) {
+ AppletState newState = (AppletState)newStateInt;
+ bool ok = false;
+ if (d->failed) {
+ return;
+ }
+ switch ( newState ) {
+ case CLASS_LOADED:
+ ok = (d->state == UNKNOWN);
+ break;
+ case INSTANCIATED:
+ if (ok) {
+ showStatus(i18n("Initializing Applet \"%1\"...").arg(appletName()));
+ }
+ ok = (d->state == CLASS_LOADED);
+ break;
+ case INITIALIZED:
+ ok = (d->state == INSTANCIATED);
+ if (ok) {
+ showStatus(i18n("Starting Applet \"%1\"...").arg(appletName()));
+ start();
+ }
+ break;
+ case STARTED:
+ ok = (d->state == INITIALIZED || d->state == STOPPED);
+ if (ok) {
+ showStatus(i18n("Applet \"%1\" started").arg(appletName()));
+ }
+ break;
+ case STOPPED:
+ ok = (d->state == INITIALIZED || d->state == STARTED);
+ if (ok) {
+ showStatus(i18n("Applet \"%1\" stopped").arg(appletName()));
+ }
+ break;
+ case DESTROYED:
+ ok = true;
+ break;
+ default:
+ break;
+ }
+ if (ok) {
+ d->state = newState;
+ } else {
+ kdError(6100) << "KJavaApplet::stateChange : don't want to switch from state "
+ << d->state << " to " << newState << endl;
+ }
+}
+
+void KJavaApplet::showStatus(const TQString &msg) {
+ TQStringList args;
+ args << msg;
+ context->processCmd("showstatus", args);
+}
+
+void KJavaApplet::setFailed() {
+ d->failed = true;
+}
+
+bool KJavaApplet::isAlive() const {
+ return (
+ !d->failed
+ && d->state >= INSTANCIATED
+ && d->state < STOPPED
+ );
+}
+
+KJavaApplet::AppletState KJavaApplet::state() const {
+ return d->state;
+}
+
+bool KJavaApplet::failed() const {
+ return d->failed;
+}
+
+#include "kjavaapplet.moc"
diff --git a/tdehtml/java/kjavaapplet.h b/tdehtml/java/kjavaapplet.h
new file mode 100644
index 000000000..8e02c5ba4
--- /dev/null
+++ b/tdehtml/java/kjavaapplet.h
@@ -0,0 +1,251 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+
+#ifndef KJAVAAPPLET_H
+#define KJAVAAPPLET_H
+
+#include <kurl.h>
+
+#include <tqobject.h>
+#include <tqstringlist.h>
+#include <tqmap.h>
+
+/**
+ * @short A Java applet
+ *
+ * This class encapsulates the data the Applet Server needs to load
+ * the Applet class files, and set the proper size of the Applet. It also
+ * has an interface for applets to resize themselves.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@kde.org
+ */
+
+class KJavaApplet;
+class KJavaAppletWidget;
+class KJavaAppletContext;
+class KJavaAppletPrivate;
+
+
+class KJavaApplet : public TQObject
+{
+Q_OBJECT
+
+public:
+ // states describing the life cycle of an applet.
+ // keep in sync with applet state in KJASAppletStub.java !
+ typedef enum {
+ UNKNOWN = 0,
+ CLASS_LOADED = 1,
+ INSTANCIATED = 2,
+ INITIALIZED = 3,
+ STARTED = 4,
+ STOPPED = 5,
+ DESTROYED = 6
+ } AppletState;
+ KJavaApplet( KJavaAppletWidget* _parent, KJavaAppletContext* _context = 0 );
+ ~KJavaApplet();
+
+ /**
+ * Set the applet context'.
+ */
+ void setAppletContext( KJavaAppletContext* _context );
+
+ /**
+ * Specify the name of the class file to run. For example 'Lake.class'.
+ */
+ void setAppletClass( const TQString& clazzName );
+
+ /**
+ * Get the name of the Class file the applet should run
+ */
+ TQString& appletClass();
+
+ /**
+ * Set the URL of the document embedding the applet.
+ */
+ void setBaseURL( const TQString& base );
+
+ /**
+ * get the Base URL of the document embedding the applet
+ */
+ TQString& baseURL();
+
+ /**
+ * Set the codebase of the applet classes.
+ */
+ void setCodeBase( const TQString& codeBase );
+
+ /**
+ * Get the codebase of the applet classes
+ */
+ TQString& codeBase();
+
+ /**
+ * Set the list of archives at the Applet's codebase to search in for
+ * class files and other resources
+ */
+ void setArchives( const TQString& _archives );
+
+ /**
+ * Get the list of Archives that should be searched for class files
+ * and other resources
+ */
+ TQString& archives();
+
+ /**
+ * Set the name the applet should be called in its context
+ */
+ void setAppletName( const TQString& name );
+
+ /**
+ * Get the name the applet should be called in its context
+ */
+ TQString& appletName();
+
+ /**
+ * Set the size of the applet
+ */
+ void setSize( TQSize size );
+
+ /**
+ * Get the size of the applet
+ */
+ TQSize size();
+
+ /**
+ * Specify a parameter to be passed to the applet.
+ */
+ void setParameter( const TQString& name, const TQString& value );
+
+ /**
+ * Look up the parameter value for the given Parameter. Returns
+ * TQString::null if the name has not been set.
+ */
+ TQString& parameter( const TQString& name );
+
+ /**
+ * Get a reference to the Paramaters and their values
+ */
+ TQMap<TQString,TQString>& getParams();
+
+ /**
+ * Set the window title for swallowing
+ */
+ void setWindowName( const TQString& title );
+
+ /**
+ * Get the window title this applet should use
+ */
+ TQString& getWindowName();
+
+ /**
+ * Interface for applets to resize themselves
+ */
+ void resizeAppletWidget( int width, int height );
+
+ /**
+ * Send message to AppletServer to create this applet's
+ * frame to be swallowed and download the applet classes
+ */
+ void create();
+
+ /**
+ * Send message to AppletServer to Initialize and show
+ * this applet
+ */
+ void init();
+
+ /**
+ * Returns status of applet- whether it's been created or not
+ */
+ bool isCreated();
+
+ /**
+ * Run the applet.
+ */
+ void start();
+
+ /**
+ * Pause the applet.
+ */
+ void stop();
+
+ /**
+ * Returns the unique ID this applet is given
+ */
+ int appletId();
+
+ /**
+ * Set the applet ID.
+ */
+ void setAppletId( int id );
+
+ KJavaAppletContext* getContext() const { return context; }
+
+ /**
+ * Get/Set the user name
+ */
+ void setUser(const TQString & _user) { username = _user; }
+ const TQString & user () const { return username; }
+
+ /**
+ * Get/Set the user password
+ */
+ void setPassword(const TQString & _password) { userpassword = _password; }
+ const TQString & password () const { return userpassword; }
+
+ /**
+ * Get/Set the auth name
+ */
+ void setAuthName(const TQString & _auth) { authname = _auth; }
+ const TQString & authName () const { return authname; }
+
+ /**
+ * called from the protocol engine
+ * changes the status according to the one on the java side.
+ * Do not call this yourself!
+ */
+ void stateChange ( const int newState );
+ void setFailed ();
+ AppletState state() const;
+ bool failed() const;
+ bool isAlive() const;
+ /**
+ * JavaScript coming from Java
+ **/
+ void jsData (const TQStringList & args) { emit jsEvent (args); }
+signals:
+ void jsEvent (const TQStringList & args);
+private:
+ void showStatus( const TQString &msg);
+ KJavaAppletPrivate* d;
+ TQMap<TQString, TQString> params;
+ KJavaAppletContext* context;
+ int id;
+ TQString username;
+ TQString userpassword;
+ TQString authname;
+};
+
+#endif // KJAVAAPPLET_H
diff --git a/tdehtml/java/kjavaappletcontext.cpp b/tdehtml/java/kjavaappletcontext.cpp
new file mode 100644
index 000000000..76914a5dc
--- /dev/null
+++ b/tdehtml/java/kjavaappletcontext.cpp
@@ -0,0 +1,274 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include "kjavaappletcontext.h"
+#include "kjavaappletserver.h"
+#include "kjavaprocess.h"
+#include "kjavaapplet.h"
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <tqmap.h>
+#include <tqguardedptr.h>
+#include <tqstringlist.h>
+#include <tqregexp.h>
+
+// This file was using 6002, but kdebug.areas didn't know about that number
+#define DEBUGAREA 6100
+
+typedef TQMap< int, TQGuardedPtr<KJavaApplet> > AppletMap;
+
+// For future expansion
+class KJavaAppletContextPrivate
+{
+friend class KJavaAppletContext;
+private:
+ AppletMap applets;
+};
+
+// Static Factory Functions
+int KJavaAppletContext::contextCount = 0;
+
+/* Class Implementation
+ */
+KJavaAppletContext::KJavaAppletContext()
+ : TQObject()
+{
+ d = new KJavaAppletContextPrivate;
+ server = KJavaAppletServer::allocateJavaServer();
+ connect(server->javaProcess(), TQT_SIGNAL(exited(int)), this, TQT_SLOT(javaProcessExited(int)));
+
+ id = contextCount;
+ server->createContext( id, this );
+
+ ++contextCount;
+}
+
+KJavaAppletContext::~KJavaAppletContext()
+{
+ server->destroyContext( id );
+ KJavaAppletServer::freeJavaServer();
+ delete d;
+}
+
+int KJavaAppletContext::contextId()
+{
+ return id;
+}
+
+void KJavaAppletContext::setContextId( int _id )
+{
+ id = _id;
+}
+
+void KJavaAppletContext::registerApplet( KJavaApplet* applet )
+{
+ static int appletId = 0;
+
+ applet->setAppletId( ++appletId );
+ d->applets.insert( appletId, applet );
+}
+
+bool KJavaAppletContext::create( KJavaApplet* applet )
+{
+ return server->createApplet( id, applet->appletId(),
+ applet->appletName(),
+ applet->appletClass(),
+ applet->baseURL(),
+ applet->user(),
+ applet->password(),
+ applet->authName(),
+ applet->codeBase(),
+ applet->archives(),
+ applet->size(),
+ applet->getParams(),
+ applet->getWindowName() );
+
+
+}
+
+void KJavaAppletContext::destroy( KJavaApplet* applet )
+{
+ const int appletId = applet->appletId();
+ d->applets.remove( appletId );
+
+ server->destroyApplet( id, appletId );
+}
+
+void KJavaAppletContext::init( KJavaApplet* applet )
+{
+ server->initApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::start( KJavaApplet* applet )
+{
+ server->startApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::stop( KJavaApplet* applet )
+{
+ server->stopApplet( id, applet->appletId() );
+}
+
+void KJavaAppletContext::processCmd( TQString cmd, TQStringList args )
+{
+ received( cmd, args );
+}
+
+void KJavaAppletContext::received( const TQString& cmd, const TQStringList& arg )
+{
+ kdDebug(6100) << "KJavaAppletContext::received, cmd = >>" << cmd << "<<" << endl;
+ kdDebug(6100) << "arg count = " << arg.count() << endl;
+
+ if ( cmd == TQString::fromLatin1("showstatus")
+ && !arg.empty() )
+ {
+ TQString tmp = arg.first();
+ tmp.replace(TQRegExp("[\n\r]"), "");
+ kdDebug(6100) << "status message = " << tmp << endl;
+ emit showStatus( tmp );
+ }
+ else if ( cmd == TQString::fromLatin1( "showurlinframe" )
+ && arg.count() > 1 )
+ {
+ kdDebug(6100) << "url = " << arg[0] << ", frame = " << arg[1] << endl;
+ emit showDocument( arg[0], arg[1] );
+ }
+ else if ( cmd == TQString::fromLatin1( "showdocument" )
+ && !arg.empty() )
+ {
+ kdDebug(6100) << "url = " << arg.first() << endl;
+ emit showDocument( arg.first(), "_top" );
+ }
+ else if ( cmd == TQString::fromLatin1( "resizeapplet" )
+ && arg.count() > 2 )
+ {
+ //arg[1] should be appletID
+ //arg[2] should be new width
+ //arg[3] should be new height
+ bool ok;
+ const int appletID = arg[0].toInt( &ok );
+ const int width = arg[1].toInt( &ok );
+ const int height = arg[2].toInt( &ok );
+
+ if( !ok )
+ {
+ kdError(DEBUGAREA) << "could not parse out parameters for resize" << endl;
+ }
+ else
+ {
+ KJavaApplet* const tmp = d->applets[appletID];
+ if (tmp)
+ tmp->resizeAppletWidget( width, height );
+ }
+ }
+ else if (cmd.startsWith(TQString::fromLatin1("audioclip_"))) {
+ kdDebug(DEBUGAREA) << "process Audio command (not yet implemented): " << cmd << " " << arg[0] << endl;
+ }
+ else if ( cmd == TQString::fromLatin1( "JS_Event" )
+ && arg.count() > 2 )
+ {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ KJavaApplet * applet;
+ if (ok && (applet = d->applets[appletID]))
+ {
+ TQStringList js_args(arg);
+ js_args.pop_front();
+ applet->jsData(js_args);
+ }
+ else
+ kdError(DEBUGAREA) << "parse JS event " << arg[0] << " " << arg[1] << endl;
+ }
+ else if ( cmd == TQString::fromLatin1( "AppletStateNotification" ) )
+ {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ if (ok)
+ {
+ KJavaApplet* const applet = d->applets[appletID];
+ if ( applet )
+ {
+ const int newState = arg[1].toInt(&ok);
+ if (ok)
+ {
+ applet->stateChange(newState);
+ if (newState == KJavaApplet::INITIALIZED) {
+ kdDebug(DEBUGAREA) << "emit appletLoaded" << endl;
+ emit appletLoaded();
+ }
+ } else
+ kdError(DEBUGAREA) << "AppletStateNotification: status is not numerical" << endl;
+ } else
+ kdWarning(DEBUGAREA) << "AppletStateNotification: No such Applet with ID=" << arg[0] << endl;
+ } else
+ kdError(DEBUGAREA) << "AppletStateNotification: Applet ID is not numerical" << endl;
+ }
+ else if ( cmd == TQString::fromLatin1( "AppletFailed" ) ) {
+ bool ok;
+ const int appletID = arg.first().toInt(&ok);
+ if (ok)
+ {
+ KJavaApplet* const applet = d->applets[appletID];
+ /*
+ TQString errorDetail(arg[1]);
+ errorDetail.replace(TQRegExp(":\\s*"), ":\n");
+ KMessageBox::detailedError(0L, i18n("Java error while loading applet."), errorDetail);
+ */
+ if (applet)
+ applet->setFailed();
+ emit appletLoaded();
+ }
+ }
+}
+
+void KJavaAppletContext::javaProcessExited(int) {
+ AppletMap::iterator it = d->applets.begin();
+ const AppletMap::iterator itEnd = d->applets.end();
+ for (; it != itEnd; ++it)
+ if (!(*it).isNull() && (*it)->isCreated() && !(*it)->failed()) {
+ (*it)->setFailed();
+ if ((*it)->state() < KJavaApplet::INITIALIZED)
+ emit appletLoaded();
+ }
+}
+
+bool KJavaAppletContext::getMember(TQStringList & args, TQStringList & ret_args) {
+ args.push_front( TQString::number(id) );
+ return server->getMember( args, ret_args );
+}
+
+bool KJavaAppletContext::putMember( TQStringList & args ) {
+ args.push_front( TQString::number(id) );
+ return server->putMember( args );
+}
+
+bool KJavaAppletContext::callMember(TQStringList & args, TQStringList &ret_args) {
+ args.push_front( TQString::number(id) );
+ return server->callMember( args, ret_args );
+}
+
+void KJavaAppletContext::derefObject( TQStringList & args ) {
+ args.push_front( TQString::number(id) );
+ server->derefObject( args );
+}
+
+#include <kjavaappletcontext.moc>
diff --git a/tdehtml/java/kjavaappletcontext.h b/tdehtml/java/kjavaappletcontext.h
new file mode 100644
index 000000000..119699f23
--- /dev/null
+++ b/tdehtml/java/kjavaappletcontext.h
@@ -0,0 +1,141 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#ifndef KJAVAAPPLETCONTEXT_H
+#define KJAVAAPPLETCONTEXT_H
+
+#include <tqobject.h>
+
+/**
+ * @short Provides a context for KJavaAppletWidgets
+ *
+ * Applets run in a context- (see the Java documentation for more information
+ * on contexts). Currently, each document in KHTML creates one context, in
+ * which multiple applets can run.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@caldera.com
+ */
+
+
+class KJavaAppletServer;
+class KJavaApplet;
+class KJavaAppletContextPrivate;
+
+class KJavaAppletContext : public TQObject
+{
+Q_OBJECT
+
+public:
+ KJavaAppletContext();
+ ~KJavaAppletContext();
+
+ /**
+ * Returns the ID of this context.
+ */
+ int contextId();
+
+ /**
+ * Sets the ID of this context.
+ */
+ void setContextId( int id );
+
+ /**
+ * registers applet
+ **/
+ void registerApplet( KJavaApplet* );
+
+ /**
+ * Sends a message to create the applet.
+ */
+ bool create( KJavaApplet* );
+
+ /**
+ * Sends a message to destroy the applet.
+ */
+ void destroy( KJavaApplet* );
+
+ /**
+ * Sends a message to initialize the applet.
+ */
+ void init( KJavaApplet* );
+
+ /**
+ * Sends a message to start the applet.
+ */
+ void start( KJavaApplet* );
+
+ /**
+ * Sends a message to stop the applet.
+ */
+ void stop( KJavaApplet* );
+
+ /**
+ * use this for applet call backs, the AppletServer
+ * calls this directly.
+ */
+ void processCmd( TQString cmd, TQStringList args );
+
+ /**
+ * LiveConnect functions
+ */
+ bool getMember(TQStringList & args, TQStringList & ret_args);
+ bool putMember(TQStringList & args);
+ bool callMember(TQStringList & args, TQStringList & ret_args);
+ void derefObject(TQStringList & args);
+
+ KJavaAppletServer* getServer() const { return server; }
+signals:
+ /**
+ * Signals the KHMTL Part to show this as the status message.
+ */
+ void showStatus ( const TQString& txt );
+
+ /**
+ * Signals the KHTML Part to show a url in a given target
+ */
+ void showDocument( const TQString& url, const TQString& target );
+
+ /**
+ * Signals the KHTML Part an applet is loaded
+ **/
+ void appletLoaded();
+
+protected:
+ //The counter to generate ID's for the contexts
+ static int contextCount;
+
+ // The applet server this context is attached to.
+ KJavaAppletServer* server;
+
+protected slots:
+ void received( const TQString& cmd, const TQStringList& arg );
+ void javaProcessExited(int);
+
+private:
+ int id;
+ KJavaAppletContextPrivate* d;
+
+};
+
+#endif // KJAVAAPPLETCONTEXT_H
diff --git a/tdehtml/java/kjavaappletserver.cpp b/tdehtml/java/kjavaappletserver.cpp
new file mode 100644
index 000000000..b125bcc1a
--- /dev/null
+++ b/tdehtml/java/kjavaappletserver.cpp
@@ -0,0 +1,833 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include <config.h>
+#include "kjavaappletserver.h"
+#include "kjavaappletcontext.h"
+#include "kjavaprocess.h"
+#include "kjavadownloader.h"
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <tdeparts/browserextension.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+
+#include <kio/job.h>
+#include <kio/kprotocolmanager.h>
+#include <ksslcertificate.h>
+#include <ksslcertchain.h>
+#include <kssl.h>
+
+#include <tqtimer.h>
+#include <tqguardedptr.h>
+#include <tqvaluelist.h>
+#include <tqptrlist.h>
+#include <tqdir.h>
+#include <tqeventloop.h>
+#include <tqapplication.h>
+#include <tqlabel.h>
+#include <tqdialog.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqregexp.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define KJAS_CREATE_CONTEXT (char)1
+#define KJAS_DESTROY_CONTEXT (char)2
+#define KJAS_CREATE_APPLET (char)3
+#define KJAS_DESTROY_APPLET (char)4
+#define KJAS_START_APPLET (char)5
+#define KJAS_STOP_APPLET (char)6
+#define KJAS_INIT_APPLET (char)7
+#define KJAS_SHOW_DOCUMENT (char)8
+#define KJAS_SHOW_URLINFRAME (char)9
+#define KJAS_SHOW_STATUS (char)10
+#define KJAS_RESIZE_APPLET (char)11
+#define KJAS_GET_URLDATA (char)12
+#define KJAS_URLDATA (char)13
+#define KJAS_SHUTDOWN_SERVER (char)14
+#define KJAS_JAVASCRIPT_EVENT (char)15
+#define KJAS_GET_MEMBER (char)16
+#define KJAS_CALL_MEMBER (char)17
+#define KJAS_PUT_MEMBER (char)18
+#define KJAS_DEREF_OBJECT (char)19
+#define KJAS_AUDIOCLIP_PLAY (char)20
+#define KJAS_AUDIOCLIP_LOOP (char)21
+#define KJAS_AUDIOCLIP_STOP (char)22
+#define KJAS_APPLET_STATE (char)23
+#define KJAS_APPLET_FAILED (char)24
+#define KJAS_DATA_COMMAND (char)25
+#define KJAS_PUT_URLDATA (char)26
+#define KJAS_PUT_DATA (char)27
+#define KJAS_SECURITY_CONFIRM (char)28
+#define KJAS_SHOW_CONSOLE (char)29
+
+
+class JSStackFrame;
+
+typedef TQMap< int, KJavaTDEIOJob* > TDEIOJobMap;
+typedef TQMap< int, JSStackFrame* > JSStack;
+
+class JSStackFrame {
+public:
+ JSStackFrame(JSStack & stack, TQStringList & a)
+ : jsstack(stack), args(a), ticket(counter++), ready(false), exit (false) {
+ jsstack.insert( ticket, this );
+ }
+ ~JSStackFrame() {
+ jsstack.erase( ticket );
+ }
+ JSStack & jsstack;
+ TQStringList & args;
+ int ticket;
+ bool ready : 1;
+ bool exit : 1;
+ static int counter;
+};
+
+int JSStackFrame::counter = 0;
+
+class KJavaAppletServerPrivate
+{
+friend class KJavaAppletServer;
+private:
+ KJavaAppletServerPrivate() : kssl( 0L ) {}
+ ~KJavaAppletServerPrivate() {
+ delete kssl;
+ }
+ int counter;
+ TQMap< int, TQGuardedPtr<KJavaAppletContext> > contexts;
+ TQString appletLabel;
+ JSStack jsstack;
+ TDEIOJobMap kiojobs;
+ bool javaProcessFailed;
+ bool useKIO;
+ KSSL * kssl;
+ //int locked_context;
+ //TQValueList<TQByteArray> java_requests;
+};
+
+static KJavaAppletServer* self = 0;
+
+KJavaAppletServer::KJavaAppletServer()
+{
+ d = new KJavaAppletServerPrivate;
+ process = new KJavaProcess();
+
+ connect( process, TQT_SIGNAL(received(const TQByteArray&)),
+ this, TQT_SLOT(slotJavaRequest(const TQByteArray&)) );
+
+ setupJava( process );
+
+ if( process->startJava() ) {
+ d->appletLabel = i18n( "Loading Applet" );
+ d->javaProcessFailed = false;
+ }
+ else {
+ d->appletLabel = i18n( "Error: java executable not found" );
+ d->javaProcessFailed = true;
+ }
+}
+
+KJavaAppletServer::~KJavaAppletServer()
+{
+ quit();
+
+ delete process;
+ delete d;
+}
+
+TQString KJavaAppletServer::getAppletLabel()
+{
+ if( self )
+ return self->appletLabel();
+ else
+ return TQString::null;
+}
+
+TQString KJavaAppletServer::appletLabel()
+{
+ return d->appletLabel;
+}
+
+KJavaAppletServer* KJavaAppletServer::allocateJavaServer()
+{
+ if( self == 0 )
+ {
+ self = new KJavaAppletServer();
+ self->d->counter = 0;
+ }
+
+ ++(self->d->counter);
+ return self;
+}
+
+void KJavaAppletServer::freeJavaServer()
+{
+ --(self->d->counter);
+
+ if( self->d->counter == 0 )
+ {
+ //instead of immediately quitting here, set a timer to kill us
+ //if there are still no servers- give us one minute
+ //this is to prevent repeated loading and unloading of the jvm
+ TDEConfig config( "konquerorrc", true );
+ config.setGroup( "Java/JavaScript Settings" );
+ if( config.readBoolEntry( "ShutdownAppletServer", true ) )
+ {
+ const int value = config.readNumEntry( "AppletServerTimeout", 60 );
+ TQTimer::singleShot( value*1000, self, TQT_SLOT( checkShutdown() ) );
+ }
+ }
+}
+
+void KJavaAppletServer::checkShutdown()
+{
+ if( self->d->counter == 0 )
+ {
+ delete self;
+ self = 0;
+ }
+}
+
+void KJavaAppletServer::setupJava( KJavaProcess *p )
+{
+ TDEConfig config ( "konquerorrc", true );
+ config.setGroup( "Java/JavaScript Settings" );
+
+ TQString jvm_path = "java";
+
+ TQString jPath = config.readPathEntry( "JavaPath" );
+ if ( !jPath.isEmpty() && jPath != "java" )
+ {
+ // Cut off trailing slash if any
+ if( jPath[jPath.length()-1] == '/' )
+ jPath.remove(jPath.length()-1, 1);
+
+ TQDir dir( jPath );
+ if( dir.exists( "bin/java" ) )
+ {
+ jvm_path = jPath + "/bin/java";
+ }
+ else if (dir.exists( "/jre/bin/java" ) )
+ {
+ jvm_path = jPath + "/jre/bin/java";
+ }
+ else if( TQFile::exists(jPath) )
+ {
+ //check here to see if they entered the whole path the java exe
+ jvm_path = jPath;
+ }
+ }
+
+ //check to see if jvm_path is valid and set d->appletLabel accordingly
+ p->setJVMPath( jvm_path );
+
+ // Prepare classpath variable
+ TQString kjava_class = locate("data", "kjava/kjava.jar");
+ kdDebug(6100) << "kjava_class = " << kjava_class << endl;
+ if( kjava_class.isNull() ) // Should not happen
+ return;
+
+ TQDir dir( kjava_class );
+ dir.cdUp();
+ kdDebug(6100) << "dir = " << dir.absPath() << endl;
+
+ const TQStringList entries = dir.entryList( "*.jar" );
+ kdDebug(6100) << "entries = " << entries.join( ":" ) << endl;
+
+ TQString classes;
+ {
+ TQStringList::ConstIterator it = entries.begin();
+ const TQStringList::ConstIterator itEnd = entries.end();
+ for( ; it != itEnd; ++it )
+ {
+ if( !classes.isEmpty() )
+ classes += ":";
+ classes += dir.absFilePath( *it );
+ }
+ }
+ p->setClasspath( classes );
+
+ // Fix all the extra arguments
+ const TQString extraArgs = config.readEntry( "JavaArgs" );
+ p->setExtraArgs( extraArgs );
+
+ if( config.readBoolEntry( "UseSecurityManager", true ) )
+ {
+ TQString class_file = locate( "data", "kjava/kjava.policy" );
+ p->setSystemProperty( "java.security.policy", class_file );
+
+ p->setSystemProperty( "java.security.manager",
+ "org.kde.kjas.server.KJASSecurityManager" );
+ }
+
+ d->useKIO = config.readBoolEntry( "UseKio", false);
+ if( d->useKIO )
+ {
+ p->setSystemProperty( "kjas.useKio", TQString::null );
+ }
+
+ //check for http proxies...
+ if( KProtocolManager::useProxy() )
+ {
+ // only proxyForURL honors automatic proxy scripts
+ // we do not know the applet url here so we just use a dummy url
+ // this is a workaround for now
+ // FIXME
+ const KURL dummyURL( "http://www.kde.org/" );
+ const TQString httpProxy = KProtocolManager::proxyForURL(dummyURL);
+ kdDebug(6100) << "httpProxy is " << httpProxy << endl;
+
+ const KURL url( httpProxy );
+ p->setSystemProperty( "http.proxyHost", url.host() );
+ p->setSystemProperty( "http.proxyPort", TQString::number( url.port() ) );
+ }
+
+ //set the main class to run
+ p->setMainClass( "org.kde.kjas.server.Main" );
+}
+
+void KJavaAppletServer::createContext( int contextId, KJavaAppletContext* context )
+{
+// kdDebug(6100) << "createContext: " << contextId << endl;
+ if ( d->javaProcessFailed ) return;
+
+ d->contexts.insert( contextId, context );
+
+ TQStringList args;
+ args.append( TQString::number( contextId ) );
+ process->send( KJAS_CREATE_CONTEXT, args );
+}
+
+void KJavaAppletServer::destroyContext( int contextId )
+{
+// kdDebug(6100) << "destroyContext: " << contextId << endl;
+ if ( d->javaProcessFailed ) return;
+ d->contexts.remove( contextId );
+
+ TQStringList args;
+ args.append( TQString::number( contextId ) );
+ process->send( KJAS_DESTROY_CONTEXT, args );
+}
+
+bool KJavaAppletServer::createApplet( int contextId, int appletId,
+ const TQString & name, const TQString & clazzName,
+ const TQString & baseURL, const TQString & user,
+ const TQString & password, const TQString & authname,
+ const TQString & codeBase, const TQString & jarFile,
+ TQSize size, const TQMap<TQString,TQString>& params,
+ const TQString & windowTitle )
+{
+// kdDebug(6100) << "createApplet: contextId = " << contextId << endl
+// << " appletId = " << appletId << endl
+// << " name = " << name << endl
+// << " clazzName = " << clazzName << endl
+// << " baseURL = " << baseURL << endl
+// << " codeBase = " << codeBase << endl
+// << " jarFile = " << jarFile << endl
+// << " width = " << size.width() << endl
+// << " height = " << size.height() << endl;
+
+ if ( d->javaProcessFailed ) return false;
+
+ TQStringList args;
+ args.append( TQString::number( contextId ) );
+ args.append( TQString::number( appletId ) );
+
+ //it's ok if these are empty strings, I take care of it later...
+ args.append( name );
+ args.append( clazzName );
+ args.append( baseURL );
+ args.append( user );
+ args.append( password );
+ args.append( authname );
+ args.append( codeBase );
+ args.append( jarFile );
+
+ args.append( TQString::number( size.width() ) );
+ args.append( TQString::number( size.height() ) );
+
+ args.append( windowTitle );
+
+ //add on the number of parameter pairs...
+ const int num = params.count();
+ const TQString num_params = TQString("%1").arg( num, 8 );
+ args.append( num_params );
+
+ TQMap< TQString, TQString >::ConstIterator it = params.begin();
+ const TQMap< TQString, TQString >::ConstIterator itEnd = params.end();
+
+ for( ; it != itEnd; ++it )
+ {
+ args.append( it.key() );
+ args.append( it.data() );
+ }
+
+ process->send( KJAS_CREATE_APPLET, args );
+
+ return true;
+}
+
+void KJavaAppletServer::initApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ TQStringList args;
+ args.append( TQString::number( contextId ) );
+ args.append( TQString::number( appletId ) );
+
+ process->send( KJAS_INIT_APPLET, args );
+}
+
+void KJavaAppletServer::destroyApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ TQStringList args;
+ args.append( TQString::number(contextId) );
+ args.append( TQString::number(appletId) );
+
+ process->send( KJAS_DESTROY_APPLET, args );
+}
+
+void KJavaAppletServer::startApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ TQStringList args;
+ args.append( TQString::number(contextId) );
+ args.append( TQString::number(appletId) );
+
+ process->send( KJAS_START_APPLET, args );
+}
+
+void KJavaAppletServer::stopApplet( int contextId, int appletId )
+{
+ if ( d->javaProcessFailed ) return;
+ TQStringList args;
+ args.append( TQString::number(contextId) );
+ args.append( TQString::number(appletId) );
+
+ process->send( KJAS_STOP_APPLET, args );
+}
+
+void KJavaAppletServer::showConsole() {
+ if ( d->javaProcessFailed ) return;
+ TQStringList args;
+ process->send( KJAS_SHOW_CONSOLE, args );
+}
+
+void KJavaAppletServer::sendURLData( int loaderID, int code, const TQByteArray& data )
+{
+ TQStringList args;
+ args.append( TQString::number(loaderID) );
+ args.append( TQString::number(code) );
+
+ process->send( KJAS_URLDATA, args, data );
+}
+
+void KJavaAppletServer::removeDataJob( int loaderID )
+{
+ const TDEIOJobMap::iterator it = d->kiojobs.find( loaderID );
+ if (it != d->kiojobs.end()) {
+ it.data()->deleteLater();
+ d->kiojobs.erase( it );
+ }
+}
+
+void KJavaAppletServer::quit()
+{
+ const TQStringList args;
+
+ process->send( KJAS_SHUTDOWN_SERVER, args );
+ process->flushBuffers();
+ process->wait( 10 );
+}
+
+void KJavaAppletServer::slotJavaRequest( const TQByteArray& qb )
+{
+ // qb should be one command only without the length string,
+ // we parse out the command and it's meaning here...
+ TQString cmd;
+ TQStringList args;
+ int index = 0;
+ const int qb_size = qb.size();
+
+ //get the command code
+ const char cmd_code = qb[ index++ ];
+ ++index; //skip the next sep
+
+ //get contextID
+ TQString contextID;
+ while( qb[index] != 0 && index < qb_size )
+ {
+ contextID += qb[ index++ ];
+ }
+ bool ok;
+ const int ID_num = contextID.toInt( &ok ); // context id or kio job id
+ /*if (d->locked_context > -1 &&
+ ID_num != d->locked_context &&
+ (cmd_code == KJAS_JAVASCRIPT_EVENT ||
+ cmd_code == KJAS_APPLET_STATE ||
+ cmd_code == KJAS_APPLET_FAILED))
+ {
+ / * Don't allow requests from other contexts if we're waiting
+ * on a return value that can trigger JavaScript events
+ * /
+ d->java_requests.push_back(qb);
+ return;
+ }*/
+ ++index; //skip the sep
+
+ if (cmd_code == KJAS_PUT_DATA) {
+ // rest of the data is for kio put
+ if (ok) {
+ TDEIOJobMap::iterator it = d->kiojobs.find( ID_num );
+ if (ok && it != d->kiojobs.end()) {
+ TQByteArray qba;
+ qba.setRawData(qb.data() + index, qb.size() - index - 1);
+ it.data()->data(qba);
+ qba.resetRawData(qb.data() + index, qb.size() - index - 1);
+ }
+ kdDebug(6100) << "PutData(" << ID_num << ") size=" << qb.size() - index << endl;
+ } else
+ kdError(6100) << "PutData error " << ok << endl;
+ return;
+ }
+ //now parse out the arguments
+ while( index < qb_size )
+ {
+ int sep_pos = qb.find( 0, index );
+ if (sep_pos < 0) {
+ kdError(6100) << "Missing separation byte" << endl;
+ sep_pos = qb_size;
+ }
+ //kdDebug(6100) << "KJavaAppletServer::slotJavaRequest: "<< TQString::fromLocal8Bit( qb.data() + index, sep_pos - index ) << endl;
+ args.append( TQString::fromLocal8Bit( qb.data() + index, sep_pos - index ) );
+ index = sep_pos + 1; //skip the sep
+ }
+ //here I should find the context and call the method directly
+ //instead of emitting signals
+ switch( cmd_code )
+ {
+ case KJAS_SHOW_DOCUMENT:
+ cmd = TQString::fromLatin1( "showdocument" );
+ break;
+
+ case KJAS_SHOW_URLINFRAME:
+ cmd = TQString::fromLatin1( "showurlinframe" );
+ break;
+
+ case KJAS_SHOW_STATUS:
+ cmd = TQString::fromLatin1( "showstatus" );
+ break;
+
+ case KJAS_RESIZE_APPLET:
+ cmd = TQString::fromLatin1( "resizeapplet" );
+ break;
+
+ case KJAS_GET_URLDATA:
+ if (ok && !args.empty() ) {
+ d->kiojobs.insert(ID_num, new KJavaDownloader(ID_num, args.first()));
+ kdDebug(6100) << "GetURLData(" << ID_num << ") url=" << args.first() << endl;
+ } else
+ kdError(6100) << "GetURLData error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_PUT_URLDATA:
+ if (ok && !args.empty()) {
+ KJavaUploader* const job = new KJavaUploader(ID_num, args.first());
+ d->kiojobs.insert(ID_num, job);
+ job->start();
+ kdDebug(6100) << "PutURLData(" << ID_num << ") url=" << args.first() << endl;
+ } else
+ kdError(6100) << "PutURLData error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_DATA_COMMAND:
+ if (ok && !args.empty()) {
+ const int cmd = args.first().toInt( &ok );
+ TDEIOJobMap::iterator it = d->kiojobs.find( ID_num );
+ if (ok && it != d->kiojobs.end())
+ it.data()->jobCommand( cmd );
+ kdDebug(6100) << "KIO Data command: " << ID_num << " " << args.first() << endl;
+ } else
+ kdError(6100) << "KIO Data command error " << ok << " args:" << args.size() << endl;
+ return;
+ case KJAS_JAVASCRIPT_EVENT:
+ cmd = TQString::fromLatin1( "JS_Event" );
+ kdDebug(6100) << "Javascript request: "<< contextID
+ << " code: " << args[0] << endl;
+ break;
+ case KJAS_GET_MEMBER:
+ case KJAS_PUT_MEMBER:
+ case KJAS_CALL_MEMBER: {
+ const int ticket = args[0].toInt();
+ JSStack::iterator it = d->jsstack.find(ticket);
+ if (it != d->jsstack.end()) {
+ kdDebug(6100) << "slotJavaRequest: " << ticket << endl;
+ args.pop_front();
+ it.data()->args.operator=(args); // just in case ..
+ it.data()->ready = true;
+ it.data()->exit = true;
+ } else
+ kdDebug(6100) << "Error: Missed return member data" << endl;
+ return;
+ }
+ case KJAS_AUDIOCLIP_PLAY:
+ cmd = TQString::fromLatin1( "audioclip_play" );
+ kdDebug(6100) << "Audio Play: url=" << args[0] << endl;
+ break;
+ case KJAS_AUDIOCLIP_LOOP:
+ cmd = TQString::fromLatin1( "audioclip_loop" );
+ kdDebug(6100) << "Audio Loop: url=" << args[0] << endl;
+ break;
+ case KJAS_AUDIOCLIP_STOP:
+ cmd = TQString::fromLatin1( "audioclip_stop" );
+ kdDebug(6100) << "Audio Stop: url=" << args[0] << endl;
+ break;
+ case KJAS_APPLET_STATE:
+ kdDebug(6100) << "Applet State Notification for Applet " << args[0] << ". New state=" << args[1] << endl;
+ cmd = TQString::fromLatin1( "AppletStateNotification" );
+ break;
+ case KJAS_APPLET_FAILED:
+ kdDebug(6100) << "Applet " << args[0] << " Failed: " << args[1] << endl;
+ cmd = TQString::fromLatin1( "AppletFailed" );
+ break;
+ case KJAS_SECURITY_CONFIRM: {
+ if (KSSL::doesSSLWork() && !d->kssl)
+ d->kssl = new KSSL;
+ TQStringList sl;
+ TQCString answer( "invalid" );
+
+ if (!d->kssl) {
+ answer = "nossl";
+ } else if (args.size() > 2) {
+ const int certsnr = args[1].toInt();
+ TQString text;
+ TQPtrList<KSSLCertificate> certs;
+ certs.setAutoDelete( true );
+ for (int i = certsnr; i >= 0; --i) {
+ KSSLCertificate * cert = KSSLCertificate::fromString(args[i+2].ascii());
+ if (cert) {
+ certs.prepend(cert);
+ if (cert->isSigner())
+ text += i18n("Signed by (validation: ");
+ else
+ text += i18n("Certificate (validation: ");
+ switch (cert->validate()) {
+ case KSSLCertificate::Ok:
+ text += i18n("Ok"); break;
+ case KSSLCertificate::NoCARoot:
+ text += i18n("NoCARoot"); break;
+ case KSSLCertificate::InvalidPurpose:
+ text += i18n("InvalidPurpose"); break;
+ case KSSLCertificate::PathLengthExceeded:
+ text += i18n("PathLengthExceeded"); break;
+ case KSSLCertificate::InvalidCA:
+ text += i18n("InvalidCA"); break;
+ case KSSLCertificate::Expired:
+ text += i18n("Expired"); break;
+ case KSSLCertificate::SelfSigned:
+ text += i18n("SelfSigned"); break;
+ case KSSLCertificate::ErrorReadingRoot:
+ text += i18n("ErrorReadingRoot"); break;
+ case KSSLCertificate::Revoked:
+ text += i18n("Revoked"); break;
+ case KSSLCertificate::Untrusted:
+ text += i18n("Untrusted"); break;
+ case KSSLCertificate::SignatureFailed:
+ text += i18n("SignatureFailed"); break;
+ case KSSLCertificate::Rejected:
+ text += i18n("Rejected"); break;
+ case KSSLCertificate::PrivateKeyFailed:
+ text += i18n("PrivateKeyFailed"); break;
+ case KSSLCertificate::InvalidHost:
+ text += i18n("InvalidHost"); break;
+ case KSSLCertificate::Unknown:
+ default:
+ text += i18n("Unknown"); break;
+ }
+ text += TQString(")\n");
+ TQString subject = cert->getSubject() + TQChar('\n');
+ TQRegExp reg(TQString("/[A-Z]+="));
+ int pos = 0;
+ while ((pos = subject.find(reg, pos)) > -1)
+ subject.replace(pos, 1, TQString("\n "));
+ text += subject.mid(1);
+ }
+ }
+ kdDebug(6100) << "Security confirm " << args.first() << certs.count() << endl;
+ if ( !certs.isEmpty() ) {
+ KSSLCertChain chain;
+ chain.setChain( certs );
+ if ( chain.isValid() )
+ answer = PermissionDialog( TQT_TQWIDGET(tqApp->activeWindow()) ).exec( text, args[0] );
+ }
+ }
+ sl.push_front( TQString(answer) );
+ sl.push_front( TQString::number(ID_num) );
+ process->send( KJAS_SECURITY_CONFIRM, sl );
+ return;
+ }
+ default:
+ return;
+ break;
+ }
+
+
+ if( !ok )
+ {
+ kdError(6100) << "could not parse out contextID to call command on" << endl;
+ return;
+ }
+
+ KJavaAppletContext* const context = d->contexts[ ID_num ];
+ if( context )
+ context->processCmd( cmd, args );
+ else if (cmd != "AppletStateNotification")
+ kdError(6100) << "no context object for this id" << endl;
+}
+
+void KJavaAppletServer::endWaitForReturnData() {
+ kdDebug(6100) << "KJavaAppletServer::endWaitForReturnData" << endl;
+ killTimers();
+ JSStack::iterator it = d->jsstack.begin();
+ JSStack::iterator itEnd = d->jsstack.end();
+ for (; it != itEnd; ++it)
+ it.data()->exit = true;
+}
+
+void KJavaAppletServer::timerEvent(TQTimerEvent *) {
+ endWaitForReturnData();
+ kdDebug(6100) << "KJavaAppletServer::timerEvent timeout" << endl;
+}
+
+void KJavaAppletServer::waitForReturnData(JSStackFrame * frame) {
+ kdDebug(6100) << ">KJavaAppletServer::waitForReturnData" << endl;
+ killTimers();
+ startTimer(15000);
+ while (!frame->exit)
+ kapp->eventLoop()->processEvents (TQEventLoop::AllEvents | TQEventLoop::WaitForMore);
+ if (d->jsstack.size() <= 1)
+ killTimers();
+ kdDebug(6100) << "<KJavaAppletServer::waitForReturnData stacksize:" << d->jsstack.size() << endl;
+}
+
+bool KJavaAppletServer::getMember(TQStringList & args, TQStringList & ret_args) {
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( TQString::number(frame.ticket) );
+
+ process->send( KJAS_GET_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready;
+}
+
+bool KJavaAppletServer::putMember( TQStringList & args ) {
+ TQStringList ret_args;
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( TQString::number(frame.ticket) );
+
+ process->send( KJAS_PUT_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready && ret_args.count() > 0 && ret_args[0].toInt();
+}
+
+bool KJavaAppletServer::callMember(TQStringList & args, TQStringList & ret_args) {
+ JSStackFrame frame( d->jsstack, ret_args );
+ args.push_front( TQString::number(frame.ticket) );
+
+ process->send( KJAS_CALL_MEMBER, args );
+ waitForReturnData( &frame );
+
+ return frame.ready;
+}
+
+void KJavaAppletServer::derefObject( TQStringList & args ) {
+ process->send( KJAS_DEREF_OBJECT, args );
+}
+
+bool KJavaAppletServer::usingKIO() {
+ return d->useKIO;
+}
+
+
+PermissionDialog::PermissionDialog( TQWidget* parent )
+ : TQObject(parent), m_button("no")
+{}
+
+TQCString PermissionDialog::exec( const TQString & cert, const TQString & perm ) {
+ TQGuardedPtr<TQDialog> dialog = new TQDialog( TQT_TQWIDGET(parent()), "PermissionDialog");
+
+ dialog->setSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, dialog->sizePolicy().hasHeightForWidth() ) );
+ dialog->setModal( true );
+ dialog->setCaption( i18n("Security Alert") );
+
+ TQVBoxLayout* const dialogLayout = new TQVBoxLayout( dialog, 11, 6, "dialogLayout");
+
+ dialogLayout->addWidget( new TQLabel( i18n("Do you grant Java applet with certificate(s):"), dialog ) );
+ dialogLayout->addWidget( new TQLabel( cert, dialog, "message" ) );
+ dialogLayout->addWidget( new TQLabel( i18n("the following permission"), dialog, "message" ) );
+ dialogLayout->addWidget( new TQLabel( perm, dialog, "message" ) );
+ TQSpacerItem* const spacer2 = new TQSpacerItem( 20, 40, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
+ dialogLayout->addItem( spacer2 );
+
+ TQHBoxLayout* const buttonLayout = new TQHBoxLayout( 0, 0, 6, "buttonLayout");
+
+ TQPushButton* const no = new TQPushButton( i18n("&No"), dialog, "no" );
+ no->setDefault( true );
+ buttonLayout->addWidget( no );
+
+ TQPushButton* const reject = new TQPushButton( i18n("&Reject All"), dialog, "reject" );
+ buttonLayout->addWidget( reject );
+
+ TQPushButton* const yes = new TQPushButton( i18n("&Yes"), dialog, "yes" );
+ buttonLayout->addWidget( yes );
+
+ TQPushButton* const grant = new TQPushButton( i18n("&Grant All"), dialog, "grant" );
+ buttonLayout->addWidget( grant );
+ dialogLayout->addLayout( buttonLayout );
+ dialog->resize( dialog->minimumSizeHint() );
+ //clearWState( WState_Polished );
+
+ connect( no, TQT_SIGNAL( clicked() ), this, TQT_SLOT( clicked() ) );
+ connect( reject, TQT_SIGNAL( clicked() ), this, TQT_SLOT( clicked() ) );
+ connect( yes, TQT_SIGNAL( clicked() ), this, TQT_SLOT( clicked() ) );
+ connect( grant, TQT_SIGNAL( clicked() ), this, TQT_SLOT( clicked() ) );
+
+ dialog->exec();
+ delete dialog;
+
+ return m_button;
+}
+
+PermissionDialog::~PermissionDialog()
+{}
+
+void PermissionDialog::clicked()
+{
+ m_button = TQT_TQOBJECT_CONST(sender())->name();
+ static_cast<const TQWidget*>(sender())->parentWidget()->close();
+}
+
+#include "kjavaappletserver.moc"
diff --git a/tdehtml/java/kjavaappletserver.h b/tdehtml/java/kjavaappletserver.h
new file mode 100644
index 000000000..63463b040
--- /dev/null
+++ b/tdehtml/java/kjavaappletserver.h
@@ -0,0 +1,180 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#ifndef KJAVAAPPLETSERVER_H
+#define KJAVAAPPLETSERVER_H
+
+#include "kjavaprocess.h"
+#include <tqobject.h>
+#include <tqmap.h>
+
+
+/**
+ * @short Communicates with a KJAS server to display and control Java applets.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ */
+
+class KJavaAppletContext;
+class KJavaAppletServerPrivate;
+class JSStackFrame;
+
+class KJavaAppletServer : public TQObject
+{
+Q_OBJECT
+
+public:
+ /**
+ * Create the applet server. These shouldn't be used directly,
+ * use allocateJavaServer instead
+ */
+ KJavaAppletServer();
+ ~KJavaAppletServer();
+
+ /**
+ * A factory method that returns the default server. This is the way this
+ * class is usually instantiated.
+ */
+ static KJavaAppletServer *allocateJavaServer();
+
+ /**
+ * When you are done using your reference to the AppletServer, you must
+ * dereference it by calling freeJavaServer().
+ */
+ static void freeJavaServer();
+
+ /**
+ * This allows the KJavaAppletWidget to display some feedback in a QLabel
+ * while the applet is being loaded. If the java process could not be
+ * started, an error message is displayed instead.
+ */
+ static TQString getAppletLabel();
+
+ /**
+ * Create an applet context with the specified id.
+ */
+ void createContext( int contextId, KJavaAppletContext* context );
+
+ /**
+ * Destroy the applet context with the specified id. All the applets in the
+ * context will be destroyed as well.
+ */
+ void destroyContext( int contextId );
+
+ /**
+ * Create an applet in the specified context with the specified id. The applet
+ * name, class etc. are specified in the same way as in the HTML APPLET tag.
+ */
+ bool createApplet( int contextId, int appletId,
+ const TQString & name, const TQString & clazzName,
+ const TQString & baseURL, const TQString & user,
+ const TQString & password, const TQString & authname,
+ const TQString & codeBase, const TQString & jarFile,
+ TQSize size, const TQMap<TQString, TQString>& params,
+ const TQString & windowTitle );
+
+ /**
+ * This should be called by the KJavaAppletWidget
+ */
+ void initApplet( int contextId, int appletId );
+
+ /**
+ * Destroy an applet in the specified context with the specified id.
+ */
+ void destroyApplet( int contextId, int appletId );
+
+ /**
+ * Start the specified applet.
+ */
+ void startApplet( int contextId, int appletId );
+
+ /**
+ * Stop the specified applet.
+ */
+ void stopApplet( int contextId, int appletId );
+
+ /**
+ * Show java console.
+ */
+ void showConsole();
+
+ /**
+ * Send data we got back from a KJavaDownloader back to the appropriate
+ * class loader.
+ */
+ void sendURLData( int loaderID, int code, const TQByteArray& data );
+ /**
+ * Removes KJavaDownloader from the list (deletes it too).
+ */
+ void removeDataJob( int loaderID );
+
+ /**
+ * Shut down the KJAS server.
+ */
+ void quit();
+ KJavaProcess* javaProcess() { return process; }
+
+ TQString appletLabel();
+
+ void waitForReturnData(JSStackFrame *);
+ void endWaitForReturnData();
+
+ bool getMember(TQStringList & args, TQStringList & ret_args);
+ bool putMember(TQStringList & args);
+ bool callMember(TQStringList & args, TQStringList & ret_args);
+ void derefObject(TQStringList & args);
+
+ bool usingKIO();
+protected:
+ void setupJava( KJavaProcess* p );
+
+ KJavaProcess* process;
+
+protected slots:
+ void slotJavaRequest( const TQByteArray& qb );
+ void checkShutdown();
+ void timerEvent(TQTimerEvent *);
+
+private:
+ KJavaAppletServerPrivate* d;
+
+};
+
+
+class PermissionDialog : public TQObject
+{
+ Q_OBJECT
+public:
+ PermissionDialog( TQWidget* );
+ ~PermissionDialog();
+
+ TQCString exec( const TQString & cert, const TQString & perm );
+
+private slots:
+ void clicked();
+
+private:
+ TQCString m_button;
+};
+
+#endif // KJAVAAPPLETSERVER_H
diff --git a/tdehtml/java/kjavaappletviewer.cpp b/tdehtml/java/kjavaappletviewer.cpp
new file mode 100644
index 000000000..fce5195ff
--- /dev/null
+++ b/tdehtml/java/kjavaappletviewer.cpp
@@ -0,0 +1,635 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
+ *
+ * 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 <stdio.h>
+
+#ifdef KDE_USE_FINAL
+#undef Always
+#endif
+#include <tqdir.h>
+#include <tqtable.h>
+#include <tqpair.h>
+#include <tqtimer.h>
+#include <tqguardedptr.h>
+#include <tqlabel.h>
+
+#include <klibloader.h>
+#include <kaboutdata.h>
+#include <kstaticdeleter.h>
+#include <klocale.h>
+#include <kstatusbar.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kio/authinfo.h>
+#include <dcopclient.h>
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletviewer.h"
+#include "kjavaappletserver.h"
+
+
+K_EXPORT_COMPONENT_FACTORY (kjavaappletviewer, KJavaAppletViewerFactory)
+
+TDEInstance *KJavaAppletViewerFactory::s_instance = 0;
+
+KJavaAppletViewerFactory::KJavaAppletViewerFactory () {
+ s_instance = new TDEInstance ("kjava");
+}
+
+KJavaAppletViewerFactory::~KJavaAppletViewerFactory () {
+ delete s_instance;
+}
+
+KParts::Part *KJavaAppletViewerFactory::createPartObject
+ (TQWidget *wparent, const char *wname,
+ TQObject *parent, const char * name, const char *, const TQStringList & args) {
+ return new KJavaAppletViewer (wparent, wname, parent, name, args);
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaServerMaintainer;
+static KJavaServerMaintainer * serverMaintainer = 0;
+
+class KJavaServerMaintainer {
+public:
+ KJavaServerMaintainer () { }
+ ~KJavaServerMaintainer ();
+
+ KJavaAppletContext * getContext (TQObject*, const TQString &);
+ void releaseContext (TQObject*, const TQString &);
+ void setServer (KJavaAppletServer * s);
+ TQGuardedPtr <KJavaAppletServer> server;
+private:
+ typedef TQMap <QPair <TQObject*, TQString>, QPair <KJavaAppletContext*, int> >
+ ContextMap;
+ ContextMap m_contextmap;
+};
+
+KJavaServerMaintainer::~KJavaServerMaintainer () {
+ delete server;
+}
+
+KJavaAppletContext * KJavaServerMaintainer::getContext (TQObject * w, const TQString & doc) {
+ ContextMap::key_type key = qMakePair (w, doc);
+ ContextMap::iterator it = m_contextmap.find (key);
+ if (it != m_contextmap.end ()) {
+ ++((*it).second);
+ return (*it).first;
+ }
+ KJavaAppletContext* const context = new KJavaAppletContext ();
+ m_contextmap.insert (key, qMakePair(context, 1));
+ return context;
+}
+
+void KJavaServerMaintainer::releaseContext (TQObject * w, const TQString & doc) {
+ ContextMap::iterator it = m_contextmap.find (qMakePair (w, doc));
+ if (it != m_contextmap.end () && --(*it).second <= 0) {
+ kdDebug(6100) << "KJavaServerMaintainer::releaseContext" << endl;
+ (*it).first->deleteLater ();
+ m_contextmap.remove (it);
+ }
+}
+
+inline void KJavaServerMaintainer::setServer (KJavaAppletServer * s) {
+ if (!server)
+ server = s;
+}
+
+static KStaticDeleter <KJavaServerMaintainer> serverMaintainerDeleter;
+
+//-----------------------------------------------------------------------------
+
+AppletParameterDialog::AppletParameterDialog (KJavaAppletWidget * parent)
+ : KDialogBase (parent, "paramdialog", true, i18n ("Applet Parameters"),
+ KDialogBase::Close, KDialogBase::Close, true),
+ m_appletWidget (parent) {
+ KJavaApplet* const applet = parent->applet ();
+ table = new TQTable (30, 2, this);
+ table->setMinimumSize (TQSize (600, 400));
+ table->setColumnWidth (0, 200);
+ table->setColumnWidth (1, 340);
+ TQHeader* const header = table->horizontalHeader();
+ header->setLabel (0, i18n ("Parameter"));
+ header->setLabel (1, i18n ("Value"));
+ TQTableItem * tit = new TQTableItem (table, TQTableItem::Never, i18n("Class"));
+ table->setItem (0, 0, tit);
+ tit = new TQTableItem(table, TQTableItem::Always, applet->appletClass());
+ table->setItem (0, 1, tit);
+ tit = new TQTableItem (table, TQTableItem::Never, i18n ("Base URL"));
+ table->setItem (1, 0, tit);
+ tit = new TQTableItem(table, TQTableItem::Always, applet->baseURL());
+ table->setItem (1, 1, tit);
+ tit = new TQTableItem (table, TQTableItem::Never, i18n ("Archives"));
+ table->setItem (2, 0, tit);
+ tit = new TQTableItem(table, TQTableItem::Always, applet->archives());
+ table->setItem (2, 1, tit);
+ TQMap<TQString,TQString>::const_iterator it = applet->getParams().begin();
+ const TQMap<TQString,TQString>::const_iterator itEnd = applet->getParams().end();
+ for (int count = 2; it != itEnd; ++it) {
+ tit = new TQTableItem (table, TQTableItem::Always, it.key ());
+ table->setItem (++count, 0, tit);
+ tit = new TQTableItem(table, TQTableItem::Always, it.data ());
+ table->setItem (count, 1, tit);
+ }
+ setMainWidget (table);
+}
+
+void AppletParameterDialog::slotClose () {
+ table->selectCells (0, 0, 0, 0);
+ KJavaApplet* const applet = m_appletWidget->applet ();
+ applet->setAppletClass (table->item (0, 1)->text ());
+ applet->setBaseURL (table->item (1, 1)->text ());
+ applet->setArchives (table->item (2, 1)->text ());
+ const int lim = table->numRows();
+ for (int i = 3; i < lim; ++i) {
+ if (table->item (i, 0) && table->item (i, 1) && !table->item (i, 0)->text ().isEmpty ())
+ applet->setParameter (table->item (i, 0)->text (),
+ table->item (i, 1)->text ());
+ }
+ hide ();
+}
+//-----------------------------------------------------------------------------
+
+class CoverWidget : public TQWidget {
+ KJavaAppletWidget * m_appletwidget;
+public:
+ CoverWidget (TQWidget *);
+ ~CoverWidget () {}
+ KJavaAppletWidget * appletWidget () const;
+protected:
+ void resizeEvent (TQResizeEvent * e);
+};
+
+inline CoverWidget::CoverWidget (TQWidget * parent)
+ : TQWidget (parent, "KJavaAppletViewer Widget")
+{
+ m_appletwidget = new KJavaAppletWidget (this);
+ setFocusProxy (m_appletwidget);
+}
+
+inline KJavaAppletWidget * CoverWidget::appletWidget () const {
+ return m_appletwidget;
+}
+
+void CoverWidget::resizeEvent (TQResizeEvent * e) {
+ m_appletwidget->resize (e->size().width(), e->size().height());
+}
+
+//-----------------------------------------------------------------------------
+
+class StatusBarIcon : public TQLabel {
+public:
+ StatusBarIcon (TQWidget * parent) : TQLabel (parent) {
+ setPixmap (SmallIcon (TQString ("java"), KJavaAppletViewerFactory::instance ()));
+ }
+protected:
+ void mousePressEvent (TQMouseEvent *) {
+ serverMaintainer->server->showConsole ();
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+KJavaAppletViewer::KJavaAppletViewer (TQWidget * wparent, const char *,
+ TQObject * parent, const char * name, const TQStringList & args)
+ : KParts::ReadOnlyPart (parent, name),
+ m_browserextension (new KJavaAppletViewerBrowserExtension (this)),
+ m_liveconnect (new KJavaAppletViewerLiveConnectExtension (this)),
+ m_statusbar (new KParts::StatusBarExtension (this)),
+ m_statusbar_icon (0L),
+ m_closed (true)
+{
+ if (!serverMaintainer) {
+ serverMaintainerDeleter.setObject (serverMaintainer,
+ new KJavaServerMaintainer);
+ }
+ m_view = new CoverWidget (wparent);
+ TQString classname, classid, codebase, tdehtml_codebase, src_param;
+ int width = -1;
+ int height = -1;
+ KJavaApplet* const applet = m_view->appletWidget()->applet ();
+ TQStringList::const_iterator it = args.begin();
+ const TQStringList::const_iterator itEnd = args.end();
+ for ( ; it != itEnd; ++it) {
+ const int equalPos = (*it).find("=");
+ if (equalPos > 0) {
+ const TQString name = (*it).left (equalPos).upper ();
+ TQString value = (*it).right ((*it).length () - equalPos - 1);
+ if (value.at(0)=='\"')
+ value = value.right (value.length () - 1);
+ if (value.at (value.length () - 1) == '\"')
+ value.truncate (value.length () - 1);
+ kdDebug(6100) << "name=" << name << " value=" << value << endl;
+ if (!name.isEmpty()) {
+ const TQString name_lower = name.lower ();
+ if (name == "__KHTML__PLUGINBASEURL") {
+ baseurl = KURL (KURL (value), TQString (".")).url ();
+ } else if (name == "__KHTML__CODEBASE")
+ tdehtml_codebase = value;
+ else if (name_lower == TQString::fromLatin1("codebase") ||
+ name_lower == TQString::fromLatin1("java_codebase")) {
+ if (!value.isEmpty ())
+ codebase = value;
+ } else if (name == "__KHTML__CLASSID")
+ //else if (name.lower()==TQString::fromLatin1("classid"))
+ classid = value;
+ else if (name_lower == TQString::fromLatin1("code") ||
+ name_lower == TQString::fromLatin1("java_code"))
+ classname = value;
+ else if (name_lower == TQString::fromLatin1("src"))
+ src_param = value;
+ else if (name_lower == TQString::fromLatin1("archive") ||
+ name_lower == TQString::fromLatin1("java_archive") ||
+ name_lower.startsWith ("cache_archive"))
+ applet->setArchives (value);
+ else if (name_lower == TQString::fromLatin1("name"))
+ applet->setAppletName (value);
+ else if (name_lower == TQString::fromLatin1("width"))
+ width = value.toInt();
+ else if (name_lower == TQString::fromLatin1("height"))
+ height = value.toInt();
+ if (!name.startsWith ("__KHTML__")) {
+ applet->setParameter (name, value);
+ }
+ }
+ }
+ }
+ if (!classid.isEmpty ()) {
+ applet->setParameter ("CLSID", classid);
+ kdDebug(6100) << "classid=" << classid << classid.startsWith("clsid:")<< endl;
+ if (classid.startsWith ("clsid:"))
+ // codeBase contains the URL to the plugin page
+ tdehtml_codebase = baseurl;
+ else if (classname.isEmpty () && classid.startsWith ("java:"))
+ classname = classid.mid(5);
+ }
+ if (classname.isEmpty ())
+ classname = src_param;
+ else if (!src_param.isEmpty ())
+ applet->setParameter (TQString ("SRC"), src_param);
+ if (codebase.isEmpty ())
+ codebase = tdehtml_codebase;
+ if (baseurl.isEmpty ()) {
+ // not embeded in tdehtml
+ TQString pwd = TQDir().absPath ();
+ if (!pwd.endsWith (TQChar (TQDir::separator ())))
+ pwd += TQDir::separator ();
+ baseurl = KURL (KURL (pwd), codebase).url ();
+ }
+ if (width > 0 && height > 0) {
+ m_view->resize (width, height);
+ applet->setSize( TQSize( width, height ) );
+ }
+ applet->setBaseURL (baseurl);
+ // check codebase first
+ const KURL kbaseURL( baseurl );
+ const KURL newURL(kbaseURL, codebase);
+ if (kapp->authorizeURLAction("redirect", KURL(baseurl), newURL))
+ applet->setCodeBase (newURL.url());
+ applet->setAppletClass (classname);
+ KJavaAppletContext* const cxt = serverMaintainer->getContext (parent, baseurl);
+ applet->setAppletContext (cxt);
+
+ KJavaAppletServer* const server = cxt->getServer ();
+
+ serverMaintainer->setServer (server);
+
+ if (!server->usingKIO ()) {
+ /* if this page needs authentication */
+ TDEIO::AuthInfo info;
+ TQString errorMsg;
+ TQCString replyType;
+ TQByteArray params;
+ TQByteArray reply;
+ TDEIO::AuthInfo authResult;
+
+ //(void) dcopClient(); // Make sure to have a dcop client.
+ info.url = baseurl;
+ info.verifyPath = true;
+
+ TQDataStream stream(params, IO_WriteOnly);
+ stream << info << m_view->topLevelWidget()->winId();
+
+ if (!kapp->dcopClient ()->call( "kded", "kpasswdserver", "checkAuthInfo(TDEIO::AuthInfo, long int)", params, replyType, reply ) ) {
+ kdWarning() << "Can't communicate with kded_kpasswdserver!" << endl;
+ } else if ( replyType == "TDEIO::AuthInfo" ) {
+ TQDataStream stream2( reply, IO_ReadOnly );
+ stream2 >> authResult;
+ applet->setUser (authResult.username);
+ applet->setPassword (authResult.password);
+ applet->setAuthName (authResult.realmValue);
+ }
+ }
+
+ /* install event filter for close events */
+ if (wparent)
+ wparent->topLevelWidget ()->installEventFilter (this);
+
+ setInstance (KJavaAppletViewerFactory::instance ());
+ KParts::Part::setWidget (m_view);
+
+ connect (applet->getContext(), TQT_SIGNAL(appletLoaded()), this, TQT_SLOT(appletLoaded()));
+ connect (applet->getContext(), TQT_SIGNAL(showDocument(const TQString&, const TQString&)), m_browserextension, TQT_SLOT(showDocument(const TQString&, const TQString&)));
+ connect (applet->getContext(), TQT_SIGNAL(showStatus(const TQString &)), this, TQT_SLOT(infoMessage(const TQString &)));
+ connect (applet, TQT_SIGNAL(jsEvent (const TQStringList &)), m_liveconnect, TQT_SLOT(jsEvent (const TQStringList &)));
+}
+
+bool KJavaAppletViewer::eventFilter (TQObject *o, TQEvent *e) {
+ if (m_liveconnect->jsSessions () > 0) {
+ switch (e->type()) {
+ case TQEvent::Destroy:
+ case TQEvent::Close:
+ case TQEvent::Quit:
+ return true;
+ default:
+ break;
+ }
+ }
+ return KParts::ReadOnlyPart::eventFilter(o,e);
+}
+
+KJavaAppletViewer::~KJavaAppletViewer () {
+ m_view = 0L;
+ serverMaintainer->releaseContext (TQT_TQOBJECT(parent()), baseurl);
+ if (m_statusbar_icon) {
+ m_statusbar->removeStatusBarItem (m_statusbar_icon);
+ delete m_statusbar_icon;
+ }
+}
+
+bool KJavaAppletViewer::openURL (const KURL & url) {
+ if (!m_view) return false;
+ m_closed = false;
+ KJavaAppletWidget* const w = m_view->appletWidget ();
+ KJavaApplet* const applet = w->applet ();
+ if (applet->isCreated ())
+ applet->stop ();
+ if (applet->appletClass ().isEmpty ()) {
+ // preview without setting a class?
+ if (applet->baseURL ().isEmpty ()) {
+ applet->setAppletClass (url.fileName ());
+ applet->setBaseURL (url.upURL ().url ());
+ } else
+ applet->setAppletClass (url.url ());
+ AppletParameterDialog (w).exec ();
+ applet->setSize (w->sizeHint());
+ }
+ if (!m_statusbar_icon) {
+ KStatusBar *sb = m_statusbar->statusBar();
+ if (sb) {
+ m_statusbar_icon = new StatusBarIcon (sb);
+ m_statusbar->addStatusBarItem (m_statusbar_icon, 0, false);
+ }
+ }
+ // delay showApplet if size is unknown and m_view not shown
+ if (applet->size().width() > 0 || m_view->isVisible())
+ w->showApplet ();
+ else
+ TQTimer::singleShot (10, this, TQT_SLOT (delayedCreateTimeOut ()));
+ if (!applet->failed ())
+ emit started (0L);
+ return url.isValid ();
+}
+
+bool KJavaAppletViewer::closeURL () {
+ kdDebug(6100) << "closeURL" << endl;
+ m_closed = true;
+ KJavaApplet* const applet = m_view->appletWidget ()->applet ();
+ if (applet->isCreated ())
+ applet->stop ();
+ applet->getContext()->getServer()->endWaitForReturnData();
+ return true;
+}
+
+bool KJavaAppletViewer::appletAlive () const {
+ return !m_closed && m_view &&
+ m_view->appletWidget ()->applet () &&
+ m_view->appletWidget ()->applet ()->isAlive ();
+}
+
+bool KJavaAppletViewer::openFile () {
+ return false;
+}
+
+void KJavaAppletViewer::delayedCreateTimeOut () {
+ KJavaAppletWidget* const w = m_view->appletWidget ();
+ if (!w->applet ()->isCreated () && !m_closed)
+ w->showApplet ();
+}
+
+void KJavaAppletViewer::appletLoaded () {
+ if (!m_view) return;
+ KJavaApplet* const applet = m_view->appletWidget ()->applet ();
+ if (applet->isAlive() || applet->failed())
+ emit completed();
+}
+
+void KJavaAppletViewer::infoMessage (const TQString & msg) {
+ m_browserextension->infoMessage(msg);
+}
+
+TDEAboutData* KJavaAppletViewer::createAboutData () {
+ return new TDEAboutData("KJavaAppletViewer", I18N_NOOP("TDE Java Applet Plugin"), "1.0");
+}
+
+//---------------------------------------------------------------------
+
+KJavaAppletViewerBrowserExtension::KJavaAppletViewerBrowserExtension (KJavaAppletViewer * parent)
+ : KParts::BrowserExtension (parent, "KJavaAppletViewer Browser Extension") {
+}
+
+void KJavaAppletViewerBrowserExtension::urlChanged (const TQString & url) {
+ emit setLocationBarURL (url);
+}
+
+void KJavaAppletViewerBrowserExtension::setLoadingProgress (int percentage) {
+ emit loadingProgress (percentage);
+}
+
+void KJavaAppletViewerBrowserExtension::setURLArgs (const KParts::URLArgs & /*args*/) {
+}
+
+void KJavaAppletViewerBrowserExtension::saveState (TQDataStream & stream) {
+ KJavaApplet* const applet = static_cast<KJavaAppletViewer*>(parent())->view()->appletWidget ()->applet ();
+ stream << applet->appletClass();
+ stream << applet->baseURL();
+ stream << applet->archives();
+ stream << applet->getParams().size ();
+ TQMap<TQString,TQString>::const_iterator it = applet->getParams().begin();
+ const TQMap<TQString,TQString>::const_iterator itEnd = applet->getParams().end();
+ for ( ; it != itEnd; ++it) {
+ stream << it.key ();
+ stream << it.data ();
+ }
+}
+
+void KJavaAppletViewerBrowserExtension::restoreState (TQDataStream & stream) {
+ KJavaAppletWidget* const w = static_cast<KJavaAppletViewer*>(parent())->view()->appletWidget();
+ KJavaApplet* const applet = w->applet ();
+ TQString key, val;
+ int paramcount;
+ stream >> val;
+ applet->setAppletClass (val);
+ stream >> val;
+ applet->setBaseURL (val);
+ stream >> val;
+ applet->setArchives (val);
+ stream >> paramcount;
+ for (int i = 0; i < paramcount; ++i) {
+ stream >> key;
+ stream >> val;
+ applet->setParameter (key, val);
+ kdDebug(6100) << "restoreState key:" << key << " val:" << val << endl;
+ }
+ applet->setSize (w->sizeHint ());
+ if (w->isVisible())
+ w->showApplet ();
+}
+
+void KJavaAppletViewerBrowserExtension::showDocument (const TQString & doc,
+ const TQString & frame) {
+ const KURL url (doc);
+ KParts::URLArgs args;
+ args.frameName = frame;
+ emit openURLRequest (url, args);
+}
+
+//-----------------------------------------------------------------------------
+
+KJavaAppletViewerLiveConnectExtension::KJavaAppletViewerLiveConnectExtension(KJavaAppletViewer * parent)
+ : KParts::LiveConnectExtension (parent, "KJavaAppletViewer LiveConnect Extension"), m_viewer (parent) {
+}
+
+bool KJavaAppletViewerLiveConnectExtension::get (
+ const unsigned long objid, const TQString & name,
+ KParts::LiveConnectExtension::Type & type,
+ unsigned long & rid, TQString & value)
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ TQStringList args, ret_args;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ args.append (TQString::number (applet->appletId ()));
+ args.append (TQString::number ((int) objid));
+ args.append (name);
+ m_jssessions++;
+ const bool ret = applet->getContext()->getMember (args, ret_args);
+ m_jssessions--;
+ if (!ret || ret_args.count() != 3) return false;
+ bool ok;
+ int itype = ret_args[0].toInt (&ok);
+ if (!ok || itype < 0) return false;
+ type = (KParts::LiveConnectExtension::Type) itype;
+ rid = ret_args[1].toInt (&ok);
+ if (!ok) return false;
+ value = ret_args[2];
+ return true;
+}
+
+bool KJavaAppletViewerLiveConnectExtension::put(const unsigned long objid, const TQString & name, const TQString & value)
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ TQStringList args;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ args.append (TQString::number (applet->appletId ()));
+ args.append (TQString::number ((int) objid));
+ args.append (name);
+ args.append (value);
+ ++m_jssessions;
+ const bool ret = applet->getContext()->putMember (args);
+ --m_jssessions;
+ return ret;
+}
+
+bool KJavaAppletViewerLiveConnectExtension::call( const unsigned long objid, const TQString & func, const TQStringList & fargs, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, TQString & value )
+{
+ if (!m_viewer->appletAlive ())
+ return false;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ TQStringList args, ret_args;
+ args.append (TQString::number (applet->appletId ()));
+ args.append (TQString::number ((int) objid));
+ args.append (func);
+ args.append (TQString::number ((int) fargs.size ()));
+ {
+ TQStringList::const_iterator it = fargs.begin();
+ const TQStringList::const_iterator itEnd = fargs.end();
+ for ( ; it != itEnd; ++it)
+ args.append(*it);
+ }
+
+ ++m_jssessions;
+ const bool ret = applet->getContext()->callMember (args, ret_args);
+ --m_jssessions;
+ if (!ret || ret_args.count () != 3) return false;
+ bool ok;
+ const int itype = ret_args[0].toInt (&ok);
+ if (!ok || itype < 0) return false;
+ type = (KParts::LiveConnectExtension::Type) itype;
+ retobjid = ret_args[1].toInt (&ok);
+ if (!ok) return false;
+ value = ret_args[2];
+ return true;
+}
+
+void KJavaAppletViewerLiveConnectExtension::unregister(const unsigned long objid)
+{
+ if (!m_viewer->view () || !m_viewer->view ())
+ return;
+ KJavaApplet* const applet = m_viewer->view ()->appletWidget ()->applet ();
+ if (!applet || objid == 0) {
+ // typically a gc after a function call on the applet,
+ // no need to send to the jvm
+ return;
+ }
+ TQStringList args;
+ args.append (TQString::number (applet->appletId ()));
+ args.append (TQString::number ((int) objid));
+ applet->getContext()->derefObject (args);
+}
+
+void KJavaAppletViewerLiveConnectExtension::jsEvent (const TQStringList & args) {
+ if (args.count () < 2 || !m_viewer->appletAlive ())
+ return;
+ bool ok;
+ TQStringList::ConstIterator it = args.begin();
+ const TQStringList::ConstIterator itEnd = args.end();
+ const unsigned long objid = (*it).toInt(&ok);
+ ++it;
+ const TQString event = (*it);
+ ++it;
+ KParts::LiveConnectExtension::ArgList arglist;
+
+ for (; it != itEnd; ++it) {
+ // take a deep breath here
+ const TQStringList::ConstIterator prev = it++;
+ arglist.push_back(KParts::LiveConnectExtension::ArgList::value_type((KParts::LiveConnectExtension::Type) (*prev).toInt(), (*it)));
+ }
+ emit partEvent (objid, event, arglist);
+}
+
+int KJavaAppletViewerLiveConnectExtension::m_jssessions = 0;
+
+//-----------------------------------------------------------------------------
+
+#include "kjavaappletviewer.moc"
diff --git a/tdehtml/java/kjavaappletviewer.desktop b/tdehtml/java/kjavaappletviewer.desktop
new file mode 100644
index 000000000..9a2d16355
--- /dev/null
+++ b/tdehtml/java/kjavaappletviewer.desktop
@@ -0,0 +1,82 @@
+[Desktop Entry]
+Name=Embedded Java Applet Viewer
+Name[af]=Ingelegde Java Program Bekyker
+Name[az]=Daxili Java Applet Nümayişçisi
+Name[be]=Унутраны праглÑдальнік аплетаў Java
+Name[bg]=Вграден визуализатор на Java аплети
+Name[bn]=অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ জাভা অà§à¦¯à¦¾à¦ªà¦²à§‡à¦Ÿ পà§à¦°à¦¦à¦°à§à¦¶à¦•
+Name[br]=Lenner enframmet eus arloadigoù Java
+Name[ca]=Applet encastable del visor Java
+Name[cs]=Zabudovaný prohlížeÄ Java appletů
+Name[csb]=Wbùdowóny przezérnik apletów Java
+Name[cy]=Gwelydd Rhaglennig Java Mewnadeiladedig
+Name[da]=Indlejret Java-applet fremviser
+Name[de]=Eingebetteter Betrachter für Java-Programme
+Name[el]=Ενσωματωμένος Ï€Ïοβολέας μικÏοεφαÏμογών Java
+Name[eo]=Enkonstruita javaplikaĵrigardilo
+Name[es]=Visor de applets de Java empotrables
+Name[et]=Põimitav Java apleti näitaja
+Name[eu]=Kapsulatutako Javaren applet-ikustailea
+Name[fa]=مشاهده‌گر برنامک جاوای نهÙته
+Name[fi]=Upotettava Java-sovelmien näyttäjä
+Name[fr]=Afficheur d'applets Java intégré
+Name[fy]=yn sluten Java Applet Werjefte
+Name[ga]=Amharcán Feidhmchláiríní Java Inleabaithe
+Name[gl]=Visualizador de Applets de Java Incrustado
+Name[he]=מציג יישומוני Java מוטבע
+Name[hi]=अंतरà¥à¤¨à¤¿à¤¹à¤¿à¤¤ जावा à¤à¤ªà¤²à¥‡à¤Ÿ दरà¥à¤¶à¤•
+Name[hr]=Ugrađeni preglednik Java appleta
+Name[hu]=Beágyazott megjelenítőprogram Java kisalkalmazásokhoz
+Name[id]=Penampil Applet Java Tersisipkan
+Name[is]=Ãvefjanlegur Java Applet skoðari
+Name[it]=Visualizzatore integrato di applet Java
+Name[ja]=埋ã‚込㿠Java アプレットビューア
+Name[ka]=ჩáƒáƒ“გმული კáƒáƒ›áƒžáƒáƒœáƒ”ნტი Java áƒáƒžáƒšáƒ”ტების სáƒáƒ©áƒ•áƒ”ნებლáƒáƒ“
+Name[kk]=Ендірілетін Java апплеттерді қарау модулі
+Name[km]=កម្មវិធី​មើល​អាប់ភ្លáŸáž Java ដែលបាន​បង្កប់
+Name[ko]=ë¼ì›Œë„£ì€ ìžë°” 애플릿 보기
+Name[lb]=Agebetteten Java-Applet-Uweiser
+Name[lt]=Įdedamas Java Applet žiūriklis
+Name[lv]=Iegultais Java sÄ«klietotņu (apletu) skatÄ«tÄjs
+Name[mk]=Вгнезден гледач на Java аплети
+Name[mn]=Суулгаж болох Жава Ðпплет Харагч
+Name[ms]=Pelihat Aplet Java Terserta
+Name[nb]=Innebygd Java Applet-viser
+Name[nds]=Inbett Kieker för Java-Lüttprogrammen
+Name[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ जाभा à¤à¤ªà¥à¤²à¥‡à¤Ÿ दरà¥à¤¶à¤•
+Name[nl]=Ingebed Java Applet-weergaveprogramma
+Name[nn]=Innebygd Java-appletvisar
+Name[pa]=ਸ਼ਾਮਿਲ Java Applet ਦਰਸ਼ਕ
+Name[pl]=Wbudowana przeglądarka apletów Javy
+Name[pt]=Visualizador Embebido de 'Applets' Java
+Name[pt_BR]=Visualizador Embutido de Applets Java
+Name[ro]=Vizualizor înglobat de miniaplicaţii Java
+Name[ru]=Ð’Ñтраиваемый модуль проÑмотра аплетов Java
+Name[rw]=Mugaragaza Java Apuleti Irimo
+Name[se]=Vuojuhanláhkái JavaprográmmaÅ¡ Äájeheaddji
+Name[sk]=Vložiteľný prehliadaÄ Java appletov
+Name[sl]=Vgrajeni pregledovalnik vstavkov java
+Name[sq]=Shikues i Ngulitur për JAVA Apletat
+Name[sr]=Уграђени приказивач Java аплета
+Name[sr@Latn]=UgraÄ‘eni prikazivaÄ Java apleta
+Name[sv]=Inbäddningsbar visare av Javaminiprogram
+Name[ta]=உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ ஜாவா சிறà¯à®¨à®¿à®°à®²à¯ காடà¯à®Ÿà®¿
+Name[te]=పొదిగిన జావా ఎపలెటౠచూపరి
+Name[tg]=Шоҳиди Java Applet дар Дарун Сохтан
+Name[th]=ตัวà¹à¸ªà¸”งจาวาà¹à¸­à¸žà¹€à¸žà¸¥à¹‡à¸•à¸—ี่à¸à¸±à¸‡à¸­à¸¢à¸¹à¹ˆ
+Name[tr]=Gömülü Java Aplet Görüntüleyici
+Name[tt]=Java Applet öçen Quşılma-Kürsätkeç
+Name[uk]=Вмонтований переглÑдач аплетів Java
+Name[uz]=Ichki Java appletini koʻruvchi
+Name[uz@cyrillic]=Ички Java апплетини кўрувчи
+Name[vi]=Bộ xem tiểu dụng Java nhúng
+Name[wa]=Ravalé håyneu d' apliketes Java
+Name[zh_CN]=嵌入的 Java å°ç¨‹åºæŸ¥çœ‹å™¨
+Name[zh_TW]=Embedded Java Applet 檢視器
+X-TDE-Library=kjavaappletviewer
+Icon=java
+MimeType=application/x-java-applet;application/x-java;
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+Type=Service
+InitialPreference=2
+X-TDE-BrowserView-PluginsInfo=kjava/pluginsinfo
diff --git a/tdehtml/java/kjavaappletviewer.h b/tdehtml/java/kjavaappletviewer.h
new file mode 100644
index 000000000..9b32e3f21
--- /dev/null
+++ b/tdehtml/java/kjavaappletviewer.h
@@ -0,0 +1,145 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos.vriezen@xs4all.nl>
+ *
+ * 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 KJAVAAPPLETVIEWER_H
+#define KJAVAAPPLETVIEWER_H
+
+#include <tdeparts/part.h>
+#include <tdeparts/browserextension.h>
+#include <tdeparts/statusbarextension.h>
+#include <tdeparts/factory.h>
+#include <kdialogbase.h>
+#include <kurl.h>
+#include <tqobject.h>
+#include <tqstringlist.h>
+#include <tqguardedptr.h>
+
+#include "kjavaappletwidget.h"
+
+class TQTable;
+class TQLabel;
+class KJavaProcess;
+class KJavaAppletViewer;
+class TDEAboutData;
+class TDEInstance;
+class TDEConfig;
+class CoverWidget;
+
+class KJavaAppletViewerBrowserExtension : public KParts::BrowserExtension {
+ Q_OBJECT
+public:
+ KJavaAppletViewerBrowserExtension (KJavaAppletViewer *parent);
+ void urlChanged (const TQString & url);
+ void setLoadingProgress (int percentage);
+
+ void setURLArgs (const KParts::URLArgs & args);
+ void saveState (TQDataStream & stream);
+ void restoreState (TQDataStream & stream);
+public slots:
+ void showDocument (const TQString & doc, const TQString & frame);
+};
+
+class KJavaAppletViewerLiveConnectExtension : public KParts::LiveConnectExtension {
+ Q_OBJECT
+public:
+ KJavaAppletViewerLiveConnectExtension(KJavaAppletViewer * parent);
+
+ bool get (const unsigned long objid, const TQString & field, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, TQString & value);
+ bool put(const unsigned long, const TQString & field, const TQString & value);
+ bool call (const unsigned long , const TQString & func, const TQStringList & args, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, TQString & value);
+ void unregister (const unsigned long objid);
+
+ int jsSessions () const { return m_jssessions; }
+public slots:
+ void jsEvent (const TQStringList & args);
+signals:
+ virtual void partEvent (const unsigned long objid, const TQString & event, const KParts::LiveConnectExtension::ArgList & args);
+
+private:
+ KJavaAppletViewer * m_viewer;
+ static int m_jssessions;
+};
+
+class KJavaAppletViewer : public KParts::ReadOnlyPart {
+ Q_OBJECT
+public:
+ KJavaAppletViewer (TQWidget * wparent, const char * wname,
+ TQObject * parent, const char * name, const TQStringList &args);
+ ~KJavaAppletViewer ();
+ CoverWidget * view () const { return m_view; }
+ static TDEAboutData* createAboutData ();
+
+ KJavaAppletViewerBrowserExtension * browserextension() const
+ { return m_browserextension; }
+ KParts::LiveConnectExtension * liveConnectExtension () const
+ { return m_liveconnect; }
+
+ bool eventFilter (TQObject *o, TQEvent *e);
+
+ bool appletAlive () const;
+public slots:
+ virtual bool openURL (const KURL & url);
+ virtual bool closeURL ();
+ void appletLoaded ();
+ void infoMessage (const TQString &);
+protected:
+ bool openFile();
+private slots:
+ void delayedCreateTimeOut ();
+private:
+ TQGuardedPtr <CoverWidget> m_view;
+ TDEConfig * m_config;
+ KJavaProcess * process;
+ KJavaAppletViewerBrowserExtension * m_browserextension;
+ KJavaAppletViewerLiveConnectExtension * m_liveconnect;
+ KParts::StatusBarExtension * m_statusbar;
+ TQGuardedPtr <TQLabel> m_statusbar_icon;
+ TQString baseurl;
+ bool m_closed;
+};
+
+class KJavaAppletViewerFactory : public KParts::Factory {
+ Q_OBJECT
+public:
+ KJavaAppletViewerFactory ();
+ virtual ~KJavaAppletViewerFactory ();
+ virtual KParts::Part *createPartObject
+ (TQWidget *wparent, const char *wname,
+ TQObject *parent, const char *name,
+ const char *className, const TQStringList &args);
+ static TDEInstance * instance () { return s_instance; }
+private:
+ static TDEInstance * s_instance;
+};
+
+class AppletParameterDialog : public KDialogBase {
+ Q_OBJECT
+public:
+ AppletParameterDialog (KJavaAppletWidget * parent);
+protected slots:
+ void slotClose ();
+private:
+ KJavaAppletWidget * m_appletWidget;
+ TQTable * table;
+};
+
+#endif
diff --git a/tdehtml/java/kjavaappletwidget.cpp b/tdehtml/java/kjavaappletwidget.cpp
new file mode 100644
index 000000000..c096261cd
--- /dev/null
+++ b/tdehtml/java/kjavaappletwidget.cpp
@@ -0,0 +1,140 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include "kjavaappletwidget.h"
+#include "kjavaappletserver.h"
+
+#include <twin.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <tqlabel.h>
+
+
+// For future expansion
+class KJavaAppletWidgetPrivate
+{
+friend class KJavaAppletWidget;
+private:
+ TQLabel* tmplabel;
+};
+
+int KJavaAppletWidget::appletCount = 0;
+
+KJavaAppletWidget::KJavaAppletWidget( TQWidget* parent, const char* name )
+ : QXEmbed ( parent, name)
+{
+ setProtocol(QXEmbed::XPLAIN);
+
+ m_applet = new KJavaApplet( this );
+ d = new KJavaAppletWidgetPrivate;
+ m_kwm = new KWinModule( TQT_TQOBJECT(this) );
+
+ d->tmplabel = new TQLabel( this );
+ d->tmplabel->setText( KJavaAppletServer::getAppletLabel() );
+ d->tmplabel->setAlignment( Qt::AlignCenter | TQt::WordBreak );
+ d->tmplabel->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
+ d->tmplabel->show();
+
+ m_swallowTitle.sprintf( "KJAS Applet - Ticket number %u", appletCount++ );
+ m_applet->setWindowName( m_swallowTitle );
+}
+
+KJavaAppletWidget::~KJavaAppletWidget()
+{
+ delete m_applet;
+ delete d;
+}
+
+void KJavaAppletWidget::showApplet()
+{
+ connect( m_kwm, TQT_SIGNAL( windowAdded( WId ) ),
+ this, TQT_SLOT( setWindow( WId ) ) );
+
+ m_kwm->doNotManage( m_swallowTitle );
+
+ //Now we send applet info to the applet server
+ if ( !m_applet->isCreated() )
+ m_applet->create();
+}
+
+void KJavaAppletWidget::setWindow( WId w )
+{
+ //make sure that this window has the right name, if so, embed it...
+ KWin::WindowInfo w_info = KWin::windowInfo( w );
+ if ( m_swallowTitle == w_info.name() ||
+ m_swallowTitle == w_info.visibleName() )
+ {
+ kdDebug(6100) << "swallowing our window: " << m_swallowTitle
+ << ", window id = " << w << endl;
+ delete d->tmplabel;
+ d->tmplabel = 0;
+
+ // disconnect from KWM events
+ disconnect( m_kwm, TQT_SIGNAL( windowAdded( WId ) ),
+ this, TQT_SLOT( setWindow( WId ) ) );
+
+
+ embed( w );
+ setFocus();
+ }
+}
+
+TQSize KJavaAppletWidget::sizeHint() const
+{
+ kdDebug(6100) << "KJavaAppletWidget::sizeHint()" << endl;
+ TQSize rval = QXEmbed::sizeHint();
+
+ if( rval.width() == 0 || rval.height() == 0 )
+ {
+ if( width() != 0 && height() != 0 )
+ {
+ rval = TQSize( width(), height() );
+ }
+ }
+
+ kdDebug(6100) << "returning: (" << rval.width() << ", " << rval.height() << ")" << endl;
+
+ return rval;
+}
+
+void KJavaAppletWidget::resize( int w, int h )
+{
+ if( d->tmplabel )
+ {
+ d->tmplabel->resize( w, h );
+ m_applet->setSize( TQSize( w, h ) );
+ }
+
+ QXEmbed::resize( w, h );
+}
+
+void KJavaAppletWidget::showEvent (TQShowEvent * e) {
+ QXEmbed::showEvent(e);
+ if (!applet()->isCreated() && !applet()->appletClass().isEmpty()) {
+ // delayed showApplet
+ if (applet()->size().width() <= 0)
+ applet()->setSize (sizeHint());
+ showApplet();
+ }
+}
+
+#include "kjavaappletwidget.moc"
diff --git a/tdehtml/java/kjavaappletwidget.h b/tdehtml/java/kjavaappletwidget.h
new file mode 100644
index 000000000..e84f96039
--- /dev/null
+++ b/tdehtml/java/kjavaappletwidget.h
@@ -0,0 +1,125 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#ifndef KJAVAAPPLETWIDGET_H
+#define KJAVAAPPLETWIDGET_H
+
+#include <tqwidget.h>
+#ifndef Q_WS_QWS //FIXME(?) I don't think this is possible with Qt Embedded
+#include "java/kjavaappletcontext.h"
+#include "java/kjavaapplet.h"
+#include <qxembed.h>
+#include <twinmodule.h>
+
+/**
+ * @short A widget for displaying Java applets
+ *
+ * KJavaAppletWidget provides support for the inclusion of Java applets
+ * in Qt and KDE applications. To create an applet, you must first create
+ * a context object in which it will run. There can be several applets and
+ * contexts in operation at a given time, for example in a web browser there
+ * would be one context object for each web page. Applets in the same context
+ * can communicate with each other, applets in different contexts cannot.
+ * Once you have created a KJavaAppletContext, you can create as many
+ * applets in it as you want.
+ *
+ * Once you have created the applet widget, you should access the applet() method
+ * to call the various setXXX methods to configure the applet,
+ * They correspond to the HTML tags used to embed applets in a web page.
+ * Once the applet is configured, call the create() method to set things in motion.
+ * The applet is running when it first appears, but you can start or stop it
+ * when you like (for example if it scrolls off the screen).
+ *
+ * This widget works by using the KJavaAppletServer, which fires off a
+ * Java server process with which it communicates using the
+ * KDE Java Applet Server (KJAS) protocol over stdin and stdout.
+ * The applet windows are swallowed and attached to the TQWidget, but they are
+ * actually running in a different process. This has the advantage of robustness
+ * and reusability. The details of the communication are hidden from the user
+ * in the KJASAppletServer class. Normally only a single server process is used for
+ * all of the applets in a given application, this is all sorted automatically.
+ * The KJAS server is 100% pure Java, and should also prove useful for people
+ * wishing to add java support to other systems (for example a perl/Tk binding
+ * is perfectly feasible). All you need to do is implement the protocol and
+ * (optionally) swallow the applet windows.
+ *
+ * The applet support in KDE is still dependent on the KWin Window Manager. The
+ * applet swallowing will not work under other Window Managers. Hopefully this
+ * will be fixed in the future.
+ *
+ * For a description of the KJAS protocol, please see the KJAS_GRAMMAR.txt file.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@caldera.com
+ */
+
+class KJavaAppletWidgetPrivate;
+
+class KJavaAppletWidget : public QXEmbed
+{
+ Q_OBJECT
+public:
+ KJavaAppletWidget( TQWidget* parent=0, const char* name=0 );
+
+ ~KJavaAppletWidget();
+
+ /**
+ * Returns a pointer to the KJavaApplet. Use this to
+ * configure the applet's parameters. You can also
+ * use it to start and stop the Applet.
+ */
+ KJavaApplet* applet() { return m_applet; }
+
+ /**
+ * Tells the AppletServer to create, initialize, and
+ * show the Applet.
+ */
+ void showApplet();
+
+ TQSize sizeHint() const;
+ void resize( int, int );
+
+protected slots:
+ /**
+ * This slot is called by KWin when new windows are added. We check
+ * to see if the window has the title we set. If so we embed it.
+ */
+ void setWindow( WId w );
+
+protected:
+ //The counter to generate ID's for the applets
+ static int appletCount;
+ void showEvent (TQShowEvent *);
+
+private:
+ KJavaAppletWidgetPrivate* d;
+
+ KJavaApplet* m_applet;
+ KWinModule* m_kwm;
+ TQString m_swallowTitle;
+
+};
+
+#endif
+#endif // KJAVAAPPLETWIDGET_H
+
diff --git a/tdehtml/java/kjavadownloader.cpp b/tdehtml/java/kjavadownloader.cpp
new file mode 100644
index 000000000..a0a8abdd2
--- /dev/null
+++ b/tdehtml/java/kjavadownloader.cpp
@@ -0,0 +1,298 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include "kjavadownloader.h"
+#include "kjavaappletserver.h"
+
+#include <kurl.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kdebug.h>
+#include <tqfile.h>
+
+static const int DATA = 0;
+static const int FINISHED = 1;
+static const int ERRORCODE = 2;
+static const int HEADERS = 3;
+static const int REDIRECT = 4;
+static const int MIMETYPE = 5;
+static const int CONNECTED = 6;
+static const int REQUESTDATA = 7;
+
+static const int KJAS_STOP = 0;
+static const int KJAS_HOLD = 1;
+static const int KJAS_RESUME = 2;
+
+KJavaTDEIOJob::~KJavaTDEIOJob() {}
+
+void KJavaTDEIOJob::data( const TQByteArray& )
+{
+ kdError(6100) << "Job id mixup" << endl;
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaDownloaderPrivate
+{
+friend class KJavaDownloader;
+public:
+ KJavaDownloaderPrivate() : responseCode(0), isfirstdata(true) {}
+ ~KJavaDownloaderPrivate()
+ {
+ delete url;
+ if (job) job->kill(); // TDEIO::Job::kill deletes itself
+ }
+private:
+ int loaderID;
+ KURL* url;
+ TQByteArray file;
+ TDEIO::TransferJob* job;
+ int responseCode;
+ bool isfirstdata;
+};
+
+
+KJavaDownloader::KJavaDownloader( int ID, const TQString& url )
+{
+ kdDebug(6100) << "KJavaDownloader(" << ID << ") = " << url << endl;
+
+ d = new KJavaDownloaderPrivate;
+
+ d->loaderID = ID;
+ d->url = new KURL( url );
+
+ d->job = TDEIO::get( *d->url, false, false );
+ d->job->addMetaData("PropagateHttpHeader", "true");
+ connect( d->job, TQT_SIGNAL(data( TDEIO::Job*, const TQByteArray& )),
+ this, TQT_SLOT(slotData( TDEIO::Job*, const TQByteArray& )) );
+ connect( d->job, TQT_SIGNAL(connected(TDEIO::Job*)),
+ this, TQT_SLOT(slotConnected(TDEIO::Job*)));
+ connect( d->job, TQT_SIGNAL(mimetype(TDEIO::Job*, const TQString&)),
+ this, TQT_SLOT(slotMimetype(TDEIO::Job*, const TQString&)));
+ connect( d->job, TQT_SIGNAL(result(TDEIO::Job*)),
+ this, TQT_SLOT(slotResult(TDEIO::Job*)) );
+}
+
+KJavaDownloader::~KJavaDownloader()
+{
+ delete d;
+}
+
+void KJavaDownloader::slotData( TDEIO::Job*, const TQByteArray& qb )
+{
+ //kdDebug(6100) << "slotData(" << d->loaderID << ")" << endl;
+
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->isfirstdata) {
+ TQString headers = d->job->queryMetaData("HTTP-Headers");
+ if (!headers.isEmpty()) {
+ d->file.resize( headers.length() );
+ memcpy( d->file.data(), headers.ascii(), headers.length() );
+ server->sendURLData( d->loaderID, HEADERS, d->file );
+ d->file.resize( 0 );
+ }
+ d->isfirstdata = false;
+ }
+ if ( qb.size() )
+ server->sendURLData( d->loaderID, DATA, qb );
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaDownloader::slotConnected(TDEIO::Job*)
+{
+ kdDebug(6100) << "slave connected" << endl;
+ d->responseCode = d->job->error();
+}
+
+void KJavaDownloader::slotMimetype(TDEIO::Job*, const TQString & type) {
+ kdDebug(6100) << "slave mimetype " << type << endl;
+}
+
+void KJavaDownloader::slotResult( TDEIO::Job* )
+{
+ kdDebug(6100) << "slotResult(" << d->loaderID << ")" << endl;
+
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if( d->job->error())
+ {
+ kdDebug(6100) << "slave had an error = " << d->job->errorString() << endl;
+ int code = d->job->error();
+ if (!code)
+ code = 404;
+ TQString codestr = TQString::number(code);
+ d->file.resize(codestr.length());
+ memcpy( d->file.data(), codestr.ascii(), codestr.length() );
+ kdDebug(6100) << "slave had an error = " << code << endl;
+
+ server->sendURLData( d->loaderID, ERRORCODE, d->file );
+ d->file.resize( 0 );
+ }
+ else
+ {
+ server->sendURLData( d->loaderID, FINISHED, d->file );
+ }
+ d->job = 0L; // signal TDEIO::Job::result deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaDownloader::jobCommand( int cmd )
+{
+ if (!d->job) return;
+ switch (cmd) {
+ case KJAS_STOP: {
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") stop" << endl;
+ d->job->kill();
+ d->job = 0L; // TDEIO::Job::kill deletes itself
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+ break;
+ }
+ case KJAS_HOLD:
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") hold" << endl;
+ d->job->suspend();
+ break;
+ case KJAS_RESUME:
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") resume" << endl;
+ d->job->resume();
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+class KJavaUploaderPrivate
+{
+public:
+ KJavaUploaderPrivate() {}
+ ~KJavaUploaderPrivate()
+ {
+ delete url;
+ if (job) job->kill(); // TDEIO::Job::kill deletes itself
+ }
+ int loaderID;
+ KURL* url;
+ TQByteArray file;
+ TDEIO::TransferJob* job;
+ bool finished;
+};
+
+KJavaUploader::KJavaUploader( int ID, const TQString& url )
+{
+ kdDebug(6100) << "KJavaUploader(" << ID << ") = " << url << endl;
+
+ d = new KJavaUploaderPrivate;
+
+ d->loaderID = ID;
+ d->url = new KURL( url );
+ d->job = 0L;
+ d->finished = false;
+}
+
+void KJavaUploader::start()
+{
+ kdDebug(6100) << "KJavaUploader::start(" << d->loaderID << ")" << endl;
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ // create a suspended job
+ d->job = TDEIO::put( *d->url, -1, false, false, false );
+ d->job->suspend();
+ connect( d->job, TQT_SIGNAL(dataReq( TDEIO::Job*, TQByteArray& )),
+ this, TQT_SLOT(slotDataRequest( TDEIO::Job*, TQByteArray& )) );
+ connect( d->job, TQT_SIGNAL(result(TDEIO::Job*)),
+ this, TQT_SLOT(slotResult(TDEIO::Job*)) );
+ server->sendURLData( d->loaderID, CONNECTED, d->file );
+ KJavaAppletServer::freeJavaServer();
+}
+
+KJavaUploader::~KJavaUploader()
+{
+ delete d;
+}
+
+void KJavaUploader::slotDataRequest( TDEIO::Job*, TQByteArray& qb )
+{
+ // send our data and suspend
+ kdDebug(6100) << "slotDataRequest(" << d->loaderID << ") finished:" << d->finished << endl;
+ qb.resize( d->file.size() );
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->file.size() == 0) {
+ d->job = 0L; // eof, job deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ } else {
+ memcpy( qb.data(), d->file.data(), d->file.size() );
+ d->file.resize( 0 );
+ if (!d->finished) {
+ server->sendURLData( d->loaderID, REQUESTDATA, d->file );
+ d->job->suspend();
+ }
+ }
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaUploader::data( const TQByteArray& qb )
+{
+ kdDebug(6100) << "KJavaUploader::data(" << d->loaderID << ")" << endl;
+ d->file.resize( qb.size() );
+ memcpy( d->file.data(), qb.data(), qb.size() );
+ d->job->resume();
+}
+
+void KJavaUploader::slotResult( TDEIO::Job* )
+{
+ kdDebug(6100) << "slotResult(" << d->loaderID << ") job:" << d->job << endl;
+
+ if (!d->job)
+ return;
+ KJavaAppletServer* server = KJavaAppletServer::allocateJavaServer();
+ if (d->job->error())
+ {
+ int code = d->job->error();
+ TQString codestr = TQString::number(code);
+ d->file.resize(codestr.length());
+ memcpy( d->file.data(), codestr.ascii(), codestr.length() );
+ kdDebug(6100) << "slave had an error " << code << ": " << d->job->errorString() << endl;
+
+ server->sendURLData( d->loaderID, ERRORCODE, d->file );
+ d->file.resize( 0 );
+ }
+ else // shouldn't come here
+ kdError(6100) << "slotResult(" << d->loaderID << ") job:" << d->job << endl;
+ d->job = 0L; // signal TDEIO::Job::result deletes itself
+ server->removeDataJob( d->loaderID ); // will delete this
+ KJavaAppletServer::freeJavaServer();
+}
+
+void KJavaUploader::jobCommand( int cmd )
+{
+ if (!d->job) return;
+ switch (cmd) {
+ case KJAS_STOP: {
+ kdDebug(6100) << "jobCommand(" << d->loaderID << ") stop" << endl;
+ d->finished = true;
+ if (d->job->isSuspended())
+ d->job->resume();
+ break;
+ }
+ }
+}
+
+#include "kjavadownloader.moc"
diff --git a/tdehtml/java/kjavadownloader.h b/tdehtml/java/kjavadownloader.h
new file mode 100644
index 000000000..22690824c
--- /dev/null
+++ b/tdehtml/java/kjavadownloader.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+
+#ifndef KJAVADOWNLOADER_H
+#define KJAVADOWNLOADER_H
+
+#include <tqobject.h>
+
+/**
+ * @short A class for handling downloads from KIO
+ *
+ * This class handles a TDEIO::get job and passes the data
+ * back to the AppletServer.
+ *
+ * @author Wynn Wilkes, wynnw@calderasystems.com
+ */
+
+namespace TDEIO {
+ class Job;
+}
+
+class KJavaDownloaderPrivate;
+class KJavaUploaderPrivate;
+
+class KJavaTDEIOJob : public TQObject
+{
+Q_OBJECT
+public:
+ virtual ~KJavaTDEIOJob();
+ virtual void jobCommand( int cmd ) = 0;
+ virtual void data( const TQByteArray& qb );
+};
+
+class KJavaDownloader : public KJavaTDEIOJob
+{
+Q_OBJECT
+
+public:
+ KJavaDownloader( int ID, const TQString& url );
+ ~KJavaDownloader();
+
+ virtual void jobCommand( int cmd );
+protected slots:
+ void slotData( TDEIO::Job*, const TQByteArray& );
+ void slotConnected( TDEIO::Job* );
+ void slotMimetype( TDEIO::Job*, const TQString& );
+ void slotResult( TDEIO::Job* );
+
+private:
+ KJavaDownloaderPrivate* d;
+
+};
+
+class KJavaUploader : public KJavaTDEIOJob
+{
+Q_OBJECT
+
+public:
+ KJavaUploader( int ID, const TQString& url );
+ ~KJavaUploader();
+
+ virtual void jobCommand( int cmd );
+ virtual void data( const TQByteArray& qb );
+ void start();
+protected slots:
+ void slotDataRequest( TDEIO::Job*, TQByteArray& );
+ void slotResult( TDEIO::Job* );
+private:
+ KJavaUploaderPrivate* d;
+
+};
+#endif
diff --git a/tdehtml/java/kjavaprocess.cpp b/tdehtml/java/kjavaprocess.cpp
new file mode 100644
index 000000000..dbe80305e
--- /dev/null
+++ b/tdehtml/java/kjavaprocess.cpp
@@ -0,0 +1,397 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#include "kjavaprocess.h"
+
+#include <kdebug.h>
+#include <kio/kprotocolmanager.h>
+
+#include <tqtextstream.h>
+#include <tqmap.h>
+
+#include <config.h>
+
+#include <unistd.h>
+#include <tqptrlist.h>
+
+class KJavaProcessPrivate
+{
+friend class KJavaProcess;
+private:
+ TQString jvmPath;
+ TQString classPath;
+ TQString mainClass;
+ TQString extraArgs;
+ TQString classArgs;
+ TQPtrList<TQByteArray> BufferList;
+ TQMap<TQString, TQString> systemProps;
+ bool processKilled;
+};
+
+KJavaProcess::KJavaProcess() : TDEProcess()
+{
+ d = new KJavaProcessPrivate;
+ d->BufferList.setAutoDelete( true );
+ d->processKilled = false;
+
+ javaProcess = this; //new TDEProcess();
+
+ connect( javaProcess, TQT_SIGNAL( wroteStdin( TDEProcess * ) ),
+ this, TQT_SLOT( slotWroteData() ) );
+ connect( javaProcess, TQT_SIGNAL( receivedStdout( int, int& ) ),
+ this, TQT_SLOT( slotReceivedData(int, int&) ) );
+ connect( javaProcess, TQT_SIGNAL( processExited (TDEProcess *) ),
+ this, TQT_SLOT( slotExited (TDEProcess *) ) );
+
+ d->jvmPath = "java";
+ d->mainClass = "-help";
+}
+
+KJavaProcess::~KJavaProcess()
+{
+ if ( isRunning() )
+ {
+ kdDebug(6100) << "stopping java process" << endl;
+ stopJava();
+ }
+
+ //delete javaProcess;
+ delete d;
+}
+
+bool KJavaProcess::isRunning()
+{
+ return javaProcess->isRunning();
+}
+
+bool KJavaProcess::startJava()
+{
+ return invokeJVM();
+}
+
+void KJavaProcess::stopJava()
+{
+ killJVM();
+}
+
+void KJavaProcess::setJVMPath( const TQString& path )
+{
+ d->jvmPath = path;
+}
+
+void KJavaProcess::setClasspath( const TQString& classpath )
+{
+ d->classPath = classpath;
+}
+
+void KJavaProcess::setSystemProperty( const TQString& name,
+ const TQString& value )
+{
+ d->systemProps.insert( name, value );
+}
+
+void KJavaProcess::setMainClass( const TQString& className )
+{
+ d->mainClass = className;
+}
+
+void KJavaProcess::setExtraArgs( const TQString& args )
+{
+ d->extraArgs = args;
+}
+
+void KJavaProcess::setClassArgs( const TQString& args )
+{
+ d->classArgs = args;
+}
+
+//Private Utility Functions used by the two send() methods
+TQByteArray* KJavaProcess::addArgs( char cmd_code, const TQStringList& args )
+{
+ //the buffer to store stuff, etc.
+ TQByteArray* const buff = new TQByteArray();
+ TQTextOStream output( *buff );
+ const char sep = 0;
+
+ //make space for the command size: 8 characters...
+ const TQCString space( " " );
+ output << space;
+
+ //write command code
+ output << cmd_code;
+
+ //store the arguments...
+ if( args.isEmpty() )
+ {
+ output << sep;
+ }
+ else
+ {
+ TQStringList::ConstIterator it = args.begin();
+ const TQStringList::ConstIterator itEnd = args.end();
+ for( ; it != itEnd; ++it )
+ {
+ if( !(*it).isEmpty() )
+ {
+ output << (*it).local8Bit();
+ }
+ output << sep;
+ }
+ }
+
+ return buff;
+}
+
+void KJavaProcess::storeSize( TQByteArray* buff )
+{
+ const int size = buff->size() - 8; //subtract out the length of the size_str
+ const TQString size_str = TQString("%1").arg( size, 8 );
+ kdDebug(6100) << "KJavaProcess::storeSize, size = " << size_str << endl;
+
+ const char* size_ptr = size_str.latin1();
+ for( int i = 0; i < 8; ++i )
+ buff->at(i) = size_ptr[i];
+}
+
+void KJavaProcess::sendBuffer( TQByteArray* buff )
+{
+ d->BufferList.append( buff );
+ if( d->BufferList.count() == 1)
+ {
+ popBuffer();
+ }
+}
+
+void KJavaProcess::send( char cmd_code, const TQStringList& args )
+{
+ if( isRunning() )
+ {
+ TQByteArray* const buff = addArgs( cmd_code, args );
+ storeSize( buff );
+ kdDebug(6100) << "<KJavaProcess::send " << (int)cmd_code << endl;
+ sendBuffer( buff );
+ }
+}
+
+void KJavaProcess::send( char cmd_code, const TQStringList& args,
+ const TQByteArray& data )
+{
+ if( isRunning() )
+ {
+ kdDebug(6100) << "KJavaProcess::send, qbytearray is size = " << data.size() << endl;
+
+ TQByteArray* const buff = addArgs( cmd_code, args );
+ const int cur_size = buff->size();
+ const int data_size = data.size();
+ buff->resize( cur_size + data_size );
+ memcpy( buff->data() + cur_size, data.data(), data_size );
+
+ storeSize( buff );
+ sendBuffer( buff );
+ }
+}
+
+void KJavaProcess::popBuffer()
+{
+ TQByteArray* const buf = d->BufferList.first();
+ if( buf )
+ {
+// DEBUG stuff...
+// kdDebug(6100) << "Sending buffer to java, buffer = >>";
+// for( unsigned int i = 0; i < buf->size(); i++ )
+// {
+// if( buf->at(i) == (char)0 )
+// kdDebug(6100) << "<SEP>";
+// else if( buf->at(i) > 0 && buf->at(i) < 10 )
+// kdDebug(6100) << "<CMD " << (int) buf->at(i) << ">";
+// else
+// kdDebug(6100) << buf->at(i);
+// }
+// kdDebug(6100) << "<<" << endl;
+
+ //write the data
+ if ( !javaProcess->writeStdin( buf->data(),
+ buf->size() ) )
+ {
+ kdError(6100) << "Could not write command" << endl;
+ }
+ }
+}
+
+void KJavaProcess::slotWroteData( )
+{
+ //do this here- we can't free the data until we know it went through
+ d->BufferList.removeFirst(); //this should delete it since we setAutoDelete(true)
+ kdDebug(6100) << "slotWroteData " << d->BufferList.count() << endl;
+
+ if ( !d->BufferList.isEmpty() )
+ {
+ popBuffer();
+ }
+}
+
+
+bool KJavaProcess::invokeJVM()
+{
+
+ *javaProcess << d->jvmPath;
+
+ if( !d->classPath.isEmpty() )
+ {
+ *javaProcess << "-classpath";
+ *javaProcess << d->classPath;
+ }
+
+ //set the system properties, iterate through the qmap of system properties
+ TQMap<TQString,TQString>::ConstIterator it = d->systemProps.begin();
+ const TQMap<TQString,TQString>::ConstIterator itEnd = d->systemProps.end();
+
+ for( ; it != itEnd; ++it )
+ {
+ TQString currarg;
+
+ if( !it.key().isEmpty() )
+ {
+ currarg = "-D" + it.key();
+ if( !it.data().isEmpty() )
+ currarg += "=" + it.data();
+ }
+
+ if( !currarg.isEmpty() )
+ *javaProcess << currarg;
+ }
+
+ //load the extra user-defined arguments
+ if( !d->extraArgs.isEmpty() )
+ {
+ // BUG HERE: if an argument contains space (-Dname="My name")
+ // this parsing will fail. Need more sophisticated parsing -- use KShell?
+ const TQStringList args = TQStringList::split( " ", d->extraArgs );
+ TQStringList::ConstIterator it = args.begin();
+ const TQStringList::ConstIterator itEnd = args.end();
+ for ( ; it != itEnd; ++it )
+ *javaProcess << *it;
+ }
+
+ *javaProcess << d->mainClass;
+
+ if ( !d->classArgs.isNull() )
+ *javaProcess << d->classArgs;
+
+ kdDebug(6100) << "Invoking JVM now...with arguments = " << endl;
+ TQString argStr;
+ TQTextOStream stream( &argStr );
+ const TQValueList<TQCString> args = javaProcess->args();
+ tqCopy( args.begin(), args.end(), TQTextOStreamIterator<TQCString>( stream, " " ) );
+ kdDebug(6100) << argStr << endl;
+
+ TDEProcess::Communication flags = (TDEProcess::Communication)
+ (TDEProcess::Stdin | TDEProcess::Stdout |
+ TDEProcess::NoRead);
+
+ const bool rval = javaProcess->start( TDEProcess::NotifyOnExit, flags );
+ if( rval )
+ javaProcess->resume(); //start processing stdout on the java process
+ else
+ killJVM();
+
+ return rval;
+}
+
+void KJavaProcess::killJVM()
+{
+ d->processKilled = true;
+ disconnect( javaProcess, TQT_SIGNAL( receivedStdout( int, int& ) ),
+ this, TQT_SLOT( slotReceivedData(int, int&) ) );
+ javaProcess->kill();
+}
+
+void KJavaProcess::flushBuffers()
+{
+ while ( !d->BufferList.isEmpty() ) {
+ if (innot)
+ slotSendData(0);
+ else
+ d->BufferList.removeFirst(); //note: AutoDelete is true
+ }
+}
+
+/* In this method, read one command and send it to the d->appletServer
+ * then return, so we don't block the event handling
+ */
+void KJavaProcess::slotReceivedData( int fd, int& len )
+{
+ //read out the length of the message,
+ //read the message and send it to the applet server
+ char length[9] = { 0 };
+ const int num_bytes = ::read( fd, length, 8 );
+ if( !num_bytes )
+ {
+ len = 0;
+ return;
+ }
+ if( num_bytes == -1 )
+ {
+ kdError(6100) << "could not read 8 characters for the message length!!!!" << endl;
+ len = 0;
+ return;
+ }
+
+ const TQString lengthstr( length );
+ bool ok;
+ const int num_len = lengthstr.toInt( &ok );
+ if( !ok )
+ {
+ kdError(6100) << "could not parse length out of: " << lengthstr << endl;
+ len = num_bytes;
+ return;
+ }
+
+ //now parse out the rest of the message.
+ char* const msg = new char[num_len];
+ const int num_bytes_msg = ::read( fd, msg, num_len );
+ if( num_bytes_msg == -1 || num_bytes_msg != num_len )
+ {
+ kdError(6100) << "could not read the msg, num_bytes_msg = " << num_bytes_msg << endl;
+ delete[] msg;
+ len = num_bytes;
+ return;
+ }
+
+ TQByteArray qb;
+ emit received( qb.duplicate( msg, num_len ) );
+ delete[] msg;
+ len = num_bytes + num_bytes_msg;
+}
+
+void KJavaProcess::slotExited( TDEProcess *process )
+{
+ if (process == javaProcess) {
+ int status = -1;
+ if (!d->processKilled) {
+ status = javaProcess->exitStatus();
+ }
+ kdDebug(6100) << "jvm exited with status " << status << endl;
+ emit exited(status);
+ }
+}
+
+#include "kjavaprocess.moc"
diff --git a/tdehtml/java/kjavaprocess.h b/tdehtml/java/kjavaprocess.h
new file mode 100644
index 000000000..4768bc382
--- /dev/null
+++ b/tdehtml/java/kjavaprocess.h
@@ -0,0 +1,164 @@
+// -*- c++ -*-
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Richard Moore <rich@kde.org>
+ * 2000 Wynn Wilkes <wynnw@caldera.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.
+ */
+
+#ifndef KJAVAPROCESS_H
+#define KJAVAPROCESS_H
+
+#include <kprocess.h>
+#include <tqcstring.h>
+
+/**
+ * @short A class for invoking a Java VM
+ *
+ * This class is a general tool for invoking a Java interpreter. It allows you
+ * to specify some of the standard options that should be understood by all
+ * JVMs.
+ *
+ * @author Richard J. Moore, rich@kde.org
+ * @author Wynn Wilkes, wynnw@calderasystems.com
+ */
+
+class KJavaProcessPrivate;
+class KJavaProcess : public TDEProcess //QObject
+{
+Q_OBJECT
+
+public:
+ /**
+ * Creates a process object, the process is NOT invoked at this point.
+ * You should first set the process's parameters, and then call startJava.
+ */
+ KJavaProcess();
+ virtual ~KJavaProcess();
+
+ /**
+ * Invoke the JVM with the parameters that have been set. The Java process
+ * will start after this call.
+ */
+ bool startJava();
+
+ /**
+ * Stop the JVM (if it's running).
+ */
+ void stopJava();
+
+ /**
+ * Returns the status of the java Process- true if it's ok, false if it has died.
+ * It calls TDEProcess::isRunning()
+ */
+ bool isRunning();
+
+ /**
+ * Used to specify the path to the Java executable to be run.
+ */
+ void setJVMPath( const TQString& path );
+
+ /**
+ * This will set the classpath the Java process will use. It's used as a the
+ * -cp command line option. It adds every jar file stored in $TDEDIRS/share/apps/kjava/
+ * to the classpath, and then adds the $CLASSPATH environmental variable. This allows
+ * users to simply drop the JSSE (Java Secure Sockets Extension classes into that directory
+ * without having to modify the jvm configuration files.
+ */
+ void setClasspath( const TQString& classpath );
+
+ /**
+ * Set a property on the java command line as -Dname=value, or -Dname if value is TQString::null.
+ * For example, you could call setSystemProperty( "kjas.debug", "" ) to set the kjas.debug property.
+ */
+ void setSystemProperty( const TQString& name, const TQString& value );
+
+ /**
+ * The class to be called when startJava() is called.
+ */
+ void setMainClass( const TQString& clazzName );
+
+ /**
+ * Extra flags passed to the JVM.
+ */
+ void setExtraArgs( const TQString& args );
+
+ /**
+ * Arguments passed to the main class. They will be very last in the java
+ * command line, after the main class.
+ */
+ void setClassArgs( const TQString& classArgs );
+
+ /**
+ * Sends a command to the KJAS Applet Server by building a QByteArray
+ * out of the data, and then writes it standard out.
+ */
+ void send( char cmd_code, const TQStringList& args );
+
+ /**
+ * Sends a command to the KJAS Applet Server by building a QByteArray
+ * out of the data, and then writes it standard out. It adds each QString
+ * in the arg list, and then adds the data array.
+ */
+ void send( char cmd_code, const TQStringList& args, const TQByteArray& data );
+
+ /**
+ * Writes all pending data to JVM
+ **/
+ void flushBuffers();
+
+protected slots:
+ /**
+ * This slot is called whenever something is written to stdin of the process.
+ * It's called again to make sure we keep emptying out the buffer that contains
+ * the messages we need send.
+ */
+ void slotWroteData();
+
+ /**
+ * This slot is called when the Java Process writes to standard out. We then
+ * process the data from the file descriptor that is passed to us and send the
+ * command to the AppletServer
+ */
+ void slotReceivedData( int, int& );
+ /**
+ * This slot is called when the Java Process exited.
+ */
+ void slotExited( TDEProcess *process );
+
+protected:
+ virtual bool invokeJVM();
+ virtual void killJVM();
+
+ TQByteArray* addArgs( char cmd_code, const TQStringList& args );
+ void popBuffer();
+ void sendBuffer( TQByteArray* buff );
+ void storeSize( TQByteArray* buff );
+
+ TDEProcess* javaProcess;
+
+signals:
+ void received( const TQByteArray& );
+ void exited( int status );
+
+private:
+ KJavaProcessPrivate *d;
+
+};
+
+#endif // KJAVAPROCESS_H
diff --git a/tdehtml/java/kqeventutil.cpp b/tdehtml/java/kqeventutil.cpp
new file mode 100644
index 000000000..ff15e97da
--- /dev/null
+++ b/tdehtml/java/kqeventutil.cpp
@@ -0,0 +1,200 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.com>
+ * 2002 Till Krech <till@snafu.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 <tqevent.h>
+#include "kqeventutil.h"
+
+TQString KQEventUtil::getQtEventName( TQEvent* e )
+{
+ TQString s;
+
+ switch( e->type() )
+ {
+ case TQEvent::None:
+ s = "None";
+ break;
+ case TQEvent::Timer:
+ s = "Timer";
+ break;
+ case TQEvent::MouseButtonPress:
+ s = "MouseButtonPress";
+ break;
+ case TQEvent::MouseButtonRelease:
+ s = "MouseButtonRelease";
+ break;
+ case TQEvent::MouseButtonDblClick:
+ s = "MouseButtonClick";
+ break;
+ case TQEvent::MouseMove:
+ s = "MouseMove";
+ break;
+ case TQEvent::KeyPress:
+ s = "KeyPress";
+ break;
+ case TQEvent::KeyRelease:
+ s = "KeyRelease";
+ break;
+ case TQEvent::FocusIn:
+ s = "FocusIn";
+ break;
+ case TQEvent::FocusOut:
+ s = "FocusOut";
+ break;
+ case TQEvent::Enter:
+ s = "Enter";
+ break;
+ case TQEvent::Leave:
+ s = "Leave";
+ break;
+ case TQEvent::Paint:
+ s = "Paint";
+ break;
+ case TQEvent::Move:
+ s = "Move";
+ break;
+ case TQEvent::Resize:
+ s = "Resize";
+ break;
+ case TQEvent::Create:
+ s = "Create";
+ break;
+ case TQEvent::Destroy:
+ s = "Destroy";
+ break;
+ case TQEvent::Show:
+ s = "Show";
+ break;
+ case TQEvent::Hide:
+ s = "Hide";
+ break;
+ case TQEvent::Close:
+ s = "Close";
+ break;
+ case TQEvent::Quit:
+ s = "Quit";
+ break;
+ case TQEvent::Reparent:
+ s = "Reparent";
+ break;
+ case TQEvent::ShowMinimized:
+ s = "ShowMinimized";
+ break;
+ case TQEvent::ShowNormal:
+ s = "ShowNormal";
+ break;
+ case TQEvent::WindowActivate:
+ s = "WindowActivate";
+ break;
+ case TQEvent::WindowDeactivate:
+ s = "WindowDeactivate";
+ break;
+ case TQEvent::ShowToParent:
+ s = "ShowToParent";
+ break;
+ case TQEvent::HideToParent:
+ s = "HideToParent";
+ break;
+ case TQEvent::ShowMaximized:
+ s = "ShowMaximized";
+ break;
+ case TQEvent::Accel:
+ s = "Accel";
+ break;
+ case TQEvent::Wheel:
+ s = "Wheel";
+ break;
+ case TQEvent::AccelAvailable:
+ s = "AccelAvailable";
+ break;
+ case TQEvent::CaptionChange:
+ s = "CaptionChange";
+ break;
+ case TQEvent::IconChange:
+ s = "IconChange";
+ break;
+ case TQEvent::ParentFontChange:
+ s = "ParentFontChange";
+ break;
+ case TQEvent::ApplicationFontChange:
+ s = "ApplicationFontChange";
+ break;
+ case TQEvent::ParentPaletteChange:
+ s = "ParentPaletteChange";
+ break;
+ case TQEvent::ApplicationPaletteChange:
+ s = "ApplicationPaletteChange";
+ break;
+ case TQEvent::Clipboard:
+ s = "Clipboard";
+ break;
+ case TQEvent::Speech:
+ s = "Speech";
+ break;
+ case TQEvent::SockAct:
+ s = "SockAct";
+ break;
+ case TQEvent::AccelOverride:
+ s = "AccelOverride";
+ break;
+ case TQEvent::DragEnter:
+ s = "DragEnter";
+ break;
+ case TQEvent::DragMove:
+ s = "DragMove";
+ break;
+ case TQEvent::DragLeave:
+ s = "DragLeave";
+ break;
+ case TQEvent::Drop:
+ s = "Drop";
+ break;
+ case TQEvent::DragResponse:
+ s = "DragResponse";
+ break;
+ case TQEvent::ChildInserted:
+ s = "ChildInserted";
+ break;
+ case TQEvent::ChildRemoved:
+ s = "ChildRemoved";
+ break;
+ case TQEvent::LayoutHint:
+ s = "LayoutHint";
+ break;
+ case TQEvent::ShowWindowRequest:
+ s = "ShowWindowRequest";
+ break;
+ case TQEvent::ActivateControl:
+ s = "ActivateControl";
+ break;
+ case TQEvent::DeactivateControl:
+ s = "DeactivateControl";
+ break;
+ case TQEvent::User:
+ s = "User Event";
+ break;
+
+ default:
+ s = "Undefined Event, value = " + TQString::number( e->type() );
+ break;
+ }
+
+ return s;
+}
diff --git a/tdehtml/java/kqeventutil.h b/tdehtml/java/kqeventutil.h
new file mode 100644
index 000000000..c7ec19bf0
--- /dev/null
+++ b/tdehtml/java/kqeventutil.h
@@ -0,0 +1,34 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Wynn Wilkes <wynnw@caldera.com>
+ * 2002 Till Krech <till@snafu.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.
+ */
+
+#ifndef KQEVENTUTIL_H
+#define KQEVENTUTIL_H
+
+#include <tqstring.h>
+class TQEvent;
+
+class KQEventUtil {
+ public:
+ static TQString getQtEventName(TQEvent *e);
+};
+
+#endif
diff --git a/tdehtml/java/kxeventutil.cpp b/tdehtml/java/kxeventutil.cpp
new file mode 100644
index 000000000..9afa5a5ac
--- /dev/null
+++ b/tdehtml/java/kxeventutil.cpp
@@ -0,0 +1,408 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till Krech <till@snafu.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 <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+
+#include "kxeventutil.h"
+
+TQString KXEventUtil::getXAnyEventInfo(XEvent *xevent) {
+ XAnyEvent *e = &xevent->xany;
+ TQString winname("window");
+ switch (e->type) {
+ case GraphicsExpose:
+ case NoExpose:
+ winname="drawable";
+ break;
+ case CreateNotify:
+ case ConfigureRequest:
+ winname="parent";
+ break;
+ case DestroyNotify:
+ case ConfigureNotify:
+ case MapNotify:
+ case ReparentNotify:
+ case UnmapNotify:
+ winname="event";
+ default:
+ break;
+ }
+ TQString s("serial=%1 send_event=%2 display=0x%3 %4=%5");
+ return
+ s.arg(e->serial)
+ .arg(e->send_event)
+ .arg((long)e->display, 0, 16)
+ .arg(winname)
+ .arg(e->window);
+}
+TQString KXEventUtil::getXButtonEventInfo(XEvent *xevent) {
+ XButtonEvent *e = &xevent->xbutton;
+ TQString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 button=%9");
+ TQString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->button)
+ +t.arg(e->same_screen);
+}
+
+TQString KXEventUtil::getXKeyEventInfo(XEvent *xevent) {
+ XKeyEvent *e = &xevent->xkey;
+ TQString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 keycode=%9");
+ TQString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->keycode)
+ +t.arg(e->same_screen);
+}
+
+TQString KXEventUtil::getXMotionEventInfo(XEvent *xevent) {
+ XMotionEvent *e = &xevent->xmotion;
+ TQString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 state=%8 is_hint=%9");
+ TQString t(" same_screen=%1");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->state)
+ .arg(e->is_hint)
+ +t.arg(e->same_screen);
+}
+TQString KXEventUtil::getXCrossingEventInfo(XEvent *xevent) {
+ XCrossingEvent *e = &xevent->xcrossing;
+ TQString ms, ds;
+ switch (e->mode) {
+ case NotifyNormal: ms = "NotifyNormal"; break;
+ case NotifyGrab: ms = "NotifyGrab"; break;
+ case NotifyUngrab: ms = "NotifyUngrab"; break;
+ default: ms="?";
+ }
+ switch (e->detail) {
+ case NotifyAncestor: ds = "NotifyAncestor"; break;
+ case NotifyVirtual: ds = "NotifyVirtual"; break;
+ case NotifyInferior: ds = "NotifyInferior"; break;
+ case NotifyNonlinear: ds = "NotifyNonlinear"; break;
+ case NotifyNonlinearVirtual: ds = "NotifyNonlinearVirtual"; break;
+ default: ds="?";
+ }
+
+ TQString s("root=%1 subwindow=%2 time=%3 x=%4 y=%5 x_root=%6 y_root=%7 mode=%8=%9 ");
+ TQString t("detail=%1=%2 same_screen=%3 focus=%4 state=%5");
+ return
+ s.arg(e->root)
+ .arg(e->subwindow)
+ .arg(e->time)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->x_root)
+ .arg(e->y_root)
+ .arg(e->mode).arg(ms)
+ +
+ t.arg(e->detail).arg(ds)
+ .arg(e->same_screen)
+ .arg(e->focus)
+ .arg(e->state);
+}
+TQString KXEventUtil::getXFocusChangeEventInfo(XEvent *xevent) {
+ XFocusChangeEvent *e = &xevent->xfocus;
+ TQString s("mode=%1 detail=%2");
+ return
+ s.arg(e->mode)
+ .arg(e->detail);
+}
+TQString KXEventUtil::getXExposeEventInfo(XEvent *xevent) {
+ XExposeEvent *e = &xevent->xexpose;
+ TQString s("x=%1 y=%2 width=%3 height=%4 count=%5");
+ return
+ s.arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->count);
+}
+
+
+
+TQString KXEventUtil::getXGraphicsExposeEventInfo(XEvent *xevent) {
+ XGraphicsExposeEvent *e = &xevent->xgraphicsexpose;
+ TQString s("x=%1 y=%2 width=%3 height=%4 count=%5 major_code=%6 minor_code=%7");
+ return
+ s.arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->count)
+ .arg(e->major_code)
+ .arg(e->minor_code);
+}
+TQString KXEventUtil::getXNoExposeEventInfo(XEvent *xevent) {
+ XNoExposeEvent *e = &xevent->xnoexpose;
+ TQString s("major_code=%1 minor_code=%2");
+ return
+ s.arg(e->major_code)
+ .arg(e->minor_code);
+}
+
+
+TQString KXEventUtil::getXCreateWindowEventInfo(XEvent *xevent) {
+ XCreateWindowEvent *e = &xevent->xcreatewindow;
+ TQString s("window=%1 x=%2 y=%3 width=%4 height=%5 border_width=%6 override_redirect=%7");
+ return
+ s.arg(e->window)
+ .arg(e->x)
+ .arg(e->y)
+ .arg(e->width)
+ .arg(e->height)
+ .arg(e->border_width)
+ .arg(e->override_redirect);
+}
+
+TQString KXEventUtil::getXDestroyWindowEventInfo(XEvent *xevent) {
+ XDestroyWindowEvent *e = &xevent->xdestroywindow;
+ TQString s("window=%1");
+ return
+ s.arg(e->window);
+}
+TQString KXEventUtil::getXMapEventInfo(XEvent *xevent) {
+ XMapEvent *e = &xevent->xmap;
+ TQString s("window=%1 override_redirect=%2");
+ return
+ s.arg(e->window)
+ .arg(e->override_redirect);
+}
+TQString KXEventUtil::getXMappingEventInfo(XEvent *xevent) {
+ XMappingEvent *e = &xevent->xmapping;
+ TQString s("request=%1 first_keycode=%2 count=%3");
+ return
+ s.arg(e->request)
+ .arg(e->first_keycode)
+ .arg(e->count);
+}
+TQString KXEventUtil::getXReparentEventInfo(XEvent *xevent) {
+ XReparentEvent *e = &xevent->xreparent;
+ TQString s("window=%1 parent=%2 x=%3 y=%4");
+ return
+ s.arg(e->window)
+ .arg(e->parent)
+ .arg(e->x)
+ .arg(e->y);
+}
+TQString KXEventUtil::getXUnmapEventInfo(XEvent *xevent) {
+ XUnmapEvent *e = &xevent->xunmap;
+ TQString s("window=%1 from_configure=%2");
+ return
+ s.arg(e->window)
+ .arg(e->from_configure);
+}
+
+TQString KXEventUtil::getXConfigureEventInfo(XEvent *xevent) {
+ XConfigureEvent *e = &xevent->xconfigure;
+ TQString s("window=%1 x=%2 y=%2 width=%3 height=%4 border_width=%5 above=%6 override_redirect=%7");
+ return
+ s.arg(e->window)
+ .arg(e->x).arg(e->y)
+ .arg(e->width).arg(e->height)
+ .arg(e->border_width)
+ .arg(e->above)
+ .arg(e->override_redirect);
+}
+
+TQString KXEventUtil::getXConfigureRequestEventInfo(XEvent *xevent) {
+ XConfigureRequestEvent *e = &xevent->xconfigurerequest;
+ unsigned vm = e->value_mask;
+ TQStringList vml;
+ if (vm & CWX) vml.append("CWX");
+ if (vm & CWY) vml.append("CWY");
+ if (vm & CWWidth) vml.append("CWWidth");
+ if (vm & CWHeight) vml.append("CWHeight");
+ if (vm & CWBorderWidth) vml.append("CWBorderWidth");
+ if (vm & CWSibling) vml.append("CWSibling");
+ if (vm & CWStackMode) vml.append("CWStackMode");
+ TQString vms = vml.join("|");
+ TQString s("window=%1 x=%2 y=%2 width=%3 height=%4 border_width=%5 above=%6 detail=%7 value_mask=0x%8=%9");
+ return
+ s.arg(e->window)
+ .arg(e->x).arg(e->y)
+ .arg(e->width).arg(e->height)
+ .arg(e->border_width)
+ .arg(e->above)
+ .arg(e->detail)
+ .arg(e->value_mask, 0, 16)
+ .arg(vms);
+}
+TQString KXEventUtil::getX11EventInfo( XEvent* e )
+{
+ TQString anyInfo = getXAnyEventInfo(e);
+ TQString info = "";
+ TQString s;
+ switch( e->type )
+ {
+ case KeyPress:
+ s = "KeyPress";
+ info = getXKeyEventInfo(e);
+ break;
+ case KeyRelease:
+ s = "KeyRelease";
+ info = getXKeyEventInfo(e);
+ break;
+ case ButtonPress:
+ s = "ButtonPress";
+ info = getXButtonEventInfo(e);
+ break;
+ case ButtonRelease:
+ s = "ButtonRelease";
+ info = getXButtonEventInfo(e);
+ break;
+ case MotionNotify:
+ s = "MotionNotify";
+ info = getXMotionEventInfo(e);
+ break;
+ case EnterNotify:
+ s = "EnterNotify";
+ info = getXCrossingEventInfo(e);
+ break;
+ case LeaveNotify:
+ s = "LeaveNotify";
+ info = getXCrossingEventInfo(e);
+ break;
+ case FocusIn:
+ s = "FocusIn";
+ info = getXFocusChangeEventInfo(e);
+ break;
+ case FocusOut:
+ s = "FocusOut";
+ info = getXFocusChangeEventInfo(e);
+ break;
+ case KeymapNotify:
+ s = "KeymapNotify";
+ break;
+ case Expose:
+ s = "Expose";
+ info = getXExposeEventInfo(e);
+ break;
+ case GraphicsExpose:
+ s = "GraphicsExpose";
+ info = getXGraphicsExposeEventInfo(e);
+ break;
+ case NoExpose:
+ info = getXNoExposeEventInfo(e);
+ s = "NoExpose";
+ break;
+ case VisibilityNotify:
+ s = "VisibilityNotify";
+ break;
+ case CreateNotify:
+ s = "CreateNotify";
+ info = getXCreateWindowEventInfo(e);
+ break;
+ case DestroyNotify:
+ s = "DestroyNotify";
+ info = getXDestroyWindowEventInfo(e);
+ break;
+ case UnmapNotify:
+ s = "UnmapNotify";
+ info = getXUnmapEventInfo(e);
+ break;
+ case MapNotify:
+ s = "MapNotify";
+ info = getXMapEventInfo(e);
+ break;
+ case MapRequest:
+ s = "MapRequest";
+ break;
+ case ReparentNotify:
+ s = "ReparentNotify";
+ info = getXReparentEventInfo(e);
+ break;
+ case ConfigureNotify:
+ s = "ConfigureNotify";
+ info = getXConfigureEventInfo(e);
+ break;
+ case ConfigureRequest:
+ s = "ConfigureRequest";
+ info = getXConfigureRequestEventInfo(e);
+ break;
+ case GravityNotify:
+ s = "GravityNotify";
+ break;
+ case ResizeRequest:
+ s = "ResizeRequest";
+ break;
+ case CirculateNotify:
+ s = "CirculateNofify";
+ break;
+ case CirculateRequest:
+ s = "CirculateRequest";
+ break;
+ case PropertyNotify:
+ s = "PropertyNotify";
+ break;
+ case SelectionClear:
+ s = "SelectionClear";
+ break;
+ case SelectionRequest:
+ s = "SelectionRequest";
+ break;
+ case SelectionNotify:
+ s = "SelectionNotify";
+ break;
+ case ColormapNotify:
+ s = "ColormapNotify";
+ break;
+ case ClientMessage:
+ s = "ClientMessage";
+ break;
+ case MappingNotify:
+ s = "MappingNotify";
+ info = getXMappingEventInfo(e);
+ break;
+ case LASTEvent:
+ s = "LASTEvent";
+ break;
+
+ default:
+ s = "Undefined";
+ break;
+ }
+
+ return s + " " + anyInfo + " " + info;
+}
diff --git a/tdehtml/java/kxeventutil.h b/tdehtml/java/kxeventutil.h
new file mode 100644
index 000000000..6eb0bf14b
--- /dev/null
+++ b/tdehtml/java/kxeventutil.h
@@ -0,0 +1,51 @@
+// -*- c++ -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till Krech <till@snafu.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.
+ */
+#ifndef KXEVENTUTIL_H
+#define KXEVENTUTIL_H
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <tqstring.h>
+
+class KXEventUtil {
+ public:
+ static TQString getXEventName(XEvent *e);
+ static TQString getXAnyEventInfo(XEvent *xevent);
+ static TQString getXButtonEventInfo(XEvent *xevent);
+ static TQString getXKeyEventInfo(XEvent *xevent);
+ static TQString getXMotionEventInfo(XEvent *xevent);
+ static TQString getXCrossingEventInfo(XEvent *xevent);
+ static TQString getXFocusChangeEventInfo(XEvent *xevent);
+ static TQString getXExposeEventInfo(XEvent *xevent);
+ static TQString getXGraphicsExposeEventInfo(XEvent *xevent);
+ static TQString getXNoExposeEventInfo(XEvent *xevent);
+ static TQString getXCreateWindowEventInfo(XEvent *xevent);
+ static TQString getXDestroyWindowEventInfo(XEvent *xevent);
+ static TQString getXMapEventInfo(XEvent *xevent);
+ static TQString getXMappingEventInfo(XEvent *xevent);
+ static TQString getXReparentEventInfo(XEvent *xevent);
+ static TQString getXUnmapEventInfo(XEvent *xevent);
+ static TQString getXConfigureEventInfo(XEvent *xevent);
+ static TQString getXConfigureRequestEventInfo(XEvent *xevent);
+ static TQString getX11EventInfo( XEvent* e );
+};
+
+#endif
diff --git a/tdehtml/java/make-jar b/tdehtml/java/make-jar
new file mode 100755
index 000000000..a817ec1f3
--- /dev/null
+++ b/tdehtml/java/make-jar
@@ -0,0 +1,12 @@
+#!/bin/sh
+# very simple shell script to compile the java
+# sources and generate the jar file
+set -e # exit on error
+set -x # be verbose
+rm -rf java-build-dir/*
+mkdir -p java-build-dir/images
+cp images/*.gif images/*.png java-build-dir/images/
+pwd=`pwd`;
+javac -d java-build-dir -deprecation -target 1.2 `find org/kde netscape -name '*.java'` \
+ && cd java-build-dir && jar c0vf $pwd/kjava.jar images `find org/kde netscape -name *.class`
+
diff --git a/tdehtml/java/netscape/javascript/JSException.java b/tdehtml/java/netscape/javascript/JSException.java
new file mode 100644
index 000000000..222033e7a
--- /dev/null
+++ b/tdehtml/java/netscape/javascript/JSException.java
@@ -0,0 +1,20 @@
+package netscape.javascript;
+
+public class JSException extends Exception {
+ public JSException() {}
+ public JSException(String s) {
+ super(s);
+ }
+ public JSException(String s, String fn, int ln, String src, int ti) {
+ super(s);
+ filename = new String(fn);
+ linenumber = ln;
+ source = src;
+ tokenindex = ti;
+ }
+ private String filename = null;
+ private int linenumber;
+ private String source = null;
+ private int tokenindex;
+}
+
diff --git a/tdehtml/java/netscape/javascript/JSObject.java b/tdehtml/java/netscape/javascript/JSObject.java
new file mode 100644
index 000000000..f103d90c8
--- /dev/null
+++ b/tdehtml/java/netscape/javascript/JSObject.java
@@ -0,0 +1,21 @@
+package netscape.javascript;
+
+import java.applet.Applet;
+
+public abstract class JSObject extends Object {
+ protected JSObject()
+ {
+ }
+ public abstract Object call(String function, Object[] arguments) throws JSException;
+ public abstract Object eval(String script) throws JSException;
+ public abstract Object getMember(String name) throws JSException;
+ public abstract void setMember(String name, Object o) throws JSException;
+ public abstract void removeMember(String name) throws JSException;
+ public abstract Object getSlot(int index) throws JSException;
+ public abstract void setSlot(int index, Object o) throws JSException;
+ public static JSObject getWindow(Applet applet) throws JSException
+ {
+ return org.kde.javascript.JSObject.getWindow(applet, 0);
+ }
+}
+
diff --git a/tdehtml/java/netscape/plugin/Plugin.java b/tdehtml/java/netscape/plugin/Plugin.java
new file mode 100644
index 000000000..c7be0e542
--- /dev/null
+++ b/tdehtml/java/netscape/plugin/Plugin.java
@@ -0,0 +1,28 @@
+package netscape.plugin;
+
+import netscape.javascript.*;
+
+public class Plugin {
+
+ public Plugin() {
+ System.out.println("Plugin.Plugin");
+ }
+ public JSObject getWindow() throws JSException {
+ System.out.println("Plugin.getWindow");
+ return JSObject.getWindow(null);
+ }
+ public void destroy() {
+ System.out.println("Plugin.destroy");
+ }
+ public int getPeer() {
+ System.out.println("Plugin.getPeer");
+ return 0;
+ }
+ public void init() {
+ System.out.println("Plugin.init");
+ }
+ public boolean isActive() {
+ System.out.println("Plugin.isActive");
+ return true;
+ }
+}
diff --git a/tdehtml/java/netscape/security/ForbiddenTargetException.java b/tdehtml/java/netscape/security/ForbiddenTargetException.java
new file mode 100644
index 000000000..27879d05b
--- /dev/null
+++ b/tdehtml/java/netscape/security/ForbiddenTargetException.java
@@ -0,0 +1,10 @@
+package netscape.security;
+public class ForbiddenTargetException extends RuntimeException {
+ public ForbiddenTargetException()
+ {
+ }
+ public ForbiddenTargetException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/tdehtml/java/netscape/security/Principal.java b/tdehtml/java/netscape/security/Principal.java
new file mode 100644
index 000000000..1f93a8293
--- /dev/null
+++ b/tdehtml/java/netscape/security/Principal.java
@@ -0,0 +1,4 @@
+package netscape.security;
+
+public class Principal {
+} \ No newline at end of file
diff --git a/tdehtml/java/netscape/security/PrivilegeManager.java b/tdehtml/java/netscape/security/PrivilegeManager.java
new file mode 100644
index 000000000..c6555eaa0
--- /dev/null
+++ b/tdehtml/java/netscape/security/PrivilegeManager.java
@@ -0,0 +1,109 @@
+package netscape.security;
+
+public class PrivilegeManager extends Object {
+ public static final int PROPER_SUBSET = 1;
+ public static final int EQUAL = 2;
+ public static final int NO_SUBSET = 3;
+ public static final int SIGNED_APPLET_DBNAME = 4;
+ public static final int TEMP_FILENAME = 5;
+
+ private static PrivilegeManager thePrivilegeManager = null;
+
+ protected PrivilegeManager()
+ {
+ }
+ public void checkPrivilegeEnabled(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeEnabled(netscape.security.Target target, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public static void enablePrivilege(String privilegeString) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target, netscape.security.Principal principal) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void enablePrivilege(netscape.security.Target target, netscape.security.Principal principal, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void revertPrivilege(netscape.security.Target target)
+ {
+ }
+ public static void revertPrivilege(String privilegeString)
+ {
+ }
+ public void disablePrivilege(netscape.security.Target target)
+ {
+ }
+ public void disablePrivilege(String privilegeString)
+ {
+ }
+ public static void checkPrivilegeGranted(String privilegeString) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public void checkPrivilegeGranted(netscape.security.Target target, netscape.security.Principal principal, Object o) throws netscape.security.ForbiddenTargetException
+ {
+ }
+ public boolean isCalledByPrincipal(netscape.security.Principal principal, int dontknow)
+ {
+ return false;
+ }
+ public boolean isCalledByPrincipal(netscape.security.Principal principal)
+ {
+ return false;
+ }
+ public static netscape.security.Principal getSystemPrincipal()
+ {
+ return null;
+ }
+ public static netscape.security.PrivilegeManager getPrivilegeManager()
+ {
+ if (thePrivilegeManager == null) {
+ thePrivilegeManager = new PrivilegeManager();
+ }
+ return thePrivilegeManager;
+ }
+ public boolean hasPrincipal(Class cl, netscape.security.Principal principal)
+ {
+ return true;
+ }
+ public int comparePrincipalArray(netscape.security.Principal[] a, netscape.security.Principal[] b)
+ {
+ return 1;
+ }
+ public boolean checkMatchPrincipal(Class cl, int dontknow)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipal(netscape.security.Principal principal, int dontknow)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipal(Class cl)
+ {
+ return true;
+ }
+ public boolean checkMatchPrincipalAlways()
+ {
+ return true;
+ }
+ public netscape.security.Principal[] getClassPrincipalsFromStack(int n)
+ {
+ return null;
+ }
+ /*
+ public netscape.security.PrivilegeTable getPrivilegeTableFromStack();
+ {
+ }
+ */
+}
diff --git a/tdehtml/java/netscape/security/Target.java b/tdehtml/java/netscape/security/Target.java
new file mode 100644
index 000000000..8b50040b5
--- /dev/null
+++ b/tdehtml/java/netscape/security/Target.java
@@ -0,0 +1,4 @@
+package netscape.security;
+
+public class Target {
+} \ No newline at end of file
diff --git a/tdehtml/java/org/kde/javascript/JSObject.java b/tdehtml/java/org/kde/javascript/JSObject.java
new file mode 100644
index 000000000..11e7f9f99
--- /dev/null
+++ b/tdehtml/java/org/kde/javascript/JSObject.java
@@ -0,0 +1,183 @@
+package org.kde.javascript;
+
+import java.applet.Applet;
+import org.kde.kjas.server.KJASAppletContext;
+import org.kde.kjas.server.Main;
+
+public class JSObject extends netscape.javascript.JSObject {
+ public String returnvalue = null;
+ public Thread thread;
+
+ private String jsobject;
+ private int id;
+ private Applet applet;
+ private String appletID = null;
+
+ /* JavaScript code:
+ * __lc=[[JS objects],call func(index,script,appletname,isglobal)]
+ */
+ private final static String decls = "if(!window.__lc) window.__lc=[[window],function(i,s,a,g){var v;var len=window.__lc[0].length;if(i>=len)v='E unknown object';else{var r;try{r=eval((g?'':'window.__lc[0][i]')+s);}catch(e){v='E '+e;r='E ';}finally{var t=typeof r;if(t=='undefined')v='V ';else if(t=='number')v='N '+r;else if(t=='string'){if(r!='E ')v='S '+r;}else{window.__lc[0][len]=r;v=''+len+' '+(r==window.__lc?'[array]':r);}}}a.__lc_ret=v},0]";
+
+ public JSObject(Applet a, String name, int _id) {
+ Main.info("JSObject.ctor: " + name);
+ jsobject = new String(name);
+ applet = a;
+ id = _id;
+ KJASAppletContext kc = (KJASAppletContext)applet.getAppletContext();
+ appletID = kc.getAppletID(a);
+ if (id == 0) {
+ kc.evaluateJavaScript(decls, appletID, null);
+ }
+ }
+
+ int getId() {
+ return id;
+ }
+
+ private String escapeString(String string) {
+ StringBuffer sb = new StringBuffer();
+ int idx = 0;
+ boolean cr = false;
+ char [] chars = string.toCharArray();
+ while (idx < chars.length) {
+ if (cr && chars[idx] != '\n') {
+ cr = false;
+ sb.append("\\n");
+ }
+ switch (chars[idx]) {
+ case '\\':
+ sb.append("\\\\");
+ break;
+ case '"':
+ sb.append("\\\"");
+ break;
+ case '\n':
+ cr = false;
+ sb.append("\\n");
+ break;
+ case '\r':
+ cr = true;
+ break;
+ default:
+ sb.append(chars[idx]);
+ }
+ idx++;
+ }
+ if (cr)
+ sb.append("\\n");
+ return sb.toString();
+ }
+
+ private Object evaluate(String script, boolean global) throws netscape.javascript.JSException {
+ Main.info("evaluate (\"" + script + "\")");
+
+ KJASAppletContext kc = (KJASAppletContext) applet.getAppletContext();
+ //String appletname = kc.getAppletName(appletID);
+ thread = Thread.currentThread();
+
+ if (!kc.evaluateJavaScript("window.__lc[1](" + id + ",\"" + escapeString(script) + "\",this" + (global ? ",true)" : ")"), appletID, this)) {
+ Main.debug("evaluate on not active applet");
+ return null;
+ }
+ boolean timedout = true;
+ try {
+ Thread.sleep(30000);
+ } catch (InterruptedException ex) {
+ timedout = false;
+ }
+ thread = null;
+ if (timedout || returnvalue == null)
+ return null;
+
+ /* lets see what we've got */
+ String retval = returnvalue;
+ int pos = retval.indexOf(' ');
+ String type = retval.substring(0, pos);
+ if (type.equals("V")) // Void
+ return null;
+ String value = retval.substring(pos+1);
+ if (type.equals("E")) // Error
+ throw new netscape.javascript.JSException("Script error: " + value);
+ Main.info("value=" + value + " (type=" + type + ")");
+ if (type.equals("N")) // Number
+ return new Double(value);
+ if (type.equals("S")) // String
+ return value;
+
+ /* Is it an applet? */
+ if (value.startsWith("[object APPLET ref=")) {
+ int p1 = value.indexOf('=');
+ int p2 = value.indexOf(']', p1+1);
+ int applethashcode = Integer.parseInt(value.substring(p1+1, p2));
+ java.util.Enumeration e = kc.getApplets();
+ while (e.hasMoreElements()) {
+ Applet app = (Applet) e.nextElement();
+ if (app.hashCode() == applethashcode)
+ return app;
+ }
+ return null;
+ }
+ /* Is it a Java object then? */
+ if (value.startsWith("[object ") && value.indexOf("ref=") > 0) {
+ int p1 = value.indexOf("ref=");
+ int p2 = value.indexOf(']', p1+4);
+ int objecthashcode = Integer.parseInt(value.substring(p1+4, p2));
+ return kc.getJSReferencedObject(applet, objecthashcode);
+ }
+ /* Ok, make it a JSObject */
+ return new JSObject(applet, value, Integer.parseInt(type));
+ }
+ private String convertValueJ2JS(Object o) {
+ if (o == null)
+ return new String("null");
+ if (o instanceof java.lang.Number || o instanceof java.lang.Boolean)
+ return o.toString();
+ if (o instanceof netscape.javascript.JSObject)
+ return new String("window.__lc[0][" + ((JSObject)o).getId() + "]");
+ return new String("\"" + escapeString(o.toString()) + "\"");
+ }
+ public Object call(String func, Object [] args) throws netscape.javascript.JSException {
+ Main.info("JSObject.call: " + jsobject + "." + func);
+ String script = new String("." + func + "(");
+ for (int i = 0; args != null && i < args.length; i++)
+ script += (i > 0 ? "," : "") + convertValueJ2JS(args[i]);
+ script += ")";
+ return evaluate(script, false);
+ }
+ public Object eval(String s) throws netscape.javascript.JSException {
+ return evaluate(s, true);
+ }
+ public boolean equals(Object obj) {
+ Main.info("JSObject.equals");
+ return super.equals(obj);
+ }
+ public Object getMember(String name) throws netscape.javascript.JSException {
+ Main.info("JSObject.getMember: " + jsobject + "." + name);
+ return evaluate("." + name, false);
+ }
+ public void setMember(String name, java.lang.Object o) throws netscape.javascript.JSException {
+ Main.info("JSObject.setMember: " + jsobject + "." + name);
+ evaluate("." + name + "=" + convertValueJ2JS(o), false);
+ }
+ public void removeMember(String name) throws netscape.javascript.JSException {
+ Main.info("JSObject.removeMember: " + jsobject + "." + name);
+ evaluate("." + name + "=null", false);
+ }
+ /* get array element; JS: this[index] */
+ public Object getSlot(int index)throws netscape.javascript.JSException {
+ Main.info("JSObject.getSlot: " + jsobject + "[" + index + "]");
+ return evaluate("[" + index + "]", false);
+ }
+ public void setSlot(int index, Object o) throws netscape.javascript.JSException {
+ Main.info("JSObject.setSlot: " + jsobject + "[" + index + "]");
+ evaluate("[" + index + "]=" + convertValueJ2JS(o), false);
+ }
+ public String toString(){
+ Main.info("JSObject.toString: " + jsobject);
+ return new String(jsobject);
+ }
+ public static JSObject getWindow(Applet a, int dummy) {
+ Main.info("JSObject.getWindow");
+ return new JSObject(a, "[WINDOW]", 0);
+ }
+}
diff --git a/tdehtml/java/org/kde/kjas/server/Console.java b/tdehtml/java/org/kde/kjas/server/Console.java
new file mode 100644
index 000000000..d089f3cd8
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/Console.java
@@ -0,0 +1,20 @@
+/*
+ * Appendable.java
+ *
+ * Created on 16. Mai 2002, 23:23
+ */
+
+package org.kde.kjas.server;
+
+/**
+ *
+ * @author till
+ */
+public interface Console {
+
+ public void clear();
+ public void append(String text);
+
+ public void setVisible(boolean visible);
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASAppletClassLoader.java b/tdehtml/java/org/kde/kjas/server/KJASAppletClassLoader.java
new file mode 100644
index 000000000..c6defa848
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASAppletClassLoader.java
@@ -0,0 +1,360 @@
+package org.kde.kjas.server;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+import java.security.*;
+/**
+ * ClassLoader used to download and instantiate Applets.
+ * <P>
+ * NOTE: The class loader extends Java 1.2 specific class.
+ */
+public final class KJASAppletClassLoader
+ extends URLClassLoader
+{
+ private static Hashtable loaders = new Hashtable();
+
+ public static synchronized void removeLoaders()
+ {
+ loaders.clear();
+ }
+
+ public static synchronized KJASAppletClassLoader getLoader( String docBase, String codeBase, String archives )
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ URL docBaseURL;
+ KJASAppletClassLoader loader = null;
+ try
+ {
+ docBaseURL = new URL( docBase );
+
+ URL codeBaseURL = getCodeBaseURL( docBaseURL, codeBase );
+ String key = codeBaseURL.toString();
+ if (archives != null)
+ key += archives;
+
+ Main.debug( "CL: getLoader: key = " + key );
+
+ loader = (KJASAppletClassLoader) loaders.get( key );
+ if( loader == null )
+ {
+ URL [] urlList = {};
+ loader = new KJASAppletClassLoader( urlList, docBaseURL, codeBaseURL);
+ loaders.put( key, loader );
+ }
+ else
+ {
+ Main.debug( "CL: reusing classloader" );
+ }
+ } catch( MalformedURLException e ) { Main.kjas_err( "bad DocBase URL", e ); }
+ return loader;
+ }
+
+ public static URL getCodeBaseURL( URL docBaseURL, String codeBase )
+ {
+ URL codeBaseURL = null;
+ try
+ {
+ //first determine what the real codeBase is: 3 cases
+ //#1. codeBase is absolute URL- use that
+ //#2. codeBase is relative to docBase, create url from those
+ //#3. last resort, use docBase as the codeBase
+ if(codeBase != null)
+ {
+ //we need to do this since codeBase should be a directory
+ if( !codeBase.endsWith("/") )
+ codeBase = codeBase + "/";
+
+ try
+ {
+ codeBaseURL = new URL( codeBase );
+ } catch( MalformedURLException mue )
+ {
+ try
+ {
+ codeBaseURL = new URL( docBaseURL, codeBase );
+ } catch( MalformedURLException mue2 ) {}
+ }
+ }
+
+ if(codeBaseURL == null)
+ {
+ //fall back to docBase but fix it up...
+ String file = docBaseURL.getFile();
+ if( file == null || (file.length() == 0) )
+ codeBaseURL = docBaseURL;
+ else if( file.endsWith( "/" ) )
+ codeBaseURL = docBaseURL;
+ else
+ {
+ //delete up to the ending '/'
+ String urlString = docBaseURL.toString();
+ int dot_index = urlString.lastIndexOf( '/' );
+ String newfile = urlString.substring( 0, dot_index+1 );
+ codeBaseURL = new URL( newfile );
+ }
+ }
+ }catch( Exception e ) { Main.kjas_err( "CL: exception ", e ); }
+ return codeBaseURL;
+ }
+
+ public static KJASAppletClassLoader getLoader( String key )
+ {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ if( loaders.containsKey( key ) )
+ return (KJASAppletClassLoader) loaders.get( key );
+
+ return null;
+ }
+
+ /*********************************************************************************
+ ****************** KJASAppletClassLoader Implementation *************************
+ **********************************************************************************/
+ private URL docBaseURL;
+ private URL codeBaseURL;
+ private Vector archives;
+ private String dbgID;
+ private static int globalId = 0;
+ private int myId = 0;
+ private Vector statusListeners = new Vector();
+ private AccessControlContext acc;
+ // a mapping JS referenced Java objects
+ private Hashtable jsReferencedObjects = new Hashtable();
+ final static RuntimePermission kjas_access = new RuntimePermission("accessClassInPackage.org.kde.kjas.server");
+
+ public KJASAppletClassLoader( URL[] urlList, URL _docBaseURL, URL _codeBaseURL)
+ {
+ super(urlList);
+ acc = AccessController.getContext();
+ synchronized(KJASAppletClassLoader.class) {
+ myId = ++globalId;
+ }
+ docBaseURL = _docBaseURL;
+ codeBaseURL = _codeBaseURL;
+ archives = new Vector();
+
+ dbgID = "CL-" + myId + "(" + codeBaseURL.toString() + "): ";
+ }
+
+ protected void addURL(URL url) {
+ Main.debug(this + " add URL: " + url);
+ super.addURL(url);
+ }
+
+ public void addStatusListener(StatusListener lsnr) {
+ statusListeners.add(lsnr);
+ }
+ public void removeStatusListener(StatusListener lsnr) {
+ statusListeners.remove(lsnr);
+ }
+ public void showStatus(String msg) {
+ Enumeration en = statusListeners.elements();
+ while (en.hasMoreElements()) {
+ StatusListener lsnr = (StatusListener)en.nextElement();
+ lsnr.showStatus(msg);
+ }
+ }
+
+ public void paramsDone() {
+ // simply builds up the search path
+ // put the archives first because they are
+ // cached.
+ for( int i = 0; i < archives.size(); ++i ) {
+ String jar = (String)archives.elementAt( i );
+ try {
+ URL jarURL = new URL(codeBaseURL, jar);
+ addURL(jarURL);
+ Main.debug("added archive URL \"" + jarURL + "\" to KJASAppletClassLoader");
+ } catch (MalformedURLException e) {
+ Main.kjas_err("Could not construct URL for jar file: " + codeBaseURL + " + " + jar, e);
+ }
+ }
+ // finally add code base url and docbase url
+ addURL(codeBaseURL);
+
+ // the docBaseURL has to be fixed.
+ // strip file part from end otherwise this
+ // will be interpreted as an archive
+ // (should this perhaps be done generally ??)
+ String dbs = docBaseURL.toString();
+ int idx = dbs.lastIndexOf("/");
+ if (idx > 0) {
+ dbs = dbs.substring(0, idx+1);
+ }
+ URL docDirURL = null;
+ try {
+ docDirURL = new URL(dbs);
+ } catch (MalformedURLException e) {
+ Main.debug("Could not make a new URL from docBaseURL=" + docBaseURL);
+ }
+ if (docDirURL != null && !codeBaseURL.equals(docDirURL)) {
+ addURL(docDirURL);
+ }
+ }
+
+ void addArchiveName( String jarname )
+ {
+ if( !archives.contains( jarname ) )
+ {
+ archives.add( jarname );
+ }
+ }
+
+
+ public URL getDocBase()
+ {
+ return docBaseURL;
+ }
+
+ public URL getCodeBase()
+ {
+ return codeBaseURL;
+ }
+
+ Hashtable getJSReferencedObjects() {
+ return jsReferencedObjects;
+ }
+ /***************************************************************************
+ **** Class Loading Methods
+ **************************************************************************/
+ public synchronized Class findClass( String name ) throws ClassNotFoundException
+ {
+ Class rval = null;
+ //check the loaded classes
+ rval = findLoadedClass( name );
+ if( rval == null ) {
+ try {
+ rval = super.findClass(name);
+ } catch (ClassFormatError cfe) {
+ Main.debug(name + ": Catched " + cfe + ". Trying to repair...");
+ rval = loadFixedClass( name );
+ } catch (Exception ex) {
+ Main.debug("findClass " + name + " " + ex.getMessage());
+ }
+ }
+ if (rval == null) {
+ throw new ClassNotFoundException("Class: " + name);
+ }
+ return rval;
+ }
+ public Class loadClass(String name) throws ClassNotFoundException {
+ if (name.startsWith("org.kde.kjas.server")) {
+ SecurityManager sec = System.getSecurityManager();
+ if (sec != null)
+ sec.checkPermission(kjas_access);
+ }
+ return super.loadClass(name);
+ }
+ private Hashtable loadedClasses = new Hashtable();
+
+ private synchronized final Class loadFixedClass(String name) throws ClassNotFoundException {
+ final String fileName = name.replace('.', '/') + ".class";
+ try {
+ // try to get the class as resource
+ final URL u = getResource(fileName);
+ Main.debug(dbgID + name + ": got URL: " + u);
+ if (u == null) {
+ throw new ClassNotFoundException(fileName + ": invalid resource URL.");
+ }
+ java.security.cert.Certificate[] certs = {}; // FIXME
+ CodeSource cs = new CodeSource(u, certs);
+ InputStream instream = (InputStream)AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ try {
+ return u.openStream();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ return null;
+ }
+ }
+ }, acc
+ );
+ if (instream == null) {
+ throw new ClassNotFoundException(name + ": could not be loaded.");
+ }
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ int cnt;
+ int total = 0;
+ int bufSize = 1024;
+ byte [] buffer = new byte[bufSize];
+ while ((cnt = instream.read(buffer, 0, bufSize)) > 0) {
+ total += cnt;
+ byteStream.write(buffer, 0, cnt);
+ }
+ Main.debug(dbgID + name + ": " + total + " bytes");
+
+ Class cl = fixAndDefineClass(name, byteStream.toByteArray(), 0, total, cs);
+ if (cl != null) {
+ loadedClasses.put(name, cl);
+ }
+ return cl;
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new ClassNotFoundException("triggered by " + e);
+ }
+ }
+
+ public URL findResource( String name)
+ {
+ Main.debug( dbgID + "findResource, name = " + name );
+ String displayName = name;
+ try {
+ URL u = new URL(name);
+ String filename = u.getFile();
+ if (filename != null && filename.length() > 0) {
+ displayName = filename;
+ }
+ } catch (Throwable e) {
+ }
+ showStatus("Loading: " + displayName);
+ URL url = super.findResource( name );
+ Main.debug("findResource for " + name + " returns " + url);
+ return url;
+ }
+
+ protected PermissionCollection getPermissions(CodeSource cs) {
+ Main.debug(dbgID + " getPermissions(" + cs + ")");
+ PermissionCollection permissions = super.getPermissions(cs);
+ Enumeration perms_enum = permissions.elements();
+ while (perms_enum.hasMoreElements()) {
+ Main.debug(this + " Permission: " + perms_enum.nextElement());
+ }
+ return permissions;
+ }
+
+
+ /**
+ * define the class <b>name</b>. If <b>name</b> is broken, try to fix it.
+ */
+ private final Class fixAndDefineClass(
+ String name,
+ byte[] b,
+ int off,
+ int len,
+ CodeSource cs) throws ClassFormatError
+ {
+ KJASBrokenClassFixer fixer = new KJASBrokenClassFixer();
+ if (fixer.process(b, off, len)) {
+ Main.debug(name + " fixed");
+ } else {
+ Main.info(name + " could not be fixed");
+ }
+ return defineClass(name,
+ fixer.getProcessedData(),
+ fixer.getProcessedDataOffset(),
+ fixer.getProcessedDataLength(),
+ cs);
+ }
+
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASAppletContext.java b/tdehtml/java/org/kde/kjas/server/KJASAppletContext.java
new file mode 100644
index 000000000..f868b7b64
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASAppletContext.java
@@ -0,0 +1,473 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.util.*;
+import java.net.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import org.kde.javascript.JSObject;
+
+final class KJASAuthenticator extends Authenticator {
+ private Hashtable authentication;
+
+ KJASAuthenticator() {
+ authentication = new Hashtable();
+ setDefault(this);
+ }
+ final void addURL(URL url, String user, String password, String authname) {
+ String key = new String(url.getProtocol() + ":" + url.getHost() + ":" +
+ url.getPort() + "_" + authname);
+ String [] auths = { user, password };
+ authentication.put(key, auths);
+ }
+ final protected PasswordAuthentication getPasswordAuthentication() {
+ URL url;
+ String key = new String(getRequestingProtocol() + ":" + getRequestingHost() + ":" + getRequestingPort() + "_" + getRequestingPrompt());
+ String [] auths = (String []) authentication.get(key);
+ if (auths != null) {
+ char [] pw = new char[auths[1].length()];
+ auths[1].getChars(0, auths[1].length(), pw, 0);
+ return new PasswordAuthentication(auths[0], pw);
+ }
+ return null;
+ }
+}
+
+/**
+ * The context in which applets live.
+ */
+public class KJASAppletContext implements AppletContext
+{
+ private Hashtable stubs;
+ private Hashtable images;
+ private Vector pendingImages;
+ private Hashtable streams;
+ private Stack jsobjects;
+
+ private String myID;
+ private KJASAppletClassLoader loader;
+ private boolean active;
+ private final static KJASAuthenticator authenticator = new KJASAuthenticator();
+
+ /**
+ * Create a KJASAppletContext
+ */
+ public KJASAppletContext( String _contextID )
+ {
+ stubs = new Hashtable();
+ images = new Hashtable();
+ pendingImages = new Vector();
+ streams = new Hashtable();
+ jsobjects = new Stack();
+ myID = _contextID;
+ active = true;
+ }
+
+ public String getID()
+ {
+ return myID;
+ }
+
+ public String getAppletID(Applet applet)
+ {
+ Enumeration e = stubs.keys();
+ while ( e.hasMoreElements() )
+ {
+ String appletID = (String) e.nextElement();
+ KJASAppletStub stub = (KJASAppletStub) stubs.get(appletID);
+ if (stub.getApplet() == applet)
+ return appletID;
+ }
+ return null;
+ }
+
+ public Applet getAppletById(String appletId) {
+ return ((KJASAppletStub) stubs.get( appletId )).getApplet();
+ }
+
+ public String getAppletName(String appletID) {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get(appletID);
+ if (stub == null)
+ return null;
+ return stub.getAppletName();
+ }
+ public void createApplet( String appletID, String name,
+ String className, String docBase,
+ String username, String password, String authname,
+ String codeBase, String archives,
+ String width, String height,
+ String windowName, Hashtable params )
+ {
+ //do kludges to support mess with parameter table and
+ //the applet variables
+ String key = new String( "ARCHIVE" );
+ if (params.containsKey(key)) {
+ String param_archive = (String)params.get(key);
+ if (archives == null) {
+ // There is no 'archive' attribute
+ // but a 'archive' param. fix archive list
+ // from param value
+ archives = param_archive;
+ } else {
+ // there is already an archive attribute.
+ // just add the value of the param to the list.
+ // But ignore bill$ personal archive format called
+ // .cab because java doesn't understand it.
+ if (!param_archive.toLowerCase().endsWith(".cab")) {
+ archives = param_archive + "," + archives;
+ }
+ }
+ } else if (archives != null) {
+ // add param if it is not present
+ params.put( key, archives);
+ }
+
+ if( codeBase == null )
+ {
+ key = new String( "CODEBASE" );
+ if( params.containsKey( key ) )
+ codeBase = (String) params.get( key );
+ }
+
+ if (username != null && !username.equals("")) {
+ try {
+ URL url = new URL(docBase);
+ int port = url.getPort();
+ if (port < 0)
+ port = url.getDefaultPort();
+ authenticator.addURL(new URL(url.getProtocol(), url.getHost(), port, ""), username, password, authname);
+ } catch (MalformedURLException muex) {
+ }
+ }
+ try
+ {
+ String sorted_archives = "";
+ TreeSet archive_set = new TreeSet();
+ if( archives != null )
+ {
+ StringTokenizer parser = new StringTokenizer( archives, ",", false );
+ while( parser.hasMoreTokens() )
+ archive_set.add ( parser.nextToken().trim() );
+ }
+ Iterator it = archive_set.iterator();
+ while (it.hasNext())
+ sorted_archives += (String) it.next();
+ KJASAppletClassLoader loader =
+ KJASAppletClassLoader.getLoader( docBase, codeBase, sorted_archives );
+ it = archive_set.iterator();
+ while (it.hasNext())
+ loader.addArchiveName( (String) it.next() );
+ loader.paramsDone();
+
+ KJASAppletStub stub = new KJASAppletStub
+ (
+ this, appletID, loader.getCodeBase(),
+ loader.getDocBase(), name, className,
+ new Dimension( Integer.parseInt(width), Integer.parseInt(height) ),
+ params, windowName, loader
+ );
+ stubs.put( appletID, stub );
+
+ stub.createApplet();
+ }
+ catch ( Exception e )
+ {
+ Main.kjas_err( "Something bad happened in createApplet: " + e, e );
+ }
+ }
+
+ public void initApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not init and show applet: " + appletID );
+ }
+ else
+ {
+ stub.initApplet();
+ }
+ }
+
+ public void destroyApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+
+ if( stub == null )
+ {
+ Main.debug( "could not destroy applet: " + appletID );
+ }
+ else
+ {
+ //Main.debug( "stopping applet: " + appletID );
+ stubs.remove( appletID );
+
+ stub.destroyApplet();
+ }
+ }
+
+ public void startApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not start applet: " + appletID );
+ }
+ else
+ {
+ stub.startApplet();
+ }
+ }
+
+ public void stopApplet( String appletID )
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( stub == null )
+ {
+ Main.debug( "could not stop applet: " + appletID );
+ }
+ else
+ {
+ stub.stopApplet();
+ }
+ }
+
+ public void destroy()
+ {
+ Enumeration e = stubs.elements();
+ while ( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+ stub.destroyApplet();
+ stub.loader.getJSReferencedObjects().clear();
+ }
+
+ stubs.clear();
+ active = false;
+ }
+
+ /***************************************************************************
+ **** AppletContext interface
+ ***************************************************************************/
+ public Applet getApplet( String appletName )
+ {
+ if( active )
+ {
+ Enumeration e = stubs.elements();
+ while( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+
+ if( stub.getAppletName().equals( appletName ) )
+ return stub.getApplet();
+ }
+ }
+
+ return null;
+ }
+
+ public Enumeration getApplets()
+ {
+ if( active )
+ {
+ Vector v = new Vector();
+ Enumeration e = stubs.elements();
+ while( e.hasMoreElements() )
+ {
+ KJASAppletStub stub = (KJASAppletStub) e.nextElement();
+ v.add( stub.getApplet() );
+ }
+
+ return v.elements();
+ }
+
+ return null;
+ }
+
+ public AudioClip getAudioClip( URL url )
+ {
+ Main.debug( "getAudioClip, url = " + url );
+ //AudioClip clip = java.applet.Applet.newAudioClip(url);
+ AudioClip clip = new KJASAudioClip(url);
+ Main.debug( "got AudioClip " + clip);
+ return clip;
+ // return new KJASSoundPlayer( myID, url );
+ }
+
+ public void addImage( String url, byte[] data )
+ {
+ Main.debug( "addImage for url = " + url );
+ images.put( url, data );
+ if (Main.cacheImages) {
+ pendingImages.remove(url);
+ }
+ }
+
+ public Image getImage( URL url )
+ {
+ if( active && url != null )
+ {
+ // directly load images using JVM
+ if (true) {
+ // Main.info("Getting image using ClassLoader:" + url);
+ if (loader != null) {
+ url = loader.findResource(url.toString());
+ //Main.debug("Resulting URL:" + url);
+ }
+ Toolkit kit = Toolkit.getDefaultToolkit();
+ Image img = kit.createImage(url);
+ return img;
+ }
+
+ //check with the Web Server
+ String str_url = url.toString();
+ Main.debug( "getImage, url = " + str_url );
+ if (Main.cacheImages && images.containsKey(str_url)) {
+ Main.debug("Cached: url=" + str_url);
+ }
+ else
+ {
+ if (Main.cacheImages) {
+ if (!pendingImages.contains(str_url)) {
+ Main.protocol.sendGetURLDataCmd( myID, str_url );
+ pendingImages.add(str_url);
+ }
+ } else {
+ Main.protocol.sendGetURLDataCmd( myID, str_url );
+ }
+ while( !images.containsKey( str_url ) && active )
+ {
+ try { Thread.sleep( 200 ); }
+ catch( InterruptedException e ){}
+ }
+ }
+ if( images.containsKey( str_url ) )
+ {
+ byte[] data = (byte[]) images.get( str_url );
+ if( data.length > 0 )
+ {
+ Toolkit kit = Toolkit.getDefaultToolkit();
+ return kit.createImage( data );
+ } else return null;
+ }
+ }
+
+ return null;
+ }
+
+ public void showDocument( URL url )
+ {
+ //Main.debug( "showDocument, url = " + url );
+
+ if( active && (url != null) )
+ {
+ Main.protocol.sendShowDocumentCmd( myID, url.toString() );
+ }
+ }
+
+ public void showDocument( URL url, String targetFrame )
+ {
+ //Main.debug( "showDocument, url = " + url + " targetFrame = " + targetFrame );
+
+ if( active && (url != null) && (targetFrame != null) )
+ {
+ Main.protocol.sendShowDocumentCmd( myID, url.toString(), targetFrame );
+ }
+ }
+
+ public void showStatus( String message )
+ {
+ if( active && (message != null) )
+ {
+ Main.protocol.sendShowStatusCmd( myID, message );
+ }
+ }
+ public boolean evaluateJavaScript(String script, String appletID, JSObject jso) {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if( active && stub != null && stub.isLoaded ()) {
+ if( jso != null ) {
+ synchronized (jsobjects) {
+ jsobjects.push(jso);
+ }
+ }
+ int [] types = { KJASAppletStub.JString };
+ String [] arglist = { script };
+ Main.protocol.sendJavaScriptEventCmd(myID, appletID, 0, "eval", types, arglist);
+ return true;
+ }
+ Main.debug( "evaluateJavaScript failure, context active:" + active + " stub:" + stub);
+ return false;
+ }
+
+ public boolean getMember(String appletID, int callid, int objid, String name)
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.getMember(callid, objid, name);
+ }
+
+ public boolean putMember(String appletID, int callid, int objid, String name, String value)
+ {
+ if (name.equals("__lc_ret")) {
+ // special case; return value of JS script evaluation
+ Main.debug("putValue: applet " + name + "=" + value);
+ JSObject jso = null;
+ synchronized (jsobjects) {
+ if (!jsobjects.empty())
+ jso = (JSObject) jsobjects.pop();
+ }
+ if (jso == null)
+ return false;
+ jso.returnvalue = value;
+ try {
+ jso.thread.interrupt();
+ } catch (SecurityException ex) {}
+ Main.protocol.sendPutMember( myID, callid, true );
+ }
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.putMember(callid, objid, name, value);
+ }
+
+ public Object getJSReferencedObject(Applet applet, int objid)
+ {
+ return ((KJASAppletClassLoader)(applet.getClass().getClassLoader())).getJSReferencedObjects().get(new Integer(objid));
+ }
+ boolean callMember(String appletID, int cid, int oid, String n, java.util.List args)
+ {
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null || !stub.isLoaded())
+ return false;
+ return stub.callMember( cid, oid, n, args);
+ }
+ public void derefObject(String appletID, int objid) {
+ if (objid == 0)
+ return; // that's an applet
+ KJASAppletStub stub = (KJASAppletStub) stubs.get( appletID );
+ if (stub == null)
+ return;
+ Hashtable jsRefs = stub.loader.getJSReferencedObjects();
+ if (jsRefs.remove(new Integer(objid)) == null)
+ Main.debug("couldn't remove referenced object");
+ }
+
+ public void setStream(String key, InputStream stream) throws IOException {
+ Main.debug("setStream, key = " + key);
+ streams.put(key, stream);
+ }
+ public InputStream getStream(String key){
+ Main.debug("getStream, key = " + key);
+ return (InputStream) streams.get(key);
+ }
+ public Iterator getStreamKeys() {
+ Main.debug("getStreamKeys");
+ return streams.keySet().iterator();
+ }
+
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASAppletPanel.java b/tdehtml/java/org/kde/kjas/server/KJASAppletPanel.java
new file mode 100644
index 000000000..d7acbdaf9
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASAppletPanel.java
@@ -0,0 +1,113 @@
+package org.kde.kjas.server;
+
+import java.applet.Applet;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.LayoutManager;
+import java.awt.Panel;
+import java.net.URL;
+
+/**
+ * @author till
+ *
+ * A panel which embeds the applet and shows some
+ * information during class loading.
+ */
+public class KJASAppletPanel extends javax.swing.JPanel implements StatusListener {
+ private final static int LOADING = 1;
+ private final static int RUNNING = 2;
+ private final static int FAILED = 3;
+
+ private Image load_img = null;
+ private Image fail_img = null;
+ private int status = LOADING;
+ private Font font;
+ private String msg = "Loading Applet...";
+
+ /**
+ * Constructor for KJASAppletPanel.
+ */
+ public KJASAppletPanel() {
+ super(new BorderLayout());
+ font = new Font("SansSerif", Font.PLAIN, 10);
+ URL url =
+ getClass().getClassLoader().getResource("images/animbean.gif");
+ load_img = getToolkit().createImage(url);
+ //setBackground(Color.white);
+ }
+
+ void setApplet(Applet applet) {
+ add("Center", applet);
+ validate();
+ }
+
+ public void showStatus(String msg) {
+ this.msg = msg;
+ if (status != RUNNING)
+ repaint();
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (status == RUNNING)
+ return;
+ Image img = (status == LOADING ? load_img : fail_img);
+ int x = getWidth() / 2;
+ int y = getHeight() / 2;
+ if (img != null) {
+ //synchronized (img) {
+ int w = img.getWidth(this);
+ int h = img.getHeight(this);
+ int imgx = x - w / 2;
+ int imgy = y - h / 2;
+ //g.setClip(imgx, imgy, w, h);
+ g.drawImage(img, imgx, imgy, this);
+ y += img.getHeight(this) / 2;
+ //}
+ }
+ if (msg != null) {
+ //synchronized(msg) {
+ g.setFont(font);
+ FontMetrics m = g.getFontMetrics();
+ int h = m.getHeight();
+ int w = m.stringWidth(msg);
+ int msgx = x - w / 2;
+ int msgy = y + h;
+ //g.setClip(0, y, getWidth(), h);
+ g.drawString(msg, msgx, msgy);
+ //}
+ }
+ }
+ void showFailed() {
+ URL url =
+ getClass().getClassLoader().getResource("images/brokenbean.gif");
+ fail_img = getToolkit().createImage(url);
+ status = FAILED;
+ msg = "Applet Failed.";
+ repaint();
+ }
+
+ void showFailed(String message) {
+ showFailed();
+ showStatus(message);
+ }
+
+ public void stopAnimation() {
+ status = RUNNING;
+ }
+
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
+ {
+ if (img != null && img == load_img && status != LOADING) {
+ img.flush();
+ load_img = null;
+ Main.debug("flushing image");
+ return false;
+ }
+ return super.imageUpdate(img, flags, x, y, w, h);
+ }
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASAppletStub.java b/tdehtml/java/org/kde/kjas/server/KJASAppletStub.java
new file mode 100644
index 000000000..e090183d7
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASAppletStub.java
@@ -0,0 +1,807 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.util.*;
+import java.net.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.JFrame;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.ProtectionDomain;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * The stub used by Applets to communicate with their environment.
+ *
+ */
+public final class KJASAppletStub
+ implements AppletStub
+{
+ private KJASAppletContext context; // The containing context.
+ private Hashtable params; // Maps parameter names to values
+ private URL codeBase; // The URL directory where files are
+ private URL docBase; // The document that referenced the applet
+ private boolean active; // Is the applet active?
+ private String appletName; // The name of this applet instance
+ private String appletID; // The id of this applet- for use in callbacks
+ private Dimension appletSize;
+ private String windowName;
+ private String className;
+ private Class appletClass;
+ private JFrame frame;
+
+ /**
+ * out of bounds applet state :-), perform an action
+ */
+ public static final int ACTION = -1;
+ /**
+ * applet state unknown
+ */
+ public static final int UNKNOWN = 0;
+ /**
+ * the applet class has been loaded
+ */
+ public static final int CLASS_LOADED = 1;
+ /**
+ * the applet has been instanciated
+ */
+ public static final int INSTANCIATED = 2;
+ /**
+ * the applet has been initialized
+ */
+ public static final int INITIALIZED = 3;
+ /**
+ * the applet has been started
+ */
+ public static final int STARTED = 4;
+ /**
+ * the applet has been stopped
+ */
+ public static final int STOPPED = 5;
+ /**
+ * the applet has been destroyed
+ */
+ public static final int DESTROYED = 6;
+ /**
+ * request for termination of the applet thread
+ */
+ private static final int TERMINATE = 7;
+ /**
+ * like TERMINATE, an end-point state
+ */
+ private static final int FAILED = 8;
+
+
+ //private KJASAppletClassLoader loader;
+ KJASAppletClassLoader loader;
+ private KJASAppletPanel panel;
+ private Applet app;
+ KJASAppletStub me;
+
+ /**
+ * Interface for so called LiveConnect actions, put-, get- and callMember
+ */
+ // keep this in sync with KParts::LiveConnectExtension::Type
+ private final static int JError = -1;
+ private final static int JVoid = 0;
+ private final static int JBoolean = 1;
+ private final static int JFunction = 2;
+ private final static int JNumber = 3;
+ private final static int JObject = 4;
+ final static int JString = 5;
+
+ interface AppletAction {
+ void apply();
+ void fail();
+ }
+
+ private class RunThread extends Thread {
+ private int request_state = CLASS_LOADED;
+ private int current_state = UNKNOWN;
+ private Vector actions = new Vector();
+ private AccessControlContext acc = null;
+
+ RunThread() {
+ super("KJAS-AppletStub-" + appletID + "-" + appletName);
+ setContextClassLoader(loader);
+ }
+ /**
+ * Ask applet to go to the next state
+ */
+ synchronized void requestState(int nstate) {
+ if (nstate > current_state) {
+ request_state = nstate;
+ notifyAll();
+ }
+ }
+ synchronized void requestAction(AppletAction action) {
+ actions.add(action);
+ notifyAll();
+ }
+ /**
+ * Get the asked state
+ */
+ synchronized private int getRequestState() {
+ while (request_state == current_state) {
+ if (!actions.isEmpty()) {
+ if (current_state >= INITIALIZED && current_state < STOPPED)
+ return ACTION;
+ else {
+ AppletAction action = (AppletAction) actions.remove(0);
+ action.fail();
+ }
+ } else {
+ try {
+ wait ();
+ } catch(InterruptedException ie) {
+ }
+ }
+ }
+ if (request_state == DESTROYED && current_state == STARTED)
+ return current_state + 1; // make sure we don't skip stop()
+ return request_state;
+ }
+ /**
+ * Get the current state
+ */
+ synchronized int getAppletState() {
+ return current_state;
+ }
+ /**
+ * Set the current state
+ */
+ synchronized private void setState(int nstate) {
+ current_state = nstate;
+ }
+ /**
+ * Put applet in asked state
+ * Note, kjavaapletviewer asks for create/start/stop/destroy, the
+ * missing states instance/init/terminate, we do automatically
+ */
+ private void doState(int nstate) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ switch (nstate) {
+ case CLASS_LOADED:
+ appletClass = loader.loadClass( className );
+ requestState(INSTANCIATED);
+ break;
+ case INSTANCIATED: {
+ Object object = null;
+ try {
+ object = appletClass.newInstance();
+ app = (Applet) object;
+ }
+ catch ( ClassCastException e ) {
+ if ( object != null && object instanceof java.awt.Component) {
+ app = new Applet();
+ app.setLayout(new BorderLayout());
+ app.add( (Component) object, BorderLayout.CENTER);
+ } else
+ throw e;
+ }
+ acc = new AccessControlContext(new ProtectionDomain[] {app.getClass().getProtectionDomain()});
+ requestState(INITIALIZED);
+ break;
+ }
+ case INITIALIZED:
+ app.setStub( me );
+ app.setVisible(false);
+ panel.setApplet( app );
+ if (appletSize.getWidth() > 0)
+ app.setBounds( 0, 0, appletSize.width, appletSize.height );
+ else
+ app.setBounds( 0, 0, panel.getSize().width, panel.getSize().height );
+ app.init();
+ loader.removeStatusListener(panel);
+ // stop the loading... animation
+ panel.stopAnimation();
+ app.setVisible(true);
+ break;
+ case STARTED:
+ active = true;
+ app.start();
+ frame.validate();
+ app.repaint();
+ break;
+ case STOPPED:
+ active = false;
+ app.stop();
+ if (Main.java_version > 1.399) {
+ // kill the windowClosing listener(s)
+ WindowListener[] l = frame.getWindowListeners();
+ for (int i = 0; l != null && i < l.length; i++)
+ frame.removeWindowListener(l[i]);
+ }
+ frame.setVisible(false);
+ break;
+ case DESTROYED:
+ if (app != null)
+ app.destroy();
+ frame.dispose();
+ app = null;
+ requestState(TERMINATE);
+ break;
+ default:
+ return;
+ }
+ }
+ /**
+ * RunThread run(), loop until state is TERMINATE
+ */
+ public void run() {
+ while (true) {
+ int nstate = getRequestState();
+ if (nstate >= TERMINATE)
+ return;
+ if (nstate == ACTION) {
+ AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ AppletAction action = (AppletAction) actions.remove(0);
+ try {
+ action.apply();
+ } catch (Exception ex) {
+ Main.debug("Error during action " + ex);
+ action.fail();
+ }
+ return null;
+ }
+ },
+ acc);
+ } else { // move to nstate
+ try {
+ doState(nstate);
+ } catch (Exception ex) {
+ Main.kjas_err("Error during state " + nstate, ex);
+ if (nstate < INITIALIZED) {
+ setState(FAILED);
+ setFailed(ex.toString());
+ return;
+ }
+ } catch (Throwable tr) {
+ setState(FAILED);
+ setFailed(tr.toString());
+ return;
+ }
+ setState(nstate);
+ stateChange(nstate);
+ }
+ }
+ }
+ }
+ private RunThread runThread = null;
+
+ /**
+ * Create an AppletStub for the specified applet. The stub will be in
+ * the specified context and will automatically attach itself to the
+ * passed applet.
+ */
+ public KJASAppletStub( KJASAppletContext _context, String _appletID,
+ URL _codeBase, URL _docBase,
+ String _appletName, String _className,
+ Dimension _appletSize, Hashtable _params,
+ String _windowName, KJASAppletClassLoader _loader )
+ {
+ context = _context;
+ appletID = _appletID;
+ codeBase = _codeBase;
+ docBase = _docBase;
+ active = false;
+ appletName = _appletName;
+ className = _className.replace( '/', '.' );
+ appletSize = _appletSize;
+ params = _params;
+ windowName = _windowName;
+ loader = _loader;
+
+ String fixedClassName = _className;
+ if (_className.endsWith(".class") || _className.endsWith(".CLASS"))
+ {
+ fixedClassName = _className.substring(0, _className.length()-6);
+ }
+ else if (_className.endsWith(".java")|| _className.endsWith(".JAVA"))
+ {
+ fixedClassName = _className.substring(0, _className.length()-5);
+ }
+ className = fixedClassName.replace('/', '.');
+
+ appletClass = null;
+ me = this;
+
+
+ }
+
+ private void stateChange(int newState) {
+ Main.protocol.sendAppletStateNotification(
+ context.getID(),
+ appletID,
+ newState);
+ }
+
+ private void setFailed(String why) {
+ loader.removeStatusListener(panel);
+ panel.stopAnimation();
+ panel.showFailed();
+ Main.protocol.sendAppletFailed(context.getID(), appletID, why);
+ }
+
+ void createApplet() {
+ panel = new KJASAppletPanel();
+ frame = new JFrame(windowName);
+ // under certain circumstances, it may happen that the
+ // applet is not embedded but shown in a separate window.
+ // think of konqueror running under fvwm or gnome.
+ // than, the user should have the ability to close the window.
+
+ frame.addWindowListener
+ (
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ me.destroyApplet();
+ }
+ }
+ );
+ frame.getContentPane().add( panel, BorderLayout.CENTER );
+ try {
+ if (Main.java_version > 1.399)
+ frame.setUndecorated(true);
+ } catch(java.awt.IllegalComponentStateException e) {
+ // This happens with gcj 4.0.1, ignore for now...
+ }
+ frame.setLocation( 0, 0 );
+ frame.pack();
+ // resize frame for j2sdk1.5beta1..
+ if (appletSize.getWidth() > 0)
+ frame.setBounds( 0, 0, appletSize.width, appletSize.height );
+ else
+ frame.setBounds( 0, 0, 50, 50 );
+ frame.setVisible(true);
+ loader.addStatusListener(panel);
+ runThread = new RunThread();
+ runThread.start();
+ }
+
+ /**
+ * starts the applet managed by this stub by calling the applets start() method.
+ * Also marks this stub as active.
+ * @see java.applet.Applet#start()
+ * @see java.applet.AppletStub#isActive()
+ *
+ */
+ void startApplet()
+ {
+ runThread.requestState(STARTED);
+ }
+
+ /**
+ * stops the applet managed by this stub by calling the applets stop() method.
+ * Also marks this stub as inactive.
+ * @see java.applet.Applet#stop()
+ * @see java.applet.AppletStub#isActive()
+ *
+ */
+ void stopApplet()
+ {
+ runThread.requestState(STOPPED);
+ }
+
+ /**
+ * initialize the applet managed by this stub by calling the applets init() method.
+ * @see java.applet.Applet#init()
+ */
+ void initApplet()
+ {
+ runThread.requestState(INITIALIZED);
+ }
+
+ /**
+ * destroys the applet managed by this stub by calling the applets destroy() method.
+ * Also marks the the applet as inactive.
+ * @see java.applet.Applet#init()
+ */
+ synchronized void destroyApplet()
+ {
+ runThread.requestState(DESTROYED);
+ }
+
+ static void waitForAppletThreads()
+ {
+ Thread [] ts = new Thread[Thread.activeCount() + 5];
+ int len = Thread.enumerate(ts);
+ for (int i = 0; i < len; i++) {
+ try {
+ if (ts[i].getName() != null &&
+ ts[i].getName().startsWith("KJAS-AppletStub-")) {
+ try {
+ ((RunThread) ts[i]).requestState(TERMINATE);
+ ts[i].join(10000);
+ } catch (InterruptedException ie) {}
+ }
+ } catch (Exception e) {}
+ }
+ }
+
+ /**
+ * get the Applet managed by this stub.
+ * @return the Applet or null if the applet could not be loaded
+ * or instanciated.
+ */
+ Applet getApplet()
+ {
+ if (runThread != null && runThread.getAppletState() > CLASS_LOADED)
+ return app;
+ return null;
+ }
+
+ /**
+ * get a parameter value given in the &lt;APPLET&gt; tag
+ * @param name the name of the parameter
+ * @return the value or null if no parameter with this name exists.
+ */
+
+ public String getParameter( String name )
+ {
+ return (String) params.get( name.toUpperCase() );
+ }
+
+ /**
+ * implements the isActive method of the AppletStub interface.
+ * @return if the applet managed by this stub is currently active.
+ * @see java.applet.AppletStub#isActive()
+ */
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ /**
+ * determines if the applet has been loaded and instanciated
+ * and can hence be used.
+ * @return true if the applet has been completely loaded.
+ */
+ boolean isLoaded() {
+ if (runThread == null)
+ return false;
+ int state = runThread.getAppletState();
+ return (state >= INSTANCIATED && state < DESTROYED);
+ }
+
+ public void appletResize( int width, int height )
+ {
+ if( active )
+ {
+ if ( (width >= 0) && (height >= 0))
+ {
+ Main.debug( "Applet #" + appletID + ": appletResize to : (" + width + ", " + height + ")" );
+ Main.protocol.sendResizeAppletCmd( context.getID(), appletID, width, height );
+ appletSize = new Dimension( width, height );
+ //pack();
+ }
+ }
+ }
+
+ /**
+ * converts Object <b>arg</b> into an object of class <b>cl</b>.
+ * @param arg Object to convert
+ * @param cl Destination class
+ * @return An Object of the specified class with the value specified
+ * in <b>arg</b>
+ */
+ private static final Object cast(Object arg, Class cl) throws NumberFormatException {
+ Object ret = arg;
+ if (arg == null) {
+ ret = null;
+ }
+ else if (cl.isAssignableFrom(arg.getClass())) {
+ return arg;
+ }
+ else if (arg instanceof String) {
+ String s = (String)arg;
+ Main.debug("Argument String: \"" + s + "\"");
+ if (cl == Boolean.TYPE || cl == Boolean.class) {
+ ret = new Boolean(s);
+ } else if (cl == Integer.TYPE || cl == Integer.class) {
+ ret = new Integer(s);
+ } else if (cl == Long.TYPE || cl == Long.class) {
+ ret = new Long(s);
+ } else if (cl == Float.TYPE || cl == Float.class) {
+ ret = new Float(s);
+ } else if (cl == Double.TYPE || cl == Double.class) {
+ ret = new Double(s);
+ } else if (cl == Short.TYPE || cl == Short.class) {
+ ret = new Short(s);
+ } else if (cl == Byte.TYPE || cl == Byte.class) {
+ ret = new Byte(s);
+ } else if (cl == Character.TYPE || cl == Character.class) {
+ ret = new Character(s.charAt(0));
+ }
+ }
+ return ret;
+ }
+ private Method findMethod(Class c, String name, Class [] argcls) {
+ try {
+ Method[] methods = c.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ Method m = methods[i];
+ if (m.getName().equals(name)) {
+ Main.debug("Candidate: " + m);
+ Class [] parameterTypes = m.getParameterTypes();
+ if (argcls == null) {
+ if (parameterTypes.length == 0) {
+ return m;
+ }
+ } else {
+ if (argcls.length == parameterTypes.length) {
+ for (int j = 0; j < argcls.length; j++) {
+ // Main.debug("Parameter " + j + " " + parameterTypes[j]);
+ argcls[j] = parameterTypes[j];
+ }
+ return m;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ private int[] getJSTypeValue(Hashtable jsRefs, Object obj, int objid, StringBuffer value) {
+ String val = obj.toString();
+ int[] rettype = { JError, objid };
+ String type = obj.getClass().getName();
+ if (type.equals("boolean") || type.equals("java.lang.Boolean"))
+ rettype[0] = JBoolean;
+ else if (type.equals("int") || type.equals("long") ||
+ type.equals("float") || type.equals("double") ||
+ type.equals("byte") || obj instanceof java.lang.Number)
+ rettype[0] = JNumber;
+ else if (type.equals("java.lang.String"))
+ rettype[0] = JString;
+ else if (!type.startsWith("org.kde.kjas.server") &&
+ !(obj instanceof java.lang.Class &&
+ ((Class)obj).getName().startsWith("org.kde.kjas.server"))) {
+ rettype[0] = JObject;
+ rettype[1] = obj.hashCode();
+ jsRefs.put(new Integer(rettype[1]), obj);
+ }
+ value.insert(0, val);
+ return rettype;
+ }
+ private class PutAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ String value;
+ PutAction(int cid, int oid, String n, String v) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ value = v;
+ }
+ public void apply() {
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ Main.debug("Error in putValue: object " + objid + " not found");
+ fail();
+ return;
+ }
+ Field f;
+ try {
+ f = o.getClass().getField(name);
+ } catch (Exception e) {
+ fail();
+ return;
+ }
+ if (f == null) {
+ Main.debug("Error in putValue: " + name + " not found");
+ fail();
+ return;
+ }
+ try {
+ String type = f.getType().getName();
+ Main.debug("putValue: (" + type + ")" + name + "=" + value);
+ if (type.equals("boolean"))
+ f.setBoolean(o, Boolean.getBoolean(value));
+ else if (type.equals("java.lang.Boolean"))
+ f.set(o, Boolean.valueOf(value));
+ else if (type.equals("int"))
+ f.setInt(o, Integer.parseInt(value));
+ else if (type.equals("java.lang.Integer"))
+ f.set(o, Integer.valueOf(value));
+ else if (type.equals("byte"))
+ f.setByte(o, Byte.parseByte(value));
+ else if (type.equals("java.lang.Byte"))
+ f.set(o, Byte.valueOf(value));
+ else if (type.equals("char"))
+ f.setChar(o, value.charAt(0));
+ else if (type.equals("java.lang.Character"))
+ f.set(o, new Character(value.charAt(0)));
+ else if (type.equals("double"))
+ f.setDouble(o, Double.parseDouble(value));
+ else if (type.equals("java.lang.Double"))
+ f.set(o, Double.valueOf(value));
+ else if (type.equals("float"))
+ f.setFloat(o, Float.parseFloat(value));
+ else if (type.equals("java.lang.Float"))
+ f.set(o, Float.valueOf(value));
+ else if (type.equals("long"))
+ f.setLong(o, Long.parseLong(value));
+ else if (type.equals("java.lang.Long"))
+ f.set(o, Long.valueOf(value));
+ else if (type.equals("short"))
+ f.setShort(o, Short.parseShort(value));
+ else if (type.equals("java.lang.Short"))
+ f.set(o, Short.valueOf(value));
+ else if (type.equals("java.lang.String"))
+ f.set(o, value);
+ else {
+ Main.debug("Error putValue: unsupported type: " + type);
+ fail();
+ return;
+ }
+ } catch (Exception e) {
+ Main.debug("Exception in putValue: " + e.getMessage());
+ fail();
+ return;
+ }
+ Main.protocol.sendPutMember( context.getID(), call_id, true );
+ }
+ public void fail() {
+ Main.protocol.sendPutMember( context.getID(), call_id, false );
+ }
+ }
+ private class GetAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ GetAction(int cid, int oid, String n) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ }
+ public void apply() {
+ Main.debug("getMember: " + name);
+ StringBuffer value = new StringBuffer();
+ int ret[] = { JError, objid };
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ fail();
+ return;
+ }
+ Class c = o.getClass();
+ try {
+ Field field = c.getField(name);
+ ret = getJSTypeValue(jsRefs, field.get(o), objid, value);
+ } catch (Exception ex) {
+ Method [] m = c.getMethods();
+ for (int i = 0; i < m.length; i++)
+ if (m[i].getName().equals(name)) {
+ ret[0] = JFunction;
+ break;
+ }
+ }
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.GetMember, call_id, ret[0], ret[1], value.toString());
+ }
+ public void fail() {
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.GetMember, call_id, -1, 0, "");
+ }
+ }
+ private class CallAction implements AppletAction {
+ int call_id;
+ int objid;
+ String name;
+ java.util.List args;
+ CallAction(int cid, int oid, String n, java.util.List a) {
+ call_id = cid;
+ objid = oid;
+ name = n;
+ args = a;
+ }
+ public void apply() {
+ StringBuffer value = new StringBuffer();
+ Hashtable jsRefs = loader.getJSReferencedObjects();
+ int [] ret = { JError, objid };
+ Object o = objid==0 ? getApplet() : jsRefs.get(new Integer(objid));
+ if (o == null) {
+ fail();
+ return;
+ }
+
+ try {
+ Main.debug("callMember: " + name);
+ Object obj;
+ Class c = o.getClass();
+ String type;
+ Class [] argcls = new Class[args.size()];
+ for (int i = 0; i < args.size(); i++)
+ argcls[i] = name.getClass(); // String for now, will be updated by findMethod
+ Method m = findMethod(c, (String) name, argcls);
+ Main.debug("Found Method: " + m);
+ if (m != null) {
+ Object [] argobj = new Object[args.size()];
+ for (int i = 0; i < args.size(); i++) {
+ argobj[i] = cast(args.get(i), argcls[i]);
+ }
+ Object retval = m.invoke(o, argobj);
+ if (retval == null)
+ ret[0] = JVoid;
+ else
+ ret = getJSTypeValue(jsRefs, retval, objid, value);
+ }
+ } catch (Exception e) {
+ Main.debug("callMember threw exception: " + e.toString());
+ }
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.CallMember, call_id, ret[0], ret[1], value.toString());
+ }
+ public void fail() {
+ Main.protocol.sendMemberValue(context.getID(), KJASProtocolHandler.CallMember, call_id, -1, 0, "");
+ }
+ }
+ boolean putMember(int callid, int objid, String name, String val) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new PutAction( callid, objid, name, val) );
+ return true;
+ }
+ boolean getMember(int cid, int oid, String name) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new GetAction( cid, oid, name) );
+ return true;
+ }
+ boolean callMember(int cid, int oid, String name, java.util.List args) {
+ if (runThread == null)
+ return false;
+ runThread.requestAction( new CallAction( cid, oid, name, args) );
+ return true;
+ }
+ /*************************************************************************
+ ********************** AppletStub Interface *****************************
+ *************************************************************************/
+ /**
+ * implements the getAppletContext method of the AppletStub interface.
+ * @return the AppletContext to which this stub belongs.
+ * @see java.applet.AppletStub#getAppletContext()
+ */
+ public AppletContext getAppletContext()
+ {
+ return context;
+ }
+
+ /**
+ * implements the getCodeBase method of the AppletStub interface.
+ * @return the code base of the applet as given in the &lt;APPLET&gt; tag.
+ * @see java.applet.AppletStub#getCodeBase()
+ */
+ public URL getCodeBase()
+ {
+ return codeBase;
+ }
+
+ /**
+ * implements the getDocumentBase method of the AppletStub interface.
+ * @return the code base of the applet as given in the
+ * &lt;APPLET&gt; tag or determined by the containing page.
+ * @see java.applet.AppletStub#getDocumentBase()
+ */
+ public URL getDocumentBase()
+ {
+ return docBase;
+ }
+
+ /**
+ * get the applet's name
+ * @return the name of the applet as given in the
+ * &lt;APPLET&gt; tag or determined by the <em>code</em> parameter.
+ */
+ public String getAppletName()
+ {
+ return appletName;
+ }
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASAudioClip.java b/tdehtml/java/org/kde/kjas/server/KJASAudioClip.java
new file mode 100644
index 000000000..3a40cf6e0
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASAudioClip.java
@@ -0,0 +1,98 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.net.*;
+import java.util.*;
+/**
+* Background Audioclip Loader and Player.
+* @author Till Krech (till@snafu.de)
+*/
+public class KJASAudioClip implements AudioClip
+{
+ private AudioClip theClip;
+ private final static int PLAYING = 1;
+ private final static int LOOPING = 2;
+ private final static int STOPPED = 3;
+ private int state;
+ private static Hashtable cache = new Hashtable();
+
+ /**
+ * creates a new Audioclip.
+ * The AudioClip is loaded in background. The Constructor returns immediately.
+ */
+ public KJASAudioClip(URL url)
+ {
+ state = STOPPED;
+ theClip = (AudioClip)cache.get(url);
+ if (theClip == null) {
+ final URL theUrl = url;
+
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip = java.applet.Applet.newAudioClip(theUrl);
+ cache.put(theUrl, theClip);
+ if (state == LOOPING) {
+ theClip.loop();
+ } else if (state == PLAYING) {
+ theClip.play();
+ }
+ }
+ }, "AudioClipLoader " + url.getFile()
+ ).start();
+ }
+ }
+
+ /**
+ * play continously when the clip is loaded
+ */
+ public void loop()
+ {
+ state = LOOPING;
+ if (theClip != null) {
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip.loop();
+ }
+ }, "AudioClipLooper "
+ ).start();
+ }
+ }
+
+ /**
+ * play when the clip is loaded
+ */
+ public void play()
+ {
+ state = PLAYING;
+ if (theClip != null) {
+ new Thread
+ (
+ new Runnable() {
+ public void run() {
+ theClip.play();
+ }
+ }, "AudioClipPlayer "
+ ).start();
+ }
+ }
+
+ /**
+ * stop the clip
+ */
+ public void stop()
+ {
+ state = STOPPED;
+ if (theClip != null) {
+ theClip.stop();
+ }
+ }
+
+ public void finalize() {
+ stop();
+ }
+}
+
diff --git a/tdehtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java b/tdehtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java
new file mode 100644
index 000000000..aab1be4af
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASBrokenClassFixer.java
@@ -0,0 +1,132 @@
+package org.kde.kjas.server;
+import java.lang.reflect.*;
+import java.net.URLClassLoader;
+import java.net.URL;
+/**
+* wrapper for the javaplugin.jar Broken11ClassFixer.
+* Uses the reflection api to wrap the class <i>sun.plugin.security.Broken11ClassFixer</i>
+* from the javaplugin.jar archive which can be found in the jre/lib directory.
+*/
+public class KJASBrokenClassFixer {
+ private static Class fixerClass = null;
+ private static Method _process;
+ private static Method _getProcessedData;
+ private static Method _getProcessedDataOffset;
+ private static Method _getProcessedDataLength;
+ private static boolean initialized = false;
+ private static final String fixerClassName = "sun.plugin.security.Broken11ClassFixer";
+ private Object fixer = null;
+ private byte [] bytes;
+ private int offset;
+ private int length;
+
+ /**
+ * creates a new KJASBrokenClassFixer.
+ * If it is the first one to be created, it tries to load the class
+ * <i>sun.plugin.security.Broken11ClassFixer</i> from the jar file
+ * <i>lib/javaplugin.jar</i> in the java jre directory.
+ */
+ public KJASBrokenClassFixer() {
+ init();
+ if (fixerClass != null) {
+ try {
+ fixer = fixerClass.newInstance();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * loads the class <i>sun.plugin.security.Broken11ClassFixer</i>,
+ * initializes the methods, ...
+ */
+ private synchronized void init() {
+ if (initialized) {
+ return;
+ }
+ try {
+ URL [] urls = { new URL(
+ "file", "", 0,
+ System.getProperty("java.home")
+ + System.getProperty("file.separator")
+ + "lib"
+ + System.getProperty("file.separator")
+ + "javaplugin.jar"), new URL(
+ "file", "", 0,
+ System.getProperty("java.home")
+ + System.getProperty("file.separator")
+ + "lib"
+ + System.getProperty("file.separator")
+ + "plugin.jar")
+ };
+ URLClassLoader loader = new URLClassLoader(urls);
+ fixerClass = Class.forName(fixerClassName, true, loader);
+ Main.debug("Loaded " + fixerClass);
+ final Class [] parameterTypes = {
+ (new byte[1]).getClass(),
+ Integer.TYPE,
+ Integer.TYPE
+ };
+ final Class [] noParameter = new Class[0];
+ _process = fixerClass.getMethod("process", parameterTypes);
+ _getProcessedData = fixerClass.getMethod("getProcessedData", noParameter);
+ _getProcessedDataOffset = fixerClass.getMethod("getProcessedDataOffset", noParameter);
+ _getProcessedDataLength = fixerClass.getMethod("getProcessedDataLength", noParameter);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ } finally {
+ initialized = true;
+ }
+ }
+ /**
+ * scan the broken bytes and create new ones.
+ * If the wrapped class could not be loaded or
+ * no instance of Broken11ClassFixer could be instantiated,
+ * this is a noop and later calls to getProcessedData() etc.
+ * will return the original data passed as arguments in this
+ * call.
+ */
+ public boolean process(byte [] b, int off, int len) {
+ if (fixer != null) {
+ try {
+ Object [] args = new Object[3];
+ args[0] = b;
+ args[1] = new Integer(off);
+ args[2] = new Integer(len);
+ Object [] none = new Object[0];
+
+ _process.invoke(fixer, args);
+ this.bytes = (byte[])_getProcessedData.invoke(fixer, none);
+ this.offset = ((Integer)_getProcessedDataOffset.invoke(fixer, none)).intValue();
+ this.length = ((Integer)_getProcessedDataLength.invoke(fixer, none)).intValue();
+ return true;
+ } catch (Throwable e) {
+ }
+ }
+ this.bytes = b;
+ this.offset = off;
+ this.length = len;
+ return false;
+ }
+
+ /**
+ * get the offset in the processed byte array
+ */
+ public int getProcessedDataOffset() {
+ return offset;
+ }
+ /**
+ * get the length of the processed data
+ */
+ public int getProcessedDataLength() {
+ return length;
+ }
+ /**
+ * get the processed (fixed) data
+ */
+ public byte [] getProcessedData() {
+ return bytes;
+ }
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASConsole.java b/tdehtml/java/org/kde/kjas/server/KJASConsole.java
new file mode 100644
index 000000000..51498b59b
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASConsole.java
@@ -0,0 +1,93 @@
+package org.kde.kjas.server;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+
+public class KJASConsole
+ extends Frame
+ implements Console
+{
+ private TextArea txt;
+
+ public KJASConsole()
+ {
+ super("Konqueror Java Console");
+
+ txt = new TextArea();
+ txt.setEditable(false);
+ txt.setBackground(Color.white);
+ txt.setForeground(Color.black);
+
+ Panel main = new Panel(new BorderLayout());
+ Panel btns = new Panel(new BorderLayout());
+
+ Button clear = new Button("Clear");
+ Button close = new Button("Close");
+
+ btns.add(clear, "West");
+ btns.add(close, "East");
+
+ main.add(txt, "Center");
+ main.add(btns, "South");
+
+ add( main );
+
+ clear.addActionListener
+ (
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ txt.setText("");
+ }
+ }
+ );
+
+ close.addActionListener
+ (
+ new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ setVisible(false);
+ }
+ }
+ );
+
+ addWindowListener
+ (
+ new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ setVisible(false);
+ }
+ }
+ );
+
+ setSize(500, 300);
+
+ PrintStream st = new PrintStream( new KJASConsoleStream(this) );
+ System.setOut(st);
+ System.setErr(st);
+
+ System.out.println( "Java VM version: " +
+ System.getProperty("java.version") );
+ System.out.println( "Java VM vendor: " +
+ System.getProperty("java.vendor") );
+ }
+
+ public void clear() {
+ txt.setText("");
+ }
+
+ public void append(String msg) {
+ if (msg == null) {
+ return;
+ }
+ int length = msg.length();
+ synchronized(txt) {
+ //get the caret position, and then get the new position
+ int old_pos = txt.getCaretPosition();
+ txt.append(msg);
+ txt.setCaretPosition( old_pos + length );
+ }
+ }
+}
+
+
diff --git a/tdehtml/java/org/kde/kjas/server/KJASConsoleStream.java b/tdehtml/java/org/kde/kjas/server/KJASConsoleStream.java
new file mode 100644
index 000000000..2c1152ed4
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASConsoleStream.java
@@ -0,0 +1,46 @@
+package org.kde.kjas.server;
+import java.io.*;
+
+class KJASConsoleStream
+ extends OutputStream
+{
+ private Console console;
+ private FileOutputStream dbg_log;
+
+ public KJASConsoleStream(Console console)
+ {
+ this.console = console;
+
+ try
+ {
+ if( Main.log )
+ {
+ dbg_log = new FileOutputStream( "/tmp/kjas.log");
+ }
+ }
+ catch( FileNotFoundException e ) {}
+ }
+
+ public void close() {}
+ public void flush() {}
+ public void write(byte[] b) {}
+ public void write(int a) {}
+
+ // Should be enough for the console
+ public void write( byte[] bytes, int offset, int length )
+ {
+ try // Just in case
+ {
+ String msg = new String( bytes, offset, length );
+ console.append(msg);
+ if( Main.log && dbg_log != null )
+ {
+ dbg_log.write( msg.getBytes() );
+ dbg_log.flush();
+ }
+ }
+ catch(Throwable t) {}
+ }
+}
+
+
diff --git a/tdehtml/java/org/kde/kjas/server/KJASProtocolHandler.java b/tdehtml/java/org/kde/kjas/server/KJASProtocolHandler.java
new file mode 100644
index 000000000..f8b50a91d
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASProtocolHandler.java
@@ -0,0 +1,900 @@
+package org.kde.kjas.server;
+
+import java.io.*;
+import java.util.*;
+import java.awt.*;
+import java.net.*;
+
+/**
+ * Encapsulates the KJAS protocol and manages the contexts
+ *
+ */
+public class KJASProtocolHandler
+{
+ // Command codes- always need to be synced up with
+ // what's in kjavaappletserver.cpp
+ private static final int CreateContextCode = 1;
+ private static final int DestroyContextCode = 2;
+ private static final int CreateAppletCode = 3;
+ private static final int DestroyAppletCode = 4;
+ private static final int StartAppletCode = 5;
+ private static final int StopAppletCode = 6;
+ private static final int InitAppletCode = 7;
+ private static final int ShowDocumentCode = 8;
+ private static final int ShowURLInFrameCode = 9;
+ private static final int ShowStatusCode = 10;
+ private static final int ResizeAppletCode = 11;
+ private static final int GetURLDataCode = 12;
+ private static final int URLDataCode = 13;
+ private static final int ShutdownServerCode = 14;
+ private static final int JavaScriptEvent = 15;
+ static final int GetMember = 16;
+ static final int CallMember = 17;
+ private static final int PutMember = 18;
+ private static final int DerefObject = 19;
+
+ private static final int AudioClipPlayCode = 20;
+ private static final int AudioClipLoopCode = 21;
+ private static final int AudioClipStopCode = 22;
+
+ private static final int AppletStateNotificationCode = 23;
+ private static final int AppletFailedCode = 24;
+ private static final int DataCommand = 25;
+ private static final int PutURLDataCode = 26;
+ private static final int PutDataCode = 27;
+ private static final int SecurityConfirmCode = 28;
+ private static final int ShowConsole = 29;
+
+ //Holds contexts in contextID-context pairs
+ private Hashtable contexts;
+
+ private PushbackInputStream commands; //Stream for reading in commands
+ private PrintStream signals; //Stream for writing out callbacks
+
+ //used for parsing each command as it comes in
+ private int cmd_index;
+ private final static char sep = (char) 0;
+
+ public KJASProtocolHandler( InputStream _commands,
+ OutputStream _signals )
+ {
+ commands = new PushbackInputStream( _commands );
+ signals = new PrintStream( _signals );
+ contexts = new Hashtable();
+ }
+
+ public void commandLoop()
+ {
+ try
+ {
+ while( true )
+ {
+ try
+ {
+ int cmd_length = readPaddedLength( 8 );
+ Main.debug( "PH: cmd_length = " + cmd_length );
+
+ //We need to have this while loop since we're not guaranteed to get
+ //all the bytes we want back, especially with large jars
+ byte[] cmd_data = new byte[cmd_length];
+ int total_read = 0;
+ while( total_read < cmd_length )
+ {
+ int numread = commands.read( cmd_data, total_read, cmd_length-total_read );
+ Main.debug( "PH: read in " + numread + " bytes for command" );
+ total_read += numread;
+ }
+
+ //parse the rest of the command and execute it
+ processCommand( cmd_data );
+ }
+ catch( NumberFormatException e )
+ {
+ Main.kjas_err( "Could not parse out message length", e );
+ e.printStackTrace();
+ System.exit( 1 );
+ }
+ catch( Throwable t )
+ {
+ Main.debug( "commandLoop caught a throwable, still going" );
+ t.printStackTrace();
+ }
+ }
+ }
+ catch( Exception i )
+ {
+ Main.kjas_err( "commandLoop exited on exception: ", i );
+ i.printStackTrace();
+ System.exit( 1 );
+ }
+ }
+
+ public void processCommand( byte[] command )
+ {
+ // Sanity checks
+ if ( command == null )
+ return;
+
+ //do all the parsing here and pass arguments as individual variables to the
+ //handler functions
+ int cmd_length = command.length;
+ cmd_index = 0;
+
+ int cmd_code_value = (int) command[cmd_index++];
+ if( cmd_code_value == CreateContextCode )
+ {
+ //parse out contextID- 1 argument
+ String contextID = getArg( command );
+ Main.debug( "createContext, id = " + contextID );
+
+ KJASAppletContext context = new KJASAppletContext( contextID );
+ contexts.put( contextID, context );
+ } else
+ if( cmd_code_value == DestroyContextCode )
+ {
+ //parse out contextID- 1 argument
+ String contextID = getArg( command );
+ Main.debug( "destroyContext, id = " + contextID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if( contexts != null )
+ {
+ context.destroy();
+ contexts.remove( contextID );
+ }
+ } else
+ if( cmd_code_value == CreateAppletCode )
+ {
+ //9 arguments- this order is important...
+ final String contextID = getArg( command );
+ final String appletID = getArg( command );
+ final String appletName = getArg( command );
+ final String className = getArg( command );
+ final String baseURL = getArg( command );
+ final String username = getArg( command );
+ final String password = getArg( command );
+ final String authname = getArg( command );
+ final String codeBase = getArg( command );
+ final String archives = getArg( command );
+ final String width = getArg( command );
+ final String height = getArg( command );
+ final String title = getArg( command );
+
+ //get the number of parameter pairs...
+ String str_params = getArg( command );
+ int num_params = Integer.parseInt( str_params.trim() );
+ final Hashtable params = new Hashtable();
+ for( int i = 0; i < num_params; i++ )
+ {
+ String name = getArg( command ); // note name is in uppercase
+ if( name == null )
+ name = new String();
+
+ String value = getArg( command );
+ if( value == null )
+ value = new String();
+ params.put( name, value );
+ //Main.debug( "parameter, name = " + name + ", value = " + value );
+ }
+
+ Main.debug( "createApplet, context = " + contextID + ", applet = " + appletID );
+ Main.debug( " name = " + appletName + ", classname = " + className );
+ Main.debug( " baseURL = " + baseURL + ", codeBase = " + codeBase );
+ Main.debug( " archives = " + archives + ", width = " + width +
+ ", height = " + height );
+
+ final KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if( context != null )
+ {
+ context.createApplet( appletID, appletName, className,
+ baseURL, username, password, authname,
+ codeBase, archives,
+ width, height, title, params );
+ }
+
+ } else
+ if( cmd_code_value == DestroyAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "destroyApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.destroyApplet( appletID );
+ } else
+ if( cmd_code_value == StartAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "startApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.startApplet( appletID );
+ } else
+ if( cmd_code_value == StopAppletCode )
+ {
+ //2 arguments
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ Main.debug( "stopApplet, context = " + contextID + ", applet = " + appletID );
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.stopApplet( appletID );
+ } else
+ if( cmd_code_value == ShutdownServerCode )
+ {
+ Main.debug( "shutDownServer received" );
+ KJASAppletStub.waitForAppletThreads();
+ System.exit( 1 );
+ }
+ else
+ if( cmd_code_value == URLDataCode )
+ {
+
+ String id = getArg( command );
+ String code = getArg( command );
+ Main.debug( "KIO URLData received(" + id + ") code:" + code );
+
+ //rest of the command should be the data...
+ byte[] data = null;
+ if (cmd_length - cmd_index > 0) {
+ data = new byte[ cmd_length - cmd_index ];
+ System.arraycopy( command, cmd_index, data, 0, data.length );
+ }
+ KIOConnection.setData(id, Integer.parseInt(code), data);
+ } else
+ if (cmd_code_value == GetMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context == null || !context.getMember(appletID, ticketnr, objid, name))
+ sendMemberValue(contextID, GetMember, ticketnr, -1, 0, "");
+ } else
+ if (cmd_code_value == PutMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ String value = getArg( command );
+ boolean ret = false;
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if (context == null || !context.putMember(appletID, ticketnr, objid, name, value))
+ sendPutMember(contextID, ticketnr, false);
+ } else
+ if (cmd_code_value == CallMember)
+ {
+ int ticketnr = Integer.parseInt( getArg( command ) );
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ int objid = Integer.parseInt( getArg( command ) );
+ String name = getArg( command );
+ int arg_count = Integer.parseInt( getArg( command ) );
+ java.util.List args = new java.util.Vector();
+ try { // fix getArg
+ String param = getArg(command);
+ while (arg_count-- > 0) {
+ if (param == null)
+ param = new String();
+ args.add(param);
+ param = getArg(command);
+ }
+ } catch (Exception e) {}
+
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context == null || !context.callMember(appletID, ticketnr, objid, name, args))
+ Main.protocol.sendMemberValue(contextID, CallMember, ticketnr, -1, 0, "");
+ } else
+ if (cmd_code_value == DerefObject)
+ {
+ String contextID = getArg( command );
+ String appletID = getArg( command );
+ String objid = getArg( command );
+ KJASAppletContext context = (KJASAppletContext) contexts.get( contextID );
+ if ( context != null )
+ context.derefObject(appletID, Integer.parseInt(objid));
+ Main.debug( "DerefObject " + objid);
+ } else
+ if (cmd_code_value == SecurityConfirmCode)
+ {
+ String id = getArg( command );
+ String confirm = getArg( command );
+ Thread t = (Thread) KJASSecurityManager.confirmRequests.get(id);
+ Main.debug( "SecurityConfirmCode " + id + " confirm:" + confirm );
+ if (t != null) {
+ KJASSecurityManager.confirmRequests.put(id, confirm);
+ try {
+ t.interrupt();
+ } catch (SecurityException se) {}
+ }
+ } else
+ if (cmd_code_value == ShowConsole)
+ {
+ Main.console.setVisible(true);
+ }
+ else
+ {
+ throw new IllegalArgumentException( "Unknown command code" );
+ }
+ }
+
+ /**************************************************************
+ ***** Methods for talking to the applet server **************
+ **************************************************************/
+
+ /**
+ * sends get url request
+ */
+ public void sendGetURLDataCmd( String jobid, String url )
+ {
+ Main.debug( "sendGetURLCmd(" + jobid + ") url = " + url );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ byte [] url_bytes = url.getBytes();
+ int length = jobid.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) GetURLDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ /**
+ * sends command for get url request (stop/hold/resume) or put (stop)
+ */
+ public void sendDataCmd( String id, int cmd )
+ {
+ Main.debug( "sendDataCmd(" + id + ") command = " + cmd );
+ byte [] cmd_bytes = String.valueOf( cmd ).getBytes();
+ int length = id.length() + cmd_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) DataCommand;
+ bytes[index++] = sep;
+
+ tmp_bytes = id.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( cmd_bytes, 0, bytes, index, cmd_bytes.length );
+ index += cmd_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends put url request
+ */
+ public void sendPutURLDataCmd( String jobid, String url )
+ {
+ Main.debug( "sendPutURLCmd(" + jobid + ") url = " + url );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ byte [] url_bytes = url.getBytes();
+ int length = jobid.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutURLDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends put data
+ */
+ public void sendPutData( String jobid, byte [] b, int off, int len )
+ {
+ Main.debug( "sendPutData(" + jobid + ") len = " + len );
+ //length = length of args plus 1 for code, 2 for seps and 1 for end
+ int length = jobid.length() + len + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutDataCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = jobid.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( b, off, bytes, index, len );
+ index += len;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**
+ * sends notification about the state of the applet.
+ * @see org.kde.kjas.server.KJASAppletStub for valid states
+ */
+ public void sendAppletStateNotification( String contextID, String appletID, int state )
+ {
+ Main.debug( "sendAppletStateNotification, contextID = " + contextID + ", appletID = " +
+ appletID + ", state=" + state );
+
+ byte [] state_bytes = String.valueOf( state ).getBytes();
+
+ int length = contextID.length() + appletID.length() + state_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) AppletStateNotificationCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( state_bytes, 0, bytes, index, state_bytes.length );
+ index += state_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ /**
+ * sends notification about applet failure.
+ * This can happen in any state.
+ * @param contextID context ID of the applet's context
+ * @param appletID ID of the applet
+ * @param errorMessage any message
+ */
+ public void sendAppletFailed ( String contextID, String appletID, String errorMessage)
+ {
+ Main.debug( "sendAppletFailed, contextID = " + contextID + ", appletID = " +
+ appletID + ", errorMessage=" + errorMessage );
+ byte [] msg_bytes = errorMessage.getBytes();
+ int length = contextID.length() + appletID.length() + msg_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) AppletFailedCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
+ index += msg_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowDocumentCmd( String loaderKey, String url )
+ {
+ Main.debug( "sendShowDocumentCmd from context#" + loaderKey + " url = " + url );
+
+ //length = length of args + 2 for seps + 1 for end + 1 for code
+ byte [] url_bytes = url.getBytes();
+ byte [] key_bytes = loaderKey.getBytes();
+ int length = key_bytes.length + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ]; //8 for the length of this message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowDocumentCode;
+ bytes[index++] = sep;
+
+ System.arraycopy( key_bytes, 0, bytes, index, key_bytes.length );
+ index += key_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowDocumentCmd( String contextID, String url, String frame)
+ {
+ Main.debug( "sendShowDocumentCmd from context#" + contextID +
+ " url = " + url + ", frame = " + frame );
+
+ //length = length of args plus code, 3 seps, end
+ byte [] url_bytes = url.getBytes();
+ byte [] frame_bytes = frame.getBytes();
+ int length = contextID.length() + url_bytes.length + frame_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowURLInFrameCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( frame_bytes, 0, bytes, index, frame_bytes.length );
+ index += frame_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendShowStatusCmd( String contextID, String msg )
+ {
+ Main.debug( "sendShowStatusCmd, contextID = " + contextID + " msg = " + msg );
+
+ byte [] msg_bytes = msg.getBytes();
+ int length = contextID.length() + msg_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ShowStatusCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( msg_bytes, 0, bytes, index, msg_bytes.length );
+ index += msg_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendResizeAppletCmd( String contextID, String appletID,
+ int width, int height )
+ {
+ Main.debug( "sendResizeAppletCmd, contextID = " + contextID + ", appletID = " +
+ appletID + ", width = " + width + ", height = " + height );
+
+ byte [] width_bytes = String.valueOf( width ).getBytes();
+ byte [] height_bytes = String.valueOf( height ).getBytes();
+
+ //length = length of args plus code, 4 seps, end
+ int length = contextID.length() + appletID.length() + width_bytes.length +
+ height_bytes.length + 6;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) ResizeAppletCode;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( width_bytes, 0, bytes, index, width_bytes.length );
+ index += width_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( height_bytes, 0, bytes, index, height_bytes.length );
+ index += height_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendJavaScriptEventCmd( String contextID, String appletID, int objid, String event, int [] types, String [] args )
+ {
+ Main.debug( "sendJavaScriptEventCmd, contextID = " + contextID + " event = " + event );
+ String objstr = new String("" + objid);
+ int length = contextID.length() + appletID.length() + event.length() + objstr.length() + 6;
+ byte [][][] arglist = null;
+ if (types != null) {
+ arglist = new byte[args.length][2][];
+ for (int i = 0; i < types.length; i++) {
+ arglist[i][0] = (new String("" + types[i])).getBytes();
+ arglist[i][1] = args[i].getBytes();
+ length += 2 + arglist[i][0].length + arglist[i][1].length;
+ }
+ }
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) JavaScriptEvent;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = appletID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = objstr.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = event.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ if (types != null)
+ for (int i = 0; i < types.length; i++) {
+ System.arraycopy( arglist[i][0], 0, bytes, index, arglist[i][0].length );
+ index += arglist[i][0].length;
+ bytes[index++] = sep;
+ System.arraycopy( arglist[i][1], 0, bytes, index, arglist[i][1].length );
+ index += arglist[i][1].length;
+ bytes[index++] = sep;
+ }
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendMemberValue( String contextID, int cmd, int ticketnr, int type, int rid, String value )
+ {
+ Main.debug( "sendMemberValue, contextID = " + contextID + " value = " + value + " type=" + type + " rid=" + rid );
+
+ String strticket = String.valueOf( ticketnr );
+ String strtype = String.valueOf( type );
+ String strobj = String.valueOf( rid );
+ byte [] value_bytes = value.getBytes();
+ int length = contextID.length() + value_bytes.length + strtype.length() + strobj.length() + strticket.length() + 7;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ int index = 0;
+
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) cmd;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strticket.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strtype.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ tmp_bytes = strobj.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( value_bytes, 0, bytes, index, value_bytes.length );
+ index += value_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ private void sendAudioClipCommand(String contextId, String url, int cmd) {
+ byte [] url_bytes = url.getBytes();
+ int length = contextId.length() + url_bytes.length + 4;
+ byte [] bytes = new byte[ length + 8 ];
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) cmd;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextId.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( url_bytes, 0, bytes, index, url_bytes.length );
+ index += url_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+
+ public void sendAudioClipPlayCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipPlayCode);
+ }
+ public void sendAudioClipLoopCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipLoopCode);
+ }
+ public void sendAudioClipStopCommand(String contextId, String url) {
+ sendAudioClipCommand(contextId, url, AudioClipStopCode);
+ }
+
+ public void sendPutMember( String contextID, int ticketnr, boolean success )
+ {
+ Main.debug("sendPutMember, contextID = " + contextID + " success = " + success);
+
+ byte [] ticket_bytes = String.valueOf( ticketnr ).getBytes();
+ byte [] ret_bytes = String.valueOf( success ? "1" : "0" ).getBytes();
+ int length = contextID.length() + ret_bytes.length + ticket_bytes.length + 5;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) PutMember;
+ bytes[index++] = sep;
+
+ tmp_bytes = contextID.getBytes();
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( ticket_bytes, 0, bytes, index, ticket_bytes.length );
+ index += ticket_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( ret_bytes, 0, bytes, index, ret_bytes.length );
+ index += ret_bytes.length;
+ bytes[index++] = sep;
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ public void sendSecurityConfirm( String [] certs, int certsnr, String perm, String id )
+ {
+ Main.debug("sendSecurityConfirm, ID = " + id + " certsnr = " + certsnr);
+
+ byte [] id_bytes = id.getBytes();
+ byte [] perm_bytes = perm.getBytes();
+ byte [] certsnr_bytes = String.valueOf( certsnr ).getBytes();
+ int length = perm_bytes.length + id_bytes.length + certsnr_bytes.length + 5;
+ for (int i = 0; i < certsnr; i++)
+ length += certs[i].length() + 1;
+ byte [] bytes = new byte[ length + 8 ]; //for length of message
+ byte [] tmp_bytes = getPaddedLengthBytes( length );
+ int index = 0;
+
+ System.arraycopy( tmp_bytes, 0, bytes, index, tmp_bytes.length );
+ index += tmp_bytes.length;
+ bytes[index++] = (byte) SecurityConfirmCode;
+ bytes[index++] = sep;
+
+ System.arraycopy( id_bytes, 0, bytes, index, id_bytes.length );
+ index += id_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( perm_bytes, 0, bytes, index, perm_bytes.length );
+ index += perm_bytes.length;
+ bytes[index++] = sep;
+
+ System.arraycopy( certsnr_bytes, 0, bytes, index, certsnr_bytes.length );
+ index += certsnr_bytes.length;
+ bytes[index++] = sep;
+
+ for (int i = 0; i < certsnr; i++) {
+ byte [] cert_bytes = certs[i].getBytes();
+ System.arraycopy( cert_bytes, 0, bytes, index, cert_bytes.length );
+ index += cert_bytes.length;
+ bytes[index++] = sep;
+ }
+
+ signals.write( bytes, 0, bytes.length );
+ }
+ /**************************************************************
+ ***** Utility functions for parsing commands ****************
+ **************************************************************/
+ private String getArg( byte[] command )
+ {
+ int begin = cmd_index;
+ while( 0 != ((int) command[cmd_index++]) );
+
+ if( cmd_index > (begin + 1) )
+ {
+ String rval = new String( command, begin, (cmd_index - begin - 1) );
+ return rval;
+ }
+ else
+ return null;
+ }
+
+ private byte[] getPaddedLengthBytes( int length )
+ {
+ byte[] length_bytes = String.valueOf( length ).getBytes();
+ if( length_bytes.length > 8 )
+ throw new IllegalArgumentException( "can't create string number of length = 8" );
+ byte [] bytes = { (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' ',
+ (byte) ' ', (byte) ' ', (byte) ' ', (byte) ' '};
+ System.arraycopy( length_bytes, 0, bytes, 0, length_bytes.length );
+ return bytes;
+ }
+ private int readPaddedLength( int string_size )
+ throws IOException
+ {
+ //read in 8 bytes for command length- length will be sent as a padded string
+ byte[] length = new byte[string_size];
+ commands.read( length, 0, string_size );
+
+ String length_str = new String( length );
+ return Integer.parseInt( length_str.trim() );
+ }
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASSecurityManager.java b/tdehtml/java/org/kde/kjas/server/KJASSecurityManager.java
new file mode 100644
index 000000000..0525bba0c
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASSecurityManager.java
@@ -0,0 +1,243 @@
+package org.kde.kjas.server;
+
+import java.security.*;
+import java.security.cert.*;
+import java.net.*;
+import java.util.*;
+
+
+public class KJASSecurityManager extends SecurityManager
+{
+ static Hashtable confirmRequests = new Hashtable();
+ static int confirmId = 0;
+ Hashtable grantedPermissions = new Hashtable();
+ HashSet grantAllPermissions = new HashSet();
+ HashSet rejectAllPermissions = new HashSet();
+
+ private static final char [] base64table = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+ static String encode64( byte [] data)
+ {
+ StringBuffer buf = new StringBuffer( 4*((data.length + 2)/3) );
+ int i = 0, b1, b2, b3;
+ while (i < data.length - 2) {
+ b1 = data[i++];
+ b2 = data[i++];
+ b3 = data[i++];
+ buf.append( base64table[(b1 >>> 2) & 0x3F] );
+ buf.append( base64table[((b1 << 4) & 0x30) | ((b2 >>> 4) & 0xF)] );
+ buf.append( base64table[((b2 << 2) & 0x3C) | ((b3 >>> 6) & 0x03)] );
+ buf.append( base64table[b3 & 0x3F] );
+ }
+ if ( i < data.length ) {
+ b1 = data[i++];
+ buf.append( base64table[(b1 >>> 2) & 0x3F] );
+ if ( i < data.length ) {
+ b2 = data[i++];
+ buf.append( base64table[((b1 << 4) & 0x30) | ((b2 >>> 4) & 0xF)] );
+ buf.append( base64table[(b2 << 2) & 0x3C] );
+ } else {
+ buf.append( base64table[(b1 << 4) & 0x30] );
+ buf.append( "=" );
+ }
+ buf.append( '=' );
+ }
+ return buf.toString();
+ }
+ public KJASSecurityManager()
+ {
+ }
+ /**
+ * checks for an applets permission to access certain resources
+ * currently, only a check for SocketPermission is done, that the
+ * applet cannot connect to any other but the host, where it comes from.
+ * Anything else seems to be handled automagically
+ */
+ public void checkPermission(Permission perm) throws SecurityException, NullPointerException {
+ // ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ try {
+ super.checkPermission(perm);
+ } catch (SecurityException se) {
+ // Don't annoy users with these
+ if (/*perm instanceof java.lang.RuntimePermission || */
+ perm instanceof java.awt.AWTPermission)
+ throw se;
+
+ // Collect certificates
+ HashSet signers = new HashSet();
+ Class [] cls = getClassContext();
+ for (int i = 1; i < cls.length; i++) {
+ Object[] objs = cls[i].getSigners();
+ if (objs != null && objs.length > 0) {
+ for (int j = 0; j < objs.length; j++)
+ if (objs[j] instanceof X509Certificate)
+ signers.add( ((X509Certificate) objs[j]) );
+ }
+ }
+ Main.debug("Certificates " + signers.size() + " for " + perm);
+
+ // Check granted/denied permission
+ if ( grantAllPermissions.contains(signers) )
+ return;
+ if ( rejectAllPermissions.contains(signers) )
+ throw se;
+ Permissions permissions = (Permissions) grantedPermissions.get(signers);
+ if (permissions != null && permissions.implies(perm))
+ return;
+
+ // Ok, ask user what to do
+ String [] certs = new String[signers.size()];
+ int certsnr = 0;
+ for (Iterator i = signers.iterator(); i.hasNext(); ) {
+ try {
+ certs[certsnr] = encode64( ((X509Certificate) i.next()).getEncoded() );
+ certsnr++;
+ } catch (CertificateEncodingException cee) {}
+ }
+ if (certsnr == 0)
+ throw se;
+ String id = "" + confirmId++;
+ confirmRequests.put(id, Thread.currentThread());
+ Main.protocol.sendSecurityConfirm(certs, certsnr, perm.toString(), id);
+ boolean granted = false;
+ try {
+ Thread.sleep(300000);
+ } catch (InterruptedException ie) {
+ if (((String) confirmRequests.get(id)).equals("yes")) {
+ granted = true;
+ permissions = (Permissions) grantedPermissions.get(signers);
+ if (permissions == null) {
+ permissions = new Permissions();
+ grantedPermissions.put(signers, permissions);
+ }
+ permissions.add(perm);
+ } else if (((String) confirmRequests.get(id)).equals("grant")) {
+ grantAllPermissions.add( signers );
+ granted = true;
+ } else if (((String) confirmRequests.get(id)).equals("reject")) {
+ rejectAllPermissions.add( signers );
+ } // else "no", "nossl" or "invalid"
+ } finally {
+ confirmRequests.remove(id);
+ }
+ if (!granted) {
+ Main.debug("Permission denied" + perm);
+ throw se;
+ }
+ }
+ }
+
+ // keytool -genkey -keystore mystore -alias myalias
+ // keytool -export -keystore mystore -alias myalias -file mycert
+ // keytool -printcert -file mycert
+ // keytool -import -keystore myotherstore -alias myalias -file mycert
+ // jarsigner -keystore mystore myjar.jar myalias
+ // jarsigner -verify -keystore myotherstore myjar.jar
+ //
+ // policy file (use policytool and check java.security):
+ // keystore "file:myotherstore", "JKS"
+ // grant signedBy "myalias"
+ // {
+ // permission java.io.FilePermission "<<ALL FILES>>", "read"
+ // }
+ //
+ // java code:
+ // KeyStore store = KeyStore.getInstance("JKS", "SUN");
+ public void disabled___checkPermission(Permission perm) throws SecurityException, NullPointerException
+ {
+ // does not seem to work as expected, Problems with proxy - and it seems that the default
+ // implementation already does all that well, what I wanted to do here.
+ // It is likely that this method will hence disappear soon again.
+ Object context = getSecurityContext();
+ Thread thread = Thread.currentThread();
+ if (perm instanceof SocketPermission) {
+ // check if this is a connection back to the originating host
+ // if not, fall through and call super.checkPermission
+ // this gives normally access denied
+ Main.debug("*** checkPermission " + perm + " in context=" + context + " Thread=" + thread);
+ // use the context class loader to determine if this is one
+ // of our applets
+ ClassLoader contextClassLoader = thread.getContextClassLoader();
+ Main.debug("* ClassLoader=" + contextClassLoader);
+ try {
+ // try to cast ...
+ KJASAppletClassLoader loader = (KJASAppletClassLoader)contextClassLoader;
+ // ok. cast succeeded. Now get the codebase of the loader
+ // because it contains the host name
+ URL codebase = loader.getCodeBase();
+ URL docbase = loader.getDocBase();
+ Main.debug("* Class Loader docbase=" + docbase + " codebase=" + codebase);
+ String hostname = perm.getName();
+ // extract the hostname from the permission name
+ // which is something like "some.host.domain:XX"
+ // with XX as the port number
+ int colonIdx = hostname.indexOf(':');
+ if (colonIdx > 0) {
+ // strip of the port
+ hostname = hostname.substring(0, colonIdx);
+ }
+ // Main.info("Checking " + hostname + "<->" + codebase.getHost());
+
+ if (hostsAreEqual(hostname, codebase.getHost())) {
+ // ok, host matches
+ String actions = perm.getActions();
+ // just check if listen is specified which we do not want
+ // to allow
+ if (actions != null && actions.indexOf("listen") >= 0) {
+ Main.debug("* Listen is not allowed.");
+ } else {
+ // ok, just return and throw _no_ exception
+ Main.debug("* Hostname equals. Permission granted.");
+ return;
+ }
+ } else {
+ Main.info("Host mismatch: " + perm + " != " + codebase.getHost());
+ }
+ } catch (ClassCastException e) {
+ Main.debug("* ClassLoader is not a KJASAppletClassLoader");
+ }
+ Main.debug("* Fall through to super.checkPermission()");
+ }
+ super.checkPermission(perm);
+ }
+
+ private static final boolean hostsAreEqual(String host1, String host2) {
+ if (host1 == null || host2 == null) {
+ return false;
+ }
+ if (host1.length() == 0 || host2.length() == 0) {
+ return false;
+ }
+ if (host1.equalsIgnoreCase(host2)) {
+ return true;
+ }
+
+ if ( Main.proxyHost != null && Main.proxyPort != 0) {
+ // if we use a proxy, we certainly cannot use DNS
+ return false;
+ }
+
+ InetAddress inet1=null, inet2=null;
+ try {
+ inet1 = InetAddress.getByName(host1);
+ } catch (UnknownHostException e) {
+ Main.kjas_err("Unknown host:" + host1, e);
+ return false;
+ }
+ try {
+ inet2 = InetAddress.getByName(host2);
+ } catch (UnknownHostException e) {
+ Main.kjas_err("Unknown host:" + host2, e);
+ return false;
+ }
+ if (inet1.equals(inet2)) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/tdehtml/java/org/kde/kjas/server/KJASSoundPlayer.java b/tdehtml/java/org/kde/kjas/server/KJASSoundPlayer.java
new file mode 100644
index 000000000..a37c2bbd4
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASSoundPlayer.java
@@ -0,0 +1,36 @@
+package org.kde.kjas.server;
+
+import java.applet.*;
+import java.net.*;
+
+public class KJASSoundPlayer implements AudioClip
+{
+ private String file;
+ private String contextId;
+
+ public KJASSoundPlayer( String _contextId, URL _file )
+ {
+ file = _file.toString();
+ contextId = _contextId;
+ Main.debug("KJASSoundPlayer( URL '" + _file + "')");
+ }
+
+ public void loop()
+ {
+ Main.debug("KJASSoundPlayer loop() URL='" + file + "'");
+ Main.protocol.sendAudioClipLoopCommand(contextId, file);
+ }
+
+ public void play()
+ {
+ Main.debug("KJASSoundPlayer play() URL='" + file + "'");
+ Main.protocol.sendAudioClipPlayCommand(contextId, file);
+ }
+
+ public void stop()
+ {
+ Main.debug("KJASSoundPlayer stop() URL='" + file + "'");
+ Main.protocol.sendAudioClipStopCommand(contextId, file);
+ }
+}
+
diff --git a/tdehtml/java/org/kde/kjas/server/KJASSwingConsole.java b/tdehtml/java/org/kde/kjas/server/KJASSwingConsole.java
new file mode 100644
index 000000000..fedda6c48
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASSwingConsole.java
@@ -0,0 +1,325 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Till
+ * Copyright (C) 2005 Koos Vriezen <koos ! vriezen () xs4all ! nl>
+ *
+ * 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.
+ */
+
+package org.kde.kjas.server;
+
+import java.awt.Toolkit;
+import java.awt.Image;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.Properties;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JButton;
+import javax.swing.JTextArea;
+import javax.swing.border.EmptyBorder;
+
+
+public class KJASSwingConsole implements Console {
+ private JFrame frame = null;
+ private JPanel jPanel1;
+ private JScrollPane jScrollPane1;
+ private JButton clearButton;
+ private JTextArea textField;
+ private JButton closeButton;
+ private JButton copyButton;
+ final static int NR_BUFFERS = 3;
+ final static int MAX_BUF_LENGTH = 3000;
+ private int queue_pos = 0;
+ private StringBuffer [] output_buffer = new StringBuffer[NR_BUFFERS];
+
+ private PrintStream real_stderr = new PrintStream(System.err);
+
+ /** Creates new form KJASSwingConsole */
+ public KJASSwingConsole() {
+ PrintStream st = new PrintStream( new KJASConsoleStream(this) );
+ System.setOut(st);
+ System.setErr(st);
+ }
+
+ private void initComponents() {
+ frame = new JFrame("Konqueror Java Console");
+ jPanel1 = new JPanel();
+ clearButton = new JButton();
+ closeButton = new JButton();
+ copyButton = new JButton();
+ jScrollPane1 = new JScrollPane();
+ textField = new JTextArea();
+
+ frame.setFont(new java.awt.Font("Monospaced", 0, 10));
+ frame.setName("KJAS Console");
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent evt) {
+ exitForm(evt);
+ }
+ });
+
+ jPanel1.setLayout(new BorderLayout());
+ jPanel1.setBorder(new EmptyBorder(new java.awt.Insets(1, 1, 1, 1)));
+ clearButton.setText("clear");
+ clearButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ clearButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(clearButton, BorderLayout.WEST);
+
+ closeButton.setText("close");
+ closeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ closeButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(closeButton, BorderLayout.EAST);
+
+ copyButton.setText("copy");
+ copyButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ copyButtonActionPerformed(evt);
+ }
+ });
+
+ jPanel1.add(copyButton, BorderLayout.CENTER);
+
+ frame.getContentPane().add(jPanel1, BorderLayout.SOUTH);
+
+ textField.setColumns(40);
+ textField.setEditable(false);
+ textField.setRows(10);
+ textField.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent evt) {
+ textFieldKeyPressed(evt);
+ }
+ });
+
+ jScrollPane1.setViewportView(textField);
+
+ frame.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
+
+ try {
+ java.net.URL iconUrl = getClass().getClassLoader().getResource("images/beanicon.png");
+ if (iconUrl != null) {
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ Image icon = tk.createImage(iconUrl);
+ frame.setIconImage(icon);
+ }
+ } catch (Throwable e) {
+ }
+ frame.pack();
+ frame.setSize(500, 300);
+ }
+
+ private void textFieldKeyPressed(java.awt.event.KeyEvent evt) {
+ // Add your handling code here:
+ char key = evt.getKeyChar();
+ switch (key) {
+ case 'h':
+ showHelp();
+ break;
+ case 'g':
+ append("Running Garbage Collection ...\n", true);
+ System.gc();
+ case 'm':
+ append("Total Memory: " + Runtime.getRuntime().totalMemory() + " bytes\n", true);
+ append("Free Memory : " + Runtime.getRuntime().freeMemory() + " bytes\n", true);
+ break;
+ case 'c':
+ clear();
+ break;
+ case 's':
+ showSystemProperties();
+ break;
+ case 't':
+ showThreads();
+ break;
+ case 'x':
+ KJASAppletClassLoader.removeLoaders();
+ append("Emptied Classloader Cache\n", true);
+ break;
+ }
+ }
+
+ private void showHelp() {
+ append("Java VM: " + System.getProperty("java.vendor") + " " + System.getProperty("java.version") + "\n", true);
+ String ph = System.getProperty("http.proxyHost");
+ if (ph != null) {
+ append("Proxy: " + ph + ":" + System.getProperty("java.proxyPort") + "\n", true);
+ }
+ SecurityManager sec = System.getSecurityManager();
+ if (sec == null) {
+ append("WARNING: Security Manager disabled!\n", true);
+ } else {
+ append("SecurityManager=" + sec + "\n", true);
+ }
+ appendSeparator();
+ append("Konqueror Java Console Help\n", true);
+ append(" c: clear console\n", true);
+ append(" g: run garbage collection\n", true);
+ append(" h: show help\n", true);
+ append(" m: show memory info\n", true);
+ append(" s: print system properties\n", true);
+ append(" t: list threads\n", true);
+ append(" x: empty classloader cache\n", true);
+ appendSeparator();
+ }
+
+ private void showSystemProperties() {
+ append("Printing System Properties ...\n", true);
+ appendSeparator();
+ Properties p = System.getProperties();
+ for (Enumeration e = p.keys(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ if ("line.separator".equals(key)) {
+ String value = (String) p.get(key);
+ StringBuffer unescaped = new StringBuffer(10);
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ if (c == '\n') unescaped.append("\\n");
+ else if (c == '\r') unescaped.append("\\n");
+ else unescaped.append(c);
+ }
+ append(key + " = " + unescaped + "\n", true);
+ } else append(key + " = " + p.get(key) + "\n", true);
+ }
+ appendSeparator();
+ }
+
+ private void showThreads() {
+ Thread t = Thread.currentThread();
+ ThreadGroup g = t.getThreadGroup();
+ ThreadGroup parent;
+ while ((parent = g.getParent()) != null) {
+ g = parent;
+ }
+ g.list();
+ }
+
+ private void copyButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ textField.selectAll();
+ textField.copy();
+ }
+
+ private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ frame.setVisible(false);
+ }
+
+ private void clearButtonActionPerformed(java.awt.event.ActionEvent evt) {
+ clear();
+ }
+
+ /** Exit the Application */
+ private void exitForm(java.awt.event.WindowEvent evt) {
+ frame.setVisible(false);
+ }
+
+ public void setVisible(boolean visible) {
+ if (frame == null && visible) {
+ initComponents();
+ frame.setVisible(visible);
+ System.out.println( "Java VM version: " +
+ System.getProperty("java.version") );
+ System.out.println( "Java VM vendor: " +
+ System.getProperty("java.vendor") );
+ String ph = System.getProperty("http.proxyHost");
+ String pp = System.getProperty("http.proxyPort");
+ if (ph != null) {
+ System.out.println("Proxy: " + ph + ":" + pp);
+ }
+ SecurityManager sec = System.getSecurityManager();
+ Main.debug("SecurityManager=" + sec);
+ if (sec == null) {
+ System.out.println( "WARNING: Security Manager disabled!" );
+ textField.setForeground(java.awt.Color.red);
+ }
+ showHelp();
+ } else if (frame != null)
+ frame.setVisible(visible);
+
+ if (visible) {
+ for (int i = 0; i < NR_BUFFERS; i++)
+ if (output_buffer[(queue_pos + i + 1) % 3] != null) {
+ textField.append(output_buffer[(queue_pos + i + 1) % 3].toString());
+ output_buffer[(queue_pos + i + 1) % 3] = null;
+ }
+ }
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ new KJASSwingConsole().setVisible(true);
+ }
+
+ public void clear() {
+ textField.setText("");
+ }
+
+ private void appendSeparator() {
+ append("----------------------------------------------------\n", true);
+ }
+
+ public void append(String txt) {
+ append(txt, false);
+ }
+
+ public void append(String txt, boolean force) {
+ if (txt == null)
+ return;
+ if (frame == null || !frame.isVisible()) {
+ if (Main.Debug)
+ real_stderr.print(txt);
+ if (output_buffer[queue_pos] != null &&
+ output_buffer[queue_pos].length() > MAX_BUF_LENGTH) {
+ queue_pos = (++queue_pos) % NR_BUFFERS;
+ if (output_buffer[queue_pos] != null) {
+ // starting overwriting old log, clear textField if exists
+ if (frame != null)
+ textField.setText("");
+ output_buffer[queue_pos] = null;
+ }
+ }
+ if (output_buffer[queue_pos] == null)
+ output_buffer[queue_pos] = new StringBuffer(txt);
+ else
+ output_buffer[queue_pos].append(txt);
+ return;
+ }
+ int length = txt.length();
+ synchronized(textField) {
+ //get the caret position, and then get the new position
+ int old_pos = textField.getCaretPosition();
+ textField.append(txt);
+ textField.setCaretPosition( old_pos + length );
+ }
+ }
+}
+
diff --git a/tdehtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java b/tdehtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java
new file mode 100644
index 000000000..58c5ff518
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/KJASURLStreamHandlerFactory.java
@@ -0,0 +1,609 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Koos Vriezen <koos ! vriezen () xs4all ! nl>
+ *
+ * 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.
+ */
+
+package org.kde.kjas.server;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.security.*;
+/**
+ *
+ */
+
+class KIOConnection
+{
+ final static int NOT_CONNECTED = 0;
+ final static int CONNECT_WAIT = 1;
+ final static int CONNECTED = 2;
+
+ final static int DATA = 0;
+ final static int FINISHED = 1;
+ final static int ERRORCODE = 2;
+ final static int CONNECT = 6;
+ final static int REQUESTDATA = 7;
+
+ final static int STOP = 0;
+ final static int HOLD = 1;
+ final static int RESUME = 2;
+
+ protected static int id = 0;
+ static Hashtable jobs = new Hashtable(); // should be thread safe
+
+ static void setData(String jobid, int code, byte [] data) {
+ KIOConnection job = (KIOConnection) jobs.get(jobid);
+ if (job == null || !job.setData(code, data))
+ Main.info("KIO KJASHttpURLConnection gone (timedout/closed)");
+ else
+ Thread.yield();
+ }
+
+ private class KJASOutputStream extends OutputStream {
+ KJASOutputStream() {
+ }
+ public void write(int b) throws IOException {
+ byte[] buf = {(byte)b};
+ write(buf);
+ }
+ public synchronized void write(byte b[], int off, int len) throws IOException {
+ byte[] buf = new byte[len];
+ System.arraycopy(b, off, buf, 0, len);
+ sendData(buf, false);
+ }
+ public void write(byte b[]) throws IOException {
+ write(b, 0, b.length);
+ }
+ public void close() throws IOException {
+ disconnect();
+ }
+ public void flush() throws IOException {
+ checkConnected();
+ sendData(null, true);
+ }
+ }
+
+ private class KJASInputStream extends InputStream {
+
+ KJASInputStream() {
+ }
+ public int read() throws IOException {
+ if (getData(true))
+ return 0x00ff & in_buf[in_bufpos++];
+ return -1;
+ }
+ public int read(byte[] b, int off, int len) throws IOException {
+ int total = 0;
+ do {
+ if (!getData(true)) break;
+ int nr = in_buf.length - in_bufpos;
+ if (nr > len)
+ nr = len;
+ System.arraycopy(in_buf, in_bufpos, b, off, nr);
+ len -= nr;
+ total += nr;
+ off += nr;
+ in_bufpos += nr;
+ } while (len > 0);
+ return total > 0 ? total : -1;
+ }
+ public int read(byte[] b) throws IOException {
+ return read(b, 0, b.length);
+ }
+ public int available() throws IOException {
+ return inAvailable();
+ }
+ public boolean markSupported() {
+ return false;
+ }
+ public void close() throws IOException {
+ disconnect();
+ }
+ }
+
+ protected URL url;
+ protected int connect_status = 0;
+ protected String jobid = null; // connection id with KIO
+ protected LinkedList data = new LinkedList(); // not thread safe
+ protected int errorcode = 0;
+ protected boolean finished = false; // all data has arived
+ protected boolean onhold = false; // KIO job is suspended
+ protected boolean request_data = false; // need data for put job
+ private KJASOutputStream out = null;
+ private KJASInputStream in = null;
+ private byte [] in_buf = null; // current input buffer
+ private int in_bufpos = 0; // position in buffer
+ private boolean in_eof = false; // all data is read
+ private final static int LOW_BUFFER_LIMIT = 5; // put onhold off
+ private final static int HIGH_BUFFER_LIMIT = 10; // put onhold on
+
+ protected KIOConnection(URL u) {
+ url = u;
+ }
+ protected void checkConnected() throws IOException {
+ if (connect_status != CONNECTED)
+ throw new IOException("not connected");
+ }
+ protected boolean haveError() {
+ return errorcode != 0;
+ }
+ synchronized protected boolean setData(int code, byte [] d) {
+ // is job still there when entering the monitor
+ if (jobs.get(jobid) == null)
+ return false;
+ if (connect_status == CONNECT_WAIT)
+ connect_status = CONNECTED;
+ switch (code) {
+ case FINISHED:
+ if (d != null && d.length > 0)
+ data.addLast(d);
+ finished = true;
+ onhold = false;
+ jobs.remove(jobid);
+ Main.debug ("KIO FINISHED (" + jobid + ") " + data.size());
+ break;
+ case DATA:
+ if (d.length > 0)
+ data.addLast(d);
+ // Main.debug ("KIO DATA (" + jobid + ") " + data.size());
+ if (!onhold && data.size() > HIGH_BUFFER_LIMIT) {
+ Main.protocol.sendDataCmd(jobid, HOLD);
+ onhold = true;
+ }
+ break;
+ case ERRORCODE:
+ String codestr = new String(d);
+ errorcode = Integer.parseInt(codestr);
+ Main.debug ("KIO ERRORECODE(" + jobid + ") " + errorcode);
+ break;
+ case CONNECT:
+ Main.debug ("KIO CONNECT(" + jobid + ") ");
+ request_data = true;
+ errorcode = 0;
+ break;
+ case REQUESTDATA:
+ Main.debug ("KIO REQUESTDATA(" + jobid + ") ");
+ request_data = true;
+ break;
+ }
+ notifyAll();
+ return true;
+ }
+
+ private synchronized boolean getData(boolean mayblock) throws IOException {
+ if (haveError()) {
+ //disconnect();
+ in_eof = true;
+ //throw new IOException("i/o error " + errorcode);
+ }
+ if (in_eof)
+ return false;
+ checkConnected();
+ if (in_buf != null && in_bufpos < in_buf.length)
+ return true;
+ int datasize = data.size();
+ if (datasize > 0) {
+ in_buf = (byte []) data.removeFirst();
+ in_bufpos = 0;
+ }
+ if (onhold && datasize < LOW_BUFFER_LIMIT) {
+ Main.protocol.sendDataCmd(jobid, RESUME);
+ onhold = false;
+ }
+ if (datasize > 0)
+ return true;
+ if (finished) {
+ in_eof = true;
+ return false;
+ }
+ if (!mayblock)
+ return false;
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ return false;
+ }
+ return getData(false);
+ }
+ synchronized private int inAvailable() throws IOException {
+ if (in_eof)
+ return 0;
+ checkConnected();
+ if (!getData(false))
+ return 0;
+ int total = in_buf.length - in_bufpos;
+ ListIterator it = data.listIterator(0);
+ while (it.hasNext())
+ total += ((byte []) it.next()).length;
+ return total;
+ }
+ synchronized private void sendData(byte [] d, boolean force) throws IOException {
+ Main.debug ("KIO sendData(" + jobid + ") force:" + force + " request_data:" + request_data);
+ if (d != null)
+ data.addLast(d);
+ if (!request_data && !force) return;
+ if (data.size() == 0) return;
+ if (force && !request_data) {
+ try {
+ wait(10000);
+ } catch (InterruptedException ie) {
+ return;
+ }
+ if (!request_data) {
+ Main.debug ("KIO sendData(" + jobid + ") timeout");
+ data.clear();
+ disconnect();
+ throw new IOException("timeout");
+ }
+ }
+ byte[] buf;
+ int total = 0;
+ ListIterator it = data.listIterator(0);
+ while (it.hasNext())
+ total += ((byte []) it.next()).length;
+ buf = new byte[total];
+ int off = 0;
+ it = data.listIterator(0);
+ while (it.hasNext()) {
+ byte [] b = (byte []) it.next();
+ System.arraycopy(b, 0, buf, off, b.length);
+ off += b.length;
+ }
+ data.clear();
+ request_data = false;
+ Main.protocol.sendPutData(jobid, buf, 0, total);
+ }
+ synchronized void connect(boolean doInput) throws IOException {
+ if (connect_status == CONNECTED)
+ return; // javadocs: call is ignored
+ //(new Exception()).printStackTrace();
+ Main.debug ("KIO connect " + url);
+ errorcode = 0;
+ finished = in_eof = false;
+ jobid = String.valueOf(id++);
+ jobs.put(jobid, this);
+ if (doInput)
+ Main.protocol.sendGetURLDataCmd(jobid, url.toExternalForm());
+ else
+ Main.protocol.sendPutURLDataCmd(jobid, url.toExternalForm());
+ connect_status = CONNECT_WAIT;
+ try {
+ wait(20000);
+ } catch (InterruptedException ie) {
+ errorcode = -1;
+ }
+ boolean isconnected = (connect_status == CONNECTED);
+ if (isconnected && !haveError()) {
+ if (doInput)
+ in = new KJASInputStream();
+ else
+ out = new KJASOutputStream();
+ Main.debug ("KIO connect(" + jobid + ") " + url);
+ return;
+ }
+ connect_status = NOT_CONNECTED;
+ jobs.remove(jobid);
+ if (isconnected) {
+ if (!finished)
+ Main.protocol.sendDataCmd(jobid, STOP);
+ Main.debug ("KIO connect error " + url);
+ throw new ConnectException("connection failed (not found)");
+ }
+ Main.debug ("KIO connect timeout " + url);
+ throw new IOException("connection failed (timeout)");
+ }
+ synchronized void disconnect() {
+ if (connect_status == NOT_CONNECTED)
+ return;
+ Main.debug ("KIO disconnect " + jobid);
+ //(new Exception()).printStackTrace();
+ if (out != null) {
+ try {
+ out.flush();
+ } catch (IOException iox) {}
+ }
+ connect_status = NOT_CONNECTED;
+ out = null;
+ in = null;
+ if (!finished) {
+ Main.protocol.sendDataCmd(jobid, STOP);
+ jobs.remove(jobid);
+ }
+ notifyAll();
+ }
+ InputStream getInputStream() throws IOException {
+ Main.debug ("KIO getInputStream(" + jobid + ") " + url);
+ return in;
+ }
+ OutputStream getOutputStream() throws IOException {
+ Main.debug ("KIO getOutputStream(" + jobid + ") " + url);
+ return out;
+ }
+}
+
+final class KIOHttpConnection extends KIOConnection
+{
+ final static int HEADERS = 3;
+ final static int REDIRECT = 4;
+ final static int MIMETYPE = 5;
+
+ Vector headers = new Vector();
+ Hashtable headersmap = new Hashtable();
+ String responseMessage = null;
+ int responseCode = -1;
+
+ KIOHttpConnection(URL u) {
+ super(u);
+ }
+ protected boolean haveError() {
+ return super.haveError() ||
+ responseCode != 404 && (responseCode < 0 || responseCode >= 400);
+ }
+ protected synchronized boolean setData(int code, byte [] d) {
+ switch (code) {
+ case HEADERS:
+ StringTokenizer tokenizer = new StringTokenizer(new String(d), "\n");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ int pos = token.indexOf(":");
+ String [] entry = {
+ token.substring(0, pos > -1 ? pos : token.length()).toLowerCase(), token.substring(pos > -1 ? pos+1: token.length()).trim()
+ };
+ headers.add(entry);
+ headersmap.put(entry[0], entry[1]);
+ // Main.debug ("KIO header " + entry[0] + "=" + entry[1]);
+ }
+ responseCode = 0;
+ if (headersmap.size() > 0) {
+ String token = ((String []) headers.get(0))[0];
+ if (!token.startsWith("http/1.")) break;
+ int spos = token.indexOf(' ');
+ if (spos < 0) break;
+ int epos = token.indexOf(' ', spos + 1);
+ if (epos < 0) break;
+ responseCode = Integer.parseInt(token.substring(spos+1, epos));
+ responseMessage = token.substring(epos+1);
+ Main.debug ("KIO responsecode=" + responseCode);
+ }
+ break;
+ }
+ return super.setData(code, d);
+ }
+}
+
+final class KIOSimpleConnection extends KIOConnection
+{
+ KIOSimpleConnection(URL u) {
+ super(u);
+ }
+}
+
+final class KJASHttpURLConnection extends HttpURLConnection
+{
+ private KIOHttpConnection kioconnection;
+
+ KJASHttpURLConnection(URL u) {
+ super(u);
+ kioconnection = new KIOHttpConnection(u);
+ }
+ public Map getHeaderFields() {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderFields");
+ return kioconnection.headersmap;
+ }
+ public String getHeaderField(String name) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ String field = (String) kioconnection.headersmap.get(name);
+ Main.debug ("KIO getHeaderField:" + name + "=" + field);
+ //(new Exception()).printStackTrace();
+ return field;
+ }
+ public String getHeaderField(int n) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderField(" + n + ") size=" + kioconnection.headersmap.size());
+ if (n >= kioconnection.headersmap.size())
+ return null;
+ String [] entry = (String []) kioconnection.headers.get(n);
+ String line = entry[0];
+ if (entry[1].length() > 0)
+ line += ":" + entry[1];
+ Main.debug ("KIO getHeaderField(" + n + ")=#" + line + "#");
+ return line;
+ }
+ public String getHeaderFieldKey(int n) {
+ try {
+ connect();
+ } catch (IOException e) {
+ Main.debug ("Error on implicit connect()");
+ }
+ Main.debug ("KIO getHeaderFieldKey " + n);
+ if (n >= kioconnection.headersmap.size())
+ return null;
+ return ((String []) kioconnection.headers.get(n))[0];
+ }
+ public int getResponseCode() throws IOException {
+ Main.debug ("KIO getResponseCode");
+ if (kioconnection.responseCode == -1) {
+ try {
+ connect();
+ } catch (IOException e) {
+ if (kioconnection.responseCode == -1)
+ throw e;
+ }
+ }
+ responseMessage = kioconnection.responseMessage;
+ return kioconnection.responseCode;
+ }
+ public boolean usingProxy() {
+ return false; // FIXME
+ }
+ public void connect() throws IOException {
+ if (connected)
+ return;
+ Main.debug ("KIO KJASHttpURLConnection.connect " + url);
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(getPermission());
+ kioconnection.connect(doInput);
+ connected = true;
+ if (kioconnection.responseCode == 404)
+ throw new FileNotFoundException(url.toExternalForm());
+ }
+ public void disconnect() {
+ kioconnection.disconnect();
+ connected = false;
+ }
+ public InputStream getInputStream() throws IOException {
+ doInput = true;
+ doOutput = false;
+ connect();
+ return kioconnection.getInputStream();
+ }
+ public OutputStream getOutputStream() throws IOException {
+ doInput = false;
+ doOutput = true;
+ connect();
+ return kioconnection.getOutputStream();
+ }
+ public InputStream getErrorStream() {
+ Main.debug("KIO KJASHttpURLConnection.getErrorStream" + url);
+ try {
+ if (connected && kioconnection.responseCode == 404)
+ return kioconnection.getInputStream();
+ } catch (Exception ex) {}
+ return null;
+ }
+}
+
+final class KJASSimpleURLConnection extends URLConnection
+{
+ private KIOSimpleConnection kioconnection = null;
+ private int default_port;
+
+ KJASSimpleURLConnection(URL u, int p) {
+ super(u);
+ default_port = p;
+ }
+ public boolean usingProxy() {
+ return false; // FIXME
+ }
+ public Permission getPermission() throws IOException {
+ int p = url.getPort();
+ if (p < 0)
+ p = default_port;
+ return new SocketPermission(url.getHost() + ":" + p, "connect");
+ }
+ public void connect() throws IOException {
+ if (kioconnection != null)
+ return;
+ Main.debug ("KIO KJASSimpleURLConnection.connection " + url);
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(getPermission());
+ kioconnection = new KIOSimpleConnection(url);
+ kioconnection.connect(doInput);
+ connected = true;
+ }
+ public void disconnect() {
+ if (kioconnection == null)
+ return;
+ kioconnection.disconnect();
+ kioconnection = null;
+ connected = false;
+ }
+ public InputStream getInputStream() throws IOException {
+ doInput = true;
+ doOutput = false;
+ if (kioconnection == null)
+ connect();
+ return kioconnection.getInputStream();
+ }
+ public OutputStream getOutputStream() throws IOException {
+ doInput = false;
+ doOutput = true;
+ if (kioconnection == null)
+ connect();
+ return kioconnection.getOutputStream();
+ }
+}
+
+
+final class KJASHttpURLStreamHandler extends URLStreamHandler
+{
+ KJASHttpURLStreamHandler(int port) {
+ default_port = port;
+ }
+ protected URLConnection openConnection(URL u) throws IOException {
+ URL url = new URL(u.toExternalForm());
+ return new KJASHttpURLConnection(url);
+ }
+ protected int getDefaultPort() {
+ return default_port;
+ }
+ private int default_port;
+}
+
+final class KJASSimpleURLStreamHandler extends URLStreamHandler
+{
+ KJASSimpleURLStreamHandler(int port) {
+ default_port = port;
+ }
+ protected URLConnection openConnection(URL u) throws IOException {
+ URL url = new URL(u.toExternalForm());
+ return new KJASSimpleURLConnection(url, default_port);
+ }
+ protected int getDefaultPort() {
+ return default_port;
+ }
+ private int default_port;
+}
+
+public final class KJASURLStreamHandlerFactory
+ implements URLStreamHandlerFactory
+{
+ public URLStreamHandler createURLStreamHandler(String protocol) {
+ if (protocol.equals("jar") || protocol.equals("file"))
+ return null;
+ //outputs to early: Main.debug ("createURLStreamHandler " + protocol);
+ Main.debug ("KIO createURLStreamHandler " + protocol);
+ if (protocol.equals("http"))
+ return new KJASHttpURLStreamHandler(80);
+ else if (protocol.equals("https"))
+ return new KJASHttpURLStreamHandler(443);
+ else if (protocol.equals("ftp"))
+ return new KJASSimpleURLStreamHandler(21);
+ else if (protocol.equals("smb"))
+ return new KJASSimpleURLStreamHandler(139);
+ else if (protocol.equals("fish"))
+ return new KJASSimpleURLStreamHandler(22);
+ return null;
+ }
+}
diff --git a/tdehtml/java/org/kde/kjas/server/Main.java b/tdehtml/java/org/kde/kjas/server/Main.java
new file mode 100644
index 000000000..50ccb14f1
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/Main.java
@@ -0,0 +1,178 @@
+package org.kde.kjas.server;
+
+import java.io.*;
+import java.security.*;
+import java.net.*;
+
+/**
+ * KJAS server recognizes these variablers:
+ * kjas.debug - makes server actions verbose
+ * kjas.showConsole - shows Java Console window
+ * kjas.log - save a transcript of the debug output to /tmp/kjas.log
+ */
+
+public class Main
+{
+ //We need to save a reference to the original stdout
+ //for sending messages back
+ static final KJASProtocolHandler protocol;
+ static Console console = null;
+ private static final boolean show_console;
+ public static final boolean Debug;
+ public static final boolean log;
+ static final boolean cacheImages;
+ static float java_version = (float) 0.0;
+ static String proxyHost = null;
+ static int proxyPort = 0;
+ private static boolean good_jdk = true;
+
+ /**************************************************************************
+ * Initialization
+ **************************************************************************/
+ static
+ {
+ Debug = System.getProperty( "kjas.debug" ) != null;
+
+ show_console = System.getProperty( "kjas.showConsole" ) != null;
+
+ if( System.getProperty( "kjas.useKio" ) != null )
+ URL.setURLStreamHandlerFactory( new KJASURLStreamHandlerFactory() );
+
+ log = System.getProperty( "kjas.log" ) != null;
+
+ cacheImages = System.getProperty( "kjas.noImageCache" ) != null;
+
+ // determine system proxy
+ proxyHost = System.getProperty( "http.proxyHost" );
+ String proxyPortString = System.getProperty( "http.proxyPort" );
+ try {
+ proxyPort = Integer.parseInt(proxyPortString);
+ } catch (Exception e) {
+ }
+ //Main.debug( "JVM version = " + System.getProperty( "java.version" ) );
+ String version = System.getProperty("java.version").substring( 0, 3 );
+ // Hack for SGI Java2 runtime
+ if (version == "Jav") { // Skip over JavaVM- (the first 7 chars)
+ version = System.getProperty("java.version").substring(7,3);
+ }
+ //Main.debug( "JVM numerical version = " + version );
+ try {
+ java_version = Float.parseFloat( version );
+ if( java_version < 1.2 )
+ good_jdk = false;
+ } catch( NumberFormatException e ) {
+ good_jdk = false;
+ }
+ PrintStream protocol_stdout = System.out;
+ console = new KJASSwingConsole();
+ protocol = new KJASProtocolHandler( System.in, protocol_stdout );
+ }
+
+ /**************************************************************************
+ * Public Utility functions available to the KJAS framework
+ **************************************************************************/
+ public static void debug( String msg )
+ {
+ if( Debug )
+ {
+ System.out.println( "KJAS: " + msg );
+ }
+ }
+ public static void info (String msg ) {
+ System.err.println( "KJAS: " + msg );
+ }
+
+ public static void kjas_err( String msg, Exception e )
+ {
+ System.err.println( msg );
+ System.err.println( "Backtrace: " );
+ e.printStackTrace();
+ }
+
+ public static void kjas_err( String msg, Throwable t )
+ {
+ System.err.println( msg );
+ t.printStackTrace();
+ }
+ private Main() {
+ }
+
+ /**************************************************************************
+ * Main- create the command loop
+ **************************************************************************/
+ public static void main( String[] args )
+ {
+ if( !good_jdk )
+ {
+ console.setVisible( true );
+ System.err.println( "ERROR: This version of Java is not supported for security reasons." );
+ System.err.println( "\t\tPlease use Java version 1.2 or higher." );
+ return;
+ }
+
+ if( show_console )
+ console.setVisible( true );
+
+ // set up https
+ boolean hasHTTPS = true;
+
+ try {
+ // https needs a secure socket provider
+ Provider[] sslProviders = Security.getProviders("SSLContext.SSL");
+
+ if (sslProviders == null || sslProviders.length == 0) {
+ // as a fallback, try to dynamically install Sun's jsse
+ Class provider = Class.forName("com.sun.net.ssl.internal.ssl.Provider");
+
+ if (provider != null) {
+ Main.debug("adding Security Provider");
+ Provider p = (Provider) provider.newInstance();
+ Security.addProvider(p);
+ } else {
+ // Try jessie (http://www.nongnu.org/jessie/) as a fallback
+ // available in the Free World
+ provider = Class.forName("org.metastatic.jessie.provider.Jessie");
+ if (provider != null) {
+ Main.debug("adding Jessie as Security Provider");
+ Provider p = (Provider) provider.newInstance();
+ Security.addProvider(p);
+ } else {
+ Main.debug("could not get class: com.sun.net.ssl.internal.ssl.Provider");
+ hasHTTPS = false;
+ }
+ }
+ }
+
+ if (hasHTTPS) {
+ // allow user to provide own protocol handler
+ // -Djava.protocol.handler.pkgs = user.package.name
+ // getting and setting of properties might generate SecurityExceptions
+ // so this needs to be in a try block
+ String handlerPkgs = System.getProperty("java.protocol.handler.pkgs");
+
+ if (handlerPkgs == null) {
+ // set default packages for Sun and IBM
+ handlerPkgs = "com.sun.net.ssl.internal.www.protocol" +
+ "|com.ibm.net.ssl.www.protocol";
+ } else {
+ // add default packages for Sun and IBM as fallback
+ handlerPkgs += "|com.sun.net.ssl.internal.www.protocol" +
+ "|com.ibm.net.ssl.www.protocol";
+ }
+
+ System.setProperty("java.protocol.handler.pkgs", handlerPkgs);
+ }
+ } catch (Exception e) {
+ hasHTTPS = false;
+ }
+
+ if (hasHTTPS == false) {
+ System.out.println("Unable to load JSSE SSL stream handler, https support not available");
+ System.out.println("For more information see http://java.sun.com/products/jsse/");
+ }
+
+ //start the command parsing
+ protocol.commandLoop();
+ }
+
+}
diff --git a/tdehtml/java/org/kde/kjas/server/StatusListener.java b/tdehtml/java/org/kde/kjas/server/StatusListener.java
new file mode 100644
index 000000000..be17c2b29
--- /dev/null
+++ b/tdehtml/java/org/kde/kjas/server/StatusListener.java
@@ -0,0 +1,5 @@
+package org.kde.kjas.server;
+
+public interface StatusListener {
+ public void showStatus(String message);
+} \ No newline at end of file
diff --git a/tdehtml/java/pluginsinfo b/tdehtml/java/pluginsinfo
new file mode 100644
index 000000000..7d37ed7c8
--- /dev/null
+++ b/tdehtml/java/pluginsinfo
@@ -0,0 +1,7 @@
+number=1
+
+[0]
+description=Java Plug-in KJAS for Konqueror
+file=kjavaappletviewer.so
+mime=application/x-java-applet:class:Java Applet;application/x-java-bean:jar:JavaBeans
+name=Java Plug-in
diff --git a/tdehtml/java/tests/Makefile.am b/tdehtml/java/tests/Makefile.am
new file mode 100644
index 000000000..55e6fc732
--- /dev/null
+++ b/tdehtml/java/tests/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/tdehtml/java -I$(top_srcdir)/tdehtml \
+ -I$(top_srcdir) $(all_includes)
+
+check_PROGRAMS = testserver
+
+testserver_SOURCES = testkjavaappletserver.cpp
+testserver_LDADD = ../libkjava.la
+
+METASOURCES = AUTO
diff --git a/tdehtml/java/tests/badapplets/BadApplet.jar b/tdehtml/java/tests/badapplets/BadApplet.jar
new file mode 100644
index 000000000..fc9c274a2
--- /dev/null
+++ b/tdehtml/java/tests/badapplets/BadApplet.jar
Binary files differ
diff --git a/tdehtml/java/tests/badapplets/BadApplet.java b/tdehtml/java/tests/badapplets/BadApplet.java
new file mode 100644
index 000000000..c8217d256
--- /dev/null
+++ b/tdehtml/java/tests/badapplets/BadApplet.java
@@ -0,0 +1,202 @@
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.*;
+import javax.swing.*;
+import java.io.*;
+import java.net.*;
+import java.awt.datatransfer.*;
+
+public class BadApplet extends JApplet {
+ JTabbedPane tabs = new JTabbedPane();
+ JPanel FileSystemTests = new JPanel();
+ JPanel NetworkTests = new JPanel();
+ JPanel EnvironmentTests = new JPanel();
+
+ JButton writeFileButton = new JButton("Write File");
+ JButton readFileButton = new JButton("Read File");
+ JButton connectSocketButton = new JButton("Connect Socket");
+ JButton frameButton = new JButton("Open Frame Without Warning Tag");
+ JButton readSystemPropButton = new JButton("Read System Property");
+ JButton printButton = new JButton("Print");
+ JButton clipBoardButton = new JButton("Read Clipboard");
+
+ JTextField writePath = new JTextField( "/amd/ns/root/home/sbarnes/test.txt" );
+ JTextField readPath = new JTextField("/amd/ns/root/home/sbarnes/test.txt");
+ JTextField url = new JTextField("URL");
+ JTextField port = new JTextField("port");
+ JTextField systemProp = new JTextField("os.name");
+ JTextField output = new JTextField();
+
+ //Construct the applet
+ public BadApplet() {
+ try {
+ //event handlers ******************************************************
+ writeFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ writeFileButton_actionPerformed(e);
+ }
+ });
+ readFileButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ readFileButton_actionPerformed(e);
+ }
+ });
+ connectSocketButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ connectSocketButton_actionPerformed(e);
+ }
+ });
+ frameButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ frameButton_actionPerformed(e);
+ }
+ });
+ readSystemPropButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ readSystemPropButton_actionPerformed(e);
+ }
+ });
+ printButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ printButton_actionPerformed(e);
+ }
+ });
+ clipBoardButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ clipBoard_actionPerformed(e);
+ }
+ });
+
+ //do layout ***********************************************************
+ getContentPane().setLayout( new BorderLayout() );
+
+ FileSystemTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ FileSystemTests.add( writeFileButton );
+ FileSystemTests.add( writePath );
+ FileSystemTests.add( readFileButton );
+ FileSystemTests.add( readPath );
+
+ NetworkTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ NetworkTests.add( connectSocketButton );
+ NetworkTests.add( url );
+ NetworkTests.add( port );
+
+ EnvironmentTests.setLayout( new FlowLayout( FlowLayout.LEFT ) );
+ EnvironmentTests.add( frameButton );
+ EnvironmentTests.add( readSystemPropButton );
+ EnvironmentTests.add( systemProp );
+ EnvironmentTests.add( printButton );
+ EnvironmentTests.add( clipBoardButton );
+
+ tabs.add( FileSystemTests, "File System" );
+ tabs.add( NetworkTests, "Network" );
+ tabs.add( EnvironmentTests, "Environment" );
+
+ this.getContentPane().add( tabs, BorderLayout.CENTER );
+ this.getContentPane().add( output, BorderLayout.SOUTH );
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void paint( Graphics g )
+ {
+ System.out.println( "graphics g = " + g );
+ System.out.println( "clip area = " + g.getClip() );
+ System.out.println( "bounds of the clip area = " + g.getClipBounds() );
+
+ super.paint( g );
+ }
+
+ //Initialize the applet
+ public void init() {}
+
+ void writeFileButton_actionPerformed(ActionEvent e) {
+ try{
+ PrintWriter writer = new PrintWriter(new FileOutputStream(writePath.getText()));
+ writer.println("Here is some text");
+ writer.close();
+ output.setText("Write was successful");
+ } catch (Exception ex){output.setText(ex.getMessage());}
+ }
+
+ void readSystemPropButton_actionPerformed(ActionEvent e) {
+ try{
+ output.setText(System.getProperty(systemProp.getText()));
+ } catch (Exception ex){output.setText("Error getting prop: " + ex.getMessage());}
+ }
+
+ void readFileButton_actionPerformed(ActionEvent e) {
+ try{
+ BufferedReader reader = new BufferedReader(new FileReader(readPath.getText()));
+ output.setText("Read was successful: " + reader.readLine());
+ } catch (Exception ex){output.setText(ex.getMessage());}
+ }
+
+ void connectSocketButton_actionPerformed(ActionEvent e) {
+ try{
+ Integer thePort = new Integer(port.getText());
+ Socket socket = new Socket(url.getText(), thePort.intValue());
+ socket.getOutputStream();
+ output.setText("Socket connection successful");
+ } catch (Exception ex){output.setText("Socket unsuccessfull: " + ex.getMessage());}
+ }
+
+ void frameButton_actionPerformed(ActionEvent e) {
+ JFrame frame = new JFrame("Does this Frame have a warning sign");
+ frame.setSize(200,200);
+ frame.show();
+ if (frame.getWarningString() == null)
+ output.setText("No warning string in frame");
+ else
+ output.setText(frame.getWarningString());
+ }
+
+ void clipBoard_actionPerformed(ActionEvent e) {
+ try {
+ Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
+
+ Transferable trans = clip.getContents(null);
+ if (trans == null){
+ output.setText("Clipboard is empty");
+ return;
+ }
+ output.setText((String)trans.getTransferData(DataFlavor.stringFlavor));
+ }catch(Exception ex){ex.getMessage();}
+ }
+
+ void printButton_actionPerformed(ActionEvent e) {
+ try{
+ JFrame testFrame = new JFrame("test");
+ testFrame.getContentPane().add(this, BorderLayout.CENTER);
+ PrintJob printer = Toolkit.getDefaultToolkit().getPrintJob(testFrame, "Applet Print Test", null);
+
+ if (printer == null){
+ output.setText("PrintJob is null");
+ return;
+ }
+
+ Graphics g = printer.getGraphics();
+ g.drawString("This is the applet print test", 50, 50);
+ g.dispose();
+ printer.end();
+ }catch(Exception ex){ex.getMessage();}
+ }
+
+ //Main method
+ public static void main(String[] args) {
+ BadApplet applet = new BadApplet();
+
+ JFrame frame = new JFrame();
+ frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
+ frame.setTitle("Applet Frame");
+ frame.getContentPane().add(applet, BorderLayout.CENTER);
+ frame.setSize(400,320);
+ frame.setVisible(true);
+
+ applet.init();
+ applet.start();
+ }
+
+}
diff --git a/tdehtml/java/tests/badapplets/applet.html b/tdehtml/java/tests/badapplets/applet.html
new file mode 100644
index 000000000..fe9e47ef9
--- /dev/null
+++ b/tdehtml/java/tests/badapplets/applet.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>SwingSet demo</title>
+ </head>
+
+ <body>
+ <h1>SwingSet demo</h1>
+ <applet code=BadApplet.class
+ archive="BadApplet.jar"
+ width=695 height=525>
+ </applet>
+ </body>
+</html>
diff --git a/tdehtml/java/tests/good_sites b/tdehtml/java/tests/good_sites
new file mode 100644
index 000000000..f9699fe2a
--- /dev/null
+++ b/tdehtml/java/tests/good_sites
@@ -0,0 +1,44 @@
+http Sites
+---------------------------------------------------------
+http://java.sun.com/products/plugin/1.3.1_01a/demos/applets.html
+www.soda.co.uk
+java.sun.com
+www.javaboutique.com
+www.teledyn.com/fun/SaubleBeach (redraw problems, also in netscape)
+www.fxapplets.com
+www.quote.com/quotecom/livecharts/
+games.yahoo.com/games/klondike.html (security exception)
+www.webtrac.co.za/cgi-bin/demo/demo.pl (classloader problem)
+www.sodaplay.com/constructor/player.htm
+www.sodaplay.com
+www.dseffects.com/applets.html
+www.controlzed.com
+javaboutique.internet.com/Durius/
+www.chess.net/play/java
+www.kmelektronik.de/root/index.html
+rdufour.mytradecenter.com/applets/Tetris/Tetris.html
+http://www.shiatsu-austria.at
+
+currently unavailable:
+----------------------
+screening.nasdaq.com/screening/NASDAQSearch.asp
+
+unavailable:
+------------
+www.indegocomputer.de
+http://aktien.onvista.de/risk-return-map/
+
+https Sites
+---------------------------------------------------------
+https://brokerage-m3.consors.de/ConSors/
+https://homebanking.dvg-ka.de/045/index.html
+https://spk-ihb.izb-hb.de/SPK_Deggendorf/index.html
+https://www3.genodirekt.de/homebank.nsf/(rzbks)/xxq1050x?OpenDocument
+https://banking.sonline.de/kreissparkasse-duesseldorf/
+
+Security Test Sites
+---------------------------------------------------------
+http://java.sun.com/sfaq/#examples
+http://www.heise.de/ct/browsercheck/java.shtml
+http://www.heise.de/ct/browsercheck/n4demo1.shtml
+
diff --git a/tdehtml/java/tests/testkjavaappletserver.cpp b/tdehtml/java/tests/testkjavaappletserver.cpp
new file mode 100644
index 000000000..ea8a7656b
--- /dev/null
+++ b/tdehtml/java/tests/testkjavaappletserver.cpp
@@ -0,0 +1,41 @@
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <tqstring.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "java/kjavaappletserver.h"
+#include "java/kjavaapplet.h"
+#include "java/kjavaappletwidget.h"
+
+static KCmdLineOptions options[] =
+{
+ { "+[tdelibs_path]", "path to tdelibs directory", 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char **argv)
+{
+ TDECmdLineArgs::init( argc, argv, "testKJASSever", "testKJASServer", "test program", "0.0" );
+
+ TDECmdLineArgs::addCmdLineOptions( options );
+
+ TDEApplication app;
+
+ TQString path_to_tdelibs = "/build/wynnw/kde-src";
+
+ KJavaAppletWidget *a = new KJavaAppletWidget;
+
+ a->show();
+
+ a->applet()->setBaseURL( "file:" + path_to_tdelibs + "/tdelibs/tdehtml/test/" );
+ a->applet()->setAppletName( "Lake" );
+ a->applet()->setAppletClass( "lake.class" );
+ a->applet()->setParameter( "image", "konqi.gif" );
+
+ a->showApplet();
+ a->applet()->start();
+
+ app.exec();
+}
diff --git a/tdehtml/kjserrordlg.ui b/tdehtml/kjserrordlg.ui
new file mode 100644
index 000000000..d5e9c7e28
--- /dev/null
+++ b/tdehtml/kjserrordlg.ui
@@ -0,0 +1,133 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KJSErrorDlg</class>
+<author>George Staikos &lt;staikos@kde.org&gt;</author>
+<widget class="TQDialog">
+ <property name="name">
+ <cstring>KJSErrorDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>484</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>JavaScript Errors</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This dialog provides you with notification and details of scripting errors that occur on web pages. In many cases it is due to an error in the web site as designed by its author. In other cases it is the result of a programming error in Konqueror. If you suspect the former, please contact the webmaster of the site in question. Conversely if you suspect an error in Konqueror, please file a bug report at http://bugs.kde.org/. A test case which illustrates the problem will be appreciated.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton" row="4" column="2">
+ <property name="name">
+ <cstring>_close</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Close</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="4" column="1">
+ <property name="name">
+ <cstring>_clear</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;lear</string>
+ </property>
+ </widget>
+ <widget class="Line" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <spacer row="3" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>311</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQTextBrowser" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>_errorText</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ </widget>
+ <widget class="KSqueezedTextLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>_url</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>_clear</sender>
+ <signal>clicked()</signal>
+ <receiver>_errorText</receiver>
+ <slot>clear()</slot>
+ </connection>
+ <connection>
+ <sender>_close</sender>
+ <signal>clicked()</signal>
+ <receiver>KJSErrorDlg</receiver>
+ <slot>hide()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>_errorText</tabstop>
+ <tabstop>_close</tabstop>
+ <tabstop>_clear</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kdialog.h</include>
+ <include location="global" impldecl="in declaration">ksqueezedtextlabel.h</include>
+</includes>
+<Q_SLOTS>
+ <slot>init()</slot>
+ <slot>addError( const TQString &amp; error )</slot>
+ <slot>setURL( const TQString &amp; url )</slot>
+ <slot>clear()</slot>
+</Q_SLOTS>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kactivelabel.h</includehint>
+</includehints>
+</UI>
diff --git a/tdehtml/kjserrordlg.ui.h b/tdehtml/kjserrordlg.ui.h
new file mode 100644
index 000000000..50b73568e
--- /dev/null
+++ b/tdehtml/kjserrordlg.ui.h
@@ -0,0 +1,32 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void KJSErrorDlg::init()
+{
+ _errorText->setTextFormat(TQTextEdit::LogText);
+ _errorText->setMaxLogLines(2048);//Limit to about 2K errors so we don't use much CPU
+}
+
+void KJSErrorDlg::addError( const TQString & error )
+{
+
+ _errorText->append(error);
+}
+
+void KJSErrorDlg::setURL( const TQString & url )
+{
+ _url->setText(url);
+}
+
+void KJSErrorDlg::clear()
+{
+ _errorText->clear();
+ init();
+}
diff --git a/tdehtml/libtdehtml.map b/tdehtml/libtdehtml.map
new file mode 100644
index 000000000..7ffe30238
--- /dev/null
+++ b/tdehtml/libtdehtml.map
@@ -0,0 +1,22 @@
+{
+ local:
+ extern "C++" {
+ kjs_html_init;
+ getTagName*;
+ getAttrName*;
+ getValueName*;
+ getPropertyName*;
+ cssyyparse*;
+ KJPEGFormat::*;
+ DOM::tagPriority;
+ DOM::getPropertyID*;
+ DOM::*Impl::*;
+ KJS::*;
+ Q*KJS::*;
+ typeinfo*KJS::*;
+ vtable*KJS::*;
+ KJSProxy*;
+ KJSCPUGuard*;
+ tdehtml::*
+ };
+};
diff --git a/tdehtml/misc/CMakeLists.txt b/tdehtml/misc/CMakeLists.txt
new file mode 100644
index 000000000..da1f0dfd3
--- /dev/null
+++ b/tdehtml/misc/CMakeLists.txt
@@ -0,0 +1,41 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/tdeutils
+ ${CMAKE_SOURCE_DIR}/kio/kfile
+)
+
+
+##### tdehtmlmisc-static ###########################
+
+set( target tdehtmlmisc )
+
+set( ${target}_SRCS
+ decoder.cpp loader.cpp loader_jpeg.cpp guess_ja.cpp
+ htmlhashes.cpp helper.cpp arena.cpp stringit.cpp
+ knsplugininstaller.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
diff --git a/tdehtml/misc/Makefile.am b/tdehtml/misc/Makefile.am
new file mode 100644
index 000000000..670fd5a1f
--- /dev/null
+++ b/tdehtml/misc/Makefile.am
@@ -0,0 +1,43 @@
+# 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 = libtdehtmlmisc.la
+libtdehtmlmisc_la_SOURCES = \
+ decoder.cpp loader.cpp loader_jpeg.cpp guess_ja.cpp\
+ htmlhashes.cpp helper.cpp arena.cpp stringit.cpp knsplugininstaller.cpp
+libtdehtmlmisc_la_LIBADD = $(LIBJPEG)
+libtdehtmlmisc_la_LDFLAGS = $(USER_LDFLAGS)
+libtdehtmlmisc_la_METASOURCES = AUTO
+
+noinst_HEADERS = \
+ decoder.h tdehtmllayout.h loader_jpeg.h loader.h guess_ja.h\
+ stringit.h htmlhashes.h helper.h shared.h arena.h knsplugininstaller.h
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/dcop -I$(top_srcdir)/kio -I$(top_srcdir)/libltdl \
+ -I$(top_srcdir)/tdehtml -I$(top_srcdir)/tdeutils $(all_includes)
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) tdecore -lqt
+
diff --git a/tdehtml/misc/arena.cpp b/tdehtml/misc/arena.cpp
new file mode 100644
index 000000000..cfbce24ab
--- /dev/null
+++ b/tdehtml/misc/arena.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Nick Blievers <nickb@adacel.com.au>
+ * Jeff Hostetler <jeff@nerdone.com>
+ * Tom Rini <trini@kernel.crashing.org>
+ * Raffaele Sena <raff@netwinder.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <kglobal.h>
+#include "arena.h"
+
+#ifdef HAVE_GETPAGESIZE
+#include <unistd.h>
+#define POOL_SIZE kMax(8192u, 2*( unsigned ) getpagesize())
+#else
+#define POOL_SIZE 8192
+#endif
+
+//#define DEBUG_ARENA_MALLOC
+#ifdef DEBUG_ARENA_MALLOC
+#include <assert.h>
+#include <stdio.h>
+#endif
+
+namespace tdehtml {
+
+#ifdef DEBUG_ARENA_MALLOC
+static int i = 0;
+#endif
+
+#define FREELIST_MAX 50
+#define LARGE_ALLOCATION_CEIL(pool) (pool)->arenasize * 256
+#define MAX_DISCRETE_ALLOCATION(pool) (pool)->arenasize * 32
+static Arena *arena_freelist = 0;
+static int freelist_count = 0;
+
+#define ARENA_DEFAULT_ALIGN sizeof(double)
+#define BIT(n) ((unsigned int)1 << (n))
+#define BITMASK(n) (BIT(n) - 1)
+#define CEILING_LOG2(_log2,_n) \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1;
+
+int CeilingLog2(unsigned int i) {
+ int log2;
+ CEILING_LOG2(log2,i);
+ return log2;
+}
+
+void InitArenaPool(ArenaPool *pool, const char* /*name*/,
+ unsigned int /*size*/, unsigned int align)
+{
+ unsigned int size = POOL_SIZE;
+ if (align == 0)
+ align = ARENA_DEFAULT_ALIGN;
+ pool->mask = BITMASK(CeilingLog2(align));
+ pool->first.next = NULL;
+ pool->first.base = pool->first.avail = pool->first.limit =
+ (uword)ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+ pool->largealloc = LARGE_ALLOCATION_CEIL(pool);
+ pool->cumul = 0;
+}
+
+
+/*
+ ** ArenaAllocate() -- allocate space from an arena pool
+ **
+ ** Description: ArenaAllocate() allocates space from an arena
+ ** pool.
+ **
+ ** First try to satisfy the request from arenas starting at
+ ** pool->current.
+ **
+ ** If there is not enough space in the arena pool->current, try
+ ** to claim an arena, on a first fit basis, from the global
+ ** freelist (arena_freelist).
+ **
+ ** If no arena in arena_freelist is suitable, then try to
+ ** allocate a new arena from the heap.
+ **
+ ** Returns: pointer to allocated space or NULL
+ **
+ */
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
+{
+ Arena *a;
+ char *rp; /* returned pointer */
+
+#ifdef DEBUG_ARENA_MALLOC
+ assert((nb & pool->mask) == 0);
+#endif
+
+ nb = (uword)ARENA_ALIGN(pool, nb); /* force alignment */
+
+ /* attempt to allocate from arenas at pool->current */
+ {
+ a = pool->current;
+ do {
+ if ( a->avail +nb <= a->limit ) {
+ pool->current = a;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+ return rp;
+ }
+ } while( NULL != (a = a->next) );
+ }
+
+ /* attempt to allocate from arena_freelist */
+ {
+ Arena *p; /* previous pointer, for unlinking from freelist */
+
+ for ( a = p = arena_freelist; a != NULL ; p = a, a = a->next ) {
+ if ( a->base +nb <= a->limit ) {
+ if ( p == arena_freelist )
+ arena_freelist = a->next;
+ else
+ p->next = a->next;
+ a->avail = a->base;
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( 0 == pool->first.next )
+ pool->first.next = a;
+ freelist_count--;
+ return(rp);
+ }
+ }
+ }
+
+ /* attempt to allocate from the heap */
+ {
+ unsigned int sz;
+#ifdef HAVE_MMAP
+ if (pool->cumul > pool->largealloc) {
+ // High memory pressure. Switch to a fractional allocation strategy
+ // so that malloc gets a chance to successfully trim us down when it's over.
+ sz = kMin(pool->cumul/25, MAX_DISCRETE_ALLOCATION(pool));
+ } else
+#endif
+ sz = pool->arenasize > nb ? pool->arenasize : nb;
+ sz += sizeof *a + pool->mask; /* header and alignment slop */
+ pool->cumul += sz;
+#ifdef DEBUG_ARENA_MALLOC
+ i++;
+ printf("Malloc: %d\n", i);
+#endif
+ a = (Arena*)malloc(sz);
+ if (a) {
+ a->limit = (uword)a + sz;
+ a->base = a->avail = (uword)ARENA_ALIGN(pool, a + 1);
+ VALGRIND_CREATE_MEMPOOL(a->base, 0, 0);
+ rp = (char *)a->avail;
+ a->avail += nb;
+ VALGRIND_MEMPOOL_ALLOC(a->base, rp, nb);
+
+ /* the newly allocated arena is linked after pool->current
+ * and becomes pool->current */
+ a->next = pool->current->next;
+ pool->current->next = a;
+ pool->current = a;
+ if ( !pool->first.next )
+ pool->first.next = a;
+ return(rp);
+ }
+ }
+
+ /* we got to here, and there's no memory to allocate */
+ return(0);
+} /* --- end ArenaAllocate() --- */
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
+{
+ Arena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG_ARENA_MALLOC
+ do {
+ assert(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ CLEAR_UNUSED(a);
+ } while ((a = a->next) != 0);
+ a = *ap;
+#endif
+
+ if (freelist_count >= FREELIST_MAX)
+ reallyFree = true;
+
+ if (reallyFree) {
+ do {
+ *ap = a->next;
+ VALGRIND_DESTROY_MEMPOOL(a->base);
+ CLEAR_ARENA(a);
+#ifdef DEBUG_ARENA_MALLOC
+ if (a) {
+ i--;
+ printf("Free: %d\n", i);
+ }
+#endif
+ free(a); a = 0;
+ } while ((a = *ap) != 0);
+ } else {
+ /* Insert as much of the arena chain as we can hold at the front of the freelist. */
+ do {
+ ap = &(*ap)->next;
+ freelist_count++;
+ } while (*ap && freelist_count < FREELIST_MAX);
+
+ /* Get rid of excess */
+ if (*ap) {
+ Arena *xa, *n;
+ for (xa = *ap; xa; xa = n) {
+ VALGRIND_DESTROY_MEMPOOL(xa->base);
+ n = xa->next;
+#ifdef DEBUG_ARENA_MALLOC
+ i--;
+ printf("Free: %d\n", i);
+#endif
+ CLEAR_ARENA(xa);
+ free(xa);
+ }
+ }
+ *ap = arena_freelist;
+ arena_freelist = a;
+ head->next = 0;
+ }
+ pool->current = head;
+}
+
+void ArenaRelease(ArenaPool *pool, char *mark)
+{
+ Arena *a;
+
+ for (a = pool->first.next; a; a = a->next) {
+ if (UPTRDIFF(mark, a->base) < UPTRDIFF(a->avail, a->base)) {
+ a->avail = (uword)ARENA_ALIGN(pool, mark);
+ FreeArenaList(pool, a, false);
+ return;
+ }
+ }
+}
+
+void FreeArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, false);
+}
+
+void FinishArenaPool(ArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first, true);
+}
+
+void ArenaFinish()
+{
+ Arena *a, *next;
+#ifdef DEBUG_ARENA_MALLOC
+ printf("releasing global Arena freelist\n");
+#endif
+ for (a = arena_freelist; a; a = next) {
+ next = a->next;
+ free(a); a = 0;
+ }
+ freelist_count = 0;
+ arena_freelist = NULL;
+}
+
+} // namespace
diff --git a/tdehtml/misc/arena.h b/tdehtml/misc/arena.h
new file mode 100644
index 000000000..1f9a1e69d
--- /dev/null
+++ b/tdehtml/misc/arena.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 1998-2000 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Nick Blievers <nickb@adacel.com.au>
+ * Jeff Hostetler <jeff@nerdone.com>
+ * Tom Rini <trini@kernel.crashing.org>
+ * Raffaele Sena <raff@netwinder.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef ARENA_H
+#define ARENA_H
+
+
+#if defined(HAVE_VALGRIND_MEMCHECK_H) && !defined(NDEBUG)
+
+#include <valgrind/memcheck.h>
+#define VALGRIND_SUPPORT
+
+#else
+
+#define VALGRIND_CREATE_MEMPOOL(base, redZone, zeroed)
+#define VALGRIND_DESTROY_MEMPOOL(base)
+#define VALGRIND_MEMPOOL_ALLOC(base, addr, size)
+#define VALGRIND_MEMPOOL_FREE(base, addr)
+
+#endif
+
+
+#define ARENA_ALIGN_MASK 3
+
+typedef unsigned long uword;
+
+namespace tdehtml {
+
+struct Arena {
+ Arena* next; // next arena
+ uword base; // aligned base address
+ uword limit; // end of arena (1+last byte)
+ uword avail; // points to next available byte in arena
+};
+
+struct ArenaPool {
+ Arena first; // first arena in pool list.
+ Arena* current; // current arena.
+ unsigned int arenasize;
+ unsigned int largealloc; // threshold for fractional allocation strategy
+ unsigned int cumul; // total bytes in pool.
+ uword mask; // Mask (power-of-2 - 1)
+};
+
+void InitArenaPool(ArenaPool *pool, const char *name,
+ unsigned int size, unsigned int align);
+void FinishArenaPool(ArenaPool *pool);
+void FreeArenaPool(ArenaPool *pool);
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
+void ArenaFinish(void);
+
+#define ARENA_ALIGN(pool, n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK)
+#define INIT_ARENA_POOL(pool, name, size) \
+ InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
+
+#define ARENA_ALLOCATE(p, pool, nb) \
+ Arena *_a = (pool)->current; \
+ unsigned int _nb = ARENA_ALIGN(pool, nb); \
+ uword _p = _a->avail; \
+ uword _q = _p + _nb; \
+ if (_q > _a->limit) \
+ _p = (uword)ArenaAllocate(pool, _nb); \
+ else { \
+ VALGRIND_MEMPOOL_ALLOC(_a->base, p, nb); \
+ _a->avail = _q; \
+ } \
+ p = (void *)_p;
+
+
+#define ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q))
+
+#ifdef DEBUG
+#define FREE_PATTERN 0xDA
+#define CLEAR_UNUSED(a) (assert((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define CLEAR_ARENA(a) memset((void*)(a), FREE_PATTERN, \
+ (a)->limit - (uword)(a))
+#else
+#define CLEAR_UNUSED(a)
+#define CLEAR_ARENA(a)
+#endif
+
+
+} // namespace
+
+#endif
diff --git a/tdehtml/misc/blocked_icon.cpp b/tdehtml/misc/blocked_icon.cpp
new file mode 100644
index 000000000..4136cd9cf
--- /dev/null
+++ b/tdehtml/misc/blocked_icon.cpp
@@ -0,0 +1,41 @@
+static const unsigned int blocked_icon_len = 599;
+
+static const unsigned char blocked_icon_data[] = {
+0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
+0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x08,0x06,0x00,0x00,0x00,0xaa,0x69,0x71,
+0xde,0x00,0x00,0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff,0xa0,
+0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,
+0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x01,0xf7,0x49,0x44,0x41,0x54,
+0x78,0xda,0xed,0x9b,0xd1,0x8e,0x84,0x30,0x08,0x45,0x07,0xb2,0x3f,0x36,0x5f,0xbe,
+0x9f,0xc6,0x3e,0xb9,0x31,0xc6,0x28,0x70,0x01,0x21,0xd5,0xe7,0xc9,0x94,0x73,0x4a,
+0x5b,0xac,0x2d,0x89,0xc8,0x67,0xe5,0x87,0x3f,0x8b,0x3f,0xcb,0x0b,0xf8,0xa9,0x6c,
+0x8c,0x88,0x7e,0xb5,0xbf,0x15,0x91,0x6f,0x49,0x4c,0x99,0x73,0xc0,0x11,0xd8,0xd2,
+0x12,0x15,0x09,0x49,0x11,0xb0,0x81,0x47,0xfe,0x33,0x25,0x89,0x08,0x15,0x90,0x01,
+0x9e,0x2d,0x22,0x44,0x40,0x05,0x78,0x96,0x08,0x48,0xc0,0x13,0xe0,0xd1,0x22,0x78,
+0x32,0xfc,0xbe,0x7d,0xcb,0x0a,0x03,0x0b,0x20,0xa2,0x5f,0x69,0x00,0xbf,0x97,0x20,
+0x4e,0x09,0xe6,0x21,0xb0,0xc1,0xa3,0x29,0xab,0xe9,0x55,0xef,0xff,0x5b,0x86,0x83,
+0x49,0x80,0x17,0x9e,0x8c,0xeb,0xf9,0xbe,0x27,0x25,0x59,0x82,0x5a,0x80,0x15,0xde,
+0x0a,0x1d,0x2d,0x43,0x2b,0x41,0x25,0xc0,0x0b,0x1f,0x59,0xb4,0x78,0xb2,0x4f,0x23,
+0xe1,0x56,0x80,0x65,0xb6,0x4f,0xab,0xd6,0xc0,0xa1,0x77,0x15,0x8f,0x6a,0x15,0x98,
+0x08,0xaf,0x8d,0x9b,0x23,0x1a,0xef,0x08,0xbf,0x97,0x70,0xb5,0x3c,0xc2,0xfb,0x01,
+0x9d,0xe1,0xa1,0x42,0x48,0x13,0xc0,0x14,0xf8,0xab,0x2c,0x80,0x33,0xa0,0x03,0x3c,
+0x45,0x67,0x80,0xb6,0xf7,0xbb,0xc0,0x8b,0xc8,0x97,0x9c,0x59,0xc0,0xc8,0xb8,0xef,
+0x02,0x8f,0xc4,0xc5,0xde,0x40,0xba,0x15,0x39,0x9a,0x78,0xce,0xb2,0xe0,0xf1,0x5d,
+0xe1,0xac,0x0a,0x2f,0xed,0x75,0x38,0xb2,0xf1,0x68,0x78,0xcd,0x5c,0x10,0xbe,0x0a,
+0x4c,0xed,0xf9,0x53,0x01,0x55,0xc5,0xc7,0x93,0xf0,0xc7,0x79,0x80,0xab,0x83,0xc8,
+0x86,0xb7,0x0e,0x03,0x5e,0x31,0xed,0x1f,0x11,0xd0,0x11,0xbe,0x4c,0x40,0x57,0xf8,
+0x12,0x01,0x9d,0xe1,0xd3,0x05,0x74,0x87,0x4f,0x15,0x30,0x01,0x3e,0x4d,0xc0,0x14,
+0xf8,0x14,0x01,0x93,0xe0,0xcd,0x02,0xee,0xf6,0xd7,0x3a,0xc0,0x5b,0x63,0x60,0xf4,
+0x65,0x62,0x5a,0xcf,0x1f,0xdb,0xe4,0x15,0xd3,0x1e,0x9a,0x03,0x8e,0xc3,0xa0,0x13,
+0xbc,0x27,0x16,0x5e,0xb5,0xe7,0xff,0xe3,0x39,0xfb,0x34,0x76,0x07,0x46,0xbb,0x6c,
+0xe8,0x02,0xaf,0xf9,0x84,0x77,0xd6,0xbe,0xeb,0x9c,0x60,0xf6,0x27,0x6b,0xe4,0x5d,
+0x3f,0x64,0x0e,0x40,0x56,0x83,0x27,0xe0,0x91,0x6d,0xfc,0xfc,0x97,0xa1,0x02,0xf8,
+0x94,0x55,0x20,0x22,0x0b,0xaa,0xe0,0x91,0x8f,0x38,0x3c,0xbd,0xe7,0xd1,0x3d,0xcc,
+0x4b,0x01,0xde,0x2c,0xe8,0x04,0x7f,0x17,0x0b,0x6b,0x81,0xa6,0xc2,0xbb,0xea,0x00,
+0xb4,0xe0,0xc9,0x3a,0x23,0x64,0x4d,0xf9,0x90,0x33,0x42,0xa8,0x04,0x54,0x44,0x8b,
+0x53,0x62,0x48,0xe9,0xeb,0x91,0xd1,0xf2,0x9c,0x20,0x2a,0xc1,0x32,0x2e,0xdb,0x9e,
+0x14,0x8d,0x92,0xd0,0x69,0xe9,0x75,0xd5,0x01,0xdb,0xf2,0x48,0x8d,0xc0,0xbd,0xab,
+0x8f,0xbb,0x10,0xda,0x1a,0xa3,0x06,0xf0,0xc8,0x44,0xfb,0xde,0x18,0x79,0xef,0x0c,
+0xbd,0xb7,0xc6,0xde,0x7b,0x83,0x75,0xe3,0x76,0xb5,0x9b,0xa3,0x13,0x9e,0xe5,0x2f,
+0x4f,0xff,0x01,0x14,0x87,0xe1,0xb6,0x01,0xbb,0x79,0x86,0x00,0x00,0x00,0x00,0x49,
+0x45,0x4e,0x44,0xae,0x42,0x60,0x82};
diff --git a/tdehtml/misc/blocked_icon.png b/tdehtml/misc/blocked_icon.png
new file mode 100644
index 000000000..0f545c393
--- /dev/null
+++ b/tdehtml/misc/blocked_icon.png
Binary files differ
diff --git a/tdehtml/misc/decoder.cpp b/tdehtml/misc/decoder.cpp
new file mode 100644
index 000000000..6000aa9cf
--- /dev/null
+++ b/tdehtml/misc/decoder.cpp
@@ -0,0 +1,790 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
+ Copyright (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 -- decoder for input stream
+
+#undef DECODE_DEBUG
+//#define DECODE_DEBUG
+
+#include <assert.h>
+
+#include "decoder.h"
+#include "guess_ja.h"
+
+using namespace tdehtml;
+
+#include "htmlhashes.h"
+
+#include <tqregexp.h>
+#include <tqtextcodec.h>
+
+#include <kglobal.h>
+#include <kcharsets.h>
+
+#include <ctype.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+
+
+Decoder::Decoder()
+{
+ // latin1
+ m_codec = TQTextCodec::codecForMib(4);
+ m_decoder = m_codec->makeDecoder();
+ enc = 0;
+ m_type = DefaultEncoding;
+ body = false;
+ beginning = true;
+ visualRTL = false;
+ m_autoDetectLanguage = SemiautomaticDetection;
+ kc = NULL;
+}
+
+Decoder::~Decoder()
+{
+ delete m_decoder;
+ if (kc)
+ delete kc;
+}
+
+void Decoder::setEncoding(const char *_encoding, EncodingType type)
+{
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "setEncoding " << _encoding << " " << type << endl;
+#endif
+ enc = _encoding;
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "old encoding is:" << m_codec->name() << endl;
+#endif
+ enc = enc.lower();
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "requesting:" << enc << endl;
+#endif
+ if(enc.isNull() || enc.isEmpty())
+ return;
+
+#ifdef APPLE_CHANGES
+ TQTextCodec *codec = (type == EncodingFromMetaTag || type == EncodingFromXMLHeader)
+ ? TQTextCodec::codecForNameEightBitOnly(enc)
+ : TQTextCodec::codecForName(enc);
+ if (codec) {
+ enc = codec->name();
+ visualRTL = codec->usesVisualOrdering();
+ }
+#else
+ if(enc == "visual") // hebrew visually ordered
+ enc = "iso8859-8";
+ bool b;
+ TQTextCodec *codec = TDEGlobal::charsets()->codecForName(enc, b);
+ if (!b)
+ codec = 0;
+
+ if (type == EncodingFromMetaTag || type == EncodingFromXMLHeader) {
+ //Sometimes the codec specified is absurd, i.e. UTF-16 despite
+ //us decoding a meta tag as ASCII. In that case, ignore it.
+ if (codec &&
+ (codec->mibEnum() == 1000)) //UTF16 or similar.
+ codec = 0;
+ }
+
+ if (codec && codec->mibEnum() == 11) {
+ //We do NOT want to use Qt's TQHebrewCodec, since it tries to reorder itself.
+ codec = TQTextCodec::codecForName("iso8859-8-i");
+
+ // visually ordered unless one of the following
+ if( !(enc == "iso-8859-8-i" || enc == "iso_8859-8-i"
+ || enc == "csiso88598i" || enc == "logical") )
+ visualRTL = true;
+ }
+#endif
+
+ if( codec ) { // in case the codec didn't exist, we keep the old one (fixes some sites specifying invalid codecs)
+ m_codec = codec;
+ m_type = type;
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ }
+
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "Decoder::encoding used is" << m_codec->name() << endl;
+#endif
+}
+
+const char *Decoder::encoding() const
+{
+ return enc;
+}
+
+// Other browsers allow comments in the head section, so we need to also.
+// It's important not to look for tags inside the comments.
+static void skipComment(const char *&ptr, const char *pEnd)
+{
+ const char *p = ptr;
+ // Allow <!-->; other browsers do.
+ if (*p == '>') {
+ p++;
+ } else {
+ while (p != pEnd) {
+ if (*p == '-') {
+ // This is the real end of comment, "-->".
+ if (p[1] == '-' && p[2] == '>') {
+ p += 3;
+ break;
+ }
+ // This is the incorrect end of comment that other browsers allow, "--!>".
+ if (p[1] == '-' && p[2] == '!' && p[3] == '>') {
+ p += 4;
+ break;
+ }
+ }
+ p++;
+ }
+ }
+ ptr = p;
+}
+
+// Returns the position of the encoding string.
+static int findXMLEncoding(const TQCString &str, int &encodingLength)
+{
+ int len = str.length();
+
+ int pos = str.find("encoding");
+ if (pos == -1)
+ return -1;
+ pos += 8;
+
+ // Skip spaces and stray control characters.
+ while (pos < len && str[pos] <= ' ')
+ ++pos;
+
+ //Bail out if nothing after
+ if (pos >= len)
+ return -1;
+
+ // Skip equals sign.
+ if (str[pos] != '=')
+ return -1;
+ ++pos;
+
+ // Skip spaces and stray control characters.
+ while (pos < len && str[pos] <= ' ')
+ ++pos;
+
+ //Bail out if nothing after
+ if (pos >= len)
+ return -1;
+
+ // Skip quotation mark.
+ char quoteMark = str[pos];
+ if (quoteMark != '"' && quoteMark != '\'')
+ return -1;
+ ++pos;
+
+ // Find the trailing quotation mark.
+ int end = pos;
+ while (end < len && str[end] != quoteMark)
+ ++end;
+
+ if (end >= len)
+ return -1;
+
+ encodingLength = end - pos;
+ return pos;
+}
+
+TQString Decoder::decode(const char *data, int len)
+{
+ // Check for UTF-16 or UTF-8 BOM mark at the beginning, which is a sure sign of a Unicode encoding.
+ int bufferLength = buffer.length();
+ const int maximumBOMLength = 10;
+ if (beginning && bufferLength + len >= maximumBOMLength) {
+ // If the user has chosen utf16 we still need to auto-detect the endianness
+ if ((m_type != UserChosenEncoding) || (m_codec->mibEnum() == 1000)) {
+ // Extract the first three bytes.
+ // Handle the case where some of bytes are already in the buffer.
+ const uchar *udata = (const uchar *)data;
+ uchar c1 = bufferLength >= 1 ? (uchar)buffer[0] : *udata++;
+ uchar c2 = bufferLength >= 2 ? (uchar)buffer[1] : *udata++;
+ uchar c3 = bufferLength >= 3 ? (uchar)buffer[2] : *udata++;
+
+ // Check for the BOM
+ const char *autoDetectedEncoding;
+ if ((c1 == 0xFE && c2 == 0xFF) || (c1 == 0xFF && c2 == 0xFE)) {
+ autoDetectedEncoding = "ISO-10646-UCS-2";
+ } else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) {
+ autoDetectedEncoding = "UTF-8";
+ } else if (c1 == 0x00 || c2 == 0x00) {
+ uchar c4 = bufferLength >= 4 ? (uchar)buffer[3] : *udata++;
+ uchar c5 = bufferLength >= 5 ? (uchar)buffer[4] : *udata++;
+ uchar c6 = bufferLength >= 6 ? (uchar)buffer[5] : *udata++;
+ uchar c7 = bufferLength >= 7 ? (uchar)buffer[6] : *udata++;
+ uchar c8 = bufferLength >= 8 ? (uchar)buffer[7] : *udata++;
+ uchar c9 = bufferLength >= 9 ? (uchar)buffer[8] : *udata++;
+ uchar c10 = bufferLength >= 10 ? (uchar)buffer[9] : *udata++;
+ int nul_count_even = (c2 != 0) + (c4 != 0) + (c6 != 0) + (c8 != 0) + (c10 != 0);
+ int nul_count_odd = (c1 != 0) + (c3 != 0) + (c5 != 0) + (c7 != 0) + (c9 != 0);
+ if ((nul_count_even == 0 && nul_count_odd == 5) ||
+ (nul_count_even == 5 && nul_count_odd == 0))
+ autoDetectedEncoding = "ISO-10646-UCS-2";
+ else
+ autoDetectedEncoding = 0;
+ } else {
+ autoDetectedEncoding = 0;
+ }
+
+ // If we found a BOM, use the encoding it implies.
+ if (autoDetectedEncoding != 0) {
+ m_type = AutoDetectedEncoding;
+ m_codec = TQTextCodec::codecForName(autoDetectedEncoding);
+ assert(m_codec);
+ enc = m_codec->name();
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ if (m_codec->mibEnum() == 1000 && c2 == 0x00)
+ {
+ // utf16LE, we need to put the decoder in LE mode
+ char reverseUtf16[3] = {0xFF, 0xFE, 0x00};
+ m_decoder->toUnicode(reverseUtf16, 2);
+ }
+ }
+ }
+ beginning = false;
+ }
+
+ // this is not completely efficient, since the function might go
+ // through the html head several times...
+
+ bool lookForMetaTag = m_type == DefaultEncoding && !body;
+
+ if (lookForMetaTag) {
+#ifdef DECODE_DEBUG
+ kdDebug(6005) << "looking for charset definition" << endl;
+#endif
+ { // extra level of braces to keep indenting matching original for better diff'ing
+#ifdef APPLE_CHANGES
+ buffer.append(data, len);
+#else
+ if(m_codec->mibEnum() != 1000) { // utf16
+ // replace '\0' by spaces, for buggy pages
+ char *d = const_cast<char *>(data);
+ int i = len - 1;
+ while(i >= 0) {
+ if(d[i] == 0) d[i] = ' ';
+ i--;
+ }
+ }
+ buffer += TQCString(data, len+1);
+#endif
+ // we still don't have an encoding, and are in the head
+ // the following tags are allowed in <head>:
+ // SCRIPT|STYLE|META|LINK|OBJECT|TITLE|BASE
+ int invalid = 0; // invalid head tag count
+#ifdef APPLE_CHANGES
+ const char *ptr = buffer.latin1();
+ const char *pEnd = ptr + buffer.length();
+#else
+ const char *ptr = buffer.data();
+ const char *pEnd = ptr + buffer.length();
+#endif
+ while(ptr != pEnd)
+ {
+ if(*ptr == '<') {
+ bool end = false;
+ ptr++;
+
+ // Handle comments.
+ if (ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') {
+ ptr += 3;
+ skipComment(ptr, pEnd);
+ continue;
+ }
+
+ // Handle XML header, which can have encoding in it.
+ if (ptr[0] == '?' && ptr[1] == 'x' && ptr[2] == 'm' && ptr[3] == 'l') {
+ const char *end = ptr;
+ while (*end != '>' && *end != '\0') end++;
+ if (*end == '\0')
+ break;
+ TQCString str(ptr, end - ptr + 1); //+1 as it must include the \0 terminator
+ int len;
+ int pos = findXMLEncoding(str, len);
+ if (pos != -1) {
+ setEncoding(str.mid(pos, len), EncodingFromXMLHeader);
+ if (m_type == EncodingFromXMLHeader)
+ goto found;
+ }
+ }
+
+ if(*ptr == '/') ptr++, end=true;
+ char tmp[20];
+ int len = 0;
+ while (
+ ((*ptr >= 'a') && (*ptr <= 'z') ||
+ (*ptr >= 'A') && (*ptr <= 'Z') ||
+ (*ptr >= '0') && (*ptr <= '9'))
+ && len < 19 )
+ {
+ tmp[len] = tolower( *ptr );
+ ptr++;
+ len++;
+ }
+ tmp[len] = 0;
+ int id = tdehtml::getTagID(tmp, len);
+ if(end) id += ID_CLOSE_TAG;
+
+ switch( id ) {
+ case ID_META:
+ {
+ // found a meta tag...
+ //ptr += 5;
+ const char * end = ptr;
+ while(*end != '>' && *end != '\0') end++;
+ if ( *end == '\0' ) break;
+ TQCString str( ptr, (end-ptr)+1);
+ str = str.lower();
+ int pos = 0;
+ //if( (pos = str.find("http-equiv", pos)) == -1) break;
+ //if( (pos = str.find("content-type", pos)) == -1) break;
+ while( pos < ( int ) str.length() ) {
+ if( (pos = str.find("charset", pos)) == -1) break;
+ pos += 7;
+ // skip whitespace..
+ while( pos < (int)str.length() && str[pos] <= ' ' ) pos++;
+ if ( pos == ( int )str.length()) break;
+ if ( str[pos++] != '=' ) continue;
+ while ( pos < ( int )str.length() &&
+ ( str[pos] <= ' ' ) || str[pos] == '=' || str[pos] == '"' || str[pos] == '\'')
+ pos++;
+
+ // end ?
+ if ( pos == ( int )str.length() ) break;
+ uint endpos = pos;
+ while( endpos < str.length() &&
+ (str[endpos] != ' ' && str[endpos] != '"' && str[endpos] != '\''
+ && str[endpos] != ';' && str[endpos] != '>') )
+ endpos++;
+ enc = str.mid(pos, endpos-pos);
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: found charset: " << enc.data() << endl;
+#endif
+ setEncoding(enc, EncodingFromMetaTag);
+ if( m_type == EncodingFromMetaTag ) goto found;
+
+ if ( endpos >= str.length() || str[endpos] == '/' || str[endpos] == '>' ) break;
+
+ pos = endpos + 1;
+ }
+ }
+ case ID_SCRIPT:
+ case (ID_SCRIPT+ID_CLOSE_TAG):
+ case ID_NOSCRIPT:
+ case (ID_NOSCRIPT+ID_CLOSE_TAG):
+ case ID_STYLE:
+ case (ID_STYLE+ID_CLOSE_TAG):
+ case ID_LINK:
+ case (ID_LINK+ID_CLOSE_TAG):
+ case ID_OBJECT:
+ case (ID_OBJECT+ID_CLOSE_TAG):
+ case ID_TITLE:
+ case (ID_TITLE+ID_CLOSE_TAG):
+ case ID_BASE:
+ case (ID_BASE+ID_CLOSE_TAG):
+ case ID_HTML:
+ case ID_HEAD:
+ case 0:
+ case (0 + ID_CLOSE_TAG ):
+ break;
+ case ID_BODY:
+ case (ID_HEAD+ID_CLOSE_TAG):
+ body = true;
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: no charset found. Id=" << id << endl;
+#endif
+ goto found;
+ default:
+ // Invalid tag in head. Let's be a little tolerant
+ invalid++;
+ if (invalid > 2) {
+ body = true;
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: no charset found. Id=" << id << endl;
+#endif
+ goto found;
+ }
+ }
+ }
+ else
+ ptr++;
+ }
+ if (invalid > 0) {
+ body = true;
+ goto found;
+ }
+ return TQString::null;
+ }
+ }
+
+ found:
+ if (m_type == DefaultEncoding)
+ {
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: use auto-detect (" << strlen(data) << ")" << endl;
+#endif
+
+ switch ( m_autoDetectLanguage) {
+ case Decoder::Arabic:
+ enc = automaticDetectionForArabic( (const unsigned char*) data, len );
+ break;
+ case Decoder::Baltic:
+ enc = automaticDetectionForBaltic( (const unsigned char*) data, len );
+ break;
+ case Decoder::CentralEuropean:
+ enc = automaticDetectionForCentralEuropean( (const unsigned char*) data, len );
+ break;
+ case Decoder::Russian:
+ case Decoder::Ukrainian:
+ enc = automaticDetectionForCyrillic( (const unsigned char*) data, len, m_autoDetectLanguage );
+ break;
+ case Decoder::Greek:
+ enc = automaticDetectionForGreek( (const unsigned char*) data, len );
+ break;
+ case Decoder::Hebrew:
+ enc = automaticDetectionForHebrew( (const unsigned char*) data, len );
+ break;
+ case Decoder::Japanese:
+ enc = automaticDetectionForJapanese( (const unsigned char*) data, len );
+ break;
+ case Decoder::Turkish:
+ enc = automaticDetectionForTurkish( (const unsigned char*) data, len );
+ break;
+ case Decoder::WesternEuropean:
+ enc = automaticDetectionForWesternEuropean( (const unsigned char*) data, len );
+ break;
+ case Decoder::SemiautomaticDetection:
+ case Decoder::Chinese:
+ case Decoder::Korean:
+ case Decoder::Thai:
+ case Decoder::Unicode:
+ // huh. somethings broken in this code ### FIXME
+ enc = 0; //Reset invalid codec we tried, so we get back to latin1 fallback.
+ break;
+ }
+
+#ifdef DECODE_DEBUG
+ kdDebug( 6005 ) << "Decoder: auto detect encoding is " << enc.data() << endl;
+#endif
+ if ( !enc.isEmpty() )
+ setEncoding( enc.data(), AutoDetectedEncoding);
+ }
+
+
+ // if we still haven't found an encoding latin1 will be used...
+ // this is according to HTML4.0 specs
+ if (!m_codec)
+ {
+ if(enc.isEmpty()) enc = "iso8859-1";
+ m_codec = TQTextCodec::codecForName(enc);
+ // be sure not to crash
+ if(!m_codec) {
+ m_codec = TQTextCodec::codecForMib(4);
+ enc = "iso8859-1";
+ }
+ delete m_decoder;
+ m_decoder = m_codec->makeDecoder();
+ }
+ TQString out;
+
+ if(!buffer.isEmpty() && enc != "ISO-10646-UCS-2") {
+ out = m_decoder->toUnicode(buffer, buffer.length());
+ buffer = "";
+ } else {
+ if(m_codec->mibEnum() != 1000) // utf16
+ {
+ // ### hack for a bug in TQTextCodec. It cut's the input stream
+ // in case there are \0 in it. ZDNET has them inside... :-(
+ char *d = const_cast<char *>(data);
+ int i = len - 1;
+ while(i >= 0) {
+ if(*(d+i) == 0) *(d+i) = ' ';
+ i--;
+ }
+ }
+ out = m_decoder->toUnicode(data, len);
+ }
+
+ return out;
+}
+
+TQString Decoder::flush() const
+{
+ return m_decoder->toUnicode(buffer, buffer.length());
+}
+
+TQCString Decoder::automaticDetectionForArabic( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F ) || ptr[ i ] == 0xA1 || ptr[ i ] == 0xA2 || ptr[ i ] == 0xA3
+ || ( ptr[ i ] >= 0xA5 && ptr[ i ] <= 0xAB ) || ( ptr[ i ] >= 0xAE && ptr[ i ] <= 0xBA )
+ || ptr[ i ] == 0xBC || ptr[ i ] == 0xBD || ptr[ i ] == 0xBE || ptr[ i ] == 0xC0
+ || ( ptr[ i ] >= 0xDB && ptr[ i ] <= 0xDF ) || ( ptr[ i ] >= 0xF3 ) ) {
+ return "cp1256";
+ }
+ }
+
+ return "iso-8859-6";
+}
+
+TQCString Decoder::automaticDetectionForBaltic( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9E ) )
+ return "cp1257";
+
+ if ( ptr[ i ] == 0xA1 || ptr[ i ] == 0xA5 )
+ return "iso-8859-13";
+ }
+
+ return "iso-8859-13";
+}
+
+TQCString Decoder::automaticDetectionForCentralEuropean(const unsigned char* ptr, int size )
+{
+ TQCString charset = TQCString();
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F ) {
+ if ( ptr[ i ] == 0x81 || ptr[ i ] == 0x83 || ptr[ i ] == 0x90 || ptr[ i ] == 0x98 )
+ return "ibm852";
+
+ if ( i + 1 > size )
+ return "cp1250";
+ else { // maybe ibm852 ?
+ charset = "cp1250";
+ continue;
+ }
+ }
+ if ( ptr[ i ] == 0xA5 || ptr[ i ] == 0xAE || ptr[ i ] == 0xBE || ptr[ i ] == 0xC3 || ptr[ i ] == 0xD0 || ptr[ i ] == 0xE3 || ptr[ i ] == 0xF0 ) {
+ if ( i + 1 > size )
+ return "iso-8859-2";
+ else { // maybe ibm852 ?
+ if ( charset.isNull() )
+ charset = "iso-8859-2";
+ continue;
+ }
+ }
+ }
+
+ if ( charset.isNull() )
+ charset = "iso-8859-3";
+
+ return charset.data();
+}
+
+TQCString Decoder::automaticDetectionForCyrillic( const unsigned char* ptr, int size, AutoDetectLanguage _language )
+{
+ int koi_st=0;
+ int cp1251_st=0;
+
+// int koi_na=0;
+// int cp1251_na=0;
+
+ int koi_o_capital=0;
+ int koi_o=0;
+ int cp1251_o_capital=0;
+ int cp1251_o=0;
+
+ int koi_a_capital=0;
+ int koi_a=0;
+ int cp1251_a_capital=0;
+ int cp1251_a=0;
+
+ int koi_i_capital=0;
+ int koi_i=0;
+ int cp1251_i_capital=0;
+ int cp1251_i=0;
+
+ int cp1251_small_range=0;
+ int koi_small_range=0;
+ int ibm866_small_range=0;
+
+ int i;
+ for (i=1; (i<size) && (cp1251_small_range+koi_small_range<1000) ;++i)
+ {
+ if (ptr[i]>0xdf)
+ {
+ ++cp1251_small_range;
+
+ if (ptr[i]==0xee)//small o
+ ++cp1251_o;
+ else if (ptr[i]==0xe0)//small a
+ ++cp1251_a;
+ else if (ptr[i]==0xe8)//small i
+ ++cp1251_i;
+ else if (ptr[i]==0xf2 && ptr[i-1]==0xf1)//small st
+ ++cp1251_st;
+
+ else if (ptr[i]==0xef)
+ ++koi_o_capital;
+ else if (ptr[i]==0xe1)
+ ++koi_a_capital;
+ else if (ptr[i]==0xe9)
+ ++koi_i_capital;
+
+ }
+ else if (ptr[i]>0xbf)
+ {
+ ++koi_small_range;
+
+ if (ptr[i]==0xcf)//small o
+ ++koi_o;
+ else if (ptr[i]==0xc1)//small a
+ ++koi_a;
+ else if (ptr[i]==0xc9)//small i
+ ++koi_i;
+ else if (ptr[i]==0xd4 && ptr[i-1]==0xd3)//small st
+ ++koi_st;
+
+ else if (ptr[i]==0xce)
+ ++cp1251_o_capital;
+ else if (ptr[i]==0xc0)
+ ++cp1251_a_capital;
+ else if (ptr[i]==0xc8)
+ ++cp1251_i_capital;
+ }
+ else if (ptr[i]>0x9f && ptr[i]<0xaf) //first 16 letterz is 60%
+ ++ibm866_small_range;
+
+ }
+
+ if (ibm866_small_range>cp1251_small_range+koi_small_range)
+ return "ibm866"; //hehe this is a rare case :)
+
+ TQCString koi_string = "koi8-u";
+ TQCString cp1251_string = "cp1251";
+
+ if (cp1251_st==0 && koi_st>1)
+ return koi_string;
+ if (koi_st==0 && cp1251_st>1)
+ return cp1251_string;
+
+ if (cp1251_st>0 && koi_st>0)
+ {
+ if (cp1251_st/koi_st>2)
+ return cp1251_string;
+ else if (koi_st/cp1251_st>2)
+ return koi_string;
+ }
+
+ if (cp1251_a>koi_a && cp1251_o>koi_o && cp1251_i>koi_i)
+ return cp1251_string;
+ if (koi_a>cp1251_a && koi_o>cp1251_o && koi_i>cp1251_i)
+ return koi_string;
+
+ if (cp1251_a_capital>koi_a_capital && cp1251_o_capital>koi_o_capital && cp1251_i_capital>koi_i_capital)
+ return cp1251_string;
+ if (koi_a_capital>cp1251_a_capital && koi_o_capital>cp1251_o_capital && koi_i_capital>cp1251_i_capital)
+ return koi_string;
+
+ //fallback...
+ if (cp1251_small_range>koi_small_range)
+ return cp1251_string;
+ else
+ return koi_string;
+
+}
+
+TQCString Decoder::automaticDetectionForGreek( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x87 ) || ptr[ i ] == 0x89 || ptr[ i ] == 0x8B
+ || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x97 ) || ptr[ i ] == 0x99 || ptr[ i ] == 0x9B || ptr[ i ] == 0xA4
+ || ptr[ i ] == 0xA5 || ptr[ i ] == 0xAE ) {
+ return "cp1253";
+ }
+ }
+
+ return "iso-8859-7";
+}
+
+TQCString Decoder::automaticDetectionForHebrew( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x89 ) || ptr[ i ] == 0x8B
+ || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x99 ) || ptr[ i ] == 0x9B || ptr[ i ] == 0xA1 || ( ptr[ i ] >= 0xBF && ptr[ i ] <= 0xC9 )
+ || ( ptr[ i ] >= 0xCB && ptr[ i ] <= 0xD8 ) ) {
+ return "cp1255";
+ }
+
+ if ( ptr[ i ] == 0xDF )
+ return "iso-8859-8-i";
+ }
+
+ return "iso-8859-8-i";
+}
+
+TQCString Decoder::automaticDetectionForJapanese( const unsigned char* ptr, int size )
+{
+ if (!kc)
+ kc = new JapaneseCode();
+
+ switch ( kc->guess_jp( (const char*)ptr, size ) ) {
+ case JapaneseCode::JIS:
+ return "jis7";
+ case JapaneseCode::EUC:
+ return "eucjp";
+ case JapaneseCode::SJIS:
+ return "sjis";
+ case JapaneseCode::UTF8:
+ return "utf8";
+ default:
+ break;
+ }
+
+ return "";
+}
+
+TQCString Decoder::automaticDetectionForTurkish( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] == 0x80 || ( ptr[ i ] >= 0x82 && ptr[ i ] <= 0x8C ) || ( ptr[ i ] >= 0x91 && ptr[ i ] <= 0x9C ) || ptr[ i ] == 0x9F ) {
+ return "cp1254";
+ }
+ }
+
+ return "iso-8859-9";
+}
+
+TQCString Decoder::automaticDetectionForWesternEuropean( const unsigned char* ptr, int size )
+{
+ for ( int i = 0; i < size; ++i ) {
+ if ( ptr[ i ] >= 0x80 && ptr[ i ] <= 0x9F )
+ return "cp1252";
+ }
+
+ return "iso-8859-1"; //"iso-8859-15"; Which better at default ?
+}
+
+
+// -----------------------------------------------------------------------------
+#undef DECODE_DEBUG
diff --git a/tdehtml/misc/decoder.h b/tdehtml/misc/decoder.h
new file mode 100644
index 000000000..2fcda7904
--- /dev/null
+++ b/tdehtml/misc/decoder.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.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.
+
+*/
+#ifndef KHTMLDECODER_H
+#define KHTMLDECODER_H
+
+#include <tqstring.h>
+class TQTextCodec;
+class TQTextDecoder;
+
+namespace tdehtml {
+
+class JapaneseCode;
+
+/**
+ * @internal
+ */
+class Decoder
+{
+public:
+ enum EncodingType {
+ DefaultEncoding,
+ AutoDetectedEncoding,
+ EncodingFromXMLHeader,
+ EncodingFromMetaTag,
+ EncodingFromHTTPHeader,
+ UserChosenEncoding
+ };
+
+ Decoder();
+ ~Decoder();
+
+ void setEncoding(const char *encoding, EncodingType type);
+ const char *encoding() const;
+
+ TQString decode(const char *data, int len);
+
+ bool visuallyOrdered() const { return visualRTL; }
+
+ const TQTextCodec *codec() const { return m_codec; }
+
+ TQString flush() const;
+
+
+ enum AutoDetectLanguage {
+ SemiautomaticDetection,
+ Arabic,
+ Baltic,
+ CentralEuropean,
+ Chinese,
+ Greek,
+ Hebrew,
+ Japanese,
+ Korean,
+ Russian,
+ Thai,
+ Turkish,
+ Ukrainian,
+ Unicode,
+ WesternEuropean
+ };
+
+ void setAutoDetectLanguage( AutoDetectLanguage _language ) { m_autoDetectLanguage = _language; }
+ AutoDetectLanguage autoDetectLanguage() { return m_autoDetectLanguage; }
+
+
+
+private:
+ TQCString automaticDetectionForArabic( const unsigned char* str, int size );
+ TQCString automaticDetectionForBaltic( const unsigned char* str, int size );
+ TQCString automaticDetectionForCentralEuropean( const unsigned char* str, int size );
+ TQCString automaticDetectionForCyrillic( const unsigned char* str, int size, AutoDetectLanguage _language );
+ TQCString automaticDetectionForGreek( const unsigned char* str, int size );
+ TQCString automaticDetectionForHebrew( const unsigned char* str, int size );
+ TQCString automaticDetectionForJapanese( const unsigned char* str, int size );
+ TQCString automaticDetectionForTurkish( const unsigned char* str, int size );
+ TQCString automaticDetectionForWesternEuropean( const unsigned char* str, int size );
+
+ // codec used for decoding. default is Latin1.
+ TQTextCodec *m_codec;
+ TQTextDecoder *m_decoder; // only used for utf16
+ TQCString enc;
+ EncodingType m_type;
+
+ TQCString buffer;
+
+ bool body;
+ bool beginning;
+ bool visualRTL;
+
+ AutoDetectLanguage m_autoDetectLanguage;
+
+ JapaneseCode *kc;
+};
+
+}
+#endif
diff --git a/tdehtml/misc/guess_ja.cpp b/tdehtml/misc/guess_ja.cpp
new file mode 100644
index 000000000..2a4e82215
--- /dev/null
+++ b/tdehtml/misc/guess_ja.cpp
@@ -0,0 +1,379 @@
+/*
+ * This file is part of the KDE libraries
+ *
+ * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the authors nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * original code is here.
+ * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup
+ */
+
+/*
+ * Maybe we should use TQTextCodec::heuristicContentMatch()
+ * But it fails detection. It's not useful.
+ */
+#include "decoder.h"
+#include "guess_ja.h"
+
+using namespace tdehtml;
+
+/* DFA tables */
+const dfa_table guess_eucj_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -1,
+ },
+ { /* state jis0201_kana */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state jis0213_1 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1,
+ },
+ { /* state jis0213_2 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, -1,
+ },
+};
+
+guess_arc guess_eucj_ar[7] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 0.8 }, /* init -> jis0201_kana */
+ { 3, 0.95 }, /* init -> jis0213_2 */
+ { 2, 1.0 }, /* init -> jis0213_1 */
+ { 0, 1.0 }, /* jis0201_kana -> init */
+ { 0, 1.0 }, /* jis0213_1 -> init */
+ { 0, 1.0 }, /* jis0213_2 -> init */
+};
+
+const dfa_table guess_sjis_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+ },
+ { /* state jis0213 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, -1, -1,
+ },
+};
+
+guess_arc guess_sjis_ar[6] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 1.0 }, /* init -> jis0213 */
+ { 0, 0.8 }, /* init -> init */
+ { 1, 0.95 }, /* init -> jis0213 */
+ { 0, 0.8 }, /* init -> init */
+ { 0, 1.0 }, /* jis0213 -> init */
+};
+
+const dfa_table guess_utf8_st[] = {
+ { /* state init */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, -1, -1,
+ },
+ { /* state 1byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 2byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 3byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 4byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+ { /* state 5byte_more */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ },
+};
+
+guess_arc guess_utf8_ar[11] = {
+ { 0, 1.0 }, /* init -> init */
+ { 1, 1.0 }, /* init -> 1byte_more */
+ { 2, 1.0 }, /* init -> 2byte_more */
+ { 3, 1.0 }, /* init -> 3byte_more */
+ { 4, 1.0 }, /* init -> 4byte_more */
+ { 5, 1.0 }, /* init -> 5byte_more */
+ { 0, 1.0 }, /* 1byte_more -> init */
+ { 1, 1.0 }, /* 2byte_more -> 1byte_more */
+ { 2, 1.0 }, /* 3byte_more -> 2byte_more */
+ { 3, 1.0 }, /* 4byte_more -> 3byte_more */
+ { 4, 1.0 }, /* 5byte_more -> 4byte_more */
+};
+
+/* Guessing Routine */
+enum JapaneseCode::Type JapaneseCode::guess_jp(const char *buf, int buflen)
+{
+ int i;
+ guess_dfa *top = NULL;
+
+ for (i=0; i<buflen; i++) {
+ int c = (unsigned char)buf[i];
+
+ /* special treatment of jis escape sequence */
+ if (c == 0x1b || last_JIS_escape) {
+ if (i < buflen-1) {
+ if (last_JIS_escape)
+ c = (unsigned char)buf[i];
+ else
+ c = (unsigned char)buf[++i];
+ last_JIS_escape = false;
+
+ if (c == '$' || c == '(') {
+ return JapaneseCode::JIS;
+ }
+ } else {
+ last_JIS_escape = true;
+ }
+ }
+
+ if (DFA_ALIVE(eucj)) {
+ if (!DFA_ALIVE(sjis) && !DFA_ALIVE(utf8)) return JapaneseCode::EUC;
+ DFA_NEXT(eucj, c);
+ }
+ if (DFA_ALIVE(sjis)) {
+ if (!DFA_ALIVE(eucj) && !DFA_ALIVE(utf8)) return JapaneseCode::SJIS;
+ DFA_NEXT(sjis, c);
+ }
+ if (DFA_ALIVE(utf8)) {
+ if (!DFA_ALIVE(sjis) && !DFA_ALIVE(eucj)) return JapaneseCode::UTF8;
+ DFA_NEXT(utf8, c);
+ }
+
+ if (!DFA_ALIVE(eucj) && !DFA_ALIVE(sjis) && !DFA_ALIVE(utf8)) {
+ /* we ran out the possibilities */
+ return JapaneseCode::ASCII;
+ }
+ }
+
+ /* ascii code check */
+ if (eucj->score == 1.0 && sjis->score == 1.0 && utf8->score == 1.0)
+ return JapaneseCode::ASCII;
+
+ /* Now, we have ambigous code. Pick the highest score. If more than
+ one candidate tie, pick the default encoding. */
+ if (DFA_ALIVE(eucj)) top = eucj;
+ if (DFA_ALIVE(utf8)) {
+ if (top) {
+ if (top->score < utf8->score) top = utf8;
+ } else {
+ top = utf8;
+ }
+ }
+ if (DFA_ALIVE(sjis)) {
+ if (top) {
+ if (top->score <= sjis->score) top = sjis;
+ } else {
+ top = sjis;
+ }
+ }
+
+ if (top == eucj) return JapaneseCode::EUC;
+ if (top == utf8) return JapaneseCode::UTF8;
+ if (top == sjis) return JapaneseCode::SJIS;
+
+ return JapaneseCode::ASCII;
+}
diff --git a/tdehtml/misc/guess_ja.h b/tdehtml/misc/guess_ja.h
new file mode 100644
index 000000000..a596d5c3a
--- /dev/null
+++ b/tdehtml/misc/guess_ja.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the KDE libraries
+ *
+ * Copyright (c) 2000-2003 Shiro Kawai, All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the authors nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+ * original code is here.
+ * http://cvs.sourceforge.net/viewcvs.py/gauche/Gauche/ext/charconv/guess.c?view=markup
+ */
+#ifndef GUESS_JA_H
+#define GUESS_JA_H
+
+namespace tdehtml {
+ class guess_arc {
+ public:
+ unsigned int next; /* next state */
+ double score; /* score */
+ };
+}
+
+using namespace tdehtml;
+
+typedef signed char dfa_table[256];
+
+/* DFA tables declared in guess_ja.cpp */
+extern const dfa_table guess_eucj_st[];
+extern guess_arc guess_eucj_ar[7];
+extern const dfa_table guess_sjis_st[];
+extern guess_arc guess_sjis_ar[6];
+extern const dfa_table guess_utf8_st[];
+extern guess_arc guess_utf8_ar[11];
+
+namespace tdehtml {
+
+ class guess_dfa {
+ public:
+ const dfa_table *states;
+ const guess_arc *arcs;
+ int state;
+ double score;
+
+ guess_dfa (const dfa_table stable[], const guess_arc *atable) :
+ states(stable), arcs(atable)
+ {
+ state = 0;
+ score = 1.0;
+ }
+ };
+
+ class JapaneseCode
+ {
+ public:
+ enum Type {ASCII, JIS, EUC, SJIS, UNICODE, UTF8 };
+ enum Type guess_jp(const char* buf, int buflen);
+
+ JapaneseCode () {
+ eucj = new guess_dfa(guess_eucj_st, guess_eucj_ar);
+ sjis = new guess_dfa(guess_sjis_st, guess_sjis_ar);
+ utf8 = new guess_dfa(guess_utf8_st, guess_utf8_ar);
+ last_JIS_escape = false;
+ }
+
+ ~JapaneseCode () {
+ if (eucj) delete eucj;
+ if (sjis) delete sjis;
+ if (utf8) delete utf8;
+ }
+
+ protected:
+ guess_dfa *eucj;
+ guess_dfa *sjis;
+ guess_dfa *utf8;
+
+ bool last_JIS_escape;
+ };
+}
+
+#define DFA_NEXT(dfa, ch) \
+ do { \
+ int arc__; \
+ if (dfa->state >= 0) { \
+ arc__ = dfa->states[dfa->state][ch]; \
+ if (arc__ < 0) { \
+ dfa->state = -1; \
+ } else { \
+ dfa->state = dfa->arcs[arc__].next; \
+ dfa->score *= dfa->arcs[arc__].score; \
+ } \
+ } \
+ } while (0)
+
+#define DFA_ALIVE(dfa) (dfa->state >= 0)
+
+#endif /* GUESS_JA_H */
diff --git a/tdehtml/misc/helper.cpp b/tdehtml/misc/helper.cpp
new file mode 100644
index 000000000..f759a9957
--- /dev/null
+++ b/tdehtml/misc/helper.cpp
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) David Carson <dacarson@gmail.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.
+ *
+ */
+#include "helper.h"
+#include "tdehtmllayout.h"
+#include <tqmap.h>
+#include <tqpainter.h>
+#include <dom/dom_string.h>
+#include <xml/dom_stringimpl.h>
+#include <rendering/render_object.h>
+#include <tqptrlist.h>
+#include <kstaticdeleter.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <tqtooltip.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+namespace tdehtml {
+ TQPainter *printpainter;
+}
+
+void tdehtml::setPrintPainter( TQPainter *printer )
+{
+ printpainter = printer;
+}
+
+
+double calcHue(double temp1, double temp2, double hueVal)
+{
+ if (hueVal < 0)
+ hueVal++;
+ else if (hueVal > 1)
+ hueVal--;
+ if (hueVal * 6 < 1)
+ return temp1 + (temp2 - temp1) * hueVal * 6;
+ if (hueVal * 2 < 1)
+ return temp2;
+ if (hueVal * 3 < 2)
+ return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hueVal) * 6;
+ return temp1;
+}
+
+// Explanation of this algorithm can be found in the CSS3 Color Module
+// specification at http://www.w3.org/TR/css3-color/#hsl-color with further
+// explanation available at http://en.wikipedia.org/wiki/HSL_color_space
+
+// all values are in the range of 0 to 1.0
+QRgb tdehtml::tqRgbaFromHsla(double h, double s, double l, double a)
+{
+ double temp2 = l < 0.5 ? l * (1.0 + s) : l + s - l * s;
+ double temp1 = 2.0 * l - temp2;
+
+ return tqRgba(calcHue(temp1, temp2, h + 1.0 / 3.0) * 255, calcHue(temp1, temp2, h) * 255, calcHue(temp1, temp2, h - 1.0 / 3.0) * 255, a * 255);
+}
+
+/** finds out the background color of an element
+ * @param obj render object
+ * @return the background color. It is guaranteed that a valid color is returned.
+ */
+TQColor tdehtml::retrieveBackgroundColor(const RenderObject *obj)
+{
+ TQColor result;
+ while (!obj->isCanvas()) {
+ result = obj->style()->backgroundColor();
+ if (result.isValid()) return result;
+
+ obj = obj->container();
+ }/*wend*/
+
+ // everything transparent? Use base then.
+ return obj->style()->palette().active().base();
+}
+
+/** checks whether the given colors have enough contrast
+ * @returns @p true if contrast is ok.
+ */
+bool tdehtml::hasSufficientContrast(const TQColor &c1, const TQColor &c2)
+{
+// New version from Germain Garand, better suited for contrast measurement
+#if 1
+
+#define HUE_DISTANCE 40
+#define CONTRAST_DISTANCE 10
+
+ int h1, s1, v1, h2, s2, v2;
+ int hdist = -CONTRAST_DISTANCE;
+ c1.hsv(&h1,&s1,&v1);
+ c2.hsv(&h2,&s2,&v2);
+ if(h1!=-1 && h2!=-1) { // grey values have no hue
+ hdist = kAbs(h1-h2);
+ if (hdist > 180) hdist = 360-hdist;
+ if (hdist < HUE_DISTANCE) {
+ hdist -= HUE_DISTANCE;
+ // see if they are high key or low key colours
+ bool hk1 = h1>=45 && h1<=225;
+ bool hk2 = h2>=45 && h2<=225;
+ if (hk1 && hk2)
+ hdist = (5*hdist)/3;
+ else if (!hk1 && !hk2)
+ hdist = (7*hdist)/4;
+ }
+ hdist = kMin(hdist, HUE_DISTANCE*2);
+ }
+ return hdist + (kAbs(s1-s2)*128)/(160+kMin(s1,s2)) + kAbs(v1-v2) > CONTRAST_DISTANCE;
+
+#undef CONTRAST_DISTANCE
+#undef HUE_DISTANCE
+
+#else // orginal fast but primitive version by me (LS)
+
+// ### arbitrary value, to be adapted if necessary (LS)
+#define CONTRAST_DISTANCE 32
+
+ if (kAbs(c1.red() - c2.red()) > CONTRAST_DISTANCE) return true;
+ if (kAbs(c1.green() - c2.green()) > CONTRAST_DISTANCE) return true;
+ if (kAbs(c1.blue() - c2.blue()) > CONTRAST_DISTANCE) return true;
+
+ return false;
+
+#undef CONTRAST_DISTANCE
+
+#endif
+}
diff --git a/tdehtml/misc/helper.h b/tdehtml/misc/helper.h
new file mode 100644
index 000000000..10ffb8035
--- /dev/null
+++ b/tdehtml/misc/helper.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the CSS implementation for KDE.
+ *
+ * Copyright (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 html_helper_h
+#define html_helper_h
+
+#include <tqcolor.h>
+class TQPainter;
+#include <tqfontmetrics.h>
+#include <tqfont.h>
+
+
+
+namespace tdehtml
+{
+ class RenderObject;
+ const QRgb transparentColor = 0x00000000;
+ const QRgb invertedColor = 0x00000002;
+
+ extern TQPainter *printpainter;
+ void setPrintPainter( TQPainter *printer );
+
+ bool hasSufficientContrast(const TQColor &c1, const TQColor &c2);
+ TQColor retrieveBackgroundColor(const RenderObject *obj);
+ QRgb tqRgbaFromHsla(double h, double s, double l, double a);
+
+ //enumerator for findSelectionNode
+ enum FindSelectionResult { SelectionPointBefore,
+ SelectionPointAfter,
+ SelectionPointInside,
+ // the next two are only used inside one line in RenderText
+ // to get BiDi contexts right.
+ SelectionPointBeforeInLine,
+ SelectionPointAfterInLine };
+}
+
+#endif
diff --git a/tdehtml/misc/htmlattrs.c b/tdehtml/misc/htmlattrs.c
new file mode 100644
index 000000000..779792e71
--- /dev/null
+++ b/tdehtml/misc/htmlattrs.c
@@ -0,0 +1,1019 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -c -a -L ANSI-C -P -G -D -E -C -o -t -k '*' -NfindAttr -Hhash_attr -Wwordlist_attr -Qspool_attr -s 2 htmlattrs.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 "htmlattrs.gperf"
+
+/* This file is automatically generated from
+#htmlattrs.in by makeattrs, do not edit */
+#include "htmlattrs.h"
+#line 6 "htmlattrs.gperf"
+struct attrs {
+ int name;
+ int id;
+};
+enum
+ {
+ TOTAL_KEYWORDS = 152,
+ MIN_WORD_LENGTH = 2,
+ MAX_WORD_LENGTH = 15,
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 576
+ };
+
+/* maximum key range = 574, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_attr (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 5, 5, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 30, 10, 0,
+ 10, 5, 10, 15, 165, 40, 140, 80, 0, 25,
+ 70, 0, 5, 5, 0, 0, 10, 55, 70, 180,
+ 5, 90, 45, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577, 577, 577, 577,
+ 577, 577, 577, 577, 577, 577, 577
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ 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]+1];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct spool_attr_t
+ {
+ char spool_attr_str0[sizeof("src")];
+ char spool_attr_str1[sizeof("onscroll")];
+ char spool_attr_str2[sizeof("cols")];
+ char spool_attr_str3[sizeof("color")];
+ char spool_attr_str4[sizeof("onerror")];
+ char spool_attr_str5[sizeof("rel")];
+ char spool_attr_str6[sizeof("loop")];
+ char spool_attr_str7[sizeof("for")];
+ char spool_attr_str8[sizeof("coords")];
+ char spool_attr_str9[sizeof("top")];
+ char spool_attr_str10[sizeof("code")];
+ char spool_attr_str11[sizeof("scope")];
+ char spool_attr_str12[sizeof("onreset")];
+ char spool_attr_str13[sizeof("onselect")];
+ char spool_attr_str14[sizeof("face")];
+ char spool_attr_str15[sizeof("label")];
+ char spool_attr_str16[sizeof("left")];
+ char spool_attr_str17[sizeof("border")];
+ char spool_attr_str18[sizeof("text")];
+ char spool_attr_str19[sizeof("defer")];
+ char spool_attr_str20[sizeof("bordercolor")];
+ char spool_attr_str21[sizeof("abbr")];
+ char spool_attr_str22[sizeof("pagex")];
+ char spool_attr_str23[sizeof("onload")];
+ char spool_attr_str24[sizeof("id")];
+ char spool_attr_str25[sizeof("selected")];
+ char spool_attr_str26[sizeof("prompt")];
+ char spool_attr_str27[sizeof("target")];
+ char spool_attr_str28[sizeof("onabort")];
+ char spool_attr_str29[sizeof("class")];
+ char spool_attr_str30[sizeof("declare")];
+ char spool_attr_str31[sizeof("data")];
+ char spool_attr_str32[sizeof("clear")];
+ char spool_attr_str33[sizeof("accept")];
+ char spool_attr_str34[sizeof("profile")];
+ char spool_attr_str35[sizeof("alt")];
+ char spool_attr_str36[sizeof("type")];
+ char spool_attr_str37[sizeof("onblur")];
+ char spool_attr_str38[sizeof("onfocus")];
+ char spool_attr_str39[sizeof("codebase")];
+ char spool_attr_str40[sizeof("char")];
+ char spool_attr_str41[sizeof("frame")];
+ char spool_attr_str42[sizeof("rules")];
+ char spool_attr_str43[sizeof("compact")];
+ char spool_attr_str44[sizeof("rev")];
+ char spool_attr_str45[sizeof("shape")];
+ char spool_attr_str46[sizeof("charset")];
+ char spool_attr_str47[sizeof("charoff")];
+ char spool_attr_str48[sizeof("lang")];
+ char spool_attr_str49[sizeof("start")];
+ char spool_attr_str50[sizeof("onresize")];
+ char spool_attr_str51[sizeof("truespeed")];
+ char spool_attr_str52[sizeof("frameborder")];
+ char spool_attr_str53[sizeof("span")];
+ char spool_attr_str54[sizeof("classid")];
+ char spool_attr_str55[sizeof("longdesc")];
+ char spool_attr_str56[sizeof("name")];
+ char spool_attr_str57[sizeof("ismap")];
+ char spool_attr_str58[sizeof("colspan")];
+ char spool_attr_str59[sizeof("media")];
+ char spool_attr_str60[sizeof("enctype")];
+ char spool_attr_str61[sizeof("datetime")];
+ char spool_attr_str62[sizeof("vspace")];
+ char spool_attr_str63[sizeof("onclick")];
+ char spool_attr_str64[sizeof("pagey")];
+ char spool_attr_str65[sizeof("usemap")];
+ char spool_attr_str66[sizeof("codetype")];
+ char spool_attr_str67[sizeof("scrolling")];
+ char spool_attr_str68[sizeof("value")];
+ char spool_attr_str69[sizeof("checked")];
+ char spool_attr_str70[sizeof("onsubmit")];
+ char spool_attr_str71[sizeof("ondblclick")];
+ char spool_attr_str72[sizeof("dir")];
+ char spool_attr_str73[sizeof("onmouseup")];
+ char spool_attr_str74[sizeof("style")];
+ char spool_attr_str75[sizeof("scrolldelay")];
+ char spool_attr_str76[sizeof("cite")];
+ char spool_attr_str77[sizeof("onmouseout")];
+ char spool_attr_str78[sizeof("object")];
+ char spool_attr_str79[sizeof("multiple")];
+ char spool_attr_str80[sizeof("axis")];
+ char spool_attr_str81[sizeof("action")];
+ char spool_attr_str82[sizeof("tabindex")];
+ char spool_attr_str83[sizeof("title")];
+ char spool_attr_str84[sizeof("onmouseover")];
+ char spool_attr_str85[sizeof("autocomplete")];
+ char spool_attr_str86[sizeof("onunload")];
+ char spool_attr_str87[sizeof("challenge")];
+ char spool_attr_str88[sizeof("plain")];
+ char spool_attr_str89[sizeof("content")];
+ char spool_attr_str90[sizeof("noresize")];
+ char spool_attr_str91[sizeof("cellspacing")];
+ char spool_attr_str92[sizeof("bgcolor")];
+ char spool_attr_str93[sizeof("href")];
+ char spool_attr_str94[sizeof("align")];
+ char spool_attr_str95[sizeof("nosave")];
+ char spool_attr_str96[sizeof("z-index")];
+ char spool_attr_str97[sizeof("rows")];
+ char spool_attr_str98[sizeof("oversrc")];
+ char spool_attr_str99[sizeof("size")];
+ char spool_attr_str100[sizeof("onkeypress")];
+ char spool_attr_str101[sizeof("onmousemove")];
+ char spool_attr_str102[sizeof("version")];
+ char spool_attr_str103[sizeof("cellpadding")];
+ char spool_attr_str104[sizeof("language")];
+ char spool_attr_str105[sizeof("topmargin")];
+ char spool_attr_str106[sizeof("valign")];
+ char spool_attr_str107[sizeof("scrollamount")];
+ char spool_attr_str108[sizeof("disabled")];
+ char spool_attr_str109[sizeof("scheme")];
+ char spool_attr_str110[sizeof("readonly")];
+ char spool_attr_str111[sizeof("wrap")];
+ char spool_attr_str112[sizeof("leftmargin")];
+ char spool_attr_str113[sizeof("hspace")];
+ char spool_attr_str114[sizeof("method")];
+ char spool_attr_str115[sizeof("headers")];
+ char spool_attr_str116[sizeof("accesskey")];
+ char spool_attr_str117[sizeof("onkeyup")];
+ char spool_attr_str118[sizeof("summary")];
+ char spool_attr_str119[sizeof("html")];
+ char spool_attr_str120[sizeof("alink")];
+ char spool_attr_str121[sizeof("bgproperties")];
+ char spool_attr_str122[sizeof("valuetype")];
+ char spool_attr_str123[sizeof("background")];
+ char spool_attr_str124[sizeof("nohref")];
+ char spool_attr_str125[sizeof("standby")];
+ char spool_attr_str126[sizeof("pluginurl")];
+ char spool_attr_str127[sizeof("pluginpage")];
+ char spool_attr_str128[sizeof("pluginspage")];
+ char spool_attr_str129[sizeof("direction")];
+ char spool_attr_str130[sizeof("accept-charset")];
+ char spool_attr_str131[sizeof("vlink")];
+ char spool_attr_str132[sizeof("noshade")];
+ char spool_attr_str133[sizeof("onchange")];
+ char spool_attr_str134[sizeof("link")];
+ char spool_attr_str135[sizeof("contenteditable")];
+ char spool_attr_str136[sizeof("nowrap")];
+ char spool_attr_str137[sizeof("rowspan")];
+ char spool_attr_str138[sizeof("hreflang")];
+ char spool_attr_str139[sizeof("maxlength")];
+ char spool_attr_str140[sizeof("archive")];
+ char spool_attr_str141[sizeof("behavior")];
+ char spool_attr_str142[sizeof("onmousedown")];
+ char spool_attr_str143[sizeof("hidden")];
+ char spool_attr_str144[sizeof("height")];
+ char spool_attr_str145[sizeof("http-equiv")];
+ char spool_attr_str146[sizeof("onkeydown")];
+ char spool_attr_str147[sizeof("visibility")];
+ char spool_attr_str148[sizeof("unknown")];
+ char spool_attr_str149[sizeof("width")];
+ char spool_attr_str150[sizeof("marginheight")];
+ char spool_attr_str151[sizeof("marginwidth")];
+ };
+static const struct spool_attr_t spool_attr_contents =
+ {
+ "src",
+ "onscroll",
+ "cols",
+ "color",
+ "onerror",
+ "rel",
+ "loop",
+ "for",
+ "coords",
+ "top",
+ "code",
+ "scope",
+ "onreset",
+ "onselect",
+ "face",
+ "label",
+ "left",
+ "border",
+ "text",
+ "defer",
+ "bordercolor",
+ "abbr",
+ "pagex",
+ "onload",
+ "id",
+ "selected",
+ "prompt",
+ "target",
+ "onabort",
+ "class",
+ "declare",
+ "data",
+ "clear",
+ "accept",
+ "profile",
+ "alt",
+ "type",
+ "onblur",
+ "onfocus",
+ "codebase",
+ "char",
+ "frame",
+ "rules",
+ "compact",
+ "rev",
+ "shape",
+ "charset",
+ "charoff",
+ "lang",
+ "start",
+ "onresize",
+ "truespeed",
+ "frameborder",
+ "span",
+ "classid",
+ "longdesc",
+ "name",
+ "ismap",
+ "colspan",
+ "media",
+ "enctype",
+ "datetime",
+ "vspace",
+ "onclick",
+ "pagey",
+ "usemap",
+ "codetype",
+ "scrolling",
+ "value",
+ "checked",
+ "onsubmit",
+ "ondblclick",
+ "dir",
+ "onmouseup",
+ "style",
+ "scrolldelay",
+ "cite",
+ "onmouseout",
+ "object",
+ "multiple",
+ "axis",
+ "action",
+ "tabindex",
+ "title",
+ "onmouseover",
+ "autocomplete",
+ "onunload",
+ "challenge",
+ "plain",
+ "content",
+ "noresize",
+ "cellspacing",
+ "bgcolor",
+ "href",
+ "align",
+ "nosave",
+ "z-index",
+ "rows",
+ "oversrc",
+ "size",
+ "onkeypress",
+ "onmousemove",
+ "version",
+ "cellpadding",
+ "language",
+ "topmargin",
+ "valign",
+ "scrollamount",
+ "disabled",
+ "scheme",
+ "readonly",
+ "wrap",
+ "leftmargin",
+ "hspace",
+ "method",
+ "headers",
+ "accesskey",
+ "onkeyup",
+ "summary",
+ "html",
+ "alink",
+ "bgproperties",
+ "valuetype",
+ "background",
+ "nohref",
+ "standby",
+ "pluginurl",
+ "pluginpage",
+ "pluginspage",
+ "direction",
+ "accept-charset",
+ "vlink",
+ "noshade",
+ "onchange",
+ "link",
+ "contenteditable",
+ "nowrap",
+ "rowspan",
+ "hreflang",
+ "maxlength",
+ "archive",
+ "behavior",
+ "onmousedown",
+ "hidden",
+ "height",
+ "http-equiv",
+ "onkeydown",
+ "visibility",
+ "unknown",
+ "width",
+ "marginheight",
+ "marginwidth"
+ };
+#define spool_attr ((const char *) &spool_attr_contents)
+
+static const struct attrs wordlist_attr[] =
+ {
+#line 157 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str0, ATTR_SRC},
+#line 151 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str1, ATTR_ONSCROLL},
+#line 33 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str2, ATTR_COLS},
+#line 32 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str3, ATTR_COLOR},
+#line 72 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str4, ATTR_ONERROR},
+#line 82 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str5, ATTR_REL},
+#line 59 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str6, ATTR_LOOP},
+#line 127 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str7, ATTR_FOR},
+#line 37 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str8, ATTR_COORDS},
+#line 100 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str9, ATTR_TOP},
+#line 122 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str10, ATTR_CODE},
+#line 87 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str11, ATTR_SCOPE},
+#line 149 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str12, ATTR_ONRESET},
+#line 150 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str13, ATTR_ONSELECT},
+#line 44 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str14, ATTR_FACE},
+#line 131 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str15, ATTR_LABEL},
+#line 56 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str16, ATTR_LEFT},
+#line 21 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str17, ATTR_BORDER},
+#line 99 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str18, ATTR_TEXT},
+#line 39 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str19, ATTR_DEFER},
+#line 22 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str20, ATTR_BORDERCOLOR},
+#line 114 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str21, ATTR_ABBR},
+#line 75 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str22, ATTR_PAGEX},
+#line 143 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str23, ATTR_ONLOAD},
+#line 130 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str24, ATTR_ID},
+#line 91 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str25, ATTR_SELECTED},
+#line 155 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str26, ATTR_PROMPT},
+#line 98 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str27, ATTR_TARGET},
+#line 71 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str28, ATTR_ONABORT},
+#line 120 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str29, ATTR_CLASS},
+#line 38 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str30, ATTR_DECLARE},
+#line 125 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str31, ATTR_DATA},
+#line 30 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str32, ATTR_CLEAR},
+#line 12 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str33, ATTR_ACCEPT},
+#line 154 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str34, ATTR_PROFILE},
+#line 116 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str35, ATTR_ALT},
+#line 103 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str36, ATTR_TYPE},
+#line 135 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str37, ATTR_ONBLUR},
+#line 139 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str38, ATTR_ONFOCUS},
+#line 123 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str39, ATTR_CODEBASE},
+#line 25 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str40, ATTR_CHAR},
+#line 45 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str41, ATTR_FRAME},
+#line 86 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str42, ATTR_RULES},
+#line 35 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str43, ATTR_COMPACT},
+#line 83 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str44, ATTR_REV},
+#line 92 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str45, ATTR_SHAPE},
+#line 28 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str46, ATTR_CHARSET},
+#line 27 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str47, ATTR_CHAROFF},
+#line 54 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str48, ATTR_LANG},
+#line 95 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str49, ATTR_START},
+#line 73 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str50, ATTR_ONRESIZE},
+#line 102 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str51, ATTR_TRUESPEED},
+#line 46 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str52, ATTR_FRAMEBORDER},
+#line 94 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str53, ATTR_SPAN},
+#line 121 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str54, ATTR_CLASSID},
+#line 132 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str55, ATTR_LONGDESC},
+#line 133 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str56, ATTR_NAME},
+#line 53 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str57, ATTR_ISMAP},
+#line 34 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str58, ATTR_COLSPAN},
+#line 63 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str59, ATTR_MEDIA},
+#line 43 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str60, ATTR_ENCTYPE},
+#line 126 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str61, ATTR_DATETIME},
+#line 110 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str62, ATTR_VSPACE},
+#line 137 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str63, ATTR_ONCLICK},
+#line 76 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str64, ATTR_PAGEY},
+#line 161 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str65, ATTR_USEMAP},
+#line 31 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str66, ATTR_CODETYPE},
+#line 90 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str67, ATTR_SCROLLING},
+#line 162 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str68, ATTR_VALUE},
+#line 29 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str69, ATTR_CHECKED},
+#line 152 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str70, ATTR_ONSUBMIT},
+#line 138 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str71, ATTR_ONDBLCLICK},
+#line 40 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str72, ATTR_DIR},
+#line 148 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str73, ATTR_ONMOUSEUP},
+#line 96 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str74, ATTR_STYLE},
+#line 89 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str75, ATTR_SCROLLDELAY},
+#line 119 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str76, ATTR_CITE},
+#line 146 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str77, ATTR_ONMOUSEOUT},
+#line 134 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str78, ATTR_OBJECT},
+#line 65 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str79, ATTR_MULTIPLE},
+#line 17 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str80, ATTR_AXIS},
+#line 115 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str81, ATTR_ACTION},
+#line 97 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str82, ATTR_TABINDEX},
+#line 160 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str83, ATTR_TITLE},
+#line 147 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str84, ATTR_ONMOUSEOVER},
+#line 16 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str85, ATTR_AUTOCOMPLETE},
+#line 153 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str86, ATTR_ONUNLOAD},
+#line 26 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str87, ATTR_CHALLENGE},
+#line 77 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str88, ATTR_PLAIN},
+#line 124 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str89, ATTR_CONTENT},
+#line 67 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str90, ATTR_NORESIZE},
+#line 24 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str91, ATTR_CELLSPACING},
+#line 19 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str92, ATTR_BGCOLOR},
+#line 129 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str93, ATTR_HREF},
+#line 14 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str94, ATTR_ALIGN},
+#line 68 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str95, ATTR_NOSAVE},
+#line 113 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str96, ATTR_Z_INDEX},
+#line 84 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str97, ATTR_ROWS},
+#line 74 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str98, ATTR_OVERSRC},
+#line 93 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str99, ATTR_SIZE},
+#line 141 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str100, ATTR_ONKEYPRESS},
+#line 145 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str101, ATTR_ONMOUSEMOVE},
+#line 107 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str102, ATTR_VERSION},
+#line 23 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str103, ATTR_CELLPADDING},
+#line 55 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str104, ATTR_LANGUAGE},
+#line 101 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str105, ATTR_TOPMARGIN},
+#line 105 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str106, ATTR_VALIGN},
+#line 88 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str107, ATTR_SCROLLAMOUNT},
+#line 42 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str108, ATTR_DISABLED},
+#line 156 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str109, ATTR_SCHEME},
+#line 81 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str110, ATTR_READONLY},
+#line 112 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str111, ATTR_WRAP},
+#line 57 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str112, ATTR_LEFTMARGIN},
+#line 50 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str113, ATTR_HSPACE},
+#line 64 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str114, ATTR_METHOD},
+#line 128 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str115, ATTR_HEADERS},
+#line 13 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str116, ATTR_ACCESSKEY},
+#line 142 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str117, ATTR_ONKEYUP},
+#line 159 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str118, ATTR_SUMMARY},
+#line 51 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str119, ATTR_HTML},
+#line 15 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str120, ATTR_ALINK},
+#line 20 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str121, ATTR_BGPROPERTIES},
+#line 106 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str122, ATTR_VALUETYPE},
+#line 118 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str123, ATTR_BACKGROUND},
+#line 66 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str124, ATTR_NOHREF},
+#line 158 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str125, ATTR_STANDBY},
+#line 80 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str126, ATTR_PLUGINURL},
+#line 78 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str127, ATTR_PLUGINPAGE},
+#line 79 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str128, ATTR_PLUGINSPAGE},
+#line 41 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str129, ATTR_DIRECTION},
+#line 11 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str130, ATTR_ACCEPT_CHARSET},
+#line 109 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str131, ATTR_VLINK},
+#line 69 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str132, ATTR_NOSHADE},
+#line 136 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str133, ATTR_ONCHANGE},
+#line 58 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str134, ATTR_LINK},
+#line 36 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str135, ATTR_CONTENTEDITABLE},
+#line 70 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str136, ATTR_NOWRAP},
+#line 85 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str137, ATTR_ROWSPAN},
+#line 49 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str138, ATTR_HREFLANG},
+#line 62 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str139, ATTR_MAXLENGTH},
+#line 117 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str140, ATTR_ARCHIVE},
+#line 18 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str141, ATTR_BEHAVIOR},
+#line 144 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str142, ATTR_ONMOUSEDOWN},
+#line 48 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str143, ATTR_HIDDEN},
+#line 47 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str144, ATTR_HEIGHT},
+#line 52 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str145, ATTR_HTTP_EQUIV},
+#line 140 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str146, ATTR_ONKEYDOWN},
+#line 108 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str147, ATTR_VISIBILITY},
+#line 104 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str148, ATTR_UNKNOWN},
+#line 111 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str149, ATTR_WIDTH},
+#line 60 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str150, ATTR_MARGINHEIGHT},
+#line 61 "htmlattrs.gperf"
+ {(int)(long)&((struct spool_attr_t *)0)->spool_attr_str151, ATTR_MARGINWIDTH}
+ };
+
+static const short lookup[] =
+ {
+ -1, -1, -1, 0, -1, -1, -1, -1, 1, 2,
+ 3, -1, 4, 5, 6, -1, -1, -1, 7, -1,
+ -1, 8, -1, 9, 10, 11, -1, 12, 13, 14,
+ 15, -1, -1, -1, 16, -1, 17, -1, -1, 18,
+ 19, 20, -1, -1, 21, 22, 23, 24, 25, -1,
+ -1, 26, -1, -1, -1, -1, 27, 28, -1, -1,
+ 29, -1, 30, -1, 31, 32, 33, 34, 35, 36,
+ -1, 37, 38, 39, 40, 41, -1, -1, -1, -1,
+ 42, -1, 43, 44, -1, 45, -1, -1, -1, -1,
+ -1, -1, 46, -1, -1, -1, -1, 47, -1, 48,
+ 49, -1, -1, 50, 51, -1, 52, -1, -1, 53,
+ -1, -1, 54, 55, 56, 57, -1, 58, -1, -1,
+ 59, -1, 60, 61, -1, -1, 62, 63, -1, -1,
+ 64, -1, -1, -1, -1, -1, 65, -1, 66, -1,
+ -1, -1, -1, -1, 67, 68, -1, 69, 70, -1,
+ 71, -1, -1, 72, 73, 74, 75, -1, -1, 76,
+ 77, 78, -1, 79, 80, -1, 81, -1, 82, -1,
+ 83, 84, 85, 86, 87, 88, -1, 89, 90, -1,
+ -1, 91, 92, -1, 93, 94, 95, 96, -1, 97,
+ -1, -1, 98, -1, 99, 100, 101, 102, -1, -1,
+ -1, 103, -1, -1, -1, -1, -1, -1, 104, 105,
+ -1, 106, 107, 108, -1, -1, 109, -1, 110, 111,
+ 112, 113, -1, -1, -1, -1, 114, 115, -1, 116,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 117, -1, -1, -1, -1, 118, -1, 119,
+ 120, -1, -1, -1, -1, -1, -1, 121, -1, 122,
+ 123, 124, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 125, -1, 126, 127, 128, -1, -1, -1,
+ -1, -1, -1, -1, 129, -1, -1, -1, -1, 130,
+ 131, -1, 132, 133, 134, 135, 136, 137, -1, -1,
+ -1, -1, -1, 138, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 139, -1, -1, 140, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 141, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 142, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 143, -1, -1, -1,
+ -1, 144, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 145, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 146, -1, -1, -1, -1, -1,
+ 147, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 148, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 149, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 150, -1, -1, -1, 151
+ };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct attrs *
+findAttr (register const char *str, register unsigned int len)
+{
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_attr (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ register const char *s = wordlist_attr[index].name + spool_attr;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist_attr[index];
+ }
+ }
+ }
+ return 0;
+}
+#line 163 "htmlattrs.gperf"
+
+
+
+static const unsigned short attrList[] = {
+ 65535,
+ 145,
+ 33,
+ 116,
+ 94,
+ 120,
+ 85,
+ 80,
+ 141,
+ 92,
+ 121,
+ 17,
+ 20,
+ 103,
+ 91,
+ 40,
+ 87,
+ 47,
+ 46,
+ 69,
+ 32,
+ 66,
+ 3,
+ 2,
+ 58,
+ 43,
+ 135,
+ 8,
+ 30,
+ 19,
+ 72,
+ 129,
+ 108,
+ 60,
+ 14,
+ 41,
+ 52,
+ 144,
+ 143,
+ 138,
+ 113,
+ 119,
+ 145,
+ 57,
+ 48,
+ 104,
+ 16,
+ 112,
+ 134,
+ 6,
+ 150,
+ 151,
+ 139,
+ 59,
+ 114,
+ 79,
+ 124,
+ 90,
+ 95,
+ 132,
+ 136,
+ 28,
+ 4,
+ 50,
+ 98,
+ 22,
+ 64,
+ 88,
+ 127,
+ 128,
+ 126,
+ 110,
+ 5,
+ 44,
+ 97,
+ 137,
+ 42,
+ 11,
+ 107,
+ 75,
+ 67,
+ 25,
+ 45,
+ 99,
+ 53,
+ 49,
+ 74,
+ 82,
+ 27,
+ 18,
+ 9,
+ 105,
+ 51,
+ 36,
+ 148,
+ 106,
+ 122,
+ 102,
+ 147,
+ 131,
+ 62,
+ 149,
+ 111,
+ 145,
+ 21,
+ 81,
+ 35,
+ 140,
+ 123,
+ 76,
+ 29,
+ 54,
+ 10,
+ 39,
+ 89,
+ 31,
+ 61,
+ 7,
+ 115,
+ 93,
+ 24,
+ 15,
+ 55,
+ 56,
+ 78,
+ 37,
+ 133,
+ 63,
+ 71,
+ 38,
+ 146,
+ 100,
+ 117,
+ 23,
+ 142,
+ 101,
+ 77,
+ 84,
+ 73,
+ 12,
+ 13,
+ 1,
+ 70,
+ 86,
+ 34,
+ 26,
+ 109,
+ 0,
+ 125,
+ 118,
+ 83,
+ 65,
+ 68,
+ 65535
+};
+
+const char* KDE_NO_EXPORT getAttrName(unsigned short id)
+{
+ if (!id || id > TOTAL_KEYWORDS) return "";
+ return spool_attr + wordlist_attr[attrList[id]].name;
+}
diff --git a/tdehtml/misc/htmlattrs.h b/tdehtml/misc/htmlattrs.h
new file mode 100644
index 000000000..d9aaff067
--- /dev/null
+++ b/tdehtml/misc/htmlattrs.h
@@ -0,0 +1,168 @@
+/* This file is automatically generated from
+htmlattrs.in by makeattrs, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef HTML_ATTRS_H
+#define HTML_ATTRS_H
+
+#include "dom/dom_string.h"
+#include <kdemacros.h>
+using namespace DOM;
+
+#define ATTR_ACCEPT_CHARSET 1
+#define ATTR_ACCEPT 2
+#define ATTR_ACCESSKEY 3
+#define ATTR_ALIGN 4
+#define ATTR_ALINK 5
+#define ATTR_AUTOCOMPLETE 6
+#define ATTR_AXIS 7
+#define ATTR_BEHAVIOR 8
+#define ATTR_BGCOLOR 9
+#define ATTR_BGPROPERTIES 10
+#define ATTR_BORDER 11
+#define ATTR_BORDERCOLOR 12
+#define ATTR_CELLPADDING 13
+#define ATTR_CELLSPACING 14
+#define ATTR_CHAR 15
+#define ATTR_CHALLENGE 16
+#define ATTR_CHAROFF 17
+#define ATTR_CHARSET 18
+#define ATTR_CHECKED 19
+#define ATTR_CLEAR 20
+#define ATTR_CODETYPE 21
+#define ATTR_COLOR 22
+#define ATTR_COLS 23
+#define ATTR_COLSPAN 24
+#define ATTR_COMPACT 25
+#define ATTR_CONTENTEDITABLE 26
+#define ATTR_COORDS 27
+#define ATTR_DECLARE 28
+#define ATTR_DEFER 29
+#define ATTR_DIR 30
+#define ATTR_DIRECTION 31
+#define ATTR_DISABLED 32
+#define ATTR_ENCTYPE 33
+#define ATTR_FACE 34
+#define ATTR_FRAME 35
+#define ATTR_FRAMEBORDER 36
+#define ATTR_HEIGHT 37
+#define ATTR_HIDDEN 38
+#define ATTR_HREFLANG 39
+#define ATTR_HSPACE 40
+#define ATTR_HTML 41
+#define ATTR_HTTP_EQUIV 42
+#define ATTR_ISMAP 43
+#define ATTR_LANG 44
+#define ATTR_LANGUAGE 45
+#define ATTR_LEFT 46
+#define ATTR_LEFTMARGIN 47
+#define ATTR_LINK 48
+#define ATTR_LOOP 49
+#define ATTR_MARGINHEIGHT 50
+#define ATTR_MARGINWIDTH 51
+#define ATTR_MAXLENGTH 52
+#define ATTR_MEDIA 53
+#define ATTR_METHOD 54
+#define ATTR_MULTIPLE 55
+#define ATTR_NOHREF 56
+#define ATTR_NORESIZE 57
+#define ATTR_NOSAVE 58
+#define ATTR_NOSHADE 59
+#define ATTR_NOWRAP 60
+#define ATTR_ONABORT 61
+#define ATTR_ONERROR 62
+#define ATTR_ONRESIZE 63
+#define ATTR_OVERSRC 64
+#define ATTR_PAGEX 65
+#define ATTR_PAGEY 66
+#define ATTR_PLAIN 67
+#define ATTR_PLUGINPAGE 68
+#define ATTR_PLUGINSPAGE 69
+#define ATTR_PLUGINURL 70
+#define ATTR_READONLY 71
+#define ATTR_REL 72
+#define ATTR_REV 73
+#define ATTR_ROWS 74
+#define ATTR_ROWSPAN 75
+#define ATTR_RULES 76
+#define ATTR_SCOPE 77
+#define ATTR_SCROLLAMOUNT 78
+#define ATTR_SCROLLDELAY 79
+#define ATTR_SCROLLING 80
+#define ATTR_SELECTED 81
+#define ATTR_SHAPE 82
+#define ATTR_SIZE 83
+#define ATTR_SPAN 84
+#define ATTR_START 85
+#define ATTR_STYLE 86
+#define ATTR_TABINDEX 87
+#define ATTR_TARGET 88
+#define ATTR_TEXT 89
+#define ATTR_TOP 90
+#define ATTR_TOPMARGIN 91
+#define ATTR_TRUESPEED 92
+#define ATTR_TYPE 93
+#define ATTR_UNKNOWN 94
+#define ATTR_VALIGN 95
+#define ATTR_VALUETYPE 96
+#define ATTR_VERSION 97
+#define ATTR_VISIBILITY 98
+#define ATTR_VLINK 99
+#define ATTR_VSPACE 100
+#define ATTR_WIDTH 101
+#define ATTR_WRAP 102
+#define ATTR_Z_INDEX 103
+#define ATTR_ABBR 104
+#define ATTR_ACTION 105
+#define ATTR_ALT 106
+#define ATTR_ARCHIVE 107
+#define ATTR_BACKGROUND 108
+#define ATTR_CITE 109
+#define ATTR_CLASS 110
+#define ATTR_CLASSID 111
+#define ATTR_CODE 112
+#define ATTR_CODEBASE 113
+#define ATTR_CONTENT 114
+#define ATTR_DATA 115
+#define ATTR_DATETIME 116
+#define ATTR_FOR 117
+#define ATTR_HEADERS 118
+#define ATTR_HREF 119
+#define ATTR_ID 120
+#define ATTR_LABEL 121
+#define ATTR_LONGDESC 122
+#define ATTR_NAME 123
+#define ATTR_OBJECT 124
+#define ATTR_ONBLUR 125
+#define ATTR_ONCHANGE 126
+#define ATTR_ONCLICK 127
+#define ATTR_ONDBLCLICK 128
+#define ATTR_ONFOCUS 129
+#define ATTR_ONKEYDOWN 130
+#define ATTR_ONKEYPRESS 131
+#define ATTR_ONKEYUP 132
+#define ATTR_ONLOAD 133
+#define ATTR_ONMOUSEDOWN 134
+#define ATTR_ONMOUSEMOVE 135
+#define ATTR_ONMOUSEOUT 136
+#define ATTR_ONMOUSEOVER 137
+#define ATTR_ONMOUSEUP 138
+#define ATTR_ONRESET 139
+#define ATTR_ONSELECT 140
+#define ATTR_ONSCROLL 141
+#define ATTR_ONSUBMIT 142
+#define ATTR_ONUNLOAD 143
+#define ATTR_PROFILE 144
+#define ATTR_PROMPT 145
+#define ATTR_SCHEME 146
+#define ATTR_SRC 147
+#define ATTR_STANDBY 148
+#define ATTR_SUMMARY 149
+#define ATTR_TITLE 150
+#define ATTR_USEMAP 151
+#define ATTR_VALUE 152
+#define ATTR_LAST_ATTR 152
+#define ATTR_LAST_CI_ATTR 103
+const char* getAttrName(unsigned short id) KDE_NO_EXPORT;
+
+#endif
diff --git a/tdehtml/misc/htmlattrs.in b/tdehtml/misc/htmlattrs.in
new file mode 100644
index 000000000..263b2fd7b
--- /dev/null
+++ b/tdehtml/misc/htmlattrs.in
@@ -0,0 +1,157 @@
+# First, list attributes with a case-insensitive value
+accept-charset
+accept
+accesskey
+align
+alink
+autocomplete
+axis
+behavior
+bgcolor
+bgproperties
+border
+bordercolor
+cellpadding
+cellspacing
+char
+challenge
+charoff
+charset
+checked
+clear
+codetype
+color
+cols
+colspan
+compact
+contenteditable
+coords
+declare
+defer
+dir
+direction
+disabled
+enctype
+face
+frame
+frameborder
+height
+hidden
+hreflang
+hspace
+html
+http-equiv
+ismap
+lang
+language
+left
+leftmargin
+link
+loop
+marginheight
+marginwidth
+maxlength
+media
+method
+multiple
+nohref
+noresize
+nosave
+noshade
+nowrap
+onabort
+onerror
+onresize
+oversrc
+pagex
+pagey
+plain
+pluginpage
+pluginspage
+pluginurl
+readonly
+rel
+rev
+rows
+rowspan
+rules
+scope
+scrollamount
+scrolldelay
+scrolling
+selected
+shape
+size
+span
+start
+style
+tabindex
+target
+text
+top
+topmargin
+truespeed
+type
+unknown
+valign
+valuetype
+version
+visibility
+vlink
+vspace
+width
+wrap
+z-index
+END_CI_ATTRIBUTES
+
+# Then attributes listed as [CS] and [CT] in the HTML specification,
+# which value is to be treated case sensitively.
+abbr
+action
+alt
+archive
+background
+cite
+class
+classid
+code
+codebase
+content
+data
+datetime
+for
+headers
+href
+id
+label
+longdesc
+name
+object
+onblur
+onchange
+onclick
+ondblclick
+onfocus
+onkeydown
+onkeypress
+onkeyup
+onload
+onmousedown
+onmousemove
+onmouseout
+onmouseover
+onmouseup
+onreset
+onselect
+onscroll
+onsubmit
+onunload
+profile
+prompt
+scheme
+src
+standby
+summary
+title
+usemap
+value
diff --git a/tdehtml/misc/htmlhashes.cpp b/tdehtml/misc/htmlhashes.cpp
new file mode 100644
index 000000000..e073f0964
--- /dev/null
+++ b/tdehtml/misc/htmlhashes.cpp
@@ -0,0 +1,45 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.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 <kglobal.h>
+
+#include "htmlhashes.h"
+#include "htmltags.c"
+#include "htmlattrs.c"
+
+int tdehtml::getTagID(const char *tagStr, int len)
+{
+ const struct tags *tagPtr = findTag(tagStr, len);
+ if (!tagPtr)
+ return 0;
+
+ return tagPtr->id;
+}
+
+int tdehtml::getAttrID(const char *tagStr, int len)
+{
+ const struct attrs *tagPtr = findAttr(tagStr, len);
+ if (!tagPtr)
+ return 0;
+
+ return tagPtr->id;
+}
+
diff --git a/tdehtml/misc/htmlhashes.h b/tdehtml/misc/htmlhashes.h
new file mode 100644
index 000000000..dfea9a289
--- /dev/null
+++ b/tdehtml/misc/htmlhashes.h
@@ -0,0 +1,14 @@
+#ifndef HTMLHASHES_H
+#define HTMLHASHES_H
+
+#include "xml/dom_stringimpl.h"
+#include "htmlattrs.h"
+#include "htmltags.h"
+
+namespace tdehtml
+{
+ int getTagID(const char *tagStr, int len);
+ int getAttrID(const char *tagStr, int len);
+}
+
+#endif
diff --git a/tdehtml/misc/htmltags.c b/tdehtml/misc/htmltags.c
new file mode 100644
index 000000000..1342e62bf
--- /dev/null
+++ b/tdehtml/misc/htmltags.c
@@ -0,0 +1,687 @@
+/* ANSI-C code produced by gperf version 3.0.1 */
+/* Command-line: gperf -a -L ANSI-C -P -D -E -C -l -o -t -k '*' -NfindTag -Hhash_tag -Wwordlist_tag -Qspool_Tag htmltags.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 "htmltags.gperf"
+
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+#include "htmltags.h"
+#line 6 "htmltags.gperf"
+struct tags {
+ int name;
+ int id;
+};
+/* maximum key range = 345, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash_tag (register const char *str, register unsigned int len)
+{
+ static const unsigned short asso_values[] =
+ {
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 70, 60, 55, 40, 25, 15, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 15, 10, 35,
+ 10, 5, 10, 0, 55, 40, 70, 30, 5, 15,
+ 30, 50, 5, 50, 20, 0, 0, 90, 120, 5,
+ 15, 35, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346, 346, 346, 346,
+ 346, 346, 346, 346, 346, 346, 346
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ 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]+1];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval;
+}
+
+struct spool_Tag_t
+ {
+ char spool_Tag_str0[sizeof("s")];
+ char spool_Tag_str1[sizeof("tr")];
+ char spool_Tag_str2[sizeof("p")];
+ char spool_Tag_str3[sizeof("td")];
+ char spool_Tag_str4[sizeof("b")];
+ char spool_Tag_str5[sizeof("br")];
+ char spool_Tag_str6[sizeof("pre")];
+ char spool_Tag_str7[sizeof("a")];
+ char spool_Tag_str8[sizeof("dd")];
+ char spool_Tag_str9[sizeof("dl")];
+ char spool_Tag_str10[sizeof("del")];
+ char spool_Tag_str11[sizeof("base")];
+ char spool_Tag_str12[sizeof("map")];
+ char spool_Tag_str13[sizeof("samp")];
+ char spool_Tag_str14[sizeof("table")];
+ char spool_Tag_str15[sizeof("em")];
+ char spool_Tag_str16[sizeof("area")];
+ char spool_Tag_str17[sizeof("label")];
+ char spool_Tag_str18[sizeof("i")];
+ char spool_Tag_str19[sizeof("th")];
+ char spool_Tag_str20[sizeof("dfn")];
+ char spool_Tag_str21[sizeof("meta")];
+ char spool_Tag_str22[sizeof("col")];
+ char spool_Tag_str23[sizeof("font")];
+ char spool_Tag_str24[sizeof("frame")];
+ char spool_Tag_str25[sizeof("q")];
+ char spool_Tag_str26[sizeof("xmp")];
+ char spool_Tag_str27[sizeof("form")];
+ char spool_Tag_str28[sizeof("hr")];
+ char spool_Tag_str29[sizeof("frameset")];
+ char spool_Tag_str30[sizeof("code")];
+ char spool_Tag_str31[sizeof("small")];
+ char spool_Tag_str32[sizeof("select")];
+ char spool_Tag_str33[sizeof("address")];
+ char spool_Tag_str34[sizeof("wbr")];
+ char spool_Tag_str35[sizeof("body")];
+ char spool_Tag_str36[sizeof("embed")];
+ char spool_Tag_str37[sizeof("legend")];
+ char spool_Tag_str38[sizeof("ol")];
+ char spool_Tag_str39[sizeof("bdo")];
+ char spool_Tag_str40[sizeof("nobr")];
+ char spool_Tag_str41[sizeof("param")];
+ char spool_Tag_str42[sizeof("h6")];
+ char spool_Tag_str43[sizeof("img")];
+ char spool_Tag_str44[sizeof("thead")];
+ char spool_Tag_str45[sizeof("li")];
+ char spool_Tag_str46[sizeof("kbd")];
+ char spool_Tag_str47[sizeof("layer")];
+ char spool_Tag_str48[sizeof("script")];
+ char spool_Tag_str49[sizeof("h5")];
+ char spool_Tag_str50[sizeof("big")];
+ char spool_Tag_str51[sizeof("abbr")];
+ char spool_Tag_str52[sizeof("title")];
+ char spool_Tag_str53[sizeof("applet")];
+ char spool_Tag_str54[sizeof("noembed")];
+ char spool_Tag_str55[sizeof("textarea")];
+ char spool_Tag_str56[sizeof("u")];
+ char spool_Tag_str57[sizeof("tt")];
+ char spool_Tag_str58[sizeof("ins")];
+ char spool_Tag_str59[sizeof("head")];
+ char spool_Tag_str60[sizeof("image")];
+ char spool_Tag_str61[sizeof("h4")];
+ char spool_Tag_str62[sizeof("span")];
+ char spool_Tag_str63[sizeof("iframe")];
+ char spool_Tag_str64[sizeof("dt")];
+ char spool_Tag_str65[sizeof("dir")];
+ char spool_Tag_str66[sizeof("tfoot")];
+ char spool_Tag_str67[sizeof("center")];
+ char spool_Tag_str68[sizeof("ul")];
+ char spool_Tag_str69[sizeof("noframes")];
+ char spool_Tag_str70[sizeof("h3")];
+ char spool_Tag_str71[sizeof("fieldset")];
+ char spool_Tag_str72[sizeof("cite")];
+ char spool_Tag_str73[sizeof("keygen")];
+ char spool_Tag_str74[sizeof("h2")];
+ char spool_Tag_str75[sizeof("nolayer")];
+ char spool_Tag_str76[sizeof("basefont")];
+ char spool_Tag_str77[sizeof("h1")];
+ char spool_Tag_str78[sizeof("sup")];
+ char spool_Tag_str79[sizeof("sub")];
+ char spool_Tag_str80[sizeof("plaintext")];
+ char spool_Tag_str81[sizeof("tbody")];
+ char spool_Tag_str82[sizeof("ilayer")];
+ char spool_Tag_str83[sizeof("link")];
+ char spool_Tag_str84[sizeof("style")];
+ char spool_Tag_str85[sizeof("noscript")];
+ char spool_Tag_str86[sizeof("isindex")];
+ char spool_Tag_str87[sizeof("menu")];
+ char spool_Tag_str88[sizeof("listing")];
+ char spool_Tag_str89[sizeof("var")];
+ char spool_Tag_str90[sizeof("html")];
+ char spool_Tag_str91[sizeof("caption")];
+ char spool_Tag_str92[sizeof("acronym")];
+ char spool_Tag_str93[sizeof("input")];
+ char spool_Tag_str94[sizeof("strike")];
+ char spool_Tag_str95[sizeof("strong")];
+ char spool_Tag_str96[sizeof("object")];
+ char spool_Tag_str97[sizeof("marquee")];
+ char spool_Tag_str98[sizeof("div")];
+ char spool_Tag_str99[sizeof("button")];
+ char spool_Tag_str100[sizeof("colgroup")];
+ char spool_Tag_str101[sizeof("option")];
+ char spool_Tag_str102[sizeof("anchor")];
+ char spool_Tag_str103[sizeof("optgroup")];
+ char spool_Tag_str104[sizeof("blockquote")];
+ };
+static const struct spool_Tag_t spool_Tag_contents =
+ {
+ "s",
+ "tr",
+ "p",
+ "td",
+ "b",
+ "br",
+ "pre",
+ "a",
+ "dd",
+ "dl",
+ "del",
+ "base",
+ "map",
+ "samp",
+ "table",
+ "em",
+ "area",
+ "label",
+ "i",
+ "th",
+ "dfn",
+ "meta",
+ "col",
+ "font",
+ "frame",
+ "q",
+ "xmp",
+ "form",
+ "hr",
+ "frameset",
+ "code",
+ "small",
+ "select",
+ "address",
+ "wbr",
+ "body",
+ "embed",
+ "legend",
+ "ol",
+ "bdo",
+ "nobr",
+ "param",
+ "h6",
+ "img",
+ "thead",
+ "li",
+ "kbd",
+ "layer",
+ "script",
+ "h5",
+ "big",
+ "abbr",
+ "title",
+ "applet",
+ "noembed",
+ "textarea",
+ "u",
+ "tt",
+ "ins",
+ "head",
+ "image",
+ "h4",
+ "span",
+ "iframe",
+ "dt",
+ "dir",
+ "tfoot",
+ "center",
+ "ul",
+ "noframes",
+ "h3",
+ "fieldset",
+ "cite",
+ "keygen",
+ "h2",
+ "nolayer",
+ "basefont",
+ "h1",
+ "sup",
+ "sub",
+ "plaintext",
+ "tbody",
+ "ilayer",
+ "link",
+ "style",
+ "noscript",
+ "isindex",
+ "menu",
+ "listing",
+ "var",
+ "html",
+ "caption",
+ "acronym",
+ "input",
+ "strike",
+ "strong",
+ "object",
+ "marquee",
+ "div",
+ "button",
+ "colgroup",
+ "option",
+ "anchor",
+ "optgroup",
+ "blockquote"
+ };
+#define spool_Tag ((const char *) &spool_Tag_contents)
+#ifdef __GNUC__
+__inline
+#endif
+const struct tags *
+findTag (register const char *str, register unsigned int len)
+{
+ enum
+ {
+ TOTAL_KEYWORDS = 105,
+ MIN_WORD_LENGTH = 1,
+ MAX_WORD_LENGTH = 10,
+ MIN_HASH_VALUE = 1,
+ MAX_HASH_VALUE = 345
+ };
+
+ static const unsigned char lengthtable[] =
+ {
+ 1, 2, 1, 2, 1, 2, 3, 1, 2, 2, 3, 4, 3, 4,
+ 5, 2, 4, 5, 1, 2, 3, 4, 3, 4, 5, 1, 3, 4,
+ 2, 8, 4, 5, 6, 7, 3, 4, 5, 6, 2, 3, 4, 5,
+ 2, 3, 5, 2, 3, 5, 6, 2, 3, 4, 5, 6, 7, 8,
+ 1, 2, 3, 4, 5, 2, 4, 6, 2, 3, 5, 6, 2, 8,
+ 2, 8, 4, 6, 2, 7, 8, 2, 3, 3, 9, 5, 6, 4,
+ 5, 8, 7, 4, 7, 3, 4, 7, 7, 5, 6, 6, 6, 7,
+ 3, 6, 8, 6, 6, 8, 10
+ };
+ static const struct tags wordlist_tag[] =
+ {
+#line 87 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str0, ID_S},
+#line 106 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str1, ID_TR},
+#line 82 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str2, ID_P},
+#line 100 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str3, ID_TD},
+#line 17 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str4, ID_B},
+#line 24 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str5, ID_BR},
+#line 85 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str6, ID_PRE},
+#line 11 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str7, ID_A},
+#line 32 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str8, ID_DD},
+#line 37 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str9, ID_DL},
+#line 33 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str10, ID_DEL},
+#line 18 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str11, ID_BASE},
+#line 69 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str12, ID_MAP},
+#line 88 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str13, ID_SAMP},
+#line 98 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str14, ID_TABLE},
+#line 39 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str15, ID_EM},
+#line 16 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str16, ID_AREA},
+#line 64 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str17, ID_LABEL},
+#line 55 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str18, ID_I},
+#line 103 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str19, ID_TH},
+#line 34 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str20, ID_DFN},
+#line 72 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str21, ID_META},
+#line 30 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str22, ID_COL},
+#line 42 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str23, ID_FONT},
+#line 44 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str24, ID_FRAME},
+#line 86 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str25, ID_Q},
+#line 112 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str26, ID_XMP},
+#line 43 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str27, ID_FORM},
+#line 53 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str28, ID_HR},
+#line 45 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str29, ID_FRAMESET},
+#line 29 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str30, ID_CODE},
+#line 91 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str31, ID_SMALL},
+#line 90 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str32, ID_SELECT},
+#line 14 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str33, ID_ADDRESS},
+#line 111 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str34, ID_WBR},
+#line 23 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str35, ID_BODY},
+#line 40 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str36, ID_EMBED},
+#line 66 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str37, ID_LEGEND},
+#line 79 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str38, ID_OL},
+#line 20 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str39, ID_BDO},
+#line 73 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str40, ID_NOBR},
+#line 83 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str41, ID_PARAM},
+#line 51 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str42, ID_H6},
+#line 58 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str43, ID_IMG},
+#line 104 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str44, ID_THEAD},
+#line 67 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str45, ID_LI},
+#line 62 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str46, ID_KBD},
+#line 65 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str47, ID_LAYER},
+#line 89 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str48, ID_SCRIPT},
+#line 50 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str49, ID_H5},
+#line 21 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str50, ID_BIG},
+#line 12 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str51, ID_ABBR},
+#line 105 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str52, ID_TITLE},
+#line 15 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str53, ID_APPLET},
+#line 74 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str54, ID_NOEMBED},
+#line 101 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str55, ID_TEXTAREA},
+#line 108 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str56, ID_U},
+#line 107 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str57, ID_TT},
+#line 60 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str58, ID_INS},
+#line 52 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str59, ID_HEAD},
+#line 114 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str60, ID_IMG},
+#line 49 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str61, ID_H4},
+#line 92 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str62, ID_SPAN},
+#line 56 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str63, ID_IFRAME},
+#line 38 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str64, ID_DT},
+#line 35 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str65, ID_DIR},
+#line 102 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str66, ID_TFOOT},
+#line 27 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str67, ID_CENTER},
+#line 109 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str68, ID_UL},
+#line 75 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str69, ID_NOFRAMES},
+#line 48 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str70, ID_H3},
+#line 41 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str71, ID_FIELDSET},
+#line 28 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str72, ID_CITE},
+#line 63 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str73, ID_KEYGEN},
+#line 47 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str74, ID_H2},
+#line 77 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str75, ID_NOLAYER},
+#line 19 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str76, ID_BASEFONT},
+#line 46 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str77, ID_H1},
+#line 97 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str78, ID_SUP},
+#line 96 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str79, ID_SUB},
+#line 84 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str80, ID_PLAINTEXT},
+#line 99 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str81, ID_TBODY},
+#line 57 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str82, ID_ILAYER},
+#line 68 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str83, ID_LINK},
+#line 95 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str84, ID_STYLE},
+#line 76 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str85, ID_NOSCRIPT},
+#line 61 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str86, ID_ISINDEX},
+#line 71 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str87, ID_MENU},
+#line 115 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str88, ID_PRE},
+#line 110 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str89, ID_VAR},
+#line 54 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str90, ID_HTML},
+#line 26 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str91, ID_CAPTION},
+#line 13 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str92, ID_ACRONYM},
+#line 59 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str93, ID_INPUT},
+#line 93 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str94, ID_STRIKE},
+#line 94 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str95, ID_STRONG},
+#line 78 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str96, ID_OBJECT},
+#line 70 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str97, ID_MARQUEE},
+#line 36 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str98, ID_DIV},
+#line 25 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str99, ID_BUTTON},
+#line 31 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str100, ID_COLGROUP},
+#line 81 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str101, ID_OPTION},
+#line 113 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str102, ID_A},
+#line 80 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str103, ID_OPTGROUP},
+#line 22 "htmltags.gperf"
+ {(int)(long)&((struct spool_Tag_t *)0)->spool_Tag_str104, ID_BLOCKQUOTE}
+ };
+
+ static const signed char lookup[] =
+ {
+ -1, 0, 1, -1, -1, -1, 2, 3, -1, -1,
+ -1, 4, 5, 6, -1, -1, 7, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 9, 10, 11,
+ -1, -1, -1, 12, 13, 14, -1, 15, -1, 16,
+ 17, 18, 19, 20, 21, -1, -1, -1, 22, 23,
+ 24, 25, -1, 26, 27, -1, -1, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, -1, 42, 43, -1, 44, -1, 45, 46, -1,
+ 47, 48, 49, 50, 51, 52, 53, 54, 55, -1,
+ -1, 56, 57, 58, 59, 60, -1, 61, -1, 62,
+ -1, 63, 64, 65, -1, 66, 67, 68, 69, -1,
+ -1, -1, 70, 71, 72, -1, 73, 74, -1, -1,
+ -1, -1, 75, 76, -1, -1, -1, 77, 78, -1,
+ -1, -1, -1, 79, 80, 81, 82, -1, -1, 83,
+ 84, -1, -1, 85, -1, -1, -1, 86, -1, 87,
+ -1, -1, 88, 89, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 90,
+ -1, -1, -1, -1, -1, -1, -1, 91, -1, -1,
+ -1, -1, 92, -1, -1, -1, -1, -1, -1, -1,
+ 93, 94, -1, -1, -1, -1, 95, -1, -1, -1,
+ -1, 96, 97, 98, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 99, -1, 100, -1,
+ -1, -1, -1, -1, -1, -1, 101, -1, -1, -1,
+ -1, 102, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 103, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 104
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash_tag (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register int index = lookup[key];
+
+ if (index >= 0)
+ {
+ if (len == lengthtable[index])
+ {
+ register const char *s = wordlist_tag[index].name + spool_Tag;
+
+ if (*str == *s && !memcmp (str + 1, s + 1, len - 1))
+ return &wordlist_tag[index];
+ }
+ }
+ }
+ }
+ return 0;
+}
+#line 116 "htmltags.gperf"
+
+
+
+static const char tagStable[] = {
+ "\000/a\000/abbr\000/acronym\000/address\000/applet\000/area\000/b"
+ "\000/base\000/basefont\000/bdo\000/big\000/blockquote\000/body"
+ "\000/br\000/button\000/caption\000/center\000/cite\000/code\000/col"
+ "\000/colgroup\000/dd\000/del\000/dfn\000/dir\000/div\000/dl\000/dt"
+ "\000/em\000/embed\000/fieldset\000/font\000/form\000/frame\000/frameset"
+ "\000/h1\000/h2\000/h3\000/h4\000/h5\000/h6\000/head\000/hr\000/html"
+ "\000/i\000/iframe\000/ilayer\000/img\000/input\000/ins\000/isindex"
+ "\000/kbd\000/keygen\000/label\000/layer\000/legend\000/li\000/link"
+ "\000/map\000/marquee\000/menu\000/meta\000/nobr\000/noembed\000/noframes"
+ "\000/noscript\000/nolayer\000/object\000/ol\000/optgroup\000/option"
+ "\000/p\000/param\000/plaintext\000/pre\000/q\000/s\000/samp\000/script"
+ "\000/select\000/small\000/span\000/strike\000/strong\000/style"
+ "\000/sub\000/sup\000/table\000/tbody\000/td\000/textarea\000/tfoot"
+ "\000/th\000/thead\000/title\000/tr\000/tt\000/u\000/ul\000/var"
+ "\000/wbr\000/xmp\000/text\000/comment\000"
+};
+
+static const unsigned short tagSList[] = {
+ 0,
+
+ 2, 5, 11, 20, 29, 37, 43, 46, 52, 62, 67, 72,
+ 84, 90, 94, 102, 111, 119, 125, 131, 136, 146, 150, 155,
+ 160, 165, 170, 174, 178, 182, 189, 199, 205, 211, 218, 228,
+ 232, 236, 240, 244, 248, 252, 258, 262, 268, 271, 279, 287,
+ 292, 299, 304, 313, 318, 326, 333, 340, 348, 352, 358, 363,
+ 372, 378, 384, 390, 399, 409, 419, 428, 436, 440, 450, 458,
+ 461, 468, 479, 484, 487, 490, 496, 504, 512, 519, 525, 533,
+ 541, 548, 553, 558, 565, 572, 576, 586, 593, 597, 604, 611,
+ 615, 619, 622, 626, 631, 636, 641, 647, 1, 4, 10, 19,
+ 28, 36, 42, 45, 51, 61, 66, 71, 83, 89, 93, 101,
+ 110, 118, 124, 130, 135, 145, 149, 154, 159, 164, 169, 173,
+ 177, 181, 188, 198, 204, 210, 217, 227, 231, 235, 239, 243,
+ 247, 251, 257, 261, 267, 270, 278, 286, 291, 298, 303, 312,
+ 317, 325, 332, 339, 347, 351, 357, 362, 371, 377, 383, 389,
+ 398, 408, 418, 427, 435, 439, 449, 457, 460, 467, 478, 483,
+ 486, 489, 495, 503, 511, 518, 524, 532, 540, 547, 552, 557,
+ 564, 571, 575, 585, 592, 596, 603, 610, 614, 618, 621, 625,
+ 630, 635, 640, 646, 0
+};
+
+const char* KDE_NO_EXPORT getTagName(unsigned short id)
+{
+ if(id > ID_CLOSE_TAG*2) id = ID_CLOSE_TAG+1;
+ return &tagStable[tagSList[id]];
+}
diff --git a/tdehtml/misc/htmltags.h b/tdehtml/misc/htmltags.h
new file mode 100644
index 000000000..a2fb0fe55
--- /dev/null
+++ b/tdehtml/misc/htmltags.h
@@ -0,0 +1,119 @@
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef KHTML_TAGS_H
+#define KHTML_TAGS_H
+
+#include "dom/dom_string.h"
+#include <kglobal.h>
+
+KDE_NO_EXPORT const char* getTagName(unsigned short id);
+
+#define ID_A 1
+#define ID_ABBR 2
+#define ID_ACRONYM 3
+#define ID_ADDRESS 4
+#define ID_APPLET 5
+#define ID_AREA 6
+#define ID_B 7
+#define ID_BASE 8
+#define ID_BASEFONT 9
+#define ID_BDO 10
+#define ID_BIG 11
+#define ID_BLOCKQUOTE 12
+#define ID_BODY 13
+#define ID_BR 14
+#define ID_BUTTON 15
+#define ID_CAPTION 16
+#define ID_CENTER 17
+#define ID_CITE 18
+#define ID_CODE 19
+#define ID_COL 20
+#define ID_COLGROUP 21
+#define ID_DD 22
+#define ID_DEL 23
+#define ID_DFN 24
+#define ID_DIR 25
+#define ID_DIV 26
+#define ID_DL 27
+#define ID_DT 28
+#define ID_EM 29
+#define ID_EMBED 30
+#define ID_FIELDSET 31
+#define ID_FONT 32
+#define ID_FORM 33
+#define ID_FRAME 34
+#define ID_FRAMESET 35
+#define ID_H1 36
+#define ID_H2 37
+#define ID_H3 38
+#define ID_H4 39
+#define ID_H5 40
+#define ID_H6 41
+#define ID_HEAD 42
+#define ID_HR 43
+#define ID_HTML 44
+#define ID_I 45
+#define ID_IFRAME 46
+#define ID_ILAYER 47
+#define ID_IMG 48
+#define ID_INPUT 49
+#define ID_INS 50
+#define ID_ISINDEX 51
+#define ID_KBD 52
+#define ID_KEYGEN 53
+#define ID_LABEL 54
+#define ID_LAYER 55
+#define ID_LEGEND 56
+#define ID_LI 57
+#define ID_LINK 58
+#define ID_MAP 59
+#define ID_MARQUEE 60
+#define ID_MENU 61
+#define ID_META 62
+#define ID_NOBR 63
+#define ID_NOEMBED 64
+#define ID_NOFRAMES 65
+#define ID_NOSCRIPT 66
+#define ID_NOLAYER 67
+#define ID_OBJECT 68
+#define ID_OL 69
+#define ID_OPTGROUP 70
+#define ID_OPTION 71
+#define ID_P 72
+#define ID_PARAM 73
+#define ID_PLAINTEXT 74
+#define ID_PRE 75
+#define ID_Q 76
+#define ID_S 77
+#define ID_SAMP 78
+#define ID_SCRIPT 79
+#define ID_SELECT 80
+#define ID_SMALL 81
+#define ID_SPAN 82
+#define ID_STRIKE 83
+#define ID_STRONG 84
+#define ID_STYLE 85
+#define ID_SUB 86
+#define ID_SUP 87
+#define ID_TABLE 88
+#define ID_TBODY 89
+#define ID_TD 90
+#define ID_TEXTAREA 91
+#define ID_TFOOT 92
+#define ID_TH 93
+#define ID_THEAD 94
+#define ID_TITLE 95
+#define ID_TR 96
+#define ID_TT 97
+#define ID_U 98
+#define ID_UL 99
+#define ID_VAR 100
+#define ID_WBR 101
+#define ID_XMP 102
+#define ID_TEXT 103
+#define ID_COMMENT 104
+#define ID_CLOSE_TAG 104
+#define ID_LAST_TAG 104
+
+#endif
diff --git a/tdehtml/misc/htmltags.in b/tdehtml/misc/htmltags.in
new file mode 100644
index 000000000..9d686364a
--- /dev/null
+++ b/tdehtml/misc/htmltags.in
@@ -0,0 +1,102 @@
+a
+abbr
+acronym
+address
+applet
+area
+b
+base
+basefont
+bdo
+big
+blockquote
+body
+br
+button
+caption
+center
+cite
+code
+col
+colgroup
+dd
+del
+dfn
+dir
+div
+dl
+dt
+em
+embed
+fieldset
+font
+form
+frame
+frameset
+h1
+h2
+h3
+h4
+h5
+h6
+head
+hr
+html
+i
+iframe
+ilayer
+img
+input
+ins
+isindex
+kbd
+keygen
+label
+layer
+legend
+li
+link
+map
+marquee
+menu
+meta
+nobr
+noembed
+noframes
+noscript
+nolayer
+object
+ol
+optgroup
+option
+p
+param
+plaintext
+pre
+q
+s
+samp
+script
+select
+small
+span
+strike
+strong
+style
+sub
+sup
+table
+tbody
+td
+textarea
+tfoot
+th
+thead
+title
+tr
+tt
+u
+ul
+var
+wbr
+xmp
diff --git a/tdehtml/misc/knsplugininstaller.cpp b/tdehtml/misc/knsplugininstaller.cpp
new file mode 100644
index 000000000..b953f34fb
--- /dev/null
+++ b/tdehtml/misc/knsplugininstaller.cpp
@@ -0,0 +1,671 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2005 Benoit Canet <bcanet@dental-on-line.fr>
+ Copyright (C) 2005 Aurelien Gateau <agateau@dental-on-line.fr>
+
+ 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 "knsplugininstaller.moc"
+
+#include <kdebug.h>
+#include <kdiroperator.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kstddirs.h>
+#include <ktempfile.h>
+#include <netaccess.h>
+
+#include <tqbuttongroup.h>
+#include <tqdir.h>
+#include <tqiodevice.h>
+#include <tqfile.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqmap.h>
+#include <tqstringlist.h>
+#include <tqtextstream.h>
+
+#include <sys/utsname.h>
+
+// Use 6031 for debugging (render_frame)
+#define DEBUG_NUMBER 6031
+
+/*
+ * Utility class to associate a list item with a pluginInfo object
+ */
+class PluginListItem : public TQListViewItem
+{
+
+public:
+ PluginListItem(KNSPluginInfo pluginInfo, TQListView *parent)
+ : TQListViewItem(parent, pluginInfo.pluginName())
+ , m_pluginInfo(pluginInfo) {}
+ KNSPluginInfo pluginInfo() const { return m_pluginInfo; }
+
+private:
+ KNSPluginInfo m_pluginInfo;
+
+};
+
+
+// public methods
+
+KNSPluginInstallEngine::KNSPluginInstallEngine(KMimeType::Ptr mime) : TQObject()
+{
+ m_mime = mime;
+
+ // Fill the architecture map
+ m_archMap["i386"] = "ia32";
+ m_archMap["i486"] = "ia32";
+ m_archMap["i586"] = "ia32";
+ m_archMap["i686"] = "ia32";
+}
+
+KNSPluginInstallEngine::~KNSPluginInstallEngine()
+{
+}
+
+bool KNSPluginInstallEngine::pluginAvailable()
+{
+
+ if(m_pluginList.count())
+ return true;
+
+ // check if pluginsListFile is present in kde config
+ if(!loadConfig())
+ return false;
+
+ // load the xml configuration file
+ if(!loadXmlConfig())
+ return false;
+
+ return findPlugin();
+}
+
+bool KNSPluginInstallEngine::isActive()
+{
+ // check if we have a configuration key in the kde registry
+ TQString pluginsListFile;
+ TDEConfig cfg("kcmnspluginrc", true);
+ cfg.setGroup("Misc");
+ pluginsListFile = cfg.readPathEntry("PluginsListFile");
+ return !pluginsListFile.isEmpty();
+}
+
+const TQValueList<KNSPluginInfo>& KNSPluginInstallEngine::pluginList() const
+{
+ return m_pluginList;
+}
+
+// private methods
+bool KNSPluginInstallEngine::loadConfig()
+{
+ TQString pluginsListFile;
+ TDEConfig cfg("kcmnspluginrc", true);
+ cfg.setGroup("Misc");
+ pluginsListFile = cfg.readPathEntry("PluginsListFile");
+ if(!pluginsListFile.isEmpty())
+ {
+ m_pluginsListFileURL = KURL(pluginsListFile);
+ kdDebug(DEBUG_NUMBER) << "config loaded "<<endl;
+ return true;
+ }
+ return false;
+}
+
+bool KNSPluginInstallEngine::loadXmlConfig()
+{
+
+ // load the Xml configuration file
+ if(m_pluginsXmlConfig.isEmpty())
+ {
+ TQString tmpFile;
+ if(TDEIO::NetAccess::download(m_pluginsListFileURL, tmpFile, NULL)) {
+ TQFile f(tmpFile);
+ if(!f.open(IO_ReadOnly))
+ return false;
+ TQTextStream stream(&f);
+ stream.setEncoding(TQTextStream::UnicodeUTF8);
+ m_pluginsXmlConfig = stream.read();
+ f.close();
+ TDEIO::NetAccess::removeTempFile(tmpFile);
+ } else
+ return false;
+ }
+ kdDebug(DEBUG_NUMBER) << "xml config loaded :" << endl;
+ return true;
+}
+
+bool KNSPluginInstallEngine::findPlugin()
+{
+
+ // get system infos
+ // TODO/FIX : correct this to work with x86-64 machines
+ utsname sysinfo;
+ if(uname(&sysinfo))
+ return false;
+ TQString sysname(sysinfo.sysname);
+ TQString machine(sysinfo.machine);
+ TQString arch = m_archMap[machine];
+
+ // Parse the document
+ TQDomDocument doc("xmlConfig");
+ doc.setContent(m_pluginsXmlConfig);
+ TQDomNodeList archList = doc.elementsByTagName(TQString("arch"));
+ TQDomNode archNode, osNode , pluginNode, node;
+ TQDomElement e;
+
+ // look for the correct architecture
+ bool found = false;
+ unsigned int i;
+ for(i=0; i < archList.count() ; i++) {
+ archNode = archList.item(i);
+ e = archNode.toElement();
+ if( e.attribute("architecture") == arch) {
+ kdDebug(DEBUG_NUMBER) << "found correct architecture :" << arch << endl;
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ return false;
+
+ // look for the correct os
+ found = false;
+ osNode = archNode.firstChild();
+ while(!osNode.isNull()) {
+ e = osNode.toElement();
+ if( e.tagName() == "os" && e.attribute("name") == sysname) {
+ kdDebug(DEBUG_NUMBER) << "found correct os :" << sysname << endl;
+ found = true;
+ break;
+ }
+ osNode=osNode.nextSibling();
+ }
+
+ if(!found)
+ return false;
+
+ // Look for a plugin with the given mimetype
+ pluginNode = osNode.firstChild();
+ while(!pluginNode.isNull()) {
+ e = pluginNode.toElement();
+ if( e.tagName() == "plugin" && m_mime->is(e.attribute("mimetype")) ) {
+ kdDebug(DEBUG_NUMBER) << "found correct plugin :" << e.attribute("mimetype") << endl;
+ KNSPluginInfo pluginInfo(pluginNode);
+ if(pluginInfo.isValid())
+ m_pluginList.append(pluginInfo);
+ }
+ pluginNode=pluginNode.nextSibling();
+ }
+
+ if(m_pluginList.count())
+ return true;
+ else
+ return false;
+}
+
+
+void KNSPluginInstallEngine::startInstall(KNSPluginInfo info)
+{
+ m_toInstallPluginInfo = info;
+ // create a temporary dowload file
+ KTempFile tempFile(locateLocal("tmp", "plugin") , TQString(".tar.gz"));
+ m_tmpPluginFileName = tempFile.name();
+ tempFile.unlink();
+ tempFile.close();
+ // start the download job
+ m_downloadJob = TDEIO::copy(info.pluginURL(), "file://"+m_tmpPluginFileName, false );
+ // connect signals
+ connect(m_downloadJob, TQT_SIGNAL(percent (TDEIO::Job *, unsigned long)), this , TQT_SLOT(slotDownLoadProgress(TDEIO::Job *, unsigned long)));
+ connect(m_downloadJob, TQT_SIGNAL(result(TDEIO::Job *)), this, TQT_SLOT(slotDownloadResult(TDEIO::Job *)) );
+ kdDebug(DEBUG_NUMBER) << "download plugin " << m_tmpPluginFileName << endl;
+}
+
+void KNSPluginInstallEngine::slotDownLoadProgress(TDEIO::Job *, unsigned long percent)
+{
+ // propagate the download progression
+ emit installProgress( ((int)percent)/3 );
+}
+
+void KNSPluginInstallEngine::slotDownloadResult(TDEIO::Job *job)
+{
+ // test if the download job suceed
+ if(job->error()) {
+ kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+ emit installFailed();
+ }
+ else {
+ kdDebug(DEBUG_NUMBER) << "download completed" << m_tmpPluginFileName << endl;
+ // the download succeed copy the plugins files
+
+ // test the existance of the homedir
+ TQDir dir(TQDir::homeDirPath());
+ if(!dir.exists()) {
+ emit installFailed();
+ return;
+ }
+
+ // test and create firefox plugins directory
+ if(!dir.exists(".mozilla"))
+ dir.mkdir(".mozilla");
+ if(!dir.exists(".mozilla/plugins"))
+ dir.mkdir(".mozilla/plugins");
+ // destination kurl
+ KURL destURL("file://"+TQDir::homeDirPath()+"/.mozilla/plugins");
+
+ // construct the source kurlList
+ KURL::List urlList;
+ TQStringList pluginFileList = m_toInstallPluginInfo.pluginFileList();
+
+ TQStringList::iterator it;
+ for( it = pluginFileList.begin(); it != pluginFileList.end(); ++it ) {
+ urlList.append( KURL("tar://"+m_tmpPluginFileName+"/"+(*it)) );
+ }
+ m_installFileJob = TDEIO::copy(urlList , destURL, false );
+ connect(m_installFileJob, TQT_SIGNAL(percent (TDEIO::Job *, unsigned long)), this , TQT_SLOT(slotCopyProgress(TDEIO::Job *, unsigned long)));
+ connect(m_installFileJob, TQT_SIGNAL(result(TDEIO::Job *)), this, TQT_SLOT(slotCopyResult(TDEIO::Job *)) );
+ }
+ kdDebug(DEBUG_NUMBER) << "COPY FILE " << m_tmpPluginFileName << endl;
+
+ // zero the download job pointer
+ m_downloadJob = NULL;
+}
+
+void KNSPluginInstallEngine::slotCopyProgress(TDEIO::Job *, unsigned long percent)
+{
+ // propagate the download progression
+ emit installProgress( ((int)percent)/3 + 33 );
+}
+
+void KNSPluginInstallEngine::slotCopyResult(TDEIO::Job *job)
+{
+ // test if the download job suceed
+ if(job->error()) {
+ kdDebug(DEBUG_NUMBER) << "download error" << m_tmpPluginFileName << endl;
+ emit installFailed();
+ }
+ else {
+ // start the plugins scan
+ m_scanProc = new TQProcess( this );
+ m_scanProc->addArgument( "nspluginscan" );
+ m_scanProc->addArgument( "--verbose" );
+
+ connect( m_scanProc, TQT_SIGNAL(readyReadStdout()),
+ this, TQT_SLOT(readScanProcFromStdout()) );
+ connect( m_scanProc, TQT_SIGNAL(processExited()),
+ this, TQT_SLOT(endScanProc()) );
+ if ( !m_scanProc->start() ) {
+ emit installFailed();
+ }
+ }
+}
+
+void KNSPluginInstallEngine::readScanProcFromStdout()
+{
+ // Monitor the scan progress
+ TQString progress = m_scanProc->readLineStdout();
+ int percent;
+ bool ok;
+ percent = progress.toInt(&ok);
+ if(!ok)
+ emit installFailed();
+ emit installProgress( (percent)/3 + 66 );
+}
+
+
+void KNSPluginInstallEngine::endScanProc()
+{
+ // end of scan
+ if(m_scanProc->normalExit()) {
+ emit installProgress( 100 );
+ emit installCompleted();
+ } else
+ emit installFailed();
+}
+
+KNSPluginWizard::KNSPluginWizard(TQWidget *parent, const char *name, KMimeType::Ptr mime)
+: KWizard(parent, name, true)
+, m_installEngine(mime)
+{
+ setCaption(i18n("TDE plugin wizard"));
+ setModal(true);
+
+ // read the plugin installer configuration
+ m_installEngine.pluginAvailable();
+
+ // init the wizzard Pages
+ initConfirmationPage();
+ initLicencePage();
+ initInstallationProgressPage();
+ initFinishPage();
+ initPagesButtonStates();
+
+ // connect signals and slots
+ connectSignals();
+
+ //set correct default installation status
+ m_installationComplete = false;
+
+};
+
+
+KNSPluginWizard::~KNSPluginWizard()
+{
+};
+
+void KNSPluginWizard::initConfirmationPage()
+{
+
+ m_confirmationVBox = new TQVBox(this);
+ new TQLabel(i18n("The following plugins are available."), m_confirmationVBox);
+ m_pluginListView = new KListView(m_confirmationVBox);
+ m_pluginListView->addColumn(i18n("Name"));
+ m_pluginListView->setSelectionMode(TQListView::Single);
+ new TQLabel(i18n("Click on next to install the selected plugin."), m_confirmationVBox);
+ addPage (m_confirmationVBox, i18n("Plugin installation confirmation"));
+
+ bool selected = false;
+
+ // Fill the plugin list
+ TQValueList<KNSPluginInfo>::iterator it;
+ TQValueList<KNSPluginInfo> pluginList = m_installEngine.pluginList();
+ for( it = pluginList.begin(); it != pluginList.end(); ++it ) {
+ PluginListItem *item = new PluginListItem((*it) , m_pluginListView);
+ if(!selected) {
+ selected = true;
+ m_pluginListView->setSelected(item, true);
+ }
+ kdDebug(DEBUG_NUMBER) << "New Plugin List item"<< endl;
+ setNextEnabled(m_confirmationVBox, true);
+ }
+}
+
+void KNSPluginWizard::initLicencePage()
+{
+ m_licenceVBox = new TQVBox(this);
+ m_licencePageLabel = new TQLabel(m_licenceVBox);
+ m_licencePageText = new KTextEdit(m_licenceVBox);
+ m_licencePageText->setReadOnly(true);
+
+ // invisible buttonGroup
+ TQButtonGroup *buttonGroup = new TQButtonGroup(this);
+ m_agreementButtonGroup = buttonGroup;
+ buttonGroup->hide();
+ buttonGroup->setExclusive(true);
+
+ m_licencePageAgree = new TQRadioButton ( i18n("I agree."), m_licenceVBox);
+
+ m_licencePageDisagree = new TQRadioButton ( i18n("I do not agree (plugin will not be installed)."), m_licenceVBox);
+
+ buttonGroup->insert(m_licencePageAgree);
+ buttonGroup->insert(m_licencePageDisagree);
+ m_licencePageDisagree->setChecked(true);
+
+ addPage (m_licenceVBox, i18n("Plugin licence"));
+
+
+ connect(buttonGroup, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotAgreementClicked(int)));
+}
+
+void KNSPluginWizard::initInstallationProgressPage() {
+
+ m_installationProgressWidget = new TQWidget(this);
+ TQVBoxLayout *layout = new TQVBoxLayout(m_installationProgressWidget);
+ layout->addWidget(new TQLabel(i18n("Installation in progress."), m_installationProgressWidget));
+ layout->addItem(new TQSpacerItem(40,20,TQSizePolicy::Expanding,TQSizePolicy::Expanding ));
+ m_installationProgressBar = new KProgress(m_installationProgressWidget);
+ m_installationProgressBar->setTotalSteps(100);
+ layout->addWidget(m_installationProgressBar);
+
+ addPage( m_installationProgressWidget, i18n("Plugin installation"));
+
+}
+
+void KNSPluginWizard::initFinishPage()
+{
+ m_finishWidget = new TQWidget(this);
+ TQVBoxLayout *layout = new TQVBoxLayout(m_finishWidget);
+ layout->addItem(new TQSpacerItem(40,20,TQSizePolicy::Expanding,TQSizePolicy::Expanding ));
+ m_finishLabel = new TQLabel(m_finishWidget);
+ layout->addWidget(m_finishLabel);
+ layout->addItem(new TQSpacerItem(40,20,TQSizePolicy::Expanding,TQSizePolicy::Expanding ));
+
+ addPage(m_finishWidget, i18n("Installation status"));
+
+}
+
+
+void KNSPluginWizard::initPagesButtonStates()
+{
+ // set buttons states for the confirmation page
+ setNextEnabled(m_confirmationVBox, true);
+ setFinishEnabled(m_confirmationVBox, false);
+ setHelpEnabled(m_confirmationVBox, false);
+
+ // set buttons states for the licence page
+ setNextEnabled(m_licenceVBox , false);
+ setBackEnabled(m_licenceVBox , false);
+ setFinishEnabled(m_licenceVBox , false);
+ setHelpEnabled(m_licenceVBox , false);
+
+ // for the installation page
+ setNextEnabled(m_installationProgressWidget , false);
+ setBackEnabled(m_installationProgressWidget , false);
+ setFinishEnabled(m_installationProgressWidget , false);
+ setHelpEnabled(m_installationProgressWidget , false);
+
+ // for the finish page
+ setNextEnabled(m_finishWidget , false);
+ setBackEnabled(m_finishWidget , false);
+ setFinishEnabled(m_finishWidget , true);
+ setHelpEnabled(m_finishWidget , false);
+}
+
+
+
+void KNSPluginWizard::connectSignals() {
+ connect(&m_installEngine, TQT_SIGNAL(installProgress(int)), m_installationProgressBar, TQT_SLOT(setProgress(int)) );
+ connect(&m_installEngine, TQT_SIGNAL(installCompleted()), this, TQT_SLOT(slotInstallationCompleted()) );
+ connect(&m_installEngine, TQT_SIGNAL(installFailed()), this, TQT_SLOT(slotInstallationFailed()) );
+
+
+}
+
+void KNSPluginWizard::showPage(TQWidget *page)
+{
+
+ // if the licence page is shown set the label and the licence content
+ if(page == m_licenceVBox && m_licencePageLabel->text().isEmpty()) {
+ KNSPluginInfo info = static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+ m_licencePageLabel->setText(i18n("To install ")+info.pluginName()+i18n(" you need to agree to the following"));
+ TQString licence;
+ licence = info.licence();
+ TQString tmpFile;
+ if(info.licenceURL().isValid())
+ // retrieve the licence if we have an url
+ if(TDEIO::NetAccess::download(info.licenceURL(), tmpFile, NULL)) {
+ TQFile f(tmpFile);
+ if(f.open(IO_ReadOnly)) {
+ TQTextStream stream(&f);
+ stream.setEncoding(TQTextStream::UnicodeUTF8);
+ licence = stream.read();
+ f.close();
+ TDEIO::NetAccess::removeTempFile(tmpFile);
+ }
+ }
+ // else display the licence found in the xml config
+ m_licencePageText->setText(licence);
+
+ }
+
+ // if the installation page is shown start the download
+ if(page == m_installationProgressWidget) {
+ KNSPluginInfo info = static_cast<PluginListItem *>(m_pluginListView->selectedItem())->pluginInfo();
+ m_installEngine.startInstall(info);
+
+ }
+
+ // If we must display the finish page
+ if(page == m_finishWidget) {
+ if(m_installationComplete) {
+ m_finishLabel->setText(i18n("Installation completed. Reload the page."));
+
+ } else
+ m_finishLabel->setText(i18n("Installation failed"));
+
+ }
+
+
+ KWizard::showPage(page);
+}
+
+int KNSPluginWizard::exec()
+{
+ if(!m_installEngine.pluginList().count())
+ return TQDialog::Rejected;
+
+ return KWizard::exec();
+}
+
+
+bool KNSPluginWizard::pluginAvailable()
+{
+ return m_installEngine.pluginAvailable();
+}
+
+void KNSPluginWizard::slotAgreementClicked(int id)
+{
+ if( id == m_agreementButtonGroup->id(m_licencePageAgree) ) {
+ setNextEnabled(m_licenceVBox, true);
+
+ } else {
+ setNextEnabled(m_licenceVBox, false);
+ }
+
+}
+
+void KNSPluginWizard::slotInstallationCompleted()
+{
+ m_installationComplete = true;
+ // enable next button
+ setNextEnabled(m_installationProgressWidget, true);
+ next();
+}
+void KNSPluginWizard::slotInstallationFailed()
+{
+ m_installationComplete = false;
+ showPage(m_finishWidget);
+}
+
+
+// KNSPlugin info copy constructor
+
+KNSPluginInfo::KNSPluginInfo()
+{
+
+}
+
+// KNSPlugin info constructor par an xml dom fragment
+KNSPluginInfo::KNSPluginInfo(TQDomNode pluginNode)
+{
+ TQDomElement e;
+ TQDomNode node;
+
+ // Read plugin informations
+ node = pluginNode.firstChild();
+ while(!node.isNull()) {
+ e = node.toElement();
+ if( e.tagName() == "pluginname") {
+ kdDebug(DEBUG_NUMBER) << "found name " << e.text() << endl;
+ m_pluginName = e.text();
+ }
+
+ if( e.tagName() == "pluginurl") {
+ kdDebug(DEBUG_NUMBER) << "found plugin url " << e.text() << endl;
+ m_pluginURL = KURL(e.text());
+ }
+
+ if( e.tagName() == "licence") {
+ kdDebug(DEBUG_NUMBER) << "found licence " << e.text() << endl;
+ m_licence = e.text();
+ }
+
+ if( e.tagName() == "licenceurl") {
+ kdDebug(DEBUG_NUMBER) << "found licenceurl " << e.text() << endl;
+ m_licenceURL = KURL(e.text());
+ }
+
+ if( e.tagName() == "pluginfile") {
+ kdDebug(DEBUG_NUMBER) << "found pluginfile " << e.text() << endl;
+ m_pluginFileList.append(e.text());
+ }
+ node = node.nextSibling();
+ }
+}
+
+
+KNSPluginInfo::~KNSPluginInfo()
+{
+
+}
+
+
+bool KNSPluginInfo::isValid() const
+{
+ // tell if the pluginInfo is a valid One
+ if( m_pluginName.isEmpty() || ( m_licence.isEmpty() && !m_licenceURL.isValid() ) || !m_pluginURL.isValid() || m_pluginFileList.empty() ) {
+ kdDebug(DEBUG_NUMBER) << "invalid plugin info" << endl;
+ return false;
+
+ }
+
+ else {
+
+ kdDebug(DEBUG_NUMBER) << "valid plugin info" << endl;
+ return true;
+ }
+}
+
+// Accesors
+TQString KNSPluginInfo::pluginName() const
+{
+ return m_pluginName;
+}
+
+TQString KNSPluginInfo::licence() const
+{
+ return m_licence;
+}
+
+KURL KNSPluginInfo::licenceURL() const
+{
+ return m_licenceURL;
+}
+
+KURL KNSPluginInfo::pluginURL() const
+{
+ return m_pluginURL;
+}
+
+const TQStringList& KNSPluginInfo::pluginFileList() const
+{
+ return m_pluginFileList;
+}
diff --git a/tdehtml/misc/knsplugininstaller.h b/tdehtml/misc/knsplugininstaller.h
new file mode 100644
index 000000000..240202468
--- /dev/null
+++ b/tdehtml/misc/knsplugininstaller.h
@@ -0,0 +1,268 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2005 Benoit Canet <bcanet@dental-on-line.fr>
+ Copyright (C) 2005 Aurelien Gateau <agateau@dental-on-line.fr>
+
+ 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 KNSPLUGININSTALLER_H
+#define KNSPLUGININSTALLER_H
+
+#include <job.h>
+#include <ktextedit.h>
+#include <kmimetype.h>
+#include <kprogress.h>
+#include <kurl.h>
+#include <kwizard.h>
+
+#include <tqbuttongroup.h>
+#include <tqdom.h>
+#include <tqlabel.h>
+#include <tqobject.h>
+#include <tqprocess.h>
+#include <tqradiobutton.h>
+#include <tqvaluelist.h>
+#include <tqvbox.h>
+#include <tqwidget.h>
+
+class TQStringList;
+
+/*
+ * This class contains all the infos needed to install a given plugin
+ * Takes and parse a TQDomNode in its constructor
+ */
+class KNSPluginInfo
+{
+
+public:
+
+ /*
+ * Construct the plugin info object
+ */
+ KNSPluginInfo();
+ KNSPluginInfo(TQDomNode pluginNode);
+ ~KNSPluginInfo();
+
+ /*
+ * Check the validity of the plugin info object
+ */
+ bool isValid() const;
+
+ //Accessor methods
+ TQString pluginName() const;
+ TQString licence() const;
+ KURL licenceURL() const;
+ KURL pluginURL() const;
+ const TQStringList& pluginFileList() const;
+
+private:
+
+ // plugin info
+ TQString m_pluginName;
+ TQString m_licence;
+ KURL m_licenceURL;
+ KURL m_pluginURL;
+ TQStringList m_pluginFileList;
+
+
+};
+
+
+/*
+ * This class contain all the the methods used to perform a plugin installation
+ *
+ */
+class KNSPluginInstallEngine : public TQObject
+{
+ Q_OBJECT
+public:
+
+ /*
+ * Construct the class
+ */
+ KNSPluginInstallEngine(KMimeType::Ptr mime);
+ ~KNSPluginInstallEngine();
+
+ /*
+ * Check if the installer engine and wizzard is activated
+ */
+ static bool isActive();
+ /**
+ * Check the availability of a plugin
+ */
+ bool pluginAvailable();
+ /*
+ * Return the list of plugins Available
+ */
+ const TQValueList<KNSPluginInfo>& pluginList() const;
+ void startInstall(KNSPluginInfo info);
+
+
+
+private:
+
+ // methods used to check the kde config and detect if an adequate plugin is available
+
+ /*
+ * load kde KNSPluginInstaller config
+ */
+ bool loadConfig();
+ /*
+ * retrieve the xml configuration file
+ */
+ bool loadXmlConfig();
+ /*
+ * parse the xml configuration file
+ */
+ bool findPlugin();
+
+
+ TQMap<TQString, TQString> m_archMap;
+ TQString m_pluginsXmlConfig;
+ TQValueList<KNSPluginInfo> m_pluginList;
+ KMimeType::Ptr m_mime;
+ KURL m_pluginsListFileURL;
+ TQString m_tmpPluginFileName;
+ TDEIO::CopyJob *m_downloadJob;
+ TDEIO::CopyJob *m_installFileJob;
+ KNSPluginInfo m_toInstallPluginInfo;
+ TQProcess *m_scanProc;
+
+signals:
+ // Signals used to communicate with the wizzard
+ void installProgress(int percent);
+ void installCompleted();
+ void installFailed();
+
+private slots:
+ // Used to monitor the plugin downloading
+ void slotDownLoadProgress(TDEIO::Job *job, unsigned long percent);
+ void slotDownloadResult(TDEIO::Job *job);
+
+ // Used to monitor the plugin installation
+ void slotCopyProgress(TDEIO::Job *job, unsigned long percent);
+ void slotCopyResult(TDEIO::Job *job);
+
+ // Used to monitor the plugins scan
+ void readScanProcFromStdout();
+ void endScanProc();
+
+
+
+};
+
+/*
+ * This class is a wizzard used to install a plugin
+ */
+class KNSPluginWizard : public KWizard
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Construct a KNSpluginInstaller
+ */
+ KNSPluginWizard(TQWidget *parent, const char *name, KMimeType::Ptr mime);
+ ~KNSPluginWizard();
+
+
+ /**
+ * Lauch the wizzard
+ */
+ int exec();
+ /*
+ * Check the availability of a plugin
+ */
+ bool pluginAvailable();
+
+
+private:
+ // methods used in the constructor to init the wizzard pages
+ void initConfirmationPage();
+ void initLicencePage();
+ void initInstallationProgressPage();
+ void initFinishPage();
+
+ // in this method we disable or enable the wizzard pages buttons
+ void initPagesButtonStates();
+
+ /*
+ * Connect signals
+ */
+ void connectSignals();
+
+ /*
+ * Overiden method called when a page is shown
+ */
+ void showPage(TQWidget *page);
+
+
+ // Plugin installation engine
+ KNSPluginInstallEngine m_installEngine;
+
+ // pages widgets
+ TQVBox *m_confirmationVBox;
+ TQVBox *m_licenceVBox;
+ TQWidget *m_installationProgressWidget;
+ TQWidget *m_finishWidget;
+
+ // plugin list
+ KListView *m_pluginListView;
+
+ // licence stuff
+ TQLabel *m_licencePageLabel;
+ KTextEdit *m_licencePageText;
+ TQRadioButton *m_licencePageAgree;
+ TQRadioButton *m_licencePageDisagree;
+ TQButtonGroup *m_agreementButtonGroup;
+
+ // installation progress bar
+ KProgress *m_installationProgressBar;
+
+ // Finish Label
+ TQLabel *m_finishLabel;
+
+ // installation status
+ bool m_installationComplete;
+
+private slots:
+ /*
+ * Check if the user Agree or disagree with the licence
+ */
+ void slotAgreementClicked(int id);
+ /*
+ * Called when the installation is completed
+ */
+ void slotInstallationCompleted();
+ /*
+ * Called when the installation has failed
+ */
+ void slotInstallationFailed();
+
+signals:
+ /*
+ * Emited when the installation has complete - TODO connect this signal to reload the page
+ */
+ void pluginInstallCompleted();
+};
+
+
+
+
+
+#endif
diff --git a/tdehtml/misc/loader.cpp b/tdehtml/misc/loader.cpp
new file mode 100644
index 000000000..60a75f856
--- /dev/null
+++ b/tdehtml/misc/loader.cpp
@@ -0,0 +1,1679 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
+ Copyright (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.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+
+ // regarding the LRU:
+ // http://www.is.kyusan-u.ac.jp/~chengk/pub/papers/compsac00_A07-07.pdf
+*/
+
+#undef CACHE_DEBUG
+//#define CACHE_DEBUG
+
+#ifdef CACHE_DEBUG
+#define CDEBUG kdDebug(6060)
+#else
+#define CDEBUG kndDebug()
+#endif
+
+#undef LOADER_DEBUG
+//#define LOADER_DEBUG
+
+#include <assert.h>
+
+#include "misc/loader.h"
+#include "misc/seed.h"
+
+// default cache size
+#define DEFCACHESIZE 2096*1024
+#define MAX_JOB_COUNT 32
+
+#include <tqasyncio.h>
+#include <tqasyncimageio.h>
+#include <tqpainter.h>
+#include <tqbitmap.h>
+#include <tqmovie.h>
+#include <tqwidget.h>
+
+#include <kapplication.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kglobal.h>
+#include <kimageio.h>
+#include <kcharsets.h>
+#include <kiconloader.h>
+#include <scheduler.h>
+#include <kdebug.h>
+#include "tdehtml_factory.h"
+#include "tdehtml_part.h"
+
+#ifdef IMAGE_TITLES
+#include <tqfile.h>
+#include <kfilemetainfo.h>
+#include <ktempfile.h>
+#endif
+
+#include "html/html_documentimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "xml/dom_docimpl.h"
+
+#include "blocked_icon.cpp"
+
+using namespace tdehtml;
+using namespace DOM;
+
+#define MAX_LRU_LISTS 20
+struct LRUList {
+ CachedObject* m_head;
+ CachedObject* m_tail;
+
+ LRUList() : m_head(0), m_tail(0) {}
+};
+
+static LRUList m_LRULists[MAX_LRU_LISTS];
+static LRUList* getLRUListFor(CachedObject* o);
+
+CachedObjectClient::~CachedObjectClient()
+{
+}
+
+CachedObject::~CachedObject()
+{
+ Cache::removeFromLRUList(this);
+}
+
+void CachedObject::finish()
+{
+ m_status = Cached;
+}
+
+bool CachedObject::isExpired() const
+{
+ if (!m_expireDate) return false;
+ time_t now = time(0);
+ return (difftime(now, m_expireDate) >= 0);
+}
+
+void CachedObject::setRequest(Request *_request)
+{
+ if ( _request && !m_request )
+ m_status = Pending;
+
+ if ( allowInLRUList() )
+ Cache::removeFromLRUList( this );
+
+ m_request = _request;
+
+ if ( allowInLRUList() )
+ Cache::insertInLRUList( this );
+}
+
+void CachedObject::ref(CachedObjectClient *c)
+{
+ // unfortunately we can be ref'ed multiple times from the
+ // same object, because it uses e.g. the same foreground
+ // and the same background picture. so deal with it.
+ m_clients.insert(c,c);
+ Cache::removeFromLRUList(this);
+ m_accessCount++;
+}
+
+void CachedObject::deref(CachedObjectClient *c)
+{
+ assert( c );
+ assert( m_clients.count() );
+ assert( !canDelete() );
+ assert( m_clients.find( c ) );
+
+ Cache::flush();
+
+ m_clients.remove(c);
+
+ if (allowInLRUList())
+ Cache::insertInLRUList(this);
+}
+
+void CachedObject::setSize(int size)
+{
+ bool sizeChanged;
+
+ if ( !m_next && !m_prev && getLRUListFor(this)->m_head != this )
+ sizeChanged = false;
+ else
+ sizeChanged = ( size - m_size ) != 0;
+
+ // The object must now be moved to a different queue,
+ // since its size has been changed.
+ if ( sizeChanged && allowInLRUList())
+ Cache::removeFromLRUList(this);
+
+ m_size = size;
+
+ if ( sizeChanged && allowInLRUList())
+ Cache::insertInLRUList(this);
+}
+
+TQTextCodec* CachedObject::codecForBuffer( const TQString& charset, const TQByteArray& buffer ) const
+{
+ // we don't use heuristicContentMatch here since it is a) far too slow and
+ // b) having too much functionality for our case.
+
+ uchar* d = ( uchar* ) buffer.data();
+ int s = buffer.size();
+
+ // BOM
+ if ( s >= 3 &&
+ d[0] == 0xef && d[1] == 0xbb && d[2] == 0xbf)
+ return TQTextCodec::codecForMib( 106 ); // UTF-8
+
+ if ( s >= 2 && ((d[0] == 0xff && d[1] == 0xfe) ||
+ (d[0] == 0xfe && d[1] == 0xff)))
+ return TQTextCodec::codecForMib( 1000 ); // UCS-2
+
+ // Link or @charset
+ if(!charset.isEmpty())
+ {
+ TQTextCodec* c = TDEGlobal::charsets()->codecForName(charset);
+ if(c->mibEnum() == 11) {
+ // iso8859-8 (visually ordered)
+ c = TQTextCodec::codecForName("iso8859-8-i");
+ }
+ return c;
+ }
+
+ // Default
+ return TQTextCodec::codecForMib( 4 ); // latin 1
+}
+
+// -------------------------------------------------------------------------------------------
+
+CachedCSSStyleSheet::CachedCSSStyleSheet(DocLoader* dl, const DOMString &url, TDEIO::CacheControl _cachePolicy,
+ const char *accept)
+ : CachedObject(url, CSSStyleSheet, _cachePolicy, 0)
+{
+ // Set the type we want (probably css or xml)
+ TQString ah = TQString::fromLatin1( accept );
+ if ( !ah.isEmpty() )
+ ah += ",";
+ ah += "*/*;q=0.1";
+ setAccept( ah );
+ m_hadError = false;
+ m_wasBlocked = false;
+ m_err = 0;
+ // load the file
+ Cache::loader()->load(dl, this, false);
+ m_loading = true;
+}
+
+CachedCSSStyleSheet::CachedCSSStyleSheet(const DOMString &url, const TQString &stylesheet_data)
+ : CachedObject(url, CSSStyleSheet, TDEIO::CC_Verify, stylesheet_data.length())
+{
+ m_loading = false;
+ m_status = Persistent;
+ m_sheet = DOMString(stylesheet_data);
+}
+
+
+void CachedCSSStyleSheet::ref(CachedObjectClient *c)
+{
+ CachedObject::ref(c);
+
+ if (!m_loading) {
+ if (m_hadError)
+ c->error( m_err, m_errText );
+ else
+ c->setStyleSheet( m_url, m_sheet, m_charset );
+ }
+}
+
+void CachedCSSStyleSheet::data( TQBuffer &buffer, bool eof )
+{
+ if(!eof) return;
+ buffer.close();
+ setSize(buffer.buffer().size());
+
+// TQString charset = checkCharset( buffer.buffer() );
+ TQTextCodec* c = 0;
+ if (!m_charset.isEmpty()) {
+ c = TDEGlobal::charsets()->codecForName(m_charset);
+ if(c->mibEnum() == 11) c = TQTextCodec::codecForName("iso8859-8-i");
+ }
+ else {
+ c = codecForBuffer( m_charsetHint, buffer.buffer() );
+ m_charset = c->name();
+ }
+ TQString data = c->toUnicode( buffer.buffer().data(), m_size );
+ // workaround TQt bugs
+ m_sheet = static_cast<TQChar>(data[0]) == TQChar::byteOrderMark ? DOMString(data.mid( 1 ) ) : DOMString(data);
+ m_loading = false;
+
+ checkNotify();
+}
+
+void CachedCSSStyleSheet::checkNotify()
+{
+ if(m_loading || m_hadError) return;
+
+ CDEBUG << "CachedCSSStyleSheet:: finishedLoading " << m_url.string() << endl;
+
+ // it() first increments, then returnes the current item.
+ // this avoids skipping an item when setStyleSheet deletes the "current" one.
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->setStyleSheet( m_url, m_sheet, m_charset );
+}
+
+
+void CachedCSSStyleSheet::error( int err, const char* text )
+{
+ m_hadError = true;
+ m_err = err;
+ m_errText = text;
+ m_loading = false;
+
+ // it() first increments, then returnes the current item.
+ // this avoids skipping an item when setStyleSheet deletes the "current" one.
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->error( m_err, m_errText );
+}
+
+#if 0
+TQString CachedCSSStyleSheet::checkCharset(const TQByteArray& buffer ) const
+{
+ int s = buffer.size();
+ if (s <= 12) return m_charset;
+
+ // @charset has to be first or directly after BOM.
+ // CSS 2.1 says @charset should win over BOM, but since more browsers support BOM
+ // than @charset, we default to that.
+ const char* d = (const char*) buffer.data();
+ if (strncmp(d, "@charset \"",10) == 0)
+ {
+ // the string until "; is the charset name
+ char *p = strchr(d+10, '"');
+ if (p == 0) return m_charset;
+ TQString charset = TQString::fromAscii(d+10, p-(d+10));
+ return charset;
+ }
+ return m_charset;
+}
+#endif
+
+// -------------------------------------------------------------------------------------------
+
+CachedScript::CachedScript(DocLoader* dl, const DOMString &url, TDEIO::CacheControl _cachePolicy, const char*)
+ : CachedObject(url, Script, _cachePolicy, 0)
+{
+ // It's javascript we want.
+ // But some websites think their scripts are <some wrong mimetype here>
+ // and refuse to serve them if we only accept application/x-javascript.
+ setAccept( TQString::fromLatin1("*/*") );
+ // load the file
+ Cache::loader()->load(dl, this, false);
+ m_loading = true;
+}
+
+CachedScript::CachedScript(const DOMString &url, const TQString &script_data)
+ : CachedObject(url, Script, TDEIO::CC_Verify, script_data.length())
+{
+ m_loading = false;
+ m_status = Persistent;
+ m_script = DOMString(script_data);
+}
+
+void CachedScript::ref(CachedObjectClient *c)
+{
+ CachedObject::ref(c);
+
+ if(!m_loading) c->notifyFinished(this);
+}
+
+void CachedScript::data( TQBuffer &buffer, bool eof )
+{
+ if(!eof) return;
+ buffer.close();
+ setSize(buffer.buffer().size());
+
+ TQTextCodec* c = codecForBuffer( m_charset, buffer.buffer() );
+ TQString data = c->toUnicode( buffer.buffer().data(), m_size );
+ m_script = static_cast<TQChar>(data[0]) == TQChar::byteOrderMark ? DOMString(data.mid( 1 ) ) : DOMString(data);
+ m_loading = false;
+ checkNotify();
+}
+
+void CachedScript::checkNotify()
+{
+ if(m_loading) return;
+
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients); it.current();)
+ it()->notifyFinished(this);
+}
+
+void CachedScript::error( int /*err*/, const char* /*text*/ )
+{
+ m_loading = false;
+ checkNotify();
+}
+
+// ------------------------------------------------------------------------------------------
+
+namespace tdehtml
+{
+
+class ImageSource : public TQDataSource
+{
+public:
+ ImageSource(TQByteArray buf)
+ : buffer( buf ), pos( 0 ), eof( false ), rew(false ), rewable( true )
+ {}
+
+ int readyToSend()
+ {
+ if(eof && pos == buffer.size())
+ return -1;
+
+ return buffer.size() - pos;
+ }
+
+ void sendTo(TQDataSink* sink, int n)
+ {
+ sink->receive((const uchar*)&buffer.at(pos), n);
+
+ pos += n;
+
+ // buffer is no longer needed
+ if(eof && pos == buffer.size() && !rewable)
+ {
+ buffer.resize(0);
+ pos = 0;
+ }
+ }
+
+ /**
+ * Sets the EOF state.
+ */
+ void setEOF( bool state ) { eof = state; }
+
+ bool rewindable() const { return rewable; }
+ void enableRewind(bool on) { rew = on; }
+
+ /*
+ Calls reset() on the TQIODevice.
+ */
+ void rewind()
+ {
+ pos = 0;
+ if (!rew) {
+ TQDataSource::rewind();
+ } else
+ ready();
+ }
+
+ /*
+ Indicates that the buffered data is no longer
+ needed.
+ */
+ void cleanBuffer()
+ {
+ // if we need to be able to rewind, buffer is needed
+ if(rew)
+ return;
+
+ rewable = false;
+
+ // buffer is no longer needed
+ if(eof && pos == buffer.size())
+ {
+ buffer.resize(0);
+ pos = 0;
+ }
+ }
+
+ TQByteArray buffer;
+ unsigned int pos;
+private:
+ bool eof : 1;
+ bool rew : 1;
+ bool rewable : 1;
+};
+
+} // end namespace
+
+static TQString buildAcceptHeader()
+{
+ return "image/png, image/jpeg, video/x-mng, image/jp2, image/gif;q=0.5,*/*;q=0.1";
+}
+
+// -------------------------------------------------------------------------------------
+
+CachedImage::CachedImage(DocLoader* dl, const DOMString &url, TDEIO::CacheControl _cachePolicy, const char*)
+ : TQObject(), CachedObject(url, Image, _cachePolicy, 0)
+{
+ static const TQString &acceptHeader = TDEGlobal::staticQString( buildAcceptHeader() );
+
+ m = 0;
+ p = 0;
+ pixPart = 0;
+ bg = 0;
+ scaled = 0;
+ bgColor = tqRgba( 0, 0, 0, 0xFF );
+ typeChecked = false;
+ isFullyTransparent = false;
+ monochrome = false;
+ formatType = 0;
+ m_status = Unknown;
+ imgSource = 0;
+ setAccept( acceptHeader );
+ m_showAnimations = dl->showAnimations();
+
+ if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( url.string() ) ) {
+ m_wasBlocked = true;
+ CachedObject::finish();
+ }
+}
+
+CachedImage::~CachedImage()
+{
+ clear();
+}
+
+void CachedImage::ref( CachedObjectClient *c )
+{
+ CachedObject::ref(c);
+
+ if( m ) {
+ m->unpause();
+ if( m->finished() || m_clients.count() == 1 )
+ m->restart();
+ }
+
+ // for mouseovers, dynamic changes
+ if ( m_status >= Persistent && !valid_rect().isNull() ) {
+ c->setPixmap( pixmap(), valid_rect(), this);
+ c->notifyFinished( this );
+ }
+}
+
+void CachedImage::deref( CachedObjectClient *c )
+{
+ CachedObject::deref(c);
+ if(m && m_clients.isEmpty() && m->running())
+ m->pause();
+}
+
+#define BGMINWIDTH 32
+#define BGMINHEIGHT 32
+
+const TQPixmap &CachedImage::tiled_pixmap(const TQColor& newc, int xWidth, int xHeight)
+{
+ static TQRgb bgTransparent = tqRgba( 0, 0, 0, 0xFF );
+
+ TQSize s(pixmap_size());
+ int w = xWidth;
+ int h = xHeight;
+ if (w == -1) xWidth = w = s.width();
+ if (h == -1) xHeight = h = s.height();
+
+ if ( ( (bgColor != bgTransparent) && (bgColor != newc.rgb()) ) ||
+ ( bgSize != TQSize(xWidth, xHeight)) )
+ {
+ delete bg; bg = 0;
+ }
+
+ if (bg)
+ return *bg;
+
+ const TQPixmap &r = pixmap();
+
+ if (r.isNull()) return r;
+
+ // no error indication for background images
+ if(m_hadError||m_wasBlocked) return *Cache::nullPixmap;
+
+ bool isvalid = newc.isValid();
+
+ const TQPixmap* src; //source for pretiling, if any
+
+ //See whether we should scale
+ if (xWidth != s.width() || xHeight != s.height()) {
+ src = &scaled_pixmap(xWidth, xHeight);
+ } else {
+ src = &r;
+ }
+
+ bgSize = TQSize(xWidth, xHeight);
+
+ //See whether we can - and should - pre-blend
+ if (isvalid && (r.hasAlphaChannel() || r.mask() )) {
+ bg = new TQPixmap(xWidth, xHeight, r.depth());
+ bg->fill(newc);
+ bitBlt(bg, 0, 0, src);
+ bgColor = newc.rgb();
+ src = bg;
+ } else {
+ bgColor = bgTransparent;
+ }
+
+ //See whether to pre-tile.
+ if ( w*h < 8192 )
+ {
+ if ( r.width() < BGMINWIDTH )
+ w = ((BGMINWIDTH-1) / xWidth + 1) * xWidth;
+ if ( r.height() < BGMINHEIGHT )
+ h = ((BGMINHEIGHT-1) / xHeight + 1) * xHeight;
+ }
+ if ( w != xWidth || h != xHeight )
+ {
+// kdDebug() << "pre-tiling " << s.width() << "," << s.height() << " to " << w << "," << h << endl;
+ TQPixmap* oldbg = bg;
+ bg = new TQPixmap(w, h, r.depth());
+
+ //Tile horizontally on the first stripe
+ for (int x = 0; x < w; x += xWidth)
+ copyBlt(bg, x, 0, src, 0, 0, xWidth, xHeight);
+
+ //Copy first stripe down
+ for (int y = xHeight; y < h; y += xHeight)
+ copyBlt(bg, 0, y, bg, 0, 0, w, xHeight);
+
+ if ( src == oldbg )
+ delete oldbg;
+ }
+
+ if (bg)
+ return *bg;
+
+ return *src;
+}
+
+const TQPixmap &CachedImage::scaled_pixmap( int xWidth, int xHeight )
+{
+ if (scaled) {
+ if (scaled->width() == xWidth && scaled->height() == xHeight)
+ return *scaled;
+ delete scaled;
+ }
+ const TQPixmap &r = pixmap();
+ if (r.isNull()) return r;
+
+// kdDebug() << "scaling " << r.width() << "," << r.height() << " to " << xWidth << "," << xHeight << endl;
+
+ TQImage image = TQImage(r.convertToImage()).smoothScale(xWidth, xHeight);
+
+ scaled = new TQPixmap(xWidth, xHeight, r.depth());
+ scaled->convertFromImage(image);
+
+ return *scaled;
+}
+
+
+const TQPixmap &CachedImage::pixmap( ) const
+{
+ if(m_hadError)
+ return *Cache::brokenPixmap;
+
+ if(m_wasBlocked)
+ return *Cache::blockedPixmap;
+
+ if(m)
+ {
+ if(m->framePixmap().size() != m->getValidRect().size())
+ {
+ // pixmap is not yet completely loaded, so we
+ // return a clipped version. asserting here
+ // that the valid rect is always from 0/0 to fullwidth/ someheight
+ if(!pixPart) pixPart = new TQPixmap();
+
+ (*pixPart) = m->framePixmap();
+ if (m->getValidRect().size().isValid())
+ pixPart->resize(m->getValidRect().size());
+ else
+ pixPart->resize(0, 0);
+ return *pixPart;
+ }
+ else
+ return m->framePixmap();
+ }
+ else if(p)
+ return *p;
+
+ return *Cache::nullPixmap;
+}
+
+
+TQSize CachedImage::pixmap_size() const
+{
+ if (m_wasBlocked) return Cache::blockedPixmap->size();
+ return (m_hadError ? Cache::brokenPixmap->size() : m ? m->framePixmap().size() : ( p ? p->size() : TQSize()));
+}
+
+
+TQRect CachedImage::valid_rect() const
+{
+ if (m_wasBlocked) return Cache::blockedPixmap->rect();
+ return (m_hadError ? Cache::brokenPixmap->rect() : m ? TQRect(m->getValidRect()) : ( p ? TQRect(p->rect()) : TQRect()) );
+}
+
+
+void CachedImage::do_notify(const TQPixmap& p, const TQRect& r)
+{
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->setPixmap( p, r, this);
+}
+
+
+void CachedImage::movieUpdated( const TQRect& r )
+{
+#ifdef LOADER_DEBUG
+ tqDebug("movie updated %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
+ m->framePixmap().size().width(), m->framePixmap().size().height());
+#endif
+
+ do_notify(m->framePixmap(), r);
+}
+
+void CachedImage::movieStatus(int status)
+{
+#ifdef LOADER_DEBUG
+ tqDebug("movieStatus(%d)", status);
+#endif
+
+ // ### the html image objects are supposed to send the load event after every frame (according to
+ // netscape). We have a problem though where an image is present, and js code creates a new Image object,
+ // which uses the same CachedImage, the one in the document is not supposed to be notified
+
+ // just another TQt 2.2.0 bug. we cannot call
+ // TQMovie::frameImage if we're after TQMovie::EndOfMovie
+ if(status == TQMovie::EndOfFrame)
+ {
+ const TQImage& im = m->frameImage();
+ monochrome = ( ( im.depth() <= 8 ) && ( im.numColors() - int( im.hasAlphaBuffer() ) <= 2 ) );
+ for (int i = 0; monochrome && i < im.numColors(); ++i)
+ if (im.colorTable()[i] != tqRgb(0xff, 0xff, 0xff) &&
+ im.colorTable()[i] != tqRgb(0x00, 0x00, 0x00))
+ monochrome = false;
+ if( (im.width() < 5 || im.height() < 5) && im.hasAlphaBuffer()) // only evaluate for small images
+ {
+ TQImage am = im.createAlphaMask();
+ if(am.depth() == 1)
+ {
+ bool solid = false;
+ for(int y = 0; y < am.height(); y++)
+ for(int x = 0; x < am.width(); x++)
+ if(am.pixelIndex(x, y)) {
+ solid = true;
+ break;
+ }
+ isFullyTransparent = (!solid);
+ }
+ }
+
+ // we have to delete our tiled bg variant here
+ // because the frame has changed (in order to keep it in sync)
+ delete bg;
+ bg = 0;
+ }
+
+ if((status == TQMovie::EndOfMovie && (!m || m->frameNumber() <= 1)) ||
+ ((status == TQMovie::EndOfLoop) && (m_showAnimations == KHTMLSettings::KAnimationLoopOnce)) ||
+ ((status == TQMovie::EndOfFrame) && (m_showAnimations == KHTMLSettings::KAnimationDisabled))
+ )
+ {
+ if(imgSource)
+ {
+ setShowAnimations( KHTMLSettings::KAnimationDisabled );
+
+ // monochrome alphamasked images are usually about 10000 times
+ // faster to draw, so this is worth the hack
+ if (p && monochrome && p->depth() > 1)
+ {
+ TQPixmap* pix = new TQPixmap;
+ pix->convertFromImage( TQImage(p->convertToImage()).convertDepth( 1 ), MonoOnly|AvoidDither );
+ if ( p->mask() )
+ pix->setMask( *p->mask() );
+ delete p;
+ p = pix;
+ monochrome = false;
+ }
+ }
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished( this );
+ m_status = Cached; //all done
+ }
+
+#if 0
+ if((status == TQMovie::EndOfFrame) || (status == TQMovie::EndOfMovie))
+ {
+#ifdef LOADER_DEBUG
+ TQRect r(valid_rect());
+ tqDebug("movie Status frame update %d/%d/%d/%d, pixmap size %d/%d", r.x(), r.y(), r.right(), r.bottom(),
+ pixmap().size().width(), pixmap().size().height());
+#endif
+ do_notify(pixmap(), valid_rect());
+ }
+#endif
+}
+
+void CachedImage::movieResize(const TQSize& /*s*/)
+{
+ do_notify(m->framePixmap(), TQRect());
+}
+
+void CachedImage::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
+{
+ m_showAnimations = showAnimations;
+ if ( (m_showAnimations == KHTMLSettings::KAnimationDisabled) && imgSource ) {
+ imgSource->cleanBuffer();
+ delete p;
+ p = new TQPixmap(m->framePixmap());
+ m->disconnectUpdate( this, TQT_SLOT( movieUpdated( const TQRect &) ));
+ m->disconnectStatus( this, TQT_SLOT( movieStatus( int ) ));
+ m->disconnectResize( this, TQT_SLOT( movieResize( const TQSize& ) ) );
+ TQTimer::singleShot(0, this, TQT_SLOT( deleteMovie()));
+ imgSource = 0;
+ }
+}
+
+void CachedImage::pauseAnimations()
+{
+ if ( m ) m->pause();
+}
+
+void CachedImage::resumeAnimations()
+{
+ if ( m ) m->unpause();
+}
+
+
+void CachedImage::deleteMovie()
+{
+ delete m; m = 0;
+}
+
+void CachedImage::clear()
+{
+ delete m; m = 0;
+ delete p; p = 0;
+ delete bg; bg = 0;
+ delete scaled; scaled = 0;
+ bgColor = tqRgba( 0, 0, 0, 0xff );
+ bgSize = TQSize(-1,-1);
+ delete pixPart; pixPart = 0;
+
+ formatType = 0;
+ typeChecked = false;
+ setSize(0);
+
+ // No need to delete imageSource - TQMovie does it for us
+ imgSource = 0;
+}
+
+void CachedImage::data ( TQBuffer &_buffer, bool eof )
+{
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << this << "in CachedImage::data(buffersize " << _buffer.buffer().size() <<", eof=" << eof << endl;
+#endif
+ if ( !typeChecked )
+ {
+ // don't attempt incremental loading if we have all the data already
+ if (!eof)
+ {
+ formatType = TQImageDecoder::formatName( (const uchar*)_buffer.buffer().data(), _buffer.size());
+ if ( formatType && strcmp( formatType, "PNG" ) == 0 )
+ formatType = 0; // Some png files contain multiple images, we want to show only the first one
+ }
+
+ typeChecked = true;
+
+ if ( formatType ) // movie format exists
+ {
+ imgSource = new ImageSource( _buffer.buffer());
+ m = new TQMovie( imgSource, 8192 );
+ m->connectUpdate( this, TQT_SLOT( movieUpdated( const TQRect &) ));
+ m->connectStatus( this, TQT_SLOT( movieStatus(int)));
+ m->connectResize( this, TQT_SLOT( movieResize( const TQSize& ) ) );
+ }
+ }
+
+ if ( imgSource )
+ {
+ imgSource->setEOF(eof);
+ imgSource->maybeReady();
+ }
+
+ if(eof)
+ {
+ // TQMovie currently doesn't support all kinds of image formats
+ // so we need to use a TQPixmap here when we finished loading the complete
+ // picture and display it then all at once.
+ if(typeChecked && !formatType)
+ {
+#ifdef CACHE_DEBUG
+ kdDebug(6060) << "CachedImage::data(): reloading as pixmap:" << endl;
+#endif
+ p = new TQPixmap;
+ {
+ TQBuffer buffer(_buffer.buffer());
+ buffer.open(IO_ReadOnly);
+ TQImageIO io( &buffer, 0 );
+ io.setGamma(2.2); // hardcoded "reasonable value"
+ bool result = io.read();
+ if (result) p->convertFromImage(io.image(), 0);
+ }
+
+ // set size of image.
+#ifdef CACHE_DEBUG
+ kdDebug(6060) << "CachedImage::data(): image is null: " << p->isNull() << endl;
+#endif
+ if(p->isNull())
+ {
+ m_hadError = true;
+ do_notify(pixmap(), TQRect(0, 0, 16, 16)); // load "broken image" icon
+ }
+ else
+ do_notify(*p, p->rect());
+
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished( this );
+ m_status = Cached; //all done
+ }
+ }
+}
+
+void CachedImage::finish()
+{
+ Status oldStatus = m_status;
+ CachedObject::finish();
+ if ( oldStatus != m_status ) {
+ const TQPixmap &pm = pixmap();
+ do_notify( pm, pm.rect() );
+ }
+ TQSize s = pixmap_size();
+ setSize( s.width() * s.height() * 2);
+}
+
+
+void CachedImage::error( int /*err*/, const char* /*text*/ )
+{
+ clear();
+ typeChecked = true;
+ m_hadError = true;
+ m_loading = false;
+ do_notify(pixmap(), TQRect(0, 0, 16, 16));
+ for (TQPtrDictIterator<CachedObjectClient> it( m_clients ); it.current();)
+ it()->notifyFinished(this);
+}
+
+// ------------------------------------------------------------------------------------------
+
+Request::Request(DocLoader* dl, CachedObject *_object, bool _incremental)
+{
+ object = _object;
+ object->setRequest(this);
+ incremental = _incremental;
+ m_docLoader = dl;
+}
+
+Request::~Request()
+{
+ object->setRequest(0);
+}
+
+// ------------------------------------------------------------------------------------------
+
+DocLoader::DocLoader(KHTMLPart* part, DocumentImpl* doc)
+{
+ m_cachePolicy = TDEIO::CC_Verify;
+ m_expireDate = 0;
+ m_creationDate = time(0);
+ m_bautoloadImages = true;
+ m_showAnimations = KHTMLSettings::KAnimationEnabled;
+ m_part = part;
+ m_doc = doc;
+
+ Cache::docloader->append( this );
+}
+
+DocLoader::~DocLoader()
+{
+ Cache::loader()->cancelRequests( this );
+ Cache::docloader->remove( this );
+}
+
+void DocLoader::setCacheCreationDate(time_t _creationDate)
+{
+ if (_creationDate)
+ m_creationDate = _creationDate;
+ else
+ m_creationDate = time(0); // Now
+}
+
+void DocLoader::setExpireDate(time_t _expireDate, bool relative)
+{
+ if (relative)
+ m_expireDate = _expireDate + m_creationDate; // Relative date
+ else
+ m_expireDate = _expireDate; // Absolute date
+#ifdef CACHE_DEBUG
+ kdDebug(6061) << "docLoader: " << m_expireDate - time(0) << " seconds left until reload required.\n";
+#endif
+}
+
+void DocLoader::insertCachedObject( CachedObject* o ) const
+{
+ if ( m_docObjects.find(o) )
+ return;
+ m_docObjects.insert( o, o );
+ if ( m_docObjects.count() > 3 * m_docObjects.size() )
+ m_docObjects.resize(tdehtml::nextSeed( m_docObjects.size() ) );
+}
+
+bool DocLoader::needReload(CachedObject *existing, const TQString& fullURL)
+{
+ bool reload = false;
+ if (m_cachePolicy == TDEIO::CC_Verify)
+ {
+ if (!m_reloadedURLs.contains(fullURL))
+ {
+ if (existing && existing->isExpired())
+ {
+ Cache::removeCacheEntry(existing);
+ m_reloadedURLs.append(fullURL);
+ reload = true;
+ }
+ }
+ }
+ else if ((m_cachePolicy == TDEIO::CC_Reload) || (m_cachePolicy == TDEIO::CC_Refresh))
+ {
+ if (!m_reloadedURLs.contains(fullURL))
+ {
+ if (existing)
+ {
+ Cache::removeCacheEntry(existing);
+ }
+ m_reloadedURLs.append(fullURL);
+ reload = true;
+ }
+ }
+ return reload;
+}
+
+#define DOCLOADER_SECCHECK(doRedirectCheck) \
+ KURL fullURL (m_doc->completeURL( url.string() )); \
+ if ( !fullURL.isValid() || \
+ ( m_part && m_part->onlyLocalReferences() && fullURL.protocol() != "file" && fullURL.protocol() != "data") || \
+ doRedirectCheck && ( kapp && m_doc && !kapp->authorizeURLAction("redirect", m_doc->URL(), fullURL))) \
+ return 0L;
+
+CachedImage *DocLoader::requestImage( const DOM::DOMString &url)
+{
+ DOCLOADER_SECCHECK(true);
+
+ CachedImage* i = Cache::requestObject<CachedImage, CachedObject::Image>( this, fullURL, 0);
+
+ if (i && i->status() == CachedObject::Unknown && autoloadImages())
+ Cache::loader()->load(this, i, true);
+
+ return i;
+}
+
+CachedCSSStyleSheet *DocLoader::requestStyleSheet( const DOM::DOMString &url, const TQString& charset,
+ const char *accept, bool userSheet )
+{
+ DOCLOADER_SECCHECK(!userSheet);
+
+ CachedCSSStyleSheet* s = Cache::requestObject<CachedCSSStyleSheet, CachedObject::CSSStyleSheet>( this, fullURL, accept );
+ if ( s && !charset.isEmpty() ) {
+ s->setCharsetHint( charset );
+ }
+ return s;
+}
+
+CachedScript *DocLoader::requestScript( const DOM::DOMString &url, const TQString& charset)
+{
+ DOCLOADER_SECCHECK(true);
+ if ( ! KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(fullURL.host()) ||
+ KHTMLFactory::defaultHTMLSettings()->isAdFiltered(fullURL.url()))
+ return 0L;
+
+ CachedScript* s = Cache::requestObject<CachedScript, CachedObject::Script>( this, fullURL, 0 );
+ if ( s && !charset.isEmpty() )
+ s->setCharset( charset );
+ return s;
+}
+
+#undef DOCLOADER_SECCHECK
+
+void DocLoader::setAutoloadImages( bool enable )
+{
+ if ( enable == m_bautoloadImages )
+ return;
+
+ m_bautoloadImages = enable;
+
+ if ( !m_bautoloadImages ) return;
+
+ for ( TQPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current()) );
+
+ CachedObject::Status status = img->status();
+ if ( status != CachedObject::Unknown )
+ continue;
+
+ Cache::loader()->load(this, img, true);
+ }
+}
+
+void DocLoader::setShowAnimations( KHTMLSettings::KAnimationAdvice showAnimations )
+{
+ if ( showAnimations == m_showAnimations ) return;
+ m_showAnimations = showAnimations;
+
+ for ( TQPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->setShowAnimations( m_showAnimations );
+ }
+}
+
+void DocLoader::pauseAnimations()
+{
+ for ( TQPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->pauseAnimations();
+ }
+}
+
+void DocLoader::resumeAnimations()
+{
+ for ( TQPtrDictIterator<CachedObject> it( m_docObjects ); it.current(); ++it )
+ if ( it.current()->type() == CachedObject::Image )
+ {
+ CachedImage *img = const_cast<CachedImage*>( static_cast<const CachedImage *>( it.current() ) );
+
+ img->resumeAnimations();
+ }
+}
+
+// ------------------------------------------------------------------------------------------
+
+Loader::Loader() : TQObject()
+{
+ m_requestsPending.setAutoDelete( true );
+ m_requestsLoading.setAutoDelete( true );
+ connect(&m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT( servePendingRequests() ) );
+}
+
+void Loader::load(DocLoader* dl, CachedObject *object, bool incremental)
+{
+ Request *req = new Request(dl, object, incremental);
+ m_requestsPending.append(req);
+
+ emit requestStarted( req->m_docLoader, req->object );
+
+ m_timer.start(0, true);
+}
+
+void Loader::servePendingRequests()
+{
+ while ( (m_requestsPending.count() != 0) && (m_requestsLoading.count() < MAX_JOB_COUNT) )
+ {
+ // get the first pending request
+ Request *req = m_requestsPending.take(0);
+
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << "starting Loader url=" << req->object->url().string() << endl;
+#endif
+
+ KURL u(req->object->url().string());
+ TDEIO::TransferJob* job = TDEIO::get( u, false, false /*no GUI*/);
+
+ job->addMetaData("cache", TDEIO::getCacheControlString(req->object->cachePolicy()));
+ if (!req->object->accept().isEmpty())
+ job->addMetaData("accept", req->object->accept());
+ if ( req->m_docLoader )
+ {
+ job->addMetaData( "referrer", req->m_docLoader->doc()->URL().url() );
+
+ KHTMLPart *part = req->m_docLoader->part();
+ if (part )
+ {
+ job->addMetaData( "cross-domain", part->toplevelURL().url() );
+ if (part->widget())
+ job->setWindow (part->widget()->topLevelWidget());
+ }
+ }
+
+ connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ), this, TQT_SLOT( slotFinished( TDEIO::Job * ) ) );
+ connect( job, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray &)),
+ TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray &)));
+
+ if ( req->object->schedule() )
+ TDEIO::Scheduler::scheduleJob( job );
+
+ m_requestsLoading.insert(job, req);
+ }
+}
+
+void Loader::slotFinished( TDEIO::Job* job )
+{
+ Request *r = m_requestsLoading.take( job );
+ TDEIO::TransferJob* j = static_cast<TDEIO::TransferJob*>(job);
+
+ if ( !r )
+ return;
+
+ if (j->error() || j->isErrorPage())
+ {
+#ifdef LOADER_DEBUG
+ kdDebug(6060) << "Loader::slotFinished, with error. job->error()= " << j->error() << " job->isErrorPage()=" << j->isErrorPage() << endl;
+#endif
+ r->object->error( job->error(), job->errorText().ascii() );
+ emit requestFailed( r->m_docLoader, r->object );
+ }
+ else
+ {
+ TQString cs = j->queryMetaData("charset");
+ if (!cs.isEmpty()) r->object->setCharset(cs);
+ r->object->data(r->m_buffer, true);
+ emit requestDone( r->m_docLoader, r->object );
+ time_t expireDate = j->queryMetaData("expire-date").toLong();
+#ifdef LOADER_DEBUG
+ kdDebug(6060) << "Loader::slotFinished, url = " << j->url().url() << endl;
+#endif
+ r->object->setExpireDate( expireDate );
+
+ if ( r->object->type() == CachedObject::Image ) {
+ TQString fn = j->queryMetaData("content-disposition");
+ static_cast<CachedImage*>( r->object )->setSuggestedFilename(fn);
+#ifdef IMAGE_TITLES
+ static_cast<CachedImage*>( r->object )->setSuggestedTitle(fn);
+ KTempFile tf;
+ tf.setAutoDelete(true);
+ tf.file()->writeBlock((const char*)r->m_buffer.buffer().data(), r->m_buffer.size());
+ tf.sync();
+ KFileMetaInfo kfmi(tf.name());
+ if (!kfmi.isEmpty()) {
+ KFileMetaInfoItem i = kfmi.item("Name");
+ if (i.isValid()) {
+ static_cast<CachedImage*>(r->object)->setSuggestedTitle(i.string());
+ } else {
+ i = kfmi.item("Title");
+ if (i.isValid()) {
+ static_cast<CachedImage*>(r->object)->setSuggestedTitle(i.string());
+ }
+ }
+ }
+#endif
+ }
+ }
+
+ r->object->finish();
+
+#ifdef LOADER_DEBUG
+ kdDebug( 6060 ) << "Loader:: JOB FINISHED " << r->object << ": " << r->object->url().string() << endl;
+#endif
+
+ delete r;
+
+ if ( (m_requestsPending.count() != 0) && (m_requestsLoading.count() < MAX_JOB_COUNT / 2) )
+ m_timer.start(0, true);
+}
+
+void Loader::slotData( TDEIO::Job*job, const TQByteArray &data )
+{
+ Request *r = m_requestsLoading[job];
+ if(!r) {
+ kdDebug( 6060 ) << "got data for unknown request!" << endl;
+ return;
+ }
+
+ if ( !r->m_buffer.isOpen() )
+ r->m_buffer.open( IO_WriteOnly );
+
+ r->m_buffer.writeBlock( data.data(), data.size() );
+
+ if(r->incremental)
+ r->object->data( r->m_buffer, false );
+}
+
+int Loader::numRequests( DocLoader* dl ) const
+{
+ int res = 0;
+
+ TQPtrListIterator<Request> pIt( m_requestsPending );
+ for (; pIt.current(); ++pIt )
+ if ( pIt.current()->m_docLoader == dl )
+ res++;
+
+ TQPtrDictIterator<Request> lIt( m_requestsLoading );
+ for (; lIt.current(); ++lIt )
+ if ( lIt.current()->m_docLoader == dl )
+ res++;
+
+ return res;
+}
+
+void Loader::cancelRequests( DocLoader* dl )
+{
+ TQPtrListIterator<Request> pIt( m_requestsPending );
+ while ( pIt.current() ) {
+ if ( pIt.current()->m_docLoader == dl )
+ {
+ CDEBUG << "canceling pending request for " << pIt.current()->object->url().string() << endl;
+ Cache::removeCacheEntry( pIt.current()->object );
+ m_requestsPending.remove( pIt );
+ }
+ else
+ ++pIt;
+ }
+
+ //kdDebug( 6060 ) << "got " << m_requestsLoading.count() << "loading requests" << endl;
+
+ TQPtrDictIterator<Request> lIt( m_requestsLoading );
+ while ( lIt.current() )
+ {
+ if ( lIt.current()->m_docLoader == dl )
+ {
+ //kdDebug( 6060 ) << "canceling loading request for " << lIt.current()->object->url().string() << endl;
+ TDEIO::Job *job = static_cast<TDEIO::Job *>( lIt.currentKey() );
+ Cache::removeCacheEntry( lIt.current()->object );
+ m_requestsLoading.remove( lIt.currentKey() );
+ job->kill();
+ //emit requestFailed( dl, pIt.current()->object );
+ }
+ else
+ ++lIt;
+ }
+}
+
+TDEIO::Job *Loader::jobForRequest( const DOM::DOMString &url ) const
+{
+ TQPtrDictIterator<Request> it( m_requestsLoading );
+
+ for (; it.current(); ++it )
+ {
+ CachedObject *obj = it.current()->object;
+
+ if ( obj && obj->url() == url )
+ return static_cast<TDEIO::Job *>( it.currentKey() );
+ }
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+
+
+TQDict<CachedObject> *Cache::cache = 0;
+TQPtrList<DocLoader>* Cache::docloader = 0;
+TQPtrList<CachedObject> *Cache::freeList = 0;
+Loader *Cache::m_loader = 0;
+
+int Cache::maxSize = DEFCACHESIZE;
+int Cache::totalSizeOfLRU;
+
+TQPixmap *Cache::nullPixmap = 0;
+TQPixmap *Cache::brokenPixmap = 0;
+TQPixmap *Cache::blockedPixmap = 0;
+
+void Cache::init()
+{
+ if ( !cache )
+ cache = new TQDict<CachedObject>(401, true);
+
+ if ( !docloader )
+ docloader = new TQPtrList<DocLoader>;
+
+ if ( !nullPixmap )
+ nullPixmap = new TQPixmap;
+
+ if ( !brokenPixmap )
+ brokenPixmap = new TQPixmap(KHTMLFactory::instance()->iconLoader()->loadIcon("file_broken", KIcon::Desktop, 16, KIcon::DisabledState));
+
+ if ( !blockedPixmap ) {
+ blockedPixmap = new TQPixmap();
+ blockedPixmap->loadFromData(blocked_icon_data, blocked_icon_len);
+ }
+
+ if ( !m_loader )
+ m_loader = new Loader();
+
+ if ( !freeList ) {
+ freeList = new TQPtrList<CachedObject>;
+ freeList->setAutoDelete(true);
+ }
+}
+
+void Cache::clear()
+{
+ if ( !cache ) return;
+#ifdef CACHE_DEBUG
+ kdDebug( 6060 ) << "Cache: CLEAR!" << endl;
+ statistics();
+#endif
+ cache->setAutoDelete( true );
+
+#ifndef NDEBUG
+ bool crash = false;
+ for (TQDictIterator<CachedObject> it(*cache); it.current(); ++it) {
+ if (!it.current()->canDelete()) {
+ kdDebug( 6060 ) << " Object in cache still linked to" << endl;
+ kdDebug( 6060 ) << " -> URL: " << it.current()->url() << endl;
+ kdDebug( 6060 ) << " -> #clients: " << it.current()->count() << endl;
+ crash = true;
+// assert(it.current()->canDelete());
+ }
+ }
+ for (freeList->first(); freeList->current(); freeList->next()) {
+ if (!freeList->current()->canDelete()) {
+ kdDebug( 6060 ) << " Object in freelist still linked to" << endl;
+ kdDebug( 6060 ) << " -> URL: " << freeList->current()->url() << endl;
+ kdDebug( 6060 ) << " -> #clients: " << freeList->current()->count() << endl;
+ crash = true;
+ /*
+ TQPtrDictIterator<CachedObjectClient> it(freeList->current()->m_clients);
+ for(;it.current(); ++it) {
+ if (dynamic_cast<RenderObject*>(it.current())) {
+ kdDebug( 6060 ) << " --> RenderObject" << endl;
+ } else
+ kdDebug( 6060 ) << " --> Something else" << endl;
+ }*/
+ }
+// assert(freeList->current()->canDelete());
+ }
+ assert(!crash);
+#endif
+
+ delete cache; cache = 0;
+ delete nullPixmap; nullPixmap = 0;
+ delete brokenPixmap; brokenPixmap = 0;
+ delete blockedPixmap; blockedPixmap = 0;
+ delete m_loader; m_loader = 0;
+ delete docloader; docloader = 0;
+ delete freeList; freeList = 0;
+}
+
+template<typename CachedObjectType, enum CachedObject::Type CachedType>
+CachedObjectType* Cache::requestObject( DocLoader* dl, const KURL& kurl, const char* accept )
+{
+ TDEIO::CacheControl cachePolicy = dl ? dl->cachePolicy() : TDEIO::CC_Verify;
+
+ TQString url = kurl.url();
+ CachedObject* o = cache->find(url);
+
+ if ( o && o->type() != CachedType ) {
+ removeCacheEntry( o );
+ o = 0;
+ }
+
+ if ( o && dl->needReload( o, url ) ) {
+ o = 0;
+ assert( cache->find( url ) == 0 );
+ }
+
+ if(!o)
+ {
+#ifdef CACHE_DEBUG
+ kdDebug( 6060 ) << "Cache: new: " << kurl.url() << endl;
+#endif
+ CachedObjectType* cot = new CachedObjectType(dl, url, cachePolicy, accept);
+ cache->insert( url, cot );
+ if ( cot->allowInLRUList() )
+ insertInLRUList( cot );
+ o = cot;
+ }
+#ifdef CACHE_DEBUG
+ else {
+ kdDebug( 6060 ) << "Cache: using pending/cached: " << kurl.url() << endl;
+ }
+#endif
+
+
+ dl->insertCachedObject( o );
+
+ return static_cast<CachedObjectType *>(o);
+}
+
+void Cache::preloadStyleSheet( const TQString &url, const TQString &stylesheet_data)
+{
+ CachedObject *o = cache->find(url);
+ if(o)
+ removeCacheEntry(o);
+
+ CachedCSSStyleSheet *stylesheet = new CachedCSSStyleSheet(url, stylesheet_data);
+ cache->insert( url, stylesheet );
+}
+
+void Cache::preloadScript( const TQString &url, const TQString &script_data)
+{
+ CachedObject *o = cache->find(url);
+ if(o)
+ removeCacheEntry(o);
+
+ CachedScript *script = new CachedScript(url, script_data);
+ cache->insert( url, script );
+}
+
+void Cache::flush(bool force)
+{
+ init();
+
+ if ( force || totalSizeOfLRU > maxSize + maxSize/4) {
+ for ( int i = MAX_LRU_LISTS-1; i >= 0 && totalSizeOfLRU > maxSize; --i )
+ while ( totalSizeOfLRU > maxSize && m_LRULists[i].m_tail )
+ removeCacheEntry( m_LRULists[i].m_tail );
+
+#ifdef CACHE_DEBUG
+ statistics();
+#endif
+ }
+
+ for ( freeList->first(); freeList->current(); ) {
+ CachedObject* p = freeList->current();
+ if ( p->canDelete() )
+ freeList->remove();
+ else
+ freeList->next();
+ }
+
+}
+
+void Cache::setSize( int bytes )
+{
+ maxSize = bytes;
+ flush(true /* force */);
+}
+
+void Cache::statistics()
+{
+ CachedObject *o;
+ // this function is for debugging purposes only
+ init();
+
+ int size = 0;
+ int msize = 0;
+ int movie = 0;
+ int images = 0;
+ int scripts = 0;
+ int stylesheets = 0;
+ TQDictIterator<CachedObject> it(*cache);
+ for(it.toFirst(); it.current(); ++it)
+ {
+ o = it.current();
+ switch(o->type()) {
+ case CachedObject::Image:
+ {
+ CachedImage *im = static_cast<CachedImage *>(o);
+ images++;
+ if(im->m != 0)
+ {
+ movie++;
+ msize += im->size();
+ }
+ break;
+ }
+ case CachedObject::CSSStyleSheet:
+ stylesheets++;
+ break;
+ case CachedObject::Script:
+ scripts++;
+ break;
+ }
+ size += o->size();
+ }
+ size /= 1024;
+
+ kdDebug( 6060 ) << "------------------------- image cache statistics -------------------" << endl;
+ kdDebug( 6060 ) << "Number of items in cache: " << cache->count() << endl;
+ kdDebug( 6060 ) << "Number of cached images: " << images << endl;
+ kdDebug( 6060 ) << "Number of cached movies: " << movie << endl;
+ kdDebug( 6060 ) << "Number of cached scripts: " << scripts << endl;
+ kdDebug( 6060 ) << "Number of cached stylesheets: " << stylesheets << endl;
+ kdDebug( 6060 ) << "pixmaps: allocated space approx. " << size << " kB" << endl;
+ kdDebug( 6060 ) << "movies : allocated space approx. " << msize/1024 << " kB" << endl;
+ kdDebug( 6060 ) << "--------------------------------------------------------------------" << endl;
+}
+
+void Cache::removeCacheEntry( CachedObject *object )
+{
+ TQString key = object->url().string();
+
+ cache->remove( key );
+ removeFromLRUList( object );
+
+ for (const DocLoader* dl=docloader->first(); dl; dl=docloader->next() )
+ dl->removeCachedObject( object );
+
+ if ( !object->free() ) {
+ Cache::freeList->append( object );
+ object->m_free = true;
+ }
+}
+
+static inline int FastLog2(unsigned int j)
+{
+ unsigned int log2;
+ log2 = 0;
+ if (j & (j-1))
+ log2 += 1;
+ if (j >> 16)
+ log2 += 16, j >>= 16;
+ if (j >> 8)
+ log2 += 8, j >>= 8;
+ if (j >> 4)
+ log2 += 4, j >>= 4;
+ if (j >> 2)
+ log2 += 2, j >>= 2;
+ if (j >> 1)
+ log2 += 1;
+
+ return log2;
+}
+
+static LRUList* getLRUListFor(CachedObject* o)
+{
+ int accessCount = o->accessCount();
+ int queueIndex;
+ if (accessCount == 0) {
+ queueIndex = 0;
+ } else {
+ int sizeLog = FastLog2(o->size());
+ queueIndex = sizeLog/o->accessCount() - 1;
+ if (queueIndex < 0)
+ queueIndex = 0;
+ if (queueIndex >= MAX_LRU_LISTS)
+ queueIndex = MAX_LRU_LISTS-1;
+ }
+ return &m_LRULists[queueIndex];
+}
+
+void Cache::removeFromLRUList(CachedObject *object)
+{
+ CachedObject *next = object->m_next;
+ CachedObject *prev = object->m_prev;
+
+ LRUList* list = getLRUListFor(object);
+ CachedObject *&head = getLRUListFor(object)->m_head;
+
+ if (next == 0 && prev == 0 && head != object) {
+ return;
+ }
+
+ object->m_next = 0;
+ object->m_prev = 0;
+
+ if (next)
+ next->m_prev = prev;
+ else if (list->m_tail == object)
+ list->m_tail = prev;
+
+ if (prev)
+ prev->m_next = next;
+ else if (head == object)
+ head = next;
+
+ totalSizeOfLRU -= object->size();
+}
+
+void Cache::insertInLRUList(CachedObject *object)
+{
+ removeFromLRUList(object);
+
+ assert( object );
+ assert( !object->free() );
+ assert( object->canDelete() );
+ assert( object->allowInLRUList() );
+
+ LRUList* list = getLRUListFor(object);
+
+ CachedObject *&head = list->m_head;
+
+ object->m_next = head;
+ if (head)
+ head->m_prev = object;
+ head = object;
+
+ if (object->m_next == 0)
+ list->m_tail = object;
+
+ totalSizeOfLRU += object->size();
+}
+
+// --------------------------------------
+
+void CachedObjectClient::setPixmap(const TQPixmap &, const TQRect&, CachedImage *) {}
+void CachedObjectClient::setStyleSheet(const DOM::DOMString &/*url*/, const DOM::DOMString &/*sheet*/, const DOM::DOMString &/*charset*/) {}
+void CachedObjectClient::notifyFinished(CachedObject * /*finishedObj*/) {}
+void CachedObjectClient::error(int /*err*/, const TQString &/*text*/) {}
+
+#undef CDEBUG
+
+#include "loader.moc"
diff --git a/tdehtml/misc/loader.h b/tdehtml/misc/loader.h
new file mode 100644
index 000000000..97e637120
--- /dev/null
+++ b/tdehtml/misc/loader.h
@@ -0,0 +1,522 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2001-2003 Dirk Mueller <mueller@kde.org>
+ Copyright (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.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef _tdehtml_loader_h
+#define _tdehtml_loader_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+
+#include "loader_client.h"
+#ifdef HAVE_LIBJPEG
+#include "loader_jpeg.h"
+#endif
+
+#include <stdlib.h>
+#include <tqptrlist.h>
+#include <tqobject.h>
+#include <tqptrdict.h>
+#include <tqdict.h>
+#include <tqpixmap.h>
+#include <tqbuffer.h>
+#include <tqstringlist.h>
+#include <tqtextcodec.h>
+#include <tqtimer.h>
+
+#include <kurl.h>
+#include <kio/global.h>
+
+#include <tdehtml_settings.h>
+#include <dom/dom_string.h>
+
+class TQMovie;
+class KHTMLPart;
+
+namespace TDEIO {
+ class Job;
+ class TransferJob;
+}
+
+namespace DOM
+{
+ class CSSStyleSheetImpl;
+ class DocumentImpl;
+}
+
+namespace tdehtml
+{
+ class CachedObject;
+ class Request;
+ class DocLoader;
+
+ /**
+ * @internal
+ *
+ * A cached object. Classes who want to use this object should derive
+ * from CachedObjectClient, to get the function calls in case the requested data has arrived.
+ *
+ * This class also does the actual communication with kio and loads the file.
+ */
+ class CachedObject
+ {
+ public:
+ enum Type {
+ Image,
+ CSSStyleSheet,
+ Script
+ };
+
+ enum Status {
+ Unknown, // let imagecache decide what to do with it
+ New, // inserting new image
+ Pending, // only partially loaded
+ Persistent, // never delete this pixmap
+ Cached // regular case
+ };
+
+ CachedObject(const DOM::DOMString &url, Type type, TDEIO::CacheControl _cachePolicy, int size)
+ : m_url(url), m_type(type), m_cachePolicy(_cachePolicy),
+ m_expireDate(0), m_size(size)
+ {
+ m_status = Pending;
+ m_accessCount = 0;
+ m_cachePolicy = _cachePolicy;
+ m_request = 0;
+ m_deleted = false;
+ m_free = false;
+ m_hadError = false;
+ m_wasBlocked = false;
+ m_prev = m_next = 0;
+ }
+ virtual ~CachedObject();
+
+ virtual void data( TQBuffer &buffer, bool eof) = 0;
+ virtual void error( int err, const char *text ) = 0;
+
+ const DOM::DOMString &url() const { return m_url; }
+ Type type() const { return m_type; }
+
+ virtual void ref(CachedObjectClient *consumer);
+ virtual void deref(CachedObjectClient *consumer);
+
+ int count() const { return m_clients.count(); }
+ int accessCount() const { return m_accessCount; }
+
+ void setStatus(Status s) { m_status = s; }
+ Status status() const { return m_status; }
+
+ virtual void setCharset( const TQString& /*charset*/ ) {}
+
+ TQTextCodec* codecForBuffer( const TQString& charset, const TQByteArray& buffer ) const;
+
+ int size() const { return m_size; }
+
+ bool isLoaded() const { return !m_loading; }
+
+ bool free() const { return m_free; }
+
+ TDEIO::CacheControl cachePolicy() const { return m_cachePolicy; }
+
+ void setRequest(Request *_request);
+
+ bool canDelete() const { return (m_clients.count() == 0 && !m_request); }
+
+ void setExpireDate(time_t _expireDate) { m_expireDate = _expireDate; }
+
+ bool isExpired() const;
+
+ virtual bool schedule() const { return false; }
+ virtual void finish();
+
+ /**
+ * List of acceptable mimetypes separated by ",". A mimetype may contain a wildcard.
+ */
+ // e.g. "text/*"
+ TQString accept() const { return m_accept; }
+ void setAccept(const TQString &_accept) { m_accept = _accept; }
+
+ protected:
+ void setSize(int size);
+ TQPtrDict<CachedObjectClient> m_clients;
+ DOM::DOMString m_url;
+ TQString m_accept;
+ Request *m_request;
+ Type m_type;
+ Status m_status;
+ int m_accessCount;
+ TDEIO::CacheControl m_cachePolicy;
+ time_t m_expireDate;
+ int m_size;
+ bool m_deleted : 1;
+ bool m_loading : 1;
+ bool m_free : 1;
+ bool m_hadError : 1;
+ bool m_wasBlocked : 1;
+
+ private:
+ bool allowInLRUList() const { return canDelete() && !m_free && status() != Persistent; }
+ CachedObject* m_next;
+ CachedObject* m_prev;
+ friend class Cache;
+ friend class ::KHTMLPart;
+ };
+
+
+ /**
+ * a cached style sheet. also used for loading xml documents.
+ *
+ * ### rename to CachedTextDoc or something since it's more generic than just for css
+ */
+ class CachedCSSStyleSheet : public CachedObject
+ {
+ public:
+ CachedCSSStyleSheet(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy,
+ const char *accept);
+ CachedCSSStyleSheet(const DOM::DOMString &url, const TQString &stylesheet_data);
+
+ const DOM::DOMString &sheet() const { return m_sheet; }
+
+ virtual void ref(CachedObjectClient *consumer);
+
+ virtual void data( TQBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ virtual bool schedule() const { return true; }
+ void setCharsetHint( const TQString& charset ) { m_charsetHint = charset; }
+ void setCharset( const TQString& charset ) { m_charset = charset; }
+
+ protected:
+ void checkNotify();
+
+ DOM::DOMString m_sheet;
+ TQString m_charset;
+ TQString m_charsetHint;
+ int m_err;
+ TQString m_errText;
+ };
+
+ /**
+ * a cached script
+ */
+ class CachedScript : public CachedObject
+ {
+ public:
+ CachedScript(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy, const char* accept );
+ CachedScript(const DOM::DOMString &url, const TQString &script_data);
+
+ const DOM::DOMString &script() const { return m_script; }
+
+ virtual void ref(CachedObjectClient *consumer);
+
+ virtual void data( TQBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ virtual bool schedule() const { return false; }
+
+ void checkNotify();
+
+ bool isLoaded() const { return !m_loading; }
+ void setCharset( const TQString& charset ) { m_charset = charset; }
+
+ protected:
+ TQString m_charset;
+ DOM::DOMString m_script;
+ };
+
+ class ImageSource;
+
+ /**
+ * a cached image
+ */
+ class CachedImage : public TQObject, public CachedObject
+ {
+ Q_OBJECT
+ public:
+ CachedImage(DocLoader* dl, const DOM::DOMString &url, TDEIO::CacheControl cachePolicy, const char* accept);
+ virtual ~CachedImage();
+
+ const TQPixmap &pixmap() const;
+ const TQPixmap &scaled_pixmap(int xWidth, int xHeight);
+ const TQPixmap &tiled_pixmap(const TQColor& bg, int xWidth = -1, int xHeight = -1);
+
+ TQSize pixmap_size() const; // returns the size of the complete (i.e. when finished) loading
+ TQRect valid_rect() const; // returns the rectangle of pixmap that has been loaded already
+
+ bool canRender() const { return !isErrorImage() && pixmap_size().width() > 0 && pixmap_size().height() > 0; }
+ void ref(CachedObjectClient *consumer);
+ virtual void deref(CachedObjectClient *consumer);
+
+ virtual void data( TQBuffer &buffer, bool eof );
+ virtual void error( int err, const char *text );
+
+ bool isTransparent() const { return isFullyTransparent; }
+ bool isErrorImage() const { return m_hadError; }
+ bool isBlockedImage() const { return m_wasBlocked; }
+ const TQString& suggestedFilename() const { return m_suggestedFilename; }
+ void setSuggestedFilename( const TQString& s ) { m_suggestedFilename = s; }
+#ifdef IMAGE_TITLES
+ const TQString& suggestedTitle() const { return m_suggestedTitle; }
+ void setSuggestedTitle( const TQString& s ) { m_suggestedTitle = s; }
+#else
+ const TQString& suggestedTitle() const { return m_suggestedFilename; }
+#endif
+
+ void setShowAnimations( KHTMLSettings::KAnimationAdvice );
+ void pauseAnimations();
+ void resumeAnimations();
+
+ virtual bool schedule() const { return true; }
+
+ virtual void finish();
+
+ protected:
+ void clear();
+
+ private slots:
+ /**
+ * gets called, whenever a TQMovie changes frame
+ */
+ void movieUpdated( const TQRect &rect );
+ void movieStatus(int);
+ void movieResize(const TQSize&);
+ void deleteMovie();
+
+ private:
+ void do_notify(const TQPixmap& p, const TQRect& r);
+
+ TQString m_suggestedFilename;
+#ifdef IMAGE_TITLES
+ TQString m_suggestedTitle;
+#endif
+ TQMovie* m;
+ TQPixmap* p;
+ TQPixmap* scaled;
+ TQPixmap* bg;
+ QRgb bgColor;
+ TQSize bgSize;
+ mutable TQPixmap* pixPart;
+
+ ImageSource* imgSource;
+ const char* formatType; // Is the name of the movie format type
+
+ int width;
+ int height;
+
+ // Is set if movie format type ( incremental/animation) was checked
+ bool typeChecked : 1;
+ bool isFullyTransparent : 1;
+ bool monochrome : 1;
+ KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
+
+ friend class Cache;
+ friend class ::KHTMLPart;
+ };
+
+ /**
+ * @internal
+ *
+ * Manages the loading of scripts/images/stylesheets for a particular document
+ */
+ class DocLoader
+ {
+ public:
+ DocLoader(KHTMLPart*, DOM::DocumentImpl*);
+ ~DocLoader();
+
+ CachedImage *requestImage( const DOM::DOMString &url);
+ CachedCSSStyleSheet *requestStyleSheet( const DOM::DOMString &url, const TQString& charsetHint,
+ const char *accept = "text/css", bool userSheet = false );
+ CachedScript *requestScript( const DOM::DOMString &url, const TQString& charset);
+
+ bool autoloadImages() const { return m_bautoloadImages; }
+ TDEIO::CacheControl cachePolicy() const { return m_cachePolicy; }
+ KHTMLSettings::KAnimationAdvice showAnimations() const { return m_showAnimations; }
+ time_t expireDate() const { return m_expireDate; }
+ KHTMLPart* part() const { return m_part; }
+ DOM::DocumentImpl* doc() const { return m_doc; }
+
+ void setCacheCreationDate( time_t );
+ void setExpireDate( time_t, bool relative );
+ void setAutoloadImages( bool );
+ void setCachePolicy( TDEIO::CacheControl cachePolicy ) { m_cachePolicy = cachePolicy; }
+ void setShowAnimations( KHTMLSettings::KAnimationAdvice );
+ void pauseAnimations();
+ void resumeAnimations();
+ void insertCachedObject( CachedObject* o ) const;
+ void removeCachedObject( CachedObject* o) const { m_docObjects.remove( o ); }
+
+ private:
+ bool needReload(CachedObject *existing, const TQString &fullUrl);
+
+ friend class Cache;
+ friend class DOM::DocumentImpl;
+ friend class ::KHTMLPart;
+
+ TQStringList m_reloadedURLs;
+ mutable TQPtrDict<CachedObject> m_docObjects;
+ time_t m_expireDate;
+ time_t m_creationDate;
+ TDEIO::CacheControl m_cachePolicy;
+ bool m_bautoloadImages : 1;
+ KHTMLSettings::KAnimationAdvice m_showAnimations : 2;
+ KHTMLPart* m_part;
+ DOM::DocumentImpl* m_doc;
+ };
+
+ /**
+ * @internal
+ */
+ class Request
+ {
+ public:
+ Request(DocLoader* dl, CachedObject *_object, bool _incremental);
+ ~Request();
+ bool incremental;
+ TQBuffer m_buffer;
+ CachedObject *object;
+ DocLoader* m_docLoader;
+ };
+
+ /**
+ * @internal
+ */
+ class Loader : public TQObject
+ {
+ Q_OBJECT
+
+ public:
+ Loader();
+
+ void load(DocLoader* dl, CachedObject *object, bool incremental = true);
+
+ int numRequests( DocLoader* dl ) const;
+ void cancelRequests( DocLoader* dl );
+
+ // may return 0L
+ TDEIO::Job *jobForRequest( const DOM::DOMString &url ) const;
+
+ signals:
+ void requestStarted( tdehtml::DocLoader* dl, tdehtml::CachedObject* obj );
+ void requestDone( tdehtml::DocLoader* dl, tdehtml::CachedObject *obj );
+ void requestFailed( tdehtml::DocLoader* dl, tdehtml::CachedObject *obj );
+
+ protected slots:
+ void slotFinished( TDEIO::Job * );
+ void slotData( TDEIO::Job *, const TQByteArray & );
+ void servePendingRequests();
+
+ protected:
+ TQPtrList<Request> m_requestsPending;
+ TQPtrDict<Request> m_requestsLoading;
+#ifdef HAVE_LIBJPEG
+ KJPEGFormatType m_jpegloader;
+#endif
+ TQTimer m_timer;
+ };
+
+ /**
+ * @internal
+ *
+ * Provides a cache/loader for objects needed for displaying the html page.
+ * At the moment these are stylesheets, scripts and images
+ */
+ class Cache
+ {
+ friend class DocLoader;
+
+ template<typename CachedObjectType, enum CachedObject::Type CachedType>
+ static CachedObjectType* requestObject( DocLoader* dl, const KURL& kurl, const char* accept );
+
+ public:
+ /**
+ * init the cache in case it's not already. This needs to get called once
+ * before using it.
+ */
+ KDE_EXPORT static void init();
+
+ /**
+ * Ask the cache for some url. Will return a cachedObject, and
+ * load the requested data in case it's not cached
+ * if the DocLoader is zero, the url must be full-qualified.
+ * Otherwise, it is automatically base-url expanded
+ */
+// static CachedImage *requestImage(const KURL& url)
+// { return Cache::requestObject<CachedImage, CachedObject::Image>( 0, url, 0 ); }
+
+ /**
+ * Pre-loads a stylesheet into the cache.
+ */
+ static void preloadStyleSheet(const TQString &url, const TQString &stylesheet_data);
+
+ /**
+ * Pre-loads a script into the cache.
+ */
+ static void preloadScript(const TQString &url, const TQString &script_data);
+
+ static void setSize( int bytes );
+ static int size() { return maxSize; };
+ static void statistics();
+ KDE_EXPORT static void flush(bool force=false);
+
+ /**
+ * clears the cache
+ * Warning: call this only at the end of your program, to clean
+ * up memory (useful for finding memory holes)
+ */
+ KDE_EXPORT static void clear();
+
+ static Loader *loader() { return m_loader; }
+
+ static TQPixmap *nullPixmap;
+ static TQPixmap *brokenPixmap;
+ static TQPixmap *blockedPixmap;
+ static int cacheSize;
+
+ static void removeCacheEntry( CachedObject *object );
+
+ private:
+
+ static void checkLRUAndUncacheableListIntegrity();
+
+ friend class CachedObject;
+
+ static TQDict<CachedObject> *cache;
+ static TQPtrList<DocLoader>* docloader;
+ static TQPtrList<CachedObject> *freeList;
+ static void insertInLRUList(CachedObject*);
+ static void removeFromLRUList(CachedObject*);
+
+ static int totalSizeOfLRU;
+ static int maxSize;
+
+ static Loader *m_loader;
+ };
+
+} // namespace
+
+#endif
diff --git a/tdehtml/misc/loader_client.h b/tdehtml/misc/loader_client.h
new file mode 100644
index 000000000..d61a52b51
--- /dev/null
+++ b/tdehtml/misc/loader_client.h
@@ -0,0 +1,35 @@
+#ifndef LOADER_CLIENT_H
+#define LOADER_CLIENT_H
+
+#include <tqpixmap.h>
+#include "dom/dom_string.h"
+
+namespace tdehtml {
+ class CachedObject;
+ class CachedImage;
+
+ /**
+ * @internal
+ *
+ * a client who wants to load stylesheets, images or scripts from the web has to
+ * inherit from this class and overload one of the 3 functions
+ *
+ */
+ class CachedObjectClient
+ {
+ public:
+ virtual ~CachedObjectClient();
+ // clipped pixmap (if it is not yet completely loaded,
+ // size of the complete (finished loading) pixmap
+ // rectangle of the part that has been loaded very recently
+ // pointer to us
+ // return whether we need manual update
+ // don't ref() or deref() elements in setPixmap!!
+ virtual void setPixmap(const TQPixmap &, const TQRect&, CachedImage *);
+ virtual void setStyleSheet(const DOM::DOMString &/*url*/, const DOM::DOMString &/*sheet*/, const DOM::DOMString &/*charset*/);
+ virtual void notifyFinished(CachedObject * /*finishedObj*/);
+ virtual void error(int err, const TQString &text);
+ };
+}
+
+#endif
diff --git a/tdehtml/misc/loader_jpeg.cpp b/tdehtml/misc/loader_jpeg.cpp
new file mode 100644
index 000000000..72816817f
--- /dev/null
+++ b/tdehtml/misc/loader_jpeg.cpp
@@ -0,0 +1,548 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBJPEG
+// on some systems, libjpeg installs its config.h file which causes a conflict
+// and makes the compiler barf with "XXX already defined".
+#ifdef HAVE_STDLIB_H
+#undef HAVE_STDLIB_H
+#endif
+#include "loader_jpeg.h"
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <tqdatetime.h>
+#include <kglobal.h>
+
+extern "C" {
+#define XMD_H
+#include <jpeglib.h>
+#undef const
+}
+
+
+#undef BUFFER_DEBUG
+//#define BUFFER_DEBUG
+
+#undef JPEG_DEBUG
+//#define JPEG_DEBUG
+
+// -----------------------------------------------------------------------------
+
+struct tdehtml_error_mgr : public jpeg_error_mgr {
+ jmp_buf setjmp_buffer;
+};
+
+extern "C" {
+
+ static
+ void tdehtml_error_exit (j_common_ptr cinfo)
+ {
+ tdehtml_error_mgr* myerr = (tdehtml_error_mgr*) cinfo->err;
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo, buffer);
+#ifdef JPEG_DEBUG
+ tqWarning("%s", buffer);
+#endif
+ longjmp(myerr->setjmp_buffer, 1);
+ }
+}
+
+static const int max_buf = 32768;
+static const int max_consumingtime = 2000;
+
+struct tdehtml_jpeg_source_mgr : public jpeg_source_mgr {
+ JOCTET buffer[max_buf];
+
+ int valid_buffer_len;
+ size_t skip_input_bytes;
+ int ateof;
+ TQRect change_rect;
+ TQRect old_change_rect;
+ TQTime decoder_timestamp;
+ bool final_pass;
+ bool decoding_done;
+ bool do_progressive;
+
+public:
+ tdehtml_jpeg_source_mgr() KDE_NO_EXPORT;
+};
+
+
+extern "C" {
+
+ static
+ void tdehtml_j_decompress_dummy(j_decompress_ptr)
+ {
+ }
+
+ static
+ boolean tdehtml_fill_input_buffer(j_decompress_ptr cinfo)
+ {
+#ifdef BUFFER_DEBUG
+ tqDebug("tdehtml_fill_input_buffer called!");
+#endif
+
+ tdehtml_jpeg_source_mgr* src = (tdehtml_jpeg_source_mgr*)cinfo->src;
+
+ if ( src->ateof )
+ {
+ /* Insert a fake EOI marker - as per jpeglib recommendation */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ src->bytes_in_buffer = 2;
+ src->next_input_byte = (JOCTET *) src->buffer;
+#ifdef BUFFER_DEBUG
+ tqDebug("...returning true!");
+#endif
+ return true;
+ }
+ else
+ return false; /* I/O suspension mode */
+ }
+
+ static
+ void tdehtml_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+ {
+ if(num_bytes <= 0)
+ return; /* required noop */
+
+#ifdef BUFFER_DEBUG
+ tqDebug("tdehtml_skip_input_data (%d) called!", num_bytes);
+#endif
+
+ tdehtml_jpeg_source_mgr* src = (tdehtml_jpeg_source_mgr*)cinfo->src;
+ src->skip_input_bytes += num_bytes;
+
+ unsigned int skipbytes = kMin(src->bytes_in_buffer, src->skip_input_bytes);
+
+#ifdef BUFFER_DEBUG
+ tqDebug("skip_input_bytes is now %d", src->skip_input_bytes);
+ tqDebug("skipbytes is now %d", skipbytes);
+ tqDebug("valid_buffer_len is before %d", src->valid_buffer_len);
+ tqDebug("bytes_in_buffer is %d", src->bytes_in_buffer);
+#endif
+
+ if(skipbytes < src->bytes_in_buffer)
+ memmove(src->buffer, src->next_input_byte+skipbytes, src->bytes_in_buffer - skipbytes);
+
+ src->bytes_in_buffer -= skipbytes;
+ src->valid_buffer_len = src->bytes_in_buffer;
+ src->skip_input_bytes -= skipbytes;
+
+ /* adjust data for jpeglib */
+ cinfo->src->next_input_byte = (JOCTET *) src->buffer;
+ cinfo->src->bytes_in_buffer = (size_t) src->valid_buffer_len;
+#ifdef BUFFER_DEBUG
+ tqDebug("valid_buffer_len is afterwards %d", src->valid_buffer_len);
+ tqDebug("skip_input_bytes is now %d", src->skip_input_bytes);
+#endif
+ }
+}
+
+
+tdehtml_jpeg_source_mgr::tdehtml_jpeg_source_mgr()
+{
+ jpeg_source_mgr::init_source = tdehtml_j_decompress_dummy;
+ jpeg_source_mgr::fill_input_buffer = tdehtml_fill_input_buffer;
+ jpeg_source_mgr::skip_input_data = tdehtml_skip_input_data;
+ jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart;
+ jpeg_source_mgr::term_source = tdehtml_j_decompress_dummy;
+ bytes_in_buffer = 0;
+ valid_buffer_len = 0;
+ skip_input_bytes = 0;
+ ateof = 0;
+ next_input_byte = buffer;
+ final_pass = false;
+ decoding_done = false;
+}
+
+
+
+// -----------------------------------------------------------------------------
+
+class KJPEGFormat : public TQImageFormat
+{
+public:
+ KJPEGFormat();
+
+ virtual ~KJPEGFormat();
+
+ virtual int decode(TQImage& img, TQImageConsumer* consumer,
+ const uchar* buffer, int length);
+private:
+
+ enum {
+ Init,
+ readHeader,
+ startDecompress,
+ decompressStarted,
+ consumeInput,
+ prepareOutputScan,
+ doOutputScan,
+ readDone,
+ invalid
+ } state;
+
+ // structs for the jpeglib
+ struct jpeg_decompress_struct cinfo;
+ struct tdehtml_error_mgr jerr;
+ struct tdehtml_jpeg_source_mgr jsrc;
+};
+
+
+// -----------------------------------------------------------------------------
+
+KJPEGFormat::KJPEGFormat()
+{
+ memset(&cinfo, 0, sizeof(cinfo));
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+ cinfo.err = jpeg_std_error(&jerr);
+ jerr.error_exit = tdehtml_error_exit;
+ cinfo.src = &jsrc;
+ state = Init;
+}
+
+
+KJPEGFormat::~KJPEGFormat()
+{
+ (void) jpeg_destroy_decompress(&cinfo);
+}
+
+/*
+ * return > 0 means "consumed x bytes, need more"
+ * return == 0 means "end of frame reached"
+ * return < 0 means "fatal error in image decoding, don't call me ever again"
+ */
+
+int KJPEGFormat::decode(TQImage& image, TQImageConsumer* consumer, const uchar* buffer, int length)
+{
+#ifdef JPEG_DEBUG
+ tqDebug("KJPEGFormat::decode(%08lx, %08lx, %08lx, %d)",
+ &image, consumer, buffer, length);
+#endif
+
+ if(jsrc.ateof) {
+#ifdef JPEG_DEBUG
+ tqDebug("ateof, eating");
+#endif
+ return length;
+ }
+
+
+ if(setjmp(jerr.setjmp_buffer))
+ {
+#ifdef JPEG_DEBUG
+ tqDebug("jump into state invalid");
+#endif
+ if(consumer)
+ consumer->end();
+
+ // this is fatal
+ return -1;
+ }
+
+ int consumed = kMin(length, max_buf - jsrc.valid_buffer_len);
+
+#ifdef BUFFER_DEBUG
+ tqDebug("consuming %d bytes", consumed);
+#endif
+
+ // filling buffer with the new data
+ memcpy(jsrc.buffer + jsrc.valid_buffer_len, buffer, consumed);
+ jsrc.valid_buffer_len += consumed;
+
+ if(jsrc.skip_input_bytes)
+ {
+#ifdef BUFFER_DEBUG
+ tqDebug("doing skipping");
+ tqDebug("valid_buffer_len %d", jsrc.valid_buffer_len);
+ tqDebug("skip_input_bytes %d", jsrc.skip_input_bytes);
+#endif
+ int skipbytes = kMin((size_t) jsrc.valid_buffer_len, jsrc.skip_input_bytes);
+
+ if(skipbytes < jsrc.valid_buffer_len)
+ memmove(jsrc.buffer, jsrc.buffer+skipbytes, jsrc.valid_buffer_len - skipbytes);
+
+ jsrc.valid_buffer_len -= skipbytes;
+ jsrc.skip_input_bytes -= skipbytes;
+
+ // still more bytes to skip
+ if(jsrc.skip_input_bytes) {
+ if(consumed <= 0) tqDebug("ERROR!!!");
+ return consumed;
+ }
+
+ }
+
+ cinfo.src->next_input_byte = (JOCTET *) jsrc.buffer;
+ cinfo.src->bytes_in_buffer = (size_t) jsrc.valid_buffer_len;
+
+#ifdef BUFFER_DEBUG
+ tqDebug("buffer contains %d bytes", jsrc.valid_buffer_len);
+#endif
+
+ if(state == Init)
+ {
+ if(jpeg_read_header(&cinfo, true) != JPEG_SUSPENDED) {
+ // do some simple memory requirements limitations
+ // as long as we use that stupid TQt stuff
+ int s = cinfo.image_width * cinfo.image_height;
+ if ( s > 16384 * 12388 )
+ cinfo.scale_denom = 8;
+ else if ( s > 8192 * 6144 )
+ cinfo.scale_denom = 4;
+ else if ( s > 4096 * 3072 )
+ cinfo.scale_denom = 2;
+
+ if ( consumer )
+ consumer->setSize(cinfo.image_width/cinfo.scale_denom,
+ cinfo.image_height/cinfo.scale_denom);
+
+ state = startDecompress;
+ }
+ }
+
+ if(state == startDecompress)
+ {
+ jsrc.do_progressive = jpeg_has_multiple_scans( &cinfo );
+
+#ifdef JPEG_DEBUG
+ tqDebug( "**** DOPROGRESSIVE: %d", jsrc.do_progressive );
+#endif
+ if ( jsrc.do_progressive )
+ cinfo.buffered_image = true;
+ else
+ cinfo.buffered_image = false;
+
+ // setup image sizes
+ jpeg_calc_output_dimensions( &cinfo );
+
+ if ( cinfo.jpeg_color_space == JCS_YCbCr )
+ cinfo.out_color_space = JCS_RGB;
+
+ cinfo.do_fancy_upsampling = true;
+ cinfo.do_block_smoothing = false;
+ cinfo.quantize_colors = false;
+
+ // false: IO suspension
+ if(jpeg_start_decompress(&cinfo)) {
+ if ( cinfo.output_components == 3 || cinfo.output_components == 4) {
+ image.create( cinfo.output_width, cinfo.output_height, 32 );
+ } else if ( cinfo.output_components == 1 ) {
+ image.create( cinfo.output_width, cinfo.output_height, 8, 256 );
+ for (int i=0; i<256; i++)
+ image.setColor(i, tqRgb(i,i,i));
+ }
+
+#ifdef JPEG_DEBUG
+ tqDebug("will create a picture %d/%d in size", cinfo.output_width, cinfo.output_height);
+#endif
+
+#ifdef JPEG_DEBUG
+ tqDebug("ok, going to decompressStarted");
+#endif
+
+ jsrc.decoder_timestamp.start();
+ state = jsrc.do_progressive ? decompressStarted : doOutputScan;
+ }
+ }
+
+again:
+
+ if(state == decompressStarted) {
+ state = (!jsrc.final_pass && jsrc.decoder_timestamp.elapsed() < max_consumingtime)
+ ? consumeInput : prepareOutputScan;
+ }
+
+ if(state == consumeInput)
+ {
+ int retval;
+
+ do {
+ retval = jpeg_consume_input(&cinfo);
+ } while (retval != JPEG_SUSPENDED && retval != JPEG_REACHED_EOI
+ && (retval != JPEG_REACHED_SOS || jsrc.decoder_timestamp.elapsed() < max_consumingtime));
+
+ if(jsrc.decoder_timestamp.elapsed() >= max_consumingtime ||
+ jsrc.final_pass ||
+ retval == JPEG_REACHED_EOI || retval == JPEG_REACHED_SOS)
+ state = prepareOutputScan;
+ }
+
+ if(state == prepareOutputScan)
+ {
+ if ( jpeg_start_output(&cinfo, cinfo.input_scan_number) )
+ state = doOutputScan;
+ }
+
+ if(state == doOutputScan)
+ {
+ if(image.isNull() || jsrc.decoding_done)
+ {
+#ifdef JPEG_DEBUG
+ tqDebug("complete in doOutputscan, eating..");
+#endif
+ return consumed;
+ }
+ uchar** lines = image.jumpTable();
+ int oldoutput_scanline = cinfo.output_scanline;
+
+ while(cinfo.output_scanline < cinfo.output_height &&
+ jpeg_read_scanlines(&cinfo, lines+cinfo.output_scanline, cinfo.output_height))
+ ; // here happens all the magic of decoding
+
+ int completed_scanlines = cinfo.output_scanline - oldoutput_scanline;
+#ifdef JPEG_DEBUG
+ tqDebug("completed now %d scanlines", completed_scanlines);
+#endif
+
+ if ( cinfo.output_components == 3 ) {
+ // Expand 24->32 bpp.
+ for (int j=oldoutput_scanline; j<oldoutput_scanline+completed_scanlines; j++) {
+ uchar *in = image.scanLine(j) + cinfo.output_width * 3;
+ TQRgb *out = (TQRgb*)image.scanLine(j);
+
+ for (uint i=cinfo.output_width; i--; ) {
+ in-=3;
+ out[i] = tqRgb(in[0], in[1], in[2]);
+ }
+ }
+ }
+
+ if(consumer && completed_scanlines)
+ {
+ TQRect r(0, oldoutput_scanline, cinfo.output_width, completed_scanlines);
+#ifdef JPEG_DEBUG
+ tqDebug("changing %d/%d %d/%d", r.x(), r.y(), r.width(), r.height());
+#endif
+ jsrc.change_rect |= r;
+
+ if ( jsrc.decoder_timestamp.elapsed() >= max_consumingtime ) {
+ if( !jsrc.old_change_rect.isEmpty()) {
+ consumer->changed(jsrc.old_change_rect);
+ jsrc.old_change_rect = TQRect();
+ }
+ consumer->changed(jsrc.change_rect);
+ jsrc.change_rect = TQRect();
+ jsrc.decoder_timestamp.restart();
+ }
+ }
+
+ if(cinfo.output_scanline >= cinfo.output_height)
+ {
+ if ( jsrc.do_progressive ) {
+ jpeg_finish_output(&cinfo);
+ jsrc.final_pass = jpeg_input_complete(&cinfo);
+ jsrc.decoding_done = jsrc.final_pass && cinfo.input_scan_number == cinfo.output_scan_number;
+ if ( !jsrc.decoding_done ) {
+ jsrc.old_change_rect |= jsrc.change_rect;
+ jsrc.change_rect = TQRect();
+ }
+ }
+ else
+ jsrc.decoding_done = true;
+
+#ifdef JPEG_DEBUG
+ tqDebug("one pass is completed, final_pass = %d, dec_done: %d, complete: %d",
+ jsrc.final_pass, jsrc.decoding_done, jpeg_input_complete(&cinfo));
+#endif
+ if(!jsrc.decoding_done)
+ {
+#ifdef JPEG_DEBUG
+ tqDebug("starting another one, input_scan_number is %d/%d", cinfo.input_scan_number,
+ cinfo.output_scan_number);
+#endif
+ jsrc.decoder_timestamp.restart();
+ state = decompressStarted;
+ // don't return until necessary!
+ goto again;
+ }
+ }
+
+ if(state == doOutputScan && jsrc.decoding_done) {
+#ifdef JPEG_DEBUG
+ tqDebug("input is complete, cleaning up, returning..");
+#endif
+ if ( consumer && !jsrc.change_rect.isEmpty() )
+ consumer->changed( jsrc.change_rect );
+
+ if(consumer)
+ consumer->end();
+
+ jsrc.ateof = true;
+
+ (void) jpeg_finish_decompress(&cinfo);
+ (void) jpeg_destroy_decompress(&cinfo);
+
+ state = readDone;
+
+ return 0;
+ }
+ }
+
+#ifdef BUFFER_DEBUG
+ tqDebug("valid_buffer_len is now %d", jsrc.valid_buffer_len);
+ tqDebug("bytes_in_buffer is now %d", jsrc.bytes_in_buffer);
+ tqDebug("consumed %d bytes", consumed);
+#endif
+ if(jsrc.bytes_in_buffer && jsrc.buffer != jsrc.next_input_byte)
+ memmove(jsrc.buffer, jsrc.next_input_byte, jsrc.bytes_in_buffer);
+ jsrc.valid_buffer_len = jsrc.bytes_in_buffer;
+ return consumed;
+}
+
+// -----------------------------------------------------------------------------
+// This is the factory that teaches TQt about progressive JPEG's
+
+TQImageFormat* tdehtml::KJPEGFormatType::decoderFor(const unsigned char* buffer, int length)
+{
+ if(length < 3) return 0;
+
+ if(buffer[0] == 0377 &&
+ buffer[1] == 0330 &&
+ buffer[2] == 0377)
+ return new KJPEGFormat;
+
+ return 0;
+}
+
+const char* tdehtml::KJPEGFormatType::formatName() const
+{
+ return "JPEG";
+}
+
+#else
+#ifdef __GNUC__
+#warning You don't seem to have libJPEG. jpeg support in tdehtml won't work
+#endif
+#endif // HAVE_LIBJPEG
+
+// -----------------------------------------------------------------------------
+
diff --git a/tdehtml/misc/loader_jpeg.h b/tdehtml/misc/loader_jpeg.h
new file mode 100644
index 000000000..568a29d44
--- /dev/null
+++ b/tdehtml/misc/loader_jpeg.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ This is a helper for progressive loading of JPEG's.
+*/
+
+#ifndef _tdehtml_loader_jpeg_h
+#define _tdehtml_loader_jpeg_h
+
+#include <tqasyncimageio.h>
+
+namespace tdehtml
+{
+ /**
+ * @internal
+ *
+ * An incremental loader factory for JPEG's.
+ */
+ class KJPEGFormatType : public TQImageFormatType
+ {
+ public:
+ TQImageFormat* decoderFor(const uchar* buffer, int length);
+ const char* formatName() const;
+ };
+
+}
+
+
+// -----------------------------------------------------------------------------
+
+#endif // _tdehtml_loader_jpeg_h
diff --git a/tdehtml/misc/makeattrs b/tdehtml/misc/makeattrs
new file mode 100644
index 000000000..935f350bd
--- /dev/null
+++ b/tdehtml/misc/makeattrs
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+#
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+# Copyright (C) 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.
+#
+#----------------------------------------------------------------------------
+#
+# KDE HTML Widget -- Script to generate tdehtmlattrs.c and tdehtmlattrs.h
+#
+open IN, "htmlattrs.in"
+ or die "Can't open in\n";
+open header, ">htmlattrs.h"
+ or die "Can't open header\n";
+open out, ">htmlattrs.gperf"
+ or die "Can't open out\n";
+
+print out "%{\n/* This file is automatically generated from
+#htmlattrs.in by makeattrs, do not edit */\n#include \"htmlattrs.h\"\n%}\n";
+print out "struct attrs {\n int name;\n int id;\n};\n%%\n";
+
+print header "/* This file is automatically generated from
+htmlattrs.in by makeattrs, do not edit */\n/* Copyright 1999 Lars Knoll */\n\n#ifndef HTML_ATTRS_H\n#define HTML_ATTRS_H\n\n#include \"dom/dom_string.h\"\n#include <kdemacros.h>\nusing namespace DOM;\n\n";
+
+my %amap = ();
+my $last_ci_attr = 0;
+$num = 0;
+while (<IN>) {
+ next if /^#/;
+ next if /^\s*$/;
+ /END_CI_ATTR/ and $last_ci_attr = $num and next;
+
+ chomp;
+ $attr = $_;
+ $num = $num + 1;
+
+ $up = uc($attr);
+ $amap{$up} = $num;
+ push(@a, $up);
+ $up =~ s/-/_/;
+ print out $attr . ", ATTR_" . $up . "\n";
+
+ print header "#define ATTR_" . $up . " " . $num . "\n";
+
+ }
+close(IN);
+
+print header "#define ATTR_LAST_ATTR $num\n";
+print header "#define ATTR_LAST_CI_ATTR $last_ci_attr\n";
+
+print out "%%\n";
+close out;
+
+print header "const char* getAttrName(unsigned short id) KDE_NO_EXPORT;\n";
+
+print header "\n#endif\n";
+close header;
+
+my $result = system("/bin/sh", "-c", "gperf -c -a -L 'ANSI-C' -P -G -D -E -C -o -t -k '*' -NfindAttr -Hhash_attr -Wwordlist_attr -Qspool_attr -s 2 htmlattrs.gperf > htmlattrs.c");
+if ($result) {
+ unlink "htmlattrs.c";
+ exit $result;
+}
+system("/bin/sh", "-c", 'perl -pi -e "s/\"\"}/\"\", 0}/g" htmlattrs.c');
+
+# read the hash mappings (is there a better way?)
+my %hmap = ();
+open(IN, "<htmlattrs.c");
+while(<IN>) {
+ if (/spool_attr_str(\d+), ATTR_([\w_]+)/) {
+ $hmap{$amap{$2}} = $1;
+ }
+}
+close(IN);
+
+open(OUT, ">>htmlattrs.c");
+print OUT "\n\nstatic const unsigned short attrList[] = {\n";
+print OUT " 65535,\n";
+
+while(defined ($line = shift @a))
+{
+ my $l = $line;
+ $l =~ y/-/_/;
+
+ die if !length($hmap{$amap{$l}});
+
+ print OUT " " .$hmap{$amap{$l}}.",\n";
+}
+print OUT " 65535\n};\n\n";
+print OUT "const char* KDE_NO_EXPORT getAttrName(unsigned short id)\n{\n";
+print OUT " if (!id || id > TOTAL_KEYWORDS) return \"\";\n";
+print OUT " return spool_attr + wordlist_attr[attrList[id]].name;\n";
+print OUT "}\n";
+
+
+
+
diff --git a/tdehtml/misc/maketags b/tdehtml/misc/maketags
new file mode 100644
index 000000000..a460cf8e4
--- /dev/null
+++ b/tdehtml/misc/maketags
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+# This file is part of the KDE libraries
+#
+# Copyright (C) 1998 Waldo Bastian (bastian@kde.org)
+# 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.
+#
+#----------------------------------------------------------------------------
+#
+# KDE HTML Widget -- Script to generate htmltags.c and htmltags.h
+#
+open IN, "htmltags.in"
+ or die "Can't open in\n";
+open header, ">htmltags.h"
+ or die "Can't open header\n";
+open out, ">htmltags.gperf"
+ or die "Can't open out\n";
+
+print out "%{\n/* This file is automatically generated from htmltags.in by maketags, do not edit */\n/* Copyright 1999 Lars Knoll */\n#include \"htmltags.h\"\n%}\n";
+print out "struct tags {\n int name;\n int id;\n};\n%%\n";
+
+print header <<EOF;
+/* This file is automatically generated from htmltags.in by maketags, do not edit */
+/* Copyright 1999 Lars Knoll */
+
+#ifndef KHTML_TAGS_H
+#define KHTML_TAGS_H
+
+#include "dom/dom_string.h"
+#include <kglobal.h>
+
+KDE_NO_EXPORT const char* getTagName(unsigned short id);
+
+EOF
+
+my @tags = ();
+$num = 0;
+while (<IN>) {
+ chomp;
+ $attr = $_;
+ $num = $num + 1;
+ push(@tags, $attr);
+ push(@a, " \"$attr\",");
+ push(@b, " \"/$attr\",");
+ $up = uc($attr);
+ $up =~ s/-/_/;
+ print out $attr . ", ID_" . $up . "\n";
+ print header "#define ID_" . $up . " " . $num . "\n";
+}
+print out "anchor, ID_A\n";
+print out "image, ID_IMG\n";
+print out "listing, ID_PRE\n";
+$num = $num+1;
+print header "#define ID_TEXT $num\n";
+$num = $num+1;
+print header "#define ID_COMMENT $num\n";
+print header "#define ID_CLOSE_TAG $num\n";
+print header "#define ID_LAST_TAG $num\n";
+
+print out "%%\n";
+close out;
+print header "\n#endif\n";
+close header;
+
+my $result = system("/bin/sh", "-c", "gperf -a -L 'ANSI-C' -P -D -E -C -l -o -t -k '*' -NfindTag -Hhash_tag -Wwordlist_tag -Qspool_Tag htmltags.gperf > htmltags.c");
+if ($result) {
+ unlink "htmltags.c";
+ exit $result;
+}
+
+open(OUT, ">>htmltags.c");
+print OUT "\n\nstatic const char tagStable[] = {\n \"";
+push (@tags, "text");
+push (@tags, "comment");
+my %stable = ();
+my $l = 1;
+my $line = 5;
+foreach my $k(@tags) {
+ if ($line > 65) {
+ print OUT "\"\n \"";
+ $line = 5;
+ }
+ #print OUT " \"\\000/$k\"\n";
+ print OUT "\\000/$k";
+ $stable{$k} = $l;
+ $l += length($k) + 2;
+ $line += length($k) + 5;
+}
+print OUT "\\000\"\n};\n";
+
+print OUT "\nstatic const unsigned short tagSList[] = {\n";
+print OUT " 0,\n";
+my $c = 0;
+foreach my $line (@tags)
+{
+ printf OUT "\n " if (($c % 12) == 0);
+ printf OUT "%4d,", ($stable{$line}+1) ;
+ ++$c;
+}
+foreach my $line (@tags)
+{
+ printf OUT "\n " if (($c % 12) == 0);
+ printf OUT "%4d,", ($stable{$line}) ;
+ ++$c;
+}
+print OUT " 0\n};\n\n";
+print OUT "const char* KDE_NO_EXPORT getTagName(unsigned short id)\n{\n";
+print OUT " if(id > ID_CLOSE_TAG*2) id = ID_CLOSE_TAG+1;\n";
+print OUT " return &tagStable[tagSList[id]];\n}\n";
+
diff --git a/tdehtml/misc/multimap.h b/tdehtml/misc/multimap.h
new file mode 100644
index 000000000..125e8e07d
--- /dev/null
+++ b/tdehtml/misc/multimap.h
@@ -0,0 +1,345 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006 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.
+ *
+ */
+
+#ifndef _MultiMap_h_
+#define _MultiMap_h_
+
+#include <tqptrdict.h>
+#include <tqptrlist.h>
+#include <assert.h>
+#include <stdlib.h>
+
+template<class T> class MultiMapPtrList;
+
+// KMultiMap is an implementaition of a Map with multiple entries per key.
+// It is originally designed to work like a shell for TQPtrDict<TQPtrList>, but
+// TQPtrList have been replaced with a much faster hash set.
+template<class T>
+class KMultiMap {
+public:
+ KMultiMap() : dict(257) { dict.setAutoDelete(true); }
+ ~KMultiMap() {};
+
+ typedef MultiMapPtrList<T> List;
+
+ void append(void* key, T* element) {
+ List *list = dict.find(key);
+ if (!list){
+ list = new List(8);
+ dict.insert(key, list);
+ }
+ list->append(element);
+ }
+ void remove(void* key, T* element) {
+ List *list = dict.find(key);
+ if (list) {
+ list->remove(element);
+ if (list->isEmpty()) dict.remove(key);
+ }
+ }
+ void remove(void* key) {
+ dict.remove(key);
+ }
+ List* find(void* key) {
+ return dict.find(key);
+ }
+private:
+ TQPtrDict<List> dict;
+
+};
+
+static inline unsigned int stupidHash(void* ptr)
+{
+ unsigned long val = (unsigned long)ptr;
+ // remove alignment and multiply by a prime unlikely to be a factor of size
+ val = (val >> 4) * 1237;
+ return val;
+}
+
+#define START_PTRLIST_SIZE 4
+#define MAX_PTRLIST_SIZE 27
+
+class PtrListEntry {
+public:
+ PtrListEntry(unsigned int log_size) : count(0), log_size(log_size), search(log_size), next(0) {
+// entry = new T* [size];
+ assert(log_size < MAX_PTRLIST_SIZE);
+ entry = (void**)calloc ((1<<log_size), sizeof(void*));
+ }
+ ~PtrListEntry() {
+// delete[] entry;
+ free(entry);
+ }
+ bool insert(void* e) {
+ unsigned int t_size = size();
+ if (count == t_size) return false;
+ unsigned int hash = stupidHash(e);
+ void** firstFree = 0;
+ // Only let elements be placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (t_size-1); // modulo size
+ // We need check to all hashes in 'search' to garuantee uniqueness
+ if (entry[i] == 0) {
+ if (!firstFree)
+ firstFree = entry + i;
+ } else
+ if (entry[i] == e)
+ return true;
+ }
+ if (firstFree) {
+ *firstFree = e;
+ count++;
+ return true;
+ }
+ // We had more than 'search' collisions
+ if (count < (t_size/3)*2) {
+ // only 2/3 full => increase search
+ unsigned int s = search *2;
+ if (s >= t_size) s = t_size;
+ search = s;
+ return insert(e);
+ }
+ return false;
+ }
+ // Insert another smaller set into this one
+ // Is only garuantied to succede when this PtrList is new
+ void insert(PtrListEntry* listEntry) {
+ assert(size() >= listEntry->count * 2);
+ unsigned int old_size = 1U << listEntry->log_size;
+ for(unsigned int i = 0; i < old_size; i++) {
+ bool s = true;
+ void *e = listEntry->entry[i];
+ if (e) s = insert(e);
+ assert(s);
+ }
+ }
+ bool remove(void* e) {
+ if (count == 0) return false;
+ unsigned int size = (1U<<log_size);
+ unsigned int hash = stupidHash(e);
+ // Elements are at most placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (size-1); // modulo size
+ if (entry[i] == e) {
+ entry[i] = 0;
+ count--;
+ return true;
+ }
+ }
+ return false;
+ }
+ bool contains(void* e) {
+ if (count == 0) return false;
+ unsigned int t_size = size();
+ unsigned int hash = stupidHash(e);
+ // Elements are at most placed 'search' spots from their hash
+ for(unsigned int j=0; j<search; j++) {
+ unsigned int i = (hash + j) & (t_size-1); // modulo size
+ if (entry[i] == e) return true;
+ }
+ return false;
+ }
+ void* at(unsigned int i) const {
+ assert (i < (1U<<log_size));
+ return entry[i];
+ }
+ bool isEmpty() const {
+ return count == 0;
+ }
+ bool isFull() const {
+ return count == size();
+ }
+ unsigned int size() const {
+ return (1U << log_size);
+ }
+
+ unsigned int count;
+ const unsigned short log_size;
+ unsigned short search;
+ PtrListEntry *next;
+ void** entry;
+};
+
+// An unsorted and unique PtrList that is implement as a linked list of hash-sets
+// Optimized for fast insert and fast lookup
+template<class T>
+class MultiMapPtrList {
+public:
+ MultiMapPtrList(unsigned int init_size= 16) : m_first(0), m_current(0), m_pos(0) {
+ assert(init_size > 0);
+ unsigned int s = init_size - 1;
+ unsigned int log_size = 0;
+ while (s > 0) {
+ log_size++;
+ s = s >> 1;
+ }
+ m_first = new PtrListEntry(log_size);
+ }
+ MultiMapPtrList(const MultiMapPtrList& ptrList) : m_first(0), m_current(0), m_pos(0) {
+ unsigned int t_count = ptrList.count();
+ unsigned int log_size = 0;
+ while (t_count > 0) {
+ log_size++;
+ t_count = t_count >> 1;
+ }
+ // At least as large as the largest ptrListEntry in the original
+ if (t_count < ptrList.m_first->log_size) log_size = ptrList.m_first->log_size;
+ m_first = new PtrListEntry(log_size);
+
+ PtrListEntry *t_current = ptrList.m_first;
+ while (t_current) {
+ unsigned int t_size = t_current->size();
+ for(unsigned int i=0; i < t_size; i++) {
+ void* e = t_current->at(i);
+ if (e != 0) {
+ bool t = m_first->insert(e);
+ if (!t) {
+ // Make a new, but keep the size
+ PtrListEntry *t_new = new PtrListEntry(log_size);
+ t_new->insert(e);
+ t_new->next = m_first;
+ m_first = t_new;
+ }
+ }
+ }
+ t_current = t_current->next;
+ }
+ }
+ ~MultiMapPtrList() {
+ PtrListEntry *t_next, *t_current = m_first;
+ while (t_current) {
+ t_next = t_current->next;
+ delete t_current;
+ t_current = t_next;
+ }
+ }
+ void append(T* e) {
+ PtrListEntry *t_last = 0, *t_current = m_first;
+ int count = 0;
+ while (t_current) {
+ if (t_current->insert(e)) return;
+ t_last = t_current;
+ t_current = t_current->next;
+ count++;
+ }
+ // Create new hash-set
+ unsigned int newsize = m_first->log_size+1;
+ if (newsize > MAX_PTRLIST_SIZE) newsize = MAX_PTRLIST_SIZE;
+ t_current = new PtrListEntry(newsize);
+ bool t = t_current->insert(e);
+ assert(t);
+ // Prepend it to the list, for insert effeciency
+ t_current->next = m_first;
+ m_first = t_current;
+ // ### rehash some of the smaller sets
+ /*
+ if (count > 4) {
+ // rehash the last in the new
+ t_current->insert(t_last);
+ }*/
+ }
+ void remove(T* e) {
+ PtrListEntry *t_next, *t_last = 0, *t_current = m_first;
+ // Remove has to check every PtrEntry.
+ while (t_current) {
+ t_next = t_current->next;
+ if (t_current->remove(e) && t_current->isEmpty()) {
+ if (t_last) {
+ t_last->next = t_current->next;
+ }
+ else {
+ assert (m_first == t_current);
+ m_first = t_current->next;
+ }
+ delete t_current;
+ } else {
+ t_last = t_current;
+ }
+ t_current = t_next;
+ }
+ }
+ bool contains(T* e) {
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ if (t_current->contains(e)) return true;
+ t_current = t_current->next;
+ }
+ return false;
+ }
+ bool isEmpty() {
+ if (!m_first) return true;
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ if (!t_current->isEmpty()) return false;
+ t_current = t_current->next;
+ }
+ return true;
+ }
+ unsigned int count() const {
+ unsigned int t_count = 0;
+ PtrListEntry *t_current = m_first;
+ while (t_current) {
+ t_count += t_current->count;
+ t_current = t_current->next;
+ }
+ return t_count;
+ }
+// Iterator functions:
+ T* first() {
+ m_current = m_first;
+ m_pos = 0;
+ // skip holes
+ if (m_current && !m_current->at(m_pos))
+ return next();
+ else
+ return current();
+ }
+ T* current() {
+ if (!m_current)
+ return (T*)0;
+ else
+ return (T*)m_current->at(m_pos);
+ }
+ T* next() {
+ if (!m_current) return (T*)0;
+ m_pos++;
+ if (m_pos >= m_current->size()) {
+ m_current = m_current->next;
+ m_pos = 0;
+ }
+ // skip holes
+ if (m_current && !m_current->at(m_pos))
+ return next();
+ else
+ return current();
+ }
+private:
+ PtrListEntry *m_first;
+// iteration:
+ PtrListEntry *m_current;
+ unsigned int m_pos;
+};
+
+#undef START_PTRLIST_SIZE
+#undef MAX_PTRLIST_SIZE
+
+#endif
diff --git a/tdehtml/misc/seed.h b/tdehtml/misc/seed.h
new file mode 100644
index 000000000..3041d1d95
--- /dev/null
+++ b/tdehtml/misc/seed.h
@@ -0,0 +1,46 @@
+/*
+ * A simple hash seed chooser.
+ *
+ * Copyright (C) 2003 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.
+ *
+ */
+
+#ifndef html_seed_h
+#define html_seed_h
+
+#define tdehtml_MaxSeed 47963
+
+namespace tdehtml {
+
+static const int primes_t[] =
+{
+ 31, 61, 107, 233, 353, 541,
+ 821, 1237, 1861, 2797, 4201, 6311,
+ 9467, 14207, 21313, 31973, 47963, 0
+};
+
+static inline int nextSeed(int curSize) {
+ for (int i = 0 ; primes_t[i] ; i++)
+ if (primes_t[i] > curSize)
+ return primes_t[i];
+ return curSize;
+}
+
+} // namespace
+
+#endif
diff --git a/tdehtml/misc/shared.h b/tdehtml/misc/shared.h
new file mode 100644
index 000000000..d99b327c6
--- /dev/null
+++ b/tdehtml/misc/shared.h
@@ -0,0 +1,227 @@
+/*
+ This file is part of the DOM implementation for KDE.
+ Copyright (C) 2005, 2006 Apple Computer, Inc.
+ Copyright (C) 2002 Lars Knoll
+
+ 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 SHARED_H
+#define SHARED_H
+
+namespace tdehtml {
+
+template<class type> class Shared
+{
+public:
+ Shared() { _ref=0; /*counter++;*/ }
+ ~Shared() { /*counter--;*/ }
+
+ void ref() { _ref++; }
+ void deref() {
+ if(_ref) _ref--;
+ if(!_ref)
+ delete static_cast<type *>(this);
+ }
+ bool hasOneRef() { //kdDebug(300) << "ref=" << _ref << endl;
+ return _ref==1; }
+
+ int refCount() const { return _ref; }
+// static int counter;
+protected:
+ unsigned int _ref;
+};
+
+template<class type> class TreeShared
+{
+public:
+ TreeShared() { _ref = 0; m_parent = 0; /*counter++;*/ }
+ TreeShared( type *parent ) { _ref=0; m_parent = parent; /*counter++;*/ }
+ ~TreeShared() { /*counter--;*/ }
+
+ virtual void removedLastRef() { delete static_cast<type*>(this); }
+
+ void ref() { _ref++; }
+ void deref() {
+ if(_ref) _ref--;
+ if(!_ref && !m_parent) {
+ removedLastRef();
+ }
+ }
+ bool hasOneRef() { //kdDebug(300) << "ref=" << _ref << endl;
+ return _ref==1; }
+
+ int refCount() const { return _ref; }
+// static int counter;
+
+ void setParent(type *parent) { m_parent = parent; }
+ type *parent() const { return m_parent; }
+private:
+ unsigned int _ref;
+protected:
+ type *m_parent;
+};
+
+template <class T> class SharedPtr;
+
+template <class T> bool operator==(const SharedPtr<T> &a, const SharedPtr<T> &b);
+template <class T> bool operator==(const SharedPtr<T> &a, const T *b);
+template <class T> bool operator==(const T *a, const SharedPtr<T> &b);
+
+template <class T> class SharedPtr
+{
+public:
+ SharedPtr() : m_ptr(0) {}
+ explicit SharedPtr(T *ptr) : m_ptr(ptr) { if (m_ptr) m_ptr->ref(); }
+ SharedPtr(const SharedPtr &o) : m_ptr(o.m_ptr) { if (m_ptr) m_ptr->ref(); }
+ ~SharedPtr() { if (m_ptr) m_ptr->deref(); }
+
+ bool isNull() const { return m_ptr == 0; }
+ bool notNull() const { return m_ptr != 0; }
+
+ void reset() { if (m_ptr) m_ptr->deref(); m_ptr = 0; }
+ void reset(T *o) { if (o) o->ref(); if (m_ptr) m_ptr->deref(); m_ptr = o; }
+
+ T * get() const { return m_ptr; }
+ T &operator*() const { return *m_ptr; }
+ T *operator->() const { return m_ptr; }
+
+ bool operator!() const { return m_ptr == 0; }
+
+ template <class C> friend bool operator==(const SharedPtr<C> &a, const SharedPtr<C> &b);
+ template <class C> friend bool operator==(const SharedPtr<C> &a, const C *b);
+ template <class C> friend bool operator==(const C *a, const SharedPtr<C> &b);
+
+ SharedPtr &operator=(const SharedPtr &);
+
+private:
+ T* m_ptr;
+};
+
+template <class T> SharedPtr<T> &SharedPtr<T>::operator=(const SharedPtr<T> &o)
+{
+ if (o.m_ptr)
+ o.m_ptr->ref();
+ if (m_ptr)
+ m_ptr->deref();
+ m_ptr = o.m_ptr;
+ return *this;
+}
+
+template <class T> inline bool operator==(const SharedPtr<T> &a, const SharedPtr<T> &b) { return a.m_ptr == b.m_ptr; }
+template <class T> inline bool operator==(const SharedPtr<T> &a, const T *b) { return a.m_ptr == b; }
+template <class T> inline bool operator==(const T *a, const SharedPtr<T> &b) { return a == b.m_ptr; }
+
+template <class T> inline bool operator!=(const SharedPtr<T> &a, const SharedPtr<T> &b) { return !(a==b); }
+template <class T> inline bool operator!=(const SharedPtr<T> &a, const T *b) { return !(a == b); }
+template <class T> inline bool operator!=(const T *a, const SharedPtr<T> &b) { return !(a == b); }
+
+template <class T, class U> inline SharedPtr<T> static_pointer_cast(const SharedPtr<U> &p) { return SharedPtr<T>(static_cast<T *>(p.get())); }
+template <class T, class U> inline SharedPtr<T> const_pointer_cast(const SharedPtr<U> &p) { return SharedPtr<T>(const_cast<T *>(p.get())); }
+
+//A special pointer for nodes keeping track of the document,
+//which helps distinguish back links from them to it, in order to break
+//cycles
+template <class T> class DocPtr {
+public:
+ DocPtr() : m_ptr(0) {}
+ DocPtr(T *ptr) : m_ptr(ptr) { if (ptr) ptr->selfOnlyRef(); }
+ DocPtr(const DocPtr &o) : m_ptr(o.m_ptr) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); }
+ ~DocPtr() { if (T *ptr = m_ptr) ptr->selfOnlyDeref(); }
+
+ template <class U> DocPtr(const DocPtr<U> &o) : m_ptr(o.get()) { if (T *ptr = m_ptr) ptr->selfOnlyRef(); }
+
+ void resetSkippingRef(T *o) { m_ptr = o; }
+
+ T *get() const { return m_ptr; }
+
+ T &operator*() const { return *m_ptr; }
+ T *operator->() const { return m_ptr; }
+
+ bool operator!() const { return !m_ptr; }
+
+ // this type conversion operator allows implicit conversion to
+ // bool but not to other integer types
+
+ typedef T * (DocPtr::*UnspecifiedBoolType)() const;
+ operator UnspecifiedBoolType() const
+ {
+ return m_ptr ? &DocPtr::get : 0;
+ }
+
+ DocPtr &operator=(const DocPtr &);
+ DocPtr &operator=(T *);
+
+ private:
+ T *m_ptr;
+};
+
+template <class T> DocPtr<T> &DocPtr<T>::operator=(const DocPtr<T> &o)
+{
+ T *optr = o.m_ptr;
+ if (optr)
+ optr->selfOnlyRef();
+ if (T *ptr = m_ptr)
+ ptr->selfOnlyDeref();
+ m_ptr = optr;
+ return *this;
+}
+
+template <class T> inline DocPtr<T> &DocPtr<T>::operator=(T *optr)
+{
+ if (optr)
+ optr->selfOnlyRef();
+ if (T *ptr = m_ptr)
+ ptr->selfOnlyDeref();
+ m_ptr = optr;
+ return *this;
+}
+
+template <class T> inline bool operator==(const DocPtr<T> &a, const DocPtr<T> &b)
+{
+ return a.get() == b.get();
+}
+
+template <class T> inline bool operator==(const DocPtr<T> &a, const T *b)
+{
+ return a.get() == b;
+}
+
+template <class T> inline bool operator==(const T *a, const DocPtr<T> &b)
+{
+ return a == b.get();
+}
+
+template <class T> inline bool operator!=(const DocPtr<T> &a, const DocPtr<T> &b)
+{
+ return a.get() != b.get();
+}
+
+template <class T> inline bool operator!=(const DocPtr<T> &a, const T *b)
+{
+ return a.get() != b;
+}
+
+template <class T> inline bool operator!=(const T *a, const DocPtr<T> &b)
+{
+ return a != b.get();
+}
+
+
+} // namespace
+
+#endif
diff --git a/tdehtml/misc/stringit.cpp b/tdehtml/misc/stringit.cpp
new file mode 100644
index 000000000..f4bea427f
--- /dev/null
+++ b/tdehtml/misc/stringit.cpp
@@ -0,0 +1,138 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 2004 Apple Computer
+
+ 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 "stringit.h"
+
+namespace tdehtml {
+
+uint TokenizerString::length() const
+{
+ uint length = m_currentString.m_length;
+ if (!m_pushedChar1.isNull()) {
+ ++length;
+ if (!m_pushedChar2.isNull())
+ ++length;
+ }
+ if (m_composite) {
+ TQValueListConstIterator<TokenizerSubstring> i = m_substrings.begin();
+ TQValueListConstIterator<TokenizerSubstring> e = m_substrings.end();
+ for (; i != e; ++i)
+ length += (*i).m_length;
+ }
+ return length;
+}
+
+void TokenizerString::clear()
+{
+ m_pushedChar1 = 0;
+ m_pushedChar2 = 0;
+ m_currentChar = 0;
+ m_currentString.clear();
+ m_substrings.clear();
+ m_lines = 0;
+ m_composite = false;
+}
+
+void TokenizerString::append(const TokenizerSubstring &s)
+{
+ if (s.m_length) {
+ if (!m_currentString.m_length) {
+ m_currentString = s;
+ } else {
+ m_substrings.append(s);
+ m_composite = true;
+ }
+ }
+}
+
+void TokenizerString::prepend(const TokenizerSubstring &s)
+{
+ assert(!escaped());
+ if (s.m_length) {
+ if (!m_currentString.m_length)
+ m_currentString = s;
+ else {
+ // Shift our m_currentString into our list.
+ m_substrings.prepend(m_currentString);
+ m_currentString = s;
+ m_composite = true;
+ }
+ }
+}
+
+void TokenizerString::append(const TokenizerString &s)
+{
+ assert(!s.escaped());
+ append(s.m_currentString);
+ if (s.m_composite) {
+ TQValueListConstIterator<TokenizerSubstring> i = s.m_substrings.begin();
+ TQValueListConstIterator<TokenizerSubstring> e = s.m_substrings.end();
+ for (; i != e; ++i)
+ append(*i);
+ }
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+}
+
+void TokenizerString::prepend(const TokenizerString &s)
+{
+ assert(!escaped());
+ assert(!s.escaped());
+ if (s.m_composite) {
+ TQValueListConstIterator<TokenizerSubstring> i = s.m_substrings.fromLast();
+ TQValueListConstIterator<TokenizerSubstring> e = s.m_substrings.end();
+ for (; i != e; --i)
+ prepend(*i);
+ }
+ prepend(s.m_currentString);
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+}
+
+void TokenizerString::advanceSubstring()
+{
+ if (m_composite) {
+ m_currentString = m_substrings.first();
+ m_substrings.remove(m_substrings.begin());
+ if (m_substrings.isEmpty())
+ m_composite = false;
+ } else {
+ m_currentString.clear();
+ }
+}
+
+TQString TokenizerString::toString() const
+{
+ TQString result;
+ if (!m_pushedChar1.isNull()) {
+ result.append(m_pushedChar1);
+ if (!m_pushedChar2.isNull())
+ result.append(m_pushedChar2);
+ }
+ m_currentString.appendTo(result);
+ if (m_composite) {
+ TQValueListConstIterator<TokenizerSubstring> i = m_substrings.begin();
+ TQValueListConstIterator<TokenizerSubstring> e = m_substrings.end();
+ for (; i != e; ++i)
+ (*i).appendTo(result);
+ }
+ return result;
+}
+
+}
diff --git a/tdehtml/misc/stringit.h b/tdehtml/misc/stringit.h
new file mode 100644
index 000000000..a93a59e4d
--- /dev/null
+++ b/tdehtml/misc/stringit.h
@@ -0,0 +1,203 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2004 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 -- String class
+
+#ifndef KHTMLSTRING_H
+#define KHTMLSTRING_H
+
+#include "dom/dom_string.h"
+
+#include <tqstring.h>
+#include <tqvaluelist.h>
+
+#include <assert.h>
+
+using namespace DOM;
+
+namespace tdehtml
+{
+
+class DOMStringIt
+{
+public:
+ DOMStringIt()
+ { s = 0, l = 0; lines = 0; }
+ DOMStringIt(TQChar *str, uint len)
+ { s = str, l = len; lines = 0; }
+ DOMStringIt(const TQString &str)
+ { s = str.unicode(); l = str.length(); lines = 0; }
+
+ DOMStringIt *operator++()
+ {
+ if(!pushedChar.isNull())
+ pushedChar=0;
+ else if(l > 0 ) {
+ if (*s == '\n')
+ lines++;
+ s++, l--;
+ }
+ return this;
+ }
+public:
+ void push(const TQChar& c) { /* assert(pushedChar.isNull());*/ pushedChar = c; }
+
+ const TQChar& operator*() const { return pushedChar.isNull() ? *s : pushedChar; }
+ const TQChar* operator->() const { return pushedChar.isNull() ? s : &pushedChar; }
+
+ bool escaped() const { return !pushedChar.isNull(); }
+ uint length() const { return l+(!pushedChar.isNull()); }
+
+ const TQChar *current() const { return pushedChar.isNull() ? s : &pushedChar; }
+ int lineCount() const { return lines; }
+
+protected:
+ TQChar pushedChar;
+ const TQChar *s;
+ int l;
+ int lines;
+};
+
+class TokenizerString;
+
+class TokenizerSubstring
+{
+ friend class TokenizerString;
+public:
+ TokenizerSubstring() : m_length(0), m_current(0) {}
+ TokenizerSubstring(const TQString &str) : m_string(str), m_length(str.length()), m_current(m_length == 0 ? 0 : str.unicode()) {}
+ TokenizerSubstring(const TQChar *str, int length) : m_length(length), m_current(length == 0 ? 0 : str) {}
+
+ void clear() { m_length = 0; m_current = 0; }
+
+ void appendTo(TQString &str) const {
+ if (m_string.unicode() == m_current) {
+ if (str.isEmpty())
+ str = m_string;
+ else
+ str.append(m_string);
+ } else {
+ str.insert(str.length(), m_current, m_length);
+ }
+ }
+private:
+ TQString m_string;
+ int m_length;
+ const TQChar *m_current;
+};
+
+class TokenizerString
+{
+
+public:
+ TokenizerString() : m_currentChar(0), m_lines(0), m_composite(false) {}
+ TokenizerString(const TQChar *str, int length) : m_currentString(str, length), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
+ TokenizerString(const TQString &str) : m_currentString(str), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
+ TokenizerString(const TokenizerString &o) : m_pushedChar1(o.m_pushedChar1), m_pushedChar2(o.m_pushedChar2),
+ m_currentString(o.m_currentString), m_substrings(o.m_substrings),
+ m_lines(o.m_lines), m_composite(o.m_composite) {
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+ }
+
+ void clear();
+
+ void append(const TokenizerString &);
+ void prepend(const TokenizerString &);
+
+ void push(TQChar c) {
+ if (m_pushedChar1.isNull()) {
+ m_pushedChar1 = c;
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
+ } else {
+ assert(m_pushedChar2.isNull());
+ m_pushedChar2 = c;
+ }
+ }
+
+ bool isEmpty() const { return !current(); }
+ uint length() const;
+
+ void advance() {
+ if (!m_pushedChar1.isNull()) {
+ m_pushedChar1 = m_pushedChar2;
+ m_pushedChar2 = 0;
+ } else if (m_currentString.m_current) {
+ m_lines += *m_currentString.m_current++ == '\n';
+ if (--m_currentString.m_length == 0)
+ advanceSubstring();
+ }
+ m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current: &m_pushedChar1;
+ }
+ uint count() const { return m_substrings.count(); }
+
+ bool escaped() const { return !m_pushedChar1.isNull(); }
+
+ int lineCount() const { return m_lines; }
+ void resetLineCount() { m_lines = 0; }
+
+ TQString toString() const;
+
+ void operator++() { advance(); }
+ const TQChar &operator*() const { return *current(); }
+ const TQChar *operator->() const { return current(); }
+
+private:
+ void append(const TokenizerSubstring &);
+ void prepend(const TokenizerSubstring &);
+
+ void advanceSubstring();
+ const TQChar *current() const { return m_currentChar; }
+
+ TQChar m_pushedChar1;
+ TQChar m_pushedChar2;
+ TokenizerSubstring m_currentString;
+ const TQChar *m_currentChar;
+ TQValueList<TokenizerSubstring> m_substrings;
+ int m_lines;
+ bool m_composite;
+
+};
+
+
+class TokenizerQueue : public TQValueList<TokenizerString>
+{
+
+public:
+ TokenizerQueue() {}
+ ~TokenizerQueue() {}
+ void push( const TokenizerString &t ) { prepend(t); }
+ TokenizerString pop() {
+ if (isEmpty())
+ return TokenizerString();
+ TokenizerString t(first());
+ remove( begin() );
+ return t;
+ }
+ TokenizerString& top() { return first(); }
+ TokenizerString& bottom() { return last(); }
+};
+
+}
+
+#endif
+
diff --git a/tdehtml/misc/tdehtmllayout.h b/tdehtml/misc/tdehtmllayout.h
new file mode 100644
index 000000000..524cc5e74
--- /dev/null
+++ b/tdehtml/misc/tdehtmllayout.h
@@ -0,0 +1,112 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (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.
+
+ This widget holds some useful definitions needed for layouting Elements
+*/
+#ifndef HTML_LAYOUT_H
+#define HTML_LAYOUT_H
+
+
+/*
+ * this namespace contains definitions for various types needed for
+ * layouting.
+ */
+namespace tdehtml
+{
+
+ const int UNDEFINED = -1;
+
+ // alignment
+ enum VAlign { VNone=0, Bottom, VCenter, Top, Baseline };
+ enum HAlign { HDefault, Left, HCenter, Right, HNone = 0 };
+
+ /*
+ * %multiLength and %Length
+ */
+ enum LengthType { Variable = 0, Relative, Percent, Fixed, Static };
+ struct Length
+ {
+ Length() : _length(0) {}
+ Length(LengthType t) { _length = 0; l.type = t; }
+ Length(int v, LengthType t, bool q=false)
+ { _length= 0; l.value = v; l.type = t; l.quirk = q; }
+ bool operator==(const Length& o) const
+ { return _length == o._length; }
+ bool operator!=(const Length& o) const
+ { return _length != o._length; }
+ void setValue(LengthType t, int v) {
+ _length = 0; l.value = v; l.type = t; l.quirk = false;
+ }
+ /*
+ * works only for Fixed and Percent, returns -1 otherwise
+ */
+ int width(int maxWidth) const
+ {
+ switch(l.type)
+ {
+ case Fixed:
+ return l.value;
+ case Percent:
+ return maxWidth*l.value/100;
+ case Variable:
+ return maxWidth;
+ default:
+ return -1;
+ }
+ }
+ /*
+ * returns the minimum width value which could work...
+ */
+ int minWidth(int maxWidth) const
+ {
+ switch(l.type)
+ {
+ case Fixed:
+ return l.value;
+ case Percent:
+ return maxWidth*l.value/100;
+ case Variable:
+ default:
+ return 0;
+ }
+ }
+ bool isVariable() const { return ((LengthType) l.type == Variable); }
+ bool isRelative() const { return ((LengthType) l.type == Relative); }
+ bool isPercent() const { return ((LengthType ) l.type == Percent); }
+ bool isFixed() const { return ((LengthType) l.type == Fixed); }
+ bool isStatic() const { return ((LengthType) l.type == Static); }
+ bool isQuirk() const { return l.quirk; }
+
+ int value() const { return l.value; }
+ LengthType type() const { return (LengthType) l.type; }
+
+ union {
+ struct {
+ signed int value : 28;
+ unsigned type : 3;
+ bool quirk : 1;
+ } l;
+ TQ_UINT32 _length;
+ };
+ };
+
+}
+
+#endif
diff --git a/tdehtml/pics/CMakeLists.txt b/tdehtml/pics/CMakeLists.txt
new file mode 100644
index 000000000..17390707c
--- /dev/null
+++ b/tdehtml/pics/CMakeLists.txt
@@ -0,0 +1,20 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+##### icons #####################################
+
+tde_install_icons(
+ bug images_display wallet_open
+ DESTINATION ${DATA_INSTALL_DIR}/tdehtml/icons )
+
+tde_install_icons(
+ dbgnext dbgrun dbgrunto dbgstep
+)
diff --git a/tdehtml/pics/Makefile.am b/tdehtml/pics/Makefile.am
new file mode 100644
index 000000000..7477bfd51
--- /dev/null
+++ b/tdehtml/pics/Makefile.am
@@ -0,0 +1,10 @@
+tdehtmliconsdir = $(kde_datadir)/tdehtml/icons
+tdehtmlicons_ICON = bug \
+ images_display \
+ wallet_open
+
+# Install globally so they show up in when JS debugger is run in Konqueror
+KDE_ICON = dbgnext \
+ dbgrun \
+ dbgrunto \
+ dbgstep
diff --git a/tdehtml/pics/cr128-action-bug.png b/tdehtml/pics/cr128-action-bug.png
new file mode 100644
index 000000000..a39081d9a
--- /dev/null
+++ b/tdehtml/pics/cr128-action-bug.png
Binary files differ
diff --git a/tdehtml/pics/cr16-action-bug.png b/tdehtml/pics/cr16-action-bug.png
new file mode 100644
index 000000000..827d5f8e6
--- /dev/null
+++ b/tdehtml/pics/cr16-action-bug.png
Binary files differ
diff --git a/tdehtml/pics/cr16-action-images_display.png b/tdehtml/pics/cr16-action-images_display.png
new file mode 100644
index 000000000..66f550e7a
--- /dev/null
+++ b/tdehtml/pics/cr16-action-images_display.png
Binary files differ
diff --git a/tdehtml/pics/cr16-action-wallet_open.png b/tdehtml/pics/cr16-action-wallet_open.png
new file mode 100644
index 000000000..f0d309834
--- /dev/null
+++ b/tdehtml/pics/cr16-action-wallet_open.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-bug.png b/tdehtml/pics/cr22-action-bug.png
new file mode 100644
index 000000000..3a3d1ea2b
--- /dev/null
+++ b/tdehtml/pics/cr22-action-bug.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-dbgnext.png b/tdehtml/pics/cr22-action-dbgnext.png
new file mode 100644
index 000000000..ee94f5854
--- /dev/null
+++ b/tdehtml/pics/cr22-action-dbgnext.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-dbgrun.png b/tdehtml/pics/cr22-action-dbgrun.png
new file mode 100644
index 000000000..32f4badc5
--- /dev/null
+++ b/tdehtml/pics/cr22-action-dbgrun.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-dbgrunto.png b/tdehtml/pics/cr22-action-dbgrunto.png
new file mode 100644
index 000000000..861c549ab
--- /dev/null
+++ b/tdehtml/pics/cr22-action-dbgrunto.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-dbgstep.png b/tdehtml/pics/cr22-action-dbgstep.png
new file mode 100644
index 000000000..c4a760435
--- /dev/null
+++ b/tdehtml/pics/cr22-action-dbgstep.png
Binary files differ
diff --git a/tdehtml/pics/cr22-action-images_display.png b/tdehtml/pics/cr22-action-images_display.png
new file mode 100644
index 000000000..96ad00c41
--- /dev/null
+++ b/tdehtml/pics/cr22-action-images_display.png
Binary files differ
diff --git a/tdehtml/pics/cr32-action-bug.png b/tdehtml/pics/cr32-action-bug.png
new file mode 100644
index 000000000..597739255
--- /dev/null
+++ b/tdehtml/pics/cr32-action-bug.png
Binary files differ
diff --git a/tdehtml/pics/cr32-action-images_display.png b/tdehtml/pics/cr32-action-images_display.png
new file mode 100644
index 000000000..ced97ac3f
--- /dev/null
+++ b/tdehtml/pics/cr32-action-images_display.png
Binary files differ
diff --git a/tdehtml/pics/cr48-action-bug.png b/tdehtml/pics/cr48-action-bug.png
new file mode 100644
index 000000000..2565d767c
--- /dev/null
+++ b/tdehtml/pics/cr48-action-bug.png
Binary files differ
diff --git a/tdehtml/pics/cr64-action-bug.png b/tdehtml/pics/cr64-action-bug.png
new file mode 100644
index 000000000..f2f45269e
--- /dev/null
+++ b/tdehtml/pics/cr64-action-bug.png
Binary files differ
diff --git a/tdehtml/rendering/CMakeLists.txt b/tdehtml/rendering/CMakeLists.txt
new file mode 100644
index 000000000..757e9a72a
--- /dev/null
+++ b/tdehtml/rendering/CMakeLists.txt
@@ -0,0 +1,46 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/kio/kfile
+ ${CMAKE_SOURCE_DIR}/tdeutils
+)
+
+
+##### tdehtmlrender-static #########################
+
+set( target tdehtmlrender )
+
+set( ${target}_SRCS
+ bidi.cpp break_lines.cpp render_block.cpp render_inline.cpp
+ render_style.cpp render_object.cpp render_container.cpp render_box.cpp
+ render_flow.cpp render_text.cpp render_arena.cpp render_layer.cpp
+ render_image.cpp render_table.cpp table_layout.cpp
+ render_replaced.cpp render_form.cpp render_list.cpp
+ render_canvas.cpp render_frames.cpp render_br.cpp
+ render_body.cpp font.cpp render_line.cpp render_generated.cpp
+ enumerate.cpp counter_tree.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
diff --git a/tdehtml/rendering/Makefile.am b/tdehtml/rendering/Makefile.am
new file mode 100644
index 000000000..605788764
--- /dev/null
+++ b/tdehtml/rendering/Makefile.am
@@ -0,0 +1,57 @@
+# 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 = libtdehtmlrender.la
+libtdehtmlrender_la_SOURCES = \
+ bidi.cpp break_lines.cpp render_block.cpp render_inline.cpp \
+ render_style.cpp render_object.cpp render_container.cpp render_box.cpp \
+ render_flow.cpp render_text.cpp render_arena.cpp render_layer.cpp \
+ render_image.cpp render_table.cpp table_layout.cpp \
+ render_replaced.cpp render_form.cpp render_list.cpp \
+ render_canvas.cpp render_frames.cpp render_br.cpp \
+ render_body.cpp font.cpp render_line.cpp render_generated.cpp \
+ enumerate.cpp counter_tree.cpp
+
+libtdehtmlrender_la_METASOURCES = AUTO
+
+noinst_HEADERS = \
+ bidi.h break_lines.h \
+ render_arena.h render_layer.h \
+ render_style.h render_object.h render_container.h render_box.h \
+ render_flow.h render_text.h render_table.h render_replaced.h \
+ render_form.h render_list.h render_canvas.h render_frames.h \
+ render_br.h render_applet.h font.h table_layout.h render_line.h \
+ render_generated.h enumerate.h
+
+INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/kio -I$(top_srcdir)/dcop \
+ -I$(top_srcdir)/kfile -I$(top_srcdir)/tdehtml -I$(top_srcdir)/tdeutils -I$(top_srcdir) $(all_includes)
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) tdecore -lqt
+
+## maintainer: regen loading icon
+loading-icon:
+ bin2c -sploading_icon $(srcdir)/img-loading.png > $(srcdir)/loading_icon.cpp
+
diff --git a/tdehtml/rendering/bidi.cpp b/tdehtml/rendering/bidi.cpp
new file mode 100644
index 000000000..a79ac9854
--- /dev/null
+++ b/tdehtml/rendering/bidi.cpp
@@ -0,0 +1,2250 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2003-2005 Apple Computer, Inc.
+ * (C) 2005 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.
+ *
+ */
+#include "rendering/bidi.h"
+#include "rendering/break_lines.h"
+#include "rendering/render_block.h"
+#include "rendering/render_text.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_layer.h"
+#include "rendering/render_canvas.h"
+#include "xml/dom_docimpl.h"
+
+#include "kdebug.h"
+#include "tqdatetime.h"
+#include "tqfontmetrics.h"
+
+#define BIDI_DEBUG 0
+//#define DEBUG_LINEBREAKS
+//#define PAGE_DEBUG
+
+namespace tdehtml {
+
+
+// an iterator which goes through a BidiParagraph
+struct BidiIterator
+{
+ BidiIterator() : par(0), obj(0), pos(0), endOfInline(0) {}
+ BidiIterator(RenderBlock *_par, RenderObject *_obj, unsigned int _pos, bool eoi=false) : par(_par), obj(_obj), pos(_pos), endOfInline(eoi) {}
+
+ void increment( BidiState &bidi, bool skipInlines=true );
+
+ bool atEnd() const;
+
+ const TQChar &current() const;
+ TQChar::Direction direction() const;
+
+ RenderBlock *par;
+ RenderObject *obj;
+ unsigned int pos;
+ bool endOfInline;
+};
+
+
+struct BidiStatus {
+ BidiStatus() : eor(TQChar::DirON), lastStrong(TQChar::DirON), last(TQChar::DirON) {}
+
+ TQChar::Direction eor;
+ TQChar::Direction lastStrong;
+ TQChar::Direction last;
+};
+
+struct BidiState {
+ BidiState() : context(0) {}
+
+ BidiIterator sor;
+ BidiIterator eor;
+ BidiIterator last;
+ BidiIterator current;
+ BidiContext *context;
+ BidiStatus status;
+};
+
+// Used to track a list of chained bidi runs.
+static BidiRun* sFirstBidiRun;
+static BidiRun* sLastBidiRun;
+static int sBidiRunCount;
+static BidiRun* sCompactFirstBidiRun;
+static BidiRun* sCompactLastBidiRun;
+static int sCompactBidiRunCount;
+static bool sBuildingCompactRuns;
+
+// Midpoint globals. The goal is not to do any allocation when dealing with
+// these midpoints, so we just keep an array around and never clear it. We track
+// the number of items and position using the two other variables.
+static TQMemArray<BidiIterator> *smidpoints;
+static uint sNumMidpoints;
+static uint sCurrMidpoint;
+static bool betweenMidpoints;
+
+static bool isLineEmpty = true;
+static bool previousLineBrokeAtBR = true;
+static TQChar::Direction dir;
+static bool adjustEmbedding;
+static bool emptyRun = true;
+static int numSpaces;
+
+static void embed( TQChar::Direction d, BidiState &bidi );
+static void appendRun( BidiState &bidi );
+
+static int getBPMWidth(int childValue, Length cssUnit)
+{
+ if (!cssUnit.isVariable())
+ return (cssUnit.isFixed() ? cssUnit.value() : childValue);
+ return 0;
+}
+
+static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
+{
+ RenderStyle* cstyle = child->style();
+ int result = 0;
+ bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
+ result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
+ (leftSide ? cstyle->marginLeft() :
+ cstyle->marginRight()));
+ result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
+ (leftSide ? cstyle->paddingLeft() :
+ cstyle->paddingRight()));
+ result += leftSide ? child->borderLeft() : child->borderRight();
+ return result;
+}
+
+#ifndef NDEBUG
+static bool inBidiRunDetach;
+#endif
+
+void BidiRun::detach(RenderArena* renderArena)
+{
+#ifndef NDEBUG
+ inBidiRunDetach = true;
+#endif
+ delete this;
+#ifndef NDEBUG
+ inBidiRunDetach = false;
+#endif
+
+ // Recover the size left there for us by operator delete and free the memory.
+ renderArena->free(*(size_t *)this, this);
+}
+
+void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void BidiRun::operator delete(void* ptr, size_t sz)
+{
+ assert(inBidiRunDetach);
+
+ // Stash size where detach can find it.
+ *(size_t*)ptr = sz;
+}
+
+static void deleteBidiRuns(RenderArena* arena)
+{
+ if (!sFirstBidiRun)
+ return;
+
+ BidiRun* curr = sFirstBidiRun;
+ while (curr) {
+ BidiRun* s = curr->nextRun;
+ curr->detach(arena);
+ curr = s;
+ }
+
+ sFirstBidiRun = 0;
+ sLastBidiRun = 0;
+ sBidiRunCount = 0;
+}
+
+// ---------------------------------------------------------------------
+
+/* a small helper class used internally to resolve Bidi embedding levels.
+ Each line of text caches the embedding level at the start of the line for faster
+ relayouting
+*/
+BidiContext::BidiContext(unsigned char l, TQChar::Direction e, BidiContext *p, bool o)
+ : level(l) , override(o), dir(e)
+{
+ parent = p;
+ if(p) {
+ p->ref();
+ basicDir = p->basicDir;
+ } else
+ basicDir = e;
+ count = 0;
+}
+
+BidiContext::~BidiContext()
+{
+ if(parent) parent->deref();
+}
+
+void BidiContext::ref() const
+{
+ count++;
+}
+
+void BidiContext::deref() const
+{
+ count--;
+ if(count <= 0) delete this;
+}
+
+// ---------------------------------------------------------------------
+
+inline bool operator==( const BidiIterator &it1, const BidiIterator &it2 )
+{
+ if(it1.pos != it2.pos) return false;
+ if(it1.obj != it2.obj) return false;
+ return true;
+}
+
+inline bool operator!=( const BidiIterator &it1, const BidiIterator &it2 )
+{
+ if(it1.pos != it2.pos) return true;
+ if(it1.obj != it2.obj) return true;
+ return false;
+}
+
+// when modifying this function, make sure you check InlineMinMaxIterator::next() as well.
+static inline RenderObject *Bidinext(RenderObject *par, RenderObject *current, BidiState &bidi,
+ bool skipInlines = true, bool *endOfInline = 0 )
+{
+ RenderObject *next = 0;
+ bool oldEndOfInline = endOfInline ? *endOfInline : false;
+ if (oldEndOfInline)
+ *endOfInline = false;
+
+ while(current != 0)
+ {
+ //kdDebug( 6040 ) << "current = " << current << endl;
+ if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
+ next = current->firstChild();
+ if ( next && adjustEmbedding ) {
+ EUnicodeBidi ub = next->style()->unicodeBidi();
+ if ( ub != UBNormal && !emptyRun ) {
+ EDirection dir = next->style()->direction();
+ TQChar::Direction d = ( ub == Embed ? ( dir == RTL ? TQChar::DirRLE : TQChar::DirLRE )
+ : ( dir == RTL ? TQChar::DirRLO : TQChar::DirLRO ) );
+ embed( d, bidi );
+ }
+ }
+ }
+ if (!next) {
+ if (!skipInlines && !oldEndOfInline && current->isInlineFlow() && endOfInline) {
+ next = current;
+ *endOfInline = true;
+ break;
+ }
+
+ while (current && current != par) {
+ next = current->nextSibling();
+ if (next) break;
+ if ( adjustEmbedding && current->style()->unicodeBidi() != UBNormal && !emptyRun ) {
+ embed( TQChar::DirPDF, bidi );
+ }
+ current = current->parent();
+ if (!skipInlines && current && current != par && current->isInlineFlow() && endOfInline) {
+ next = current;
+ *endOfInline = true;
+ break;
+ }
+ }
+ }
+
+ if (!next) break;
+
+ if (next->isText() || next->isBR() || next->isFloating() || next->isReplaced() || next->isPositioned() || next->isGlyph()
+ || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines.
+ && next->isInlineFlow()))
+ break;
+ current = next;
+ }
+ return next;
+}
+
+static RenderObject *first( RenderObject *par, BidiState &bidi, bool skipInlines = true )
+{
+ if(!par->firstChild()) return 0;
+ RenderObject *o = par->firstChild();
+
+ if (o->isInlineFlow()) {
+ if (skipInlines && o->firstChild())
+ o = Bidinext( par, o, bidi, skipInlines );
+ else
+ return o; // Never skip empty inlines.
+ }
+
+ if (o && !o->isText() && !o->isBR() && !o->isReplaced() && !o->isFloating() && !o->isPositioned() && !o->isGlyph())
+ o = Bidinext( par, o, bidi, skipInlines );
+ return o;
+}
+
+inline void BidiIterator::increment (BidiState &bidi, bool skipInlines)
+{
+ if(!obj) return;
+ if(obj->isText()) {
+ pos++;
+ if(pos >= static_cast<RenderText *>(obj)->stringLength()) {
+ obj = Bidinext( par, obj, bidi, skipInlines );
+ pos = 0;
+ }
+ } else {
+ obj = Bidinext( par, obj, bidi, skipInlines, &endOfInline );
+ pos = 0;
+ }
+}
+
+inline bool BidiIterator::atEnd() const
+{
+ if(!obj) return true;
+ return false;
+}
+
+const TQChar &BidiIterator::current() const
+{
+ static TQChar nonBreakingSpace(0xA0);
+
+ if (!obj || !obj->isText())
+ return nonBreakingSpace;
+
+ RenderText* text = static_cast<RenderText*>(obj);
+ if (!text->text())
+ return nonBreakingSpace;
+
+ return text->text()[pos];
+}
+
+inline TQChar::Direction BidiIterator::direction() const
+{
+ if(!obj || !obj->isText() ) return TQChar::DirON;
+
+ RenderText *renderTxt = static_cast<RenderText *>( obj );
+ if ( pos >= renderTxt->stringLength() )
+ return TQChar::DirON;
+ return renderTxt->text()[pos].direction();
+}
+
+// -------------------------------------------------------------------------------------------------
+
+static void addRun(BidiRun* bidiRun)
+{
+ if (!sFirstBidiRun)
+ sFirstBidiRun = sLastBidiRun = bidiRun;
+ else {
+ sLastBidiRun->nextRun = bidiRun;
+ sLastBidiRun = bidiRun;
+ }
+ sBidiRunCount++;
+ bidiRun->compact = sBuildingCompactRuns;
+
+ // Compute the number of spaces in this run,
+ if (bidiRun->obj && bidiRun->obj->isText()) {
+ RenderText* text = static_cast<RenderText*>(bidiRun->obj);
+ if (text->text()) {
+ for (int i = bidiRun->start; i < bidiRun->stop; i++) {
+ const TQChar c = text->text()[i];
+ if (c.category() == TQChar::Separator_Space || c == '\n')
+ numSpaces++;
+ }
+ }
+ }
+}
+
+static void reverseRuns(int start, int end)
+{
+ if (start >= end)
+ return;
+
+ assert(start >= 0 && end < sBidiRunCount);
+
+ // Get the item before the start of the runs to reverse and put it in
+ // |beforeStart|. |curr| should point to the first run to reverse.
+ BidiRun* curr = sFirstBidiRun;
+ BidiRun* beforeStart = 0;
+ int i = 0;
+ while (i < start) {
+ i++;
+ beforeStart = curr;
+ curr = curr->nextRun;
+ }
+
+ BidiRun* startRun = curr;
+ while (i < end) {
+ i++;
+ curr = curr->nextRun;
+ }
+ BidiRun* endRun = curr;
+ BidiRun* afterEnd = curr->nextRun;
+
+ i = start;
+ curr = startRun;
+ BidiRun* newNext = afterEnd;
+ while (i <= end) {
+ // Do the reversal.
+ BidiRun* next = curr->nextRun;
+ curr->nextRun = newNext;
+ newNext = curr;
+ curr = next;
+ i++;
+ }
+
+ // Now hook up beforeStart and afterEnd to the newStart and newEnd.
+ if (beforeStart)
+ beforeStart->nextRun = endRun;
+ else
+ sFirstBidiRun = endRun;
+
+ startRun->nextRun = afterEnd;
+ if (!afterEnd)
+ sLastBidiRun = startRun;
+}
+
+static void chopMidpointsAt(RenderObject* obj, uint pos)
+{
+ if (!sNumMidpoints) return;
+ BidiIterator* midpoints = smidpoints->data();
+ for (uint i = 0; i < sNumMidpoints; i++) {
+ const BidiIterator& point = midpoints[i];
+ if (point.obj == obj && point.pos == pos) {
+ sNumMidpoints = i;
+ break;
+ }
+ }
+}
+
+static void checkMidpoints(BidiIterator& lBreak, BidiState &bidi)
+{
+ // Check to see if our last midpoint is a start point beyond the line break. If so,
+ // shave it off the list, and shave off a trailing space if the previous end point isn't
+ // white-space: pre.
+ if (lBreak.obj && sNumMidpoints && sNumMidpoints%2 == 0) {
+ BidiIterator* midpoints = smidpoints->data();
+ BidiIterator& endpoint = midpoints[sNumMidpoints-2];
+ const BidiIterator& startpoint = midpoints[sNumMidpoints-1];
+ BidiIterator currpoint = endpoint;
+ while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
+ currpoint.increment( bidi );
+ if (currpoint == lBreak) {
+ // We hit the line break before the start point. Shave off the start point.
+ sNumMidpoints--;
+ if (!endpoint.obj->style()->preserveWS()) {
+ if (endpoint.obj->isText()) {
+ // Don't shave a character off the endpoint if it was from a soft hyphen.
+ RenderText* textObj = static_cast<RenderText*>(endpoint.obj);
+ if (endpoint.pos+1 < textObj->length() &&
+ textObj->text()[endpoint.pos+1].unicode() == SOFT_HYPHEN)
+ return;
+ }
+ endpoint.pos--;
+ }
+ }
+ }
+}
+
+static void addMidpoint(const BidiIterator& midpoint)
+{
+ if (!smidpoints)
+ return;
+
+ if (smidpoints->size() <= sNumMidpoints)
+ smidpoints->resize(sNumMidpoints+10);
+
+ BidiIterator* midpoints = smidpoints->data();
+ midpoints[sNumMidpoints++] = midpoint;
+}
+
+static void appendRunsForObject(int start, int end, RenderObject* obj, BidiState &bidi)
+{
+ if (start > end || obj->isFloating() ||
+ (obj->isPositioned() && !obj->hasStaticX() && !obj->hasStaticY()))
+ return;
+
+ bool haveNextMidpoint = (smidpoints && sCurrMidpoint < sNumMidpoints);
+ BidiIterator nextMidpoint;
+ if (haveNextMidpoint)
+ nextMidpoint = smidpoints->at(sCurrMidpoint);
+ if (betweenMidpoints) {
+ if (!(haveNextMidpoint && nextMidpoint.obj == obj))
+ return;
+ // This is a new start point. Stop ignoring objects and
+ // adjust our start.
+ betweenMidpoints = false;
+ start = nextMidpoint.pos;
+ sCurrMidpoint++;
+ if (start < end)
+ return appendRunsForObject(start, end, obj, bidi);
+ }
+ else {
+ if (!smidpoints || !haveNextMidpoint || (obj != nextMidpoint.obj)) {
+ addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, dir));
+ return;
+ }
+
+ // An end midpoint has been encountered within our object. We
+ // need to go ahead and append a run with our endpoint.
+ if (int(nextMidpoint.pos+1) <= end) {
+ betweenMidpoints = true;
+ sCurrMidpoint++;
+ if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
+ addRun(new (obj->renderArena())
+ BidiRun(start, nextMidpoint.pos+1, obj, bidi.context, dir));
+ return appendRunsForObject(nextMidpoint.pos+1, end, obj, bidi);
+ }
+ }
+ else
+ addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, dir));
+ }
+}
+
+static void appendRun( BidiState &bidi )
+{
+ if ( emptyRun ) return;
+#if BIDI_DEBUG > 1
+ kdDebug(6041) << "appendRun: dir="<<(int)dir<<endl;
+#endif
+
+ bool b = adjustEmbedding;
+ adjustEmbedding = false;
+
+ int start = bidi.sor.pos;
+ RenderObject *obj = bidi.sor.obj;
+ while( obj && obj != bidi.eor.obj ) {
+ appendRunsForObject(start, obj->length(), obj, bidi);
+ start = 0;
+ obj = Bidinext( bidi.sor.par, obj, bidi );
+ }
+ if (obj)
+ appendRunsForObject(start, bidi.eor.pos+1, obj, bidi);
+
+ bidi.eor.increment( bidi );
+ bidi.sor = bidi.eor;
+ dir = TQChar::DirON;
+ bidi.status.eor = TQChar::DirON;
+ adjustEmbedding = b;
+}
+
+static void embed( TQChar::Direction d, BidiState &bidi )
+{
+#if BIDI_DEBUG > 1
+ tqDebug("*** embed dir=%d emptyrun=%d", d, emptyRun );
+#endif
+ bool b = adjustEmbedding ;
+ adjustEmbedding = false;
+ if ( d == TQChar::DirPDF ) {
+ BidiContext *c = bidi.context->parent;
+ if (c) {
+ if ( bidi.eor != bidi.last ) {
+ appendRun( bidi );
+ bidi.eor = bidi.last;
+ }
+ appendRun( bidi );
+ emptyRun = true;
+ bidi.status.last = bidi.context->dir;
+ bidi.context->deref();
+ bidi.context = c;
+ if(bidi.context->override)
+ dir = bidi.context->dir;
+ else
+ dir = TQChar::DirON;
+ bidi.status.lastStrong = bidi.context->dir;
+ }
+ } else {
+ TQChar::Direction runDir;
+ if( d == TQChar::DirRLE || d == TQChar::DirRLO )
+ runDir = TQChar::DirR;
+ else
+ runDir = TQChar::DirL;
+ bool override;
+ if( d == TQChar::DirLRO || d == TQChar::DirRLO )
+ override = true;
+ else
+ override = false;
+
+ unsigned char level = bidi.context->level;
+ if ( runDir == TQChar::DirR ) {
+ if(level%2) // we have an odd level
+ level += 2;
+ else
+ level++;
+ } else {
+ if(level%2) // we have an odd level
+ level++;
+ else
+ level += 2;
+ }
+
+ if(level < 61) {
+ if ( bidi.eor != bidi.last ) {
+ appendRun( bidi );
+ bidi.eor = bidi.last;
+ }
+ appendRun( bidi );
+ emptyRun = true;
+
+ bidi.context = new BidiContext(level, runDir, bidi.context, override);
+ bidi.context->ref();
+ dir = runDir;
+ bidi.status.last = runDir;
+ bidi.status.lastStrong = runDir;
+ bidi.status.eor = runDir;
+ }
+ }
+ adjustEmbedding = b;
+}
+
+InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
+{
+ // See if we have an unconstructed line box for this object that is also
+ // the last item on the line.
+ KHTMLAssert(obj->isInlineFlow() || obj == this);
+ RenderFlow* flow = static_cast<RenderFlow*>(obj);
+
+ // Get the last box we made for this render object.
+ InlineFlowBox* box = flow->lastLineBox();
+
+ // If this box is constructed then it is from a previous line, and we need
+ // to make a new box for our line. If this box is unconstructed but it has
+ // something following it on the line, then we know we have to make a new box
+ // as well. In this situation our inline has actually been split in two on
+ // the same line (this can happen with very fancy language mixtures).
+ if (!box || box->isConstructed() || box->nextOnLine()) {
+ // We need to make a new box for this render object. Once
+ // made, we need to place it at the end of the current line.
+ InlineBox* newBox = obj->createInlineBox(false, obj == this);
+ KHTMLAssert(newBox->isInlineFlowBox());
+ box = static_cast<InlineFlowBox*>(newBox);
+ box->setFirstLineStyleBit(m_firstLine);
+
+ // We have a new box. Append it to the inline box we get by constructing our
+ // parent. If we have hit the block itself, then |box| represents the root
+ // inline box for the line, and it doesn't have to be appended to any parent
+ // inline.
+ if (obj != this) {
+ InlineFlowBox* parentBox = createLineBoxes(obj->parent());
+ parentBox->addToLine(box);
+ }
+ }
+
+ return box;
+}
+
+InlineFlowBox* RenderBlock::constructLine(const BidiIterator &/*start*/, const BidiIterator &end)
+{
+ if (!sFirstBidiRun)
+ return 0; // We had no runs. Don't make a root inline box at all. The line is empty.
+
+ InlineFlowBox* parentBox = 0;
+ for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
+ // Create a box for our object.
+ r->box = r->obj->createInlineBox(r->obj->isPositioned(), false);
+
+ // If we have no parent box yet, or if the run is not simply a sibling,
+ // then we need to construct inline boxes as necessary to properly enclose the
+ // run's inline box.
+ if (!parentBox || (parentBox->object() != r->obj->parent()))
+ // Create new inline boxes all the way back to the appropriate insertion point.
+ parentBox = createLineBoxes(r->obj->parent());
+
+ // Append the inline box to this line.
+ parentBox->addToLine(r->box);
+ }
+
+ // We should have a root inline box. It should be unconstructed and
+ // be the last continuation of our line list.
+ KHTMLAssert(lastLineBox() && !lastLineBox()->isConstructed());
+
+ // Set bits on our inline flow boxes that indicate which sides should
+ // paint borders/margins/padding. This knowledge will ultimately be used when
+ // we determine the horizontal positions and widths of all the inline boxes on
+ // the line.
+ RenderObject* endObject = 0;
+ bool lastLine = !end.obj;
+ if (end.obj && end.pos == 0)
+ endObject = end.obj;
+ lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject);
+
+ // Now mark the line boxes as being constructed.
+ lastLineBox()->setConstructed();
+
+ // Return the last line.
+ return lastLineBox();
+}
+
+void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi)
+{
+ // First determine our total width.
+ int totWidth = lineBox->getFlowSpacingWidth();
+ BidiRun* r = 0;
+ for (r = sFirstBidiRun; r; r = r->nextRun) {
+ if (r->obj->isPositioned())
+ continue; // Positioned objects are only participating to figure out their
+ // correct static x position. They have no effect on the width.
+ if (r->obj->isText())
+ r->box->setWidth(static_cast<RenderText *>(r->obj)->width(r->start, r->stop-r->start, m_firstLine));
+ else if (!r->obj->isInlineFlow()) {
+ r->obj->calcWidth();
+ r->box->setWidth(r->obj->width());
+ totWidth += r->obj->marginLeft() + r->obj->marginRight();
+ }
+ totWidth += r->box->width();
+ }
+
+ // Armed with the total width of the line (without justification),
+ // we now examine our text-align property in order to determine where to position the
+ // objects horizontally. The total width of the line can be increased if we end up
+ // justifying text.
+ int x = leftOffset(m_height);
+ int availableWidth = lineWidth(m_height);
+ switch(style()->textAlign()) {
+ case LEFT:
+ case KHTML_LEFT:
+ numSpaces = 0;
+ break;
+ case JUSTIFY:
+ if (numSpaces != 0 && !bidi.current.atEnd() && !bidi.current.obj->isBR() )
+ break;
+ // fall through
+ case TAAUTO:
+ numSpaces = 0;
+ // for right to left fall through to right aligned
+ if (bidi.context->basicDir == TQChar::DirL)
+ break;
+ case RIGHT:
+ case KHTML_RIGHT:
+ x += availableWidth - totWidth;
+ numSpaces = 0;
+ break;
+ case CENTER:
+ case KHTML_CENTER:
+ int xd = (availableWidth - totWidth)/2;
+ x += xd >0 ? xd : 0;
+ numSpaces = 0;
+ break;
+ }
+
+ if (numSpaces > 0) {
+ for (r = sFirstBidiRun; r; r = r->nextRun) {
+ int spaceAdd = 0;
+ if (numSpaces > 0 && r->obj->isText()) {
+ // get the number of spaces in the run
+ int spaces = 0;
+ for ( int i = r->start; i < r->stop; i++ ) {
+ const TQChar c = static_cast<RenderText *>(r->obj)->text()[i];
+ if (c.category() == TQChar::Separator_Space || c == '\n')
+ spaces++;
+ }
+
+ KHTMLAssert(spaces <= numSpaces);
+
+ // Only justify text with white-space: normal.
+ if (r->obj->style()->whiteSpace() == NORMAL) {
+ spaceAdd = (availableWidth - totWidth)*spaces/numSpaces;
+ static_cast<InlineTextBox*>(r->box)->setSpaceAdd(spaceAdd);
+ totWidth += spaceAdd;
+ }
+ numSpaces -= spaces;
+ }
+ }
+ }
+
+ // The widths of all runs are now known. We can now place every inline box (and
+ // compute accurate widths for the inline flow boxes).
+ int rightPos = lineBox->placeBoxesHorizontally(x);
+ if (rightPos > m_overflowWidth)
+ m_overflowWidth = rightPos; // FIXME: Work for rtl overflow also.
+ if (x < 0)
+ m_overflowLeft = kMin(m_overflowLeft, x);
+}
+
+void RenderBlock::computeVerticalPositionsForLine(InlineFlowBox* lineBox)
+{
+ lineBox->verticallyAlignBoxes(m_height);
+// lineBox->setBlockHeight(m_height);
+
+ // Check for page-breaks
+ if (canvas()->pagedMode() && !lineBox->afterPageBreak())
+ // If we get a page-break we might need to redo the line-break
+ if (clearLineOfPageBreaks(lineBox) && hasFloats()) return;
+
+ // See if the line spilled out. If so set overflow height accordingly.
+ int bottomOfLine = lineBox->bottomOverflow();
+ if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
+ m_overflowHeight = bottomOfLine;
+
+ bool beforeContent = true;
+
+ // Now make sure we place replaced render objects correctly.
+ for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
+
+ // For positioned placeholders, cache the static Y position an object with non-inline display would have.
+ // Either it is unchanged if it comes before any real linebox, or it must clear the current line (already accounted in m_height).
+ // This value will be picked up by position() if relevant.
+ if (r->obj->isPositioned())
+ r->box->setYPos( beforeContent && r->obj->isBox() ? static_cast<RenderBox*>(r->obj)->staticY() : m_height );
+ else if (beforeContent)
+ beforeContent = false;
+
+ // Position is used to properly position both replaced elements and
+ // to update the static normal flow x/y of positioned elements.
+ r->obj->position(r->box, r->start, r->stop - r->start, r->level%2);
+ }
+}
+
+bool RenderBlock::clearLineOfPageBreaks(InlineFlowBox* lineBox)
+{
+ bool doPageBreak = false;
+ // Check for physical page-breaks
+ int xpage = crossesPageBreak(lineBox->topOverflow(), lineBox->bottomOverflow());
+ if (xpage) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " Line crosses to page " << xpage << endl;
+ kdDebug(6040) << renderName() << " at pos " << lineBox->yPos() << " height " << lineBox->height() << endl;
+#endif
+
+ doPageBreak = true;
+ // check page-break-inside
+ if (!style()->pageBreakInside()) {
+ if (parent()->canClear(this, PageBreakNormal)) {
+ setNeedsPageClear(true);
+ doPageBreak = false;
+ }
+#ifdef PAGE_DEBUG
+ else
+ kdDebug(6040) << "Ignoring page-break-inside: avoid" << endl;
+#endif
+ }
+ // check orphans
+ int orphans = 0;
+ InlineRunBox* box = lineBox->prevLineBox();
+ while (box && orphans < style()->orphans()) {
+ orphans++;
+ box = box->prevLineBox();
+ }
+
+ if (orphans == 0) {
+ setNeedsPageClear(true);
+ doPageBreak = false;
+ } else
+ if (orphans < style()->orphans() ) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << "Orphans: " << orphans << endl;
+#endif
+ // Orphans is a level 2 page-break rule and can be broken only
+ // if the break is physically required.
+ if (parent()->canClear(this, PageBreakHarder)) {
+ // move block instead
+ setNeedsPageClear(true);
+ doPageBreak = false;
+ }
+#ifdef PAGE_DEBUG
+ else
+ kdDebug(6040) << "Ignoring violated orphans" << endl;
+#endif
+ }
+ if (doPageBreak) {
+ int pTop = pageTopAfter(lineBox->yPos());
+
+ m_height = pTop;
+ lineBox->setAfterPageBreak(true);
+ lineBox->verticallyAlignBoxes(m_height);
+ if (lineBox->yPos() < pTop) {
+ // ### serious crap. render_line is sometimes placing lines too high
+ kdDebug(6040) << "page top overflow by repositioned line" << endl;
+ int heightIncrease = pTop - lineBox->yPos();
+ m_height = pTop + heightIncrease;
+ lineBox->verticallyAlignBoxes(m_height);
+ }
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << "Cleared line " << lineBox->yPos() - oldYPos << "px" << endl;
+#endif
+ setContainsPageBreak(true);
+ }
+ }
+ return doPageBreak;
+}
+
+// collects one line of the paragraph and transforms it to visual order
+void RenderBlock::bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi)
+{
+ if ( start == end ) {
+ if ( start.current() == '\n' ) {
+ m_height += lineHeight( m_firstLine );
+ }
+ return;
+ }
+
+#if BIDI_DEBUG > 1
+ kdDebug(6041) << "reordering Line from " << start.obj << "/" << start.pos << " to " << end.obj << "/" << end.pos << endl;
+#endif
+
+ sFirstBidiRun = 0;
+ sLastBidiRun = 0;
+ sBidiRunCount = 0;
+
+ // context->ref();
+
+ dir = TQChar::DirON;
+ emptyRun = true;
+
+ numSpaces = 0;
+
+ bidi.current = start;
+ bidi.last = bidi.current;
+ bool atEnd = false;
+ while( 1 ) {
+
+ TQChar::Direction dirCurrent;
+ if (atEnd) {
+ //kdDebug(6041) << "atEnd" << endl;
+ BidiContext *c = bidi.context;
+ if ( bidi.current.atEnd())
+ while ( c->parent )
+ c = c->parent;
+ dirCurrent = c->dir;
+ } else {
+ dirCurrent = bidi.current.direction();
+ }
+
+#ifndef QT_NO_UNICODETABLES
+
+#if BIDI_DEBUG > 1
+ kdDebug(6041) << "directions: dir=" << (int)dir << " current=" << (int)dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << (int)context->dir << " level =" << (int)context->level << endl;
+#endif
+
+ switch(dirCurrent) {
+
+ // embedding and overrides (X1-X9 in the Bidi specs)
+ case TQChar::DirRLE:
+ case TQChar::DirLRE:
+ case TQChar::DirRLO:
+ case TQChar::DirLRO:
+ case TQChar::DirPDF:
+ embed( dirCurrent, bidi );
+ break;
+
+ // strong types
+ case TQChar::DirL:
+ if(dir == TQChar::DirON)
+ dir = TQChar::DirL;
+ switch(bidi.status.last)
+ {
+ case TQChar::DirL:
+ bidi.eor = bidi.current; bidi.status.eor = TQChar::DirL; break;
+ case TQChar::DirR:
+ case TQChar::DirAL:
+ case TQChar::DirEN:
+ case TQChar::DirAN:
+ appendRun( bidi );
+ break;
+ case TQChar::DirES:
+ case TQChar::DirET:
+ case TQChar::DirCS:
+ case TQChar::DirBN:
+ case TQChar::DirB:
+ case TQChar::DirS:
+ case TQChar::DirWS:
+ case TQChar::DirON:
+ if( bidi.status.eor != TQChar::DirL ) {
+ //last stuff takes embedding dir
+ if(bidi.context->dir == TQChar::DirL || bidi.status.lastStrong == TQChar::DirL) {
+ if ( bidi.status.eor != TQChar::DirEN && bidi.status.eor != TQChar::DirAN && bidi.status.eor != TQChar::DirON )
+ appendRun( bidi );
+ dir = TQChar::DirL;
+ bidi.eor = bidi.current;
+ bidi.status.eor = TQChar::DirL;
+ } else {
+ if ( bidi.status.eor == TQChar::DirEN || bidi.status.eor == TQChar::DirAN )
+ {
+ dir = bidi.status.eor;
+ appendRun( bidi );
+ }
+ dir = TQChar::DirR;
+ bidi.eor = bidi.last;
+ appendRun( bidi );
+ dir = TQChar::DirL;
+ bidi.status.eor = TQChar::DirL;
+ }
+ } else {
+ bidi.eor = bidi.current; bidi.status.eor = TQChar::DirL;
+ }
+ default:
+ break;
+ }
+ bidi.status.lastStrong = TQChar::DirL;
+ break;
+ case TQChar::DirAL:
+ case TQChar::DirR:
+ if(dir == TQChar::DirON) dir = TQChar::DirR;
+ switch(bidi.status.last)
+ {
+ case TQChar::DirR:
+ case TQChar::DirAL:
+ bidi.eor = bidi.current; bidi.status.eor = TQChar::DirR; break;
+ case TQChar::DirL:
+ case TQChar::DirEN:
+ case TQChar::DirAN:
+ appendRun( bidi );
+ dir = TQChar::DirR;
+ bidi.eor = bidi.current;
+ bidi.status.eor = TQChar::DirR;
+ break;
+ case TQChar::DirES:
+ case TQChar::DirET:
+ case TQChar::DirCS:
+ case TQChar::DirBN:
+ case TQChar::DirB:
+ case TQChar::DirS:
+ case TQChar::DirWS:
+ case TQChar::DirON:
+ if( !(bidi.status.eor == TQChar::DirR) && !(bidi.status.eor == TQChar::DirAL) ) {
+ //last stuff takes embedding dir
+ if(bidi.context->dir == TQChar::DirR || bidi.status.lastStrong == TQChar::DirR
+ || bidi.status.lastStrong == TQChar::DirAL) {
+ appendRun( bidi );
+ dir = TQChar::DirR;
+ bidi.eor = bidi.current;
+ bidi.status.eor = TQChar::DirR;
+ } else {
+ dir = TQChar::DirL;
+ bidi.eor = bidi.last;
+ appendRun( bidi );
+ dir = TQChar::DirR;
+ bidi.status.eor = TQChar::DirR;
+ }
+ } else {
+ bidi.eor = bidi.current; bidi.status.eor = TQChar::DirR;
+ }
+ default:
+ break;
+ }
+ bidi.status.lastStrong = dirCurrent;
+ break;
+
+ // weak types:
+
+ case TQChar::DirNSM:
+ // ### if @sor, set dir to dirSor
+ break;
+ case TQChar::DirEN:
+ if(!(bidi.status.lastStrong == TQChar::DirAL)) {
+ // if last strong was AL change EN to AN
+ if(dir == TQChar::DirON) {
+ dir = TQChar::DirL;
+ }
+ switch(bidi.status.last)
+ {
+ case TQChar::DirET:
+ if ( bidi.status.lastStrong == TQChar::DirR || bidi.status.lastStrong == TQChar::DirAL ) {
+ appendRun( bidi );
+ dir = TQChar::DirEN;
+ bidi.status.eor = TQChar::DirEN;
+ }
+ // fall through
+ case TQChar::DirEN:
+ case TQChar::DirL:
+ bidi.eor = bidi.current;
+ bidi.status.eor = dirCurrent;
+ break;
+ case TQChar::DirR:
+ case TQChar::DirAL:
+ case TQChar::DirAN:
+ appendRun( bidi );
+ bidi.status.eor = TQChar::DirEN;
+ dir = TQChar::DirEN; break;
+ case TQChar::DirES:
+ case TQChar::DirCS:
+ if(bidi.status.eor == TQChar::DirEN) {
+ bidi.eor = bidi.current; break;
+ }
+ case TQChar::DirBN:
+ case TQChar::DirB:
+ case TQChar::DirS:
+ case TQChar::DirWS:
+ case TQChar::DirON:
+ if(bidi.status.eor == TQChar::DirR) {
+ // neutrals go to R
+ bidi.eor = bidi.last;
+ appendRun( bidi );
+ dir = TQChar::DirEN;
+ bidi.status.eor = TQChar::DirEN;
+ }
+ else if( bidi.status.eor == TQChar::DirL ||
+ (bidi.status.eor == TQChar::DirEN && bidi.status.lastStrong == TQChar::DirL)) {
+ bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ } else {
+ // numbers on both sides, neutrals get right to left direction
+ if(dir != TQChar::DirL) {
+ appendRun( bidi );
+ bidi.eor = bidi.last;
+ dir = TQChar::DirR;
+ appendRun( bidi );
+ dir = TQChar::DirEN;
+ bidi.status.eor = TQChar::DirEN;
+ } else {
+ bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ }
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ case TQChar::DirAN:
+ dirCurrent = TQChar::DirAN;
+ if(dir == TQChar::DirON) dir = TQChar::DirAN;
+ switch(bidi.status.last)
+ {
+ case TQChar::DirL:
+ case TQChar::DirAN:
+ bidi.eor = bidi.current; bidi.status.eor = TQChar::DirAN; break;
+ case TQChar::DirR:
+ case TQChar::DirAL:
+ case TQChar::DirEN:
+ appendRun( bidi );
+ dir = TQChar::DirAN; bidi.status.eor = TQChar::DirAN;
+ break;
+ case TQChar::DirCS:
+ if(bidi.status.eor == TQChar::DirAN) {
+ bidi.eor = bidi.current; break;
+ }
+ case TQChar::DirES:
+ case TQChar::DirET:
+ case TQChar::DirBN:
+ case TQChar::DirB:
+ case TQChar::DirS:
+ case TQChar::DirWS:
+ case TQChar::DirON:
+ if(bidi.status.eor == TQChar::DirR) {
+ // neutrals go to R
+ bidi.eor = bidi.last;
+ appendRun( bidi );
+ dir = TQChar::DirAN;
+ bidi.status.eor = TQChar::DirAN;
+ } else if( bidi.status.eor == TQChar::DirL ||
+ (bidi.status.eor == TQChar::DirEN && bidi.status.lastStrong == TQChar::DirL)) {
+ bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ } else {
+ // numbers on both sides, neutrals get right to left direction
+ if(dir != TQChar::DirL) {
+ appendRun( bidi );
+ bidi.eor = bidi.last;
+ dir = TQChar::DirR;
+ appendRun( bidi );
+ dir = TQChar::DirAN;
+ bidi.status.eor = TQChar::DirAN;
+ } else {
+ bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ }
+ }
+ default:
+ break;
+ }
+ break;
+ case TQChar::DirES:
+ case TQChar::DirCS:
+ break;
+ case TQChar::DirET:
+ if(bidi.status.last == TQChar::DirEN) {
+ dirCurrent = TQChar::DirEN;
+ bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
+ break;
+ }
+ break;
+
+ // boundary neutrals should be ignored
+ case TQChar::DirBN:
+ break;
+ // neutrals
+ case TQChar::DirB:
+ // ### what do we do with newline and paragraph seperators that come to here?
+ break;
+ case TQChar::DirS:
+ // ### implement rule L1
+ break;
+ case TQChar::DirWS:
+ break;
+ case TQChar::DirON:
+ break;
+ default:
+ break;
+ }
+
+ //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << context->dir << endl;
+
+ if(bidi.current.atEnd()) break;
+
+ // set status.last as needed.
+ switch(dirCurrent)
+ {
+ case TQChar::DirET:
+ case TQChar::DirES:
+ case TQChar::DirCS:
+ case TQChar::DirS:
+ case TQChar::DirWS:
+ case TQChar::DirON:
+ switch(bidi.status.last)
+ {
+ case TQChar::DirL:
+ case TQChar::DirR:
+ case TQChar::DirAL:
+ case TQChar::DirEN:
+ case TQChar::DirAN:
+ bidi.status.last = dirCurrent;
+ break;
+ default:
+ bidi.status.last = TQChar::DirON;
+ }
+ break;
+ case TQChar::DirNSM:
+ case TQChar::DirBN:
+ // ignore these
+ break;
+ case TQChar::DirEN:
+ if ( bidi.status.last == TQChar::DirL ) {
+ break;
+ }
+ // fall through
+ default:
+ bidi.status.last = dirCurrent;
+ }
+#endif
+
+ if ( atEnd ) break;
+ bidi.last = bidi.current;
+
+ if ( emptyRun ) {
+ bidi.sor = bidi.current;
+ bidi.eor = bidi.current;
+ emptyRun = false;
+ }
+
+ // this causes the operator ++ to open and close embedding levels as needed
+ // for the CSS unicode-bidi property
+ adjustEmbedding = true;
+ bidi.current.increment( bidi );
+ adjustEmbedding = false;
+
+ if ( bidi.current == end ) {
+ if ( emptyRun )
+ break;
+ atEnd = true;
+ }
+ }
+
+#if BIDI_DEBUG > 0
+ kdDebug(6041) << "reached end of line current=" << current.obj << "/" << current.pos
+ << ", eor=" << eor.obj << "/" << eor.pos << endl;
+#endif
+ if ( !emptyRun && bidi.sor != bidi.current ) {
+ bidi.eor = bidi.last;
+ appendRun( bidi );
+ }
+
+ // reorder line according to run structure...
+
+ // first find highest and lowest levels
+ uchar levelLow = 128;
+ uchar levelHigh = 0;
+ BidiRun *r = sFirstBidiRun;
+ while ( r ) {
+ if ( r->level > levelHigh )
+ levelHigh = r->level;
+ if ( r->level < levelLow )
+ levelLow = r->level;
+ r = r->nextRun;
+ }
+
+ // implements reordering of the line (L2 according to Bidi spec):
+ // L2. From the highest level found in the text to the lowest odd level on each line,
+ // reverse any contiguous sequence of characters that are at that level or higher.
+
+ // reversing is only done up to the lowest odd level
+ if( !(levelLow%2) ) levelLow++;
+
+#if BIDI_DEBUG > 0
+ kdDebug(6041) << "lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl;
+ kdDebug(6041) << "logical order is:" << endl;
+ TQPtrListIterator<BidiRun> it2(runs);
+ BidiRun *r2;
+ for ( ; (r2 = it2.current()); ++it2 )
+ kdDebug(6041) << " " << r2 << " start=" << r2->start << " stop=" << r2->stop << " level=" << (uint)r2->level << endl;
+#endif
+
+ int count = sBidiRunCount - 1;
+
+ // do not reverse for visually ordered web sites
+ if(!style()->visuallyOrdered()) {
+ while(levelHigh >= levelLow) {
+ int i = 0;
+ BidiRun* currRun = sFirstBidiRun;
+ while ( i < count ) {
+ while(i < count && currRun && currRun->level < levelHigh) {
+ i++;
+ currRun = currRun->nextRun;
+ }
+ int start = i;
+ while(i <= count && currRun && currRun->level >= levelHigh) {
+ i++;
+ currRun = currRun->nextRun;
+ }
+ int end = i-1;
+ reverseRuns(start, end);
+ }
+ levelHigh--;
+ }
+ }
+
+#if BIDI_DEBUG > 0
+ kdDebug(6041) << "visual order is:" << endl;
+ for (BidiRun* curr = sFirstRun; curr; curr = curr->nextRun)
+ kdDebug(6041) << " " << curr << endl;
+#endif
+}
+
+void RenderBlock::layoutInlineChildren(bool relayoutChildren, int breakBeforeLine)
+{
+ BidiState bidi;
+
+ m_overflowHeight = 0;
+
+ invalidateVerticalPositions();
+#ifdef DEBUG_LAYOUT
+ TQTime qt;
+ qt.start();
+ kdDebug( 6040 ) << renderName() << " layoutInlineChildren( " << this <<" )" << endl;
+#endif
+#if BIDI_DEBUG > 1 || defined( DEBUG_LINEBREAKS )
+ kdDebug(6041) << " ------- bidi start " << this << " -------" << endl;
+#endif
+
+ m_height = borderTop() + paddingTop();
+ int toAdd = borderBottom() + paddingBottom();
+ if (m_layer && scrollsOverflowX() && style()->height().isVariable())
+ toAdd += m_layer->horizontalScrollbarHeight();
+
+ // Clear out our line boxes.
+ deleteInlineBoxes();
+
+ // Text truncation only kicks in if your overflow isn't visible and your
+ // text-overflow-mode isn't clip.
+ bool hasTextOverflow = style()->textOverflow() && hasOverflowClip();
+
+ // Walk all the lines and delete our ellipsis line boxes if they exist.
+ if (hasTextOverflow)
+ deleteEllipsisLineBoxes();
+
+ if (firstChild()) {
+ // layout replaced elements
+ RenderObject *o = first( this, bidi, false );
+ while ( o ) {
+ if (o->markedForRepaint()) {
+ o->repaintDuringLayout();
+ o->setMarkedForRepaint(false);
+ }
+ if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
+ // clear the placeHolderBox
+ if (o->isBox())
+ static_cast<RenderBox*>(o)->RenderBox::deleteInlineBoxes();
+
+ //kdDebug(6041) << "layouting replaced or floating child" << endl;
+ if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
+ o->setChildNeedsLayout(true, false);
+ if (o->isPositioned())
+ o->containingBlock()->insertPositionedObject(o);
+ else
+ o->layoutIfNeeded();
+ }
+ else {
+ o->deleteInlineBoxes();
+ o->setNeedsLayout(false);
+ }
+ o = Bidinext( this, o, bidi, false );
+ }
+
+ BidiContext *startEmbed;
+ if( style()->direction() == LTR ) {
+ startEmbed = new BidiContext( 0, TQChar::DirL );
+ bidi.status.eor = TQChar::DirL;
+ } else {
+ startEmbed = new BidiContext( 1, TQChar::DirR );
+ bidi.status.eor = TQChar::DirR;
+ }
+ startEmbed->ref();
+
+ bidi.status.lastStrong = TQChar::DirON;
+ bidi.status.last = TQChar::DirON;
+
+ bidi.context = startEmbed;
+ adjustEmbedding = true;
+ BidiIterator start(this, first(this, bidi), 0);
+ adjustEmbedding = false;
+ BidiIterator end = start;
+
+ m_firstLine = true;
+
+ if (!smidpoints)
+ smidpoints = new TQMemArray<BidiIterator>;
+
+ sNumMidpoints = 0;
+ sCurrMidpoint = 0;
+ sCompactFirstBidiRun = sCompactLastBidiRun = 0;
+ sCompactBidiRunCount = 0;
+
+ previousLineBrokeAtBR = true;
+
+ int lineCount = 0;
+ bool pagebreakHint = false;
+ int oldPos = 0;
+ BidiIterator oldStart;
+ BidiState oldBidi;
+ const bool pagedMode = canvas()->pagedMode();
+//
+ while( !end.atEnd() ) {
+ start = end;
+ lineCount++;
+ betweenMidpoints = false;
+ isLineEmpty = true;
+ pagebreakHint = false;
+ if (pagedMode) {
+ oldPos = m_height;
+ oldStart = start;
+ oldBidi = bidi;
+ }
+ if (lineCount == breakBeforeLine) {
+ m_height = pageTopAfter(oldPos);
+ pagebreakHint = true;
+ }
+redo_linebreak:
+ end = findNextLineBreak(start, bidi);
+ if( start.atEnd() ) break;
+ if (!isLineEmpty) {
+ bidiReorderLine(start, end, bidi);
+
+ // Now that the runs have been ordered, we create the line boxes.
+ // At the same time we figure out where border/padding/margin should be applied for
+ // inline flow boxes.
+
+ if (sBidiRunCount) {
+ InlineFlowBox* lineBox = constructLine(start, end);
+ if (lineBox) {
+ if (pagebreakHint) lineBox->setAfterPageBreak(true);
+
+ // Now we position all of our text runs horizontally.
+ computeHorizontalPositionsForLine(lineBox, bidi);
+
+ // Now position our text runs vertically.
+ computeVerticalPositionsForLine(lineBox);
+
+ deleteBidiRuns(renderArena());
+
+ if (lineBox->afterPageBreak() && hasFloats() && !pagebreakHint) {
+ start = end = oldStart;
+ bidi = oldBidi;
+ m_height = pageTopAfter(oldPos);
+ deleteLastLineBox(renderArena());
+ pagebreakHint = true;
+ goto redo_linebreak;
+ }
+ }
+ }
+
+ if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
+ adjustEmbedding = true;
+ end.increment(bidi);
+ adjustEmbedding = false;
+ } else if (end.obj && end.obj->style()->preserveLF() && end.current() == TQChar('\n')) {
+ adjustEmbedding = true;
+ end.increment(bidi);
+ adjustEmbedding = false;
+ }
+
+ m_firstLine = false;
+ newLine();
+ }
+
+ sNumMidpoints = 0;
+ sCurrMidpoint = 0;
+ sCompactFirstBidiRun = sCompactLastBidiRun = 0;
+ sCompactBidiRunCount = 0;
+ }
+ startEmbed->deref();
+ //embed->deref();
+ }
+
+ sNumMidpoints = 0;
+ sCurrMidpoint = 0;
+
+ // If we violate widows page-breaking rules, we set a hint and relayout.
+ // Note that the widows rule might still be violated afterwards if the lines have become wider
+ if (canvas()->pagedMode() && containsPageBreak() && breakBeforeLine == 0)
+ {
+ int orphans = 0;
+ int widows = 0;
+ // find breaking line
+ InlineRunBox* lineBox = firstLineBox();
+ while (lineBox) {
+ if (lineBox->isInlineFlowBox()) {
+ InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(lineBox);
+ if (flowBox->afterPageBreak()) break;
+ }
+ orphans++;
+ lineBox = lineBox->nextLineBox();
+ }
+ InlineFlowBox* pageBreaker = static_cast<InlineFlowBox*>(lineBox);
+ if (!pageBreaker) goto no_break;
+ // count widows
+ while (lineBox && widows < style()->widows()) {
+ if (lineBox->hasTextChildren())
+ widows++;
+ lineBox = lineBox->nextLineBox();
+ }
+ // Widows rule broken and more orphans left to use
+ if (widows < style()->widows() && orphans > 0) {
+ kdDebug( 6040 ) << "Widows: " << widows << endl;
+ // Check if we have enough orphans after respecting widows count
+ int newOrphans = orphans - (style()->widows() - widows);
+ if (newOrphans < style()->orphans()) {
+ if (parent()->canClear(this,PageBreakHarder)) {
+ // Relayout to remove incorrect page-break
+ setNeedsPageClear(true);
+ setContainsPageBreak(false);
+ layoutInlineChildren(relayoutChildren, -1);
+ return;
+ }
+ } else {
+ // Set hint and try again
+ layoutInlineChildren(relayoutChildren, newOrphans+1);
+ return;
+ }
+ }
+ }
+ no_break:
+
+ // in case we have a float on the last line, it might not be positioned up to now.
+ // This has to be done before adding in the bottom border/padding, or the float will
+ // include the padding incorrectly. -dwh
+ positionNewFloats();
+
+ // Now add in the bottom border/padding.
+ m_height += toAdd;
+
+ // Always make sure this is at least our height.
+ m_overflowHeight = kMax(m_height, m_overflowHeight);
+
+ // See if any lines spill out of the block. If so, we need to update our overflow width.
+ checkLinesForOverflow();
+
+ // See if we have any lines that spill out of our block. If we do, then we will
+ // possibly need to truncate text.
+ if (hasTextOverflow)
+ checkLinesForTextOverflow();
+
+#if BIDI_DEBUG > 1
+ kdDebug(6041) << " ------- bidi end " << this << " -------" << endl;
+#endif
+ //kdDebug() << "RenderBlock::layoutInlineChildren time used " << qt.elapsed() << endl;
+ //kdDebug(6040) << "height = " << m_height <<endl;
+}
+
+static void setStaticPosition( RenderBlock* p, RenderObject *o, bool *needToSetStaticX = 0, bool *needToSetStaticY = 0 )
+{
+ // If our original display wasn't an inline type, then we can
+ // determine our static x position now.
+ bool nssx, nssy;
+ bool isInlineType = o->style()->isOriginalDisplayInlineType();
+ nssx = o->hasStaticX();
+ if (nssx && !isInlineType && o->isBox()) {
+ static_cast<RenderBox*>(o)->setStaticX(o->parent()->style()->direction() == LTR ?
+ p->borderLeft()+p->paddingLeft() :
+ p->borderRight()+p->paddingRight());
+ nssx = false;
+ }
+
+ // If our original display was an INLINE type, then we can
+ // determine our static y position now.
+ nssy = o->hasStaticY();
+ if (nssy && o->isBox()) {
+ static_cast<RenderBox*>(o)->setStaticY(p->height());
+ nssy = !isInlineType;
+ }
+ if (needToSetStaticX) *needToSetStaticX = nssx;
+ if (needToSetStaticY) *needToSetStaticY = nssy;
+}
+
+BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
+{
+ int width = lineWidth(m_height);
+ int w = 0;
+ int tmpW = 0;
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "findNextLineBreak: line at " << m_height << " line width " << width << endl;
+ kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
+#endif
+
+ BidiIterator posStart = start;
+ bool hadPosStart = false;
+
+ // eliminate spaces at beginning of line
+ // remove leading spaces. Any inline flows we encounter will be empty and should also
+ // be skipped.
+ while (!start.atEnd() && (start.obj->isInlineFlow() || (!start.obj->style()->preserveWS() && !start.obj->isBR() &&
+#ifndef QT_NO_UNICODETABLES
+ ( (start.current().unicode() == (ushort)0x0020) || // ASCII space
+ (start.current().unicode() == (ushort)0x0009) || // ASCII tab
+ (start.current().unicode() == (ushort)0x000A) || // ASCII line feed
+ (start.current().unicode() == (ushort)0x000C) || // ASCII form feed
+ (start.current().unicode() == (ushort)0x200B) || // Zero-width space
+ start.obj->isFloatingOrPositioned() )
+#else
+ ( start.current() == ' ' || start.current() == '\n' || start.obj->isFloatingOrPositioned() )
+#endif
+ ))) {
+ if( start.obj->isFloatingOrPositioned() ) {
+ RenderObject *o = start.obj;
+ // add to special objects...
+ if (o->isFloating()) {
+ insertFloatingObject(o);
+ positionNewFloats();
+ width = lineWidth(m_height);
+ }
+ else if (o->isBox() && o->isPositioned()) {
+ if (!hadPosStart) {
+ hadPosStart = true;
+ posStart = start;
+ // end
+ addMidpoint(BidiIterator(0, o, 0));
+ } else {
+ // start/end
+ addMidpoint(BidiIterator(0, o, 0));
+ addMidpoint(BidiIterator(0, o, 0));
+ }
+ setStaticPosition(this, o);
+ }
+ }
+ adjustEmbedding = true;
+ start.increment(bidi, false /*skipInlines*/);
+ adjustEmbedding = false;
+ }
+
+ if (hadPosStart && !start.atEnd())
+ addMidpoint(start);
+
+ if ( start.atEnd() ){
+ if (hadPosStart) {
+ start = posStart;
+ posStart.increment(bidi);
+ return posStart;
+ }
+ return start;
+ }
+
+ // This variable says we have encountered an object after which initial whitespace should be ignored (e.g. InlineFlows at the begining of a line).
+ // Either we have nothing to do, if there is no whitespace after the object... or we have to enter the ignoringSpaces state.
+ // This dilemma will be resolved when we have a peek at the next object.
+ bool checkShouldIgnoreInitialWhitespace = false;
+
+ // This variable is used only if whitespace isn't set to PRE, and it tells us whether
+ // or not we are currently ignoring whitespace.
+ bool ignoringSpaces = false;
+ BidiIterator ignoreStart;
+
+ // This variable tracks whether the very last character we saw was a space. We use
+ // this to detect when we encounter a second space so we know we have to terminate
+ // a run.
+ bool currentCharacterIsSpace = false;
+ RenderObject* trailingSpaceObject = 0;
+
+ BidiIterator lBreak = start;
+
+ InlineMinMaxIterator it(start.par, start.obj, start.endOfInline, false /*skipPositioned*/);
+ InlineMinMaxIterator lastIt = it;
+ int pos = start.pos;
+
+ bool prevLineBrokeCleanly = previousLineBrokeAtBR;
+ previousLineBrokeAtBR = false;
+
+ RenderObject* o = it.current;
+ while( o ) {
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "new object "<< o <<" width = " << w <<" tmpw = " << tmpW << endl;
+#endif
+ if(o->isBR()) {
+ if( w + tmpW <= width ) {
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ lBreak.endOfInline = it.endOfInline;
+
+ // A <br> always breaks a line, so don't let the line be collapsed
+ // away. Also, the space at the end of a line with a <br> does not
+ // get collapsed away. It only does this if the previous line broke
+ // cleanly. Otherwise the <br> has no effect on whether the line is
+ // empty or not.
+ if (prevLineBrokeCleanly)
+ isLineEmpty = false;
+ trailingSpaceObject = 0;
+ previousLineBrokeAtBR = true;
+
+ if (!isLineEmpty) {
+ // only check the clear status for non-empty lines.
+ EClear clear = o->style()->clear();
+ if(clear != CNONE)
+ m_clearStatus = (EClear) (m_clearStatus | clear);
+ }
+ }
+ goto end;
+ }
+ if( o->isFloatingOrPositioned() ) {
+ // add to special objects...
+ if(o->isFloating()) {
+ insertFloatingObject(o);
+ // check if it fits in the current line.
+ // If it does, position it now, otherwise, position
+ // it after moving to next line (in newLine() func)
+ if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
+ positionNewFloats();
+ width = lineWidth(m_height);
+ }
+ }
+ else if (o->isPositioned()) {
+ bool needToSetStaticX;
+ bool needToSetStaticY;
+ setStaticPosition(this, o, &needToSetStaticX, &needToSetStaticY);
+
+ // If we're ignoring spaces, we have to stop and include this object and
+ // then start ignoring spaces again.
+ if (needToSetStaticX || needToSetStaticY) {
+ trailingSpaceObject = 0;
+ ignoreStart.obj = o;
+ ignoreStart.pos = 0;
+ if (ignoringSpaces) {
+ addMidpoint(ignoreStart); // Stop ignoring spaces.
+ addMidpoint(ignoreStart); // Start ignoring again.
+ }
+ }
+ }
+ } else if (o->isInlineFlow()) {
+ tmpW += getBorderPaddingMargin(o, it.endOfInline);
+ if (isLineEmpty) isLineEmpty = !tmpW;
+ if (o->isWordBreak()) { // #### shouldn't be an InlineFlow!
+ w += tmpW;
+ tmpW = 0;
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ lBreak.endOfInline = it.endOfInline;
+ } else if (!it.endOfInline) {
+ // this is the beginning of the line (other non-initial inline flows are handled directly when
+ // incrementing the iterator below). We want to skip initial whitespace as much as possible.
+ checkShouldIgnoreInitialWhitespace = true;
+ }
+ } else if ( o->isReplaced() || o->isGlyph() ) {
+ EWhiteSpace currWS = o->style()->whiteSpace();
+ EWhiteSpace lastWS = lastIt.current->style()->whiteSpace();
+
+ // WinIE marquees have different whitespace characteristics by default when viewed from
+ // the outside vs. the inside. Text inside is NOWRAP, and so we altered the marquee's
+ // style to reflect this, but we now have to get back to the original whitespace value
+ // for the marquee when checking for line breaking.
+ if (o->isHTMLMarquee() && o->layer() && o->layer()->marquee())
+ currWS = o->layer()->marquee()->whiteSpace();
+ if (lastIt.current->isHTMLMarquee() && lastIt.current->layer() && lastIt.current->layer()->marquee())
+ lastWS = lastIt.current->layer()->marquee()->whiteSpace();
+
+ // Break on replaced elements if either has normal white-space.
+ if (currWS == NORMAL || lastWS == NORMAL) {
+ w += tmpW;
+ tmpW = 0;
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ lBreak.endOfInline = false;
+ }
+
+ tmpW += o->width()+o->marginLeft()+o->marginRight();
+ if (ignoringSpaces) {
+ BidiIterator startMid( 0, o, 0 );
+ addMidpoint(startMid);
+ }
+ isLineEmpty = false;
+ ignoringSpaces = false;
+ currentCharacterIsSpace = false;
+ trailingSpaceObject = 0;
+
+ if (o->isListMarker() && o->style()->listStylePosition() == OUTSIDE) {
+ checkShouldIgnoreInitialWhitespace = true;
+ }
+ } else if ( o->isText() ) {
+ RenderText *t = static_cast<RenderText *>(o);
+ int strlen = t->stringLength();
+ int len = strlen - pos;
+ TQChar *str = t->text();
+
+ const Font *f = t->htmlFont( m_firstLine );
+ // proportional font, needs a bit more work.
+ int lastSpace = pos;
+ bool autoWrap = o->style()->autoWrap();
+ bool preserveWS = o->style()->preserveWS();
+ bool preserveLF = o->style()->preserveLF();
+#ifdef APPLE_CHANGES
+ int wordSpacing = o->style()->wordSpacing();
+#endif
+ bool nextIsSoftBreakable = false;
+ bool checkBreakWord = autoWrap && (o->style()->wordWrap() == WWBREAKWORD);
+
+ while(len) {
+ bool previousCharacterIsSpace = currentCharacterIsSpace;
+ bool isSoftBreakable = nextIsSoftBreakable;
+ nextIsSoftBreakable = false;
+ const TQChar c = str[pos];
+ currentCharacterIsSpace = c == ' ';
+ checkBreakWord &= !w; // only break words when no other breaking opportunity exists earlier
+ // on the line (even within the text object we are currently processing)
+
+ if (preserveWS || !currentCharacterIsSpace)
+ isLineEmpty = false;
+
+ // Check for soft hyphens. Go ahead and ignore them.
+ if (c.unicode() == SOFT_HYPHEN && pos > 0) {
+ nextIsSoftBreakable = true;
+ if (!ignoringSpaces) {
+ // Ignore soft hyphens
+ BidiIterator endMid(0, o, pos-1);
+ addMidpoint(endMid);
+
+ // Add the width up to but not including the hyphen.
+ tmpW += t->width(lastSpace, pos - lastSpace, f);
+
+ // For wrapping text only, include the hyphen. We need to ensure it will fit
+ // on the line if it shows when we break.
+ if (o->style()->autoWrap())
+ tmpW += t->width(pos, 1, f);
+
+ BidiIterator startMid(0, o, pos+1);
+ addMidpoint(startMid);
+ }
+
+ pos++;
+ len--;
+ lastSpace = pos; // Cheesy hack to prevent adding in widths of the run twice.
+ continue;
+ }
+#ifdef APPLE_CHANGES // KDE applies wordspacing differently
+ bool applyWordSpacing = false;
+#endif
+ if (ignoringSpaces) {
+ // We need to stop ignoring spaces, if we encounter a non-space or
+ // a run that doesn't collapse spaces.
+ if (!currentCharacterIsSpace || preserveWS) {
+ // Stop ignoring spaces and begin at this
+ // new point.
+ ignoringSpaces = false;
+ lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
+ BidiIterator startMid ( 0, o, pos );
+ addMidpoint(startMid);
+ }
+ else {
+ // Just keep ignoring these spaces.
+ pos++;
+ len--;
+ continue;
+ }
+ }
+
+ const bool isbreakablePosition = (preserveLF && c == '\n') || (autoWrap &&
+ (isBreakable( str, pos, strlen ) || isSoftBreakable));
+ if ( isbreakablePosition || checkBreakWord ) {
+
+ tmpW += t->width(lastSpace, pos - lastSpace, f);
+#ifdef APPLE_CHANGES
+ applyWordSpacing = (wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace &&
+ !t->containsOnlyWhitespace(pos+1, strlen-(pos+1)));
+#endif
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "found space at " << pos << " in string '" << TQString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
+#endif
+ if ( autoWrap && w + tmpW > width && w == 0 ) {
+ int fb = nearestFloatBottom(m_height);
+ int newLineWidth = lineWidth(fb);
+ // See if |tmpW| will fit on the new line. As long as it does not,
+ // keep adjusting our float bottom until we find some room.
+ int lastFloatBottom = m_height;
+ while (lastFloatBottom < fb && tmpW > newLineWidth) {
+ lastFloatBottom = fb;
+ fb = nearestFloatBottom(fb);
+ newLineWidth = lineWidth(fb);
+ }
+
+ if(!w && m_height < fb && width < newLineWidth) {
+ m_height = fb;
+ width = newLineWidth;
+#ifdef DEBUG_LINEBREAKS
+ kdDebug() << "RenderBlock::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
+#endif
+ }
+ }
+
+ if (autoWrap) {
+ if (w+tmpW > width) {
+ if (checkBreakWord && pos) {
+ lBreak.obj = o;
+ lBreak.pos = pos-1;
+ lBreak.endOfInline = false;
+ }
+ goto end;
+ } else if ( (pos > 1 && str[pos-1].unicode() == SOFT_HYPHEN) )
+ // Subtract the width of the soft hyphen out since we fit on a line.
+ tmpW -= t->width(pos-1, 1, f);
+ }
+
+ if( preserveLF && *(str+pos) == '\n' ) {
+ lBreak.obj = o;
+ lBreak.pos = pos;
+ lBreak.endOfInline = false;
+
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
+#endif
+ return lBreak;
+ }
+
+ if ( autoWrap && isbreakablePosition ) {
+ w += tmpW;
+ tmpW = 0;
+ lBreak.obj = o;
+ lBreak.pos = pos;
+ lBreak.endOfInline = false;
+ }
+
+ lastSpace = pos;
+#ifdef APPLE_CHANGES
+ if (applyWordSpacing)
+ w += wordSpacing;
+#endif
+ }
+
+ if (!ignoringSpaces && !preserveWS) {
+ // If we encounter a second space, we need to go ahead and break up this run
+ // and enter a mode where we start collapsing spaces.
+ if (currentCharacterIsSpace && previousCharacterIsSpace) {
+ ignoringSpaces = true;
+
+ // We just entered a mode where we are ignoring
+ // spaces. Create a midpoint to terminate the run
+ // before the second space.
+ addMidpoint(ignoreStart);
+ lastSpace = pos;
+ }
+ }
+
+ if (currentCharacterIsSpace && !previousCharacterIsSpace) {
+ ignoreStart.obj = o;
+ ignoreStart.pos = pos;
+ }
+
+ if (!preserveWS && currentCharacterIsSpace && !ignoringSpaces)
+ trailingSpaceObject = o;
+ else if (preserveWS || !currentCharacterIsSpace)
+ trailingSpaceObject = 0;
+
+ pos++;
+ len--;
+ }
+
+ if (!ignoringSpaces) {
+ // We didn't find any space that would be beyond the line |width|.
+ // Lets add to |tmpW| the remaining width since the last space we found.
+ // Before we test this new |tmpW| however, we will have to look ahead to check
+ // if the next object/position can serve as a line breaking opportunity.
+ tmpW += t->width(lastSpace, pos - lastSpace, f);
+ if (checkBreakWord && !w && pos && tmpW > width) {
+ // Avoid doing the costly lookahead for break-word,
+ // since we know we are allowed to break.
+ lBreak.obj = o;
+ lBreak.pos = pos-1;
+ lBreak.endOfInline = false;
+ goto end;
+ }
+ }
+ } else
+ KHTMLAssert( false );
+
+ InlineMinMaxIterator savedIt = lastIt;
+ lastIt = it;
+ o = it.next();
+
+ // advance the iterator to the next non-inline-flow
+ while (o && o->isInlineFlow() && !o->isWordBreak()) {
+ tmpW += getBorderPaddingMargin(o, it.endOfInline);
+ if (isLineEmpty) isLineEmpty = !tmpW;
+ o = it.next();
+ }
+
+ if (checkShouldIgnoreInitialWhitespace) {
+ // Check if we should switch to ignoringSpaces state
+ if (!style()->preserveWS() && it.current && it.current->isText()) {
+ const RenderText* rt = static_cast<RenderText*>(it.current);
+ if (rt->stringLength() > 0 && (rt->text()[0].category() == TQChar::Separator_Space || rt->text()[0] == '\n')) {
+ currentCharacterIsSpace = true;
+ ignoringSpaces = true;
+ BidiIterator endMid( 0, lastIt.current, 0 );
+ addMidpoint(endMid);
+ }
+ }
+ checkShouldIgnoreInitialWhitespace = false;
+ }
+
+ bool autoWrap = lastIt.current->style()->autoWrap();
+ bool checkForBreak = autoWrap;
+ if (w && w + tmpW > width && lBreak.obj && !lastIt.current->style()->preserveLF() && !autoWrap)
+ checkForBreak = true;
+ else if (it.current && lastIt.current->isText() && it.current->isText() && !it.current->isBR()) {
+ if (autoWrap || it.current->style()->autoWrap()) {
+ if (currentCharacterIsSpace)
+ checkForBreak = true;
+ else {
+ checkForBreak = false;
+ RenderText* nextText = static_cast<RenderText*>(it.current);
+ if (nextText->stringLength() != 0) {
+ TQChar c = nextText->text()[0];
+ if (c == ' ' || c == '\t' || (c == '\n' && !it.current->style()->preserveLF())) {
+ // If the next item on the line is text, and if we did not end with
+ // a space, then the next text run continues our word (and so it needs to
+ // keep adding to |tmpW|. Just update and continue.
+ checkForBreak = true;
+ }
+ }
+
+ bool canPlaceOnLine = (w + tmpW <= width) || !autoWrap;
+ if (canPlaceOnLine && checkForBreak) {
+ w += tmpW;
+ tmpW = 0;
+ lBreak.obj = it.current;
+ lBreak.pos = 0;
+ lBreak.endOfInline = it.endOfInline;
+ }
+ }
+ }
+ }
+
+ if (checkForBreak && (w + tmpW > width)) {
+ //kdDebug() << " too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
+ //kdDebug() << "start=" << start.obj << " current=" << o << endl;
+ // if we have floats, try to get below them.
+ if (currentCharacterIsSpace && !ignoringSpaces && !lastIt.current->style()->preserveWS())
+ trailingSpaceObject = 0;
+
+ int fb = nearestFloatBottom(m_height);
+ int newLineWidth = lineWidth(fb);
+ // See if |tmpW| will fit on the new line. As long as it does not,
+ // keep adjusting our float bottom until we find some room.
+ int lastFloatBottom = m_height;
+ while (lastFloatBottom < fb && tmpW > newLineWidth) {
+ lastFloatBottom = fb;
+ fb = nearestFloatBottom(fb);
+ newLineWidth = lineWidth(fb);
+ }
+ if( !w && m_height < fb && width < newLineWidth ) {
+ m_height = fb;
+ width = newLineWidth;
+#ifdef DEBUG_LINEBREAKS
+ kdDebug() << "RenderBlock::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
+#endif
+ }
+
+ // |width| may have been adjusted because we got shoved down past a float (thus
+ // giving us more room), so we need to retest, and only jump to
+ // the end label if we still don't fit on the line. -dwh
+ if (w + tmpW > width) {
+ it = lastIt;
+ lastIt = savedIt;
+ o = it.current;
+ goto end;
+ }
+ }
+
+ if (!lastIt.current->isFloatingOrPositioned() && lastIt.current->isReplaced() && lastIt.current->style()->autoWrap()) {
+ // Go ahead and add in tmpW.
+ w += tmpW;
+ tmpW = 0;
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ lBreak.endOfInline = it.endOfInline;
+ }
+
+ // Clear out our character space bool, since inline <pre>s don't collapse whitespace
+ // with adjacent inline normal/nowrap spans.
+ if (lastIt.current->style()->preserveWS())
+ currentCharacterIsSpace = false;
+
+ pos = 0;
+ }
+
+#ifdef DEBUG_LINEBREAKS
+ kdDebug( 6041 ) << "end of par, width = " << width << " linewidth = " << w + tmpW << endl;
+#endif
+ if( w + tmpW <= width || (lastIt.current && !lastIt.current->style()->autoWrap())) {
+ lBreak.obj = 0;
+ lBreak.pos = 0;
+ lBreak.endOfInline = false;
+ }
+
+ end:
+
+ if( lBreak == start && !lBreak.obj->isBR() ) {
+ // we just add as much as possible
+ if ( style()->whiteSpace() == PRE ) {
+ // FIXME: Don't really understand this case.
+ if(pos != 0) {
+ lBreak.obj = o;
+ lBreak.pos = pos - 1;
+ lBreak.endOfInline = it.endOfInline;
+ } else {
+ lBreak.obj = lastIt.current;
+ lBreak.pos = lastIt.current->isText() ? lastIt.current->length() : 0;
+ lBreak.endOfInline = lastIt.endOfInline;
+ }
+ } else if( lBreak.obj ) {
+ if( lastIt.current != o ) {
+ // better to break between object boundaries than in the middle of a word
+ lBreak.obj = o;
+ lBreak.pos = 0;
+ lBreak.endOfInline = it.endOfInline;
+ } else {
+ // Don't ever break in the middle of a word if we can help it.
+ // There's no room at all. We just have to be on this line,
+ // even though we'll spill out.
+ lBreak.obj = o;
+ lBreak.pos = pos;
+ lBreak.endOfInline = it.endOfInline;
+ }
+ }
+ }
+
+ if (hadPosStart)
+ start = posStart;
+
+ // make sure we consume at least one char/object.
+ // and avoid returning an InlineFlow
+ // (FIXME: turn those wordbreaks into empty text objects - they shouldn't be inline flows!)
+ if( lBreak == start || (lBreak.obj && lBreak.obj->isInlineFlow() && !lBreak.obj->isWordBreak())) {
+ lBreak.increment(bidi);
+ }
+
+#ifdef DEBUG_LINEBREAKS
+ kdDebug(6041) << "regular break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
+#endif
+
+ // Sanity check our midpoints.
+ checkMidpoints(lBreak, bidi);
+
+ if (trailingSpaceObject) {
+ // This object is either going to be part of the last midpoint, or it is going
+ // to be the actual endpoint. In both cases we just decrease our pos by 1 level to
+ // exclude the space, allowing it to - in effect - collapse into the newline.
+ if (sNumMidpoints%2==1) {
+ BidiIterator* midpoints = smidpoints->data();
+ midpoints[sNumMidpoints-1].pos--;
+ }
+ //else if (lBreak.pos > 0)
+ // lBreak.pos--;
+ else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
+ // Add a new end midpoint that stops right at the very end.
+ RenderText* text = static_cast<RenderText *>(trailingSpaceObject);
+ unsigned pos = text->length() >=2 ? text->length() - 2 : UINT_MAX;
+ BidiIterator endMid ( 0, trailingSpaceObject, pos );
+ addMidpoint(endMid);
+ }
+ }
+
+ // We might have made lBreak an iterator that points past the end
+ // of the object. Do this adjustment to make it point to the start
+ // of the next object instead to avoid confusing the rest of the
+ // code.
+ if (lBreak.pos > 0) {
+ lBreak.pos--;
+ lBreak.increment(bidi);
+ }
+
+ if (lBreak.obj && lBreak.pos >= 2 && lBreak.obj->isText()) {
+ // For soft hyphens on line breaks, we have to chop out the midpoints that made us
+ // ignore the hyphen so that it will render at the end of the line.
+ TQChar c = static_cast<RenderText*>(lBreak.obj)->text()[lBreak.pos-1];
+ if (c.unicode() == SOFT_HYPHEN)
+ chopMidpointsAt(lBreak.obj, lBreak.pos-2);
+ }
+
+ return lBreak;
+}
+
+void RenderBlock::checkLinesForOverflow()
+{
+ for (RootInlineBox* curr = static_cast<tdehtml::RootInlineBox*>(firstLineBox()); curr; curr = static_cast<tdehtml::RootInlineBox*>(curr->nextLineBox())) {
+// m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);
+ m_overflowTop = kMin(curr->topOverflow(), m_overflowTop);
+// m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth);
+ m_overflowHeight = kMax(curr->bottomOverflow(), m_overflowHeight);
+ }
+}
+
+void RenderBlock::deleteEllipsisLineBoxes()
+{
+ for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
+ curr->clearTruncation();
+}
+
+void RenderBlock::checkLinesForTextOverflow()
+{
+ // Determine the width of the ellipsis using the current font.
+ TQChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable
+ static TQString ellipsisStr(ellipsis);
+ const Font& firstLineFont = style(true)->htmlFont();
+ const Font& font = style()->htmlFont();
+ int firstLineEllipsisWidth = firstLineFont.width(&ellipsis, 1, 0);
+ int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(&ellipsis, 1, 0);
+
+ // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
+ // if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
+ // check the left edge of the line box to see if it is less
+ // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
+ bool ltr = style()->direction() == LTR;
+ for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+ int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
+ int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
+ if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
+ // This line spills out of our box in the appropriate direction. Now we need to see if the line
+ // can be truncated. In order for truncation to be possible, the line must have sufficient space to
+ // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
+ // space.
+ int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
+ if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
+ curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width);
+ }
+ }
+}
+
+// For --enable-final
+#undef BIDI_DEBUG
+#undef DEBUG_LINEBREAKS
+#undef DEBUG_LAYOUT
+
+}
diff --git a/tdehtml/rendering/bidi.h b/tdehtml/rendering/bidi.h
new file mode 100644
index 000000000..ec926d99a
--- /dev/null
+++ b/tdehtml/rendering/bidi.h
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (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 BIDI_H
+#define BIDI_H
+
+#include <tqstring.h>
+#include "rendering/render_object.h"
+
+namespace tdehtml {
+ class RenderArena;
+ class RenderBlock;
+ class RenderObject;
+ class InlineBox;
+
+ class BidiContext {
+ public:
+ BidiContext(unsigned char level, TQChar::Direction embedding, BidiContext *parent = 0, bool override = false);
+ ~BidiContext();
+
+ void ref() const;
+ void deref() const;
+
+ unsigned char level;
+ bool override : 1;
+ TQChar::Direction dir : 5;
+ TQChar::Direction basicDir : 5;
+
+ BidiContext *parent;
+
+
+ // refcounting....
+ mutable int count;
+ };
+
+ struct BidiRun {
+ BidiRun(int _start, int _stop, RenderObject *_obj, BidiContext *context, TQChar::Direction dir)
+ : start( _start ), stop( _stop ), obj( _obj ), box(0), nextRun(0)
+ {
+ if(dir == TQChar::DirON) dir = context->dir;
+
+ level = context->level;
+
+ // add level of run (cases I1 & I2)
+ if( level % 2 ) {
+ if(dir == TQChar::DirL || dir == TQChar::DirAN || dir == TQChar::DirEN)
+ level++;
+ } else {
+ if( dir == TQChar::DirR )
+ level++;
+ else if( dir == TQChar::DirAN || dir == TQChar::DirEN)
+ level += 2;
+ }
+ }
+
+ void detach(RenderArena* renderArena);
+
+ // Overloaded new operator.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw();
+
+public:
+ int start;
+ int stop;
+
+ RenderObject *obj;
+ InlineBox* box;
+
+ // explicit + implicit levels here
+ uchar level;
+
+ bool compact : 1;
+
+ BidiRun* nextRun;
+ };
+
+ struct BidiIterator;
+ struct BidiState;
+
+ struct InlineMinMaxIterator
+ {
+ /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
+ inline min/max width calculations. Note the following about the way it walks:
+ (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
+ (2) We do not drill into the children of floats or replaced elements, since you can't break
+ in the middle of such an element.
+ (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
+ distinct borders/margin/padding that contribute to the min/max width.
+ */
+ RenderObject* parent;
+ RenderObject* current;
+ bool endOfInline;
+ bool skipPositioned;
+ InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool eOI=false, bool skipPos=true)
+ :parent(p), current(o), endOfInline(eOI), skipPositioned(skipPos) {}
+ inline RenderObject* next();
+ };
+
+ inline RenderObject* InlineMinMaxIterator::next()
+ {
+ RenderObject* result = 0;
+ bool oldEndOfInline = endOfInline;
+ endOfInline = false;
+ while (current != 0 || (current == parent))
+ {
+ //kDebug( 6040 ) << "current = " << current;
+ if (!oldEndOfInline &&
+ (current == parent ||
+ (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
+ result = current->firstChild();
+ if (!result) {
+ // We hit the end of our inline. (It was empty, e.g., <span></span>.)
+ if (!oldEndOfInline && current->isInlineFlow()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
+ while (current && current != parent) {
+ result = current->nextSibling();
+ if (result) break;
+ current = current->parent();
+ if (current && current != parent && current->isInlineFlow()) {
+ result = current;
+ endOfInline = true;
+ break;
+ }
+ }
+ }
+
+ if (!result) break;
+
+ if ((!skipPositioned || !result->isPositioned()) && (result->isText() || result->isBR() ||
+ result->isFloatingOrPositioned() || result->isReplaced() || result->isGlyph() || result->isInlineFlow()))
+ break;
+
+ current = result;
+ result = 0;
+ }
+
+ // Update our position.
+ current = result;
+ return current;
+ }
+
+}
+
+#endif
diff --git a/tdehtml/rendering/break_lines.cpp b/tdehtml/rendering/break_lines.cpp
new file mode 100644
index 000000000..e82787eb8
--- /dev/null
+++ b/tdehtml/rendering/break_lines.cpp
@@ -0,0 +1,126 @@
+#include <break_lines.h>
+#include <klibloader.h>
+#include "tqcstring.h"
+#include <tqtextcodec.h>
+#include <tqcleanuphandler.h>
+#include <config.h>
+
+
+/* If HAVE_LIBTHAI is defined, libtdehtml will link against
+ * libthai since compile time. Otherwise it will try to
+ * dlopen at run-time
+ *
+ * Ott Pattara Nov 14, 2004
+ */
+
+#ifndef HAVE_LIBTHAI
+typedef int (*th_brk_def)(const unsigned char*, int[], int);
+static th_brk_def th_brk;
+#else
+#include <thai/thailib.h>
+#include <thai/thbrk.h>
+#endif
+
+namespace tdehtml {
+ struct ThaiCache
+ {
+ ThaiCache() {
+ string = 0;
+ allocated = 0x400;
+ wbrpos = (int *) malloc(allocated*sizeof(int));
+ numwbrpos = 0;
+ numisbreakable = 0x400;
+ isbreakable = (int *) malloc(numisbreakable*sizeof(int));
+ library = 0;
+ }
+ ~ThaiCache() {
+ free(wbrpos);
+ free(isbreakable);
+ if (library) library->unload();
+ }
+ const TQChar *string;
+ int *wbrpos;
+ int *isbreakable;
+ int allocated;
+ int numwbrpos,numisbreakable;
+ KLibrary *library;
+ };
+ static ThaiCache *cache = 0;
+
+ void cleanup_thaibreaks()
+ {
+ delete cache;
+ cache = 0;
+#ifndef HAVE_LIBTHAI
+ th_brk = 0;
+#endif
+ }
+
+ bool isBreakableThai( const TQChar *string, const int pos, const int len)
+ {
+ static TQTextCodec *thaiCodec = TQTextCodec::codecForMib(2259);
+ //printf("Entering isBreakableThai with pos = %d\n", pos);
+
+#ifndef HAVE_LIBTHAI
+
+ KLibrary *lib = 0;
+
+ /* load libthai dynamically */
+ if (( !th_brk ) && thaiCodec ) {
+ printf("Try to load libthai dynamically...\n");
+ KLibLoader *loader = KLibLoader::self();
+ lib = loader->library("libthai");
+ if (lib && lib->hasSymbol("th_brk")) {
+ th_brk = (th_brk_def) lib->symbol("th_brk");
+ } else {
+ // indication that loading failed and we shouldn't try to load again
+ printf("Error, can't load libthai...\n");
+ thaiCodec = 0;
+ if (lib)
+ lib->unload();
+ }
+ }
+
+ if (!th_brk ) {
+ return true;
+ }
+#endif
+
+ if (!cache ) {
+ cache = new ThaiCache;
+#ifndef HAVE_LIBTHAI
+ cache->library = lib;
+#endif
+ }
+
+ // build up string of thai chars
+ if ( string != cache->string ) {
+ //fprintf(stderr,"new string found (not in cache), calling libthai\n");
+ TQCString cstr = thaiCodec->fromUnicode( TQConstString(string,len).string());
+ //printf("About to call libthai::th_brk with str: %s",cstr.data());
+
+ cache->numwbrpos = th_brk((const unsigned char*) cstr.data(), cache->wbrpos, cache->allocated);
+ //fprintf(stderr,"libthai returns with value %d\n",cache->numwbrpos);
+ if (cache->numwbrpos > cache->allocated) {
+ cache->allocated = cache->numwbrpos;
+ cache->wbrpos = (int *)realloc(cache->wbrpos, cache->allocated*sizeof(int));
+ cache->numwbrpos = th_brk((const unsigned char*) cstr.data(), cache->wbrpos, cache->allocated);
+ }
+ if ( len > cache->numisbreakable ) {
+ cache->numisbreakable=len;
+ cache->isbreakable = (int *)realloc(cache->isbreakable, cache->numisbreakable*sizeof(int));
+ }
+ for (int i = 0 ; i < len ; ++i) {
+ cache->isbreakable[i] = 0;
+ }
+ if ( cache->numwbrpos > 0 ) {
+ for (int i = cache->numwbrpos-1; i >= 0; --i) {
+ cache->isbreakable[cache->wbrpos[i]] = 1;
+ }
+ }
+ cache->string = string;
+ }
+ //printf("Returning %d\n", cache->isbreakable[pos]);
+ return cache->isbreakable[pos];
+ }
+}
diff --git a/tdehtml/rendering/break_lines.h b/tdehtml/rendering/break_lines.h
new file mode 100644
index 000000000..34b733121
--- /dev/null
+++ b/tdehtml/rendering/break_lines.h
@@ -0,0 +1,163 @@
+#ifndef BREAK_LINES_H
+#define BREAK_LINES_H
+
+#include <tqstring.h>
+
+namespace tdehtml {
+
+ /*
+ array of unicode codes where breaking shouldn't occur.
+ (in sorted order because of using with binary search)
+ these are currently for Japanese, though simply adding
+ Korean, Chinese ones should work as well
+ */
+ /*
+ dontbreakbefore[] contains characters not covered by TQChar::Punctuation_Close that shouldn't be broken before.
+ chars included in TQChar::Punctuation_Close are listed below.(look at UAX #14)
+ - 3001 ideographic comma
+ - 3002 ideographic full stop
+ - FE50 small comma
+ - FF52 small full stop
+ - FF0C fullwidth comma
+ - FF0E fullwidth full stop
+ - FF61 halfwidth ideographic full stop
+ - FF64 halfwidth ideographic comma
+ these character is commented out.
+ */
+ const ushort dontbreakbefore[] = {
+ //0x3001, //ideographic comma
+ //0x3002, //ideographic full stop
+ 0x3005, //ideographic iteration mark
+ 0x3009, //right angle bracket
+ 0x300b, //right double angle bracket
+ 0x300d, //right corner bracket
+ 0x300f, //right white corner bracket
+ 0x3011, //right black lenticular bracket
+ 0x3015, //right tortoise shell bracket
+ 0x3041, //small a hiragana
+ 0x3043, //small i hiragana
+ 0x3045, //small u hiragana
+ 0x3047, //small e hiragana
+ 0x3049, //small o hiragana
+ 0x3063, //small tsu hiragana
+ 0x3083, //small ya hiragana
+ 0x3085, //small yu hiragana
+ 0x3087, //small yo hiragana
+ 0x308E, //small wa hiragana
+ 0x309B, //jap voiced sound mark
+ 0x309C, //jap semi-voiced sound mark
+ 0x309D, //jap iteration mark hiragana
+ 0x309E, //jap voiced iteration mark hiragana
+ 0x30A1, //small a katakana
+ 0x30A3, //small i katakana
+ 0x30A5, //small u katakana
+ 0x30A7, //small e katakana
+ 0x30A9, //small o katakana
+ 0x30C3, //small tsu katakana
+ 0x30E3, //small ya katakana
+ 0x30E5, //small yu katakana
+ 0x30E7, //small yo katakana
+ 0x30EE, //small wa katakana
+ 0x30F5, //small ka katakana
+ 0x30F6, //small ke katakana
+ 0x30FC, //jap prolonged sound mark
+ 0x30FD, //jap iteration mark katakana
+ 0x30FE, //jap voiced iteration mark katakana
+ //0xFE50, //small comma
+ //0xFF52, //small full stop
+ 0xFF01, //fullwidth exclamation mark
+ 0xFF09, //fullwidth right parenthesis
+ //0xFF0C, //fullwidth comma
+ 0xFF0D, //fullwidth hypen-minus
+ //0xFF0E, //fullwidth full stop
+ 0xFF1F, //fullwidth question mark
+ 0xFF3D, //fullwidth right square bracket
+ 0xFF5D, //fullwidth right curly bracket
+ //0xFF61, //halfwidth ideographic full stop
+ 0xFF63, //halfwidth right corner bracket
+ //0xFF64, //halfwidth ideographic comma
+ 0xFF67, //halfwidth katakana letter small a
+ 0xFF68, //halfwidth katakana letter small i
+ 0xFF69, //halfwidth katakana letter small u
+ 0xFF6a, //halfwidth katakana letter small e
+ 0xFF6b, //halfwidth katakana letter small o
+ 0xFF6c, //halfwidth katakana letter small ya
+ 0xFF6d, //halfwidth katakana letter small yu
+ 0xFF6e, //halfwidth katakana letter small yo
+ 0xFF6f, //halfwidth katakana letter small tu
+ 0xFF70 //halfwidth katakana-hiragana prolonged sound mark
+ };
+
+ // characters that aren't covered by TQChar::Punctuation_Open
+ const ushort dontbreakafter[] = {
+ 0x3012, //postal mark
+ 0xFF03, //full width pound mark
+ 0xFF04, //full width dollar sign
+ 0xFF20, //full width @
+ 0xFFE1, //full width british pound sign
+ 0xFFE5 //full width yen sign
+ };
+
+ inline bool break_bsearch( const ushort* arr, const ushort val ) {
+ int left = 0;
+ int right = (sizeof(arr) / sizeof(ushort)) - 1;
+
+ while (1) {
+ if (left == right)
+ return val != arr[left];
+
+ int i = (left + right) >> 1;
+ if ( val == arr[i] )
+ return false;
+ if ( val < arr[i] )
+ right = i;
+ else
+ left = i + 1;
+ }
+ }
+
+ bool isBreakableThai( const TQChar *string, const int pos, const int len);
+ void cleanup_thaibreaks();
+
+ inline bool isBreakable( const TQChar *str, const int pos, int len )
+ {
+ const TQChar *c = str+pos;
+ unsigned short ch = c->unicode();
+ if ( ch > 0xff ) {
+ // not latin1, need to do more sophisticated checks for asian fonts
+ unsigned char row = c->row();
+ if ( row == 0x0e ) {
+ // 0e00 - 0e7f == Thai
+ if ( c->cell() < 0x80 ) {
+ // consult libthai
+ return isBreakableThai(str, pos, len);
+ } else
+ return false;
+ }
+ if ( row > 0x2d && row < 0xfb || row == 0x11 ) {
+ /* asian line breaking. */
+ if ( pos == 0 )
+ return false; // never break before first character
+
+ // check for simple punctuation cases
+ TQChar::Category cat = c->category();
+ if ( cat == TQChar::Punctuation_Close ||
+ cat == TQChar::Punctuation_Other ||
+ (str+(pos-1))->category() == TQChar::Punctuation_Open )
+ return false;
+
+ // do binary search in dontbreak[]
+ return break_bsearch(dontbreakbefore, c->unicode()) &&
+ break_bsearch(dontbreakafter, (str+(pos-1))->unicode());
+ } else // no asian font
+ return c->isSpace();
+ } else {
+ if ( ch == ' ' || ch == '\n' )
+ return true;
+ }
+ return false;
+ }
+
+}
+
+#endif
diff --git a/tdehtml/rendering/counter_tree.cpp b/tdehtml/rendering/counter_tree.cpp
new file mode 100644
index 000000000..931c54332
--- /dev/null
+++ b/tdehtml/rendering/counter_tree.cpp
@@ -0,0 +1,222 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2005 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.
+ *
+ */
+
+#include "rendering/counter_tree.h"
+#include "rendering/render_object.h"
+
+namespace tdehtml {
+
+CounterNode::CounterNode(RenderObject *o)
+ : m_hasCounters(false), m_isVisual(false),
+ m_value(0), m_count(0), m_parent(0), m_previous(0), m_next(0),
+ m_renderer(o) {}
+
+CounterNode::~CounterNode()
+{
+ if (m_parent) m_parent->removeChild(this);
+}
+
+void CounterNode::insertAfter ( CounterNode *, CounterNode *)
+{
+ Q_ASSERT( false);
+}
+
+void CounterNode::removeChild ( CounterNode *)
+{
+ Q_ASSERT( false);
+}
+
+void CounterNode::remove ()
+{
+ if (m_parent) m_parent->removeChild(this);
+ else {
+ Q_ASSERT(isReset());
+ Q_ASSERT(!firstChild());
+ Q_ASSERT(!lastChild());
+ }
+}
+
+void CounterNode::setHasCounters ()
+{
+ m_hasCounters = true;
+ if (parent())
+ parent()->setHasCounters();
+}
+
+void CounterNode::recount (bool first)
+{
+ int old_count = m_count;
+ if (m_previous)
+ m_count = m_previous->count() + m_value;
+ else {
+ assert(m_parent->firstChild() == this);
+ m_count = m_parent->value() + m_value;
+ }
+ if (old_count != m_count && !first)
+ setSelfDirty();
+ if (old_count != m_count || first) {
+ if (m_parent) m_parent->updateTotal(m_count);
+ if (m_next) m_next->recount();
+ }
+}
+
+void CounterNode::setSelfDirty ()
+{
+ if (m_renderer && m_isVisual)
+ m_renderer->setNeedsLayoutAndMinMaxRecalc();
+}
+
+void CounterNode::setParentDirty ()
+{
+ if (m_renderer && m_isVisual && m_hasCounters)
+ m_renderer->setNeedsLayoutAndMinMaxRecalc();
+}
+
+CounterReset::CounterReset(RenderObject *o) : CounterNode(o), m_total(0), m_first(0), m_last(0) {}
+CounterReset::~CounterReset() {}
+
+void CounterReset::insertAfter ( CounterNode *newChild, CounterNode *refChild )
+{
+ Q_ASSERT( newChild );
+ Q_ASSERT( !refChild || refChild->parent() == this );
+
+ newChild->m_parent = this;
+ newChild->m_previous = refChild;
+
+ if (refChild) {
+ newChild->m_next = refChild->m_next;
+ refChild->m_next = newChild;
+ } else {
+ newChild->m_next = m_first;
+ m_first = newChild;
+ }
+
+ if (newChild->m_next) {
+ assert(newChild->m_next->m_previous == refChild);
+ newChild->m_next->m_previous = newChild;
+ }
+ else {
+ assert (m_last == refChild);
+ m_last = newChild;
+ }
+
+ newChild->recount(true);
+}
+
+void CounterReset::removeChild ( CounterNode *oldChild )
+{
+ Q_ASSERT( oldChild );
+
+ CounterNode* next = oldChild->m_next;
+ CounterNode* prev = oldChild->m_previous;
+
+ if (oldChild->firstChild()) {
+ CounterNode* first = oldChild->firstChild();
+ CounterNode* last = oldChild->lastChild();
+ if (prev) {
+ prev->m_next = first;
+ first->m_previous = prev;
+ }
+ else {
+ assert ( m_first == oldChild );
+ m_first = first;
+ }
+
+ if (next) {
+ next->m_previous = last;
+ last->m_next = next;
+ }
+ else {
+ assert ( m_last == oldChild );
+ m_last = last;
+ }
+
+ next = first;
+ while (next) {
+ next->m_parent = this;
+ if (next == last) break;
+ next = next->m_next;
+ }
+
+ first->recount(true);
+ }
+ else {
+ if (prev) prev->m_next = next;
+ else {
+ assert ( m_first == oldChild );
+ m_first = next;
+ }
+ if (next) next->m_previous = prev;
+ else {
+ assert ( m_last == oldChild );
+ m_last = prev;
+ }
+ if (next)
+ next->recount();
+ }
+
+
+ oldChild->m_next = 0;
+ oldChild->m_previous = 0;
+ oldChild->m_parent = 0;
+}
+
+void CounterReset::recount (bool first)
+{
+ int old_count = m_count;
+ if (m_previous)
+ m_count = m_previous->count();
+ else if (m_parent)
+ m_count = m_parent->value();
+ else
+ m_count = 0;
+
+ updateTotal(m_value);
+ if (!first) setSelfDirty();
+ if (first || m_count != old_count) {
+ if (m_next) m_next->recount();
+ }
+}
+
+void CounterReset::setSelfDirty ()
+{
+ setParentDirty();
+}
+
+void CounterReset::setParentDirty ()
+{
+ if (hasCounters()) {
+ if (m_renderer && m_isVisual) m_renderer->setNeedsLayoutAndMinMaxRecalc();
+ CounterNode* n = firstChild();
+ for(; n; n = n->nextSibling())
+ {
+ n->setParentDirty();
+ }
+ }
+}
+
+void CounterReset::updateTotal (int value)
+{
+ if (value > m_total) m_total = value;
+}
+
+} // namespace
diff --git a/tdehtml/rendering/counter_tree.h b/tdehtml/rendering/counter_tree.h
new file mode 100644
index 000000000..0266dcc75
--- /dev/null
+++ b/tdehtml/rendering/counter_tree.h
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2005 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.
+ *
+ */
+#ifndef _Counter_Tree_h_
+#define _Counter_Tree_h_
+
+#include "misc/shared.h"
+#include "rendering/render_object.h"
+
+namespace tdehtml {
+
+class CounterReset;
+
+// This file implements a counter-tree that is used for finding all parents in counters() lookup,
+// and for propagating count-changes when nodes are added or removed.
+// Please note that only counter-reset and root can be parents here, and that render-tree parents
+// are just counter-tree siblings
+
+// Implementation of counter-increment and counter-content
+class CounterNode
+{
+public:
+ CounterNode(RenderObject *o);
+ virtual ~CounterNode();
+
+ CounterReset* parent() const { return m_parent; }
+ CounterNode* previousSibling() const { return m_previous; }
+ CounterNode* nextSibling() const { return m_next; }
+ virtual CounterNode* firstChild() const { return 0; } ;
+ virtual CounterNode* lastChild() const { return 0; };
+ virtual void insertAfter ( CounterNode *newChild, CounterNode *refChild );
+ virtual void removeChild ( CounterNode *oldChild );
+ // Convenient self-refering version of the above
+ void remove();
+
+ int value() const { return m_value; };
+ void setValue(short v) { m_value = v; };
+ int count() const { return m_count; };
+
+ virtual bool isReset() { return false; };
+ virtual void recount( bool first = false );
+ virtual void setSelfDirty();
+ virtual void setParentDirty();
+
+ bool hasCounters() const { return m_hasCounters; };
+ bool isVisual() const { return m_isVisual; };
+ void setHasCounters();
+ void setIsVisual() { m_isVisual = true; };
+ bool isRoot() { return m_renderer && m_renderer->isRoot(); };
+
+ void setRenderer(RenderObject *o) { m_renderer = o; };
+ RenderObject* renderer() const { return m_renderer; };
+
+ friend class CounterReset;
+protected:
+ bool m_hasCounters : 1;
+ bool m_isVisual : 1;
+ short m_value;
+ short m_count;
+ CounterReset *m_parent;
+ CounterNode *m_previous;
+ CounterNode *m_next;
+ RenderObject *m_renderer;
+};
+
+// Implementation of counter-reset and root
+class CounterReset : public CounterNode
+{
+public:
+ CounterReset(RenderObject *o);
+ virtual ~CounterReset();
+
+ virtual CounterNode *firstChild() const { return m_first; };
+ virtual CounterNode *lastChild() const { return m_last; };
+ virtual void insertAfter ( CounterNode *newChild, CounterNode *refChild );
+ virtual void removeChild ( CounterNode *oldChild );
+
+ virtual bool isReset() { return true; };
+ virtual void recount( bool first = false );
+ virtual void setSelfDirty();
+ virtual void setParentDirty();
+
+ void updateTotal(int value);
+ // The highest value among children
+ int total() const { return m_total; };
+
+protected:
+ int m_total;
+ CounterNode *m_first;
+ CounterNode *m_last;
+};
+
+} // namespace
+
+#endif
+
diff --git a/tdehtml/rendering/enumerate.cpp b/tdehtml/rendering/enumerate.cpp
new file mode 100644
index 000000000..bd2ff3696
--- /dev/null
+++ b/tdehtml/rendering/enumerate.cpp
@@ -0,0 +1,411 @@
+/**
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ *
+ * (C) Hebrew algorithm by herouth@netvision.net.il
+ * and schlpbch@iam.unibe.ch
+ *
+ * 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 "rendering/enumerate.h"
+
+#include <tqstring.h>
+#include <tqvaluelist.h>
+
+namespace tdehtml {
+
+namespace Enumerate {
+
+TQString toRoman( int number, bool upper )
+{
+ if (number < 1 || number > 3999) return TQString::number(number);
+ TQString roman;
+ static const TQChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
+ static const TQChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
+ const TQChar *digits = upper ? udigits : ldigits;
+ int i, d = 0;
+
+ do
+ {
+ int num = number % 10;
+
+ if ( num % 5 < 4 )
+ for ( i = num % 5; i > 0; i-- )
+ roman.prepend( digits[ d ] );
+
+ if ( num >= 4 && num <= 8)
+ roman.prepend( digits[ d+1 ] );
+
+ if ( num == 9 )
+ roman.prepend( digits[ d+2 ] );
+
+ if ( num % 5 == 4 )
+ roman.prepend( digits[ d ] );
+
+ number /= 10;
+ d += 2;
+ }
+ while ( number );
+
+ return roman;
+}
+
+TQString toGeorgian( int number )
+{
+ TQString georgian;
+ const TQChar tenthousand = 0x10ef;
+ static const TQChar thousands[9] = {0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec,
+ 0x10ed, 0x10ee, 0x10f4, 0x10f5 };
+ static const TQChar hundreds[9] = {0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10f3,
+ 0x10e4, 0x10e5, 0x10e6, 0x10e7 };
+ static const TQChar tens[9] = {0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc,
+ 0x10f2, 0x10dd, 0x10de, 0x10df };
+ static const TQChar units[9] = {0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4,
+ 0x10d5, 0x10d6, 0x10f1, 0x10d7 };
+
+ if (number < 1 || number > 19999) return TQString::number(number);
+ if (number >= 10000) {
+ georgian.append(tenthousand);
+ number = number - 10000;
+ }
+ if (number >= 1000) {
+ georgian.append(thousands[number/1000-1]);
+ number = number % 1000;
+ }
+ if (number >= 100) {
+ georgian.append(hundreds[number/100-1]);
+ number = number % 100;
+ }
+ if (number >= 10) {
+ georgian.append(tens[number/10-1]);
+ number = number % 10;
+ }
+ if (number >= 1) {
+ georgian.append(units[number-1]);
+ }
+
+ return georgian;
+}
+
+TQString toArmenian( int number )
+{
+ TQString armenian;
+ int onethousand = 0x57c;
+ int hundreds = 0x572;
+ int tens = 0x569;
+ int units = 0x560;
+
+ // The standard defines values over 1999, but 7000 is very hard to render
+ if (number < 1 || number > 1999) return TQString::number(number);
+ if (number >= 1000) {
+ armenian.append(TQChar(onethousand));
+ number = number - 1000;
+ }
+ if (number >= 100) {
+ armenian.append(TQChar(hundreds+number/100));
+ number = number % 100;
+ }
+ if (number >= 10) {
+ armenian.append(TQChar(tens+number/10));
+ number = number % 10;
+ }
+ if (number >= 1) {
+ armenian.append(TQChar(units+number));
+ }
+
+ return armenian;
+}
+
+TQString toHebrew( int number ) {
+ static const TQChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
+
+ TQString letter;
+ if (number < 1) return TQString::number(number);
+ if (number>999) {
+ letter = toHebrew(number/1000) + TQString::fromLatin1("'");
+ number = number%1000;
+ }
+
+ int hunderts = (number/400);
+ if (hunderts > 0) {
+ for(int i=0; i<hunderts; i++) {
+ letter += TQChar(1511 + 3);
+ }
+ }
+ number = number % 400;
+ if ((number / 100) != 0) {
+ letter += TQChar (1511 + (number / 100) -1);
+ }
+ number = number % 100;
+ int tens = number/10;
+ if (tens > 0 && !(number == 15 || number == 16)) {
+ letter += tenDigit[tens-1];
+ }
+ if (number == 15 || number == 16) { // special because of religious
+ letter += TQChar(1487 + 9); // reasons
+ letter += TQChar(1487 + number - 9);
+ } else {
+ number = number % 10;
+ if (number != 0) {
+ letter += TQChar (1487 + number);
+ }
+ }
+ return letter;
+}
+
+static inline TQString toLatin( int number, int base ) {
+ if (number < 1) return TQString::number(number);
+ TQValueList<TQChar> letters;
+ while(number > 0) {
+ number--; // number 0 is letter a
+ TQChar letter = (TQChar) (base + (number % 26));
+ letters.prepend(letter);
+ number /= 26;
+ }
+ TQString str;
+ str.setLength(letters.size());
+ int i=0;
+ while(!letters.isEmpty()) {
+ str[i++] = letters.front();
+ letters.pop_front();
+ }
+ return str;
+}
+
+TQString toLowerLatin( int number ) {
+ return toLatin( number, 'a' );
+}
+
+TQString toUpperLatin( int number ) {
+ return toLatin( number, 'A' );
+}
+
+static inline TQString toAlphabetic( int number, int base, const TQChar alphabet[] ) {
+ if (number < 1) return TQString::number(number);
+ TQValueList<TQChar> letters;
+ while(number > 0) {
+ number--; // number 0 is letter 1
+ TQChar letter = alphabet[number % base];
+ letters.prepend(letter);
+ number /= base;
+ }
+ TQString str;
+ str.setLength(letters.size());
+ int i=0;
+ while(!letters.isEmpty()) {
+ str[i++] = letters.front();
+ letters.pop_front();
+ }
+ return str;
+}
+
+TQString toHiragana( int number ) {
+ static const TQChar hiragana[48] = {0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D,
+ 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
+ 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B,
+ 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078,
+ 0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086,
+ 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F,
+ 0x3090, 0x3091, 0x9092, 0x3093};
+ return toAlphabetic( number, 48, hiragana );
+}
+
+TQString toHiraganaIroha( int number ) {
+ static const TQChar hiragana[47] = {0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
+ 0x3061, 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B,
+ 0x3088, 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, 0x306A,
+ 0x3089, 0x3080, 0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084,
+ 0x307E, 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, 0x3042, 0x3055,
+ 0x304D, 0x3086, 0x3081, 0x307F, 0x3057, 0x3091, 0x3072, 0x3082,
+ 0x305B, 0x3059 };
+ return toAlphabetic( number, 47, hiragana );
+}
+
+TQString toKatakana( int number ) {
+ static const TQChar katakana[48] = {0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
+ 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB,
+ 0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA,
+ 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5,
+ 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
+ 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC,
+ 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x90F2, 0x30F3};
+ return toAlphabetic( number, 48, katakana );
+}
+
+TQString toKatakanaIroha( int number ) {
+ static const TQChar katakana[47] = {0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
+ 0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB,
+ 0x30E8, 0x30BF, 0x30EC, 0x30ED, 0x30C4, 0x30CD, 0x30CA,
+ 0x30E9, 0x30E0, 0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF,
+ 0x30E4, 0x30DE, 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
+ 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
+ 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x90B9};
+ return toAlphabetic( number, 47, katakana );
+}
+
+TQString toLowerGreek( int number ) {
+ static const TQChar greek[24] = { 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7,
+ 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE,
+ 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6,
+ 0x3C7, 0x3C8, 0x3C0};
+
+ return toAlphabetic( number, 24, greek );
+}
+
+TQString toUpperGreek( int number ) {
+ // The standard claims to be base 24, but only lists 19 letters.
+ static const TQChar greek[19] = { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398,
+ 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F,
+ 0x3A0, 0x3A1, 0x3A3, 0x3A9};
+
+ return toAlphabetic( number, 19, greek );
+}
+
+static inline TQString toNumeric( int number, int base ) {
+ TQString letter = TQString::number(number);
+ for(unsigned int i = 0; i < letter.length(); i++) {
+ if (letter[i].isDigit())
+ letter[i] = TQChar(letter[i].digitValue()+base);
+ }
+ return letter;
+}
+
+TQString toArabicIndic( int number ) {
+ return toNumeric(number, 0x660);
+}
+
+TQString toPersianUrdu( int number ) {
+ return toNumeric(number, 0x6F0);
+}
+
+TQString toLao( int number ) {
+ return toNumeric(number, 0xED0);
+}
+
+TQString toThai( int number ) {
+ return toNumeric(number, 0xE50);
+}
+
+TQString toTibetan( int number ) {
+ return toNumeric(number, 0xF20);
+}
+
+static inline TQString toIdeographic(int number, const TQChar digits[], const TQChar digitmarkers[]) {
+ if (number < 0 || number > 9999) return TQString::number(number);
+
+ TQString grp = TQString::number(number);
+
+ // ### Append group markers to handle numbers > 9999
+
+ TQString str;
+
+ // special case
+ if (number < 20 && number >= 10) {
+ str.append(digitmarkers[0]);
+ str.append(digits[grp[1].digitValue()]);
+ return str;
+ }
+
+ int len = grp.length();
+ bool collapseZero = false;
+ for (int i = 0; i < len ; i++) {
+ int digit = grp[i].digitValue();
+ // Add digit markers to digits > 0
+ if ((len-i-1) > 0 && digit > 0)
+ str.append(digitmarkers[(len-i-2)]);
+ // Add digit, but collapse consecutive zeros
+ if (!collapseZero || digit > 0) {
+ str.append(digits[digit]);
+
+ if (digit == 0)
+ collapseZero = true;
+ else
+ collapseZero = false;
+ }
+ }
+ return str;
+}
+
+TQString toTradChineseFormal( int number ) {
+// static const TQChar groupMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
+ static const TQChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
+ static const TQChar digits[10] = {0x96f6, 0x4e00,
+ 0x4ebc, 0x4e09,
+ 0x56db, 0x4e94,
+ 0x516d, 0x4e03,
+ 0x516b, 0x4e5d};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+TQString toTradChineseInformal( int number ) {
+// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digits[10] = {0x96f6, 0x4e00,
+ 0x4ebc, 0x4e09,
+ 0x56db, 0x4e94,
+ 0x516d, 0x4e03,
+ 0x516b, 0x4e5d};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+TQString toSimpChineseFormal( int number ) {
+// static const TQChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
+ static const TQChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
+ static const TQChar digits[10] = {0x96f6, 0x58f9,
+ 0x8cb3, 0x53c3,
+ 0x8086, 0x4f0d,
+ 0x9678, 0x67d2,
+ 0x634c, 0x7396};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+TQString toSimpChineseInformal( int number ) {
+// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digits[10] = {0x96f6, 0x58f9,
+ 0x8cb3, 0x53c3,
+ 0x8086, 0x4f0d,
+ 0x9678, 0x67d2,
+ 0x634c, 0x7396};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+TQString toJapaneseFormal( int number ) {
+// static const TQChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
+ static const TQChar digitMarkers[3] = {0x62fe, 0x4f70, 0x4edf};
+ static const TQChar digits[10] = {0x96f6, 0x58f9,
+ 0x8cb3, 0x53c3,
+ 0x8086, 0x4f0d,
+ 0x9678, 0x67d2,
+ 0x634c, 0x7396};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+TQString toJapaneseInformal( int number ) {
+// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
+ static const TQChar digits[10] = {0x96f6, 0x58f9,
+ 0x8d30, 0x53c1,
+ 0x8086, 0x4f0d,
+ 0x9646, 0x67d2,
+ 0x634c, 0x7396};
+ return toIdeographic(number, digits, digitMarkers);
+}
+
+}} // namespace
diff --git a/tdehtml/rendering/enumerate.h b/tdehtml/rendering/enumerate.h
new file mode 100644
index 000000000..16b92f43c
--- /dev/null
+++ b/tdehtml/rendering/enumerate.h
@@ -0,0 +1,66 @@
+/**
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2004-2005 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.
+ *
+ */
+
+#ifndef ENUMERATE_H
+#define ENUMERATE_H
+
+class TQChar;
+class TQString;
+
+namespace tdehtml {
+
+namespace Enumerate {
+
+// Numeric
+ TQString toArabicIndic( int number );
+ TQString toLao( int number );
+ TQString toPersianUrdu( int number );
+ TQString toThai( int number );
+ TQString toTibetan( int number );
+
+// Alphabetic
+ TQString toLowerLatin( int number );
+ TQString toUpperLatin( int number );
+ TQString toLowerGreek( int number );
+ TQString toUpperGreek( int number );
+ TQString toHiragana( int number );
+ TQString toHiraganaIroha( int number );
+ TQString toKatakana( int number );
+ TQString toKatakanaIroha( int number );
+
+// Algorithmic
+ TQString toRoman( int number, bool upper );
+ TQString toHebrew( int number );
+ TQString toGeorgian( int number );
+ TQString toArmenian( int number );
+
+// Ideographic
+ TQString toJapaneseFormal ( int number );
+ TQString toJapaneseInformal ( int number );
+ TQString toSimpChineseFormal ( int number );
+ TQString toSimpChineseInformal ( int number );
+ TQString toTradChineseFormal ( int number );
+ TQString toTradChineseInformal ( int number );
+
+}} // namespaces
+
+#endif
diff --git a/tdehtml/rendering/font.cpp b/tdehtml/rendering/font.cpp
new file mode 100644
index 000000000..3ace5ddd1
--- /dev/null
+++ b/tdehtml/rendering/font.cpp
@@ -0,0 +1,502 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 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 "config.h"
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include "font.h"
+#include "tdehtml_factory.h"
+#include "tdehtml_settings.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <tqpainter.h>
+#include <tqfontdatabase.h>
+#include <tqpaintdevicemetrics.h>
+
+using namespace tdehtml;
+
+/** closes the current word and returns its width in pixels
+ * @param fm metrics of font to be used
+ * @param str string
+ * @param pos zero-indexed position within @p str upon which all other
+ * indices are based
+ * @param wordStart relative index pointing to the position where the word started
+ * @param wordEnd relative index pointing one position after the word ended
+ * @return the width in pixels. May be 0 if @p wordStart and @p wordEnd were
+ * equal.
+ */
+inline int closeWordAndGetWidth(const TQFontMetrics &fm, const TQChar *str, int pos,
+ int wordStart, int wordEnd)
+{
+ if (wordEnd <= wordStart) return 0;
+
+ TQConstString s(str + pos + wordStart, wordEnd - wordStart);
+ return fm.width(s.string());
+}
+
+/** closes the current word and draws it
+ * @param p painter
+ * @param d text direction
+ * @param x current x position, will be inc-/decremented correctly according
+ * to text direction
+ * @param y baseline of text
+ * @param widths list of widths; width of word is expected at position
+ * wordStart
+ * @param str string
+ * @param pos zero-indexed position within @p str upon which all other
+ * indices are based
+ * @param wordStart relative index pointing to the position where the word started,
+ * will be set to wordEnd after function
+ * @param wordEnd relative index pointing one position after the word ended
+ */
+inline void closeAndDrawWord(TQPainter *p, TQPainter::TextDirection d,
+ int &x, int y, const short widths[], const TQChar *str, int pos,
+ int &wordStart, int wordEnd)
+{
+ if (wordEnd <= wordStart) return;
+
+ int width = widths[wordStart];
+ if (d == TQPainter::RTL)
+ x -= width;
+
+ TQConstString s(str + pos + wordStart, wordEnd - wordStart);
+ p->drawText(x, y, s.string(), -1, d);
+
+ if (d != TQPainter::RTL)
+ x += width;
+
+ wordStart = wordEnd;
+}
+
+void Font::drawText( TQPainter *p, int x, int y, TQChar *str, int slen, int pos, int len,
+ int toAdd, TQPainter::TextDirection d, int from, int to, TQColor bg, int uy, int h, int deco ) const
+{
+ if (!str) return;
+ TQConstString cstr = TQConstString(str, slen);
+ TQString qstr = cstr.string();
+
+ // ### fixme for RTL
+ if ( !scFont && !letterSpacing && !wordSpacing && !toAdd && from==-1 ) {
+ // simply draw it
+ // Due to some unfounded cause TQPainter::drawText traverses the
+ // *whole* string when painting, not only the specified
+ // [pos, pos + len) segment. This makes painting *extremely* slow for
+ // long render texts (in the order of several megabytes).
+ // Hence, only hand over the piece of text of the actual inline text box
+ TQConstString cstr = TQConstString(str + pos, len);
+ p->drawText( x, y, cstr.string(), 0, len, d );
+ } else {
+ if (from < 0) from = 0;
+ if (to < 0) to = len;
+
+ int numSpaces = 0;
+ if ( toAdd ) {
+ for( int i = 0; i < len; ++i )
+ if ( str[i+pos].category() == TQChar::Separator_Space )
+ ++numSpaces;
+ }
+
+ const int totWidth = width( str, slen, pos, len );
+ if ( d == TQPainter::RTL ) {
+ x += totWidth + toAdd;
+ }
+ TQString upper = qstr;
+ TQFontMetrics sc_fm = fm;
+ if ( scFont ) {
+ // draw in small caps
+ upper = qstr.upper();
+ sc_fm = TQFontMetrics( *scFont );
+ }
+
+ // ### sc could be optimized by only painting uppercase letters extra,
+ // and treat the rest WordWise, but I think it's not worth it.
+ // Somebody else may volunteer, and implement this ;-) (LS)
+
+ // The mode determines whether the text is displayed character by
+ // character, word by word, or as a whole
+ enum { CharacterWise, WordWise, Whole }
+ mode = Whole;
+ if (!letterSpacing && !scFont && (wordSpacing || toAdd > 0))
+ mode = WordWise;
+ else if (letterSpacing || scFont)
+ mode = CharacterWise;
+
+ if (mode == Whole) { // most likely variant is treated extra
+
+ if (to < 0) to = len;
+ const TQConstString cstr(str + pos, len);
+ const TQConstString segStr(str + pos + from, to - from);
+ const int preSegmentWidth = fm.width(cstr.string(), from);
+ const int segmentWidth = fm.width(segStr.string());
+ const int eff_x = d == TQPainter::RTL ? x - preSegmentWidth - segmentWidth
+ : x + preSegmentWidth;
+
+ // draw whole string segment, with optional background
+ if ( bg.isValid() )
+ p->fillRect( eff_x, uy, segmentWidth, h, bg );
+ p->drawText(eff_x, y, segStr.string(), -1, d);
+ if (deco)
+ drawDecoration(p, eff_x, uy, y - uy, segmentWidth - 1, h, deco);
+ return;
+ }
+
+ // We are using two passes. In the first pass, the widths are collected,
+ // and stored. In the second, the actual characters are drawn.
+
+ // For each letter in the text box, save the width of the character.
+ // When word-wise, only the first letter contains the width, but of the
+ // whole word.
+ short* const widthList = (short *)alloca(to*sizeof(short));
+
+ // First pass: gather widths
+ int preSegmentWidth = 0;
+ int segmentWidth = 0;
+ int lastWordBegin = 0;
+ bool onSegment = from == 0;
+ for( int i = 0; i < to; ++i ) {
+ if (i == from) {
+ // Also close words on visibility boundary
+ if (mode == WordWise) {
+ const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, i);
+
+ if (lastWordBegin < i) {
+ widthList[lastWordBegin] = (short)width;
+ lastWordBegin = i;
+ preSegmentWidth += width;
+ }
+ }
+ onSegment = true;
+ }
+
+ const TQChar ch = str[pos+i];
+ bool lowercase = (ch.category() == TQChar::Letter_Lowercase);
+ bool is_space = (ch.category() == TQChar::Separator_Space);
+ int chw = 0;
+ if ( letterSpacing )
+ chw += letterSpacing;
+ if ( (wordSpacing || toAdd) && is_space ) {
+ if (mode == WordWise) {
+ const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, i);
+ if (lastWordBegin < i) {
+ widthList[lastWordBegin] = (short)width;
+ lastWordBegin = i;
+ (onSegment ? segmentWidth : preSegmentWidth) += width;
+ }
+ ++lastWordBegin; // ignore this space
+ }
+ chw += wordSpacing;
+ if ( numSpaces ) {
+ const int a = toAdd/numSpaces;
+ chw += a;
+ toAdd -= a;
+ --numSpaces;
+ }
+ }
+ if (is_space || mode == CharacterWise) {
+ chw += lowercase ? sc_fm.charWidth( upper, pos+i ) : fm.charWidth( qstr, pos+i );
+ widthList[i] = (short)chw;
+
+ (onSegment ? segmentWidth : preSegmentWidth) += chw;
+ }
+
+ }
+
+ // close last word
+ Q_ASSERT(onSegment);
+ if (mode == WordWise) {
+ const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, to);
+ segmentWidth += width;
+ widthList[lastWordBegin] = (short)width;
+ }
+
+ if (d == TQPainter::RTL) x -= preSegmentWidth;
+ else x += preSegmentWidth;
+
+ const int startx = d == TQPainter::RTL ? x-segmentWidth : x;
+
+ // optionally draw background
+ if ( bg.isValid() )
+ p->fillRect( startx, uy, segmentWidth, h, bg );
+
+ // second pass: do the actual drawing
+ lastWordBegin = from;
+ for( int i = from; i < to; ++i ) {
+ const TQChar ch = str[pos+i];
+ bool lowercase = (ch.category() == TQChar::Letter_Lowercase);
+ bool is_space = ch.category() == TQChar::Separator_Space;
+ if ( is_space ) {
+ if (mode == WordWise) {
+ closeAndDrawWord(p, d, x, y, widthList, str, pos, lastWordBegin, i);
+ ++lastWordBegin; // jump over space
+ }
+ }
+ if (is_space || mode == CharacterWise) {
+ const int chw = widthList[i];
+ if (d == TQPainter::RTL)
+ x -= chw;
+
+ if ( scFont )
+ p->setFont( lowercase ? *scFont : f );
+ p->drawText( x, y, (lowercase ? upper : qstr), pos+i, 1, d );
+
+ if (d != TQPainter::RTL)
+ x += chw;
+ }
+
+ }
+
+ // don't forget to draw last word
+ if (mode == WordWise) {
+ closeAndDrawWord(p, d, x, y, widthList, str, pos, lastWordBegin, to);
+ }
+
+ if (deco)
+ drawDecoration(p, startx, uy, y - uy, segmentWidth - 1, h, deco);
+
+ if ( scFont )
+ p->setFont( f );
+ }
+}
+
+
+int Font::width( TQChar *chs, int, int pos, int len, int start, int end, int toAdd ) const
+{
+ const TQConstString cstr(chs+pos, len);
+ int w = 0;
+
+ const TQString qstr = cstr.string();
+ if ( scFont ) {
+ const TQString upper = qstr.upper();
+ const TQChar *uc = qstr.unicode();
+ const TQFontMetrics sc_fm( *scFont );
+ for ( int i = 0; i < len; ++i ) {
+ if ( (uc+i)->category() == TQChar::Letter_Lowercase )
+ w += sc_fm.charWidth( upper, i );
+ else
+ w += fm.charWidth( qstr, i );
+ }
+ } else {
+ // ### might be a little inaccurate
+ w = fm.width( qstr );
+ }
+
+ if ( letterSpacing )
+ w += len*letterSpacing;
+
+ if ( wordSpacing )
+ // add amount
+ for( int i = 0; i < len; ++i ) {
+ if( chs[i+pos].category() == TQChar::Separator_Space )
+ w += wordSpacing;
+ }
+
+ if ( toAdd ) {
+ // first gather count of spaces
+ int numSpaces = 0;
+ for( int i = start; i != end; ++i )
+ if ( chs[i].category() == TQChar::Separator_Space )
+ ++numSpaces;
+ // distribute pixels evenly among spaces, but count only those within
+ // [pos, pos+len)
+ for ( int i = start; numSpaces && i != pos + len; i++ )
+ if ( chs[i].category() == TQChar::Separator_Space ) {
+ const int a = toAdd/numSpaces;
+ if ( i >= pos ) w += a;
+ toAdd -= a;
+ --numSpaces;
+ }
+ }
+
+ return w;
+}
+
+int Font::width( TQChar *chs, int slen, int pos ) const
+{
+ int w;
+ if ( scFont && chs[pos].category() == TQChar::Letter_Lowercase ) {
+ TQString str( chs, slen );
+ str[pos] = chs[pos].upper();
+ w = TQFontMetrics( *scFont ).charWidth( str, pos );
+ } else {
+ const TQConstString cstr( chs, slen );
+ w = fm.charWidth( cstr.string(), pos );
+ }
+ if ( letterSpacing )
+ w += letterSpacing;
+
+ if ( wordSpacing && (chs+pos)->category() == TQChar::Separator_Space )
+ w += wordSpacing;
+ return w;
+}
+
+/** Querying QFontDB whether something is scalable is expensive, so we cache. */
+struct Font::ScalKey
+{
+ TQString family;
+ int weight;
+ int italic;
+
+ ScalKey(const TQFont& font) :
+ family(font.family()), weight(font.weight()), italic(font.italic())
+ {}
+
+ ScalKey() {}
+
+ bool operator<(const ScalKey& other) const {
+ if (weight < other.weight)
+ return true;
+ if (weight > other.weight)
+ return false;
+
+ if (italic < other.italic)
+ return true;
+ if (italic > other.italic)
+ return false;
+
+ return family < other.family;
+ }
+
+ bool operator==(const ScalKey& other) const {
+ return (weight == other.weight &&
+ italic == other.italic &&
+ family == other.family);
+ }
+};
+
+TQMap<Font::ScalKey, Font::ScalInfo>* Font::scalCache;
+TQMap<Font::ScalKey, TQValueList<int> >* Font::scalSizesCache;
+
+bool Font::isFontScalable(TQFontDatabase& db, const TQFont& font)
+{
+ if (!scalCache)
+ scalCache = new TQMap<ScalKey, ScalInfo>;
+
+ ScalKey key(font);
+
+ ScalInfo &s = (*scalCache)[key];
+ if (s == Unknown) {
+ s = db.isSmoothlyScalable(font.family(), db.styleString(font)) ? Yes : No;
+
+ if (s == No) {
+ /* Cache size info */
+ if (!scalSizesCache)
+ scalSizesCache = new TQMap<ScalKey, TQValueList<int> >;
+ (*scalSizesCache)[key] = db.smoothSizes(font.family(), db.styleString(font));
+ }
+ }
+
+ return (s == Yes);
+}
+
+
+void Font::update( TQPaintDeviceMetrics* devMetrics ) const
+{
+ f.setFamily( fontDef.family.isEmpty() ? KHTMLFactory::defaultHTMLSettings()->stdFontName() : fontDef.family );
+ f.setItalic( fontDef.italic );
+ f.setWeight( fontDef.weight );
+
+ TQFontDatabase db;
+
+ int size = fontDef.size;
+ const int lDpiY = kMax(devMetrics->logicalDpiY(), 96);
+
+ // ok, now some magic to get a nice unscaled font
+ // all other font properties should be set before this one!!!!
+ if( !isFontScalable(db, f) )
+ {
+ const TQValueList<int>& pointSizes = (*scalSizesCache)[ScalKey(f)];
+ // lets see if we find a nice looking font, which is not too far away
+ // from the requested one.
+ // kdDebug(6080) << "tdehtml::setFontSize family = " << f.family() << " size requested=" << size << endl;
+
+
+ float diff = 1; // ### 100% deviation
+ float bestSize = 0;
+
+ TQValueList<int>::ConstIterator it = pointSizes.begin();
+ const TQValueList<int>::ConstIterator itEnd = pointSizes.end();
+
+ for( ; it != itEnd; ++it )
+ {
+ float newDiff = ((*it)*(lDpiY/72.) - float(size))/float(size);
+ //kdDebug( 6080 ) << "smooth font size: " << *it << " diff=" << newDiff << endl;
+ if(newDiff < 0) newDiff = -newDiff;
+ if(newDiff < diff)
+ {
+ diff = newDiff;
+ bestSize = *it;
+ }
+ }
+ //kdDebug( 6080 ) << "best smooth font size: " << bestSize << " diff=" << diff << endl;
+ if ( bestSize != 0 && diff < 0.2 ) // 20% deviation, otherwise we use a scaled font...
+ size = (int)((bestSize*lDpiY) / 72);
+ }
+
+ // make sure we don't bust up X11
+ // Also, Qt does not support sizing a TQFont to zero.
+ size = kMax(1, kMin(255, size));
+
+// tqDebug("setting font to %s, italic=%d, weight=%d, size=%d", fontDef.family.latin1(), fontDef.italic,
+// fontDef.weight, size );
+
+
+ f.setPixelSize( size );
+
+ fm = TQFontMetrics( f );
+
+ // small caps
+ delete scFont;
+ scFont = 0;
+
+ if ( fontDef.smallCaps ) {
+ scFont = new TQFont( f );
+ scFont->setPixelSize( kMax(1, f.pixelSize()*7/10) );
+ }
+}
+
+void Font::drawDecoration(TQPainter *pt, int _tx, int _ty, int baseline, int width, int height, int deco) const
+{
+ Q_UNUSED(height);
+ // thick lines on small fonts look ugly
+ const int thickness = fm.height() > 20 ? fm.lineWidth() : 1;
+ const TQBrush brush = pt->pen().color();
+ if (deco & UNDERLINE) {
+ int underlineOffset = ( fm.height() + baseline ) / 2;
+ if (underlineOffset <= baseline) underlineOffset = baseline+1;
+
+ pt->fillRect(_tx, _ty + underlineOffset, width + 1, thickness, brush );
+ }
+ if (deco & OVERLINE) {
+ pt->fillRect(_tx, _ty, width + 1, thickness, brush );
+ }
+ if (deco & LINE_THROUGH) {
+ pt->fillRect(_tx, _ty + 2*baseline/3, width + 1, thickness, brush );
+ }
+}
+
diff --git a/tdehtml/rendering/font.h b/tdehtml/rendering/font.h
new file mode 100644
index 000000000..81110e0d0
--- /dev/null
+++ b/tdehtml/rendering/font.h
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 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.
+ *
+ */
+
+#ifndef KHTMLFONT_H
+#define KHTMLFONT_H
+
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqmap.h>
+#include <tqpainter.h>
+
+class TQFontDatabase;
+class TQPaintDeviceMetrics;
+
+namespace tdehtml
+{
+class RenderStyle;
+class CSSStyleSelector;
+
+class FontDef
+{
+public:
+ FontDef()
+ : size( 0 ), italic( false ), smallCaps( false ), weight( 50 ) {}
+ bool operator == ( const FontDef &other ) const {
+ return ( family == other.family &&
+ size == other.size &&
+ italic == other.italic &&
+ smallCaps == other.smallCaps &&
+ weight == other.weight );
+ }
+
+ TQString family;
+ short int size;
+ bool italic : 1;
+ bool smallCaps : 1;
+ unsigned int weight : 8;
+};
+
+
+class Font
+{
+ friend class RenderStyle;
+ friend class CSSStyleSelector;
+
+public:
+ Font() : fontDef(), f(), fm( f ), scFont( 0 ), letterSpacing( 0 ), wordSpacing( 0 ) {}
+ Font( const FontDef &fd )
+ : fontDef( fd ), f(), fm( f ), scFont( 0 ), letterSpacing( 0 ), wordSpacing( 0 )
+ {}
+ Font(const Font& o)
+ : fontDef(o.fontDef), f(o.f), fm(o.fm), scFont(o.scFont), letterSpacing(o.letterSpacing), wordSpacing(o.wordSpacing) { if (o.scFont) scFont = new TQFont(*o.scFont); }
+ ~Font() { delete scFont; }
+
+ bool operator == ( const Font &other ) const {
+ return (fontDef == other.fontDef &&
+ letterSpacing == other.letterSpacing &&
+ wordSpacing == other.wordSpacing );
+ }
+
+ const FontDef& getFontDef() const { return fontDef; }
+
+ void update( TQPaintDeviceMetrics *devMetrics ) const;
+
+ /**
+ * Draws a piece from the given piece of text.
+ * @param p painter
+ * @param x x-coordinate to begin drawing, always denotes leftmost position
+ * @param y y-coordinate of baseline of text
+ * @param str string to draw a piece from
+ * @param slen total length of string
+ * @param pos zero-based offset of beginning of piece
+ * @param len length of piece
+ * @param width additional pixels to be distributed equally among all
+ * spaces
+ * @param d text direction
+ * @param from begin with this position relative to @p pos, -1 to start
+ * at @p pos
+ * @param to stop before this position relative to @p pos, -1 to use full
+ * length of piece
+ * @param bg if valid, fill the background of the drawn piece with this
+ * color
+ * @param uy y-coordinate of top position, used for background and text
+ * decoration painting
+ * @param h total height of line, only used for background and text
+ * decoration painting
+ * @param deco combined text decoration (see Decoration)
+ */
+ void drawText( TQPainter *p, int x, int y, TQChar *str, int slen, int pos, int len, int width,
+ TQPainter::TextDirection d, int from=-1, int to=-1, TQColor bg=TQColor(),
+ int uy=-1, int h=-1, int deco=0 ) const;
+
+ /** returns the width of the given string chunk in pixels.
+ *
+ * The method also considers various styles like text-align and font-variant
+ * @param str pointer to string
+ * @param slen total length of string
+ * @param pos zero-based position in string where to start measuring
+ * @param len count of characters up to which the width should be determined
+ * @param start starting position of inline text box within str, only
+ * used when toAdd is specified.
+ * @param end ending position of inline text box within str, only
+ * used when toAdd is specified.
+ * @param toAdd amount of pixels to distribute evenly among all spaces of
+ * str. Note that toAdd applies to all spaces within str, but only those
+ * within [pos, pos+len) are counted towards the width.
+ */
+ int width( TQChar *str, int slen, int pos, int len, int start = 0, int end = 0, int toAdd = 0 ) const;
+ /** return the width of the given char in pixels.
+ *
+ * The method also considers various styles like text-align and font-variant
+ * @param str pointer to string
+ * @param slen total length of string
+ * @param pos zero-based position of char in string
+ */
+ int width( TQChar *str, int slen, int pos) const;
+
+ /** Text decoration constants.
+ *
+ * The enumeration constant values match those of ETextDecoration, but only
+ * a subset is supported.
+ */
+ enum Decoration { UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4 };
+ // Keep in sync with ETextDecoration
+
+ /** draws text decoration
+ * @param p painter
+ * @param x x-coordinate
+ * @param y top y-coordinate of line box
+ * @param baseline baseline
+ * @param width length of decoration in pixels
+ * @param height height of line box
+ * @param deco decoration to be drawn (see Decoration). The enumeration
+ * constants may be combined.
+ */
+ void drawDecoration(TQPainter *p, int x, int y, int baseline, int width, int height, int deco) const;
+
+ /** returns letter spacing
+ */
+ int getLetterSpacing() const { return letterSpacing; }
+ /** returns word spacing
+ */
+ int getWordSpacing() const { return wordSpacing; }
+
+private:
+ mutable FontDef fontDef;
+ mutable TQFont f;
+ mutable TQFontMetrics fm;
+ mutable TQFont *scFont;
+ short letterSpacing;
+ short wordSpacing;
+
+ struct ScalKey;
+ enum ScalInfo {
+ Unknown,
+ No,
+ Yes
+ };
+
+ static TQMap<ScalKey, ScalInfo>* scalCache;
+ static TQMap<ScalKey, TQValueList<int> >* scalSizesCache;
+ static bool isFontScalable(TQFontDatabase& db, const TQFont& font);
+};
+
+} // namespace
+
+#endif
diff --git a/tdehtml/rendering/img-loading.png b/tdehtml/rendering/img-loading.png
new file mode 100644
index 000000000..ae5a9732f
--- /dev/null
+++ b/tdehtml/rendering/img-loading.png
Binary files differ
diff --git a/tdehtml/rendering/loading_icon.cpp b/tdehtml/rendering/loading_icon.cpp
new file mode 100644
index 000000000..218befcf8
--- /dev/null
+++ b/tdehtml/rendering/loading_icon.cpp
@@ -0,0 +1,25 @@
+static const unsigned char loading_icon_data[] = {
+0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,
+0x52,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x08,0x04,0x00,0x00,0x00,0x8c,
+0x9d,0x86,0xb1,0x00,0x00,0x00,0x04,0x67,0x41,0x4d,0x41,0x00,0x00,0xb1,0x8f,
+0x0b,0xfc,0x61,0x05,0x00,0x00,0x00,0x02,0x62,0x4b,0x47,0x44,0x00,0xff,0x87,
+0x8f,0xcc,0xbf,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x12,
+0x00,0x00,0x0b,0x12,0x01,0xd2,0xdd,0x7e,0xfc,0x00,0x00,0x00,0x07,0x74,0x49,
+0x4d,0x45,0x07,0xd4,0x0c,0x17,0x10,0x00,0x23,0xf3,0x04,0xa4,0xbc,0x00,0x00,
+0x00,0xbf,0x49,0x44,0x41,0x54,0x78,0x9c,0x75,0xd1,0x31,0x4e,0x04,0x31,0x0c,
+0x85,0xe1,0x2f,0xc9,0x1c,0x63,0xee,0x02,0x82,0x9a,0x23,0x70,0x01,0xba,0xad,
+0xe8,0x98,0x0d,0x35,0xab,0xe9,0x10,0xf7,0x80,0x76,0xe0,0x32,0x7b,0x01,0x44,
+0x9d,0x84,0x22,0xc3,0x32,0xd2,0x82,0x5d,0xd9,0xbf,0xf5,0xe4,0x67,0x07,0xd9,
+0x59,0x4c,0xf2,0x04,0x91,0xf6,0x47,0x3e,0x64,0x18,0xe0,0x1d,0x51,0x15,0x05,
+0x05,0xc1,0x5e,0xc8,0x79,0x1a,0xba,0x50,0x54,0x3d,0x49,0x76,0xa2,0xaa,0x61,
+0x4f,0x8e,0x1d,0x05,0xb3,0x1b,0xc5,0xb5,0x2a,0x79,0x14,0x04,0xb9,0xcb,0x06,
+0x45,0xf1,0x2a,0x21,0x2a,0x16,0x5c,0x09,0x1d,0x16,0xd1,0xbd,0x4b,0x2c,0xaa,
+0xa4,0x48,0x4e,0x0b,0xf5,0x58,0x24,0xcd,0x2d,0x38,0x6a,0xdd,0x0a,0xd1,0x41,
+0x41,0x01,0xcf,0xa7,0xf1,0x08,0xd5,0x68,0x16,0x11,0x70,0xe7,0x73,0x0b,0x13,
+0x46,0x07,0x34,0x47,0x47,0x5f,0x2b,0x1c,0xa0,0x81,0xd1,0x6c,0x67,0xd9,0x9c,
+0x71,0xe8,0xb2,0x2f,0x6b,0xf9,0xe6,0x43,0xd0,0xd4,0x5f,0x98,0x2c,0x48,0x9a,
+0xba,0xb6,0x37,0x56,0x2e,0xce,0x1f,0xf3,0x03,0xc3,0x3f,0x88,0x6f,0xc1,0xe0,
+0x3e,0x9e,0x60,0xe9,0x10,0xaa,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,
+0x42,0x60,0x82
+};
+static const unsigned int loading_icon_len = 318;
diff --git a/tdehtml/rendering/render_applet.cpp b/tdehtml/rendering/render_applet.cpp
new file mode 100644
index 000000000..1b65ca8de
--- /dev/null
+++ b/tdehtml/rendering/render_applet.cpp
@@ -0,0 +1,145 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (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 <config.h>
+#include <klocale.h>
+
+#include <kdebug.h>
+
+#include "rendering/render_applet.h"
+#include "rendering/render_canvas.h"
+#include "xml/dom_docimpl.h"
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+
+#include <tqlabel.h>
+
+#ifndef Q_WS_QWS // We don't have Java in Qt Embedded
+
+#include "java/kjavaappletwidget.h"
+#include "misc/htmltags.h"
+#include "html/html_objectimpl.h"
+
+using namespace tdehtml;
+using namespace DOM;
+
+RenderApplet::RenderApplet(HTMLElementImpl *applet, const TQMap<TQString, TQString> &args )
+ : RenderWidget(applet)
+{
+ // init RenderObject attributes
+ setInline(true);
+
+ KJavaAppletContext *context = 0;
+ KHTMLView *_view = applet->getDocument()->view();
+ if ( _view ) {
+ KHTMLPart *part = _view->part();
+ context = part->createJavaContext();
+ }
+
+ if ( context ) {
+ //kdDebug(6100) << "RenderApplet::RenderApplet, setting TQWidget" << endl;
+ setQWidget( new KJavaAppletWidget(context, _view->viewport()) );
+ processArguments(args);
+ }
+}
+
+RenderApplet::~RenderApplet()
+{
+}
+
+short RenderApplet::intrinsicWidth() const
+{
+ int rval = 300;
+
+ if( m_widget )
+ rval = ((KJavaAppletWidget*)(m_widget))->sizeHint().width();
+
+ return rval > 10 ? rval : 50;
+}
+
+int RenderApplet::intrinsicHeight() const
+{
+ int rval = 150;
+
+ if( m_widget )
+ rval = m_widget->sizeHint().height();
+
+ return rval > 10 ? rval : 50;
+}
+
+void RenderApplet::layout()
+{
+ //kdDebug(6100) << "RenderApplet::layout" << endl;
+
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ calcWidth();
+ calcHeight();
+
+ KJavaAppletWidget *tmp = static_cast<KJavaAppletWidget*>(m_widget);
+ if ( tmp ) {
+ NodeImpl *child = element()->firstChild();
+
+ while(child) {
+
+ if(child->id() == ID_PARAM) {
+ HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>(child);
+ if(tmp->applet())
+ tmp->applet()->setParameter( p->name(), p->value());
+ }
+ child = child->nextSibling();
+ }
+ //kdDebug(6100) << "setting applet widget to size: " << m_width << ", " << m_height << endl;
+ m_widget->resize(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
+ m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom());
+ tmp->showApplet();
+ }
+
+ setNeedsLayout(false);
+}
+
+void RenderApplet::processArguments(const TQMap<TQString, TQString> &args)
+{
+ KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(m_widget);
+ KJavaApplet* applet = w ? w->applet() : 0;
+
+ if ( applet ) {
+ applet->setBaseURL( args[TQString::fromLatin1("baseURL") ] );
+ applet->setAppletClass( args[TQString::fromLatin1("code") ] );
+
+ TQString str = args[TQString::fromLatin1("codeBase") ];
+ if( !str.isEmpty() )
+ applet->setCodeBase( str );
+
+ str = args[TQString::fromLatin1("name") ];
+ if( !str.isNull() )
+ applet->setAppletName( str );
+ else
+ applet->setAppletName( args[TQString::fromLatin1("code") ] );
+
+ str = args[TQString::fromLatin1("archive") ];
+ if( !str.isEmpty() )
+ applet->setArchives( args[TQString::fromLatin1("archive") ] );
+ }
+}
+
+#endif
diff --git a/tdehtml/rendering/render_applet.h b/tdehtml/rendering/render_applet.h
new file mode 100644
index 000000000..24907edaa
--- /dev/null
+++ b/tdehtml/rendering/render_applet.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (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 render_applet_h
+#define render_applet_h
+
+#include "rendering/render_replaced.h"
+#include "html/html_objectimpl.h"
+
+#include <tqwidget.h>
+#include <tqmap.h>
+
+class KHTMLView;
+
+namespace DOM {
+ class HTMLElementImpl;
+}
+
+namespace tdehtml {
+
+class RenderApplet : public RenderWidget
+{
+public:
+ RenderApplet(DOM::HTMLElementImpl* node, const TQMap<TQString, TQString> &args);
+ virtual ~RenderApplet();
+
+ virtual const char *renderName() const { return "RenderApplet"; }
+
+ virtual void layout();
+ virtual short intrinsicWidth() const;
+ virtual int intrinsicHeight() const;
+ virtual bool isApplet() const { return true; }
+
+ DOM::HTMLElementImpl *element() const
+ { return static_cast<DOM::HTMLElementImpl*>(RenderObject::element()); }
+
+private:
+ void processArguments( const TQMap<TQString, TQString> &args );
+};
+
+}
+#endif
diff --git a/tdehtml/rendering/render_arena.cpp b/tdehtml/rendering/render_arena.cpp
new file mode 100644
index 000000000..14c55ef89
--- /dev/null
+++ b/tdehtml/rendering/render_arena.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2002 Apple Computer, Inc.
+ * Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "render_arena.h"
+
+#include <string.h>
+#include <assert.h>
+
+using namespace tdehtml;
+
+namespace tdehtml {
+
+//#ifdef NDEBUG
+#define KHTML_USE_ARENA_ALLOCATOR
+//#endif
+
+typedef struct {
+ RenderArena *arena;
+ size_t size;
+} RenderArenaDebugHeader;
+
+#ifdef VALGRIND_SUPPORT
+Arena* findContainingArena(ArenaPool* pool, void* ptr) {
+ uword ptrBits = reinterpret_cast<uword>(ptr);
+ for (Arena* a = &pool->first; a; a = a->next)
+ if (ptrBits >= a->base && ptrBits < a->limit)
+ return a;
+ return 0; //Should not happen
+}
+#endif
+
+RenderArena::RenderArena(unsigned int arenaSize)
+{
+ // Initialize the arena pool
+ INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
+
+ // Zero out the recyclers array
+ memset(m_recyclers, 0, sizeof(m_recyclers));
+}
+
+RenderArena::~RenderArena()
+{
+ // Free the arena in the pool and finish using it
+ FreeArenaPool(&m_pool);
+}
+
+void* RenderArena::allocate(size_t size)
+{
+#ifndef KHTML_USE_ARENA_ALLOCATOR
+ // Use standard malloc so that memory debugging tools work.
+ void *block = ::malloc(sizeof(RenderArenaDebugHeader) + size);
+ RenderArenaDebugHeader *header = (RenderArenaDebugHeader *)block;
+ header->arena = this;
+ header->size = size;
+ return header + 1;
+#else
+ void* result = 0;
+
+ // Ensure we have correct alignment for pointers. Important for Tru64
+ size = KHTML_ROUNDUP(size, sizeof(void*));
+
+ // Check recyclers first
+ if (size < KHTML_MAX_RECYCLED_SIZE) {
+ const int index = size >> 2;
+
+ result = m_recyclers[index];
+ if (result) {
+#ifdef VALGRIND_SUPPORT
+ VALGRIND_MEMPOOL_ALLOC(findContainingArena(&m_pool, result)->base, result, size);
+#endif
+ // Need to move to the next object
+ void* next = *((void**)result);
+ m_recyclers[index] = next;
+ }
+ }
+
+ if (!result) {
+ // Allocate a new chunk from the arena
+ ARENA_ALLOCATE(result, &m_pool, size);
+ }
+
+ return result;
+#endif
+}
+
+void RenderArena::free(size_t size, void* ptr)
+{
+#ifndef KHTML_USE_ARENA_ALLOCATOR
+ // Use standard free so that memory debugging tools work.
+ assert(this);
+ RenderArenaDebugHeader *header = (RenderArenaDebugHeader *)ptr - 1;
+ assert(header->size == size);
+ assert(header->arena == this);
+ ::free(header);
+#else
+
+#ifdef VALGRIND_SUPPORT
+ VALGRIND_MEMPOOL_FREE(findContainingArena(&m_pool, ptr)->base, ptr);
+#endif
+
+ // Ensure we have correct alignment for pointers. Important for Tru64
+ size = KHTML_ROUNDUP(size, sizeof(void*));
+
+ // See if it's a size that we recycle
+ if (size < KHTML_MAX_RECYCLED_SIZE) {
+ const int index = size >> 2;
+ void* currentTop = m_recyclers[index];
+ m_recyclers[index] = ptr;
+ *((void**)ptr) = currentTop;
+ }
+#endif
+}
+
+}
diff --git a/tdehtml/rendering/render_arena.h b/tdehtml/rendering/render_arena.h
new file mode 100644
index 000000000..1beab6fed
--- /dev/null
+++ b/tdehtml/rendering/render_arena.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2002 Apple Computer, Inc.
+ * Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef RENDERARENA_H
+#define RENDERARENA_H
+
+#include "misc/arena.h"
+#include "misc/shared.h"
+
+#include <stdlib.h>
+
+namespace tdehtml {
+
+#define KHTML_MAX_RECYCLED_SIZE 400
+#define KHTML_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+
+class RenderArena: public Shared<RenderArena> {
+public:
+ RenderArena(unsigned int arenaSize = 4096);
+ ~RenderArena();
+
+ // Memory management functions
+ void* allocate(size_t size);
+ void free(size_t size, void* ptr);
+
+private:
+ // Underlying arena pool
+ ArenaPool m_pool;
+
+ // The recycler array is sparse with the indices being multiples of 4,
+ // i.e., 0, 4, 8, 12, 16, 20, ...
+ void* m_recyclers[KHTML_MAX_RECYCLED_SIZE >> 2];
+};
+
+
+} // namespace
+
+
+#endif
+
diff --git a/tdehtml/rendering/render_block.cpp b/tdehtml/rendering/render_block.cpp
new file mode 100644
index 000000000..3c6c79543
--- /dev/null
+++ b/tdehtml/rendering/render_block.cpp
@@ -0,0 +1,3155 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2003,2005 Apple Computer, Inc.
+ * (C) 2004 Germain Garand (germain@ebooksfrance.org)
+ * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * (C) 2006 Charles Samuels (charles@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.
+ *
+ */
+
+//#define DEBUG
+//#define DEBUG_LAYOUT
+//#define BOX_DEBUG
+//#define FLOAT_DEBUG
+//#define PAGE_DEBUG
+
+#include <kdebug.h>
+#include "rendering/render_text.h"
+#include "rendering/render_table.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_layer.h"
+#include "rendering/render_block.h"
+
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "html/html_formimpl.h"
+#include "misc/htmltags.h"
+
+#include "tdehtmlview.h"
+
+using namespace DOM;
+
+namespace tdehtml {
+
+// -------------------------------------------------------------------------------------------------------
+
+// Our MarginInfo state used when laying out block children.
+RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
+{
+ // Whether or not we can collapse our own margins with our children. We don't do this
+ // if we had any border/padding (obviously), if we're the root or HTML elements, or if
+ // we're positioned, floating, a table cell.
+ m_canCollapseWithChildren = !block->isCanvas() && !block->isRoot() && !block->isPositioned() &&
+ !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();
+
+ m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) /*&& block->style()->marginTopCollapse() != MSEPARATE */;
+
+ // If any height other than auto is specified in CSS, then we don't collapse our bottom
+ // margins with our children's margins. To do otherwise would be to risk odd visual
+ // effects when the children overflow out of the parent block and yet still collapse
+ // with it. We also don't collapse if we have any bottom border/padding.
+ m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
+ (block->style()->height().isVariable() && block->style()->height().value() == 0) /*&& block->style()->marginBottomCollapse() != MSEPARATE*/;
+
+ m_quirkContainer = block->isTableCell() || block->isBody() /*|| block->style()->marginTopCollapse() == MDISCARD ||
+ block->style()->marginBottomCollapse() == MDISCARD*/;
+
+ m_atTopOfBlock = true;
+ m_atBottomOfBlock = false;
+
+ m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
+ m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
+
+ m_selfCollapsingBlockClearedFloat = false;
+
+ m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
+}
+
+// -------------------------------------------------------------------------------------------------------
+
+RenderBlock::RenderBlock(DOM::NodeImpl* node)
+ : RenderFlow(node)
+{
+ m_childrenInline = true;
+ m_floatingObjects = 0;
+ m_positionedObjects = 0;
+ m_firstLine = false;
+ m_avoidPageBreak = false;
+ m_clearStatus = CNONE;
+ m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
+ m_topMarginQuirk = m_bottomMarginQuirk = false;
+ m_overflowHeight = m_overflowWidth = 0;
+ m_overflowLeft = m_overflowTop = 0;
+}
+
+RenderBlock::~RenderBlock()
+{
+ delete m_floatingObjects;
+ delete m_positionedObjects;
+}
+
+void RenderBlock::setStyle(RenderStyle* _style)
+{
+ setReplaced(_style->isDisplayReplacedType());
+
+ RenderFlow::setStyle(_style);
+
+ // ### we could save this call when the change only affected
+ // non inherited properties
+ RenderObject *child = firstChild();
+ while (child != 0)
+ {
+ if (child->isAnonymousBlock())
+ {
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(BLOCK);
+ child->setStyle(newStyle);
+ }
+ child = child->nextSibling();
+ }
+
+ if (attached()) {
+ // Update generated content and ::inside
+ updateReplacedContent();
+ // Update pseudos for :before and :after
+ updatePseudoChildren();
+ }
+
+ // handled by close() during parsing
+ // ### remove close move upto updatePseudo
+ if (!document()->parsing()) {
+ updateFirstLetter();
+ }
+}
+
+// Attach handles initial setStyle that requires parent nodes
+void RenderBlock::attach()
+{
+ RenderFlow::attach();
+
+ updateReplacedContent();
+ updatePseudoChildren();
+}
+
+void RenderBlock::updateFirstLetter()
+{
+ // Only blocks with inline-children can generate a first-letter
+ if (!childrenInline() || !firstChild()) return;
+
+ // Don't recurse
+ if (style()->styleType() == RenderStyle::FIRST_LETTER) return;
+
+ // The first-letter style is inheritable.
+ RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LETTER);
+ RenderObject *o = this;
+ while (o && !pseudoStyle) {
+ // ### We should ignore empty preceding siblings
+ if (o->parent() && o->parent()->firstChild() == this)
+ o = o->parent();
+ else
+ break;
+ pseudoStyle = o->style()->getPseudoStyle(RenderStyle::FIRST_LETTER);
+ };
+
+ // FIXME: Currently we don't delete first-letters, this is
+ // handled instead in NodeImpl::diff by issuing Detach on first-letter changes.
+ if (!pseudoStyle) {
+ return;
+ }
+
+ // Drill into inlines looking for our first text child.
+ RenderObject* firstText = firstChild();
+ while (firstText && firstText->needsLayout() && !firstText->isFloating() && !firstText->isRenderBlock() && !firstText->isReplaced() && !firstText->isText())
+ // ### We should skip first children with only white-space and punctuation
+ firstText = firstText->firstChild();
+
+ if (firstText && firstText->isText() && !firstText->isBR()) {
+ RenderObject* firstLetterObject = 0;
+ // Find the old first-letter
+ if (firstText->parent()->style()->styleType() == RenderStyle::FIRST_LETTER)
+ firstLetterObject = firstText->parent();
+
+ // Force inline display (except for floating first-letters)
+ pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);
+ pseudoStyle->setPosition( STATIC ); // CSS2 says first-letter can't be positioned.
+
+ if (firstLetterObject != 0) {
+ firstLetterObject->setStyle( pseudoStyle );
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom( pseudoStyle );
+ firstText->setStyle( newStyle );
+ return;
+ }
+
+ RenderText* textObj = static_cast<RenderText*>(firstText);
+ RenderObject* firstLetterContainer = firstText->parent();
+
+ firstLetterObject = RenderFlow::createFlow(node(), pseudoStyle, renderArena() );
+ firstLetterObject->setIsAnonymous( true );
+ firstLetterContainer->addChild(firstLetterObject, firstLetterContainer->firstChild());
+
+ // if this object is the result of a :begin, then the text may have not been
+ // generated yet if it is a counter
+ if (textObj->recalcMinMax())
+ textObj->recalcMinMaxWidths();
+
+ // The original string is going to be either a generated content string or a DOM node's
+ // string. We want the original string before it got transformed in case first-letter has
+ // no text-transform or a different text-transform applied to it.
+ DOMStringImpl* oldText = textObj->originalString();
+ if (!oldText)
+ oldText = textObj->string();
+ // ### In theory a first-letter can stretch across multiple text objects, if they only contain
+ // punctuation and white-space
+ if(oldText->l >= 1) {
+ oldText->ref();
+ // begin: we need skip leading whitespace so that RenderBlock::findNextLineBreak
+ // won't think we're continuing from a previous run
+ unsigned int begin = 0; // the position that first-letter begins
+ unsigned int length = 0; // the position that "the rest" begins
+ while ( length < oldText->l && (oldText->s+length)->isSpace() )
+ length++;
+ begin = length;
+ while ( length < oldText->l &&
+ ( (oldText->s+length)->isPunct()) || (oldText->s+length)->isSpace() )
+ length++;
+ if ( length < oldText->l &&
+ !( (oldText->s+length)->isSpace() || (oldText->s+length)->isPunct() ))
+ length++;
+ while ( length < oldText->l && (oldText->s+length)->isMark() )
+ length++;
+
+ // we need to generated a remainingText object even if no text is left
+ // because it holds the place and style for the old textObj
+ RenderTextFragment* remainingText =
+ new (renderArena()) RenderTextFragment(textObj->node(), oldText, length, oldText->l-length);
+ remainingText->setIsAnonymous( textObj->isAnonymous() );
+ remainingText->setStyle(textObj->style());
+ if (remainingText->element())
+ remainingText->element()->setRenderer(remainingText);
+
+ RenderObject* nextObj = textObj->nextSibling();
+ textObj->detach();
+ firstLetterContainer->addChild(remainingText, nextObj);
+
+ RenderTextFragment* letter =
+ new (renderArena()) RenderTextFragment(remainingText->node(), oldText, begin, length-begin);
+ letter->setIsAnonymous( remainingText->isAnonymous() );
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom(pseudoStyle);
+ letter->setStyle(newStyle);
+ firstLetterObject->addChild(letter);
+ oldText->deref();
+ }
+ firstLetterObject->close();
+ }
+}
+
+void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+{
+ // Make sure we don't append things after :after-generated content if we have it.
+ if ( !beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER )
+ beforeChild = lastChild();
+
+ bool madeBoxesNonInline = false;
+
+ // If the requested beforeChild is not one of our children, then this is most likely because
+ // there is an anonymous block box within this object that contains the beforeChild. So
+ // just insert the child into the anonymous block box instead of here. This may also be
+ // needed in cases of things like anonymous tables.
+ if (beforeChild && beforeChild->parent() != this) {
+
+ KHTMLAssert(beforeChild->parent());
+
+ // In the special case where we are prepending a block-level element before
+ // something contained inside an anonymous block, we can just prepend it before
+ // the anonymous block.
+ if (!newChild->isInline() && beforeChild->parent()->isAnonymousBlock() &&
+ beforeChild->parent()->parent() == this &&
+ beforeChild->parent()->firstChild() == beforeChild)
+ return addChildToFlow(newChild, beforeChild->parent());
+
+ // Otherwise find our kid inside which the beforeChild is, and delegate to it.
+ // This may be many levels deep due to anonymous tables, table sections, etc.
+ RenderObject* responsible = beforeChild->parent();
+ while (responsible->parent() != this)
+ responsible = responsible->parent();
+
+ return responsible->addChild(newChild,beforeChild);
+ }
+
+ // prevent elements that haven't received a layout yet from getting painted by pushing
+ // them far above the top of the page
+ if (!newChild->isInline())
+ newChild->setPos(newChild->xPos(), -500000);
+
+ if (!newChild->isText() && newChild->style()->position() != STATIC)
+ setOverhangingContents();
+
+ // A block has to either have all of its children inline, or all of its children as blocks.
+ // So, if our children are currently inline and a block child has to be inserted, we move all our
+ // inline children into anonymous block boxes
+ if ( m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned() )
+ {
+ // This is a block with inline content. Wrap the inline content in anonymous blocks.
+ makeChildrenNonInline(beforeChild);
+ madeBoxesNonInline = true;
+
+ if (beforeChild && beforeChild->parent() != this) {
+ beforeChild = beforeChild->parent();
+ KHTMLAssert(beforeChild->isAnonymousBlock());
+ KHTMLAssert(beforeChild->parent() == this);
+ }
+ }
+ else if (!m_childrenInline && !newChild->isFloatingOrPositioned())
+ {
+ // If we're inserting an inline child but all of our children are blocks, then we have to make sure
+ // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
+ // a new one is created and inserted into our list of children in the appropriate position.
+ if (newChild->isInline()) {
+ if (beforeChild) {
+ if ( beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousBlock() ) {
+ beforeChild->previousSibling()->addChild(newChild);
+ return;
+ }
+ }
+ else {
+ if ( m_last && m_last->isAnonymousBlock() ) {
+ m_last->addChild(newChild);
+ return;
+ }
+ }
+
+ // no suitable existing anonymous box - create a new one
+ RenderBlock* newBox = createAnonymousBlock();
+ RenderBox::addChild(newBox,beforeChild);
+ newBox->addChild(newChild);
+
+ //the above may actually destroy newBox in case an anonymous
+ //table got created, and made the anonymous block redundant.
+ //so look up what to hide indirectly.
+ RenderObject* toHide = newChild;
+ while (toHide->parent() != this)
+ toHide = toHide->parent();
+
+ toHide->setPos(toHide->xPos(), -500000);
+ return;
+ }
+ else {
+ // We are adding another block child... if the current last child is an anonymous box
+ // then it needs to be closed.
+ // ### get rid of the closing thing altogether this will only work during initial parsing
+ if (lastChild() && lastChild()->isAnonymous()) {
+ lastChild()->close();
+ }
+ }
+ }
+
+ RenderBox::addChild(newChild,beforeChild);
+ // ### care about aligned stuff
+
+ if ( madeBoxesNonInline )
+ removeLeftoverAnonymousBoxes();
+}
+
+static void getInlineRun(RenderObject* start, RenderObject* stop,
+ RenderObject*& inlineRunStart,
+ RenderObject*& inlineRunEnd)
+{
+ // Beginning at |start| we find the largest contiguous run of inlines that
+ // we can. We denote the run with start and end points, |inlineRunStart|
+ // and |inlineRunEnd|. Note that these two values may be the same if
+ // we encounter only one inline.
+ //
+ // We skip any non-inlines we encounter as long as we haven't found any
+ // inlines yet.
+ //
+ // |stop| indicates a non-inclusive stop point. Regardless of whether |stop|
+ // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
+ // a non-inline.
+
+ RenderObject * curr = start;
+ bool sawInline;
+ do {
+ while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
+ curr = curr->nextSibling();
+
+ inlineRunStart = inlineRunEnd = curr;
+
+ if (!curr)
+ return; // No more inline children to be found.
+
+ sawInline = curr->isInline();
+
+ curr = curr->nextSibling();
+ while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != stop)) {
+ inlineRunEnd = curr;
+ if (curr->isInline())
+ sawInline = true;
+ curr = curr->nextSibling();
+ }
+ } while (!sawInline);
+
+}
+
+void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
+{
+ // makeChildrenNonInline takes a block whose children are *all* inline and it
+ // makes sure that inline children are coalesced under anonymous
+ // blocks. If |insertionPoint| is defined, then it represents the insertion point for
+ // the new block child that is causing us to have to wrap all the inlines. This
+ // means that we cannot coalesce inlines before |insertionPoint| with inlines following
+ // |insertionPoint|, because the new child is going to be inserted in between the inlines,
+ // splitting them.
+ KHTMLAssert(isReplacedBlock() || !isInline());
+ KHTMLAssert(!insertionPoint || insertionPoint->parent() == this);
+
+ m_childrenInline = false;
+
+ RenderObject *child = firstChild();
+
+ while (child) {
+ RenderObject *inlineRunStart, *inlineRunEnd;
+ getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
+
+ if (!inlineRunStart)
+ break;
+
+ child = inlineRunEnd->nextSibling();
+
+ RenderBlock* box = createAnonymousBlock();
+ insertChildNode(box, inlineRunStart);
+ RenderObject* o = inlineRunStart;
+ while(o != inlineRunEnd)
+ {
+ RenderObject* no = o;
+ o = no->nextSibling();
+ box->appendChildNode(removeChildNode(no));
+ }
+ box->appendChildNode(removeChildNode(inlineRunEnd));
+ box->close();
+ box->setPos(box->xPos(), -500000);
+ }
+}
+
+void RenderBlock::makePageBreakAvoidBlocks()
+{
+ KHTMLAssert(!childrenInline());
+ KHTMLAssert(canvas()->pagedMode());
+
+ RenderObject *breakAfter = firstChild();
+ RenderObject *breakBefore = breakAfter ? breakAfter->nextSibling() : 0;
+
+ RenderBlock* pageRun = 0;
+
+ // ### Should follow margin-collapsing rules, skipping self-collapsing blocks
+ // and exporting page-breaks from first/last child when collapsing with parent margin.
+ while (breakAfter) {
+ if (breakAfter->isRenderBlock() && !breakAfter->childrenInline())
+ static_cast<RenderBlock*>(breakAfter)->makePageBreakAvoidBlocks();
+ EPageBreak pbafter = breakAfter->style()->pageBreakAfter();
+ EPageBreak pbbefore = breakBefore ? breakBefore->style()->pageBreakBefore() : PBALWAYS;
+ if ((pbafter == PBAVOID && pbbefore == PBAVOID) ||
+ (pbafter == PBAVOID && pbbefore == PBAUTO) ||
+ (pbafter == PBAUTO && pbbefore == PBAVOID))
+ {
+ if (!pageRun) {
+ pageRun = createAnonymousBlock();
+ pageRun->m_avoidPageBreak = true;
+ pageRun->setChildrenInline(false);
+ }
+ pageRun->appendChildNode(removeChildNode(breakAfter));
+ } else
+ {
+ if (pageRun) {
+ pageRun->appendChildNode(removeChildNode(breakAfter));
+ pageRun->close();
+ insertChildNode(pageRun, breakBefore);
+ pageRun = 0;
+ }
+ }
+ breakAfter = breakBefore;
+ breakBefore = breakBefore ? breakBefore->nextSibling() : 0;
+ }
+
+ // recurse into positioned block children as well.
+ if (m_positionedObjects) {
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; it.current(); ++it ) {
+ if (it.current()->isRenderBlock() && !it.current()->childrenInline()) {
+ static_cast<RenderBlock*>(it.current())->makePageBreakAvoidBlocks();
+ }
+ }
+ }
+
+ // recurse into floating block children.
+ if (m_floatingObjects) {
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; it.current(); ++it ) {
+ if (it.current()->node->isRenderBlock() && !it.current()->node->childrenInline()) {
+ static_cast<RenderBlock*>(it.current()->node)->makePageBreakAvoidBlocks();
+ }
+ }
+ }
+}
+
+void RenderBlock::removeChild(RenderObject *oldChild)
+{
+ // If this child is a block, and if our previous and next siblings are
+ // both anonymous blocks with inline content, then we can go ahead and
+ // fold the inline content back together.
+ RenderObject* prev = oldChild->previousSibling();
+ RenderObject* next = oldChild->nextSibling();
+ bool mergedBlocks = false;
+ if (document()->renderer() && !isInline() && !oldChild->isInline() && !oldChild->continuation() &&
+ prev && prev->isAnonymousBlock() && prev->childrenInline() &&
+ next && next->isAnonymousBlock() && next->childrenInline()) {
+ // Take all the children out of the |next| block and put them in
+ // the |prev| block.
+ RenderObject* o = next->firstChild();
+ while (o) {
+ RenderObject* no = o;
+ o = no->nextSibling();
+ prev->appendChildNode(next->removeChildNode(no));
+ no->setNeedsLayoutAndMinMaxRecalc();
+ }
+ prev->setNeedsLayoutAndMinMaxRecalc();
+
+ // Nuke the now-empty block.
+ next->detach();
+
+ mergedBlocks = true;
+ }
+
+ RenderFlow::removeChild(oldChild);
+
+ if (mergedBlocks && prev && !prev->previousSibling() && !prev->nextSibling()) {
+ // The remerge has knocked us down to containing only a single anonymous
+ // box. We can go ahead and pull the content right back up into our
+ // box.
+ RenderObject* anonBlock = removeChildNode(prev);
+ m_childrenInline = true;
+ RenderObject* o = anonBlock->firstChild();
+ while (o) {
+ RenderObject* no = o;
+ o = no->nextSibling();
+ appendChildNode(anonBlock->removeChildNode(no));
+ no->setNeedsLayoutAndMinMaxRecalc();
+ }
+
+ // Nuke the now-empty block.
+ anonBlock->detach();
+ }
+}
+
+bool RenderBlock::isSelfCollapsingBlock() const
+{
+ // We are not self-collapsing if we
+ // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
+ // (b) are a table,
+ // (c) have border/padding,
+ // (d) have a min-height
+ if (m_height > 0 ||
+ isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
+ style()->minHeight().value() > 0)
+ return false;
+
+ bool hasAutoHeight = style()->height().isVariable();
+ if (style()->height().isPercent() && !style()->htmlHacks()) {
+ hasAutoHeight = true;
+ for (RenderBlock* cb = containingBlock(); !cb->isCanvas(); cb = cb->containingBlock()) {
+ if (cb->style()->height().isFixed() || cb->isTableCell())
+ hasAutoHeight = false;
+ }
+ }
+
+ // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
+ // on whether we have content that is all self-collapsing or not.
+ if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().value() == 0)) {
+ // If the block has inline children, see if we generated any line boxes. If we have any
+ // line boxes, then we can't be self-collapsing, since we have content.
+ if (childrenInline())
+ return !firstLineBox();
+
+ // Whether or not we collapse is dependent on whether all our normal flow children
+ // are also self-collapsing.
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isFloatingOrPositioned())
+ continue;
+ if (!child->isSelfCollapsingBlock())
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+void RenderBlock::layout()
+{
+ // Table cells call layoutBlock directly, so don't add any logic here. Put code into
+ // layoutBlock().
+ layoutBlock(false);
+}
+
+void RenderBlock::layoutBlock(bool relayoutChildren)
+{
+ if (isInline() && !isReplacedBlock()) {
+ setNeedsLayout(false);
+ return;
+ }
+ // kdDebug( 6040 ) << renderName() << " " << this << "::layoutBlock() start" << endl;
+ // TQTime t;
+ // t.start();
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ if (canvas()->pagedMode()) relayoutChildren = true;
+
+ if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
+ // All we have to is lay out our positioned objects.
+ layoutPositionedObjects(relayoutChildren);
+ if (hasOverflowClip())
+ m_layer->checkScrollbarsAfterLayout();
+ setNeedsLayout(false);
+ return;
+ }
+
+ if (markedForRepaint()) {
+ repaintDuringLayout();
+ setMarkedForRepaint(false);
+ }
+
+ int oldWidth = m_width;
+
+ calcWidth();
+ m_overflowWidth = m_width;
+ m_overflowLeft = 0;
+ if (style()->direction() == LTR )
+ {
+ int cw=0;
+ if (style()->textIndent().isPercent())
+ cw = containingBlock()->contentWidth();
+ m_overflowLeft = kMin(0, style()->textIndent().minWidth(cw));
+ }
+
+ if ( oldWidth != m_width )
+ relayoutChildren = true;
+
+ // kdDebug( 6040 ) << floatingObjects << "," << oldWidth << ","
+ // << m_width << ","<< needsLayout() << "," << isAnonymousBox() << ","
+ // << overhangingContents() << "," << isPositioned() << endl;
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderBlock) " << this << " ::layout() width=" << m_width << ", needsLayout=" << needsLayout() << endl;
+ if(containingBlock() == static_cast<RenderObject *>(this))
+ kdDebug( 6040 ) << renderName() << ": containingBlock == this" << endl;
+#endif
+
+ clearFloats();
+
+ int previousHeight = m_height;
+ m_height = 0;
+ m_overflowHeight = 0;
+ m_clearStatus = CNONE;
+
+ // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
+ // our current maximal positive and negative margins. These values are used when we
+ // are collapsed with adjacent blocks, so for example, if you have block A and B
+ // collapsing together, then you'd take the maximal positive margin from both A and B
+ // and subtract it from the maximal negative margin from both A and B to get the
+ // true collapsed margin. This algorithm is recursive, so when we finish layout()
+ // our block knows its current maximal positive/negative values.
+ //
+ // Start out by setting our margin values to our current margins. Table cells have
+ // no margins, so we don't fill in the values for table cells.
+ if (!isTableCell()) {
+ initMaxMarginValues();
+
+ m_topMarginQuirk = style()->marginTop().isQuirk();
+ m_bottomMarginQuirk = style()->marginBottom().isQuirk();
+
+ if (element() && element()->id() == ID_FORM && static_cast<HTMLFormElementImpl*>(element())->isMalformed())
+ // See if this form is malformed (i.e., unclosed). If so, don't give the form
+ // a bottom margin.
+ m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
+ }
+
+ if (scrollsOverflow() && m_layer) {
+ // For overflow:scroll blocks, ensure we have both scrollbars in place always.
+ if (style()->overflowX() == OSCROLL)
+ m_layer->showScrollbar( Qt::Horizontal, true );
+ if (style()->overflowY() == OSCROLL)
+ m_layer->showScrollbar( Qt::Vertical, true );
+ }
+
+ setContainsPageBreak(false);
+
+ if (childrenInline())
+ layoutInlineChildren( relayoutChildren );
+ else
+ layoutBlockChildren( relayoutChildren );
+
+ // Expand our intrinsic height to encompass floats.
+ int toAdd = borderBottom() + paddingBottom();
+ if (m_layer && scrollsOverflowX() && style()->height().isVariable())
+ toAdd += m_layer->horizontalScrollbarHeight();
+ if ( hasOverhangingFloats() && (isFloatingOrPositioned() || flowAroundFloats()) )
+ m_overflowHeight = m_height = floatBottom() + toAdd;
+
+ int oldHeight = m_height;
+ calcHeight();
+ if (oldHeight != m_height) {
+ m_overflowHeight -= toAdd;
+ if (m_layer && scrollsOverflowY()) {
+ // overflow-height only includes padding-bottom when it scrolls
+ m_overflowHeight += paddingBottom();
+ }
+ // If the block got expanded in size, then increase our overflowheight to match.
+ if (m_overflowHeight < m_height)
+ m_overflowHeight = m_height;
+ }
+ if (previousHeight != m_height)
+ relayoutChildren = true;
+
+ if (isTableCell()) {
+ // Table cells need to grow to accommodate both overhanging floats and
+ // blocks that have overflowed content.
+ // Check for an overhanging float first.
+ // FIXME: This needs to look at the last flow, not the last child.
+ if (lastChild() && lastChild()->hasOverhangingFloats() && !lastChild()->hasOverflowClip()) {
+ KHTMLAssert(lastChild()->isRenderBlock());
+ m_height = lastChild()->yPos() + static_cast<RenderBlock*>(lastChild())->floatBottom();
+ m_height += borderBottom() + paddingBottom();
+ }
+
+ if (m_overflowHeight > m_height && !hasOverflowClip())
+ m_height = m_overflowHeight + borderBottom() + paddingBottom();
+ }
+
+ if( hasOverhangingFloats() && ((isFloating() && style()->height().isVariable()) || isTableCell())) {
+ m_height = floatBottom();
+ m_height += borderBottom() + paddingBottom();
+ }
+
+ if (canvas()->pagedMode()) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " Page Bottom: " << pageTopAfter(0) << endl;
+ kdDebug(6040) << renderName() << " Bottom: " << m_height << endl;
+#endif
+ bool needsPageBreak = false;
+ int xpage = crossesPageBreak(0, m_height);
+ if (xpage) {
+ needsPageBreak = true;
+#ifdef PAGE_DEBUG
+ kdDebug( 6040 ) << renderName() << " crosses to page " << xpage << endl;
+#endif
+ }
+ if (needsPageBreak && !containsPageBreak()) {
+ setNeedsPageClear(true);
+#ifdef PAGE_DEBUG
+ kdDebug( 6040 ) << renderName() << " marked for page-clear" << endl;
+#endif
+ }
+ }
+
+ layoutPositionedObjects( relayoutChildren );
+
+ // Always ensure our overflow width/height are at least as large as our width/height.
+ m_overflowWidth = kMax(m_overflowWidth, (int)m_width);
+ m_overflowHeight = kMax(m_overflowHeight, m_height);
+
+ // Update our scrollbars if we're overflow:auto/scroll now that we know if
+ // we overflow or not.
+ if (hasOverflowClip() && m_layer)
+ m_layer->checkScrollbarsAfterLayout();
+
+ setNeedsLayout(false);
+}
+
+void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
+{
+ if (child->isBox() && child->hasStaticX()) {
+ if (style()->direction() == LTR)
+ static_cast<RenderBox*>(child)->setStaticX(borderLeft() + paddingLeft());
+ else
+ static_cast<RenderBox*>(child)->setStaticX(borderRight() + paddingRight());
+ }
+
+ if (child->isBox() && child->hasStaticY()) {
+ int y = m_height;
+ if (!marginInfo.canCollapseWithTop()) {
+ child->calcVerticalMargins();
+ int marginTop = child->marginTop();
+ int collapsedTopPos = marginInfo.posMargin();
+ int collapsedTopNeg = marginInfo.negMargin();
+ if (marginTop > 0) {
+ if (marginTop > collapsedTopPos)
+ collapsedTopPos = marginTop;
+ } else {
+ if (-marginTop > collapsedTopNeg)
+ collapsedTopNeg = -marginTop;
+ }
+ y += (collapsedTopPos - collapsedTopNeg) - marginTop;
+ }
+ static_cast<RenderBox*>(child)->setStaticY(y);
+ }
+}
+
+void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
+{
+ // The float should be positioned taking into account the bottom margin
+ // of the previous flow. We add that margin into the height, get the
+ // float positioned properly, and then subtract the margin out of the
+ // height again. In the case of self-collapsing blocks, we always just
+ // use the top margins, since the self-collapsing block collapsed its
+ // own bottom margin into its top margin.
+ //
+ // Note also that the previous flow may collapse its margin into the top of
+ // our block. If this is the case, then we do not add the margin in to our
+ // height when computing the position of the float. This condition can be tested
+ // for by simply calling canCollapseWithTop. See
+ // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
+ // an example of this scenario.
+ int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
+ m_height += marginOffset;
+ positionNewFloats();
+ m_height -= marginOffset;
+}
+
+RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
+{
+ // Handle positioned children first.
+ RenderObject* next = handlePositionedChild(child, marginInfo, handled);
+ if (handled) return next;
+
+ // Handle floating children next.
+ next = handleFloatingChild(child, marginInfo, handled);
+ if (handled) return next;
+
+ // See if we have a compact element. If we do, then try to tuck the compact element into the margin space of the next block.
+ next = handleCompactChild(child, compactInfo, marginInfo, handled);
+ if (handled) return next;
+
+ // Finally, see if we have a run-in element.
+ return handleRunInChild(child, handled);
+}
+
+RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+{
+ if (child->isPositioned()) {
+ handled = true;
+ child->containingBlock()->insertPositionedObject(child);
+ adjustPositionedBlock(child, marginInfo);
+ return child->nextSibling();
+ }
+ return 0;
+}
+
+RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+{
+ if (child->isFloating()) {
+ handled = true;
+ insertFloatingObject(child);
+ adjustFloatingBlock(marginInfo);
+ return child->nextSibling();
+ }
+ return 0;
+}
+
+static inline bool isAnonymousWhitespace( RenderObject* o ) {
+ if (!o->isAnonymous())
+ return false;
+ RenderObject *fc = o->firstChild();
+ return fc && fc == o->lastChild() && fc->isText() && static_cast<RenderText *>(fc)->stringLength() == 1 &&
+ static_cast<RenderText *>(fc)->text()[0].unicode() == ' ';
+}
+
+RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, const MarginInfo& marginInfo, bool& handled)
+{
+ // FIXME: We only deal with one compact at a time. It is unclear what should be
+ // done if multiple contiguous compacts are encountered. For now we assume that
+ // compact A followed by another compact B should simply be treated as block A.
+ if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
+ // Get the next non-positioned/non-floating RenderBlock.
+ RenderObject* next = child->nextSibling();
+ RenderObject* curr = next;
+ while (curr && (curr->isFloatingOrPositioned() || isAnonymousWhitespace(curr)) )
+ curr = curr->nextSibling();
+ if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
+ curr->calcWidth(); // So that horizontal margins are correct.
+ // Need to compute margins for the child as though it is a block.
+ child->style()->setDisplay(BLOCK);
+ child->calcWidth();
+ child->style()->setDisplay(COMPACT);
+
+ int childMargins = child->marginLeft() + child->marginRight();
+ int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
+ if (margin >= (childMargins + child->maxWidth())) {
+ // The compact will fit in the margin.
+ handled = true;
+ compactInfo.set(child, curr);
+ child->layoutIfNeeded();
+ int off = marginInfo.margin();
+ m_height += off + curr->marginTop() < child->marginTop() ?
+ child->marginTop() - curr->marginTop() -off: 0;
+
+ child->setPos(0,0); // This position will be updated to reflect the compact's
+ // desired position and the line box for the compact will
+ // pick that position up.
+ return next;
+ }
+ }
+ }
+ return 0;
+}
+
+void RenderBlock::adjustSizeForCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
+{
+ // if the compact is bigger than the block it was run into
+ // then "this" block should take the height of the compact
+ if (compactInfo.matches(child)) {
+ // We have a compact child to squeeze in.
+ RenderObject* compactChild = compactInfo.compact();
+ if (compactChild->height() > child->height())
+ m_height += compactChild->height() - child->height();
+ }
+}
+
+void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
+{
+ if (compactInfo.matches(child)) {
+ // We have a compact child to squeeze in.
+ RenderObject* compactChild = compactInfo.compact();
+ int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
+ if (style()->direction() == RTL) {
+ compactChild->calcWidth(); // have to do this because of the capped maxwidth
+ compactXPos = width() - borderRight() - paddingRight() -
+ compactChild->width() - compactChild->marginRight();
+ }
+
+ int compactYPos = child->yPos() + child->borderTop() + child->paddingTop()
+ - compactChild->paddingTop() - compactChild->borderTop();
+ int adj = 0;
+ KHTMLAssert(child->isRenderBlock());
+ InlineRunBox *b = static_cast<RenderBlock*>(child)->firstLineBox();
+ InlineRunBox *c = static_cast<RenderBlock*>(compactChild)->firstLineBox();
+ if (b && c) {
+ // adjust our vertical position
+ int vpos = compactChild->getVerticalPosition( true, child );
+ if (vpos == PositionBottom)
+ adj = b->height() > c->height() ? (b->height() + b->yPos() - c->height() - c->yPos()) : 0;
+ else if (vpos == PositionTop)
+ adj = b->yPos() - c->yPos();
+ else
+ adj = vpos;
+ compactYPos += adj;
+ }
+ Length newLineHeight( kMax(compactChild->lineHeight(true)+adj, (int)child->lineHeight(true)), tdehtml::Fixed);
+ child->style()->setLineHeight( newLineHeight );
+ child->setNeedsLayout( true, false );
+ child->layout();
+
+ compactChild->setPos(compactXPos, compactYPos); // Set the x position.
+ compactInfo.clear();
+ }
+}
+
+RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
+{
+ // See if we have a run-in element with inline children. If the
+ // children aren't inline, then just treat the run-in as a normal
+ // block.
+ if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
+ // Get the next non-positioned/non-floating RenderBlock.
+ RenderObject* curr = child->nextSibling();
+ while (curr && (curr->isFloatingOrPositioned() || isAnonymousWhitespace(curr)) )
+ curr = curr->nextSibling();
+ if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
+ // The block acts like an inline, so just null out its
+ // position.
+ handled = true;
+ child->setInline(true);
+ child->setPos(0,0);
+
+ // Remove the child.
+ RenderObject* next = child->nextSibling();
+ removeChildNode(child);
+
+ // Now insert the child under |curr|.
+ curr->insertChildNode(child, curr->firstChild());
+ return next;
+ }
+ }
+ return 0;
+}
+
+void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
+{
+ // Get our max pos and neg top margins.
+ int posTop = child->maxTopMargin(true);
+ int negTop = child->maxTopMargin(false);
+
+ // For self-collapsing blocks, collapse our bottom margins into our
+ // top to get new posTop and negTop values.
+ if (child->isSelfCollapsingBlock()) {
+ posTop = kMax(posTop, (int)child->maxBottomMargin(true));
+ negTop = kMax(negTop, (int)child->maxBottomMargin(false));
+ }
+
+ // See if the top margin is quirky. We only care if this child has
+ // margins that will collapse with us.
+ bool topQuirk = child->isTopMarginQuirk() /*|| style()->marginTopCollapse() == MDISCARD*/;
+
+ if (marginInfo.canCollapseWithTop()) {
+ // This child is collapsing with the top of the
+ // block. If it has larger margin values, then we need to update
+ // our own maximal values.
+ if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk) {
+ m_maxTopPosMargin = kMax(posTop, (int)m_maxTopPosMargin);
+ m_maxTopNegMargin = kMax(negTop, (int)m_maxTopNegMargin);
+ }
+
+ // The minute any of the margins involved isn't a quirk, don't
+ // collapse it away, even if the margin is smaller (www.webreference.com
+ // has an example of this, a <dt> with 0.8em author-specified inside
+ // a <dl> inside a <td>.
+ if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
+ m_topMarginQuirk = false;
+ marginInfo.setDeterminedTopQuirk(true);
+ }
+
+ if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
+ // We have no top margin and our top child has a quirky margin.
+ // We will pick up this quirky margin and pass it through.
+ // This deals with the <td><div><p> case.
+ // Don't do this for a block that split two inlines though. You do
+ // still apply margins in this case.
+ m_topMarginQuirk = true;
+ }
+
+ if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
+ marginInfo.setTopQuirk(topQuirk);
+
+ int ypos = m_height;
+ if (child->isSelfCollapsingBlock()) {
+ // This child has no height. We need to compute our
+ // position before we collapse the child's margins together,
+ // so that we can get an accurate position for the zero-height block.
+ int collapsedTopPos = kMax(marginInfo.posMargin(), (int)child->maxTopMargin(true));
+ int collapsedTopNeg = kMax(marginInfo.negMargin(), (int)child->maxTopMargin(false));
+ marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
+
+ // Now collapse the child's margins together, which means examining our
+ // bottom margin values as well.
+ marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
+ marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));
+
+ if (!marginInfo.canCollapseWithTop())
+ // We need to make sure that the position of the self-collapsing block
+ // is correct, since it could have overflowing content
+ // that needs to be positioned correctly (e.g., a block that
+ // had a specified height of 0 but that actually had subcontent).
+ ypos = m_height + collapsedTopPos - collapsedTopNeg;
+ }
+ else {
+#ifdef APPLE_CHANGES
+ if (child->style()->marginTopCollapse() == MSEPARATE) {
+ m_height += marginInfo.margin() + child->marginTop();
+ ypos = m_height;
+ }
+ else
+#endif
+ if (!marginInfo.atTopOfBlock() ||
+ (!marginInfo.canCollapseTopWithChildren()
+ && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
+ // We're collapsing with a previous sibling's margins and not
+ // with the top of the block.
+ m_height += kMax(marginInfo.posMargin(), posTop) - kMax(marginInfo.negMargin(), negTop);
+ ypos = m_height;
+ }
+
+ marginInfo.setPosMargin(child->maxBottomMargin(true));
+ marginInfo.setNegMargin(child->maxBottomMargin(false));
+
+ if (marginInfo.margin())
+ marginInfo.setBottomQuirk(child->isBottomMarginQuirk() /*|| style()->marginBottomCollapse() == MDISCARD*/);
+
+ marginInfo.setSelfCollapsingBlockClearedFloat(false);
+ }
+
+ child->setPos(child->xPos(), ypos);
+ if (ypos != yPosEstimate) {
+ if (child->style()->width().isPercent() && child->usesLineWidth())
+ // The child's width is a percentage of the line width.
+ // When the child shifts to clear an item, its width can
+ // change (because it has more available line width).
+ // So go ahead and mark the item as dirty.
+ child->setChildNeedsLayout(true);
+
+ if (!child->flowAroundFloats() && child->hasFloats())
+ child->markAllDescendantsWithFloatsForLayout();
+
+ // Our guess was wrong. Make the child lay itself out again.
+ child->layoutIfNeeded();
+ }
+}
+
+void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
+{
+ int heightIncrease = getClearDelta(child);
+ if (heightIncrease) {
+ // The child needs to be lowered. Move the child so that it just clears the float.
+ child->setPos(child->xPos(), child->yPos() + heightIncrease);
+
+ // Increase our height by the amount we had to clear.
+ bool selfCollapsing = child->isSelfCollapsingBlock();
+ if (!selfCollapsing)
+ m_height += heightIncrease;
+ else {
+ // For self-collapsing blocks that clear, they may end up collapsing
+ // into the bottom of the parent block. We simulate this behavior by
+ // setting our positive margin value to compensate for the clear.
+ marginInfo.setPosMargin(kMax(0, child->yPos() - m_height));
+ marginInfo.setNegMargin(0);
+ marginInfo.setSelfCollapsingBlockClearedFloat(true);
+ }
+
+ if (marginInfo.canCollapseWithTop()) {
+ // We can no longer collapse with the top of the block since a clear
+ // occurred. The empty blocks collapse into the cleared block.
+ // FIXME: This isn't quite correct. Need clarification for what to do
+ // if the height the cleared block is offset by is smaller than the
+ // margins involved.
+ m_maxTopPosMargin = oldTopPosMargin;
+ m_maxTopNegMargin = oldTopNegMargin;
+ marginInfo.setAtTopOfBlock(false);
+ }
+
+ // If our value of clear caused us to be repositioned vertically to be
+ // underneath a float, we might have to do another layout to take into account
+ // the extra space we now have available.
+ if (!selfCollapsing && !child->style()->width().isFixed() && child->usesLineWidth())
+ // The child's width is a percentage of the line width.
+ // When the child shifts to clear an item, its width can
+ // change (because it has more available line width).
+ // So go ahead and mark the item as dirty.
+ child->setChildNeedsLayout(true);
+ if (!child->flowAroundFloats() && child->hasFloats())
+ child->markAllDescendantsWithFloatsForLayout();
+ child->layoutIfNeeded();
+ }
+}
+
+bool RenderBlock::canClear(RenderObject *child, PageBreakLevel level)
+{
+ KHTMLAssert(child->parent() && child->parent() == this);
+ KHTMLAssert(canvas()->pagedMode());
+
+ // Positioned elements cannot be moved. Only normal flow and floating.
+ if (child->isPositioned() || child->isRelPositioned()) return false;
+
+ switch(level) {
+ case PageBreakNormal:
+ // check page-break-inside: avoid
+ if (!style()->pageBreakInside())
+ // we cannot, but can our parent?
+ if(!parent()->canClear(this, level)) return false;
+ case PageBreakHarder:
+ // check page-break-after/before: avoid
+ if (m_avoidPageBreak)
+ // we cannot, but can our parent?
+ if(!parent()->canClear(this, level)) return false;
+ case PageBreakForced:
+ // child is larger than page-height and is forced to break
+ if(child->height() > canvas()->pageHeight()) return false;
+ return true;
+ }
+ assert(false);
+ return false;
+}
+
+void RenderBlock::clearPageBreak(RenderObject* child, int pageBottom)
+{
+ KHTMLAssert(child->parent() && child->parent() == this);
+ KHTMLAssert(canvas()->pagedMode());
+
+ if (child->yPos() >= pageBottom) return;
+
+ int heightIncrease = 0;
+
+ heightIncrease = pageBottom - child->yPos();
+
+ // ### should never happen, canClear should have been called to detect it.
+ if (child->height() > canvas()->pageHeight()) {
+ kdDebug(6040) << "### child is too large to clear: " << child->height() << " > " << canvas()->pageHeight() << endl;
+ return;
+ }
+
+ // The child needs to be lowered. Move the child so that it just clears the break.
+ child->setPos(child->xPos(), pageBottom);
+
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << "Cleared block " << heightIncrease << "px" << endl;
+#endif
+
+ // Increase our height by the amount we had to clear.
+ m_height += heightIncrease;
+
+ // We might have to do another layout to take into account
+ // the extra space we now have available.
+ if (!child->style()->width().isFixed() && child->usesLineWidth())
+ // The child's width is a percentage of the line width.
+ // When the child shifts to clear a page-break, its width can
+ // change (because it has more available line width).
+ // So go ahead and mark the item as dirty.
+ child->setChildNeedsLayout(true);
+ if (!child->flowAroundFloats() && child->hasFloats())
+ child->markAllDescendantsWithFloatsForLayout();
+ if (child->containsPageBreak())
+ child->setNeedsLayout(true);
+ child->layoutIfNeeded();
+
+ child->setAfterPageBreak(true);
+}
+
+int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
+{
+ // FIXME: We need to eliminate the estimation of vertical position, because
+ // when it's wrong we sometimes trigger a pathological relayout if there are
+ // intruding floats.
+ int yPosEstimate = m_height;
+ if (!marginInfo.canCollapseWithTop()) {
+ int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
+ yPosEstimate += kMax(marginInfo.margin(), childMarginTop);
+ }
+ return yPosEstimate;
+}
+
+void RenderBlock::determineHorizontalPosition(RenderObject* child)
+{
+ if (style()->direction() == LTR) {
+ int xPos = borderLeft() + paddingLeft();
+
+ // Add in our left margin.
+ int chPos = xPos + child->marginLeft();
+
+ // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
+ // to shift over as necessary to dodge any floats that might get in the way.
+ if (child->flowAroundFloats()) {
+ int leftOff = leftOffset(m_height);
+ if (style()->textAlign() != KHTML_CENTER && !child->style()->marginLeft().isVariable()) {
+ if (child->marginLeft() < 0)
+ leftOff += child->marginLeft();
+ chPos = kMax(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
+ }
+ else if (leftOff != xPos) {
+ // The object is shifting right. The object might be centered, so we need to
+ // recalculate our horizontal margins. Note that the containing block content
+ // width computation will take into account the delta between |leftOff| and |xPos|
+ // so that we can just pass the content width in directly to the |calcHorizontalMargins|
+ // function.
+ static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+ chPos = leftOff + child->marginLeft();
+ }
+ }
+
+ child->setPos(chPos, child->yPos());
+ } else {
+ int xPos = m_width - borderRight() - paddingRight();
+ if (m_layer && scrollsOverflowY())
+ xPos -= m_layer->verticalScrollbarWidth();
+ int chPos = xPos - (child->width() + child->marginRight());
+ if (child->flowAroundFloats()) {
+ int rightOff = rightOffset(m_height);
+ if (style()->textAlign() != KHTML_CENTER && !child->style()->marginRight().isVariable()) {
+ if (child->marginRight() < 0)
+ rightOff -= child->marginRight();
+ chPos = kMin(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
+ } else if (rightOff != xPos) {
+ // The object is shifting left. The object might be centered, so we need to
+ // recalculate our horizontal margins. Note that the containing block content
+ // width computation will take into account the delta between |rightOff| and |xPos|
+ // so that we can just pass the content width in directly to the |calcHorizontalMargins|
+ // function.
+ static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+ chPos = rightOff - child->marginRight() - child->width();
+ }
+ }
+ child->setPos(chPos, child->yPos());
+ }
+}
+
+void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
+{
+ if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) {
+ // Update our max pos/neg bottom margins, since we collapsed our bottom margins
+ // with our children.
+ m_maxBottomPosMargin = kMax((int)m_maxBottomPosMargin, marginInfo.posMargin());
+ m_maxBottomNegMargin = kMax((int)m_maxBottomNegMargin, marginInfo.negMargin());
+
+ if (!marginInfo.bottomQuirk())
+ m_bottomMarginQuirk = false;
+
+ if (marginInfo.bottomQuirk() && marginBottom() == 0)
+ // We have no bottom margin and our last child has a quirky margin.
+ // We will pick up this quirky margin and pass it through.
+ // This deals with the <td><div><p> case.
+ m_bottomMarginQuirk = true;
+ }
+}
+
+void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
+{
+ // If our last flow was a self-collapsing block that cleared a float, then we don't
+ // collapse it with the bottom of the block.
+ if (!marginInfo.selfCollapsingBlockClearedFloat())
+ marginInfo.setAtBottomOfBlock(true);
+
+ // If we can't collapse with children then go ahead and add in the bottom margin.
+ if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
+ && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
+ m_height += marginInfo.margin();
+
+ // Now add in our bottom border/padding.
+ m_height += bottom;
+
+ // Negative margins can cause our height to shrink below our minimal height (border/padding).
+ // If this happens, ensure that the computed height is increased to the minimal height.
+ m_height = kMax(m_height, top + bottom);
+
+ // Always make sure our overflow height is at least our height.
+ m_overflowHeight = kMax(m_height, m_overflowHeight);
+
+ // Update our bottom collapsed margin info.
+ setCollapsedBottomMargin(marginInfo);
+}
+
+void RenderBlock::layoutBlockChildren( bool relayoutChildren )
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << " layoutBlockChildren( " << this <<" ), relayoutChildren="<< relayoutChildren << endl;
+#endif
+
+ int top = borderTop() + paddingTop();
+ int bottom = borderBottom() + paddingBottom();
+ if (m_layer && scrollsOverflowX() && style()->height().isVariable())
+ bottom += m_layer->horizontalScrollbarHeight();
+
+ m_height = m_overflowHeight = top;
+
+ // The margin struct caches all our current margin collapsing state.
+ // The compact struct caches state when we encounter compacts.
+ MarginInfo marginInfo(this, top, bottom);
+ CompactInfo compactInfo;
+
+ // Fieldsets need to find their legend and position it inside the border of the object.
+ // The legend then gets skipped during normal layout.
+ RenderObject* legend = layoutLegend(relayoutChildren);
+
+ PageBreakInfo pageBreakInfo(pageTopAfter(0));
+
+ RenderObject* child = firstChild();
+ while( child != 0 )
+ {
+ if (legend == child) {
+ child = child->nextSibling();
+ continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
+ }
+
+ int oldTopPosMargin = m_maxTopPosMargin;
+ int oldTopNegMargin = m_maxTopNegMargin;
+
+ // make sure we relayout children if we need it.
+ if (!child->isPositioned() && (relayoutChildren ||
+ (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) ||
+ (child->isRenderBlock() && child->style()->height().isPercent()) ||
+ (child->isBody() && child->style()->htmlHacks())))
+ {
+ child->setChildNeedsLayout(true);
+ }
+
+ // Handle the four types of special elements first. These include positioned content, floating content, compacts and
+ // run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
+ bool handled = false;
+ RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled);
+ if (handled) { child = next; continue; }
+
+ // The child is a normal flow object. Compute its vertical margins now.
+ child->calcVerticalMargins();
+
+#ifdef APPLE_CHANGES /* margin-*-collapse not merged yet */
+ // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
+ if (child->style()->marginTopCollapse() == MSEPARATE) {
+ marginInfo.setAtTopOfBlock(false);
+ marginInfo.clearMargin();
+ }
+#endif
+
+ // Try to guess our correct y position. In most cases this guess will
+ // be correct. Only if we're wrong (when we compute the real y position)
+ // will we have to potentially relayout.
+ int yPosEstimate = estimateVerticalPosition(child, marginInfo);
+
+ // If an element might be affected by the presence of floats, then always mark it for
+ // layout.
+ if ( !child->flowAroundFloats() || child->usesLineWidth() ) {
+ int fb = floatBottom();
+ if (fb > m_height || fb > yPosEstimate)
+ child->setChildNeedsLayout(true);
+ }
+
+ // Go ahead and position the child as though it didn't collapse with the top.
+ child->setPos(child->xPos(), yPosEstimate);
+ child->layoutIfNeeded();
+
+ // Now determine the correct ypos based on examination of collapsing margin
+ // values.
+ collapseMargins(child, marginInfo, yPosEstimate);
+
+ // Now check for clear.
+ clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
+
+ // We are no longer at the top of the block if we encounter a non-empty child.
+ // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
+ if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
+ marginInfo.setAtTopOfBlock(false);
+
+ // Now place the child in the correct horizontal position
+ determineHorizontalPosition(child);
+
+ adjustSizeForCompactIfNeeded(child, compactInfo);
+ // Update our height now that the child has been placed in the correct position.
+ m_height += child->height();
+
+#ifdef APPLE_CHANGES
+ if (child->style()->marginBottomCollapse() == MSEPARATE) {
+ m_height += child->marginBottom();
+ marginInfo.clearMargin();
+ }
+#endif
+
+ // Check for page-breaks
+ if (canvas()->pagedMode())
+ clearChildOfPageBreaks(child, pageBreakInfo, marginInfo);
+
+ if (child->hasOverhangingFloats() && !child->flowAroundFloats()) {
+ // need to add the child's floats to our floating objects list, but not in the case where
+ // overflow is auto/scroll
+ addOverHangingFloats( static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos(), true );
+ }
+
+ // See if this child has made our overflow need to grow.
+ int effX = child->effectiveXPos();
+ int effY = child->effectiveYPos();
+ m_overflowWidth = kMax(effX + child->effectiveWidth(), m_overflowWidth);
+ m_overflowLeft = kMin(effX, m_overflowLeft);
+ m_overflowHeight = kMax(effY + child->effectiveHeight(), m_overflowHeight);
+ m_overflowTop = kMin(effY, m_overflowTop);
+
+ // Insert our compact into the block margin if we have one.
+ insertCompactIfNeeded(child, compactInfo);
+
+ child = child->nextSibling();
+ }
+
+ // The last child had forced page-break-after
+ if (pageBreakInfo.forcePageBreak())
+ m_height = pageBreakInfo.pageBottom();
+
+ // Now do the handling of the bottom of the block, adding in our bottom border/padding and
+ // determining the correct collapsed bottom margin information.
+ handleBottomOfBlock(top, bottom, marginInfo);
+
+ setNeedsLayout(false);
+}
+
+void RenderBlock::clearChildOfPageBreaks(RenderObject *child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo)
+{
+ (void)marginInfo;
+ int childTop = child->yPos();
+ int childBottom = child->yPos()+child->height();
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " ChildTop: " << childTop << " ChildBottom: " << childBottom << endl;
+#endif
+
+ bool forcePageBreak = pageBreakInfo.forcePageBreak() || child->style()->pageBreakBefore() == PBALWAYS;
+#ifdef PAGE_DEBUG
+ if (forcePageBreak)
+ kdDebug(6040) << renderName() << "Forced break required" << endl;
+#endif
+
+ int xpage = crossesPageBreak(childTop, childBottom);
+ if (xpage || forcePageBreak)
+ {
+ if (!forcePageBreak && child->containsPageBreak() && !child->needsPageClear()) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " Child contains page-break to page " << xpage << endl;
+#endif
+ // ### Actually this assumes floating children are breaking/clearing
+ // nicely as well.
+ setContainsPageBreak(true);
+ }
+ else {
+ bool doBreak = true;
+ // don't break before the first child or when page-break-inside is avoid
+ if (!forcePageBreak && (!style()->pageBreakInside() || m_avoidPageBreak || child == firstChild())) {
+ if (parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << "Avoid page-break inside" << endl;
+#endif
+ child->setNeedsPageClear(false);
+ setNeedsPageClear(true);
+ doBreak = false;
+ }
+#ifdef PAGE_DEBUG
+ else
+ kdDebug(6040) << renderName() << "Ignoring page-break avoid" << endl;
+#endif
+ }
+ if (doBreak) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " Clearing child of page-break" << endl;
+ kdDebug(6040) << renderName() << " child top of page " << xpage << endl;
+#endif
+ clearPageBreak(child, pageBreakInfo.pageBottom());
+ child->setNeedsPageClear(false);
+ setContainsPageBreak(true);
+ }
+ }
+ pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight());
+ }
+ else
+ if (child->yPos() >= pageBreakInfo.pageBottom()) {
+ bool doBreak = true;
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << "Page-break between children" << endl;
+#endif
+ if (!style()->pageBreakInside() || m_avoidPageBreak) {
+ if(parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << "Avoid page-break inside" << endl;
+#endif
+ child->setNeedsPageClear(false);
+ setNeedsPageClear(true);
+ doBreak = false;
+ }
+#ifdef PAGE_DEBUG
+ else
+ kdDebug(6040) << "Ignoring page-break avoid" << endl;
+#endif
+ }
+ if (doBreak) {
+ // Break between children
+ setContainsPageBreak(true);
+ // ### Should collapse top-margin with page-margin
+ }
+ pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight());
+ }
+
+ // Do we need a forced page-break before next child?
+ pageBreakInfo.setForcePageBreak(false);
+ if (child->style()->pageBreakAfter() == PBALWAYS)
+ pageBreakInfo.setForcePageBreak(true);
+}
+
+void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
+{
+ if (m_positionedObjects) {
+ //kdDebug( 6040 ) << renderName() << " " << this << "::layoutPositionedObjects() start" << endl;
+ RenderObject* r;
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; (r = it.current()); ++it ) {
+ //kdDebug(6040) << " have a positioned object" << endl;
+ if (r->markedForRepaint()) {
+ r->repaintDuringLayout();
+ r->setMarkedForRepaint(false);
+ }
+ if ( relayoutChildren || r->style()->position() == FIXED ||
+ ((r->hasStaticY()||r->hasStaticX()) && r->parent() != this && r->parent()->isBlockFlow()) ) {
+ r->setChildNeedsLayout(true);
+ r->dirtyFormattingContext(false);
+ }
+ r->layoutIfNeeded();
+ }
+ }
+}
+
+void RenderBlock::paint(PaintInfo& pI, int _tx, int _ty)
+{
+ _tx += m_x;
+ _ty += m_y;
+
+ // check if we need to do anything at all...
+ if (!isRoot() && !isInlineFlow() && !overhangingContents() && !isRelPositioned() && !isPositioned() )
+ {
+ int h = m_overflowHeight;
+ int yPos = _ty;
+ if (m_floatingObjects && floatBottom() > h)
+ h = floatBottom();
+
+ yPos += overflowTop();
+
+ int os = maximalOutlineSize(pI.phase);
+ if( (yPos > pI.r.bottom() + os) || (_ty + h <= pI.r.y() - os))
+ return;
+ }
+
+ paintObject(pI, _tx, _ty);
+}
+
+void RenderBlock::paintObject(PaintInfo& pI, int _tx, int _ty, bool shouldPaintOutline)
+{
+#ifdef DEBUG_LAYOUT
+ //kdDebug( 6040 ) << renderName() << "(RenderBlock) " << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
+#endif
+
+ // If we're a repositioned run-in, don't paint background/borders.
+ bool inlineFlow = isInlineFlow();
+
+ // 1. paint background, borders etc
+ if (!inlineFlow &&
+ (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground ) &&
+ shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE)
+ paintBoxDecorations(pI, _tx, _ty);
+
+ if ( pI.phase == PaintActionElementBackground )
+ return;
+ if ( pI.phase == PaintActionChildBackgrounds )
+ pI.phase = PaintActionChildBackground;
+
+ // 2. paint contents
+ int scrolledX = _tx;
+ int scrolledY = _ty;
+ if (hasOverflowClip() && m_layer)
+ m_layer->subtractScrollOffset(scrolledX, scrolledY);
+
+ if (childrenInline())
+ paintLines(pI, scrolledX, scrolledY);
+ else {
+ for(RenderObject *child = firstChild(); child; child = child->nextSibling())
+ if(!child->layer() && !child->isFloating())
+ child->paint(pI, scrolledX, scrolledY);
+ }
+
+ // 3. paint floats.
+ if (!inlineFlow && (pI.phase == PaintActionFloat || pI.phase == PaintActionSelection))
+ paintFloats(pI, scrolledX, scrolledY, pI.phase == PaintActionSelection);
+
+ // 4. paint outline.
+ if (shouldPaintOutline && !inlineFlow && pI.phase == PaintActionOutline &&
+ style()->outlineWidth() && style()->visibility() == VISIBLE)
+ paintOutline(pI.p, _tx, _ty, width(), height(), style());
+
+#ifdef BOX_DEBUG
+ if ( style() && style()->visibility() == VISIBLE ) {
+ if(isAnonymous())
+ outlineBox(pI.p, _tx, _ty, "green");
+ if(isFloating())
+ outlineBox(pI.p, _tx, _ty, "yellow");
+ else
+ outlineBox(pI.p, _tx, _ty);
+ }
+#endif
+}
+
+void RenderBlock::paintFloats(PaintInfo& pI, int _tx, int _ty, bool paintSelection)
+{
+ if (!m_floatingObjects)
+ return;
+
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it) {
+ // Only paint the object if our noPaint flag isn't set.
+ if (r->node->isFloating() && !r->noPaint && !r->node->layer()) {
+ PaintAction oldphase = pI.phase;
+ if (paintSelection) {
+ pI.phase = PaintActionSelection;
+ r->node->paint(pI, _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ }
+ else {
+ pI.phase = PaintActionElementBackground;
+ r->node->paint(pI,
+ _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ pI.phase = PaintActionChildBackgrounds;
+ r->node->paint(pI,
+ _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ pI.phase = PaintActionFloat;
+ r->node->paint(pI,
+ _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ pI.phase = PaintActionForeground;
+ r->node->paint(pI,
+ _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ pI.phase = PaintActionOutline;
+ r->node->paint(pI,
+ _tx + r->left - r->node->xPos() + r->node->marginLeft(),
+ _ty + r->startY - r->node->yPos() + r->node->marginTop());
+ }
+ pI.phase = oldphase;
+ }
+ }
+}
+
+void RenderBlock::insertPositionedObject(RenderObject *o)
+{
+ // Create the list of special objects if we don't aleady have one
+ if (!m_positionedObjects) {
+ m_positionedObjects = new TQPtrList<RenderObject>;
+ m_positionedObjects->setAutoDelete(false);
+ }
+ else {
+ // Don't insert the object again if it's already in the list
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ RenderObject* f;
+ while ( (f = it.current()) ) {
+ if (f == o) return;
+ ++it;
+ }
+ }
+
+ // Create the special object entry & append it to the list
+ setOverhangingContents();
+ m_positionedObjects->append(o);
+}
+
+void RenderBlock::removePositionedObject(RenderObject *o)
+{
+ if (m_positionedObjects) {
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ while (it.current()) {
+ if (it.current() == o)
+ m_positionedObjects->removeRef(it.current());
+ ++it;
+ }
+ if (m_positionedObjects->isEmpty()) {
+ delete m_positionedObjects;
+ m_positionedObjects = 0;
+ }
+ }
+}
+
+void RenderBlock::insertFloatingObject(RenderObject *o)
+{
+ // Create the list of special objects if we don't aleady have one
+ if (!m_floatingObjects) {
+ m_floatingObjects = new TQPtrList<FloatingObject>;
+ m_floatingObjects->setAutoDelete(true);
+ }
+ else {
+ // Don't insert the object again if it's already in the list
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ FloatingObject* f;
+ while ( (f = it.current()) ) {
+ if (f->node == o) return;
+ ++it;
+ }
+ }
+
+ // Create the special object entry & append it to the list
+
+ FloatingObject *newObj;
+ if (o->isFloating()) {
+ // floating object
+ o->layoutIfNeeded();
+
+ if(o->style()->floating() & FLEFT)
+ newObj = new FloatingObject(FloatingObject::FloatLeft);
+ else
+ newObj = new FloatingObject(FloatingObject::FloatRight);
+
+ newObj->startY = -500000;
+ newObj->endY = -500000;
+ newObj->width = o->width() + o->marginLeft() + o->marginRight();
+ }
+ else {
+ // We should never get here, as insertFloatingObject() should only ever be called with floating
+ // objects.
+ KHTMLAssert(false);
+ newObj = 0; // keep gcc's uninitialized variable warnings happy
+ }
+
+ newObj->node = o;
+
+ m_floatingObjects->append(newObj);
+}
+
+void RenderBlock::removeFloatingObject(RenderObject *o)
+{
+ if (m_floatingObjects) {
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ while (it.current()) {
+ if (it.current()->node == o)
+ m_floatingObjects->removeRef(it.current());
+ ++it;
+ }
+ }
+}
+
+void RenderBlock::positionNewFloats()
+{
+ if(!m_floatingObjects) return;
+ FloatingObject *f = m_floatingObjects->getLast();
+ if(!f || f->startY != -500000) return;
+ FloatingObject *lastFloat;
+ while(1)
+ {
+ lastFloat = m_floatingObjects->prev();
+ if (!lastFloat || lastFloat->startY != -500000) {
+ m_floatingObjects->next();
+ break;
+ }
+ f = lastFloat;
+ }
+
+ int y = m_height;
+
+
+ // the float can not start above the y position of the last positioned float.
+ if(lastFloat && lastFloat->startY > y)
+ y = lastFloat->startY;
+
+ while(f)
+ {
+ //skip elements copied from elsewhere and positioned elements
+ if (f->node->containingBlock()!=this)
+ {
+ f = m_floatingObjects->next();
+ continue;
+ }
+
+ RenderObject *o = f->node;
+ int _height = o->height() + o->marginTop() + o->marginBottom();
+
+ // floats avoid page-breaks
+ if(canvas()->pagedMode())
+ {
+ int top = y;
+ int bottom = y + o->height();
+ if (crossesPageBreak(top, bottom) && o->height() < canvas()->pageHeight() ) {
+ int newY = pageTopAfter(top);
+#ifdef PAGE_DEBUG
+ kdDebug(6040) << renderName() << " clearing float " << newY - y << "px" << endl;
+#endif
+ y = newY;
+ }
+ }
+
+ int ro = rightOffset(); // Constant part of right offset.
+ int lo = leftOffset(); // Constant part of left offset.
+ int fwidth = f->width; // The width we look for.
+ //kdDebug( 6040 ) << " Object width: " << fwidth << " available width: " << ro - lo << endl;
+
+ // in quirk mode, floated auto-width tables try to fit within remaining linewidth
+ bool ftQuirk = o->isTable() && style()->htmlHacks() && o->style()->width().isVariable();
+ if (ftQuirk)
+ fwidth = kMin( o->minWidth()+o->marginLeft()+o->marginRight(), fwidth );
+
+ if (ro - lo < fwidth)
+ fwidth = ro - lo; // Never look for more than what will be available.
+
+ if ( o->style()->clear() & CLEFT )
+ y = kMax( leftBottom(), y );
+ if ( o->style()->clear() & CRIGHT )
+ y = kMax( rightBottom(), y );
+
+ bool canClearLine;
+ if (o->style()->floating() & FLEFT)
+ {
+ int heightRemainingLeft = 1;
+ int heightRemainingRight = 1;
+ int fx = leftRelOffset(y,lo, false, &heightRemainingLeft, &canClearLine);
+ if (canClearLine)
+ {
+ while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth)
+ {
+ y += kMin( heightRemainingLeft, heightRemainingRight );
+ fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
+ }
+ }
+ if (ftQuirk && (rightRelOffset(y,ro, false)-fx < f->width)) {
+ o->setPos( o->xPos(), y + o->marginTop() );
+ o->setChildNeedsLayout(true, false);
+ o->layoutIfNeeded();
+ _height = o->height() + o->marginTop() + o->marginBottom();
+ f->width = o->width() + o->marginLeft() + o->marginRight();
+ }
+ f->left = fx;
+ //kdDebug( 6040 ) << "positioning left aligned float at (" << fx + o->marginLeft() << "/" << y + o->marginTop() << ") fx=" << fx << endl;
+ o->setPos(fx + o->marginLeft(), y + o->marginTop());
+ }
+ else
+ {
+ int heightRemainingLeft = 1;
+ int heightRemainingRight = 1;
+ int fx = rightRelOffset(y,ro, false, &heightRemainingRight, &canClearLine);
+ if (canClearLine)
+ {
+ while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth)
+ {
+ y += kMin(heightRemainingLeft, heightRemainingRight);
+ fx = rightRelOffset(y,ro, false, &heightRemainingRight);
+ }
+ }
+ if (ftQuirk && (fx - leftRelOffset(y,lo, false) < f->width)) {
+ o->setPos( o->xPos(), y + o->marginTop() );
+ o->setChildNeedsLayout(true, false);
+ o->layoutIfNeeded();
+ _height = o->height() + o->marginTop() + o->marginBottom();
+ f->width = o->width() + o->marginLeft() + o->marginRight();
+ }
+ f->left = fx - f->width;
+ //kdDebug( 6040 ) << "positioning right aligned float at (" << fx - o->marginRight() - o->width() << "/" << y + o->marginTop() << ")" << endl;
+ o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
+ }
+
+ if ( m_layer && hasOverflowClip()) {
+ if (o->xPos()+o->width() > m_overflowWidth)
+ m_overflowWidth = o->xPos()+o->width();
+ else
+ if (o->xPos() < m_overflowLeft)
+ m_overflowLeft = o->xPos();
+ }
+
+ f->startY = y;
+ f->endY = f->startY + _height;
+
+
+ //kdDebug( 6040 ) << "floatingObject x/y= (" << f->left << "/" << f->startY << "-" << f->width << "/" << f->endY - f->startY << ")" << endl;
+
+ f = m_floatingObjects->next();
+ }
+}
+
+void RenderBlock::newLine()
+{
+ positionNewFloats();
+ // set y position
+ int newY = 0;
+ switch(m_clearStatus)
+ {
+ case CLEFT:
+ newY = leftBottom();
+ break;
+ case CRIGHT:
+ newY = rightBottom();
+ break;
+ case CBOTH:
+ newY = floatBottom();
+ default:
+ break;
+ }
+ if(m_height < newY)
+ {
+ // kdDebug( 6040 ) << "adjusting y position" << endl;
+ m_height = newY;
+ }
+ m_clearStatus = CNONE;
+}
+
+int
+RenderBlock::leftOffset() const
+{
+ return borderLeft()+paddingLeft();
+}
+
+int
+RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent, int *heightRemaining, bool *canClearLine ) const
+{
+ int left = fixedOffset;
+ if (canClearLine) *canClearLine = true;
+
+ if (m_floatingObjects) {
+ if ( heightRemaining ) *heightRemaining = 1;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ {
+ //kdDebug( 6040 ) <<(void *)this << " left: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
+ if (r->startY <= y && r->endY > y &&
+ r->type == FloatingObject::FloatLeft &&
+ r->left + r->width > left) {
+ left = r->left + r->width;
+ if ( heightRemaining ) *heightRemaining = r->endY - y;
+ if ( canClearLine ) *canClearLine = (r->node->style()->floating() != FLEFT_ALIGN);
+ }
+ }
+ }
+
+ if (applyTextIndent && m_firstLine && style()->direction() == LTR ) {
+ int cw=0;
+ if (style()->textIndent().isPercent())
+ cw = containingBlock()->contentWidth();
+ left += style()->textIndent().minWidth(cw);
+ }
+
+ //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
+ return left;
+}
+
+int
+RenderBlock::rightOffset() const
+{
+ int right = m_width - borderRight() - paddingRight();
+ if (m_layer && scrollsOverflowY())
+ right -= m_layer->verticalScrollbarWidth();
+ return right;
+}
+
+int
+RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent, int *heightRemaining, bool *canClearLine ) const
+{
+ int right = fixedOffset;
+ if (canClearLine) *canClearLine = true;
+
+ if (m_floatingObjects) {
+ if (heightRemaining) *heightRemaining = 1;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ {
+ //kdDebug( 6040 ) << "right: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
+ if (r->startY <= y && r->endY > y &&
+ r->type == FloatingObject::FloatRight &&
+ r->left < right) {
+ right = r->left;
+ if ( heightRemaining ) *heightRemaining = r->endY - y;
+ if ( canClearLine ) *canClearLine = (r->node->style()->floating() != FRIGHT_ALIGN);
+ }
+ }
+ }
+
+ if (applyTextIndent && m_firstLine && style()->direction() == RTL ) {
+ int cw=0;
+ if (style()->textIndent().isPercent())
+ cw = containingBlock()->contentWidth();
+ right -= style()->textIndent().minWidth(cw);
+ }
+
+ //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
+ return right;
+}
+
+unsigned short
+RenderBlock::lineWidth(int y, bool *canClearLine) const
+{
+ //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
+ int result;
+ if (canClearLine) {
+ bool rightCanClearLine;
+ bool leftCanClearLine;
+ result = rightOffset(y, &rightCanClearLine) - leftOffset(y, &leftCanClearLine);
+ *canClearLine = rightCanClearLine && leftCanClearLine;
+ } else
+ result = rightOffset(y) - leftOffset(y);
+ return (result < 0) ? 0 : result;
+}
+
+int
+RenderBlock::nearestFloatBottom(int height) const
+{
+ if (!m_floatingObjects) return 0;
+ int bottom = 0;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ if (r->endY>height && (r->endY<bottom || bottom==0))
+ bottom=r->endY;
+ return kMax(bottom, height);
+}
+
+int RenderBlock::floatBottom() const
+{
+ if (!m_floatingObjects) return 0;
+ int bottom=0;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ if (r->endY>bottom)
+ bottom=r->endY;
+ return bottom;
+}
+
+int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return bottom;
+ if (includeSelf && m_overflowHeight > bottom)
+ bottom = m_overflowHeight;
+
+ if (m_floatingObjects) {
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (!r->noPaint) {
+ int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
+ bottom = kMax(bottom, lp);
+ }
+ }
+ }
+ bottom = kMax(bottom, lowestAbsolutePosition());
+
+ if (!includeSelf && lastLineBox()) {
+ int lp = lastLineBox()->yPos() + lastLineBox()->height();
+ bottom = kMax(bottom, lp);
+ }
+
+ return bottom;
+}
+
+int RenderBlock::lowestAbsolutePosition() const
+{
+ if (!m_positionedObjects)
+ return 0;
+
+ // Fixed positioned objects do not scroll and thus should not constitute
+ // part of the lowest position.
+ int bottom = 0;
+ RenderObject* r;
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (r->style()->position() == FIXED)
+ continue;
+ int lp = r->yPos() + r->lowestPosition(false);
+ bottom = kMax(bottom, lp);
+ }
+ return bottom;
+}
+
+int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return right;
+ if (includeSelf && m_overflowWidth > right)
+ right = m_overflowWidth;
+
+ if (m_floatingObjects) {
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (!r->noPaint) {
+ int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
+ right = kMax(right, rp);
+ }
+ }
+ }
+ right = kMax(right, rightmostAbsolutePosition());
+
+ if (!includeSelf && firstLineBox()) {
+ for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
+ int rp = currBox->xPos() + currBox->width();
+ right = kMax(right, rp);
+ }
+ }
+
+ return right;
+}
+
+int RenderBlock::rightmostAbsolutePosition() const
+{
+ if (!m_positionedObjects)
+ return 0;
+ int right = 0;
+ RenderObject* r;
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (r->style()->position() == FIXED)
+ continue;
+ int rp = r->xPos() + r->rightmostPosition(false);
+ right = kMax(right, rp);
+ }
+ return right;
+}
+
+int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return left;
+
+ if (includeSelf && m_overflowLeft < left)
+ left = m_overflowLeft;
+
+ if (m_floatingObjects) {
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (!r->noPaint) {
+ int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
+ left = kMin(left, lp);
+ }
+ }
+ }
+ left = kMin(left, leftmostAbsolutePosition());
+
+ if (!includeSelf && firstLineBox()) {
+ for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
+ left = kMin(left, (int)currBox->xPos());
+ }
+
+ return left;
+}
+
+int RenderBlock::leftmostAbsolutePosition() const
+{
+ if (!m_positionedObjects)
+ return 0;
+ int left = 0;
+ RenderObject* r;
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (r->style()->position() == FIXED)
+ continue;
+ int lp = r->xPos() + r->leftmostPosition(false);
+ left = kMin(left, lp);
+ }
+ return left;
+}
+
+int RenderBlock::highestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int top = RenderFlow::highestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return top;
+
+ if (includeSelf && m_overflowTop < top)
+ top = m_overflowTop;
+
+ if (m_floatingObjects) {
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (!r->noPaint) {
+ int hp = r->startY + r->node->marginTop() + r->node->highestPosition(false);
+ top = kMin(top, hp);
+ }
+ }
+ }
+ top = kMin(top, highestAbsolutePosition());
+
+ if (!includeSelf && firstLineBox()) {
+ top = kMin(top, (int)firstLineBox()->yPos());
+ }
+
+ return top;
+}
+
+int RenderBlock::highestAbsolutePosition() const
+{
+ if (!m_positionedObjects)
+ return 0;
+ int top = 0;
+ RenderObject* r;
+ TQPtrListIterator<RenderObject> it(*m_positionedObjects);
+ for ( ; (r = it.current()); ++it ) {
+ if (r->style()->position() == FIXED)
+ continue;
+ int hp = r->yPos() + r->highestPosition(false);
+ hp = kMin(top, hp);
+ }
+ return top;
+}
+
+int
+RenderBlock::leftBottom()
+{
+ if (!m_floatingObjects) return 0;
+ int bottom=0;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ if (r->endY>bottom && r->type == FloatingObject::FloatLeft)
+ bottom=r->endY;
+
+ return bottom;
+}
+
+int
+RenderBlock::rightBottom()
+{
+ if (!m_floatingObjects) return 0;
+ int bottom=0;
+ FloatingObject* r;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it )
+ if (r->endY>bottom && r->type == FloatingObject::FloatRight)
+ bottom=r->endY;
+
+ return bottom;
+}
+
+void
+RenderBlock::clearFloats()
+{
+ if (m_floatingObjects)
+ m_floatingObjects->clear();
+
+ // we are done if the element defines a new block formatting context
+ if (flowAroundFloats() || isRoot() || isCanvas() || isFloatingOrPositioned() || isTableCell()) return;
+
+ RenderObject *prev = previousSibling();
+
+ // find the element to copy the floats from
+ // pass non-flows
+ // pass fAF's
+ bool parentHasFloats = false;
+ while (prev) {
+ if (!prev->isRenderBlock() || prev->isFloatingOrPositioned() || prev->flowAroundFloats()) {
+ if ( prev->isFloating() && parent()->isRenderBlock() ) {
+ parentHasFloats = true;
+ }
+ prev = prev->previousSibling();
+ } else
+ break;
+ }
+
+ int offset = m_y;
+ if (parentHasFloats)
+ {
+ addOverHangingFloats( static_cast<RenderBlock *>( parent() ),
+ parent()->borderLeft() + parent()->paddingLeft(), offset, false );
+ }
+
+ int xoffset = 0;
+ if (prev) {
+ if(prev->isTableCell()) return;
+ offset -= prev->yPos();
+ } else {
+ prev = parent();
+ if(!prev) return;
+ xoffset += prev->borderLeft() + prev->paddingLeft();
+ }
+ //kdDebug() << "RenderBlock::clearFloats found previous "<< (void *)this << " prev=" << (void *)prev<< endl;
+
+ // add overhanging special objects from the previous RenderBlock
+ if(!prev->isRenderBlock()) return;
+ RenderBlock * flow = static_cast<RenderBlock *>(prev);
+ if(!flow->m_floatingObjects) return;
+ if(flow->floatBottom() > offset)
+ addOverHangingFloats( flow, xoffset, offset, false );
+}
+
+void RenderBlock::addOverHangingFloats( RenderBlock *flow, int xoff, int offset, bool child )
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << (void *)this << ": adding overhanging floats xoff=" << xoff << " offset=" << offset << " child=" << child << endl;
+#endif
+
+ // Prevent floats from being added to the canvas by the root element, e.g., <html>.
+ if ( !flow->m_floatingObjects || (child && flow->isRoot()) )
+ return;
+
+ // if I am clear of my floats, don't add them
+ // the CSS spec also mentions that child floats
+ // are not cleared.
+ if (!child && style()->clear() == CBOTH)
+ {
+ return;
+ }
+
+ TQPtrListIterator<FloatingObject> it(*flow->m_floatingObjects);
+ FloatingObject *r;
+ for ( ; (r = it.current()); ++it ) {
+
+ if (!child && r->type == FloatingObject::FloatLeft && style()->clear() == CLEFT )
+ continue;
+ if (!child && r->type == FloatingObject::FloatRight && style()->clear() == CRIGHT )
+ continue;
+
+ if ( ( !child && r->endY > offset ) ||
+ ( child && flow->yPos() + r->endY > height() ) ) {
+ if (child && !r->crossedLayer) {
+ if (flow->enclosingLayer() == enclosingLayer()) {
+ // Set noPaint to true only if we didn't cross layers.
+ r->noPaint = true;
+ } else {
+ r->crossedLayer = true;
+ }
+ }
+
+ FloatingObject* f = 0;
+ // don't insert it twice!
+ if (m_floatingObjects) {
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ while ( (f = it.current()) ) {
+ if (f->node == r->node) break;
+ ++it;
+ }
+ }
+ if ( !f ) {
+ FloatingObject *floatingObj = new FloatingObject(r->type);
+ floatingObj->startY = r->startY - offset;
+ floatingObj->endY = r->endY - offset;
+ floatingObj->left = r->left - xoff;
+ // Applying the child's margin makes no sense in the case where the child was passed in.
+ // since his own margin was added already through the subtraction of the |xoff| variable
+ // above. |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
+ // into account. Only apply this code if |child| is false, since otherwise the left margin
+ // will get applied twice. -dwh
+ if (!child && flow != parent())
+ floatingObj->left += flow->marginLeft();
+ if ( !child ) {
+ floatingObj->left -= marginLeft();
+ floatingObj->noPaint = true;
+ }
+ else {
+ floatingObj->noPaint = (r->crossedLayer || !r->noPaint);
+ floatingObj->crossedLayer = r->crossedLayer;
+ }
+
+ floatingObj->width = r->width;
+ floatingObj->node = r->node;
+ if (!m_floatingObjects) {
+ m_floatingObjects = new TQPtrList<FloatingObject>;
+ m_floatingObjects->setAutoDelete(true);
+ }
+ m_floatingObjects->append(floatingObj);
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "addOverHangingFloats x/y= (" << floatingObj->left << "/" << floatingObj->startY << "-" << floatingObj->width << "/" << floatingObj->endY - floatingObj->startY << ")" << endl;
+#endif
+ }
+ }
+ }
+}
+
+bool RenderBlock::containsFloat(RenderObject* o) const
+{
+ if (m_floatingObjects) {
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ while (it.current()) {
+ if (it.current()->node == o)
+ return true;
+ ++it;
+ }
+ }
+ return false;
+}
+
+void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
+{
+ dirtyFormattingContext(false);
+ setChildNeedsLayout(true);
+
+ if (floatToRemove)
+ removeFloatingObject(floatToRemove);
+
+ // Iterate over our children and mark them as needed.
+ if (!childrenInline()) {
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (isBlockFlow() && !child->isFloatingOrPositioned() &&
+ ((floatToRemove ? child->containsFloat(floatToRemove) : child->hasFloats()) || child->usesLineWidth()))
+ child->markAllDescendantsWithFloatsForLayout(floatToRemove);
+ }
+ }
+}
+
+int RenderBlock::getClearDelta(RenderObject *child)
+{
+ if (!hasFloats())
+ return 0;
+
+ //kdDebug( 6040 ) << "getClearDelta on child " << child << " oldheight=" << m_height << endl;
+ bool clearSet = child->style()->clear() != CNONE;
+ int bottom = 0;
+ switch(child->style()->clear())
+ {
+ case CNONE:
+ break;
+ case CLEFT:
+ bottom = leftBottom();
+ break;
+ case CRIGHT:
+ bottom = rightBottom();
+ break;
+ case CBOTH:
+ bottom = floatBottom();
+ break;
+ }
+
+ // We also clear floats if we are too big to sit on the same line as a float, and happen to flow around floats.
+ // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
+ // to fit) and not all (we should be using nearestFloatBottom and looping).
+
+ int result = clearSet ? kMax(0, bottom - child->yPos()) : 0;
+ if (!result && child->flowAroundFloats() && !style()->width().isVariable()) {
+ bool canClearLine;
+ int lw = lineWidth(child->yPos(), &canClearLine);
+ if (((child->style()->width().isPercent() && child->width() > lw) ||
+ (child->style()->width().isFixed() && child->minWidth() > lw)) &&
+ child->minWidth() <= contentWidth() && canClearLine)
+ result = kMax(0, floatBottom() - child->yPos());
+ }
+ return result;
+}
+
+bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
+{
+ if (!scrollsOverflow() || !m_layer)
+ return false;
+
+ if (m_layer->verticalScrollbarWidth()) {
+ TQRect vertRect(_tx + width() - borderRight() - m_layer->verticalScrollbarWidth(),
+ _ty + borderTop() - borderTopExtra(),
+ m_layer->verticalScrollbarWidth(),
+ height() + borderTopExtra() + borderBottomExtra()-borderTop()-borderBottom());
+ if (vertRect.contains(_x, _y)) {
+#ifdef APPLE_CHANGES
+ RenderLayer::gScrollBar = m_layer->verticalScrollbar();
+#endif
+ return true;
+ }
+ }
+
+ if (m_layer->horizontalScrollbarHeight()) {
+ TQRect horizRect(_tx + borderLeft(),
+ _ty + height() + borderTop() + borderBottomExtra() - borderBottom() - m_layer->horizontalScrollbarHeight(),
+ width()-borderLeft()-borderRight(),
+ m_layer->horizontalScrollbarHeight());
+ if (horizRect.contains(_x, _y)) {
+#ifdef APPLE_CHANGES
+ RenderLayer::gScrollBar = m_layer->horizontalScrollbar();
+#endif
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox)
+{
+ bool inScrollbar = isPointInScrollbar(_x, _y, _tx+xPos(), _ty+yPos());
+ if (inScrollbar && hitTestAction != HitTestChildrenOnly)
+ inBox = true;
+
+ if (hitTestAction != HitTestSelfOnly && m_floatingObjects && !inScrollbar) {
+ int stx = _tx + xPos();
+ int sty = _ty + yPos();
+ if (hasOverflowClip() && m_layer)
+ m_layer->subtractScrollOffset(stx, sty);
+ FloatingObject* o;
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for (it.toLast(); (o = it.current()); --it)
+ if (!o->noPaint && !o->node->layer())
+ inBox |= o->node->nodeAtPoint(info, _x, _y,
+ stx+o->left + o->node->marginLeft() - o->node->xPos(),
+ sty+o->startY + o->node->marginTop() - o->node->yPos(), HitTestAll ) ;
+ }
+
+ inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
+ return inBox;
+}
+
+void RenderBlock::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
+#endif
+
+ m_minWidth = 0;
+ m_maxWidth = 0;
+
+ bool noWrap = !style()->autoWrap();
+ if (childrenInline())
+ calcInlineMinMaxWidth();
+ else
+ calcBlockMinMaxWidth();
+
+ if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
+
+ if (noWrap && childrenInline()) {
+ m_minWidth = m_maxWidth;
+
+ // A horizontal marquee with inline children has no minimum width.
+ if (style()->overflowX() == OMARQUEE && m_layer && m_layer->marquee() &&
+ m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
+ m_minWidth = 0;
+ }
+
+ if (isTableCell()) {
+ Length w = static_cast<RenderTableCell*>(this)->styleOrColWidth();
+ if (w.isFixed() && w.value() > 0)
+ m_maxWidth = kMax((int)m_minWidth, calcContentWidth(w.value()));
+ } else if (style()->width().isFixed() && style()->width().value() > 0)
+ m_minWidth = m_maxWidth = calcContentWidth(style()->width().value());
+
+ if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+ m_maxWidth = kMax(m_maxWidth, (int)calcContentWidth(style()->minWidth().value()));
+ m_minWidth = kMax(m_minWidth, (short)calcContentWidth(style()->minWidth().value()));
+ }
+
+ if (style()->maxWidth().isFixed() && style()->maxWidth().value() != UNDEFINED) {
+ m_maxWidth = kMin(m_maxWidth, (int)calcContentWidth(style()->maxWidth().value()));
+ m_minWidth = kMin(m_minWidth, (short)calcContentWidth(style()->maxWidth().value()));
+ }
+
+ int toAdd = 0;
+ toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+
+ m_minWidth += toAdd;
+ m_maxWidth += toAdd;
+
+ setMinMaxKnown();
+
+ //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
+ // ### compare with min/max width set in style sheet...
+}
+
+// bidi.cpp defines the following functions too.
+// Maybe these should not be static, after all...
+
+#ifndef KDE_USE_FINAL
+
+static int getBPMWidth(int childValue, Length cssUnit)
+{
+ if (!cssUnit.isVariable())
+ return (cssUnit.isFixed() ? cssUnit.value() : childValue);
+ return 0;
+}
+
+static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
+{
+ RenderStyle* cstyle = child->style();
+ int result = 0;
+ bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
+ result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
+ (leftSide ? cstyle->marginLeft() :
+ cstyle->marginRight()));
+ result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
+ (leftSide ? cstyle->paddingLeft() :
+ cstyle->paddingRight()));
+ result += leftSide ? child->borderLeft() : child->borderRight();
+ return result;
+}
+#endif
+
+static void stripTrailingSpace(bool preserveWS,
+ int& inlineMax, int& inlineMin,
+ RenderObject* trailingSpaceChild)
+{
+ if (!preserveWS && trailingSpaceChild && trailingSpaceChild->isText()) {
+ // Collapse away the trailing space at the end of a block.
+ RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
+ const Font *f = t->htmlFont( false );
+ TQChar space[1]; space[0] = ' ';
+ int spaceWidth = f->width(space, 1, 0);
+ inlineMax -= spaceWidth;
+ if (inlineMin > inlineMax)
+ inlineMin = inlineMax;
+ }
+}
+
+void RenderBlock::calcInlineMinMaxWidth()
+{
+ int inlineMax=0;
+ int inlineMin=0;
+
+ int cw = containingBlock()->contentWidth();
+ int floatMaxWidth = 0;
+
+ // If we are at the start of a line, we want to ignore all white-space.
+ // Also strip spaces if we previously had text that ended in a trailing space.
+ bool stripFrontSpaces = true;
+
+ bool isTcQuirk = isTableCell() && style()->htmlHacks() && style()->width().isVariable();
+
+ RenderObject* trailingSpaceChild = 0;
+
+ bool autoWrap, oldAutoWrap;
+ autoWrap = oldAutoWrap = style()->autoWrap();
+
+ InlineMinMaxIterator childIterator(this, this);
+ bool addedTextIndent = false; // Only gets added in once.
+ RenderObject* prevFloat = 0;
+ while (RenderObject* child = childIterator.next())
+ {
+ autoWrap = child->style()->autoWrap();
+
+ if( !child->isBR() )
+ {
+ // Step One: determine whether or not we need to go ahead and
+ // terminate our current line. Each discrete chunk can become
+ // the new min-width, if it is the widest chunk seen so far, and
+ // it can also become the max-width.
+
+ // Children fall into three categories:
+ // (1) An inline flow object. These objects always have a min/max of 0,
+ // and are included in the iteration solely so that their margins can
+ // be added in.
+ //
+ // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+ // These objects can always be on a line by themselves, so in this situation
+ // we need to go ahead and break the current line, and then add in our own
+ // margins and min/max width on its own line, and then terminate the line.
+ //
+ // (3) A text object. Text runs can have breakable characters at the start,
+ // the middle or the end. They may also lose whitespace off the front if
+ // we're already ignoring whitespace. In order to compute accurate min-width
+ // information, we need three pieces of information.
+ // (a) the min-width of the first non-breakable run. Should be 0 if the text string
+ // starts with whitespace.
+ // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+ // ends with whitespace.
+ // (c) the min/max width of the string (trimmed for whitespace).
+ //
+ // If the text string starts with whitespace, then we need to go ahead and
+ // terminate our current line (unless we're already in a whitespace stripping
+ // mode.
+ //
+ // If the text string has a breakable character in the middle, but didn't start
+ // with whitespace, then we add the width of the first non-breakable run and
+ // then end the current line. We then need to use the intermediate min/max width
+ // values (if any of them are larger than our current min/max). We then look at
+ // the width of the last non-breakable run and use that to start a new line
+ // (unless we end in whitespace).
+ RenderStyle* cstyle = child->style();
+ short childMin = 0;
+ short childMax = 0;
+
+ if (!child->isText()) {
+ // Case (1) and (2). Inline replaced and inline flow elements.
+ if (child->isInlineFlow()) {
+ // Add in padding/border/margin from the appropriate side of
+ // the element.
+ int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
+ childMin += bpm;
+ childMax += bpm;
+
+ inlineMin += childMin;
+ inlineMax += childMax;
+ }
+ else {
+ // Inline replaced elements add in their margins to their min/max values.
+ int margins = 0;
+ LengthType type = cstyle->marginLeft().type();
+ if ( type != Variable )
+ margins += (type == Fixed ? cstyle->marginLeft().value() : child->marginLeft());
+ type = cstyle->marginRight().type();
+ if ( type != Variable )
+ margins += (type == Fixed ? cstyle->marginRight().value() : child->marginRight());
+ childMin += margins;
+ childMax += margins;
+ }
+ }
+
+ if (!child->isRenderInline() && !child->isText()) {
+
+ bool qBreak = isTcQuirk && !child->isFloatingOrPositioned();
+ // Case (2). Inline replaced elements and floats.
+ // Go ahead and terminate the current line as far as
+ // minwidth is concerned.
+ childMin += child->minWidth();
+ childMax += child->maxWidth();
+
+ if (!qBreak && (autoWrap || oldAutoWrap)) {
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = 0;
+ }
+
+ // Check our "clear" setting. If we're supposed to clear the previous float, then
+ // go ahead and terminate maxwidth as well.
+ if (child->isFloating()) {
+ if (prevFloat &&
+ ((inlineMax + childMax > floatMaxWidth) ||
+ ((prevFloat->style()->floating() & FLEFT) && (child->style()->clear() & CLEFT)) ||
+ ((prevFloat->style()->floating() & FRIGHT) && (child->style()->clear() & CRIGHT)))) {
+ m_maxWidth = kMax(inlineMax, (int)m_maxWidth);
+ inlineMax = 0;
+ }
+ prevFloat = child;
+ if (!floatMaxWidth)
+ floatMaxWidth = availableWidth();
+ }
+
+ // Add in text-indent. This is added in only once.
+ int ti = 0;
+ if ( !addedTextIndent ) {
+ addedTextIndent = true;
+ ti = style()->textIndent().minWidth( cw );
+ childMin+=ti;
+ childMax+=ti;
+ }
+
+ // Add our width to the max.
+ inlineMax += childMax;
+
+ if (!autoWrap||qBreak)
+ inlineMin += childMin;
+ else {
+ // Now check our line.
+ inlineMin = childMin;
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+
+ // Now start a new line.
+ inlineMin = 0;
+ }
+
+ // We are no longer stripping whitespace at the start of
+ // a line.
+ if (!child->isFloating()) {
+ stripFrontSpaces = false;
+ trailingSpaceChild = 0;
+ }
+ }
+ else if (child->isText())
+ {
+ // Case (3). Text.
+ RenderText* t = static_cast<RenderText *>(child);
+
+ // Determine if we have a breakable character. Pass in
+ // whether or not we should ignore any spaces at the front
+ // of the string. If those are going to be stripped out,
+ // then they shouldn't be considered in the breakable char
+ // check.
+ bool hasBreakableChar, hasBreak;
+ short beginMin, endMin;
+ bool beginWS, endWS;
+ short beginMax, endMax;
+ t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
+ hasBreak, beginMax, endMax,
+ childMin, childMax, stripFrontSpaces);
+
+ // This text object is insignificant and will not be rendered. Just
+ // continue.
+ if (!hasBreak && childMax == 0) continue;
+
+ if (stripFrontSpaces)
+ trailingSpaceChild = child;
+ else
+ trailingSpaceChild = 0;
+
+ // Add in text-indent. This is added in only once.
+ int ti = 0;
+ if (!addedTextIndent) {
+ addedTextIndent = true;
+ ti = style()->textIndent().minWidth(cw);
+ childMin+=ti; beginMin += ti;
+ childMax+=ti; beginMax += ti;
+ }
+
+ // If we have no breakable characters at all,
+ // then this is the easy case. We add ourselves to the current
+ // min and max and continue.
+ if (!hasBreakableChar) {
+ inlineMin += childMin;
+ }
+ else {
+ // We have a breakable character. Now we need to know if
+ // we start and end with whitespace.
+ if (beginWS) {
+ // Go ahead and end the current line.
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ }
+ else {
+ inlineMin += beginMin;
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ childMin -= ti;
+ }
+
+ inlineMin = childMin;
+
+ if (endWS) {
+ // We end in whitespace, which means we can go ahead
+ // and end our current line.
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = 0;
+ }
+ else {
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ inlineMin = endMin;
+ }
+ }
+
+ if (hasBreak) {
+ inlineMax += beginMax;
+ if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+ if (m_maxWidth < childMax) m_maxWidth = childMax;
+ inlineMax = endMax;
+ }
+ else
+ inlineMax += childMax;
+ }
+ }
+ else
+ {
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+ inlineMin = inlineMax = 0;
+ stripFrontSpaces = true;
+ trailingSpaceChild = 0;
+ }
+
+ oldAutoWrap = autoWrap;
+ }
+
+ stripTrailingSpace(style()->preserveWS(), inlineMax, inlineMin, trailingSpaceChild);
+
+ if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+ if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+ // kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
+ // << " m_maxWidth=" << m_maxWidth << endl;
+}
+
+// Use a very large value (in effect infinite).
+#define BLOCK_MAX_WIDTH 15000
+
+void RenderBlock::calcBlockMinMaxWidth()
+{
+ bool nowrap = !style()->autoWrap();
+
+ RenderObject *child = firstChild();
+ RenderObject* prevFloat = 0;
+ int floatWidths = 0;
+ int floatMaxWidth = 0;
+
+ while(child != 0)
+ {
+ // positioned children don't affect the minmaxwidth
+ if (child->isPositioned()) {
+ child = child->nextSibling();
+ continue;
+ }
+
+ if (prevFloat && (!child->isFloating() ||
+ ((prevFloat->style()->floating() & FLEFT) && (child->style()->clear() & CLEFT)) ||
+ ((prevFloat->style()->floating() & FRIGHT) && (child->style()->clear() & CRIGHT)))) {
+ m_maxWidth = kMax(floatWidths, m_maxWidth);
+ floatWidths = 0;
+ }
+
+ Length ml = child->style()->marginLeft();
+ Length mr = child->style()->marginRight();
+
+ // Call calcWidth on the child to ensure that our margins are
+ // up to date. This method can be called before the child has actually
+ // calculated its margins (which are computed inside calcWidth).
+ if (ml.isPercent() || mr.isPercent())
+ calcWidth();
+
+ // A margin basically has three types: fixed, percentage, and auto (variable).
+ // Auto margins simply become 0 when computing min/max width.
+ // Fixed margins can be added in as is.
+ // Percentage margins are computed as a percentage of the width we calculated in
+ // the calcWidth call above. In this case we use the actual cached margin values on
+ // the RenderObject itself.
+ int margin = 0;
+ if (ml.isFixed())
+ margin += ml.value();
+ else if (ml.isPercent())
+ margin += child->marginLeft();
+
+ if (mr.isFixed())
+ margin += mr.value();
+ else if (mr.isPercent())
+ margin += child->marginRight();
+
+ if (margin < 0) margin = 0;
+
+ int w = child->minWidth() + margin;
+ if(m_minWidth < w) m_minWidth = w;
+ // IE ignores tables for calculation of nowrap. Makes some sense.
+ if ( nowrap && !child->isTable() && m_maxWidth < w )
+ m_maxWidth = w;
+
+ w = child->maxWidth() + margin;
+
+ if(m_maxWidth < w) m_maxWidth = w;
+
+ if (child->isFloating()) {
+ if (prevFloat && (floatWidths + w > floatMaxWidth)) {
+ m_maxWidth = kMax(floatWidths, m_maxWidth);
+ floatWidths = w;
+ } else
+ floatWidths += w;
+ } else if (m_maxWidth < w)
+ m_maxWidth = w;
+
+ // A very specific WinIE quirk.
+ // Example:
+ /*
+ <div style="position:absolute; width:100px; top:50px;">
+ <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
+ <table style="width:100%"><tr><td></table>
+ </div>
+ </div>
+ */
+ // In the above example, the inner absolute positioned block should have a computed width
+ // of 100px because of the table.
+ // We can achieve this effect by making the maxwidth of blocks that contain tables
+ // with percentage widths be infinite (as long as they are not inside a table cell).
+ if (style()->htmlHacks() && child->style()->width().isPercent() &&
+ !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
+ RenderBlock* cb = containingBlock();
+ while (!cb->isCanvas() && !cb->isTableCell())
+ cb = cb->containingBlock();
+ if (!cb->isTableCell())
+ m_maxWidth = BLOCK_MAX_WIDTH;
+ }
+ if (child->isFloating()) {
+ prevFloat = child;
+ if (!floatMaxWidth)
+ floatMaxWidth = availableWidth();
+ }
+ child = child->nextSibling();
+ }
+ m_maxWidth = kMax(floatWidths, m_maxWidth);
+}
+
+void RenderBlock::close()
+{
+ if (lastChild() && lastChild()->isAnonymousBlock())
+ lastChild()->close();
+ updateFirstLetter();
+ RenderFlow::close();
+}
+
+int RenderBlock::getBaselineOfFirstLineBox()
+{
+ if (m_firstLineBox)
+ return m_firstLineBox->yPos() + m_firstLineBox->baseline();
+
+ if (isInline())
+ return -1; // We're inline and had no line box, so we have no baseline we can return.
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ int result = curr->getBaselineOfFirstLineBox();
+ if (result != -1)
+ return curr->yPos() + result; // Translate to our coordinate space.
+ }
+
+ return -1;
+}
+
+InlineFlowBox* RenderBlock::getFirstLineBox()
+{
+ if (m_firstLineBox)
+ return m_firstLineBox;
+
+ if (isInline())
+ return 0; // We're inline and had no line box, so we have no baseline we can return.
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ InlineFlowBox* result = curr->getFirstLineBox();
+ if (result)
+ return result;
+ }
+
+ return 0;
+}
+
+bool RenderBlock::inRootBlockContext() const
+{
+ if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
+ return false;
+
+ if (isRoot() || isCanvas())
+ return true;
+
+ return containingBlock()->inRootBlockContext();
+}
+
+const char *RenderBlock::renderName() const
+{
+ if (isFloating())
+ return "RenderBlock (floating)";
+ if (isPositioned())
+ return "RenderBlock (positioned)";
+ if (isAnonymousBlock() && m_avoidPageBreak)
+ return "RenderBlock (avoidPageBreak)";
+ if (isAnonymousBlock())
+ return "RenderBlock (anonymous)";
+ else if (isAnonymous())
+ return "RenderBlock (generated)";
+ if (isRelPositioned())
+ return "RenderBlock (relative positioned)";
+ if (style() && style()->display() == COMPACT)
+ return "RenderBlock (compact)";
+ if (style() && style()->display() == RUN_IN)
+ return "RenderBlock (run-in)";
+ return "RenderBlock";
+}
+
+#ifdef ENABLE_DUMP
+void RenderBlock::printTree(int indent) const
+{
+ RenderFlow::printTree(indent);
+
+ if (m_floatingObjects)
+ {
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ FloatingObject *r;
+ for ( ; (r = it.current()); ++it )
+ {
+ TQString s;
+ s.fill(' ', indent);
+ kdDebug() << s << renderName() << ": " <<
+ (r->type == FloatingObject::FloatLeft ? "FloatLeft" : "FloatRight" ) <<
+ "[" << r->node->renderName() << ": " << (void*)r->node << "] (" << r->startY << " - " << r->endY << ")" << "width: " << r->width <<
+ endl;
+ }
+ }
+}
+
+void RenderBlock::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderFlow::dump(stream,ind);
+
+ if (m_childrenInline) { stream << " childrenInline"; }
+ // FIXME: currently only print pre to not mess up regression
+ if (style()->preserveWS()) { stream << " pre"; }
+ if (m_firstLine) { stream << " firstLine"; }
+
+ if (m_floatingObjects && !m_floatingObjects->isEmpty())
+ {
+ stream << " special(";
+ TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ FloatingObject *r;
+ bool first = true;
+ for ( ; (r = it.current()); ++it )
+ {
+ if (!first)
+ stream << ",";
+ stream << r->node->renderName();
+ first = false;
+ }
+ stream << ")";
+ }
+
+ // ### EClear m_clearStatus
+}
+#endif
+
+#undef DEBUG
+#undef DEBUG_LAYOUT
+#undef BOX_DEBUG
+
+} // namespace tdehtml
+
diff --git a/tdehtml/rendering/render_block.h b/tdehtml/rendering/render_block.h
new file mode 100644
index 000000000..84fd15a0b
--- /dev/null
+++ b/tdehtml/rendering/render_block.h
@@ -0,0 +1,378 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 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.
+ *
+ */
+
+#ifndef RENDER_BLOCK_H
+#define RENDER_BLOCK_H
+
+#include <tqptrlist.h>
+
+#include "render_flow.h"
+
+namespace tdehtml {
+
+class RenderBlock : public RenderFlow
+{
+public:
+ RenderBlock(DOM::NodeImpl* node);
+ virtual ~RenderBlock();
+
+ virtual const char *renderName() const;
+
+ virtual bool isRenderBlock() const { return true; }
+ virtual bool isBlockFlow() const { return !isInline() && !isTable(); }
+ virtual bool isInlineFlow() const { return isInline() && !isReplaced(); }
+ virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
+
+ virtual bool childrenInline() const { return m_childrenInline; }
+ virtual void setChildrenInline(bool b) { m_childrenInline = b; }
+ void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+
+ void makePageBreakAvoidBlocks();
+
+ // The height (and width) of a block when you include overflow spillage out of the bottom
+ // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
+ // it would have an overflow height of borderTop() + paddingTop() + 100px.
+ virtual int overflowHeight() const { return m_overflowHeight; }
+ virtual int overflowWidth() const { return m_overflowWidth; }
+ virtual int overflowLeft() const { return m_overflowLeft; }
+ virtual int overflowTop() const { return m_overflowTop; }
+ virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
+ virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
+ virtual void setOverflowLeft(int l) { m_overflowLeft = l; }
+ virtual void setOverflowTop(int t) { m_overflowTop = t; }
+
+ virtual bool isSelfCollapsingBlock() const;
+ virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
+ virtual bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
+
+ virtual short maxTopMargin(bool positive) const {
+ if (positive)
+ return m_maxTopPosMargin;
+ else
+ return m_maxTopNegMargin;
+ }
+ virtual short maxBottomMargin(bool positive) const {
+ if (positive)
+ return m_maxBottomPosMargin;
+ else
+ return m_maxBottomNegMargin;
+ }
+
+ void initMaxMarginValues() {
+ if (m_marginTop >= 0)
+ m_maxTopPosMargin = m_marginTop;
+ else
+ m_maxTopNegMargin = -m_marginTop;
+ if (m_marginBottom >= 0)
+ m_maxBottomPosMargin = m_marginBottom;
+ else
+ m_maxBottomNegMargin = -m_marginBottom;
+ }
+
+ virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
+ virtual void removeChild(RenderObject *oldChild);
+
+ virtual void setStyle(RenderStyle* _style);
+ virtual void attach();
+ void updateFirstLetter();
+
+ virtual void layout();
+ void layoutBlock( bool relayoutChildren );
+ void layoutBlockChildren( bool relayoutChildren );
+ void layoutInlineChildren( bool relayoutChildren, int breakBeforeLine = 0);
+
+ void layoutPositionedObjects( bool relayoutChildren );
+ void insertPositionedObject(RenderObject *o);
+ void removePositionedObject(RenderObject *o);
+
+ // Called to lay out the legend for a fieldset.
+ virtual RenderObject* layoutLegend(bool /*relayoutChildren*/) { return 0; };
+
+ // the implementation of the following functions is in bidi.cpp
+ void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi );
+ BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info );
+ InlineFlowBox* constructLine(const BidiIterator& start, const BidiIterator& end);
+ InlineFlowBox* createLineBoxes(RenderObject* obj);
+ void computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi);
+ void computeVerticalPositionsForLine(InlineFlowBox* lineBox);
+ bool clearLineOfPageBreaks(InlineFlowBox* lineBox);
+ void checkLinesForOverflow();
+ void deleteEllipsisLineBoxes();
+ void checkLinesForTextOverflow();
+ // end bidi.cpp functions
+
+ virtual void paint(PaintInfo& i, int tx, int ty);
+ void paintObject(PaintInfo& i, int tx, int ty, bool paintOutline = true);
+ void paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection = false);
+
+ void insertFloatingObject(RenderObject *o);
+ void removeFloatingObject(RenderObject *o);
+
+ // called from lineWidth, to position the floats added in the last line.
+ void positionNewFloats();
+ void clearFloats();
+ int getClearDelta(RenderObject *child);
+ virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
+
+ // FIXME: containsFloats() should not return true if the floating objects list
+ // is empty. However, layoutInlineChildren() relies on the current behavior.
+ // http://bugzilla.opendarwin.org/show_bug.cgi?id=7395#c3
+ virtual bool hasFloats() const { return m_floatingObjects!=0; }
+ virtual bool containsFloat(RenderObject* o) const;
+
+ virtual bool hasOverhangingFloats() const { return floatBottom() > m_height; }
+ void addOverHangingFloats( RenderBlock *block, int xoffset, int yoffset, bool child );
+
+ int nearestFloatBottom(int height) const;
+ int floatBottom() const;
+ inline int leftBottom();
+ inline int rightBottom();
+
+ virtual unsigned short lineWidth(int y, bool *canClearLine = 0) const;
+ virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int highestPosition(bool includeOverflowInterior, bool includeSelf) const;
+ int lowestAbsolutePosition() const;
+ int leftmostAbsolutePosition() const;
+ int rightmostAbsolutePosition() const;
+ int highestAbsolutePosition() const;
+
+ int rightOffset() const;
+ int rightRelOffset(int y, int fixedOffset, bool applyTextIndent=true, int *heightRemaining = 0, bool *canClearLine = 0) const;
+ int rightOffset(int y, bool *canClearLine = 0) const { return rightRelOffset(y, rightOffset(), true, 0, canClearLine); }
+
+ int leftOffset() const;
+ int leftRelOffset(int y, int fixedOffset, bool applyTextIndent=true, int *heightRemaining = 0, bool *canClearLine = 0) const;
+ int leftOffset(int y, bool *canClearLine = 0) const { return leftRelOffset(y, leftOffset(), true, 0, canClearLine); }
+
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int _tx, int _ty, HitTestAction hitTestAction = HitTestAll, bool inside=false);
+
+ bool isPointInScrollbar(int x, int y, int tx, int ty);
+
+ virtual void calcMinMaxWidth();
+ void calcInlineMinMaxWidth();
+ void calcBlockMinMaxWidth();
+
+ virtual void close();
+
+ virtual int getBaselineOfFirstLineBox();
+ virtual InlineFlowBox* getFirstLineBox();
+
+ RootInlineBox* firstRootBox() { return static_cast<RootInlineBox*>(m_firstLineBox); }
+ RootInlineBox* lastRootBox() { return static_cast<RootInlineBox*>(m_lastLineBox); }
+
+ bool inRootBlockContext() const;
+
+#ifdef ENABLE_DUMP
+ virtual void printTree(int indent=0) const;
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+protected:
+ void newLine();
+
+protected:
+ struct FloatingObject {
+ enum Type {
+ FloatLeft,
+ FloatRight
+ };
+
+ FloatingObject(Type _type) {
+ node = 0;
+ startY = 0;
+ endY = 0;
+ type = _type;
+ left = 0;
+ width = 0;
+ noPaint = false;
+ crossedLayer = false;
+
+ }
+ RenderObject* node;
+ int startY;
+ int endY;
+ short left;
+ short width;
+ Type type : 1; // left or right aligned
+ bool noPaint : 1;
+ bool crossedLayer : 1; // lock noPaint flag
+ };
+
+ // The following helper functions and structs are used by layoutBlockChildren.
+ class CompactInfo {
+ // A compact child that needs to be collapsed into the margin of the following block.
+ RenderObject* m_compact;
+
+ // The block with the open margin that the compact child is going to place itself within.
+ RenderObject* m_block;
+ bool m_treatAsBlock : 1;
+
+ public:
+ RenderObject* compact() const { return m_compact; }
+ RenderObject* block() const { return m_block; }
+ void setTreatAsBlock(bool b) { m_treatAsBlock = b; }
+ bool treatAsBlock() const { return m_treatAsBlock; }
+ bool matches(RenderObject* child) const { return m_compact && m_block == child; }
+
+ void clear() { set(0, 0); }
+ void set(RenderObject* c, RenderObject* b) { m_compact = c; m_block = b; }
+
+ CompactInfo() { clear(); }
+ };
+
+ class MarginInfo {
+ // Collapsing flags for whether we can collapse our margins with our children's margins.
+ bool m_canCollapseWithChildren : 1;
+ bool m_canCollapseTopWithChildren : 1;
+ bool m_canCollapseBottomWithChildren : 1;
+
+ // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
+ // margins in our container. Table cells and the body are the common examples. We
+ // also have a custom style property for Safari RSS to deal with TypePad blog articles.
+ bool m_quirkContainer : 1;
+
+ // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
+ // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
+ // always be collapsing with one another. This variable can remain set to true through multiple iterations
+ // as long as we keep encountering self-collapsing blocks.
+ bool m_atTopOfBlock : 1;
+
+ // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
+ bool m_atBottomOfBlock : 1;
+
+ // If our last normal flow child was a self-collapsing block that cleared a float,
+ // we track it in this variable.
+ bool m_selfCollapsingBlockClearedFloat : 1;
+
+ // These variables are used to detect quirky margins that we need to collapse away (in table cells
+ // and in the body element).
+ bool m_topQuirk : 1;
+ bool m_bottomQuirk : 1;
+ bool m_determinedTopQuirk : 1;
+
+ // These flags track the previous maximal positive and negative margins.
+ int m_posMargin;
+ int m_negMargin;
+
+ public:
+ MarginInfo(RenderBlock* b, int top, int bottom);
+
+ void setAtTopOfBlock(bool b) { m_atTopOfBlock = b; }
+ void setAtBottomOfBlock(bool b) { m_atBottomOfBlock = b; }
+ void clearMargin() { m_posMargin = m_negMargin = 0; }
+ void setSelfCollapsingBlockClearedFloat(bool b) { m_selfCollapsingBlockClearedFloat = b; }
+ void setTopQuirk(bool b) { m_topQuirk = b; }
+ void setBottomQuirk(bool b) { m_bottomQuirk = b; }
+ void setDeterminedTopQuirk(bool b) { m_determinedTopQuirk = b; }
+ void setPosMargin(int p) { m_posMargin = p; }
+ void setNegMargin(int n) { m_negMargin = n; }
+ void setPosMarginIfLarger(int p) { if (p > m_posMargin) m_posMargin = p; }
+ void setNegMarginIfLarger(int n) { if (n > m_negMargin) m_negMargin = n; }
+
+ void setMargin(int p, int n) { m_posMargin = p; m_negMargin = n; }
+
+ bool atTopOfBlock() const { return m_atTopOfBlock; }
+ bool canCollapseWithTop() const { return m_atTopOfBlock && m_canCollapseTopWithChildren; }
+ bool canCollapseWithBottom() const { return m_atBottomOfBlock && m_canCollapseBottomWithChildren; }
+ bool canCollapseTopWithChildren() const { return m_canCollapseTopWithChildren; }
+ bool canCollapseBottomWithChildren() const { return m_canCollapseBottomWithChildren; }
+ bool selfCollapsingBlockClearedFloat() const { return m_selfCollapsingBlockClearedFloat; }
+ bool quirkContainer() const { return m_quirkContainer; }
+ bool determinedTopQuirk() const { return m_determinedTopQuirk; }
+ bool topQuirk() const { return m_topQuirk; }
+ bool bottomQuirk() const { return m_bottomQuirk; }
+ int posMargin() const { return m_posMargin; }
+ int negMargin() const { return m_negMargin; }
+ int margin() const { return m_posMargin - m_negMargin; }
+ };
+
+ class PageBreakInfo {
+ int m_pageBottom; // Next calculated page-break
+ bool m_forcePageBreak : 1; // Must break before next block
+ // ### to do better "page-break-after/before: avoid" this struct
+ // should keep a pagebreakAvoid block and gather children in it
+ public:
+ PageBreakInfo(int pageBottom) : m_pageBottom(pageBottom), m_forcePageBreak(false) {};
+ bool forcePageBreak() { return m_forcePageBreak; }
+ void setForcePageBreak(bool b) { m_forcePageBreak = b; }
+ int pageBottom() { return m_pageBottom; };
+ void setPageBottom(int bottom) { m_pageBottom = bottom; }
+ };
+
+ virtual bool canClear(RenderObject *child, PageBreakLevel level);
+ void clearPageBreak(RenderObject* child, int pageBottom);
+
+ void adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo);
+ void adjustFloatingBlock(const MarginInfo& marginInfo);
+ RenderObject* handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled);
+ RenderObject* handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled);
+ RenderObject* handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled);
+ RenderObject* handleCompactChild(RenderObject* child, CompactInfo& compactInfo, const MarginInfo& marginInfo, bool& handled);
+ RenderObject* handleRunInChild(RenderObject* child, bool& handled);
+ void collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate);
+ void clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin);
+ void adjustSizeForCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo);
+ void insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo);
+ int estimateVerticalPosition(RenderObject* child, const MarginInfo& info);
+ void determineHorizontalPosition(RenderObject* child);
+ void handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo);
+ void setCollapsedBottomMargin(const MarginInfo& marginInfo);
+ void clearChildOfPageBreaks(RenderObject* child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo);
+ // End helper functions and structs used by layoutBlockChildren.
+
+protected:
+ // How much content overflows out of our block vertically or horizontally (all we support
+ // for now is spillage out of the bottom and the right, which are the common cases).
+ int m_overflowHeight;
+ int m_overflowWidth;
+
+ // Left and top overflow.
+ int m_overflowTop;
+ int m_overflowLeft;
+
+private:
+ TQPtrList<FloatingObject>* m_floatingObjects;
+ TQPtrList<RenderObject>* m_positionedObjects;
+
+ bool m_childrenInline : 1;
+ bool m_firstLine : 1; // used in inline layouting
+ EClear m_clearStatus : 2; // used during layuting of paragraphs
+ bool m_avoidPageBreak : 1; // anonymous avoid page-break block
+ bool m_topMarginQuirk : 1;
+ bool m_bottomMarginQuirk : 1;
+
+ short m_maxTopPosMargin;
+ short m_maxTopNegMargin;
+ short m_maxBottomPosMargin;
+ short m_maxBottomNegMargin;
+
+};
+
+} // namespace
+
+#endif // RENDER_BLOCK_H
+
diff --git a/tdehtml/rendering/render_body.cpp b/tdehtml/rendering/render_body.cpp
new file mode 100644
index 000000000..80a613000
--- /dev/null
+++ b/tdehtml/rendering/render_body.cpp
@@ -0,0 +1,121 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000-2003 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 "rendering/render_body.h"
+#include "rendering/render_canvas.h"
+#include "html/html_baseimpl.h"
+#include "xml/dom_docimpl.h"
+#include "tdehtmlview.h"
+
+#include <kglobal.h>
+#include <kdebug.h>
+
+using namespace tdehtml;
+using namespace DOM;
+
+RenderBody::RenderBody(HTMLBodyElementImpl* element)
+ : RenderBlock(element)
+{
+ scrollbarsStyled = false;
+}
+
+RenderBody::~RenderBody()
+{
+}
+
+void RenderBody::setStyle(RenderStyle* style)
+{
+// tqDebug("RenderBody::setStyle()");
+ // ignore position: fixed on body
+ if (style->htmlHacks() && style->position() == FIXED)
+ style->setPosition(STATIC);
+
+ RenderBlock::setStyle(style);
+ document()->setTextColor( style->color() );
+ scrollbarsStyled = false;
+}
+
+void RenderBody::paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
+ TQColor bgColor;
+ const BackgroundLayer *bgLayer = 0;
+
+ if( parent()->style()->hasBackground() ) {
+ // the root element already has a non-transparent background of its own
+ // so we must fork our own. (CSS2.1 - 14.2 §4)
+ bgColor = style()->backgroundColor();
+ bgLayer = style()->backgroundLayers();
+ }
+
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ _ty -= borderTopExtra();
+
+ int my = kMax(_ty, paintInfo.r.y());
+ int end = kMin( paintInfo.r.y()+paintInfo.r.height(), _ty + h );
+ int mh = end - my;
+
+ paintBackgrounds(paintInfo.p, bgColor, bgLayer, my, mh, _tx, _ty, w, h);
+
+ if(style()->hasBorder())
+ paintBorder( paintInfo.p, _tx, _ty, w, h, style() );
+
+}
+
+void RenderBody::repaint(Priority p)
+{
+ RenderObject *cb = containingBlock();
+ if(cb)
+ cb->repaint(p);
+}
+
+void RenderBody::layout()
+{
+ // in quirk mode, we'll need to have our margins determined
+ // for percentage height calculations
+ if (style()->htmlHacks())
+ calcHeight();
+ RenderBlock::layout();
+
+ if (!scrollbarsStyled)
+ {
+ RenderCanvas* canvas = this->canvas();
+ if (canvas->view())
+ {
+ canvas->view()->horizontalScrollBar()->setPalette(style()->palette());
+ canvas->view()->verticalScrollBar()->setPalette(style()->palette());
+ }
+ scrollbarsStyled=true;
+ }
+}
+
+int RenderBody::availableHeight() const
+{
+ int h = RenderBlock::availableHeight();
+
+ if( style()->marginTop().isFixed() )
+ h -= style()->marginTop().value();
+ if( style()->marginBottom().isFixed() )
+ h -= style()->marginBottom().value();
+
+ return kMax(0, h);
+}
diff --git a/tdehtml/rendering/render_body.h b/tdehtml/rendering/render_body.h
new file mode 100644
index 000000000..b7ac7c99a
--- /dev/null
+++ b/tdehtml/rendering/render_body.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000-2003 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 RENDER_BODY
+#define RENDER_BODY
+
+#include "rendering/render_block.h"
+
+namespace DOM
+{
+ class HTMLBodyElementImpl;
+}
+
+namespace tdehtml {
+
+class RenderBody : public RenderBlock
+{
+public:
+ RenderBody(DOM::HTMLBodyElementImpl* node);
+ virtual ~RenderBody();
+
+ virtual bool isBody() const { return true; }
+
+ virtual const char *renderName() const { return "RenderBody"; }
+ virtual void repaint(Priority p=NormalPriority);
+
+ virtual void layout();
+ virtual void setStyle(RenderStyle* style);
+
+ virtual int availableHeight() const;
+
+protected:
+ virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
+ bool scrollbarsStyled;
+};
+
+} // end namespace
+#endif
diff --git a/tdehtml/rendering/render_box.cpp b/tdehtml/rendering/render_box.cpp
new file mode 100644
index 000000000..4cf7080c7
--- /dev/null
+++ b/tdehtml/rendering/render_box.cpp
@@ -0,0 +1,2325 @@
+/**
+ * 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) 2002-2003 Apple Computer, Inc.
+ * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * (C) 2006 Samuel Weinig (sam.weinig@gmail.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_LAYOUT
+//#define CLIP_DEBUG
+
+
+#include <tqpainter.h>
+
+#include "misc/loader.h"
+#include "rendering/render_replaced.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_table.h"
+#include "rendering/render_inline.h"
+#include "rendering/render_block.h"
+#include "rendering/render_line.h"
+#include "rendering/render_layer.h"
+#include "misc/htmlhashes.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "html/html_elementimpl.h"
+
+#include <tdehtmlview.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <assert.h>
+
+
+using namespace DOM;
+using namespace tdehtml;
+
+#define TABLECELLMARGIN -0x4000
+
+RenderBox::RenderBox(DOM::NodeImpl* node)
+ : RenderContainer(node)
+{
+ m_minWidth = -1;
+ m_maxWidth = -1;
+ m_width = m_height = 0;
+ m_x = 0;
+ m_y = 0;
+ m_marginTop = 0;
+ m_marginBottom = 0;
+ m_marginLeft = 0;
+ m_marginRight = 0;
+ m_staticX = 0;
+ m_staticY = 0;
+
+ m_placeHolderBox = 0;
+ m_layer = 0;
+}
+
+RenderBlock* RenderBox::createAnonymousBlock()
+{
+ RenderStyle *newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(BLOCK);
+
+ RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous*/);
+ newBox->setStyle(newStyle);
+ return newBox;
+}
+
+void RenderBox::restructureParentFlow() {
+ if (!parent() || parent()->childrenInline() == isInline())
+ return;
+ // We have gone from not affecting the inline status of the parent flow to suddenly
+ // having an impact. See if there is a mismatch between the parent flow's
+ // childrenInline() state and our state.
+ if (!isInline()) {
+ if (parent()->isRenderInline()) {
+ // We have to split the parent flow.
+ RenderInline* parentInline = static_cast<RenderInline*>(parent());
+ RenderBlock* newBox = parentInline->createAnonymousBlock();
+
+ RenderFlow* oldContinuation = parent()->continuation();
+ parentInline->setContinuation(newBox);
+
+ RenderObject* beforeChild = nextSibling();
+ parent()->removeChildNode(this);
+ parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
+ }
+ else if (parent()->isRenderBlock())
+ static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
+ }
+ else {
+ // An anonymous block must be made to wrap this inline.
+ RenderBlock* box = createAnonymousBlock();
+ parent()->insertChildNode(box, this);
+ box->appendChildNode(parent()->removeChildNode(this));
+ }
+}
+
+static inline bool overflowAppliesTo(RenderObject* o)
+{
+ // css 2.1-11.1.1
+ // 1) overflow only applies to non-replaced block-level elements, table cells, and inline-block elements
+ if (o->isRenderBlock() || o->isTableRow() || o->isTableSection())
+ // 2) overflow on root applies to the viewport (cf. KHTMLView::layout)
+ if (!o->isRoot())
+ // 3) overflow on body may apply to the viewport...
+ if (!o->isBody()
+ // ...but only for HTML documents...
+ || !o->document()->isHTMLDocument()
+ // ...and only when the root has a visible overflow
+ || !o->document()->documentElement()->renderer()
+ || !o->document()->documentElement()->renderer()->style()
+ || o->document()->documentElement()->renderer()->style()->hidesOverflow())
+ return true;
+
+ return false;
+}
+
+void RenderBox::setStyle(RenderStyle *_style)
+{
+ bool affectsParent = style() && isFloatingOrPositioned() &&
+ (!_style->isFloating() && _style->position() != ABSOLUTE && _style->position() != FIXED) &&
+ parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
+
+ RenderContainer::setStyle(_style);
+
+ // The root always paints its background/border.
+ if (isRoot())
+ setShouldPaintBackgroundOrBorder(true);
+
+ switch(_style->display())
+ {
+ case INLINE:
+ case INLINE_BLOCK:
+ case INLINE_TABLE:
+ setInline(true);
+ break;
+ case RUN_IN:
+ if (isInline() && parent() && parent()->childrenInline())
+ break;
+ default:
+ setInline(false);
+ }
+
+ switch(_style->position())
+ {
+ case ABSOLUTE:
+ case FIXED:
+ setPositioned(true);
+ break;
+ default:
+ setPositioned(false);
+ if( !isTableCell() && _style->isFloating() )
+ setFloating(true);
+
+ if( _style->position() == RELATIVE )
+ setRelPositioned(true);
+ }
+
+ if (overflowAppliesTo(this) && _style->hidesOverflow())
+ setHasOverflowClip();
+
+ if (requiresLayer()) {
+ if (!m_layer) {
+ m_layer = new (renderArena()) RenderLayer(this);
+ m_layer->insertOnlyThisLayer();
+ if (parent() && containingBlock())
+ m_layer->updateLayerPosition();
+ }
+ }
+ else if (m_layer && !isCanvas()) {
+ m_layer->removeOnlyThisLayer();
+ m_layer = 0;
+ }
+
+ if (m_layer)
+ m_layer->styleChanged();
+
+ if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintActionOutline))
+ static_cast<RenderCanvas*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
+ if (affectsParent)
+ restructureParentFlow();
+}
+
+RenderBox::~RenderBox()
+{
+ //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
+}
+
+void RenderBox::detach()
+{
+ RenderLayer* layer = m_layer;
+ RenderArena* arena = renderArena();
+
+ RenderContainer::detach();
+
+ if (layer)
+ layer->detach(arena);
+}
+
+InlineBox* RenderBox::createInlineBox(bool /*makePlaceHolderBox*/, bool /*isRootLineBox*/)
+{
+ if (m_placeHolderBox)
+ m_placeHolderBox->detach(renderArena());
+ return (m_placeHolderBox = new (renderArena()) InlineBox(this));
+}
+
+void RenderBox::deleteInlineBoxes(RenderArena* arena)
+{
+ if (m_placeHolderBox) {
+ m_placeHolderBox->detach( arena ? arena : renderArena() );
+ m_placeHolderBox = 0;
+ }
+}
+
+short RenderBox::contentWidth() const
+{
+ short w = m_width - style()->borderLeftWidth() - style()->borderRightWidth();
+ w -= paddingLeft() + paddingRight();
+
+ if (m_layer && scrollsOverflowY())
+ w -= m_layer->verticalScrollbarWidth();
+
+ //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl;
+ return w;
+}
+
+int RenderBox::contentHeight() const
+{
+ int h = m_height - style()->borderTopWidth() - style()->borderBottomWidth();
+ h -= paddingTop() + paddingBottom();
+
+ if (m_layer && scrollsOverflowX())
+ h -= m_layer->horizontalScrollbarHeight();
+
+ return h;
+}
+
+void RenderBox::setPos( int xPos, int yPos )
+{
+ m_x = xPos; m_y = yPos;
+}
+
+short RenderBox::width() const
+{
+ return m_width;
+}
+
+int RenderBox::height() const
+{
+ return m_height;
+}
+
+void RenderBox::setWidth( int width )
+{
+ m_width = width;
+}
+
+void RenderBox::setHeight( int height )
+{
+ m_height = height;
+}
+
+int RenderBox::calcBoxHeight(int h) const
+{
+ if (style()->boxSizing() == CONTENT_BOX)
+ h += borderTop() + borderBottom() + paddingTop() + paddingBottom();
+
+ return h;
+}
+
+int RenderBox::calcBoxWidth(int w) const
+{
+ if (style()->boxSizing() == CONTENT_BOX)
+ w += borderLeft() + borderRight() + paddingLeft() + paddingRight();
+
+ return w;
+}
+
+int RenderBox::calcContentHeight(int h) const
+{
+ if (style()->boxSizing() == BORDER_BOX)
+ h -= borderTop() + borderBottom() + paddingTop() + paddingBottom();
+
+ return kMax(0, h);
+}
+
+int RenderBox::calcContentWidth(int w) const
+{
+ if (style()->boxSizing() == BORDER_BOX)
+ w -= borderLeft() + borderRight() + paddingLeft() + paddingRight();
+
+ return kMax(0, w);
+}
+
+// --------------------- painting stuff -------------------------------
+
+void RenderBox::paint(PaintInfo& i, int _tx, int _ty)
+{
+ _tx += m_x;
+ _ty += m_y;
+
+ if (hasOverflowClip() && m_layer)
+ m_layer->subtractScrollOffset(_tx, _ty);
+
+ // default implementation. Just pass things through to the children
+ for(RenderObject* child = firstChild(); child; child = child->nextSibling())
+ child->paint(i, _tx, _ty);
+}
+
+void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ //kdDebug( 6040 ) << renderName() << "::paintRootBoxDecorations()" << _tx << "/" << _ty << endl;
+ const BackgroundLayer* bgLayer = style()->backgroundLayers();
+ TQColor bgColor = style()->backgroundColor();
+ if (document()->isHTMLDocument() && !style()->hasBackground()) {
+ // Locate the <body> element using the DOM. This is easier than trying
+ // to crawl around a render tree with potential :before/:after content and
+ // anonymous blocks created by inline <body> tags etc. We can locate the <body>
+ // render object very easily via the DOM.
+ HTMLElementImpl* body = document()->body();
+ RenderObject* bodyObject = (body && body->id() == ID_BODY) ? body->renderer() : 0;
+
+ if (bodyObject) {
+ bgLayer = bodyObject->style()->backgroundLayers();
+ bgColor = bodyObject->style()->backgroundColor();
+ }
+ }
+
+ if( !bgColor.isValid() && canvas()->view())
+ bgColor = canvas()->view()->palette().active().color(TQColorGroup::Base);
+
+ int w = width();
+ int h = height();
+
+ // kdDebug(0) << "width = " << w <<endl;
+
+ int rw, rh;
+ if (canvas()->view()) {
+ rw = canvas()->view()->contentsWidth();
+ rh = canvas()->view()->contentsHeight();
+ } else {
+ rw = canvas()->docWidth();
+ rh = canvas()->docHeight();
+ }
+
+ // kdDebug(0) << "rw = " << rw <<endl;
+
+ int bx = _tx - marginLeft();
+ int by = _ty - marginTop();
+ int bw = QMAX(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw);
+ int bh = QMAX(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh);
+
+ // CSS2 14.2:
+ // " The background of the box generated by the root element covers the entire canvas."
+ // hence, paint the background even in the margin areas (unlike for every other element!)
+ // I just love these little inconsistencies .. :-( (Dirk)
+ int my = kMax(by, paintInfo.r.y());
+
+ paintBackgrounds(paintInfo.p, bgColor, bgLayer, my, paintInfo.r.height(), bx, by, bw, bh);
+
+ if(style()->hasBorder())
+ paintBorder( paintInfo.p, _tx, _ty, w, h, style() );
+}
+
+void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
+
+ if(isRoot())
+ return paintRootBoxDecorations(paintInfo, _tx, _ty);
+
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ _ty -= borderTopExtra();
+
+ int my = kMax(_ty,paintInfo.r.y());
+ int end = kMin( paintInfo.r.y() + paintInfo.r.height(), _ty + h );
+ int mh = end - my;
+
+ // The <body> only paints its background if the root element has defined a background
+ // independent of the body. Go through the DOM to get to the root element's render object,
+ // since the root could be inline and wrapped in an anonymous block.
+
+ if (!isBody() || !document()->isHTMLDocument() || document()->documentElement()->renderer()->style()->hasBackground())
+ paintBackgrounds(paintInfo.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
+
+ if(style()->hasBorder()) {
+ paintBorder(paintInfo.p, _tx, _ty, w, h, style());
+ }
+}
+
+void RenderBox::paintBackgrounds(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int height)
+ {
+ if (!bgLayer) return;
+ paintBackgrounds(p, c, bgLayer->next(), clipy, cliph, _tx, _ty, w, height);
+ paintBackground(p, c, bgLayer, clipy, cliph, _tx, _ty, w, height);
+}
+
+void RenderBox::paintBackground(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int height)
+{
+ paintBackgroundExtended(p, c, bgLayer, clipy, cliph, _tx, _ty, w, height,
+ borderLeft(), borderRight(), paddingLeft(), paddingRight());
+}
+
+static void calculateBackgroundSize(const BackgroundLayer* bgLayer, int& scaledWidth, int& scaledHeight)
+{
+ CachedImage* bg = bgLayer->backgroundImage();
+
+ if (bgLayer->isBackgroundSizeSet()) {
+ Length bgWidth = bgLayer->backgroundSize().width;
+ Length bgHeight = bgLayer->backgroundSize().height;
+
+ if (bgWidth.isPercent())
+ scaledWidth = scaledWidth * bgWidth.value() / 100;
+ else if (bgWidth.isFixed())
+ scaledWidth = bgWidth.value();
+ else if (bgWidth.isVariable()) {
+ // If the width is auto and the height is not, we have to use the appropriate
+ // scale to maintain our aspect ratio.
+ if (bgHeight.isPercent()) {
+ int scaledH = scaledHeight * bgHeight.value() / 100;
+ scaledWidth = bg->pixmap_size().width() * scaledH / bg->pixmap_size().height();
+ } else if (bgHeight.isFixed())
+ scaledWidth = bg->pixmap_size().width() * bgHeight.value() / bg->pixmap_size().height();
+ }
+
+ if (bgHeight.isPercent())
+ scaledHeight = scaledHeight * bgHeight.value() / 100;
+ else if (bgHeight.isFixed())
+ scaledHeight = bgHeight.value();
+ else if (bgHeight.isVariable()) {
+ // If the height is auto and the width is not, we have to use the appropriate
+ // scale to maintain our aspect ratio.
+ if (bgWidth.isPercent())
+ scaledHeight = bg->pixmap_size().height() * scaledWidth / bg->pixmap_size().width();
+ else if (bgWidth.isFixed())
+ scaledHeight = bg->pixmap_size().height() * bgWidth.value() / bg->pixmap_size().width();
+ else if (bgWidth.isVariable()) {
+ // If both width and height are auto, we just want to use the image's
+ // intrinsic size.
+ scaledWidth = bg->pixmap_size().width();
+ scaledHeight = bg->pixmap_size().height();
+ }
+ }
+ } else {
+ scaledWidth = bg->pixmap_size().width();
+ scaledHeight = bg->pixmap_size().height();
+ }
+}
+
+void RenderBox::paintBackgroundExtended(TQPainter *p, const TQColor &c, const BackgroundLayer* bgLayer, int clipy, int cliph,
+ int _tx, int _ty, int w, int h,
+ int bleft, int bright, int pleft, int pright)
+{
+ if ( cliph < 0 )
+ return;
+
+ if (bgLayer->backgroundClip() != BGBORDER) {
+ // Clip to the padding or content boxes as necessary.
+ bool includePadding = bgLayer->backgroundClip() == BGCONTENT;
+ int x = _tx + bleft + (includePadding ? pleft : 0);
+ int y = _ty + borderTop() + (includePadding ? paddingTop() : 0);
+ int width = w - bleft - bright - (includePadding ? pleft + pright : 0);
+ int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0);
+ p->save();
+ p->setClipRect(TQRect(x, y, width, height), TQPainter::CoordPainter);
+ }
+
+ CachedImage* bg = bgLayer->backgroundImage();
+ bool shouldPaintBackgroundImage = bg && bg->pixmap_size() == bg->valid_rect().size() && !bg->isTransparent() && !bg->isErrorImage();
+ TQColor bgColor = c;
+
+ // Paint the color first underneath all images.
+ if (!bgLayer->next() && bgColor.isValid() && tqAlpha(bgColor.rgb()) > 0)
+ p->fillRect(_tx, clipy, w, cliph, bgColor);
+
+ // no progressive loading of the background image
+ if (shouldPaintBackgroundImage) {
+ int sx = 0;
+ int sy = 0;
+ int cw,ch;
+ int cx,cy;
+ int scaledImageWidth, scaledImageHeight;
+
+ // CSS2 chapter 14.2.1
+
+ if (bgLayer->backgroundAttachment()) {
+ //scroll
+ int hpab = 0, vpab = 0, left = 0, top = 0; // Init to 0 for background-origin of 'border'
+ if (bgLayer->backgroundOrigin() != BGBORDER) {
+ hpab += bleft + bright;
+ vpab += borderTop() + borderBottom();
+ left += bleft;
+ top += borderTop();
+ if (bgLayer->backgroundOrigin() == BGCONTENT) {
+ hpab += pleft + pright;
+ vpab += paddingTop() + paddingBottom();
+ left += pleft;
+ top += paddingTop();
+ }
+ }
+
+ int pw = w - hpab;
+ int ph = h - vpab;
+ scaledImageWidth = pw;
+ scaledImageHeight = ph;
+ calculateBackgroundSize(bgLayer, scaledImageWidth, scaledImageHeight);
+
+ EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
+ if (bgr == NO_REPEAT || bgr == REPEAT_Y) {
+ cw = scaledImageWidth;
+ int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
+ if ( xPosition >= 0 ) {
+ cx = _tx + xPosition;
+ cw = kMin(scaledImageWidth, pw - xPosition);
+ }
+ else {
+ cx = _tx;
+ if (scaledImageWidth > 0) {
+ sx = -xPosition;
+ cw = kMin(scaledImageWidth+xPosition, pw);
+ }
+ }
+ cx += left;
+ } else {
+ // repeat over x
+ cw = w;
+ cx = _tx;
+ if (scaledImageWidth > 0) {
+ int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
+ sx = scaledImageWidth - (xPosition % scaledImageWidth);
+ sx -= left % scaledImageWidth;
+ }
+ }
+ if (bgr == NO_REPEAT || bgr == REPEAT_X) {
+ ch = scaledImageHeight;
+ int yPosition = bgLayer->backgroundYPosition().minWidth(ph - scaledImageHeight);
+ if ( yPosition >= 0 ) {
+ cy = _ty + yPosition;
+ ch = kMin(ch, ph - yPosition);
+ }
+ else {
+ cy = _ty;
+ if (scaledImageHeight > 0) {
+ sy = -yPosition;
+ ch = kMin(scaledImageHeight+yPosition, ph);
+ }
+ }
+
+ cy += top;
+ } else {
+ // repeat over y
+ ch = h;
+ cy = _ty;
+ if (scaledImageHeight > 0) {
+ int yPosition = bgLayer->backgroundYPosition().minWidth(ph - scaledImageHeight);
+ sy = scaledImageHeight - (yPosition % scaledImageHeight);
+ sy -= top % scaledImageHeight;
+ }
+ }
+ if (layer())
+ layer()->scrollOffset(sx, sy);
+ }
+ else
+ {
+ //fixed
+ TQRect vr = viewRect();
+ int pw = vr.width();
+ int ph = vr.height();
+ scaledImageWidth = pw;
+ scaledImageHeight = ph;
+ calculateBackgroundSize(bgLayer, scaledImageWidth, scaledImageHeight);
+ EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
+
+ int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
+ if (bgr == NO_REPEAT || bgr == REPEAT_Y) {
+ cw = kMin(scaledImageWidth, pw - xPosition);
+ cx = vr.x() + xPosition;
+ } else {
+ cw = pw;
+ cx = vr.x();
+ if (scaledImageWidth > 0)
+ sx = scaledImageWidth - xPosition % scaledImageWidth;
+ }
+
+ int yPosition = bgLayer->backgroundYPosition().minWidth(ph-scaledImageHeight);
+ if (bgr == NO_REPEAT || bgr == REPEAT_X) {
+ ch = kMin(scaledImageHeight, ph - yPosition);
+ cy = vr.y() + yPosition;
+ } else {
+ ch = ph;
+ cy = vr.y();
+ if (scaledImageHeight > 0)
+ sy = scaledImageHeight - yPosition % scaledImageHeight;
+ }
+
+ TQRect fix(cx, cy, cw, ch);
+ TQRect ele(_tx, _ty, w, h);
+ TQRect b = fix.intersect(ele);
+
+ //kdDebug() <<" ele is " << ele << " b is " << b << " fix is " << fix << endl;
+ sx+=b.x()-cx;
+ sy+=b.y()-cy;
+ cx=b.x();cy=b.y();cw=b.width();ch=b.height();
+ }
+ // restrict painting to repaint-clip
+ if (cy < clipy) {
+ ch -= (clipy - cy);
+ sy += (clipy - cy);
+ cy = clipy;
+ }
+ ch = kMin(ch, cliph);
+
+// kdDebug() << " clipy, cliph: " << clipy << ", " << cliph << endl;
+// kdDebug() << " drawTiledPixmap(" << cx << ", " << cy << ", " << cw << ", " << ch << ", " << sx << ", " << sy << ")" << endl;
+ if (cw>0 && ch>0)
+ p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c, scaledImageWidth, scaledImageHeight), sx, sy);
+
+ }
+
+ if (bgLayer->backgroundClip() != BGBORDER)
+ p->restore(); // Undo the background clip
+
+}
+
+void RenderBox::outlineBox(TQPainter *p, int _tx, int _ty, const char *color)
+{
+ p->setPen(TQPen(TQColor(color), 1, Qt::DotLine));
+ p->setBrush( Qt::NoBrush );
+ p->drawRect(_tx, _ty, m_width, m_height);
+}
+
+TQRect RenderBox::getOverflowClipRect(int tx, int ty)
+{
+ // XXX When overflow-clip (CSS3) is implemented, we'll obtain the property
+ // here.
+ int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight();
+ int clipx = tx+bl;
+ int clipy = ty+bt;
+ int clipw = m_width-bl-br;
+ int cliph = m_height-bt-bb+borderTopExtra()+borderBottomExtra();
+
+ // Substract out scrollbars if we have them.
+ if (m_layer) {
+ clipw -= m_layer->verticalScrollbarWidth();
+ cliph -= m_layer->horizontalScrollbarHeight();
+ }
+
+ return TQRect(clipx,clipy,clipw,cliph);
+}
+
+TQRect RenderBox::getClipRect(int tx, int ty)
+{
+ int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight();
+ // ### what about paddings?
+ int clipw = m_width-bl-br;
+ int cliph = m_height-bt-bb;
+
+ bool rtl = (style()->direction() == RTL);
+
+ int clipleft = 0;
+ int clipright = clipw;
+ int cliptop = 0;
+ int clipbottom = cliph;
+
+ if ( style()->hasClip() && style()->position() == ABSOLUTE ) {
+ // the only case we use the clip property according to CSS 2.1
+ if (!style()->clipLeft().isVariable()) {
+ int c = style()->clipLeft().width(clipw);
+ if ( rtl )
+ clipleft = clipw - c;
+ else
+ clipleft = c;
+ }
+ if (!style()->clipRight().isVariable()) {
+ int w = style()->clipRight().width(clipw);
+ if ( rtl ) {
+ clipright = clipw - w;
+ } else {
+ clipright = w;
+ }
+ }
+ if (!style()->clipTop().isVariable())
+ cliptop = style()->clipTop().width(cliph);
+ if (!style()->clipBottom().isVariable())
+ clipbottom = style()->clipBottom().width(cliph);
+ }
+ int clipx = tx + clipleft;
+ int clipy = ty + cliptop;
+ clipw = clipright-clipleft;
+ cliph = clipbottom-cliptop;
+
+ //kdDebug( 6040 ) << "setting clip("<<clipx<<","<<clipy<<","<<clipw<<","<<cliph<<")"<<endl;
+
+ return TQRect(clipx,clipy,clipw,cliph);
+}
+
+void RenderBox::close()
+{
+ setNeedsLayoutAndMinMaxRecalc();
+}
+
+short RenderBox::containingBlockWidth() const
+{
+ if (isCanvas() && canvas()->view())
+ {
+ if (canvas()->pagedMode())
+ return canvas()->width();
+ else
+ return canvas()->view()->visibleWidth();
+ }
+
+ RenderBlock* cb = containingBlock();
+ if (isRenderBlock() && cb->isTable() && static_cast<RenderTable*>(cb)->caption() == this) {
+ //captions are not affected by table border or padding
+ return cb->width();
+ }
+ if (usesLineWidth())
+ return cb->lineWidth(m_y);
+ else
+ return cb->contentWidth();
+}
+
+bool RenderBox::absolutePosition(int &_xPos, int &_yPos, bool f) const
+{
+ if ( style()->position() == FIXED )
+ f = true;
+ RenderObject *o = container();
+ if( o && o->absolutePosition(_xPos, _yPos, f))
+ {
+ if ( o->layer() ) {
+ if (o->hasOverflowClip())
+ o->layer()->subtractScrollOffset( _xPos, _yPos );
+ if (isPositioned())
+ o->layer()->checkInlineRelOffset(this, _xPos, _yPos);
+ }
+
+ if(!isInline() || isReplaced()) {
+ _xPos += xPos(),
+ _yPos += yPos();
+ }
+
+ if(isRelPositioned())
+ relativePositionOffset(_xPos, _yPos);
+ return true;
+ }
+ else
+ {
+ _xPos = 0;
+ _yPos = 0;
+ return false;
+ }
+}
+
+void RenderBox::position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/)
+{
+ if (isPositioned()) {
+ // Cache the x position only if we were an INLINE type originally.
+ bool wasInline = style()->isOriginalDisplayInlineType();
+
+ if (wasInline && hasStaticX()) {
+ // The value is cached in the xPos of the box. We only need this value if
+ // our object was inline originally, since otherwise it would have ended up underneath
+ // the inlines.
+ m_staticX = box->xPos();
+ }
+ else if (!wasInline && hasStaticY()) {
+ // Our object was a block originally, so we make our normal flow position be
+ // just below the line box (as though all the inlines that came before us got
+ // wrapped in an anonymous block, which is what would have happened had we been
+ // in flow). This value was cached in the yPos() of the box.
+ m_staticY = box->yPos();
+ }
+ }
+ else if (isReplaced())
+ setPos( box->xPos(), box->yPos() );
+}
+
+void RenderBox::repaint(Priority prior)
+{
+ int ow = style() ? style()->outlineSize() : 0;
+ if( isInline() && !isReplaced() )
+ {
+ RenderObject* p = parent();
+ Q_ASSERT(p);
+ while( p->isInline() && !p->isReplaced() )
+ p = p->parent();
+ int xoff = p->hasOverflowClip() ? 0 : p->overflowLeft();
+ int yoff = p->hasOverflowClip() ? 0 : p->overflowTop();
+ p->repaintRectangle( -ow + xoff, -ow + yoff, p->effectiveWidth()+ow*2, p->effectiveHeight()+ow*2, prior);
+ }
+ else
+ {
+ int xoff = hasOverflowClip() ? 0 : overflowLeft();
+ int yoff = hasOverflowClip() ? 0 : overflowTop();
+ repaintRectangle( -ow + xoff, -ow + yoff, effectiveWidth()+ow*2, effectiveHeight()+ow*2, prior);
+ }
+}
+
+void RenderBox::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
+{
+ x += m_x;
+ y += m_y;
+
+ // Apply the relative position offset when invalidating a rectangle. The layer
+ // is translated, but the render box isn't, so we need to do this to get the
+ // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
+ // flag on the RenderObject has been cleared, so use the one on the style().
+ if (style()->position() == RELATIVE && m_layer)
+ relativePositionOffset(x,y);
+
+ if (style()->position() == FIXED) f=true;
+
+ // kdDebug( 6040 ) << "RenderBox(" <<this << ", " << renderName() << ")::repaintRectangle (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl;
+ RenderObject *o = container();
+ if( o ) {
+ if (o->layer()) {
+ if (o->style()->hidesOverflow() && o->layer() && !o->isInlineFlow())
+ o->layer()->subtractScrollOffset(x,y); // For overflow:auto/scroll/hidden.
+ if (style()->position() == ABSOLUTE)
+ o->layer()->checkInlineRelOffset(this,x,y);
+ }
+ o->repaintRectangle(x, y, w, h, p, f);
+ }
+}
+
+void RenderBox::relativePositionOffset(int &tx, int &ty) const
+{
+ if(!style()->left().isVariable())
+ tx += style()->left().width(containingBlockWidth());
+ else if(!style()->right().isVariable())
+ tx -= style()->right().width(containingBlockWidth());
+ if(!style()->top().isVariable())
+ {
+ if (!style()->top().isPercent()
+ || containingBlock()->style()->height().isFixed())
+ ty += style()->top().width(containingBlockHeight());
+ }
+ else if(!style()->bottom().isVariable())
+ {
+ if (!style()->bottom().isPercent()
+ || containingBlock()->style()->height().isFixed())
+ ty -= style()->bottom().width(containingBlockHeight());
+ }
+}
+
+void RenderBox::calcWidth()
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "RenderBox("<<renderName()<<")::calcWidth()" << endl;
+#endif
+ if (isPositioned())
+ {
+ calcAbsoluteHorizontal();
+ }
+ else
+ {
+ bool treatAsReplaced = isReplaced() && !isInlineBlockOrInlineTable();
+ Length w;
+ if (treatAsReplaced)
+ w = Length( calcReplacedWidth(), Fixed );
+ else
+ w = style()->width();
+
+ Length ml = style()->marginLeft();
+ Length mr = style()->marginRight();
+
+ int cw = containingBlockWidth();
+ if (cw<0) cw = 0;
+
+ m_marginLeft = 0;
+ m_marginRight = 0;
+
+ if (isInline() && !isInlineBlockOrInlineTable())
+ {
+ // just calculate margins
+ m_marginLeft = ml.minWidth(cw);
+ m_marginRight = mr.minWidth(cw);
+ if (treatAsReplaced)
+ {
+ m_width = calcBoxWidth(w.width(cw));
+ m_width = KMAX(m_width, m_minWidth);
+ }
+
+ return;
+ }
+ else
+ {
+ LengthType widthType, minWidthType, maxWidthType;
+ if (treatAsReplaced) {
+ m_width = calcBoxWidth(w.width(cw));
+ widthType = w.type();
+ } else {
+ m_width = calcWidthUsing(Width, cw, widthType);
+ int minW = calcWidthUsing(MinWidth, cw, minWidthType);
+ int maxW = style()->maxWidth().value() == UNDEFINED ?
+ m_width : calcWidthUsing(MaxWidth, cw, maxWidthType);
+
+ if (m_width > maxW) {
+ m_width = maxW;
+ widthType = maxWidthType;
+ }
+ if (m_width < minW) {
+ m_width = minW;
+ widthType = minWidthType;
+ }
+ }
+
+ if (widthType == Variable) {
+ // kdDebug( 6040 ) << "variable" << endl;
+ m_marginLeft = ml.minWidth(cw);
+ m_marginRight = mr.minWidth(cw);
+ }
+ else
+ {
+// kdDebug( 6040 ) << "non-variable " << w.type << ","<< w.value << endl;
+ calcHorizontalMargins(ml,mr,cw);
+ }
+ }
+
+ if (cw && cw != m_width + m_marginLeft + m_marginRight && !isFloating() && !isInline())
+ {
+ if (containingBlock()->style()->direction()==LTR)
+ m_marginRight = cw - m_width - m_marginLeft;
+ else
+ m_marginLeft = cw - m_width - m_marginRight;
+ }
+ }
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "RenderBox::calcWidth(): m_width=" << m_width << " containingBlockWidth()=" << containingBlockWidth() << endl;
+ kdDebug( 6040 ) << "m_marginLeft=" << m_marginLeft << " m_marginRight=" << m_marginRight << endl;
+#endif
+}
+
+int RenderBox::calcWidthUsing(WidthType widthType, int cw, LengthType& lengthType)
+{
+ int width = m_width;
+ Length w;
+ if (widthType == Width)
+ w = style()->width();
+ else if (widthType == MinWidth)
+ w = style()->minWidth();
+ else
+ w = style()->maxWidth();
+
+ lengthType = w.type();
+
+ if (lengthType == Variable) {
+ int marginLeft = style()->marginLeft().minWidth(cw);
+ int marginRight = style()->marginRight().minWidth(cw);
+ if (cw) width = cw - marginLeft - marginRight;
+
+ // size to max width?
+ if (sizesToMaxWidth()) {
+ width = KMAX(width, (int)m_minWidth);
+ width = KMIN(width, (int)m_maxWidth);
+ }
+ }
+ else
+ {
+ width = calcBoxWidth(w.width(cw));
+ }
+
+ return width;
+}
+
+void RenderBox::calcHorizontalMargins(const Length& ml, const Length& mr, int cw)
+{
+ if (isFloating() || isInline()) // Inline blocks/tables and floats don't have their margins increased.
+ {
+ m_marginLeft = ml.minWidth(cw);
+ m_marginRight = mr.minWidth(cw);
+ }
+ else
+ {
+ if ( (ml.isVariable() && mr.isVariable() && m_width<cw) ||
+ (!ml.isVariable() && !mr.isVariable() &&
+ containingBlock()->style()->textAlign() == KHTML_CENTER) )
+ {
+ m_marginLeft = (cw - m_width)/2;
+ if (m_marginLeft<0) m_marginLeft=0;
+ m_marginRight = cw - m_width - m_marginLeft;
+ }
+ else if ( (mr.isVariable() && m_width<cw) ||
+ (!ml.isVariable() && containingBlock()->style()->direction() == RTL &&
+ containingBlock()->style()->textAlign() == KHTML_LEFT))
+ {
+ m_marginLeft = ml.width(cw);
+ m_marginRight = cw - m_width - m_marginLeft;
+ }
+ else if ( (ml.isVariable() && m_width<cw) ||
+ (!mr.isVariable() && containingBlock()->style()->direction() == LTR &&
+ containingBlock()->style()->textAlign() == KHTML_RIGHT))
+ {
+ m_marginRight = mr.width(cw);
+ m_marginLeft = cw - m_width - m_marginRight;
+ }
+ else
+ {
+ // this makes auto margins 0 if we failed a m_width<cw test above (css2.1, 10.3.3)
+ m_marginLeft = ml.minWidth(cw);
+ m_marginRight = mr.minWidth(cw);
+ }
+ }
+}
+
+void RenderBox::calcHeight()
+{
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "RenderBox::calcHeight()" << endl;
+#endif
+
+ //cell height is managed by table, inline elements do not have a height property.
+ if ( isTableCell() || (isInline() && !isReplaced()) )
+ return;
+
+ if (isPositioned())
+ calcAbsoluteVertical();
+ else
+ {
+ calcVerticalMargins();
+
+ // For tables, calculate margins only
+ if (isTable())
+ return;
+
+ Length h;
+ bool treatAsReplaced = isReplaced() && !isInlineBlockOrInlineTable();
+ bool checkMinMaxHeight = false;
+
+ if ( treatAsReplaced )
+ h = Length( calcReplacedHeight(), Fixed );
+ else {
+ h = style()->height();
+ checkMinMaxHeight = true;
+ }
+
+ int height;
+ if (checkMinMaxHeight) {
+ height = calcHeightUsing(style()->height());
+ if (height == -1)
+ height = m_height;
+ int minH = calcHeightUsing(style()->minHeight()); // Leave as -1 if unset.
+ int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcHeightUsing(style()->maxHeight());
+ if (maxH == -1)
+ maxH = height;
+ height = kMin(maxH, height);
+ height = kMax(minH, height);
+ }
+ else {
+ // The only times we don't check min/max height are when a fixed length has
+ // been given as an override. Just use that.
+ height = calcBoxHeight(h.value());
+ }
+
+ if (height<m_height && !overhangingContents() && !hasOverflowClip())
+ setOverhangingContents();
+
+ m_height = height;
+ }
+
+ // Unfurling marquees override with the furled height.
+ if (style()->overflowX() == OMARQUEE && m_layer && m_layer->marquee() &&
+ m_layer->marquee()->isUnfurlMarquee() && !m_layer->marquee()->isHorizontal()) {
+ m_layer->marquee()->setEnd(m_height);
+ m_height = kMin(m_height, m_layer->marquee()->unfurlPos());
+ }
+
+}
+
+int RenderBox::calcHeightUsing(const Length& h)
+{
+ int height = -1;
+ if (!h.isVariable()) {
+ if (h.isFixed())
+ height = h.value();
+ else if (h.isPercent())
+ height = calcPercentageHeight(h);
+ if (height != -1) {
+ height = calcBoxHeight(height);
+ return height;
+ }
+ }
+ return height;
+}
+
+int RenderBox::calcImplicitHeight() const {
+ assert(hasImplicitHeight());
+
+ RenderBlock* cb = containingBlock();
+ // padding-box height
+ int ch = cb->height() - cb->borderTop() + cb->borderBottom();
+ int top = style()->top().width(ch);
+ int bottom = style()->bottom().width(ch);
+
+ return ch - top - bottom;
+}
+
+int RenderBox::calcPercentageHeight(const Length& height, bool treatAsReplaced) const
+{
+ int result = -1;
+ RenderBlock* cb = containingBlock();
+ // In quirk mode, table cells violate what the CSS spec says to do with heights.
+ if (cb->isTableCell() && style()->htmlHacks()) {
+ result = static_cast<RenderTableCell*>(cb)->cellPercentageHeight();
+ }
+
+ // Otherwise we only use our percentage height if our containing block had a specified
+ // height.
+ else if (cb->style()->height().isFixed())
+ result = cb->calcContentHeight(cb->style()->height().value());
+ else if (cb->style()->height().isPercent()) {
+ // We need to recur and compute the percentage height for our containing block.
+ result = cb->calcPercentageHeight(cb->style()->height(), treatAsReplaced);
+ if (result != -1)
+ result = cb->calcContentHeight(result);
+ }
+ else if (cb->isCanvas()) {
+ if (!canvas()->pagedMode())
+ result = static_cast<RenderCanvas*>(cb)->viewportHeight();
+ else
+ result = static_cast<RenderCanvas*>(cb)->height();
+ result -= cb->style()->borderTopWidth() - cb->style()->borderBottomWidth();
+ result -= cb->paddingTop() + cb->paddingBottom();
+ }
+ else if (cb->isBody() && style()->htmlHacks() &&
+ cb->style()->height().isVariable() && !cb->isFloatingOrPositioned()) {
+ int margins = cb->collapsedMarginTop() + cb->collapsedMarginBottom();
+ int visHeight = canvas()->viewportHeight();
+ RenderObject* p = cb->parent();
+ result = visHeight - (margins + p->marginTop() + p->marginBottom() +
+ p->borderTop() + p->borderBottom() +
+ p->paddingTop() + p->paddingBottom());
+ }
+ else if (cb->isRoot() && style()->htmlHacks() && cb->style()->height().isVariable()) {
+ int visHeight = canvas()->viewportHeight();
+ result = visHeight - (marginTop() + marginBottom() +
+ borderTop() + borderBottom() +
+ paddingTop() + paddingBottom());
+ }
+ else if (cb->isAnonymousBlock() || treatAsReplaced && style()->htmlHacks()) {
+ // IE quirk.
+ result = cb->calcPercentageHeight(cb->style()->height(), treatAsReplaced);
+ }
+ else if (cb->hasImplicitHeight()) {
+ result = cb->calcImplicitHeight();
+ }
+
+ if (result != -1) {
+ result = height.width(result);
+ if (cb->isTableCell() && style()->boxSizing() != BORDER_BOX) {
+ result -= (borderTop() + paddingTop() + borderBottom() + paddingBottom());
+ result = kMax(0, result);
+ }
+ }
+ return result;
+}
+
+short RenderBox::calcReplacedWidth() const
+{
+ int width = calcReplacedWidthUsing(Width);
+ int minW = calcReplacedWidthUsing(MinWidth);
+ int maxW = style()->maxWidth().value() == UNDEFINED ? width : calcReplacedWidthUsing(MaxWidth);
+
+ if (width > maxW)
+ width = maxW;
+
+ if (width < minW)
+ width = minW;
+
+ return width;
+}
+
+int RenderBox::calcReplacedWidthUsing(WidthType widthType) const
+{
+ Length w;
+ if (widthType == Width)
+ w = style()->width();
+ else if (widthType == MinWidth)
+ w = style()->minWidth();
+ else
+ w = style()->maxWidth();
+
+ switch (w.type()) {
+ case Fixed:
+ return w.value();
+ case Percent:
+ {
+ const int cw = containingBlockWidth();
+ if (cw > 0) {
+ int result = w.minWidth(cw);
+ return result;
+ }
+ }
+ // fall through
+ default:
+ return intrinsicWidth();
+ }
+}
+
+int RenderBox::calcReplacedHeight() const
+{
+ int height = calcReplacedHeightUsing(Height);
+ int minH = calcReplacedHeightUsing(MinHeight);
+ int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcReplacedHeightUsing(MaxHeight);
+
+ if (height > maxH)
+ height = maxH;
+
+ if (height < minH)
+ height = minH;
+
+ return height;
+}
+
+int RenderBox::calcReplacedHeightUsing(HeightType heightType) const
+{
+ Length h;
+ if (heightType == Height)
+ h = style()->height();
+ else if (heightType == MinHeight)
+ h = style()->minHeight();
+ else
+ h = style()->maxHeight();
+ switch( h.type() ) {
+ case Fixed:
+ return h.value();
+ case Percent:
+ {
+ int th = calcPercentageHeight(h, true);
+ if (th != -1)
+ return th;
+ // fall through
+ }
+ default:
+ return intrinsicHeight();
+ };
+}
+
+int RenderBox::availableHeight() const
+{
+ return availableHeightUsing(style()->height());
+}
+
+int RenderBox::availableHeightUsing(const Length& h) const
+{
+ if (h.isFixed())
+ return calcContentHeight(h.value());
+
+ if (isCanvas())
+ if (static_cast<const RenderCanvas*>(this)->pagedMode())
+ return static_cast<const RenderCanvas*>(this)->pageHeight();
+ else
+ return static_cast<const RenderCanvas*>(this)->viewportHeight();
+
+ // We need to stop here, since we don't want to increase the height of the table
+ // artificially. We're going to rely on this cell getting expanded to some new
+ // height, and then when we lay out again we'll use the calculation below.
+ if (isTableCell() && (h.isVariable() || h.isPercent())) {
+ const RenderTableCell* tableCell = static_cast<const RenderTableCell*>(this);
+ return tableCell->cellPercentageHeight() -
+ (borderTop()+borderBottom()+paddingTop()+paddingBottom());
+ }
+
+ if (h.isPercent())
+ return calcContentHeight(h.width(containingBlock()->availableHeight()));
+
+ // Check for implicit height
+ if (hasImplicitHeight())
+ return calcImplicitHeight();
+
+ return containingBlock()->availableHeight();
+}
+
+int RenderBox::availableWidth() const
+{
+ return availableWidthUsing(style()->width());
+}
+
+int RenderBox::availableWidthUsing(const Length& w) const
+{
+ if (w.isFixed())
+ return calcContentWidth(w.value());
+
+ if (isCanvas())
+ return static_cast<const RenderCanvas*>(this)->viewportWidth();
+
+ if (w.isPercent())
+ return calcContentWidth(w.width(containingBlock()->availableWidth()));
+
+ return containingBlock()->availableWidth();
+}
+
+void RenderBox::calcVerticalMargins()
+{
+ if( isTableCell() ) {
+ // table margins are basically infinite
+ m_marginTop = TABLECELLMARGIN;
+ m_marginBottom = TABLECELLMARGIN;
+ return;
+ }
+
+ Length tm = style()->marginTop();
+ Length bm = style()->marginBottom();
+
+ // margins are calculated with respect to the _width_ of
+ // the containing block (8.3)
+ int cw = containingBlock()->contentWidth();
+
+ m_marginTop = tm.minWidth(cw);
+ m_marginBottom = bm.minWidth(cw);
+}
+
+void RenderBox::setStaticX(short staticX)
+{
+ m_staticX = staticX;
+}
+
+void RenderBox::setStaticY(int staticY)
+{
+ m_staticY = staticY;
+}
+
+void RenderBox::calcAbsoluteHorizontal()
+{
+ if (isReplaced()) {
+ calcAbsoluteHorizontalReplaced();
+ return;
+ }
+
+ // QUESTIONS
+ // FIXME 1: Which RenderObject's 'direction' property should used: the
+ // containing block (cb) as the spec seems to imply, the parent (parent()) as
+ // was previously done in calculating the static distances, or ourself, which
+ // was also previously done for deciding what to override when you had
+ // over-constrained margins? Also note that the container block is used
+ // in similar situations in other parts of the RenderBox class (see calcWidth()
+ // and calcHorizontalMargins()). For now we are using the parent for quirks
+ // mode and the containing block for strict mode.
+
+ // FIXME 2: Can perhaps optimize out cases when max-width/min-width are greater
+ // than or less than the computed m_width. Be careful of box-sizing and
+ // percentage issues.
+
+ // The following is based off of the W3C Working Draft from April 11, 2006 of
+ // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
+ // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
+ // (block-style-comments in this function and in calcAbsoluteHorizontalValues()
+ // correspond to text from the spec)
+
+
+ // We don't use containingBlock(), since we may be positioned by an enclosing
+ // relative positioned inline.
+ const RenderObject* containerBlock = container();
+
+ // FIXME: This is incorrect for cases where the container block is a relatively
+ // positioned inline.
+ const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
+
+ // To match WinIE, in quirks mode use the parent's 'direction' property
+ // instead of the the container block's.
+ EDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
+
+ const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+ const Length marginLeft = style()->marginLeft();
+ const Length marginRight = style()->marginRight();
+ Length left = style()->left();
+ Length right = style()->right();
+
+ /*---------------------------------------------------------------------------*\
+ * For the purposes of this section and the next, the term "static position"
+ * (of an element) refers, roughly, to the position an element would have had
+ * in the normal flow. More precisely:
+ *
+ * * The static position for 'left' is the distance from the left edge of the
+ * containing block to the left margin edge of a hypothetical box that would
+ * have been the first box of the element if its 'position' property had
+ * been 'static' and 'float' had been 'none'. The value is negative if the
+ * hypothetical box is to the left of the containing block.
+ * * The static position for 'right' is the distance from the right edge of the
+ * containing block to the right margin edge of the same hypothetical box as
+ * above. The value is positive if the hypothetical box is to the left of the
+ * containing block's edge.
+ *
+ * But rather than actually calculating the dimensions of that hypothetical box,
+ * user agents are free to make a guess at its probable position.
+ *
+ * For the purposes of calculating the static position, the containing block of
+ * fixed positioned elements is the initial containing block instead of the
+ * viewport, and all scrollable boxes should be assumed to be scrolled to their
+ * origin.
+ \*---------------------------------------------------------------------------*/
+
+ // Calculate the static distance if needed.
+ if (left.isVariable() && right.isVariable()) {
+ if (containerDirection == LTR) {
+ // 'm_staticX' should already have been set through layout of the parent.
+ int staticPosition = m_staticX - containerBlock->borderLeft();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
+ staticPosition += po->xPos();
+ left = Length(staticPosition, Fixed);
+ } else {
+ RenderObject* po = parent();
+ // 'm_staticX' should already have been set through layout of the parent.
+ int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
+ for (; po && po != containerBlock; po = po->parent())
+ staticPosition -= po->xPos();
+ right = Length(staticPosition, Fixed);
+ }
+ }
+
+ // Calculate constraint equation values for 'width' case.
+ calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerDirection,
+ containerWidth, bordersPlusPadding,
+ left, right, marginLeft, marginRight,
+ m_width, m_marginLeft, m_marginRight, m_x);
+ // Calculate constraint equation values for 'max-width' case.calcContentWidth(width.width(containerWidth));
+ if (style()->maxWidth().value() != UNDEFINED) {
+ short maxWidth;
+ short maxMarginLeft;
+ short maxMarginRight;
+ short maxXPos;
+
+ calcAbsoluteHorizontalValues(style()->maxWidth(), containerBlock, containerDirection,
+ containerWidth, bordersPlusPadding,
+ left, right, marginLeft, marginRight,
+ maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
+
+ if (m_width > maxWidth) {
+ m_width = maxWidth;
+ m_marginLeft = maxMarginLeft;
+ m_marginRight = maxMarginRight;
+ m_x = maxXPos;
+ }
+ }
+
+ // Calculate constraint equation values for 'min-width' case.
+ if (style()->minWidth().value()) {
+ short minWidth;
+ short minMarginLeft;
+ short minMarginRight;
+ short minXPos;
+
+ calcAbsoluteHorizontalValues(style()->minWidth(), containerBlock, containerDirection,
+ containerWidth, bordersPlusPadding,
+ left, right, marginLeft, marginRight,
+ minWidth, minMarginLeft, minMarginRight, minXPos);
+
+ if (m_width < minWidth) {
+ m_width = minWidth;
+ m_marginLeft = minMarginLeft;
+ m_marginRight = minMarginRight;
+ m_x = minXPos;
+ }
+ }
+
+ // Put m_width into correct form.
+ m_width += bordersPlusPadding;
+}
+
+void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock, EDirection containerDirection,
+ const int containerWidth, const int bordersPlusPadding,
+ const Length left, const Length right, const Length marginLeft, const Length marginRight,
+ short& widthValue, short& marginLeftValue, short& marginRightValue, short& xPos)
+{
+ // 'left' and 'right' cannot both be 'auto' because one would of been
+ // converted to the static postion already
+ assert(!(left.isVariable() && right.isVariable()));
+
+ int leftValue = 0;
+
+ bool widthIsAuto = width.isVariable();
+ bool leftIsAuto = left.isVariable();
+ bool rightIsAuto = right.isVariable();
+
+ if (!leftIsAuto && !widthIsAuto && !rightIsAuto) {
+ /*-----------------------------------------------------------------------*\
+ * If none of the three is 'auto': If both 'margin-left' and 'margin-
+ * right' are 'auto', solve the equation under the extra constraint that
+ * the two margins get equal values, unless this would make them negative,
+ * in which case when direction of the containing block is 'ltr' ('rtl'),
+ * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
+ * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
+ * solve the equation for that value. If the values are over-constrained,
+ * ignore the value for 'left' (in case the 'direction' property of the
+ * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
+ * and solve for that value.
+ \*-----------------------------------------------------------------------*/
+ // NOTE: It is not necessary to solve for 'right' in the over constrained
+ // case because the value is not used for any further calculations.
+
+ leftValue = left.width(containerWidth);
+ widthValue = calcContentWidth(width.width(containerWidth));
+
+ const int availableSpace = containerWidth - (leftValue + widthValue + right.width(containerWidth) + bordersPlusPadding);
+
+ // Margins are now the only unknown
+ if (marginLeft.isVariable() && marginRight.isVariable()) {
+ // Both margins auto, solve for equality
+ if (availableSpace >= 0) {
+ marginLeftValue = availableSpace / 2; // split the diference
+ marginRightValue = availableSpace - marginLeftValue; // account for odd valued differences
+ } else {
+ // see FIXME 1
+ if (containerDirection == LTR) {
+ marginLeftValue = 0;
+ marginRightValue = availableSpace; // will be negative
+ } else {
+ marginLeftValue = availableSpace; // will be negative
+ marginRightValue = 0;
+ }
+ }
+ } else if (marginLeft.isVariable()) {
+ // Solve for left margin
+ marginRightValue = marginRight.width(containerWidth);
+ marginLeftValue = availableSpace - marginRightValue;
+ } else if (marginRight.isVariable()) {
+ // Solve for right margin
+ marginLeftValue = marginLeft.width(containerWidth);
+ marginRightValue = availableSpace - marginLeftValue;
+ } else {
+ // Over-constrained, solve for left if direction is RTL
+ marginLeftValue = marginLeft.width(containerWidth);
+ marginRightValue = marginRight.width(containerWidth);
+
+ // see FIXME 1 -- used to be "this->style()->direction()"
+ if (containerDirection == RTL)
+ leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue;
+ }
+ } else {
+ /*--------------------------------------------------------------------*\
+ * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
+ * to 0, and pick the one of the following six rules that applies.
+ *
+ * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
+ * width is shrink-to-fit. Then solve for 'left'
+ *
+ * OMIT RULE 2 AS IT SHOULD NEVER BE HIT
+ * ------------------------------------------------------------------
+ * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
+ * the 'direction' property of the containing block is 'ltr' set
+ * 'left' to the static position, otherwise set 'right' to the
+ * static position. Then solve for 'left' (if 'direction is 'rtl')
+ * or 'right' (if 'direction' is 'ltr').
+ * ------------------------------------------------------------------
+ *
+ * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
+ * width is shrink-to-fit . Then solve for 'right'
+ * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
+ * for 'left'
+ * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
+ * for 'width'
+ * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
+ * for 'right'
+ *
+ * Calculation of the shrink-to-fit width is similar to calculating the
+ * width of a table cell using the automatic table layout algorithm.
+ * Roughly: calculate the preferred width by formatting the content
+ * without breaking lines other than where explicit line breaks occur,
+ * and also calculate the preferred minimum width, e.g., by trying all
+ * possible line breaks. CSS 2.1 does not define the exact algorithm.
+ * Thirdly, calculate the available width: this is found by solving
+ * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
+ * to 0.
+ *
+ * Then the shrink-to-fit width is:
+ * kMin(kMax(preferred minimum width, available width), preferred width).
+ \*--------------------------------------------------------------------*/
+ // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
+ // because the value is not used for any further calculations.
+
+ // Calculate margins, 'auto' margins are ignored.
+ marginLeftValue = marginLeft.minWidth(containerWidth);
+ marginRightValue = marginRight.minWidth(containerWidth);
+
+ const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding);
+
+ // FIXME: Is there a faster way to find the correct case?
+ // Use rule/case that applies.
+ if (leftIsAuto && widthIsAuto && !rightIsAuto) {
+ // RULE 1: (use shrink-to-fit for width, and solve of left)
+ int rightValue = right.width(containerWidth);
+
+ // FIXME: would it be better to have shrink-to-fit in one step?
+ int preferredWidth = m_maxWidth - bordersPlusPadding;
+ int preferredMinWidth = m_minWidth - bordersPlusPadding;
+ int availableWidth = availableSpace - rightValue;
+ widthValue = kMin(kMax(preferredMinWidth, availableWidth), preferredWidth);
+ leftValue = availableSpace - (widthValue + rightValue);
+ } else if (!leftIsAuto && widthIsAuto && rightIsAuto) {
+ // RULE 3: (use shrink-to-fit for width, and no need solve of right)
+ leftValue = left.width(containerWidth);
+
+ // FIXME: would it be better to have shrink-to-fit in one step?
+ int preferredWidth = m_maxWidth - bordersPlusPadding;
+ int preferredMinWidth = m_minWidth - bordersPlusPadding;
+ int availableWidth = availableSpace - leftValue;
+ widthValue = kMin(kMax(preferredMinWidth, availableWidth), preferredWidth);
+ } else if (leftIsAuto && !width.isVariable() && !rightIsAuto) {
+ // RULE 4: (solve for left)
+ widthValue = calcContentWidth(width.width(containerWidth));
+ leftValue = availableSpace - (widthValue + right.width(containerWidth));
+ } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) {
+ // RULE 5: (solve for width)
+ leftValue = left.width(containerWidth);
+ widthValue = availableSpace - (leftValue + right.width(containerWidth));
+ } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) {
+ // RULE 6: (no need solve for right)
+ leftValue = left.width(containerWidth);
+ widthValue = calcContentWidth(width.width(containerWidth));
+ }
+ }
+
+ // Use computed values to calculate the horizontal position.
+ xPos = leftValue + marginLeftValue + containerBlock->borderLeft();
+}
+
+
+void RenderBox::calcAbsoluteVertical()
+{
+ if (isReplaced()) {
+ calcAbsoluteVerticalReplaced();
+ return;
+ }
+
+ // The following is based off of the W3C Working Draft from April 11, 2006 of
+ // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
+ // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
+ // (block-style-comments in this function and in calcAbsoluteVerticalValues()
+ // correspond to text from the spec)
+
+
+ // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+ const RenderObject* containerBlock = container();
+ const int containerHeight = containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom();
+
+ const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom();
+ const Length marginTop = style()->marginTop();
+ const Length marginBottom = style()->marginBottom();
+ Length top = style()->top();
+ Length bottom = style()->bottom();
+
+ /*---------------------------------------------------------------------------*\
+ * For the purposes of this section and the next, the term "static position"
+ * (of an element) refers, roughly, to the position an element would have had
+ * in the normal flow. More precisely, the static position for 'top' is the
+ * distance from the top edge of the containing block to the top margin edge
+ * of a hypothetical box that would have been the first box of the element if
+ * its 'position' property had been 'static' and 'float' had been 'none'. The
+ * value is negative if the hypothetical box is above the containing block.
+ *
+ * But rather than actually calculating the dimensions of that hypothetical
+ * box, user agents are free to make a guess at its probable position.
+ *
+ * For the purposes of calculating the static position, the containing block
+ * of fixed positioned elements is the initial containing block instead of
+ * the viewport.
+ \*---------------------------------------------------------------------------*/
+
+ // Calculate the static distance if needed.
+ if (top.isVariable() && bottom.isVariable()) {
+ // m_staticY should already have been set through layout of the parent()
+ int staticTop = m_staticY - containerBlock->borderTop();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ staticTop += po->yPos();
+ }
+ top.setValue(Fixed, staticTop);
+ }
+
+
+ int height; // Needed to compute overflow.
+
+ // Calculate constraint equation values for 'height' case.
+ calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
+ top, bottom, marginTop, marginBottom,
+ height, m_marginTop, m_marginBottom, m_y);
+
+ // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
+ // see FIXME 2
+
+ // Calculate constraint equation values for 'max-height' case.
+ if (style()->maxHeight().value() != UNDEFINED) {
+ int maxHeight;
+ short maxMarginTop;
+ short maxMarginBottom;
+ int maxYPos;
+
+ calcAbsoluteVerticalValues(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding,
+ top, bottom, marginTop, marginBottom,
+ maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
+
+ if (height > maxHeight) {
+ height = maxHeight;
+ m_marginTop = maxMarginTop;
+ m_marginBottom = maxMarginBottom;
+ m_y = maxYPos;
+ }
+ }
+
+ // Calculate constraint equation values for 'min-height' case.
+ if (style()->minHeight().value()) {
+ int minHeight;
+ short minMarginTop;
+ short minMarginBottom;
+ int minYPos;
+
+ calcAbsoluteVerticalValues(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding,
+ top, bottom, marginTop, marginBottom,
+ minHeight, minMarginTop, minMarginBottom, minYPos);
+
+ if (height < minHeight) {
+ height = minHeight;
+ m_marginTop = minMarginTop;
+ m_marginBottom = minMarginBottom;
+ m_y = minYPos;
+ }
+ }
+
+ height += bordersPlusPadding;
+
+ // Set final height value.
+ m_height = height;
+}
+
+void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock,
+ const int containerHeight, const int bordersPlusPadding,
+ const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
+ int& heightValue, short& marginTopValue, short& marginBottomValue, int& yPos)
+{
+ // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
+ // converted to the static position in calcAbsoluteVertical()
+ assert(!(top.isVariable() && bottom.isVariable()));
+
+ int contentHeight = m_height - bordersPlusPadding;
+
+ int topValue = 0;
+
+ bool heightIsAuto = height.isVariable();
+ bool topIsAuto = top.isVariable();
+ bool bottomIsAuto = bottom.isVariable();
+
+ if (isTable() && heightIsAuto) {
+ // Height is never unsolved for tables. "auto" means shrink to fit.
+ // Use our height instead.
+ heightValue = contentHeight;
+ heightIsAuto = false;
+ } else if (!heightIsAuto) {
+ heightValue = calcContentHeight(height.width(containerHeight));
+ if (contentHeight > heightValue) {
+ if (!isTable())
+ contentHeight = heightValue;
+ else
+ heightValue = contentHeight;
+ }
+ }
+
+
+ if (!topIsAuto && !heightIsAuto && !bottomIsAuto) {
+ /*-----------------------------------------------------------------------*\
+ * If none of the three are 'auto': If both 'margin-top' and 'margin-
+ * bottom' are 'auto', solve the equation under the extra constraint that
+ * the two margins get equal values. If one of 'margin-top' or 'margin-
+ * bottom' is 'auto', solve the equation for that value. If the values
+ * are over-constrained, ignore the value for 'bottom' and solve for that
+ * value.
+ \*-----------------------------------------------------------------------*/
+ // NOTE: It is not necessary to solve for 'bottom' in the over constrained
+ // case because the value is not used for any further calculations.
+
+ topValue = top.width(containerHeight);
+
+ const int availableSpace = containerHeight - (topValue + heightValue + bottom.width(containerHeight) + bordersPlusPadding);
+
+ // Margins are now the only unknown
+ if (marginTop.isVariable() && marginBottom.isVariable()) {
+ // Both margins auto, solve for equality
+ // NOTE: This may result in negative values.
+ marginTopValue = availableSpace / 2; // split the diference
+ marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences
+ } else if (marginTop.isVariable()) {
+ // Solve for top margin
+ marginBottomValue = marginBottom.width(containerHeight);
+ marginTopValue = availableSpace - marginBottomValue;
+ } else if (marginBottom.isVariable()) {
+ // Solve for bottom margin
+ marginTopValue = marginTop.width(containerHeight);
+ marginBottomValue = availableSpace - marginTopValue;
+ } else {
+ // Over-constrained, (no need solve for bottom)
+ marginTopValue = marginTop.width(containerHeight);
+ marginBottomValue = marginBottom.width(containerHeight);
+ }
+ } else {
+ /*--------------------------------------------------------------------*\
+ * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
+ * to 0, and pick the one of the following six rules that applies.
+ *
+ * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
+ * the height is based on the content, and solve for 'top'.
+ *
+ * OMIT RULE 2 AS IT SHOULD NEVER BE HIT
+ * ------------------------------------------------------------------
+ * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
+ * set 'top' to the static position, and solve for 'bottom'.
+ * ------------------------------------------------------------------
+ *
+ * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
+ * the height is based on the content, and solve for 'bottom'.
+ * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
+ * solve for 'top'.
+ * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
+ * solve for 'height'.
+ * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
+ * solve for 'bottom'.
+ \*--------------------------------------------------------------------*/
+ // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
+ // because the value is not used for any further calculations.
+
+ // Calculate margins, 'auto' margins are ignored.
+ marginTopValue = marginTop.minWidth(containerHeight);
+ marginBottomValue = marginBottom.minWidth(containerHeight);
+
+ const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding);
+
+ // Use rule/case that applies.
+ if (topIsAuto && heightIsAuto && !bottomIsAuto) {
+ // RULE 1: (height is content based, solve of top)
+ heightValue = contentHeight;
+ topValue = availableSpace - (heightValue + bottom.width(containerHeight));
+ }
+ else if (topIsAuto && !heightIsAuto && bottomIsAuto) {
+ // RULE 2: (shouldn't happen)
+ }
+ else if (!topIsAuto && heightIsAuto && bottomIsAuto) {
+ // RULE 3: (height is content based, no need solve of bottom)
+ heightValue = contentHeight;
+ topValue = top.width(containerHeight);
+ } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
+ // RULE 4: (solve of top)
+ topValue = availableSpace - (heightValue + bottom.width(containerHeight));
+ } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
+ // RULE 5: (solve of height)
+ topValue = top.width(containerHeight);
+ heightValue = kMax(0, availableSpace - (topValue + bottom.width(containerHeight)));
+ } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
+ // RULE 6: (no need solve of bottom)
+ topValue = top.width(containerHeight);
+ }
+ }
+
+ // Use computed values to calculate the vertical position.
+ yPos = topValue + marginTopValue + containerBlock->borderTop();
+}
+
+void RenderBox::calcAbsoluteHorizontalReplaced()
+{
+ // The following is based off of the W3C Working Draft from April 11, 2006 of
+ // CSS 2.1: Section 10.3.8 "Absolutly positioned, replaced elements"
+ // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
+ // (block-style-comments in this function correspond to text from the spec and
+ // the numbers correspond to numbers in spec)
+
+ // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+ const RenderObject* containerBlock = container();
+
+ // FIXME: This is incorrect for cases where the container block is a relatively
+ // positioned inline.
+ const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
+
+ // To match WinIE, in quirks mode use the parent's 'direction' property
+ // instead of the the container block's.
+ EDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
+
+ // Variables to solve.
+ Length left = style()->left();
+ Length right = style()->right();
+ Length marginLeft = style()->marginLeft();
+ Length marginRight = style()->marginRight();
+
+
+ /*-----------------------------------------------------------------------*\
+ * 1. The used value of 'width' is determined as for inline replaced
+ * elements.
+ \*-----------------------------------------------------------------------*/
+ // NOTE: This value of width is FINAL in that the min/max width calculations
+ // are dealt with in calcReplacedWidth(). This means that the steps to produce
+ // correct max/min in the non-replaced version, are not necessary.
+ m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
+ const int availableSpace = containerWidth - m_width;
+
+ /*-----------------------------------------------------------------------*\
+ * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
+ * of the containing block is 'ltr', set 'left' to the static position;
+ * else if 'direction' is 'rtl', set 'right' to the static position.
+ \*-----------------------------------------------------------------------*/
+ if (left.isVariable() && right.isVariable()) {
+ // see FIXME 1
+ if (containerDirection == LTR) {
+ // 'm_staticX' should already have been set through layout of the parent.
+ int staticPosition = m_staticX - containerBlock->borderLeft();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
+ staticPosition += po->xPos();
+ left.setValue(Fixed, staticPosition);
+ } else {
+ RenderObject* po = parent();
+ // 'm_staticX' should already have been set through layout of the parent.
+ int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
+ for (; po && po != containerBlock; po = po->parent())
+ staticPosition -= po->xPos();
+ right.setValue(Fixed, staticPosition);
+ }
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
+ * or 'margin-right' with '0'.
+ \*-----------------------------------------------------------------------*/
+ if (left.isVariable() || right.isVariable()) {
+ if (marginLeft.isVariable())
+ marginLeft.setValue(Fixed, 0);
+ if (marginRight.isVariable())
+ marginRight.setValue(Fixed, 0);
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 4. If at this point both 'margin-left' and 'margin-right' are still
+ * 'auto', solve the equation under the extra constraint that the two
+ * margins must get equal values, unless this would make them negative,
+ * in which case when the direction of the containing block is 'ltr'
+ * ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
+ * 'margin-right' ('margin-left').
+ \*-----------------------------------------------------------------------*/
+ int leftValue = 0;
+ int rightValue = 0;
+
+ if (marginLeft.isVariable() && marginRight.isVariable()) {
+ // 'left' and 'right' cannot be 'auto' due to step 3
+ assert(!(left.isVariable() && right.isVariable()));
+
+ leftValue = left.width(containerWidth);
+ rightValue = right.width(containerWidth);
+
+ int difference = availableSpace - (leftValue + rightValue);
+ if (difference > 0) {
+ m_marginLeft = difference / 2; // split the diference
+ m_marginRight = difference - m_marginLeft; // account for odd valued differences
+ } else {
+ // see FIXME 1
+ if (containerDirection == LTR) {
+ m_marginLeft = 0;
+ m_marginRight = difference; // will be negative
+ } else {
+ m_marginLeft = difference; // will be negative
+ m_marginRight = 0;
+ }
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 5. If at this point there is an 'auto' left, solve the equation for
+ * that value.
+ \*-----------------------------------------------------------------------*/
+ } else if (left.isVariable()) {
+ m_marginLeft = marginLeft.width(containerWidth);
+ m_marginRight = marginRight.width(containerWidth);
+ rightValue = right.width(containerWidth);
+
+ // Solve for 'left'
+ leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
+ } else if (right.isVariable()) {
+ m_marginLeft = marginLeft.width(containerWidth);
+ m_marginRight = marginRight.width(containerWidth);
+ leftValue = left.width(containerWidth);
+
+ // Solve for 'right'
+ rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
+ } else if (marginLeft.isVariable()) {
+ m_marginRight = marginRight.width(containerWidth);
+ leftValue = left.width(containerWidth);
+ rightValue = right.width(containerWidth);
+
+ // Solve for 'margin-left'
+ m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight);
+ } else if (marginRight.isVariable()) {
+ m_marginLeft = marginLeft.width(containerWidth);
+ leftValue = left.width(containerWidth);
+ rightValue = right.width(containerWidth);
+
+ // Solve for 'margin-right'
+ m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft);
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 6. If at this point the values are over-constrained, ignore the value
+ * for either 'left' (in case the 'direction' property of the
+ * containing block is 'rtl') or 'right' (in case 'direction' is
+ * 'ltr') and solve for that value.
+ \*-----------------------------------------------------------------------*/
+ else {
+ m_marginLeft = marginLeft.width(containerWidth);
+ m_marginRight = marginRight.width(containerWidth);
+ if (containerDirection == LTR) {
+ leftValue = left.width(containerWidth);
+ rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
+ }
+ else {
+ rightValue = right.width(containerWidth);
+ leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
+ }
+ }
+
+ int totalWidth = m_width + leftValue + rightValue + m_marginLeft + m_marginRight;
+ if (totalWidth > containerWidth && (containerDirection == RTL))
+ leftValue = containerWidth - (totalWidth - leftValue);
+
+ // Use computed values to calculate the horizontal position.
+ m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
+}
+
+void RenderBox::calcAbsoluteVerticalReplaced()
+{
+ // The following is based off of the W3C Working Draft from April 11, 2006 of
+ // CSS 2.1: Section 10.6.5 "Absolutly positioned, replaced elements"
+ // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
+ // (block-style-comments in this function correspond to text from the spec and
+ // the numbers correspond to numbers in spec)
+
+ // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+ const RenderObject* containerBlock = container();
+ const int containerHeight = containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom();
+
+ // Variables to solve.
+ Length top = style()->top();
+ Length bottom = style()->bottom();
+ Length marginTop = style()->marginTop();
+ Length marginBottom = style()->marginBottom();
+
+
+ /*-----------------------------------------------------------------------*\
+ * 1. The used value of 'height' is determined as for inline replaced
+ * elements.
+ \*-----------------------------------------------------------------------*/
+ // NOTE: This value of height is FINAL in that the min/max height calculations
+ // are dealt with in calcReplacedHeight(). This means that the steps to produce
+ // correct max/min in the non-replaced version, are not necessary.
+ m_height = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
+ const int availableSpace = containerHeight - m_height;
+
+ /*-----------------------------------------------------------------------*\
+ * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
+ * with the element's static position.
+ \*-----------------------------------------------------------------------*/
+ if (top.isVariable() && bottom.isVariable()) {
+ // m_staticY should already have been set through layout of the parent().
+ int staticTop = m_staticY - containerBlock->borderTop();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ staticTop += po->yPos();
+ }
+ top.setValue(Fixed, staticTop);
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
+ * 'margin-bottom' with '0'.
+ \*-----------------------------------------------------------------------*/
+ // FIXME: The spec. says that this step should only be taken when bottom is
+ // auto, but if only top is auto, this makes step 4 impossible.
+ if (top.isVariable() || bottom.isVariable()) {
+ if (marginTop.isVariable())
+ marginTop.setValue(Fixed, 0);
+ if (marginBottom.isVariable())
+ marginBottom.setValue(Fixed, 0);
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 4. If at this point both 'margin-top' and 'margin-bottom' are still
+ * 'auto', solve the equation under the extra constraint that the two
+ * margins must get equal values.
+ \*-----------------------------------------------------------------------*/
+ int topValue = 0;
+ int bottomValue = 0;
+
+ if (marginTop.isVariable() && marginBottom.isVariable()) {
+ // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combinded.
+ assert(!(top.isVariable() || bottom.isVariable()));
+
+ topValue = top.width(containerHeight);
+ bottomValue = bottom.width(containerHeight);
+
+ int difference = availableSpace - (topValue + bottomValue);
+ // NOTE: This may result in negative values.
+ m_marginTop = difference / 2; // split the difference
+ m_marginBottom = difference - m_marginTop; // account for odd valued differences
+
+ /*-----------------------------------------------------------------------*\
+ * 5. If at this point there is only one 'auto' left, solve the equation
+ * for that value.
+ \*-----------------------------------------------------------------------*/
+ } else if (top.isVariable()) {
+ m_marginTop = marginTop.width(containerHeight);
+ m_marginBottom = marginBottom.width(containerHeight);
+ bottomValue = bottom.width(containerHeight);
+
+ // Solve for 'top'
+ topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom);
+ } else if (bottom.isVariable()) {
+ m_marginTop = marginTop.width(containerHeight);
+ m_marginBottom = marginBottom.width(containerHeight);
+ topValue = top.width(containerHeight);
+
+ // Solve for 'bottom'
+ // NOTE: It is not necessary to solve for 'bottom' because we don't ever
+ // use the value.
+ } else if (marginTop.isVariable()) {
+ m_marginBottom = marginBottom.width(containerHeight);
+ topValue = top.width(containerHeight);
+ bottomValue = bottom.width(containerHeight);
+
+ // Solve for 'margin-top'
+ m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom);
+ } else if (marginBottom.isVariable()) {
+ m_marginTop = marginTop.width(containerHeight);
+ topValue = top.width(containerHeight);
+ bottomValue = bottom.width(containerHeight);
+
+ // Solve for 'margin-bottom'
+ m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop);
+ }
+
+ /*-----------------------------------------------------------------------*\
+ * 6. If at this point the values are over-constrained, ignore the value
+ * for 'bottom' and solve for that value.
+ \*-----------------------------------------------------------------------*/
+ else {
+ m_marginTop = marginTop.width(containerHeight);
+ m_marginBottom = marginBottom.width(containerHeight);
+ topValue = top.width(containerHeight);
+
+ // Solve for 'bottom'
+ // NOTE: It is not necessary to solve for 'bottom' because we don't ever
+ // use the value.
+ }
+
+ // Use computed values to calculate the vertical position.
+ m_y = topValue + m_marginTop + containerBlock->borderTop();
+}
+
+int RenderBox::highestPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
+{
+ return includeSelf ? 0 : m_height;
+}
+
+int RenderBox::lowestPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
+{
+ return includeSelf ? m_height : 0;
+}
+
+int RenderBox::rightmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
+{
+ return includeSelf ? m_width : 0;
+}
+
+int RenderBox::leftmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
+{
+ return includeSelf ? 0 : m_width;
+}
+
+int RenderBox::pageTopAfter(int y) const
+{
+ RenderObject* cb = container();
+ if (cb)
+ return cb->pageTopAfter(y+yPos()) - yPos();
+ else
+ return 0;
+}
+
+int RenderBox::crossesPageBreak(int t, int b) const
+{
+ RenderObject* cb = container();
+ if (cb)
+ return cb->crossesPageBreak(yPos()+t, yPos()+b);
+ else
+ return false;
+}
+
+void RenderBox::caretPos(int /*offset*/, int flags, int &_x, int &_y, int &width, int &height)
+{
+#if 0
+ _x = -1;
+
+ // propagate it downwards to its children, someone will feel responsible
+ RenderObject *child = firstChild();
+// if (child) kdDebug(6040) << "delegating caretPos to " << child->renderName() << endl;
+ if (child) child->caretPos(offset, override, _x, _y, width, height);
+
+ // if not, use the extents of this box. offset 0 means left, offset 1 means
+ // right
+ if (_x == -1) {
+ //kdDebug(6040) << "no delegation" << endl;
+ _x = xPos() + (offset == 0 ? 0 : m_width);
+ _y = yPos();
+ height = m_height;
+ width = override && offset == 0 ? m_width : 1;
+
+ // If height of box is smaller than font height, use the latter one,
+ // otherwise the caret might become invisible.
+ // FIXME: ignoring :first-line, missing good reason to take care of
+ int fontHeight = style()->fontMetrics().height();
+ if (fontHeight > height)
+ height = fontHeight;
+
+ int absx, absy;
+
+ RenderObject *cb = containingBlock();
+
+ if (cb && cb != this && cb->absolutePosition(absx,absy)) {
+ //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
+ _x += absx;
+ _y += absy;
+ } else {
+ // we don't know our absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+ }
+#endif
+
+ _x = xPos();
+ _y = yPos();
+// kdDebug(6040) << "_x " << _x << " _y " << _y << endl;
+ width = 1; // no override is indicated in boxes
+
+ RenderBlock *cb = containingBlock();
+
+ // Place caret outside the border
+ if (flags & CFOutside) {
+
+ RenderStyle *s = element() && element()->parent()
+ && element()->parent()->renderer()
+ ? element()->parent()->renderer()->style()
+ : cb->style();
+
+ const TQFontMetrics &fm = s->fontMetrics();
+ height = fm.height();
+
+ bool rtl = s->direction() == RTL;
+ bool outsideEnd = flags & CFOutsideEnd;
+
+ if (outsideEnd) {
+ _x += this->width();
+ } else {
+ _x--;
+ }
+
+ int hl = fm.leading() / 2;
+ if (!isReplaced() || style()->display() == BLOCK) {
+ if (!outsideEnd ^ rtl)
+ _y -= hl;
+ else
+ _y += kMax(this->height() - fm.ascent() - hl, 0);
+ } else {
+ _y += baselinePosition(false) - fm.ascent() - hl;
+ }
+
+ // Place caret inside the element
+ } else {
+ const TQFontMetrics &fm = style()->fontMetrics();
+ height = fm.height();
+
+ RenderStyle *s = style();
+
+ _x += borderLeft() + paddingLeft();
+ _y += borderTop() + paddingTop();
+
+ // ### regard direction
+ switch (s->textAlign()) {
+ case LEFT:
+ case KHTML_LEFT:
+ case TAAUTO: // ### find out what this does
+ case JUSTIFY:
+ break;
+ case CENTER:
+ case KHTML_CENTER:
+ _x += contentWidth() / 2;
+ break;
+ case KHTML_RIGHT:
+ case RIGHT:
+ _x += contentWidth();
+ break;
+ }
+ }
+
+ int absx, absy;
+ if (cb && cb != this && cb->absolutePosition(absx,absy)) {
+// kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
+ _x += absx;
+ _y += absy;
+ } else {
+ // we don't know our absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+}
+
+#undef DEBUG_LAYOUT
diff --git a/tdehtml/rendering/render_box.h b/tdehtml/rendering/render_box.h
new file mode 100644
index 000000000..0a65df72e
--- /dev/null
+++ b/tdehtml/rendering/render_box.h
@@ -0,0 +1,213 @@
+/*
+ * 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) 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 RENDER_BOX_H
+#define RENDER_BOX_H
+
+#include "render_container.h"
+
+namespace tdehtml {
+
+enum WidthType { Width, MinWidth, MaxWidth };
+enum HeightType { Height, MinHeight, MaxHeight };
+
+class RenderBlock;
+
+class RenderBox : public RenderContainer
+{
+
+
+// combines ElemImpl & PosElImpl (all rendering objects are positioned)
+// should contain all border and padding handling
+
+public:
+ RenderBox(DOM::NodeImpl* node);
+ virtual ~RenderBox();
+
+ virtual const char *renderName() const { return "RenderBox"; }
+ virtual bool isBox() const { return true; }
+
+ virtual void setStyle(RenderStyle *style);
+ virtual void paint(PaintInfo& i, int _tx, int _ty);
+
+ virtual void close();
+
+ virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
+ virtual void deleteInlineBoxes(RenderArena* arena=0);
+
+ virtual void detach();
+
+ virtual short minWidth() const { return m_minWidth; }
+ virtual int maxWidth() const { return m_maxWidth; }
+
+ virtual short contentWidth() const;
+ virtual int contentHeight() const;
+
+ virtual bool absolutePosition(int &xPos, int &yPos, bool f = false) const;
+
+ virtual void setPos( int xPos, int yPos );
+
+ virtual int xPos() const { return m_x; }
+ virtual int yPos() const { return m_y; }
+ virtual short width() const;
+ virtual int height() const;
+
+ virtual short marginTop() const { return m_marginTop; }
+ virtual short marginBottom() const { return m_marginBottom; }
+ virtual short marginLeft() const { return m_marginLeft; }
+ virtual short marginRight() const { return m_marginRight; }
+
+ virtual void setWidth( int width );
+ virtual void setHeight( int height );
+
+ virtual void position(InlineBox* box, int from, int len, bool reverse);
+
+ virtual int highestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+
+ virtual void repaint(Priority p=NormalPriority);
+
+ virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
+
+ virtual short containingBlockWidth() const;
+ void relativePositionOffset(int &tx, int &ty) const;
+
+ virtual void calcWidth();
+ virtual void calcHeight();
+
+ virtual short calcReplacedWidth() const;
+ virtual int calcReplacedHeight() const;
+
+ virtual int availableHeight() const;
+ virtual int availableWidth() const;
+
+ void calcVerticalMargins();
+
+ virtual RenderLayer* layer() const { return m_layer; }
+
+ void setStaticX(short staticX);
+ void setStaticY(int staticY);
+ int staticX() const { return m_staticX; }
+ int staticY() const { return m_staticY; }
+
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+
+ void calcHorizontalMargins(const Length& ml, const Length& mr, int cw);
+ RenderBlock* createAnonymousBlock();
+
+ virtual int pageTopAfter(int y) const;
+ virtual int crossesPageBreak(int t, int b) const;
+
+ int calcBoxWidth(int w) const;
+ int calcBoxHeight(int h) const;
+ int calcContentWidth(int w) const;
+ int calcContentHeight(int h) const;
+
+protected:
+ int calcWidthUsing(WidthType widthType, int cw, LengthType& lengthType);
+ int calcHeightUsing(const Length& height);
+ int calcReplacedWidthUsing(WidthType widthType) const;
+ int calcReplacedHeightUsing(HeightType heightType) const;
+ int calcPercentageHeight(const Length& height, bool treatAsReplaced = false) const;
+ int availableHeightUsing(const Length& h) const;
+ int availableWidthUsing(const Length& w) const;
+ int calcImplicitHeight() const;
+ bool hasImplicitHeight() const {
+ return isPositioned() && !style()->top().isVariable() && !style()->bottom().isVariable();
+ }
+
+protected:
+ virtual void paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty);
+ void paintRootBoxDecorations( PaintInfo& paintInfo, int _tx, int _ty);
+
+ void paintBackgrounds(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int h);
+ void paintBackground(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int h);
+
+ virtual void paintBackgroundExtended(TQPainter* /*p*/, const TQColor& /*c*/, const BackgroundLayer* /*bgLayer*/,
+ int /*clipy*/, int /*cliph*/, int /*_tx*/, int /*_ty*/,
+ int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/ );
+
+ void outlineBox(TQPainter *p, int _tx, int _ty, const char *color = "red");
+
+ void calcAbsoluteHorizontal();
+ void calcAbsoluteVertical();
+ void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, EDirection containerDirection,
+ const int containerWidth, const int bordersPlusPadding,
+ const Length left, const Length right, const Length marginLeft, const Length marginRight,
+ short& widthValue, short& marginLeftValue, short& marginRightValue, short& xPos);
+ void calcAbsoluteVerticalValues(Length height, const RenderObject* cb,
+ const int containerHeight, const int bordersPlusPadding,
+ const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
+ int& heightValue, short& marginTopValue, short& marginBottomValue, int& yPos);
+
+ void calcAbsoluteVerticalReplaced();
+ void calcAbsoluteHorizontalReplaced();
+
+ TQRect getOverflowClipRect(int tx, int ty);
+ TQRect getClipRect(int tx, int ty);
+
+ void restructureParentFlow();
+
+
+ // the actual height of the contents + borders + padding (border-box)
+ int m_height;
+ int m_y;
+
+ short m_width;
+ short m_x;
+
+ short m_marginTop;
+ short m_marginBottom;
+
+ short m_marginLeft;
+ short m_marginRight;
+
+ /*
+ * the minimum width the element needs, to be able to render
+ * its content without clipping
+ */
+ short m_minWidth;
+ /* The maximum width the element can fill horizontally
+ * ( = the width of the element with line breaking disabled)
+ */
+ int m_maxWidth;
+
+ // Cached normal flow values for absolute positioned elements with static left/top values.
+ short m_staticX;
+ int m_staticY;
+
+ RenderLayer *m_layer;
+
+ /* A box used to represent this object on a line
+ * when its inner content isn't contextually relevant
+ * (e.g replaced or positioned elements)
+ */
+ InlineBox *m_placeHolderBox;
+};
+
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_br.cpp b/tdehtml/rendering/render_br.cpp
new file mode 100644
index 000000000..f330e5f17
--- /dev/null
+++ b/tdehtml/rendering/render_br.cpp
@@ -0,0 +1,79 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 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 "render_br.h"
+
+using namespace tdehtml;
+
+
+RenderBR::RenderBR(DOM::NodeImpl* node)
+ : RenderText(node, new DOM::DOMStringImpl(TQChar('\n')))
+{
+ m_hasReturn = true;
+}
+
+RenderBR::~RenderBR()
+{
+}
+
+#if 0
+void RenderBR::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
+{
+ RenderText::caretPos(offset,flags,_x,_y,width,height);
+ return;
+#if 0
+ if (previousSibling() && !previousSibling()->isBR() && !previousSibling()->isFloating()) {
+ int offset = 0;
+ if (previousSibling()->isText())
+ offset = static_cast<RenderText*>(previousSibling())->maxOffset();
+
+ // FIXME: this won't return a big width in override mode (LS)
+ previousSibling()->caretPos(offset,override,_x,_y,width,height);
+ return;
+ }
+
+ int absx, absy;
+ absolutePosition(absx,absy);
+ if (absx == -1) {
+ // we don't know out absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+ else {
+ _x += absx;
+ _y += absy;
+ }
+ height = RenderText::verticalPositionHint( false );
+ width = override ? height / 2 : 1;
+#endif
+}
+#endif
+
+FindSelectionResult RenderBR::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &state)
+{
+ // Simply take result of previous one
+ RenderText *prev = static_cast<RenderText *>(previousSibling());
+ if (!prev || !prev->isText() || !prev->inlineTextBoxCount() || prev->isBR())
+ prev = this;
+
+ //kdDebug(6040) << "delegated to " << prev->renderName() << "@" << prev << endl;
+ return prev->RenderText::checkSelectionPoint(_x, _y, _tx, _ty, node, offset, state);
+}
diff --git a/tdehtml/rendering/render_br.h b/tdehtml/rendering/render_br.h
new file mode 100644
index 000000000..8e511c94f
--- /dev/null
+++ b/tdehtml/rendering/render_br.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 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 RENDER_BR_H
+#define RENDER_BR_H
+
+#include "render_text.h"
+
+/*
+ * The whole class here is a hack to get <br> working, as long as we don't have support for
+ * CSS2 :before and :after pseudo elements
+ */
+namespace tdehtml {
+
+class RenderBR : public RenderText
+{
+public:
+ RenderBR(DOM::NodeImpl* node);
+ virtual ~RenderBR();
+
+ virtual const char *renderName() const { return "RenderBR"; }
+
+ virtual void paint( PaintInfo&, int, int) {}
+
+ virtual unsigned int width(unsigned int, unsigned int, const Font *) const { return 0; }
+ virtual unsigned int width( unsigned int, unsigned int, bool) const { return 0; }
+ virtual short width() const { return RenderText::width(); }
+
+ virtual int height() const { return 0; }
+
+ // overrides
+ virtual void calcMinMaxWidth() {}
+ virtual short minWidth() const { return 0; }
+ virtual int maxWidth() const { return 0; }
+
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*& node, int & offset,
+ SelPointState & );
+
+ virtual bool isBR() const { return true; }
+#if 0
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+#endif
+ /** returns the lowest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns 0.
+ */
+ virtual long minOffset() const { return 0; }
+ /** returns the highest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns also 0, as BRs have no width.
+ */
+ virtual long maxOffset() const { return 0; }
+};
+
+}
+#endif
diff --git a/tdehtml/rendering/render_canvas.cpp b/tdehtml/rendering/render_canvas.cpp
new file mode 100644
index 000000000..53dc32162
--- /dev/null
+++ b/tdehtml/rendering/render_canvas.cpp
@@ -0,0 +1,780 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2003 Apple Computer, Inc.
+ * (C) 2005 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.
+ */
+
+
+#include "rendering/render_canvas.h"
+#include "rendering/render_layer.h"
+#include "xml/dom_docimpl.h"
+
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include <kdebug.h>
+#include <kglobal.h>
+
+using namespace tdehtml;
+
+//#define BOX_DEBUG
+//#define SPEED_DEBUG
+
+RenderCanvas::RenderCanvas(DOM::NodeImpl* node, KHTMLView *view)
+ : RenderBlock(node)
+{
+ // init RenderObject attributes
+ setInline(false);
+ setIsAnonymous(false);
+
+ m_view = view;
+ // try to contrain the width to the views width
+
+ m_minWidth = 0;
+ m_height = 0;
+
+ m_width = m_minWidth;
+ m_maxWidth = m_minWidth;
+
+ m_rootWidth = m_rootHeight = 0;
+ m_viewportWidth = m_viewportHeight = 0;
+ m_cachedDocWidth = m_cachedDocHeight = -1;
+
+ setPositioned(true); // to 0,0 :)
+
+ m_staticMode = false;
+ m_pagedMode = false;
+ m_printImages = true;
+
+ m_pageTop = 0;
+ m_pageBottom = 0;
+
+ m_page = 0;
+
+ m_maximalOutlineSize = 0;
+
+ m_selectionStart = 0;
+ m_selectionEnd = 0;
+ m_selectionStartPos = -1;
+ m_selectionEndPos = -1;
+
+ m_needsWidgetMasks = false;
+
+ // Create a new root layer for our layer hierarchy.
+ m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
+}
+
+RenderCanvas::~RenderCanvas()
+{
+ delete m_page;
+}
+
+void RenderCanvas::setStyle(RenderStyle* style)
+{
+ /*
+ if (m_pagedMode)
+ style->setOverflow(OHIDDEN); */
+ RenderBlock::setStyle(style);
+}
+
+void RenderCanvas::calcHeight()
+{
+ if (m_pagedMode || !m_view)
+ m_height = m_rootHeight;
+ else
+ m_height = m_view->visibleHeight();
+}
+
+void RenderCanvas::calcWidth()
+{
+ // the width gets set by KHTMLView::print when printing to a printer.
+ if(m_pagedMode || !m_view)
+ {
+ m_width = m_rootWidth;
+ return;
+ }
+
+ m_width = m_view ? m_view->frameWidth() : m_minWidth;
+
+ if (style()->marginLeft().isFixed())
+ m_marginLeft = style()->marginLeft().value();
+ else
+ m_marginLeft = 0;
+
+ if (style()->marginRight().isFixed())
+ m_marginRight = style()->marginRight().value();
+ else
+ m_marginRight = 0;
+}
+
+void RenderCanvas::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ RenderBlock::calcMinMaxWidth();
+
+ m_maxWidth = m_minWidth;
+
+ setMinMaxKnown();
+}
+
+//#define SPEED_DEBUG
+
+void RenderCanvas::layout()
+{
+ if (m_pagedMode) {
+ m_minWidth = m_width;
+// m_maxWidth = m_width;
+ }
+
+ m_needsFullRepaint = markedForRepaint() || !view() || view()->needsFullRepaint() || m_pagedMode;
+
+ setChildNeedsLayout(true);
+ setMinMaxKnown(false);
+ for(RenderObject* c = firstChild(); c; c = c->nextSibling())
+ c->setChildNeedsLayout(true);
+
+ int oldWidth = m_width;
+ int oldHeight = m_height;
+
+ m_cachedDocWidth = m_cachedDocHeight = -1;
+
+ if (m_pagedMode || !m_view) {
+ m_width = m_rootWidth;
+ m_height = m_rootHeight;
+ }
+ else
+ {
+ m_viewportWidth = m_width = m_view->visibleWidth();
+ m_viewportHeight = m_height = m_view->visibleHeight();
+ }
+
+#ifdef SPEED_DEBUG
+ TQTime qt;
+ qt.start();
+#endif
+
+ if ( recalcMinMax() )
+ recalcMinMaxWidths();
+
+#ifdef SPEED_DEBUG
+ kdDebug() << "RenderCanvas::calcMinMax time used=" << qt.elapsed() << endl;
+ qt.start();
+#endif
+
+ bool relayoutChildren = (oldWidth != m_width) || (oldHeight != m_height);
+
+ RenderBlock::layoutBlock( relayoutChildren );
+
+#ifdef SPEED_DEBUG
+ kdDebug() << "RenderCanvas::layout time used=" << qt.elapsed() << endl;
+ qt.start();
+#endif
+
+ updateDocumentSize();
+
+ layer()->updateLayerPositions( layer(), needsFullRepaint(), true );
+
+ if (!m_pagedMode && m_needsWidgetMasks)
+ layer()->updateWidgetMasks(layer());
+
+ scheduleDeferredRepaints();
+ setNeedsLayout(false);
+
+#ifdef SPEED_DEBUG
+ kdDebug() << "RenderCanvas::end time used=" << qt.elapsed() << endl;
+#endif
+}
+
+void RenderCanvas::updateDocumentSize()
+{
+ // update our cached document size
+ int hDocH = m_cachedDocHeight = docHeight();
+ int hDocW = m_cachedDocWidth = docWidth();
+
+ if (!m_pagedMode && m_view) {
+
+ bool vss = m_view->verticalScrollBar()->isShown();
+ bool hss = m_view->horizontalScrollBar()->isShown();
+ TQSize s = m_view->viewportSize(m_cachedDocWidth, m_cachedDocHeight);
+
+ // if we are about to show a scrollbar, and the document is sized to the viewport w or h,
+ // then reserve the scrollbar space so that it doesn't trigger the _other_ scrollbar
+
+ if (!vss && m_width - m_view->verticalScrollBar()->sizeHint().width() == s.width() &&
+ m_cachedDocWidth <= m_width)
+ hDocW = kMin( m_cachedDocWidth, s.width() );
+
+ if (!hss && m_height - m_view->horizontalScrollBar()->sizeHint().height() == s.height() &&
+ m_cachedDocHeight <= m_height)
+ hDocH = kMin( m_cachedDocHeight, s.height() );
+
+ // likewise, if a scrollbar is shown, and we have a cunning plan to turn it off,
+ // think again if we are falling downright in the hysteresis zone
+
+ if (vss && s.width() > m_cachedDocWidth && m_cachedDocWidth > m_view->visibleWidth())
+ hDocW = s.width()+1;
+
+ if (hss && s.height() > m_cachedDocHeight && m_cachedDocHeight > m_view->visibleHeight())
+ hDocH = s.height()+1;
+
+ m_view->resizeContents(hDocW, hDocH);
+
+ setWidth( m_viewportWidth = s.width() );
+ setHeight( m_viewportHeight = s.height() );
+ }
+ layer()->resize( kMax( m_cachedDocWidth,int( m_width ) ), kMax( m_cachedDocHeight,m_height ) );
+}
+
+void RenderCanvas::updateDocSizeAfterLayerTranslation( RenderObject* o, bool posXOffset, bool posYOffset )
+{
+ if (needsLayout())
+ return;
+ int rightmost, lowest;
+ o->absolutePosition( rightmost, lowest );
+ if (posXOffset) {
+ rightmost += o->rightmostPosition(false, true);
+ setCachedDocWidth( kMax(docWidth(), rightmost) );
+ } else {
+ setCachedDocWidth( -1 );
+ }
+ if (posYOffset) {
+ lowest += o->lowestPosition(false, true);
+ setCachedDocHeight( kMax(docHeight(), lowest) );
+ } else {
+ setCachedDocHeight( -1 );
+ }
+// kdDebug() << " posXOffset: " << posXOffset << " posYOffset " << posYOffset << " m_cachedDocWidth " << m_cachedDocWidth << " m_cachedDocHeight " << m_cachedDocHeight << endl;
+ updateDocumentSize();
+}
+
+bool RenderCanvas::needsFullRepaint() const
+{
+ return m_needsFullRepaint || m_pagedMode;
+}
+
+void RenderCanvas::repaintViewRectangle(int x, int y, int w, int h, bool asap)
+{
+ KHTMLAssert( view() );
+ view()->scheduleRepaint( x, y, w, h, asap );
+}
+
+bool RenderCanvas::absolutePosition(int &xPos, int &yPos, bool f) const
+{
+ if ( f && m_pagedMode) {
+ xPos = 0;
+ yPos = m_pageTop;
+ }
+ else if ( f && m_view) {
+ xPos = m_view->contentsX();
+ yPos = m_view->contentsY();
+ }
+ else {
+ xPos = yPos = 0;
+ }
+ return true;
+}
+
+void RenderCanvas::paint(PaintInfo& paintInfo, int _tx, int _ty)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
+#endif
+
+ // 1. paint background, borders etc
+ if(paintInfo.phase == PaintActionElementBackground) {
+ paintBoxDecorations(paintInfo, _tx, _ty);
+ return;
+ }
+
+ // 2. paint contents
+ for( RenderObject *child = firstChild(); child; child=child->nextSibling())
+ if(!child->layer() && !child->isFloating())
+ child->paint(paintInfo, _tx, _ty);
+
+ // 3. paint floats.
+ if (paintInfo.phase == PaintActionFloat)
+ paintFloats(paintInfo, _tx, _ty);
+
+#ifdef BOX_DEBUG
+ if (m_view)
+ {
+ _tx += m_view->contentsX();
+ _ty += m_view->contentsY();
+ }
+
+ outlineBox(p, _tx, _ty);
+#endif
+
+}
+
+void RenderCanvas::paintBoxDecorations(PaintInfo& paintInfo, int /*_tx*/, int /*_ty*/)
+{
+ if ((firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
+ return;
+
+ paintInfo.p->fillRect(paintInfo.r, view()->palette().active().color(TQColorGroup::Base));
+}
+
+void RenderCanvas::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
+{
+ if (m_staticMode) return;
+// kdDebug( 6040 ) << "updating views contents (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl;
+
+ if (f && m_pagedMode) {
+ y += m_pageTop;
+ } else
+ if ( f && m_view ) {
+ x += m_view->contentsX();
+ y += m_view->contentsY();
+ }
+
+ TQRect vr = viewRect();
+ TQRect ur(x, y, w, h);
+
+ if (m_view && ur.intersects(vr)) {
+
+ if (p == RealtimePriority)
+ // ### KWQ's updateContents has an additional parameter "now".
+ // It's not clear what the difference between updateContents(...,true)
+ // and repaintContents(...) is. As Qt doesn't have this, I'm leaving it out. (LS)
+ m_view->updateContents(ur/*, true*/);
+ else if (p == HighPriority)
+ m_view->scheduleRepaint(x, y, w, h, true /*asap*/);
+ else
+ m_view->scheduleRepaint(x, y, w, h);
+ }
+}
+
+void RenderCanvas::deferredRepaint( RenderObject* o )
+{
+ m_dirtyChildren.append( o );
+}
+
+void RenderCanvas::scheduleDeferredRepaints()
+{
+ if (!needsFullRepaint()) {
+ TQValueList<RenderObject*>::const_iterator it;
+ for ( it = m_dirtyChildren.begin(); it != m_dirtyChildren.end(); ++it )
+ (*it)->repaint();
+ }
+ //kdDebug(6040) << "scheduled deferred repaints: " << m_dirtyChildren.count() << " needed full repaint: " << needsFullRepaint() << endl;
+ m_dirtyChildren.clear();
+}
+
+void RenderCanvas::repaint(Priority p)
+{
+ if (m_view && !m_staticMode) {
+ if (p == RealtimePriority) {
+ //m_view->resizeContents(docWidth(), docHeight());
+ m_view->unscheduleRepaint();
+ if (needsLayout()) {
+ m_view->scheduleRelayout();
+ return;
+ }
+ // ### same as in repaintRectangle
+ m_view->updateContents(m_view->contentsX(), m_view->contentsY(),
+ m_view->visibleWidth(), m_view->visibleHeight()/*, true*/);
+ }
+ else if (p == HighPriority)
+ m_view->scheduleRepaint(m_view->contentsX(), m_view->contentsY(),
+ m_view->visibleWidth(), m_view->visibleHeight(), true /*asap*/);
+ else
+ m_view->scheduleRepaint(m_view->contentsX(), m_view->contentsY(),
+ m_view->visibleWidth(), m_view->visibleHeight());
+ }
+}
+
+static TQRect enclosingPositionedRect (RenderObject *n)
+{
+ RenderObject *enclosingParent = n->containingBlock();
+ TQRect rect(0,0,0,0);
+ if (enclosingParent) {
+ int ox, oy;
+ enclosingParent->absolutePosition(ox, oy);
+ int off = 0;
+ if (!enclosingParent->hasOverflowClip()) {
+ ox += enclosingParent->overflowLeft();
+ oy += enclosingParent->overflowTop();
+ }
+ rect.setX(ox);
+ rect.setY(oy);
+ rect.setWidth(enclosingParent->effectiveWidth());
+ rect.setHeight(enclosingParent->effectiveHeight());
+ }
+ return rect;
+}
+
+TQRect RenderCanvas::selectionRect() const
+{
+ RenderObject *r = m_selectionStart;
+ if (!r)
+ return TQRect();
+
+ TQRect selectionRect = enclosingPositionedRect(r);
+
+ while (r && r != m_selectionEnd)
+ {
+ RenderObject* n;
+ if ( !(n = r->firstChild()) ){
+ if ( !(n = r->nextSibling()) )
+ {
+ n = r->parent();
+ while (n && !n->nextSibling())
+ n = n->parent();
+ if (n)
+ n = n->nextSibling();
+ }
+ }
+ r = n;
+ if (r) {
+ selectionRect = selectionRect.unite(enclosingPositionedRect(r));
+ }
+ }
+
+ return selectionRect;
+}
+
+void RenderCanvas::setSelection(RenderObject *s, int sp, RenderObject *e, int ep)
+{
+ // Check we got valid renderobjects. www.msnbc.com and clicking
+ // around, to find the case where this happened.
+ if ( !s || !e )
+ {
+ kdWarning(6040) << "RenderCanvas::setSelection() called with start=" << s << " end=" << e << endl;
+ return;
+ }
+// kdDebug( 6040 ) << "RenderCanvas::setSelection(" << s << "," << sp << "," << e << "," << ep << ")" << endl;
+
+ bool changedSelectionBorder = ( s != m_selectionStart || e != m_selectionEnd );
+
+ // Cut out early if the selection hasn't changed.
+ if ( !changedSelectionBorder && m_selectionStartPos == sp && m_selectionEndPos == ep )
+ return;
+
+ // Record the old selected objects. Will be used later
+ // to delta against the selected objects.
+
+ RenderObject *oldStart = m_selectionStart;
+ int oldStartPos = m_selectionStartPos;
+ RenderObject *oldEnd = m_selectionEnd;
+ int oldEndPos = m_selectionEndPos;
+ TQPtrList<RenderObject> oldSelectedInside;
+ TQPtrList<RenderObject> newSelectedInside;
+ RenderObject *os = oldStart;
+
+ while (os && os != oldEnd)
+ {
+ RenderObject* no;
+ if ( !(no = os->firstChild()) ){
+ if ( !(no = os->nextSibling()) )
+ {
+ no = os->parent();
+ while (no && !no->nextSibling())
+ no = no->parent();
+ if (no)
+ no = no->nextSibling();
+ }
+ }
+ if (os->selectionState() == SelectionInside && !oldSelectedInside.containsRef(os))
+ oldSelectedInside.append(os);
+
+ os = no;
+ }
+ if (changedSelectionBorder)
+ clearSelection(false);
+
+ while (s->firstChild())
+ s = s->firstChild();
+ while (e->lastChild())
+ e = e->lastChild();
+
+#if 0
+ bool changedSelectionBorder = ( s != m_selectionStart || e != m_selectionEnd );
+
+ if ( !changedSelectionBorder && m_selectionStartPos == sp && m_selectionEndPos = ep )
+ return;
+#endif
+
+ // set selection start
+ if (m_selectionStart)
+ m_selectionStart->setIsSelectionBorder(false);
+ m_selectionStart = s;
+ if (m_selectionStart)
+ m_selectionStart->setIsSelectionBorder(true);
+ m_selectionStartPos = sp;
+
+ // set selection end
+ if (m_selectionEnd)
+ m_selectionEnd->setIsSelectionBorder(false);
+ m_selectionEnd = e;
+ if (m_selectionEnd)
+ m_selectionEnd->setIsSelectionBorder(true);
+ m_selectionEndPos = ep;
+
+#if 0
+ kdDebug( 6040 ) << "old selection (" << oldStart << "," << oldStartPos << "," << oldEnd << "," << oldEndPos << ")" << endl;
+ kdDebug( 6040 ) << "new selection (" << s << "," << sp << "," << e << "," << ep << ")" << endl;
+#endif
+
+ // update selection status of all objects between m_selectionStart and m_selectionEnd
+ RenderObject* o = s;
+
+ while (o && o!=e)
+ {
+ o->setSelectionState(SelectionInside);
+// kdDebug( 6040 ) << "setting selected " << o << ", " << o->isText() << endl;
+ RenderObject* no;
+ if ( !(no = o->firstChild()) )
+ if ( !(no = o->nextSibling()) )
+ {
+ no = o->parent();
+ while (no && !no->nextSibling())
+ no = no->parent();
+ if (no)
+ no = no->nextSibling();
+ }
+ if (o->selectionState() == SelectionInside && !newSelectedInside.containsRef(o))
+ newSelectedInside.append(o);
+
+ o=no;
+ }
+ s->setSelectionState(SelectionStart);
+ e->setSelectionState(SelectionEnd);
+ if(s == e) s->setSelectionState(SelectionBoth);
+
+ if (!m_view)
+ return;
+
+ newSelectedInside.removeRef(s);
+ newSelectedInside.removeRef(e);
+
+ TQRect updateRect;
+
+ // Don't use repaint() because it will cause all rects to
+ // be united (see tdehtmlview::scheduleRepaint()). Instead
+ // just draw damage rects for objects that have a change
+ // in selection state.
+ // ### for Qt, updateContents will unite them, too. This has to be
+ // circumvented somehow (LS)
+
+ // Are any of the old fully selected objects not in the new selection?
+ // If so we have to draw them.
+ // Could be faster by building list of non-intersecting rectangles rather
+ // than unioning rectangles.
+ TQPtrListIterator<RenderObject> oldIterator(oldSelectedInside);
+ bool firstRect = true;
+ for (; oldIterator.current(); ++oldIterator){
+ if (!newSelectedInside.containsRef(oldIterator.current())){
+ if (firstRect){
+ updateRect = enclosingPositionedRect(oldIterator.current());
+ firstRect = false;
+ }
+ else
+ updateRect = updateRect.unite(enclosingPositionedRect(oldIterator.current()));
+ }
+ }
+ if (!firstRect){
+ m_view->updateContents( updateRect );
+ }
+
+ // Are any of the new fully selected objects not in the previous selection?
+ // If so we have to draw them.
+ // Could be faster by building list of non-intersecting rectangles rather
+ // than unioning rectangles.
+ TQPtrListIterator<RenderObject> newIterator(newSelectedInside);
+ firstRect = true;
+ for (; newIterator.current(); ++newIterator){
+ if (!oldSelectedInside.containsRef(newIterator.current())){
+ if (firstRect){
+ updateRect = enclosingPositionedRect(newIterator.current());
+ firstRect = false;
+ }
+ else
+ updateRect = updateRect.unite(enclosingPositionedRect(newIterator.current()));
+ }
+ }
+ if (!firstRect) {
+ m_view->updateContents( updateRect );
+ }
+
+ // Is the new starting object different, or did the position in the starting
+ // element change? If so we have to draw it.
+ if (oldStart != m_selectionStart ||
+ (oldStart == oldEnd && (oldStartPos != m_selectionStartPos || oldEndPos != m_selectionEndPos)) ||
+ (oldStart == m_selectionStart && oldStartPos != m_selectionStartPos)){
+ m_view->updateContents( enclosingPositionedRect(m_selectionStart) );
+ }
+
+ // Draw the old selection start object if it's different than the new selection
+ // start object.
+ if (oldStart && oldStart != m_selectionStart){
+ m_view->updateContents( enclosingPositionedRect(oldStart) );
+ }
+
+ // Does the selection span objects and is the new end object different, or did the position
+ // in the end element change? If so we have to draw it.
+ if (/*(oldStart != oldEnd || !oldEnd) &&*/
+ (oldEnd != m_selectionEnd ||
+ (oldEnd == m_selectionEnd && oldEndPos != m_selectionEndPos))){
+ m_view->updateContents( enclosingPositionedRect(m_selectionEnd) );
+ }
+
+ // Draw the old selection end object if it's different than the new selection
+ // end object.
+ if (oldEnd && oldEnd != m_selectionEnd){
+ m_view->updateContents( enclosingPositionedRect(oldEnd) );
+ }
+}
+
+void RenderCanvas::clearSelection(bool doRepaint)
+{
+ // update selection status of all objects between m_selectionStart and m_selectionEnd
+ RenderObject* o = m_selectionStart;
+ while (o && o!=m_selectionEnd)
+ {
+ if (o->selectionState()!=SelectionNone)
+ if (doRepaint)
+ o->repaint();
+ o->setSelectionState(SelectionNone);
+ o->repaint();
+ RenderObject* no;
+ if ( !(no = o->firstChild()) )
+ if ( !(no = o->nextSibling()) )
+ {
+ no = o->parent();
+ while (no && !no->nextSibling())
+ no = no->parent();
+ if (no)
+ no = no->nextSibling();
+ }
+ o=no;
+ }
+ if (m_selectionEnd) {
+ m_selectionEnd->setSelectionState(SelectionNone);
+ if (doRepaint)
+ m_selectionEnd->repaint();
+ }
+
+ // set selection start & end to 0
+ if (m_selectionStart)
+ m_selectionStart->setIsSelectionBorder(false);
+ m_selectionStart = 0;
+ m_selectionStartPos = -1;
+
+ if (m_selectionEnd)
+ m_selectionEnd->setIsSelectionBorder(false);
+ m_selectionEnd = 0;
+ m_selectionEndPos = -1;
+}
+
+void RenderCanvas::selectionStartEnd(int& spos, int& epos)
+{
+ spos = m_selectionStartPos;
+ epos = m_selectionEndPos;
+}
+
+TQRect RenderCanvas::viewRect() const
+{
+ if (m_pagedMode)
+ if (m_pageTop == m_pageBottom) {
+ kdDebug(6040) << "viewRect: " << TQRect(0, m_pageTop, m_width, m_height) << endl;
+ return TQRect(0, m_pageTop, m_width, m_height);
+ }
+ else {
+ kdDebug(6040) << "viewRect: " << TQRect(0, m_pageTop, m_width, m_pageBottom - m_pageTop) << endl;
+ return TQRect(0, m_pageTop, m_width, m_pageBottom - m_pageTop);
+ }
+ else if (m_view)
+ return TQRect(m_view->contentsX(),
+ m_view->contentsY(),
+ m_view->visibleWidth(),
+ m_view->visibleHeight());
+ else
+ return TQRect(0,0,m_rootWidth,m_rootHeight);
+}
+
+int RenderCanvas::docHeight() const
+{
+ if (m_cachedDocHeight != -1)
+ return m_cachedDocHeight;
+
+ int h;
+ if (m_pagedMode || !m_view)
+ h = m_height;
+ else
+ h = 0;
+
+ RenderObject *fc = firstChild();
+ if(fc) {
+ int dh = fc->overflowHeight() + fc->marginTop() + fc->marginBottom();
+ int lowestPos = fc->lowestPosition(false);
+// kdDebug(6040) << "h " << h << " lowestPos " << lowestPos << " dh " << dh << " fc->rh " << fc->effectiveHeight() << " fc->height() " << fc->height() << endl;
+ if( lowestPos > dh )
+ dh = lowestPos;
+ lowestPos = lowestAbsolutePosition();
+ if( lowestPos > dh )
+ dh = lowestPos;
+ if( dh > h )
+ h = dh;
+ }
+
+ RenderLayer *layer = m_layer;
+ h = kMax( h, layer->yPos() + layer->height() );
+// kdDebug(6040) << "h " << h << " layer(" << layer->renderer()->renderName() << "@" << layer->renderer() << ")->height " << layer->height() << " lp " << (layer->yPos() + layer->height()) << " height() " << layer->renderer()->height() << " rh " << layer->renderer()->effectiveHeight() << endl;
+ return h;
+}
+
+int RenderCanvas::docWidth() const
+{
+ if (m_cachedDocWidth != -1)
+ return m_cachedDocWidth;
+
+ int w;
+ if (m_pagedMode || !m_view)
+ w = m_width;
+ else
+ w = 0;
+
+ RenderObject *fc = firstChild();
+ if(fc) {
+ // ow: like effectiveWidth() but without the negative
+ const int ow = fc->hasOverflowClip() ? fc->width() : fc->overflowWidth();
+ int dw = ow + fc->marginLeft() + fc->marginRight();
+ int rightmostPos = fc->rightmostPosition(false);
+// kdDebug(6040) << "w " << w << " rightmostPos " << rightmostPos << " dw " << dw << " fc->rw " << fc->effectiveWidth() << " fc->width() " << fc->width() << endl;
+ if( rightmostPos > dw )
+ dw = rightmostPos;
+ rightmostPos = rightmostAbsolutePosition();
+ if ( rightmostPos > dw )
+ dw = rightmostPos;
+ if( dw > w )
+ w = dw;
+ }
+
+ RenderLayer *layer = m_layer;
+ w = kMax( w, layer->xPos() + layer->width() );
+// kdDebug(6040) << "w " << w << " layer(" << layer->renderer()->renderName() << ")->width " << layer->width() << " rm " << (layer->xPos() + layer->width()) << " width() " << layer->renderer()->width() << " rw " << layer->renderer()->effectiveWidth() << endl;
+ return w;
+}
+
+RenderPage* RenderCanvas::page() {
+ if (!m_page) m_page = new RenderPage(this);
+ return m_page;
+}
diff --git a/tdehtml/rendering/render_canvas.h b/tdehtml/rendering/render_canvas.h
new file mode 100644
index 000000000..8495b87bc
--- /dev/null
+++ b/tdehtml/rendering/render_canvas.h
@@ -0,0 +1,250 @@
+/*
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2005 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.
+ *
+ */
+#ifndef render_canvas_h
+#define render_canvas_h
+
+#include "render_block.h"
+
+class KHTMLView;
+class TQScrollView;
+
+namespace tdehtml {
+
+class RenderPage;
+class RenderStyle;
+
+enum CanvasMode {
+ CanvasViewPort, // Paints inside a viewport
+ CanvasPage, // Paints one page
+ CanvasDocument // Paints the whole document
+};
+
+class RenderCanvas : public RenderBlock
+{
+public:
+ RenderCanvas(DOM::NodeImpl* node, KHTMLView *view);
+ ~RenderCanvas();
+
+ virtual const char *renderName() const { return "RenderCanvas"; }
+
+ virtual bool isCanvas() const { return true; }
+
+ virtual void setStyle(RenderStyle *style);
+ virtual void layout();
+ virtual void calcWidth();
+ virtual void calcHeight();
+ virtual void calcMinMaxWidth();
+ virtual bool absolutePosition(int &xPos, int&yPos, bool f = false) const;
+
+ int docHeight() const;
+ int docWidth() const;
+
+ KHTMLView *view() const { return m_view; }
+
+ virtual void repaint(Priority p=NormalPriority);
+ virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
+ void repaintViewRectangle(int x, int y, int w, int h, bool asap=false);
+ bool needsFullRepaint() const;
+ void deferredRepaint( RenderObject* o );
+ void scheduleDeferredRepaints();
+
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty);
+ virtual void setSelection(RenderObject *s, int sp, RenderObject *e, int ep);
+ virtual void clearSelection(bool doRepaint=true);
+ virtual RenderObject *selectionStart() const { return m_selectionStart; }
+ virtual RenderObject *selectionEnd() const { return m_selectionEnd; }
+
+ void setPrintImages(bool enable) { m_printImages = enable; }
+ bool printImages() const { return m_printImages; }
+
+ void setCanvasMode(CanvasMode mode) { m_canvasMode = mode; }
+ CanvasMode canvasMode() const { return m_canvasMode; }
+
+ void setPagedMode(bool b) { m_pagedMode = b; }
+ void setStaticMode(bool b) { m_staticMode = b; }
+
+ bool pagedMode() const { return m_pagedMode; }
+ bool staticMode() const { return m_staticMode; }
+
+ void setPageTop(int top) {
+ m_pageTop = top;
+// m_y = top;
+ }
+ void setPageBottom(int bottom) { m_pageBottom = bottom; }
+ int pageTop() const { return m_pageTop; }
+ int pageBottom() const { return m_pageBottom; }
+
+ int pageTopAfter(int y) const {
+ if (pageHeight() == 0) return 0;
+ return (y / pageHeight() + 1) * pageHeight() ;
+ }
+
+ int crossesPageBreak(int top, int bottom) const {
+ if (pageHeight() == 0) return false;
+ int pT = top / pageHeight();
+ // bottom is actually the first line not in the box
+ int pB = (bottom-1) / pageHeight();
+ return (pT == pB) ? 0 : (pB + 1);
+ }
+
+ void setPageNumber(int number) { m_pageNr = number; }
+ int pageNumber() const { return m_pageNr; }
+
+public:
+ virtual void setWidth( int width ) { m_rootWidth = m_width = width; }
+ virtual void setHeight( int height ) { m_rootHeight = m_height = height; }
+
+// void setPageHeight( int height ) { m_viewportHeight = m_pageHeight = height; }
+ int pageHeight() const { return m_pageBottom - m_pageTop; }
+
+ int viewportWidth() const { return m_viewportWidth; }
+ int viewportHeight() const { return m_viewportHeight; }
+
+ RenderPage* page();
+
+ TQRect selectionRect() const;
+
+ void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; }
+ int maximalOutlineSize() const { return m_maximalOutlineSize; }
+
+ void setNeedsWidgetMasks( bool b=true) { m_needsWidgetMasks = b; }
+ bool needsWidgetMasks() const { return m_needsWidgetMasks; }
+
+ void updateDocSizeAfterLayerTranslation( RenderObject* o, bool posXOffset, bool posYOffset );
+protected:
+ // makes sure document, scrollbars and viewport size are accurate
+ void updateDocumentSize();
+
+ // internal setters for cached values of document width/height
+ // Setting to -1/-1 invalidates the cache.
+ void setCachedDocWidth(int w ) { m_cachedDocWidth = w; }
+ void setCachedDocHeight(int h) { m_cachedDocHeight = h; }
+
+ virtual void selectionStartEnd(int& spos, int& epos);
+
+ virtual TQRect viewRect() const;
+
+ KHTMLView *m_view;
+
+ RenderObject* m_selectionStart;
+ RenderObject* m_selectionEnd;
+ int m_selectionStartPos;
+ int m_selectionEndPos;
+
+ CanvasMode m_canvasMode;
+
+ int m_rootWidth;
+ int m_rootHeight;
+
+ int m_viewportWidth;
+ int m_viewportHeight;
+
+ int m_cachedDocWidth;
+ int m_cachedDocHeight;
+
+ bool m_printImages;
+ bool m_needsFullRepaint;
+
+ // Canvas is not interactive
+ bool m_staticMode;
+ // Canvas is paged
+ bool m_pagedMode;
+ // Canvas contains overlaid widgets
+ bool m_needsWidgetMasks;
+
+ short m_pageNr;
+
+ int m_pageTop;
+ int m_pageBottom;
+
+ RenderPage* m_page;
+
+ int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+ TQValueList<RenderObject*> m_dirtyChildren;
+};
+
+inline RenderCanvas* RenderObject::canvas() const
+{
+ return static_cast<RenderCanvas*>(document()->renderer());
+}
+
+// Represents the page-context of CSS
+class RenderPage
+{
+public:
+ RenderPage(RenderCanvas* canvas) : m_canvas(canvas),
+ m_marginTop(0), m_marginBottom(0),
+ m_marginLeft(0), m_marginRight(0),
+ m_pageWidth(0), m_pageHeight(0),
+ m_fixedSize(false)
+ {
+ m_style = new RenderPageStyle();
+ }
+ virtual ~RenderPage()
+ {
+ delete m_style;
+ }
+
+ int marginTop() const { return m_marginTop; }
+ int marginBottom() const { return m_marginBottom; }
+ int marginLeft() const { return m_marginLeft; }
+ int marginRight() const { return m_marginRight; }
+
+ void setMarginTop(int margin) { m_marginTop = margin; }
+ void setMarginBottom(int margin) { m_marginBottom = margin; }
+ void setMarginLeft(int margin) { m_marginLeft = margin; }
+ void setMarginRight(int margin) { m_marginRight = margin; }
+
+ int pageWidth() const { return m_pageWidth; }
+ int pageHeight() const { return m_pageHeight; }
+
+ void setPageSize(int width, int height) {
+ m_pageWidth = width;
+ m_pageHeight = height;
+ }
+
+ // Returns true if size was set by document, false if set by user-agent
+ bool fixedSize() const { return m_fixedSize; }
+ void setFixedSize(bool b) { m_fixedSize = b; }
+
+ RenderPageStyle* style() { return m_style; }
+ const RenderPageStyle* style() const { return m_style; }
+
+protected:
+ RenderCanvas* m_canvas;
+ RenderPageStyle* m_style;
+
+ int m_marginTop;
+ int m_marginBottom;
+ int m_marginLeft;
+ int m_marginRight;
+
+ int m_pageWidth;
+ int m_pageHeight;
+
+ bool m_fixedSize;
+};
+
+}
+#endif
diff --git a/tdehtml/rendering/render_container.cpp b/tdehtml/rendering/render_container.cpp
new file mode 100644
index 000000000..b91bc91df
--- /dev/null
+++ b/tdehtml/rendering/render_container.cpp
@@ -0,0 +1,597 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2001-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2001 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000-2003 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.
+ *
+ */
+
+//#define DEBUG_LAYOUT
+
+#include "rendering/render_container.h"
+#include "rendering/render_table.h"
+#include "rendering/render_text.h"
+#include "rendering/render_image.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_generated.h"
+#include "rendering/render_inline.h"
+#include "xml/dom_docimpl.h"
+#include "css/css_valueimpl.h"
+
+#include <kdebug.h>
+#include <assert.h>
+
+using namespace tdehtml;
+
+RenderContainer::RenderContainer(DOM::NodeImpl* node)
+ : RenderObject(node)
+{
+ m_first = 0;
+ m_last = 0;
+}
+
+void RenderContainer::detach()
+{
+ if (continuation())
+ continuation()->detach();
+
+ // We simulate removeNode calls for all our children
+ // and set parent to 0 to avoid removeNode from being called.
+ // First call removeLayers and removeFromObjectLists since they assume
+ // a valid render-tree
+ for(RenderObject* n = m_first; n; n = n->nextSibling() ) {
+ n->removeLayers(enclosingLayer());
+ n->removeFromObjectLists();
+ }
+
+ RenderObject* next;
+ for(RenderObject* n = m_first; n; n = next ) {
+ n->setParent(0);
+ next = n->nextSibling();
+ n->detach();
+ }
+ m_first = 0;
+ m_last = 0;
+
+ RenderObject::detach();
+}
+
+void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject)::addChild( " << newChild << ": " <<
+ newChild->renderName() << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
+#endif
+ // protect ourselves from deletion
+ setDoNotDelete(true);
+
+ bool needsTable = false;
+
+ if(!newChild->isText() && !newChild->isReplaced()) {
+ switch(newChild->style()->display()) {
+ case INLINE:
+ case BLOCK:
+ case LIST_ITEM:
+ case RUN_IN:
+ case COMPACT:
+ case INLINE_BLOCK:
+ case TABLE:
+ case INLINE_TABLE:
+ break;
+ case TABLE_COLUMN:
+ if ( isTableCol() )
+ break;
+ // nobreak
+ case TABLE_COLUMN_GROUP:
+ case TABLE_CAPTION:
+ case TABLE_ROW_GROUP:
+ case TABLE_HEADER_GROUP:
+ case TABLE_FOOTER_GROUP:
+
+ //kdDebug( 6040 ) << "adding section" << endl;
+ if ( !isTable() )
+ needsTable = true;
+ break;
+ case TABLE_ROW:
+ //kdDebug( 6040 ) << "adding row" << endl;
+ if ( !isTableSection() )
+ needsTable = true;
+ break;
+ case TABLE_CELL:
+ //kdDebug( 6040 ) << "adding cell" << endl;
+ if ( !isTableRow() )
+ needsTable = true;
+ // I'm not 100% sure this is the best way to fix this, but without this
+ // change we recurse infinitely when trying to render the CSS2 test page:
+ // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
+ if ( isTableCell() && !firstChild() && !newChild->isTableCell() )
+ needsTable = false;
+
+ break;
+ case NONE:
+ // RenderHtml and some others can have display:none
+ // KHTMLAssert(false);
+ break;
+ }
+ }
+
+ if ( needsTable ) {
+ RenderTable *table;
+ RenderObject *last = beforeChild ? beforeChild->previousSibling() : lastChild();
+ if ( last && last->isTable() && last->isAnonymous() ) {
+ table = static_cast<RenderTable *>(last);
+ } else {
+ //kdDebug( 6040 ) << "creating anonymous table, before=" << beforeChild << endl;
+ table = new (renderArena()) RenderTable(document() /* is anonymous */);
+ RenderStyle *newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay( TABLE );
+ newStyle->setFlowAroundFloats( true );
+ table->setParent( this ); // so it finds the arena
+ table->setStyle(newStyle);
+ table->setParent( 0 );
+ addChild(table, beforeChild);
+ }
+ table->addChild(newChild);
+ } else {
+ // just add it...
+ insertChildNode(newChild, beforeChild);
+ }
+
+ if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
+ DOM::DOMStringImpl* textToTransform = static_cast<RenderText*>(newChild)->originalString();
+ if (textToTransform)
+ static_cast<RenderText*>(newChild)->setText(textToTransform, true);
+ }
+ newChild->attach();
+
+ setDoNotDelete(false);
+}
+
+RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
+{
+ KHTMLAssert(oldChild->parent() == this);
+
+ // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+ // that a positioned child got yanked). We also repaint, so that the area exposed when the child
+ // disappears gets repainted properly.
+ if ( document()->renderer() ) {
+ oldChild->setNeedsLayoutAndMinMaxRecalc();
+ oldChild->repaint();
+
+ // Keep our layer hierarchy updated.
+ oldChild->removeLayers(enclosingLayer());
+ // remove the child from any special layout lists
+ oldChild->removeFromObjectLists();
+
+ // if oldChild is the start or end of the selection, then clear
+ // the selection to avoid problems of invalid pointers
+
+ // ### This is not the "proper" solution... ideally the selection
+ // ### should be maintained based on DOM Nodes and a Range, which
+ // ### gets adjusted appropriately when nodes are deleted/inserted
+ // ### near etc. But this at least prevents crashes caused when
+ // ### the start or end of the selection is deleted and then
+ // ### accessed when the user next selects something.
+
+ if (oldChild->isSelectionBorder()) {
+ RenderObject *root = oldChild;
+ while (root->parent())
+ root = root->parent();
+ if (root->isCanvas()) {
+ static_cast<RenderCanvas*>(root)->clearSelection();
+ }
+ }
+ }
+
+ // remove the child from the render-tree
+ if (oldChild->previousSibling())
+ oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+ if (oldChild->nextSibling())
+ oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+ if (m_first == oldChild)
+ m_first = oldChild->nextSibling();
+ if (m_last == oldChild)
+ m_last = oldChild->previousSibling();
+
+ oldChild->setPreviousSibling(0);
+ oldChild->setNextSibling(0);
+ oldChild->setParent(0);
+
+ return oldChild;
+}
+
+void RenderContainer::setStyle(RenderStyle* _style)
+{
+ RenderObject::setStyle(_style);
+
+ // If we are a pseudo-container we need to restyle the children
+ if (style()->isGenerated())
+ {
+ // ### we could save this call when the change only affected
+ // non inherited properties
+ RenderStyle *pseudoStyle = new RenderStyle();
+ pseudoStyle->inheritFrom(style());
+ pseudoStyle->ref();
+ RenderObject *child = firstChild();
+ while (child != 0)
+ {
+ child->setStyle(pseudoStyle);
+ child = child->nextSibling();
+ }
+ pseudoStyle->deref();
+ }
+}
+
+void RenderContainer::updatePseudoChildren()
+{
+ // In CSS2, before/after pseudo-content cannot nest. Check this first.
+ // Remove when CSS 3 Generated Content becomes Candidate Recommendation
+ if (style()->styleType() == RenderStyle::BEFORE
+ || style()->styleType() == RenderStyle::AFTER)
+ return;
+
+ updatePseudoChild(RenderStyle::BEFORE);
+ updatePseudoChild(RenderStyle::AFTER);
+ // updatePseudoChild(RenderStyle::MARKER, marker());
+}
+
+void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type)
+{
+ // The head manages generated content for its continuations
+ if (isInlineContinuation()) return;
+
+ RenderStyle* pseudo = style()->getPseudoStyle(type);
+
+ RenderObject* child = pseudoContainer(type);
+
+ // Whether or not we currently have generated content attached.
+ bool oldContentPresent = child && (child->style()->styleType() == type);
+
+ // Whether or not we now want generated content.
+ bool newContentWanted = pseudo && pseudo->display() != NONE;
+
+ // No generated content
+ if (!oldContentPresent && !newContentWanted)
+ return;
+
+ bool movedContent = (type == RenderStyle::AFTER && isRenderInline() && continuation());
+
+ // Whether or not we want the same old content.
+ bool sameOldContent = oldContentPresent && newContentWanted && !movedContent
+ && (child->style()->contentDataEquivalent(pseudo));
+
+ // No change in content, update style
+ if( sameOldContent ) {
+ child->setStyle(pseudo);
+ return;
+ }
+
+ // If we don't want generated content any longer, or if we have generated content,
+ // but it's no longer identical to the new content data we want to build
+ // render objects for, then we nuke all of the old generated content.
+ if (oldContentPresent && (!newContentWanted || !sameOldContent))
+ {
+ // The child needs to be removed.
+ oldContentPresent = false;
+ child->detach();
+ child = 0;
+ }
+
+ // If we have no pseudo-style or if the pseudo's display type is NONE, then we
+ // have no generated content and can now return.
+ if (!newContentWanted)
+ return;
+
+ // Generated content consists of a single container that houses multiple children (specified
+ // by the content property). This pseudo container gets the pseudo style set on it.
+ RenderContainer* pseudoContainer = 0;
+ pseudoContainer = RenderFlow::createFlow(element(), pseudo, renderArena());
+ pseudoContainer->setIsAnonymous( true );
+ pseudoContainer->createGeneratedContent();
+
+ // Only add the container if it had content
+ if (pseudoContainer->firstChild()) {
+ addPseudoContainer(pseudoContainer);
+ pseudoContainer->close();
+ }
+}
+
+void RenderContainer::createGeneratedContent()
+{
+ RenderStyle* pseudo = style();
+ RenderStyle* style = new RenderStyle();
+ style->ref();
+ style->inheritFrom(pseudo);
+
+ // Now walk our list of generated content and create render objects for every type
+ // we encounter.
+ for (ContentData* contentData = pseudo->contentData();
+ contentData; contentData = contentData->_nextContent)
+ {
+ if (contentData->_contentType == CONTENT_TEXT)
+ {
+ RenderText* t = new (renderArena()) RenderText( node(), 0);
+ t->setIsAnonymous( true );
+ t->setStyle(style);
+ t->setText(contentData->contentText());
+ addChild(t);
+ }
+ else if (contentData->_contentType == CONTENT_OBJECT)
+ {
+ RenderImage* img = new (renderArena()) RenderImage(node());
+ img->setIsAnonymous( true );
+ img->setStyle(style);
+ img->setContentObject(contentData->contentObject());
+ addChild(img);
+ }
+ else if (contentData->_contentType == CONTENT_COUNTER)
+ {
+ // really a counter or just a glyph?
+ EListStyleType type = (EListStyleType)contentData->contentCounter()->listStyle();
+ RenderObject *t = 0;
+ if (isListStyleCounted(type)) {
+ t = new (renderArena()) RenderCounter( node(), contentData->contentCounter() );
+ }
+ else {
+ t = new (renderArena()) RenderGlyph( node(), type );
+ }
+ t->setIsAnonymous( true );
+ t->setStyle(style);
+ addChild(t);
+ }
+ else if (contentData->_contentType == CONTENT_QUOTE)
+ {
+ RenderQuote* t = new (renderArena()) RenderQuote( node(), contentData->contentQuote() );
+ t->setIsAnonymous( true );
+ t->setStyle(style);
+ addChild(t);
+ }
+ }
+ style->deref();
+}
+
+RenderContainer* RenderContainer::pseudoContainer(RenderStyle::PseudoId type) const
+{
+ RenderObject *child = 0;
+ switch (type) {
+ case RenderStyle::AFTER:
+ child = lastChild();
+ break;
+ case RenderStyle::BEFORE:
+ child = firstChild();
+ break;
+ case RenderStyle::REPLACED:
+ child = lastChild();
+ if (child && child->style()->styleType() == RenderStyle::AFTER)
+ child = child->previousSibling();
+ break;
+ default:
+ child = 0;
+ }
+
+ if (child && child->style()->styleType() == type) {
+ assert(child->isRenderBlock() || child->isRenderInline());
+ return static_cast<RenderContainer*>(child);
+ }
+ if (type == RenderStyle::AFTER) {
+ // check continuations
+ if (continuation())
+ return continuation()->pseudoContainer(type);
+ }
+ if (child && child->isAnonymousBlock())
+ return static_cast<RenderBlock*>(child)->pseudoContainer(type);
+ return 0;
+}
+
+void RenderContainer::addPseudoContainer(RenderObject* child)
+{
+ RenderStyle::PseudoId type = child->style()->styleType();
+ switch (type) {
+ case RenderStyle::AFTER: {
+ RenderObject *o = this;
+ while (o->continuation()) o = o->continuation();
+
+ // Coalesce inlines
+ if (child->style()->display() == INLINE && o->lastChild() && o->lastChild()->isAnonymousBlock()) {
+ o->lastChild()->addChild(child, 0);
+ } else
+ o->addChild(child, 0);
+ break;
+ }
+ case RenderStyle::BEFORE:
+ // Coalesce inlines
+ if (child->style()->display() == INLINE && firstChild() && firstChild()->isAnonymousBlock()) {
+ firstChild()->addChild(child, firstChild()->firstChild());
+ } else
+ addChild(child, firstChild());
+ break;
+ case RenderStyle::REPLACED:
+ addChild(child, pseudoContainer(RenderStyle::AFTER));
+ break;
+ default:
+ break;
+ }
+}
+
+void RenderContainer::updateReplacedContent()
+{
+ // Only for normal elements
+ if (!style() || style()->styleType() != RenderStyle::NOPSEUDO)
+ return;
+
+ // delete old generated content
+ RenderContainer *container = pseudoContainer(RenderStyle::REPLACED);
+ if (container) {
+ container->detach();
+ }
+
+ if (style()->useNormalContent()) return;
+
+ // create generated content
+ RenderStyle* pseudo = style()->getPseudoStyle(RenderStyle::REPLACED);
+ if (!pseudo) {
+ pseudo = new RenderStyle();
+ pseudo->inheritFrom(style());
+ pseudo->setStyleType(RenderStyle::REPLACED);
+ }
+ if (pseudo->useNormalContent())
+ pseudo->setContentData(style()->contentData());
+
+ container = RenderFlow::createFlow(node(), pseudo, renderArena());
+ container->setIsAnonymous( true );
+ container->createGeneratedContent();
+
+ addChild(container, pseudoContainer(RenderStyle::AFTER));
+}
+
+void RenderContainer::appendChildNode(RenderObject* newChild)
+{
+ KHTMLAssert(newChild->parent() == 0);
+
+ newChild->setParent(this);
+ RenderObject* lChild = lastChild();
+
+ if(lChild)
+ {
+ newChild->setPreviousSibling(lChild);
+ lChild->setNextSibling(newChild);
+ }
+ else
+ setFirstChild(newChild);
+
+ setLastChild(newChild);
+
+ // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
+ // and don't have a layer attached to ourselves.
+ if (newChild->firstChild() || newChild->layer()) {
+ RenderLayer* layer = enclosingLayer();
+ newChild->addLayers(layer, newChild);
+ }
+
+ newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy.
+ if (!normalChildNeedsLayout())
+ setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+}
+
+void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
+{
+ if(!beforeChild) {
+ appendChildNode(child);
+ return;
+ }
+
+ KHTMLAssert(!child->parent());
+ while ( beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock() )
+ beforeChild = beforeChild->parent();
+ KHTMLAssert(beforeChild->parent() == this);
+
+ if(beforeChild == firstChild())
+ setFirstChild(child);
+
+ RenderObject* prev = beforeChild->previousSibling();
+ child->setNextSibling(beforeChild);
+ beforeChild->setPreviousSibling(child);
+ if(prev) prev->setNextSibling(child);
+ child->setPreviousSibling(prev);
+ child->setParent(this);
+
+ // Keep our layer hierarchy updated.
+ RenderLayer* layer = enclosingLayer();
+ child->addLayers(layer, child);
+
+ child->setNeedsLayoutAndMinMaxRecalc();
+ if (!normalChildNeedsLayout())
+ setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+}
+
+
+void RenderContainer::layout()
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+ const bool pagedMode = canvas()->pagedMode();
+ RenderObject *child = firstChild();
+ while( child ) {
+ if (pagedMode) child->setNeedsLayout(true);
+ child->layoutIfNeeded();
+ if (child->containsPageBreak()) setContainsPageBreak(true);
+ if (child->needsPageClear()) setNeedsPageClear(true);
+ child = child->nextSibling();
+ }
+ setNeedsLayout(false);
+}
+
+void RenderContainer::removeLeftoverAnonymousBoxes()
+{
+ // we have to go over all child nodes and remove anonymous boxes, that do _not_
+ // have inline children to keep the tree flat
+ RenderObject *child = firstChild();
+ while( child ) {
+ RenderObject *next = child->nextSibling();
+
+ if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() &&
+ !child->childrenInline() && !child->isTableCell() && !child->doNotDelete()) {
+ RenderObject *firstAnChild = child->firstChild();
+ RenderObject *lastAnChild = child->lastChild();
+ if ( firstAnChild ) {
+ RenderObject *o = firstAnChild;
+ while( o ) {
+ o->setParent( this );
+ o = o->nextSibling();
+ }
+ firstAnChild->setPreviousSibling( child->previousSibling() );
+ lastAnChild->setNextSibling( child->nextSibling() );
+ if ( child->previousSibling() )
+ child->previousSibling()->setNextSibling( firstAnChild );
+ if ( child->nextSibling() )
+ child->nextSibling()->setPreviousSibling( lastAnChild );
+ if ( child == firstChild() )
+ m_first = firstAnChild;
+ if ( child == lastChild() )
+ m_last = lastAnChild;
+ } else {
+ if ( child->previousSibling() )
+ child->previousSibling()->setNextSibling( child->nextSibling() );
+ if ( child->nextSibling() )
+ child->nextSibling()->setPreviousSibling( child->previousSibling() );
+ if ( child == firstChild() )
+ m_first = child->nextSibling();
+ if ( child == lastChild() )
+ m_last = child->previousSibling();
+ }
+ child->setParent( 0 );
+ child->setPreviousSibling( 0 );
+ child->setNextSibling( 0 );
+ if ( !child->isText() ) {
+ RenderContainer *c = static_cast<RenderContainer *>(child);
+ c->m_first = 0;
+ c->m_next = 0;
+ }
+ child->detach();
+ }
+ child = next;
+ }
+ if ( parent() )
+ parent()->removeLeftoverAnonymousBoxes();
+}
+
+#undef DEBUG_LAYOUT
diff --git a/tdehtml/rendering/render_container.h b/tdehtml/rendering/render_container.h
new file mode 100644
index 000000000..44ff88384
--- /dev/null
+++ b/tdehtml/rendering/render_container.h
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2001 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 render_container_h
+#define render_container_h
+
+#include "render_object.h"
+
+namespace tdehtml
+{
+
+
+/**
+ * Base class for rendering objects that can have children
+ */
+class RenderContainer : public RenderObject
+{
+public:
+ RenderContainer(DOM::NodeImpl* node);
+
+ void detach();
+
+ RenderObject *firstChild() const { return m_first; }
+ RenderObject *lastChild() const { return m_last; }
+
+ virtual bool childAllowed() const {
+ // Prevent normal children when we are replaced by generated content
+ if (style()) return style()->useNormalContent();
+ return true;
+ }
+
+ virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
+
+ virtual RenderObject* removeChildNode(RenderObject* child);
+ virtual void appendChildNode(RenderObject* child);
+ virtual void insertChildNode(RenderObject* child, RenderObject* before);
+
+ virtual void layout();
+ virtual void calcMinMaxWidth() { setMinMaxKnown( true ); }
+
+ virtual void removeLeftoverAnonymousBoxes();
+
+ virtual void setStyle(RenderStyle* _style);
+
+protected:
+ // Generate CSS content
+ void createGeneratedContent();
+ void updateReplacedContent();
+
+ void updatePseudoChildren();
+ void updatePseudoChild(RenderStyle::PseudoId type);
+
+ RenderContainer* pseudoContainer( RenderStyle::PseudoId type ) const;
+ void addPseudoContainer(RenderObject* child);
+private:
+
+ void setFirstChild(RenderObject *first) { m_first = first; }
+ void setLastChild(RenderObject *last) { m_last = last; }
+
+protected:
+
+ RenderObject *m_first;
+ RenderObject *m_last;
+};
+
+}
+#endif
diff --git a/tdehtml/rendering/render_flow.cpp b/tdehtml/rendering/render_flow.cpp
new file mode 100644
index 000000000..71456d0a8
--- /dev/null
+++ b/tdehtml/rendering/render_flow.cpp
@@ -0,0 +1,412 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2003-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.
+ */
+// -------------------------------------------------------------------------
+
+#include <kdebug.h>
+#include <assert.h>
+#include <tqpainter.h>
+#include <kglobal.h>
+
+#include "rendering/render_flow.h"
+#include "rendering/render_text.h"
+#include "rendering/render_table.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_inline.h"
+#include "rendering/render_block.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_line.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmltags.h"
+#include "html/html_formimpl.h"
+
+#include "tdehtmlview.h"
+
+using namespace DOM;
+using namespace tdehtml;
+
+RenderFlow* RenderFlow::createFlow(DOM::NodeImpl* node, RenderStyle* style, RenderArena* arena)
+{
+ RenderFlow* result;
+ if (style->display() == INLINE)
+ result = new (arena) RenderInline(node);
+ else
+ result = new (arena) RenderBlock(node);
+ result->setStyle(style);
+ return result;
+}
+
+RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
+{
+ if (beforeChild && beforeChild->parent() == this)
+ return this;
+
+ RenderFlow* curr = continuation();
+ RenderFlow* nextToLast = this;
+ RenderFlow* last = this;
+ while (curr) {
+ if (beforeChild && beforeChild->parent() == curr) {
+ if (curr->firstChild() == beforeChild)
+ return last;
+ return curr;
+ }
+
+ nextToLast = last;
+ last = curr;
+ curr = curr->continuation();
+ }
+
+ if (!beforeChild && !last->firstChild())
+ return nextToLast;
+ return last;
+}
+
+void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
+{
+ RenderFlow* flow = continuationBefore(beforeChild);
+ while(beforeChild && beforeChild->parent() != flow && !beforeChild->parent()->isAnonymousBlock()) {
+ // skip implicit containers around beforeChild
+ beforeChild = beforeChild->parent();
+ }
+ RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) :
+ (flow->continuation() ? flow->continuation() : flow);
+
+ if (newChild->isFloatingOrPositioned())
+ return beforeChildParent->addChildToFlow(newChild, beforeChild);
+
+ // A continuation always consists of two potential candidates: an inline or an anonymous
+ // block box holding block children.
+ bool childInline = newChild->isInline();
+ bool bcpInline = beforeChildParent->isInline();
+ bool flowInline = flow->isInline();
+
+ if (flow == beforeChildParent)
+ return flow->addChildToFlow(newChild, beforeChild);
+ else {
+ // The goal here is to match up if we can, so that we can coalesce and create the
+ // minimal # of continuations needed for the inline.
+ if (childInline == bcpInline)
+ return beforeChildParent->addChildToFlow(newChild, beforeChild);
+ else if (flowInline == childInline)
+ return flow->addChildToFlow(newChild, 0); // Just treat like an append.
+ else
+ return beforeChildParent->addChildToFlow(newChild, beforeChild);
+ }
+}
+
+void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderFlow)::addChild( " << newChild->renderName() <<
+ ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
+ kdDebug( 6040 ) << "current height = " << m_height << endl;
+#endif
+
+ if (continuation())
+ return addChildWithContinuation(newChild, beforeChild);
+ return addChildToFlow(newChild, beforeChild);
+}
+
+void RenderFlow::deleteInlineBoxes(RenderArena* arena)
+{
+ RenderBox::deleteInlineBoxes(arena); //In case we upcalled
+ //during construction
+ if (m_firstLineBox) {
+ if (!arena)
+ arena = renderArena();
+ InlineRunBox *curr=m_firstLineBox, *next=0;
+ while (curr) {
+ next = curr->nextLineBox();
+ curr->detach(arena);
+ curr = next;
+ }
+ m_firstLineBox = 0;
+ m_lastLineBox = 0;
+ }
+}
+
+void RenderFlow::deleteLastLineBox(RenderArena* arena)
+{
+ if (m_lastLineBox) {
+ if (!arena)
+ arena = renderArena();
+ InlineRunBox *curr=m_lastLineBox, *prev = m_lastLineBox;
+ if (m_firstLineBox == m_lastLineBox)
+ m_firstLineBox = m_lastLineBox = 0;
+ else {
+ prev = curr->prevLineBox();
+ while (!prev->isInlineFlowBox()) {
+ prev = prev->prevLineBox();
+ prev->detach(arena);
+ }
+ m_lastLineBox = static_cast<InlineFlowBox*>(prev);
+ prev->setNextLineBox(0);
+ }
+ if (curr->parent()) {
+ curr->parent()->removeFromLine(curr);
+ }
+ curr->detach(arena);
+ }
+}
+
+InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox)
+{
+ if ( !isRootLineBox &&
+ (isReplaced() || makePlaceHolderBox) ) // Inline tables and inline blocks
+ return RenderBox::createInlineBox(false, false); // (or positioned element placeholders).
+
+ InlineFlowBox* flowBox = 0;
+ if (isInlineFlow())
+ flowBox = new (renderArena()) InlineFlowBox(this);
+ else
+ flowBox = new (renderArena()) RootInlineBox(this);
+
+ if (!m_firstLineBox) {
+ m_firstLineBox = m_lastLineBox = flowBox;
+ } else {
+ m_lastLineBox->setNextLineBox(flowBox);
+ flowBox->setPreviousLineBox(m_lastLineBox);
+ m_lastLineBox = flowBox;
+ }
+
+ return flowBox;
+}
+
+void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty)
+{
+ // Only paint during the foreground/selection phases.
+ if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline)
+ return;
+
+ if (!firstLineBox())
+ return;
+
+ // We can check the first box and last box and avoid painting if we don't
+ // intersect. This is a quick short-circuit that we can take to avoid walking any lines.
+ // FIXME: This check is flawed in two extremely obscure ways.
+ // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
+ // (2) The overflow from an inline block on a line is not reported to the line.
+ int maxOutlineSize = maximalOutlineSize(i.phase);
+ int yPos = firstLineBox()->root()->topOverflow() - maxOutlineSize;
+ int h = maxOutlineSize + lastLineBox()->root()->bottomOverflow() - yPos;
+ yPos += _ty;
+ if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
+ return;
+ for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
+ yPos = curr->root()->topOverflow() - maxOutlineSize;
+ h = curr->root()->bottomOverflow() + maxOutlineSize - yPos;
+ yPos += _ty;
+ if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
+ curr->paint(i, _tx, _ty);
+ }
+
+ if (i.phase == PaintActionOutline && i.outlineObjects) {
+ TQValueList<RenderFlow *>::iterator it;;
+ for( it = (*i.outlineObjects).begin(); it != (*i.outlineObjects).end(); ++it )
+ if ((*it)->isRenderInline())
+ static_cast<RenderInline*>(*it)->paintOutlines(i.p, _tx, _ty);
+ i.outlineObjects->clear();
+ }
+}
+
+
+bool RenderFlow::hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+ (void) hitTestAction;
+ /*
+ if (hitTestAction != HitTestForeground) // ### port hitTest
+ return false;
+ */
+
+ if (!firstLineBox())
+ return false;
+
+ // We can check the first box and last box and avoid hit testing if we don't
+ // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
+ // FIXME: This check is flawed in two extremely obscure ways.
+ // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
+ // (2) The overflow from an inline block on a line is not reported to the line.
+ if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
+ return false;
+
+ // See if our root lines contain the point. If so, then we hit test
+ // them further. Note that boxes can easily overlap, so we can't make any assumptions
+ // based off positions of our first line box or our last line box.
+ for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
+ if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
+ bool inside = curr->nodeAtPoint(i, x, y, tx, ty);
+ if (inside) {
+ setInnerNode(i);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+void RenderFlow::repaint(Priority prior)
+{
+ if (isInlineFlow()) {
+ // Find our leftmost position.
+ int left = 0;
+ // root inline box not reliably availabe during relayout
+ int top = firstLineBox() ? (
+ needsLayout() ? firstLineBox()->xPos() : firstLineBox()->root()->topOverflow()
+ ) : 0;
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ if (curr == firstLineBox() || curr->xPos() < left)
+ left = curr->xPos();
+
+ // Now invalidate a rectangle.
+ int ow = style() ? style()->outlineSize() : 0;
+
+ // We need to add in the relative position offsets of any inlines (including us) up to our
+ // containing block.
+ RenderBlock* cb = containingBlock();
+ for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb;
+ inlineFlow = inlineFlow->parent()) {
+ if (inlineFlow->style() && inlineFlow->style()->position() == RELATIVE && inlineFlow->layer()) {
+ KHTMLAssert(inlineFlow->isBox());
+ static_cast<RenderBox*>(inlineFlow)->relativePositionOffset(left, top);
+ }
+ }
+
+ RootInlineBox *lastRoot = lastLineBox() && !needsLayout() ? lastLineBox()->root() : 0;
+ containingBlock()->repaintRectangle(-ow+left, -ow+top,
+ width()+ow*2,
+ (lastRoot ? lastRoot->bottomOverflow() - top : height())+ow*2, prior);
+ }
+ else {
+ if (firstLineBox() && firstLineBox()->topOverflow() < 0) {
+ int ow = style() ? style()->outlineSize() : 0;
+ repaintRectangle(-ow, -ow+firstLineBox()->topOverflow(),
+ effectiveWidth()+ow*2, effectiveHeight()+ow*2, prior);
+ }
+ else
+ return RenderBox::repaint(prior);
+ }
+}
+
+int
+RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return bottom;
+
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
+ int lp = c->yPos() + c->lowestPosition(false);
+ bottom = kMax(bottom, lp);
+ }
+ }
+
+ if (isRelPositioned()) {
+ int x;
+ relativePositionOffset(x, bottom);
+ }
+
+ return bottom;
+}
+
+int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return right;
+
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
+ int rp = c->xPos() + c->rightmostPosition(false);
+ right = kMax(right, rp);
+ }
+ }
+
+ if (isRelPositioned()) {
+ int y;
+ relativePositionOffset(right, y);
+ }
+
+ return right;
+}
+
+int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return left;
+
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
+ int lp = c->xPos() + c->leftmostPosition(false);
+ left = kMin(left, lp);
+ }
+ }
+
+ if (isRelPositioned()) {
+ int y;
+ relativePositionOffset(left, y);
+ }
+
+ return left;
+}
+
+int RenderFlow::highestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int top = RenderBox::highestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return top;
+
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
+ int hp = c->yPos() + c->highestPosition(false);
+ top = kMin(top, hp);
+ }
+ }
+
+ if (isRelPositioned()) {
+ int x;
+ relativePositionOffset(x, top);
+ }
+
+ return top;
+}
diff --git a/tdehtml/rendering/render_flow.h b/tdehtml/rendering/render_flow.h
new file mode 100644
index 000000000..684968bc1
--- /dev/null
+++ b/tdehtml/rendering/render_flow.h
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 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.
+ *
+ */
+#ifndef RENDER_FLOW_H
+#define RENDER_FLOW_H
+
+#include "render_box.h"
+#include "bidi.h"
+#include "render_line.h"
+
+namespace tdehtml {
+
+/**
+ * all geometry managing stuff is only in the block elements.
+ *
+ * Inline elements don't layout themselves, but the whole paragraph
+ * gets flowed by the surrounding block element. This is, because
+ * one needs to know the whole paragraph to calculate bidirectional
+ * behaviour of text, so putting the layouting routines in the inline
+ * elements is impossible.
+ */
+class RenderFlow : public RenderBox
+{
+public:
+ RenderFlow(DOM::NodeImpl* node)
+ : RenderBox(node)
+ { m_continuation = 0; m_firstLineBox = 0; m_lastLineBox = 0; }
+
+ virtual RenderFlow* continuation() const { return m_continuation; }
+ void setContinuation(RenderFlow* c) { m_continuation = c; }
+ RenderFlow* continuationBefore(RenderObject* beforeChild);
+
+ void addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild);
+ virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild) = 0;
+ virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
+
+ static RenderFlow* createFlow(DOM::NodeImpl* node, RenderStyle* style, RenderArena* arena);
+
+ virtual void deleteLastLineBox(RenderArena* arena=0);
+ virtual void deleteInlineBoxes(RenderArena* arena=0);
+
+
+ InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
+ InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
+
+ virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
+
+ void paintLines(PaintInfo& i, int _tx, int _ty);
+ bool hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction);
+
+ virtual void repaint(Priority p=NormalPriority);
+
+ virtual int highestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+ virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
+
+protected:
+ // An inline can be split with blocks occurring in between the inline content.
+ // When this occurs we need a pointer to our next object. We can basically be
+ // split into a sequence of inlines and blocks. The continuation will either be
+ // an anonymous block (that houses other blocks) or it will be an inline flow.
+ RenderFlow* m_continuation;
+
+ // For block flows, each box represents the root inline box for a line in the
+ // paragraph.
+ // For inline flows, each box represents a portion of that inline.
+ InlineFlowBox* m_firstLineBox;
+ InlineFlowBox* m_lastLineBox;
+};
+
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_form.cpp b/tdehtml/rendering/render_form.cpp
new file mode 100644
index 000000000..7fe009a7f
--- /dev/null
+++ b/tdehtml/rendering/render_form.cpp
@@ -0,0 +1,1914 @@
+/*
+ * 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) 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 <kcompletionbox.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kfind.h>
+#include <kfinddialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kreplace.h>
+#include <kreplacedialog.h>
+#include <tdespell.h>
+#include <kurlcompletion.h>
+#include <twin.h>
+
+#include <tqstyle.h>
+
+#include "misc/helper.h"
+#include "xml/dom2_eventsimpl.h"
+#include "html/html_formimpl.h"
+#include "misc/htmlhashes.h"
+
+#include "rendering/render_form.h"
+#include <assert.h>
+
+#include "tdehtmlview.h"
+#include "tdehtml_ext.h"
+#include "xml/dom_docimpl.h"
+
+#include <tqpopupmenu.h>
+#include <tqbitmap.h>
+
+using namespace tdehtml;
+
+RenderFormElement::RenderFormElement(HTMLGenericFormElementImpl *element)
+ : RenderWidget(element)
+{
+ // init RenderObject attributes
+ setInline(true); // our object is Inline
+
+ m_state = 0;
+}
+
+RenderFormElement::~RenderFormElement()
+{
+}
+
+short RenderFormElement::baselinePosition( bool f ) const
+{
+ return RenderWidget::baselinePosition( f ) - 2 - style()->fontMetrics().descent();
+}
+
+void RenderFormElement::updateFromElement()
+{
+ m_widget->setEnabled(!element()->disabled());
+ RenderWidget::updateFromElement();
+}
+
+void RenderFormElement::layout()
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ // minimum height
+ m_height = 0;
+
+ calcWidth();
+ calcHeight();
+
+ if ( m_widget )
+ resizeWidget(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
+ m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom());
+
+ setNeedsLayout(false);
+}
+
+TQ_Alignment RenderFormElement::textAlignment() const
+{
+ switch (style()->textAlign()) {
+ case LEFT:
+ case KHTML_LEFT:
+ return Qt::AlignLeft;
+ case RIGHT:
+ case KHTML_RIGHT:
+ return Qt::AlignRight;
+ case CENTER:
+ case KHTML_CENTER:
+ return Qt::AlignHCenter;
+ case JUSTIFY:
+ // Just fall into the auto code for justify.
+ case TAAUTO:
+ return style()->direction() == RTL ? Qt::AlignRight : Qt::AlignLeft;
+ }
+ assert(false); // Should never be reached.
+ return Qt::AlignLeft;
+}
+
+// -------------------------------------------------------------------------
+
+RenderButton::RenderButton(HTMLGenericFormElementImpl *element)
+ : RenderFormElement(element)
+{
+}
+
+short RenderButton::baselinePosition( bool f ) const
+{
+ return RenderWidget::baselinePosition( f ) - 2;
+}
+
+// -------------------------------------------------------------------------------
+
+
+RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element)
+ : RenderButton(element)
+{
+ TQCheckBox* b = new TQCheckBox(view()->viewport(), "__tdehtml");
+ b->setAutoMask(true);
+ b->setMouseTracking(true);
+ setQWidget(b);
+
+ // prevent firing toggled() signals on initialization
+ b->setChecked(element->checked());
+
+ connect(b,TQT_SIGNAL(stateChanged(int)),this,TQT_SLOT(slotStateChanged(int)));
+}
+
+
+void RenderCheckBox::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ TQCheckBox *cb = static_cast<TQCheckBox *>( m_widget );
+ TQSize s( cb->style().pixelMetric( TQStyle::PM_IndicatorWidth ),
+ cb->style().pixelMetric( TQStyle::PM_IndicatorHeight ) );
+ setIntrinsicWidth( s.width() );
+ setIntrinsicHeight( s.height() );
+
+ RenderButton::calcMinMaxWidth();
+}
+
+void RenderCheckBox::updateFromElement()
+{
+ widget()->setChecked(element()->checked());
+
+ RenderButton::updateFromElement();
+}
+
+void RenderCheckBox::slotStateChanged(int state)
+{
+ element()->setChecked(state == TQButton::On);
+ element()->setIndeterminate(state == TQButton::NoChange);
+
+ ref();
+ element()->onChange();
+ deref();
+}
+
+// -------------------------------------------------------------------------------
+
+RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element)
+ : RenderButton(element)
+{
+ TQRadioButton* b = new TQRadioButton(view()->viewport(), "__tdehtml");
+ b->setMouseTracking(true);
+ setQWidget(b);
+
+ // prevent firing toggled() signals on initialization
+ b->setChecked(element->checked());
+
+ connect(b,TQT_SIGNAL(toggled(bool)),this,TQT_SLOT(slotToggled(bool)));
+}
+
+void RenderRadioButton::updateFromElement()
+{
+ widget()->setChecked(element()->checked());
+
+ RenderButton::updateFromElement();
+}
+
+void RenderRadioButton::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ TQRadioButton *rb = static_cast<TQRadioButton *>( m_widget );
+ TQSize s( rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorWidth ),
+ rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorHeight ) );
+ setIntrinsicWidth( s.width() );
+ setIntrinsicHeight( s.height() );
+
+ RenderButton::calcMinMaxWidth();
+}
+
+void RenderRadioButton::slotToggled(bool activated)
+{
+ if(activated) {
+ ref();
+ element()->onChange();
+ deref();
+ }
+}
+
+// -------------------------------------------------------------------------------
+
+
+RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element)
+ : RenderButton(element)
+{
+ TQPushButton* p = new TQPushButton(view()->viewport(), "__tdehtml");
+ setQWidget(p);
+ p->setAutoMask(true);
+ p->setMouseTracking(true);
+}
+
+TQString RenderSubmitButton::rawText()
+{
+ TQString value = element()->valueWithDefault().string();
+ value = value.stripWhiteSpace();
+ TQString raw;
+ for(unsigned int i = 0; i < value.length(); i++) {
+ raw += value[i];
+ if(value[i] == '&')
+ raw += '&';
+ }
+ return raw;
+}
+
+void RenderSubmitButton::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ TQString raw = rawText();
+ TQPushButton* pb = static_cast<TQPushButton*>(m_widget);
+ pb->setText(raw);
+ pb->setFont(style()->font());
+
+ bool empty = raw.isEmpty();
+ if ( empty )
+ raw = TQString::fromLatin1("X");
+ TQFontMetrics fm = pb->fontMetrics();
+ TQSize ts = fm.size( ShowPrefix, raw);
+ TQSize s(pb->style().tqsizeFromContents( TQStyle::CT_PushButton, pb, ts )
+ .expandedTo(TQApplication::globalStrut()));
+ int margin = pb->style().pixelMetric( TQStyle::PM_ButtonMargin, pb) +
+ pb->style().pixelMetric( TQStyle::PM_DefaultFrameWidth, pb ) * 2;
+ int w = ts.width() + margin;
+ int h = s.height();
+ if (pb->isDefault() || pb->autoDefault()) {
+ int dbw = pb->style().pixelMetric( TQStyle::PM_ButtonDefaultIndicator, pb ) * 2;
+ w += dbw;
+ }
+
+ // add 30% margins to the width (heuristics to make it look similar to IE)
+ s = TQSize( w*13/10, h ).expandedTo(TQApplication::globalStrut());
+
+ setIntrinsicWidth( s.width() );
+ setIntrinsicHeight( s.height() );
+
+ RenderButton::calcMinMaxWidth();
+}
+
+void RenderSubmitButton::updateFromElement()
+{
+ TQString oldText = static_cast<TQPushButton*>(m_widget)->text();
+ TQString newText = rawText();
+ static_cast<TQPushButton*>(m_widget)->setText(newText);
+ if ( oldText != newText )
+ setNeedsLayoutAndMinMaxRecalc();
+ RenderFormElement::updateFromElement();
+}
+
+short RenderSubmitButton::baselinePosition( bool f ) const
+{
+ return RenderFormElement::baselinePosition( f );
+}
+
+// -------------------------------------------------------------------------------
+
+RenderResetButton::RenderResetButton(HTMLInputElementImpl *element)
+ : RenderSubmitButton(element)
+{
+}
+
+// -------------------------------------------------------------------------------
+
+LineEditWidget::LineEditWidget(DOM::HTMLInputElementImpl* input, KHTMLView* view, TQWidget* parent)
+ : KLineEdit(parent, "__tdehtml"), m_input(input), m_view(view), m_spell(0)
+{
+ setMouseTracking(true);
+ KActionCollection *ac = new KActionCollection(this);
+ m_spellAction = KStdAction::spelling( TQT_TQOBJECT(this), TQT_SLOT( slotCheckSpelling() ), ac );
+}
+
+LineEditWidget::~LineEditWidget()
+{
+ delete m_spell;
+ m_spell = 0L;
+}
+
+void LineEditWidget::slotCheckSpelling()
+{
+ if ( text().isEmpty() ) {
+ return;
+ }
+
+ delete m_spell;
+ m_spell = new KSpell( this, i18n( "Spell Checking" ), TQT_TQOBJECT(this), TQT_SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
+
+ connect( m_spell, TQT_SIGNAL( death() ),this, TQT_SLOT( spellCheckerFinished() ) );
+ connect( m_spell, TQT_SIGNAL( misspelling( const TQString &, const TQStringList &, unsigned int ) ),this, TQT_SLOT( spellCheckerMisspelling( const TQString &, const TQStringList &, unsigned int ) ) );
+ connect( m_spell, TQT_SIGNAL( corrected( const TQString &, const TQString &, unsigned int ) ),this, TQT_SLOT( spellCheckerCorrected( const TQString &, const TQString &, unsigned int ) ) );
+}
+
+void LineEditWidget::spellCheckerMisspelling( const TQString &_text, const TQStringList &, unsigned int pos)
+{
+ highLightWord( _text.length(),pos );
+}
+
+void LineEditWidget::highLightWord( unsigned int length, unsigned int pos )
+{
+ setSelection ( pos, length );
+}
+
+void LineEditWidget::spellCheckerCorrected( const TQString &old, const TQString &corr, unsigned int pos )
+{
+ if( old!= corr )
+ {
+ setSelection ( pos, old.length() );
+ insert( corr );
+ setSelection ( pos, corr.length() );
+ }
+}
+
+void LineEditWidget::spellCheckerFinished()
+{
+}
+
+void LineEditWidget::slotSpellCheckReady( KSpell *s )
+{
+ s->check( text() );
+ connect( s, TQT_SIGNAL( done( const TQString & ) ), this, TQT_SLOT( slotSpellCheckDone( const TQString & ) ) );
+}
+
+void LineEditWidget::slotSpellCheckDone( const TQString &s )
+{
+ if( s != text() )
+ setText( s );
+}
+
+
+TQPopupMenu *LineEditWidget::createPopupMenu()
+{
+ TQPopupMenu *popup = KLineEdit::createPopupMenu();
+
+ if ( !popup ) {
+ return 0L;
+ }
+
+ connect( popup, TQT_SIGNAL( activated( int ) ),
+ this, TQT_SLOT( extendedMenuActivated( int ) ) );
+
+ if (m_input->autoComplete()) {
+ popup->insertSeparator();
+ int id = popup->insertItem( SmallIconSet("edit"), i18n("&Edit History..."), EditHistory );
+ popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) );
+ id = popup->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), ClearHistory );
+ popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) );
+ }
+
+ if (echoMode() == TQLineEdit::Normal &&
+ !isReadOnly()) {
+ popup->insertSeparator();
+
+ m_spellAction->plug(popup);
+ m_spellAction->setEnabled( !text().isEmpty() );
+ }
+
+ return popup;
+}
+
+
+void LineEditWidget::extendedMenuActivated( int id)
+{
+ switch ( id )
+ {
+ case ClearHistory:
+ m_view->clearCompletionHistory(m_input->name().string());
+ if (compObj())
+ compObj()->clear();
+ case EditHistory:
+ {
+ KHistoryComboEditor dlg( compObj() ? compObj()->items() : TQStringList(), this );
+ connect( &dlg, TQT_SIGNAL( removeFromHistory(const TQString&) ), TQT_SLOT( slotRemoveFromHistory(const TQString&)) );
+ dlg.exec();
+ }
+ default:
+ break;
+ }
+}
+
+void LineEditWidget::slotRemoveFromHistory(const TQString &entry)
+{
+ m_view->removeFormCompletionItem(m_input->name().string(), entry);
+ if (compObj())
+ compObj()->removeItem(entry);
+}
+
+
+bool LineEditWidget::event( TQEvent *e )
+{
+ if (KLineEdit::event(e))
+ return true;
+
+ if ( e->type() == TQEvent::AccelAvailable && isReadOnly() ) {
+ TQKeyEvent* ke = (TQKeyEvent*) e;
+ if ( ke->state() & ControlButton ) {
+ switch ( ke->key() ) {
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ case Key_Home:
+ case Key_End:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+void LineEditWidget::mouseMoveEvent(TQMouseEvent *e)
+{
+ // hack to prevent Qt from calling setCursor on the widget
+ setDragEnabled(false);
+ KLineEdit::mouseMoveEvent(e);
+ setDragEnabled(true);
+}
+
+
+// -----------------------------------------------------------------------------
+
+RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element)
+ : RenderFormElement(element)
+{
+ LineEditWidget *edit = new LineEditWidget(element, view(), view()->viewport());
+ connect(edit,TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed()));
+ connect(edit,TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &)));
+
+ if(element->inputType() == HTMLInputElementImpl::PASSWORD)
+ edit->setEchoMode( TQLineEdit::Password );
+
+ if ( element->autoComplete() ) {
+ TQStringList completions = view()->formCompletionItems(element->name().string());
+ if (completions.count()) {
+ edit->completionObject()->setItems(completions);
+ edit->setContextMenuEnabled(true);
+ edit->completionBox()->setTabHandling( false );
+ }
+ }
+
+ setQWidget(edit);
+}
+
+void RenderLineEdit::setStyle(RenderStyle* _style)
+{
+ RenderFormElement::setStyle( _style );
+
+ widget()->setAlignment(textAlignment());
+}
+
+void RenderLineEdit::highLightWord( unsigned int length, unsigned int pos )
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ if ( w )
+ w->highLightWord( length, pos );
+}
+
+
+void RenderLineEdit::slotReturnPressed()
+{
+ // don't submit the form when return was pressed in a completion-popup
+ KCompletionBox *box = widget()->completionBox(false);
+
+ if ( box && box->isVisible() && box->currentItem() != -1 ) {
+ box->hide();
+ return;
+ }
+
+ // Emit onChange if necessary
+ // Works but might not be enough, dirk said he had another solution at
+ // hand (can't remember which) - David
+ handleFocusOut();
+
+ HTMLFormElementImpl* fe = element()->form();
+ if ( fe )
+ fe->submitFromKeyboard();
+}
+
+void RenderLineEdit::handleFocusOut()
+{
+ if ( widget() && widget()->edited() ) {
+ element()->onChange();
+ widget()->setEdited( false );
+ }
+}
+
+void RenderLineEdit::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ const TQFontMetrics &fm = style()->fontMetrics();
+ TQSize s;
+
+ int size = element()->size();
+
+ int h = fm.lineSpacing();
+ int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some"
+ s = TQSize(w + 2 + 2*widget()->frameWidth(),
+ kMax(h, 14) + 2 + 2*widget()->frameWidth())
+ .expandedTo(TQApplication::globalStrut());
+
+ setIntrinsicWidth( s.width() );
+ setIntrinsicHeight( s.height() );
+
+ RenderFormElement::calcMinMaxWidth();
+}
+
+void RenderLineEdit::updateFromElement()
+{
+ int ml = element()->maxLength();
+ if ( ml < 0 )
+ ml = 32767;
+
+ if ( widget()->maxLength() != ml ) {
+ widget()->setMaxLength( ml );
+ }
+
+ if (element()->value().string() != widget()->text()) {
+ widget()->blockSignals(true);
+ int pos = widget()->cursorPosition();
+ widget()->setText(element()->value().string());
+
+ widget()->setEdited( false );
+
+ widget()->setCursorPosition(pos);
+ widget()->blockSignals(false);
+ }
+ widget()->setReadOnly(element()->readOnly());
+
+ RenderFormElement::updateFromElement();
+}
+
+void RenderLineEdit::slotTextChanged(const TQString &string)
+{
+ // don't use setValue here!
+ element()->m_value = string;
+ element()->m_unsubmittedFormChange = true;
+}
+
+void RenderLineEdit::select()
+{
+ static_cast<LineEditWidget*>(m_widget)->selectAll();
+}
+
+long RenderLineEdit::selectionStart()
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ if (w->hasSelectedText())
+ return w->selectionStart();
+ else
+ return w->cursorPosition();
+}
+
+
+long RenderLineEdit::selectionEnd()
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ if (w->hasSelectedText())
+ return w->selectionStart() + w->selectedText().length();
+ else
+ return w->cursorPosition();
+}
+
+void RenderLineEdit::setSelectionStart(long pos)
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ //See whether we have a non-empty selection now.
+ long end = selectionEnd();
+ if (end > pos)
+ w->setSelection(pos, end - pos);
+ w->setCursorPosition(pos);
+}
+
+void RenderLineEdit::setSelectionEnd(long pos)
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ //See whether we have a non-empty selection now.
+ long start = selectionStart();
+ if (start < pos)
+ w->setSelection(start, pos - start);
+
+ w->setCursorPosition(pos);
+}
+
+void RenderLineEdit::setSelectionRange(long start, long end)
+{
+ LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
+ w->setCursorPosition(end);
+ w->setSelection(start, end - start);
+}
+
+// ---------------------------------------------------------------------------
+
+RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element)
+ : RenderBlock(element)
+{
+}
+
+RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
+{
+ RenderObject* legend = findLegend();
+ if (legend) {
+ if (relayoutChildren)
+ legend->setNeedsLayout(true);
+ legend->layoutIfNeeded();
+
+ int xPos = borderLeft() + paddingLeft() + legend->marginLeft();
+ if (style()->direction() == RTL)
+ xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
+ int b = borderTop();
+ int h = legend->height();
+ legend->setPos(xPos, kMax((b-h)/2, 0));
+ m_height = kMax(b,h) + paddingTop();
+ }
+ return legend;
+}
+
+RenderObject* RenderFieldset::findLegend()
+{
+ for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
+ if (!legend->isFloatingOrPositioned() && legend->element() &&
+ legend->element()->id() == ID_LEGEND)
+ return legend;
+ }
+ return 0;
+}
+
+void RenderFieldset::paintBoxDecorations(PaintInfo& pI, int _tx, int _ty)
+{
+ //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
+
+ RenderObject* legend = findLegend();
+ if (!legend)
+ return RenderBlock::paintBoxDecorations(pI, _tx, _ty);
+
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ int yOff = (legend->yPos() > 0) ? 0 : (legend->height()-borderTop())/2;
+ h -= yOff;
+ _ty += yOff - borderTopExtra();
+
+ int my = kMax(_ty,pI.r.y());
+ int end = kMin( pI.r.y() + pI.r.height(), _ty + h );
+ int mh = end - my;
+
+ paintBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
+
+ if ( style()->hasBorder() )
+ paintBorderMinusLegend(pI.p, _tx, _ty, w, h, style(), legend->xPos(), legend->width());
+}
+
+void RenderFieldset::paintBorderMinusLegend(TQPainter *p, int _tx, int _ty, int w, int h,
+ const RenderStyle* style, int lx, int lw)
+{
+
+ const TQColor& tc = style->borderTopColor();
+ const TQColor& bc = style->borderBottomColor();
+
+ EBorderStyle ts = style->borderTopStyle();
+ EBorderStyle bs = style->borderBottomStyle();
+ EBorderStyle ls = style->borderLeftStyle();
+ EBorderStyle rs = style->borderRightStyle();
+
+ bool render_t = ts > BHIDDEN;
+ bool render_l = ls > BHIDDEN;
+ bool render_r = rs > BHIDDEN;
+ bool render_b = bs > BHIDDEN;
+
+ if(render_t) {
+ drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+ (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0), 0);
+ drawBorder(p, _tx+lx+lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+ 0, (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0));
+ }
+
+ if(render_b)
+ drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
+ (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0),
+ (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0));
+
+ if(render_l)
+ {
+ const TQColor& lc = style->borderLeftColor();
+
+ bool ignore_top =
+ (tc == lc) &&
+ (ls >= OUTSET) &&
+ (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+ bool ignore_bottom =
+ (bc == lc) &&
+ (ls >= OUTSET) &&
+ (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+ drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
+ ignore_top?0:style->borderTopWidth(),
+ ignore_bottom?0:style->borderBottomWidth());
+ }
+
+ if(render_r)
+ {
+ const TQColor& rc = style->borderRightColor();
+
+ bool ignore_top =
+ (tc == rc) &&
+ (rs >= DOTTED || rs == INSET) &&
+ (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+ bool ignore_bottom =
+ (bc == rc) &&
+ (rs >= DOTTED || rs == INSET) &&
+ (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+ drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
+ ignore_top?0:style->borderTopWidth(),
+ ignore_bottom?0:style->borderBottomWidth());
+ }
+}
+
+void RenderFieldset::setStyle(RenderStyle* _style)
+{
+ RenderBlock::setStyle(_style);
+
+ // WinIE renders fieldsets with display:inline like they're inline-blocks. For us,
+ // an inline-block is just a block element with replaced set to true and inline set
+ // to true. Ensure that if we ended up being inline that we set our replaced flag
+ // so that we're treated like an inline-block.
+ if (isInline())
+ setReplaced(true);
+}
+
+// -------------------------------------------------------------------------
+
+RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
+ : RenderFormElement(element)
+{
+ KURLRequester* w = new KURLRequester( view()->viewport(), "__tdehtml" );
+
+ w->setMode(KFile::File | KFile::ExistingOnly);
+ w->completionObject()->setDir(TDEGlobalSettings::documentPath());
+
+ connect(w->lineEdit(), TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed()));
+ connect(w->lineEdit(), TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &)));
+ connect(w, TQT_SIGNAL(urlSelected(const TQString &)),this,TQT_SLOT(slotUrlSelected(const TQString &)));
+
+ setQWidget(w);
+ m_haveFocus = false;
+}
+
+
+
+void RenderFileButton::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ const TQFontMetrics &fm = style()->fontMetrics();
+ int size = element()->size();
+
+ int h = fm.lineSpacing();
+ int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some"
+ KLineEdit* edit = static_cast<KURLRequester*>( m_widget )->lineEdit();
+ TQSize s = edit->style().tqsizeFromContents(TQStyle::CT_LineEdit,
+ edit,
+ TQSize(w + 2 + 2*edit->frameWidth(), kMax(h, 14) + 2 + 2*edit->frameWidth()))
+ .expandedTo(TQApplication::globalStrut());
+ TQSize bs = static_cast<KURLRequester*>( m_widget )->minimumSizeHint() - edit->minimumSizeHint();
+
+ setIntrinsicWidth( s.width() + bs.width() );
+ setIntrinsicHeight( kMax(s.height(), bs.height()) );
+
+ RenderFormElement::calcMinMaxWidth();
+}
+
+void RenderFileButton::handleFocusOut()
+{
+ if ( widget()->lineEdit() && widget()->lineEdit()->edited() ) {
+ element()->onChange();
+ widget()->lineEdit()->setEdited( false );
+ }
+}
+
+void RenderFileButton::updateFromElement()
+{
+ KLineEdit* edit = widget()->lineEdit();
+ edit->blockSignals(true);
+ edit->setText(element()->value().string());
+ edit->blockSignals(false);
+ edit->setEdited( false );
+
+ RenderFormElement::updateFromElement();
+}
+
+void RenderFileButton::slotReturnPressed()
+{
+ handleFocusOut();
+
+ if (element()->form())
+ element()->form()->submitFromKeyboard();
+}
+
+void RenderFileButton::slotTextChanged(const TQString &/*string*/)
+{
+ element()->m_value = KURL( widget()->url() ).prettyURL( 0, KURL::StripFileProtocol );
+}
+
+void RenderFileButton::slotUrlSelected(const TQString &)
+{
+ element()->onChange();
+}
+
+void RenderFileButton::select()
+{
+ widget()->lineEdit()->selectAll();
+}
+
+// -------------------------------------------------------------------------
+
+RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
+ : RenderFormElement(element)
+{
+
+}
+
+// -------------------------------------------------------------------------
+
+RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
+ : RenderBlock(element)
+{
+}
+
+// -------------------------------------------------------------------------------
+
+ComboBoxWidget::ComboBoxWidget(TQWidget *parent)
+ : KComboBox(false, parent, "__tdehtml")
+{
+ setAutoMask(true);
+ if (listBox()) listBox()->installEventFilter(this);
+ setMouseTracking(true);
+}
+
+bool ComboBoxWidget::event(TQEvent *e)
+{
+ if (KComboBox::event(e))
+ return true;
+ if (e->type()==TQEvent::KeyPress)
+ {
+ TQKeyEvent *ke = TQT_TQKEYEVENT(e);
+ switch(ke->key())
+ {
+ case Key_Return:
+ case Key_Enter:
+ popup();
+ ke->accept();
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+bool ComboBoxWidget::eventFilter(TQObject *dest, TQEvent *e)
+{
+ if (TQT_BASE_OBJECT(dest)==TQT_BASE_OBJECT(listBox()) && e->type()==TQEvent::KeyPress)
+ {
+ TQKeyEvent *ke = TQT_TQKEYEVENT(e);
+ bool forward = false;
+ switch(ke->key())
+ {
+ case Key_Tab:
+ forward=true;
+ case Key_BackTab:
+ // ugly hack. emulate popdownlistbox() (private in TQComboBox)
+ // we re-use ke here to store the reference to the generated event.
+ ke = new TQKeyEvent(TQEvent::KeyPress, Key_Escape, 0, 0);
+ TQApplication::sendEvent(dest,ke);
+ focusNextPrevChild(forward);
+ delete ke;
+ return true;
+ default:
+ return KComboBox::eventFilter(dest, e);
+ }
+ }
+ return KComboBox::eventFilter(dest, e);
+}
+
+// -------------------------------------------------------------------------
+
+RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
+ : RenderFormElement(element)
+{
+ m_ignoreSelectEvents = false;
+ m_multiple = element->multiple();
+ m_size = element->size();
+ m_useListBox = (m_multiple || m_size > 1);
+ m_selectionChanged = true;
+ m_optionsChanged = true;
+
+ if(m_useListBox)
+ setQWidget(createListBox());
+ else
+ setQWidget(createComboBox());
+}
+
+void RenderSelect::updateFromElement()
+{
+ m_ignoreSelectEvents = true;
+
+ // change widget type
+ bool oldMultiple = m_multiple;
+ unsigned oldSize = m_size;
+ bool oldListbox = m_useListBox;
+
+ m_multiple = element()->multiple();
+ m_size = element()->size();
+ m_useListBox = (m_multiple || m_size > 1);
+
+ if (oldMultiple != m_multiple || oldSize != m_size) {
+ if (m_useListBox != oldListbox) {
+ // type of select has changed
+ if(m_useListBox)
+ setQWidget(createListBox());
+ else
+ setQWidget(createComboBox());
+ }
+
+ if (m_useListBox && oldMultiple != m_multiple) {
+ static_cast<KListBox*>(m_widget)->setSelectionMode(m_multiple ? TQListBox::Extended : TQListBox::Single);
+ }
+ m_selectionChanged = true;
+ m_optionsChanged = true;
+ }
+
+ // update contents listbox/combobox based on options in m_element
+ if ( m_optionsChanged ) {
+ if (element()->m_recalcListItems)
+ element()->recalcListItems();
+ TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
+ int listIndex;
+
+ if(m_useListBox) {
+ static_cast<KListBox*>(m_widget)->clear();
+ }
+
+ else
+ static_cast<KComboBox*>(m_widget)->clear();
+
+ for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
+ if (listItems[listIndex]->id() == ID_OPTGROUP) {
+ DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL);
+ if (text.isNull())
+ text = "";
+
+ if(m_useListBox) {
+ TQListBoxText *item = new TQListBoxText(TQString(text.implementation()->s, text.implementation()->l));
+ static_cast<KListBox*>(m_widget)
+ ->insertItem(item, listIndex);
+ item->setSelectable(false);
+ }
+ else {
+ static_cast<KComboBox*>(m_widget)
+ ->insertItem(TQString(text.implementation()->s, text.implementation()->l), listIndex);
+ static_cast<KComboBox*>(m_widget)->listBox()->item(listIndex)->setSelectable(false);
+ }
+ }
+ else if (listItems[listIndex]->id() == ID_OPTION) {
+ HTMLOptionElementImpl* optElem = static_cast<HTMLOptionElementImpl*>(listItems[listIndex]);
+ TQString text = optElem->text().string();
+ if (optElem->parentNode()->id() == ID_OPTGROUP)
+ {
+ // Prefer label if set
+ DOMString label = optElem->getAttribute(ATTR_LABEL);
+ if (!label.isEmpty())
+ text = label.string();
+ text = TQString::fromLatin1(" ")+text;
+ }
+
+ if(m_useListBox) {
+ KListBox *l = static_cast<KListBox*>(m_widget);
+ l->insertItem(text, listIndex);
+ DOMString disabled = optElem->getAttribute(ATTR_DISABLED);
+ if (!disabled.isNull() && l->item( listIndex )) {
+ l->item( listIndex )->setSelectable( false );
+ }
+ } else
+ static_cast<KComboBox*>(m_widget)->insertItem(text, listIndex);
+ }
+ else
+ KHTMLAssert(false);
+ m_selectionChanged = true;
+ }
+
+ // TQComboBox caches the size hint unless you call setFont (ref: TT docu)
+ if(!m_useListBox) {
+ KComboBox *that = static_cast<KComboBox*>(m_widget);
+ that->setFont( that->font() );
+ }
+ setNeedsLayoutAndMinMaxRecalc();
+ m_optionsChanged = false;
+ }
+
+ // update selection
+ if (m_selectionChanged) {
+ updateSelection();
+ }
+
+
+ m_ignoreSelectEvents = false;
+
+ RenderFormElement::updateFromElement();
+}
+
+void RenderSelect::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ if (m_optionsChanged)
+ updateFromElement();
+
+ // ### ugly HACK FIXME!!!
+ setMinMaxKnown();
+ layoutIfNeeded();
+ setNeedsLayoutAndMinMaxRecalc();
+ // ### end FIXME
+
+ RenderFormElement::calcMinMaxWidth();
+}
+
+void RenderSelect::layout( )
+{
+ KHTMLAssert(needsLayout());
+ KHTMLAssert(minMaxKnown());
+
+ // ### maintain selection properly between type/size changes, and work
+ // out how to handle multiselect->singleselect (probably just select
+ // first selected one)
+
+ // calculate size
+ if(m_useListBox) {
+ KListBox* w = static_cast<KListBox*>(m_widget);
+
+ TQListBoxItem* p = w->firstItem();
+ int width = 0;
+ int height = 0;
+ while(p) {
+ width = kMax(width, p->width(p->listBox()));
+ height = kMax(height, p->height(p->listBox()));
+ p = p->next();
+ }
+ if ( !height )
+ height = w->fontMetrics().height();
+ if ( !width )
+ width = w->fontMetrics().width( 'x' );
+
+ int size = m_size;
+ // check if multiple and size was not given or invalid
+ // Internet Exploder sets size to kMin(number of elements, 4)
+ // Netscape seems to simply set it to "number of elements"
+ // the average of that is IMHO kMin(number of elements, 10)
+ // so I did that ;-)
+ if(size < 1)
+ size = kMin(static_cast<KListBox*>(m_widget)->count(), 10u);
+
+ width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width();
+ height = size*height + 2*w->frameWidth();
+
+ setIntrinsicWidth( width );
+ setIntrinsicHeight( height );
+ }
+ else {
+ TQSize s(m_widget->sizeHint());
+ setIntrinsicWidth( s.width() );
+ setIntrinsicHeight( s.height() );
+ }
+
+ /// uuh, ignore the following line..
+ setNeedsLayout(true);
+ RenderFormElement::layout();
+
+ // and now disable the widget in case there is no <option> given
+ TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
+
+ bool foundOption = false;
+ for (uint i = 0; i < listItems.size() && !foundOption; i++)
+ foundOption = (listItems[i]->id() == ID_OPTION);
+
+ m_widget->setEnabled(foundOption && ! element()->disabled());
+}
+
+void RenderSelect::slotSelected(int index) // emitted by the combobox only
+{
+ if ( m_ignoreSelectEvents ) return;
+
+ KHTMLAssert( !m_useListBox );
+
+ TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
+ if(index >= 0 && index < int(listItems.size()))
+ {
+ bool found = ( listItems[index]->id() == ID_OPTION );
+
+ if ( !found ) {
+ // this one is not selectable, we need to find an option element
+ while ( ( unsigned ) index < listItems.size() ) {
+ if ( listItems[index]->id() == ID_OPTION ) {
+ found = true;
+ break;
+ }
+ ++index;
+ }
+
+ if ( !found ) {
+ while ( index >= 0 ) {
+ if ( listItems[index]->id() == ID_OPTION ) {
+ found = true;
+ break;
+ }
+ --index;
+ }
+ }
+ }
+
+ if ( found ) {
+ bool changed = false;
+
+ for ( unsigned int i = 0; i < listItems.size(); ++i )
+ if ( listItems[i]->id() == ID_OPTION && i != (unsigned int) index )
+ {
+ HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>( listItems[i] );
+ changed |= (opt->m_selected == true);
+ opt->m_selected = false;
+ }
+
+ HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>(listItems[index]);
+ changed |= (opt->m_selected == false);
+ opt->m_selected = true;
+
+ if ( index != static_cast<ComboBoxWidget*>( m_widget )->currentItem() )
+ static_cast<ComboBoxWidget*>( m_widget )->setCurrentItem( index );
+
+ // When selecting an optgroup item, and we move forward to we
+ // shouldn't emit onChange. Hence this bool, the if above doesn't do it.
+ if ( changed )
+ {
+ ref();
+ element()->onChange();
+ deref();
+ }
+ }
+ }
+}
+
+
+void RenderSelect::slotSelectionChanged() // emitted by the listbox only
+{
+ if ( m_ignoreSelectEvents ) return;
+
+ // don't use listItems() here as we have to avoid recalculations - changing the
+ // option list will make use update options not in the way the user expects them
+ TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->m_listItems;
+ for ( unsigned i = 0; i < listItems.count(); i++ )
+ // don't use setSelected() here because it will cause us to be called
+ // again with updateSelection.
+ if ( listItems[i]->id() == ID_OPTION )
+ static_cast<HTMLOptionElementImpl*>( listItems[i] )
+ ->m_selected = static_cast<KListBox*>( m_widget )->isSelected( i );
+
+ ref();
+ element()->onChange();
+ deref();
+}
+
+void RenderSelect::setOptionsChanged(bool _optionsChanged)
+{
+ m_optionsChanged = _optionsChanged;
+}
+
+KListBox* RenderSelect::createListBox()
+{
+ KListBox *lb = new KListBox(view()->viewport(), "__tdehtml");
+ lb->setSelectionMode(m_multiple ? TQListBox::Extended : TQListBox::Single);
+ // ### looks broken
+ //lb->setAutoMask(true);
+ connect( lb, TQT_SIGNAL( selectionChanged() ), this, TQT_SLOT( slotSelectionChanged() ) );
+// connect( lb, TQT_SIGNAL( clicked( TQListBoxItem * ) ), this, TQT_SLOT( slotClicked() ) );
+ m_ignoreSelectEvents = false;
+ lb->setMouseTracking(true);
+
+ return lb;
+}
+
+ComboBoxWidget *RenderSelect::createComboBox()
+{
+ ComboBoxWidget *cb = new ComboBoxWidget(view()->viewport());
+ connect(cb, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelected(int)));
+ return cb;
+}
+
+void RenderSelect::updateSelection()
+{
+ TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
+ int i;
+ if (m_useListBox) {
+ // if multi-select, we select only the new selected index
+ KListBox *listBox = static_cast<KListBox*>(m_widget);
+ for (i = 0; i < int(listItems.size()); i++)
+ listBox->setSelected(i,listItems[i]->id() == ID_OPTION &&
+ static_cast<HTMLOptionElementImpl*>(listItems[i])->selected());
+ }
+ else {
+ bool found = false;
+ unsigned firstOption = listItems.size();
+ i = listItems.size();
+ while (i--)
+ if (listItems[i]->id() == ID_OPTION) {
+ if (found)
+ static_cast<HTMLOptionElementImpl*>(listItems[i])->m_selected = false;
+ else if (static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()) {
+ static_cast<KComboBox*>( m_widget )->setCurrentItem(i);
+ found = true;
+ }
+ firstOption = i;
+ }
+
+ Q_ASSERT(firstOption == listItems.size() || found);
+ }
+
+ m_selectionChanged = false;
+}
+
+
+// -------------------------------------------------------------------------
+
+TextAreaWidget::TextAreaWidget(int wrap, TQWidget* parent)
+ : KTextEdit(parent, "__tdehtml"), m_findDlg(0), m_find(0), m_repDlg(0), m_replace(0)
+{
+ if(wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) {
+ setWordWrap(TQTextEdit::WidgetWidth);
+ setHScrollBarMode( AlwaysOff );
+ setVScrollBarMode( AlwaysOn );
+ }
+ else {
+ setWordWrap(TQTextEdit::NoWrap);
+ setHScrollBarMode( Auto );
+ setVScrollBarMode( Auto );
+ }
+ KCursor::setAutoHideCursor(viewport(), true);
+ setTextFormat(TQTextEdit::PlainText);
+ setAutoMask(true);
+ setMouseTracking(true);
+
+ KActionCollection *ac = new KActionCollection(this);
+ m_findAction = KStdAction::find( TQT_TQOBJECT(this), TQT_SLOT( slotFind() ), ac );
+ m_findNextAction = KStdAction::findNext( TQT_TQOBJECT(this), TQT_SLOT( slotFindNext() ), ac );
+ m_replaceAction = KStdAction::replace( TQT_TQOBJECT(this), TQT_SLOT( slotReplace() ), ac );
+}
+
+
+TextAreaWidget::~TextAreaWidget()
+{
+ delete m_replace;
+ m_replace = 0L;
+ delete m_find;
+ m_find = 0L;
+ delete m_repDlg;
+ m_repDlg = 0L;
+ delete m_findDlg;
+ m_findDlg = 0L;
+}
+
+
+TQPopupMenu *TextAreaWidget::createPopupMenu(const TQPoint& pos)
+{
+ TQPopupMenu *popup = KTextEdit::createPopupMenu(pos);
+
+ if ( !popup ) {
+ return 0L;
+ }
+
+ if (!isReadOnly()) {
+ popup->insertSeparator();
+
+ m_findAction->plug(popup);
+ m_findAction->setEnabled( !text().isEmpty() );
+
+ m_findNextAction->plug(popup);
+ m_findNextAction->setEnabled( m_find != 0 );
+
+ m_replaceAction->plug(popup);
+ m_replaceAction->setEnabled( !text().isEmpty() );
+ }
+
+ return popup;
+}
+
+
+void TextAreaWidget::slotFindHighlight(const TQString& text, int matchingIndex, int matchingLength)
+{
+ Q_UNUSED(text)
+ //kdDebug() << "Highlight: [" << text << "] mi:" << matchingIndex << " ml:" << matchingLength << endl;
+ if (sender() == m_replace) {
+ setSelection(m_repPara, matchingIndex, m_repPara, matchingIndex + matchingLength);
+ setCursorPosition(m_repPara, matchingIndex);
+ } else {
+ setSelection(m_findPara, matchingIndex, m_findPara, matchingIndex + matchingLength);
+ setCursorPosition(m_findPara, matchingIndex);
+ }
+ ensureCursorVisible();
+}
+
+
+void TextAreaWidget::slotReplaceText(const TQString &text, int replacementIndex, int /*replacedLength*/, int matchedLength) {
+ Q_UNUSED(text)
+ //kdDebug() << "Replace: [" << text << "] ri:" << replacementIndex << " rl:" << replacedLength << " ml:" << matchedLength << endl;
+ setSelection(m_repPara, replacementIndex, m_repPara, replacementIndex + matchedLength);
+ removeSelectedText();
+ insertAt(m_repDlg->replacement(), m_repPara, replacementIndex);
+ if (m_replace->options() & KReplaceDialog::PromptOnReplace) {
+ ensureCursorVisible();
+ }
+}
+
+
+void TextAreaWidget::slotDoReplace()
+{
+ if (!m_repDlg) {
+ // Should really assert()
+ return;
+ }
+
+ delete m_replace;
+ m_replace = new KReplace(m_repDlg->pattern(), m_repDlg->replacement(), m_repDlg->options(), this);
+ if (m_replace->options() & KFindDialog::FromCursor) {
+ getCursorPosition(&m_repPara, &m_repIndex);
+ } else if (m_replace->options() & KFindDialog::FindBackwards) {
+ m_repPara = paragraphs() - 1;
+ m_repIndex = paragraphLength(m_repPara) - 1;
+ } else {
+ m_repPara = 0;
+ m_repIndex = 0;
+ }
+
+ // Connect highlight signal to code which handles highlighting
+ // of found text.
+ connect(m_replace, TQT_SIGNAL(highlight(const TQString &, int, int)),
+ this, TQT_SLOT(slotFindHighlight(const TQString &, int, int)));
+ connect(m_replace, TQT_SIGNAL(findNext()), this, TQT_SLOT(slotReplaceNext()));
+ connect(m_replace, TQT_SIGNAL(replace(const TQString &, int, int, int)),
+ this, TQT_SLOT(slotReplaceText(const TQString &, int, int, int)));
+
+ m_repDlg->close();
+ slotReplaceNext();
+}
+
+
+void TextAreaWidget::slotReplaceNext()
+{
+ if (!m_replace) {
+ // assert?
+ return;
+ }
+
+ if (!(m_replace->options() & KReplaceDialog::PromptOnReplace)) {
+ viewport()->setUpdatesEnabled(false);
+ }
+
+ KFind::Result res = KFind::NoMatch;
+ while (res == KFind::NoMatch) {
+ // If we're done.....
+ if (m_replace->options() & KFindDialog::FindBackwards) {
+ if (m_repIndex == 0 && m_repPara == 0) {
+ break;
+ }
+ } else {
+ if (m_repPara == paragraphs() - 1 &&
+ m_repIndex == paragraphLength(m_repPara) - 1) {
+ break;
+ }
+ }
+
+ if (m_replace->needData()) {
+ m_replace->setData(text(m_repPara), m_repIndex);
+ }
+
+ res = m_replace->replace();
+
+ if (res == KFind::NoMatch) {
+ if (m_replace->options() & KFindDialog::FindBackwards) {
+ if (m_repPara == 0) {
+ m_repIndex = 0;
+ } else {
+ m_repPara--;
+ m_repIndex = paragraphLength(m_repPara) - 1;
+ }
+ } else {
+ if (m_repPara == paragraphs() - 1) {
+ m_repIndex = paragraphLength(m_repPara) - 1;
+ } else {
+ m_repPara++;
+ m_repIndex = 0;
+ }
+ }
+ }
+ }
+
+ if (!(m_replace->options() & KReplaceDialog::PromptOnReplace)) {
+ viewport()->setUpdatesEnabled(true);
+ repaintChanged();
+ }
+
+ if (res == KFind::NoMatch) { // at end
+ m_replace->displayFinalDialog();
+ delete m_replace;
+ m_replace = 0;
+ ensureCursorVisible();
+ //or if ( m_replace->shouldRestart() ) { reinit (w/o FromCursor) and call slotReplaceNext(); }
+ } else {
+ //m_replace->closeReplaceNextDialog();
+ }
+}
+
+
+void TextAreaWidget::slotDoFind()
+{
+ if (!m_findDlg) {
+ // Should really assert()
+ return;
+ }
+
+ delete m_find;
+ m_find = new KFind(m_findDlg->pattern(), m_findDlg->options(), this);
+ if (m_find->options() & KFindDialog::FromCursor) {
+ getCursorPosition(&m_findPara, &m_findIndex);
+ } else if (m_find->options() & KFindDialog::FindBackwards) {
+ m_findPara = paragraphs() - 1;
+ m_findIndex = paragraphLength(m_findPara) - 1;
+ } else {
+ m_findPara = 0;
+ m_findIndex = 0;
+ }
+
+ // Connect highlight signal to code which handles highlighting
+ // of found text.
+ connect(m_find, TQT_SIGNAL(highlight(const TQString &, int, int)),
+ this, TQT_SLOT(slotFindHighlight(const TQString &, int, int)));
+ connect(m_find, TQT_SIGNAL(findNext()), this, TQT_SLOT(slotFindNext()));
+
+ m_findDlg->close();
+ m_find->closeFindNextDialog();
+ slotFindNext();
+}
+
+
+void TextAreaWidget::slotFindNext()
+{
+ if (!m_find) {
+ // assert?
+ return;
+ }
+
+ KFind::Result res = KFind::NoMatch;
+ while (res == KFind::NoMatch) {
+ // If we're done.....
+ if (m_find->options() & KFindDialog::FindBackwards) {
+ if (m_findIndex == 0 && m_findPara == 0) {
+ break;
+ }
+ } else {
+ if (m_findPara == paragraphs() - 1 &&
+ m_findIndex == paragraphLength(m_findPara) - 1) {
+ break;
+ }
+ }
+
+ if (m_find->needData()) {
+ m_find->setData(text(m_findPara), m_findIndex);
+ }
+
+ res = m_find->find();
+
+ if (res == KFind::NoMatch) {
+ if (m_find->options() & KFindDialog::FindBackwards) {
+ if (m_findPara == 0) {
+ m_findIndex = 0;
+ } else {
+ m_findPara--;
+ m_findIndex = paragraphLength(m_findPara) - 1;
+ }
+ } else {
+ if (m_findPara == paragraphs() - 1) {
+ m_findIndex = paragraphLength(m_findPara) - 1;
+ } else {
+ m_findPara++;
+ m_findIndex = 0;
+ }
+ }
+ }
+ }
+
+ if (res == KFind::NoMatch) { // at end
+ m_find->displayFinalDialog();
+ delete m_find;
+ m_find = 0;
+ //or if ( m_find->shouldRestart() ) { reinit (w/o FromCursor) and call slotFindNext(); }
+ } else {
+ //m_find->closeFindNextDialog();
+ }
+}
+
+
+void TextAreaWidget::slotFind()
+{
+ if( text().isEmpty() ) // saves having to track the text changes
+ return;
+
+ if ( m_findDlg ) {
+ KWin::activateWindow( m_findDlg->winId() );
+ } else {
+ m_findDlg = new KFindDialog(false, this, "KHTML Text Area Find Dialog");
+ connect( m_findDlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotDoFind()) );
+ }
+ m_findDlg->show();
+}
+
+
+void TextAreaWidget::slotReplace()
+{
+ if( text().isEmpty() ) // saves having to track the text changes
+ return;
+
+ if ( m_repDlg ) {
+ KWin::activateWindow( m_repDlg->winId() );
+ } else {
+ m_repDlg = new KReplaceDialog(this, "KHTMLText Area Replace Dialog", 0,
+ TQStringList(), TQStringList(), false);
+ connect( m_repDlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotDoReplace()) );
+ }
+ m_repDlg->show();
+}
+
+
+bool TextAreaWidget::event( TQEvent *e )
+{
+ if ( e->type() == TQEvent::AccelAvailable && isReadOnly() ) {
+ TQKeyEvent* ke = (TQKeyEvent*) e;
+ if ( ke->state() & ControlButton ) {
+ switch ( ke->key() ) {
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ case Key_Home:
+ case Key_End:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ }
+ return KTextEdit::event( e );
+}
+
+// -------------------------------------------------------------------------
+
+RenderTextArea::RenderTextArea(HTMLTextAreaElementImpl *element)
+ : RenderFormElement(element)
+{
+ scrollbarsStyled = false;
+
+ TextAreaWidget *edit = new TextAreaWidget(element->wrap(), view());
+ setQWidget(edit);
+ const KHTMLSettings *settings = view()->part()->settings();
+ edit->setCheckSpellingEnabled( settings->autoSpellCheck() );
+ edit->setTabChangesFocus( ! settings->allowTabulation() );
+
+ connect(edit,TQT_SIGNAL(textChanged()),this,TQT_SLOT(slotTextChanged()));
+}
+
+RenderTextArea::~RenderTextArea()
+{
+ if ( element()->m_dirtyvalue ) {
+ element()->m_value = text();
+ element()->m_dirtyvalue = false;
+ }
+}
+
+void RenderTextArea::handleFocusOut()
+{
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ if ( w && element()->m_dirtyvalue ) {
+ element()->m_value = text();
+ element()->m_dirtyvalue = false;
+ }
+
+ if ( w && element()->m_changed ) {
+ element()->m_changed = false;
+ element()->onChange();
+ }
+}
+
+void RenderTextArea::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ const TQFontMetrics &m = style()->fontMetrics();
+ w->setTabStopWidth(8 * m.width(" "));
+ TQSize size( kMax(element()->cols(), 1L)*m.width('x') + w->frameWidth() +
+ w->verticalScrollBar()->sizeHint().width(),
+ kMax(element()->rows(), 1L)*m.lineSpacing() + w->frameWidth()*4 +
+ (w->wordWrap() == TQTextEdit::NoWrap ?
+ w->horizontalScrollBar()->sizeHint().height() : 0)
+ );
+
+ setIntrinsicWidth( size.width() );
+ setIntrinsicHeight( size.height() );
+
+ RenderFormElement::calcMinMaxWidth();
+}
+
+void RenderTextArea::setStyle(RenderStyle* _style)
+{
+ bool unsubmittedFormChange = element()->m_unsubmittedFormChange;
+
+ RenderFormElement::setStyle(_style);
+
+ widget()->blockSignals(true);
+ widget()->setAlignment(textAlignment());
+ widget()->blockSignals(false);
+
+ scrollbarsStyled = false;
+
+ element()->m_unsubmittedFormChange = unsubmittedFormChange;
+}
+
+void RenderTextArea::layout()
+{
+ KHTMLAssert( needsLayout() );
+
+ RenderFormElement::layout();
+
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+
+ if (!scrollbarsStyled) {
+ w->horizontalScrollBar()->setPalette(style()->palette());
+ w->verticalScrollBar()->setPalette(style()->palette());
+ scrollbarsStyled=true;
+ }
+}
+
+void RenderTextArea::updateFromElement()
+{
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ w->setReadOnly(element()->readOnly());
+ TQString elementText = element()->value().string();
+ if ( elementText != text() )
+ {
+ w->blockSignals(true);
+ int line, col;
+ w->getCursorPosition( &line, &col );
+ int cx = w->contentsX();
+ int cy = w->contentsY();
+ w->setText( elementText );
+ w->setCursorPosition( line, col );
+ w->scrollBy( cx, cy );
+ w->blockSignals(false);
+ }
+ element()->m_dirtyvalue = false;
+
+ RenderFormElement::updateFromElement();
+}
+
+void RenderTextArea::close( )
+{
+ element()->setValue( element()->defaultValue() );
+
+ RenderFormElement::close();
+}
+
+
+TQString RenderTextArea::text()
+{
+ TQString txt;
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+
+ if(element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
+ // yeah, TQTextEdit has no accessor for getting the visually wrapped text
+ for (int p=0; p < w->paragraphs(); ++p) {
+ int ll = 0;
+ int lindex = w->lineOfChar(p, 0);
+ TQString paragraphText = w->text(p);
+ int pl = w->paragraphLength(p);
+ paragraphText = paragraphText.left(pl); //Snip invented space.
+ for (int l = 0; l < pl; ++l) {
+ if (lindex != w->lineOfChar(p, l)) {
+ paragraphText.insert(l+ll++, TQString::fromLatin1("\n"));
+ lindex = w->lineOfChar(p, l);
+ }
+ }
+ txt += paragraphText;
+ if (p < w->paragraphs() - 1)
+ txt += TQString::fromLatin1("\n");
+ }
+ }
+ else
+ txt = w->text();
+
+ return txt;
+}
+
+int RenderTextArea::queryParagraphInfo(int para, Mode m, int param) {
+ /* We have to be a bit careful here, as we need to match up the positions
+ to what our value returns here*/
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int length = 0;
+
+ bool physWrap = element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical;
+
+ TQString paragraphText = w->text(para);
+ int pl = w->paragraphLength(para);
+ int physicalPL = pl;
+ if (m == ParaPortionLength)
+ pl = param;
+
+ if (physWrap) {
+ //Go through all the chars of paragraph, and count line changes, chars, etc.
+ int lindex = w->lineOfChar(para, 0);
+ for (int c = 0; c < pl; ++c) {
+ ++length;
+ // Is there a change after this char?
+ if (c+1 < physicalPL && lindex != w->lineOfChar(para, c+1)) {
+ lindex = w->lineOfChar(para, c+1);
+ ++length;
+ }
+ if (m == ParaPortionOffset && length > param)
+ return c;
+ }
+ } else {
+ //Make sure to count the LF, CR as appropriate. ### this is stupid now, simplify
+ for (int c = 0; c < pl; ++c) {
+ ++length;
+ if (m == ParaPortionOffset && length > param)
+ return c;
+ }
+ }
+ if (m == ParaPortionOffset)
+ return pl;
+ if (m == ParaPortionLength)
+ return length;
+ return length + 1;
+}
+
+long RenderTextArea::computeCharOffset(int para, int index) {
+ if (para < 0)
+ return 0;
+
+ long pos = 0;
+ for (int cp = 0; cp < para; ++cp)
+ pos += queryParagraphInfo(cp, ParaLength);
+
+ if (index >= 0)
+ pos += queryParagraphInfo(para, ParaPortionLength, index);
+ return pos;
+}
+
+void RenderTextArea::computeParagraphAndIndex(long offset, int* para, int* index) {
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+
+ if (!w->paragraphs()) {
+ *para = -1;
+ *index = -1;
+ return;
+ }
+
+ //Find the paragraph that contains us..
+ int containingPar = 0;
+ long endPos = 0;
+ long startPos = 0;
+ for (int p = 0; p < w->paragraphs(); ++p) {
+ int len = queryParagraphInfo(p, ParaLength);
+ endPos += len;
+ if (endPos > offset) {
+ containingPar = p;
+ break;
+ }
+ startPos += len;
+ }
+
+ *para = containingPar;
+
+ //Now, scan within the paragraph to find the position..
+ long localOffset = offset - startPos;
+
+ *index = queryParagraphInfo(containingPar, ParaPortionOffset, localOffset);
+}
+
+void RenderTextArea::highLightWord( unsigned int length, unsigned int pos )
+{
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ if ( w )
+ w->highLightWord( length, pos );
+}
+
+
+void RenderTextArea::slotTextChanged()
+{
+ element()->m_dirtyvalue = true;
+ element()->m_changed = true;
+ if (element()->m_value != text())
+ element()->m_unsubmittedFormChange = true;
+}
+
+void RenderTextArea::select()
+{
+ static_cast<TextAreaWidget *>(m_widget)->selectAll();
+}
+
+long RenderTextArea::selectionStart()
+{
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int para, index, dummy1, dummy2;
+ w->getSelection(&para, &index, &dummy1, &dummy2);
+ if (para == -1 || index == -1)
+ w->getCursorPosition(&para, &index);
+
+ return computeCharOffset(para, index);
+}
+
+long RenderTextArea::selectionEnd()
+{
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int para, index, dummy1, dummy2;
+ w->getSelection(&dummy1, &dummy2, &para, &index);
+ if (para == -1 || index == -1)
+ w->getCursorPosition(&para, &index);
+
+ return computeCharOffset(para, index);
+}
+
+void RenderTextArea::setSelectionStart(long offset) {
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int fromPara, fromIndex, toPara, toIndex;
+ w->getSelection(&fromPara, &fromIndex, &toPara, &toIndex);
+ computeParagraphAndIndex(offset, &fromPara, &fromIndex);
+ if (toPara == -1 || toIndex == -1) {
+ toPara = fromPara;
+ toIndex = fromIndex;
+ }
+ w->setSelection(fromPara, fromIndex, toPara, toIndex);
+}
+
+void RenderTextArea::setSelectionEnd(long offset) {
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int fromPara, fromIndex, toPara, toIndex;
+ w->getSelection(&fromPara, &fromIndex, &toPara, &toIndex);
+ computeParagraphAndIndex(offset, &toPara, &toIndex);
+ w->setSelection(fromPara, fromIndex, toPara, toIndex);
+}
+
+void RenderTextArea::setSelectionRange(long start, long end) {
+ TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
+ int fromPara, fromIndex, toPara, toIndex;
+ computeParagraphAndIndex(start, &fromPara, &fromIndex);
+ computeParagraphAndIndex(end, &toPara, &toIndex);
+ w->setSelection(fromPara, fromIndex, toPara, toIndex);
+}
+// ---------------------------------------------------------------------------
+
+#include "render_form.moc"
diff --git a/tdehtml/rendering/render_form.h b/tdehtml/rendering/render_form.h
new file mode 100644
index 000000000..d1611c1e0
--- /dev/null
+++ b/tdehtml/rendering/render_form.h
@@ -0,0 +1,511 @@
+/*
+ * 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-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.
+ *
+ */
+#ifndef RENDER_FORM_H
+#define RENDER_FORM_H
+
+#include "rendering/render_replaced.h"
+#include "rendering/render_image.h"
+#include "rendering/render_flow.h"
+#include "rendering/render_style.h"
+#include "html/html_formimpl.h"
+
+class TQWidget;
+class TQLineEdit;
+class QListboxItem;
+
+#include <ktextedit.h>
+#include <kurlrequester.h>
+#include <klineedit.h>
+#include <tqcheckbox.h>
+#include <tqradiobutton.h>
+#include <tqpushbutton.h>
+#include <tqhbox.h>
+#include <klistbox.h>
+#include <kcombobox.h>
+#include "dom/dom_misc.h"
+
+class KHTMLPartBrowserExtension;
+class KSpell;
+class KFindDialog;
+class KReplaceDialog;
+class KFind;
+class KReplace;
+class KAction;
+class KURLRequester;
+
+namespace DOM {
+ class HTMLFormElementImpl;
+ class HTMLInputElementImpl;
+ class HTMLSelectElementImpl;
+ class HTMLGenericFormElementImpl;
+ class HTMLTextAreaElementImpl;
+}
+
+namespace tdehtml {
+
+class DocLoader;
+
+// -------------------------------------------------------------------------
+
+class RenderFormElement : public tdehtml::RenderWidget
+{
+public:
+ RenderFormElement(DOM::HTMLGenericFormElementImpl* node);
+ virtual ~RenderFormElement();
+
+ virtual const char *renderName() const { return "RenderForm"; }
+
+ virtual bool isFormElement() const { return true; }
+
+ // form elements never have padding
+ virtual int paddingTop() const { return 0; }
+ virtual int paddingBottom() const { return 0; }
+ virtual int paddingLeft() const { return 0; }
+ virtual int paddingRight() const { return 0; }
+
+ virtual void updateFromElement();
+
+ virtual void layout();
+ virtual short baselinePosition( bool ) const;
+
+ DOM::HTMLGenericFormElementImpl *element() const
+ { return static_cast<DOM::HTMLGenericFormElementImpl*>(RenderObject::element()); }
+
+protected:
+ virtual bool isRenderButton() const { return false; }
+ virtual bool isEditable() const { return false; }
+ TQ_Alignment textAlignment() const;
+
+ TQPoint m_mousePos;
+ int m_state;
+};
+
+// -------------------------------------------------------------------------
+
+// generic class for all buttons
+class RenderButton : public RenderFormElement
+{
+ Q_OBJECT
+public:
+ RenderButton(DOM::HTMLGenericFormElementImpl* node);
+
+ virtual const char *renderName() const { return "RenderButton"; }
+
+ virtual short baselinePosition( bool ) const;
+
+ // don't even think about making this method virtual!
+ DOM::HTMLInputElementImpl* element() const
+ { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
+
+protected:
+ virtual bool isRenderButton() const { return true; }
+};
+
+// -------------------------------------------------------------------------
+
+class RenderCheckBox : public RenderButton
+{
+ Q_OBJECT
+public:
+ RenderCheckBox(DOM::HTMLInputElementImpl* node);
+
+ virtual const char *renderName() const { return "RenderCheckBox"; }
+ virtual void updateFromElement();
+ virtual void calcMinMaxWidth();
+
+ virtual bool handleEvent(const DOM::EventImpl&) { return false; }
+
+ TQCheckBox *widget() const { return static_cast<TQCheckBox*>(m_widget); }
+
+public slots:
+ virtual void slotStateChanged(int state);
+};
+
+// -------------------------------------------------------------------------
+
+class RenderRadioButton : public RenderButton
+{
+ Q_OBJECT
+public:
+ RenderRadioButton(DOM::HTMLInputElementImpl* node);
+
+ virtual const char *renderName() const { return "RenderRadioButton"; }
+
+ virtual void calcMinMaxWidth();
+ virtual void updateFromElement();
+
+ virtual bool handleEvent(const DOM::EventImpl&) { return false; }
+
+ TQRadioButton *widget() const { return static_cast<TQRadioButton*>(m_widget); }
+
+public slots:
+ virtual void slotToggled(bool);
+};
+
+// -------------------------------------------------------------------------
+
+class RenderSubmitButton : public RenderButton
+{
+public:
+ RenderSubmitButton(DOM::HTMLInputElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderSubmitButton"; }
+
+ virtual void calcMinMaxWidth();
+ virtual void updateFromElement();
+ virtual short baselinePosition( bool ) const;
+private:
+ TQString rawText();
+};
+
+// -------------------------------------------------------------------------
+
+class RenderImageButton : public RenderImage
+{
+public:
+ RenderImageButton(DOM::HTMLInputElementImpl *element)
+ : RenderImage(element) {}
+
+ virtual const char *renderName() const { return "RenderImageButton"; }
+};
+
+
+// -------------------------------------------------------------------------
+
+class RenderResetButton : public RenderSubmitButton
+{
+public:
+ RenderResetButton(DOM::HTMLInputElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderResetButton"; }
+
+};
+
+// -------------------------------------------------------------------------
+
+class RenderPushButton : public RenderSubmitButton
+{
+public:
+ RenderPushButton(DOM::HTMLInputElementImpl *element)
+ : RenderSubmitButton(element) {}
+
+};
+
+// -------------------------------------------------------------------------
+
+class RenderLineEdit : public RenderFormElement
+{
+ Q_OBJECT
+public:
+ RenderLineEdit(DOM::HTMLInputElementImpl *element);
+
+ virtual void calcMinMaxWidth();
+
+ virtual const char *renderName() const { return "RenderLineEdit"; }
+ virtual void updateFromElement();
+ virtual void setStyle(RenderStyle *style);
+
+ void select();
+
+ KLineEdit *widget() const { return static_cast<KLineEdit*>(m_widget); }
+ DOM::HTMLInputElementImpl* element() const
+ { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
+ void highLightWord( unsigned int length, unsigned int pos );
+
+ long selectionStart();
+ long selectionEnd();
+ void setSelectionStart(long pos);
+ void setSelectionEnd(long pos);
+ void setSelectionRange(long start, long end);
+public slots:
+ void slotReturnPressed();
+ void slotTextChanged(const TQString &string);
+protected:
+ virtual void handleFocusOut();
+
+private:
+ virtual bool isEditable() const { return true; }
+ virtual bool canHaveBorder() const { return true; }
+};
+
+// -------------------------------------------------------------------------
+
+class LineEditWidget : public KLineEdit
+{
+ Q_OBJECT
+public:
+ LineEditWidget(DOM::HTMLInputElementImpl* input,
+ KHTMLView* view, TQWidget* parent);
+ ~LineEditWidget();
+ void highLightWord( unsigned int length, unsigned int pos );
+
+protected:
+ virtual bool event( TQEvent *e );
+ virtual void mouseMoveEvent(TQMouseEvent *e);
+ virtual TQPopupMenu *createPopupMenu();
+private slots:
+ void extendedMenuActivated( int id);
+ void slotCheckSpelling();
+ void slotSpellCheckReady( KSpell *s );
+ void slotSpellCheckDone( const TQString &s );
+ void spellCheckerMisspelling( const TQString &text, const TQStringList &, unsigned int pos);
+ void spellCheckerCorrected( const TQString &, const TQString &, unsigned int );
+ void spellCheckerFinished();
+ void slotRemoveFromHistory( const TQString & );
+
+private:
+ enum LineEditMenuID {
+ ClearHistory,
+ EditHistory
+ };
+ DOM::HTMLInputElementImpl* m_input;
+ KHTMLView* m_view;
+ KSpell *m_spell;
+ KAction *m_spellAction;
+};
+
+// -------------------------------------------------------------------------
+
+class RenderFieldset : public RenderBlock
+{
+public:
+ RenderFieldset(DOM::HTMLGenericFormElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderFieldSet"; }
+ virtual RenderObject* layoutLegend(bool relayoutChildren);
+ virtual void setStyle(RenderStyle* _style);
+
+protected:
+ virtual void paintBoxDecorations(PaintInfo& pI, int _tx, int _ty);
+ void paintBorderMinusLegend(TQPainter *p, int _tx, int _ty, int w,
+ int h, const RenderStyle *style, int lx, int lw);
+ RenderObject* findLegend();
+};
+
+// -------------------------------------------------------------------------
+
+class RenderFileButton : public RenderFormElement
+{
+ Q_OBJECT
+public:
+ RenderFileButton(DOM::HTMLInputElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderFileButton"; }
+ virtual void calcMinMaxWidth();
+ virtual void updateFromElement();
+ void select();
+
+ KURLRequester *widget() const { return static_cast<KURLRequester*>(m_widget); }
+
+ DOM::HTMLInputElementImpl *element() const
+ { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
+
+public slots:
+ void slotReturnPressed();
+ void slotTextChanged(const TQString &string);
+ void slotUrlSelected(const TQString &string);
+
+protected:
+ virtual void handleFocusOut();
+
+ virtual bool isEditable() const { return true; }
+ virtual bool canHaveBorder() const { return true; }
+ virtual bool acceptsSyntheticEvents() const { return false; }
+
+ bool m_clicked;
+ bool m_haveFocus;
+};
+
+
+// -------------------------------------------------------------------------
+
+class RenderLabel : public RenderFormElement
+{
+public:
+ RenderLabel(DOM::HTMLGenericFormElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderLabel"; }
+
+protected:
+ virtual bool canHaveBorder() const { return true; }
+};
+
+
+// -------------------------------------------------------------------------
+
+class RenderLegend : public RenderBlock
+{
+public:
+ RenderLegend(DOM::HTMLGenericFormElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderLegend"; }
+};
+
+// -------------------------------------------------------------------------
+
+class ComboBoxWidget : public KComboBox
+{
+public:
+ ComboBoxWidget(TQWidget *parent);
+
+protected:
+ virtual bool event(TQEvent *);
+ virtual bool eventFilter(TQObject *dest, TQEvent *e);
+};
+
+// -------------------------------------------------------------------------
+
+class RenderSelect : public RenderFormElement
+{
+ Q_OBJECT
+public:
+ RenderSelect(DOM::HTMLSelectElementImpl *element);
+
+ virtual const char *renderName() const { return "RenderSelect"; }
+
+ virtual void calcMinMaxWidth();
+ virtual void layout();
+
+ void setOptionsChanged(bool _optionsChanged);
+
+ bool selectionChanged() { return m_selectionChanged; }
+ void setSelectionChanged(bool _selectionChanged) { m_selectionChanged = _selectionChanged; }
+ virtual void updateFromElement();
+
+ void updateSelection();
+
+ DOM::HTMLSelectElementImpl *element() const
+ { return static_cast<DOM::HTMLSelectElementImpl*>(RenderObject::element()); }
+
+protected:
+ KListBox *createListBox();
+ ComboBoxWidget *createComboBox();
+
+ unsigned m_size;
+ bool m_multiple;
+ bool m_useListBox;
+ bool m_selectionChanged;
+ bool m_ignoreSelectEvents;
+ bool m_optionsChanged;
+
+protected slots:
+ void slotSelected(int index);
+ void slotSelectionChanged();
+};
+
+// -------------------------------------------------------------------------
+class TextAreaWidget : public KTextEdit
+{
+ Q_OBJECT
+public:
+ TextAreaWidget(int wrap, TQWidget* parent);
+ virtual ~TextAreaWidget();
+
+protected:
+ virtual bool event (TQEvent *e );
+ virtual TQPopupMenu *createPopupMenu(const TQPoint& pos);
+ virtual TQPopupMenu* createPopupMenu() { return KTextEdit::createPopupMenu(); }
+private slots:
+ void slotFind();
+ void slotDoFind();
+ void slotFindNext();
+ void slotReplace();
+ void slotDoReplace();
+ void slotReplaceNext();
+ void slotReplaceText(const TQString&, int, int, int);
+ void slotFindHighlight(const TQString&, int, int);
+private:
+ KFindDialog *m_findDlg;
+ KFind *m_find;
+ KReplaceDialog *m_repDlg;
+ KReplace *m_replace;
+ KAction *m_findAction;
+ KAction *m_findNextAction;
+ KAction *m_replaceAction;
+ int m_findIndex, m_findPara;
+ int m_repIndex, m_repPara;
+};
+
+
+// -------------------------------------------------------------------------
+
+class RenderTextArea : public RenderFormElement
+{
+ Q_OBJECT
+public:
+ RenderTextArea(DOM::HTMLTextAreaElementImpl *element);
+ ~RenderTextArea();
+
+ virtual const char *renderName() const { return "RenderTextArea"; }
+ virtual void calcMinMaxWidth();
+ virtual void layout();
+ virtual void setStyle(RenderStyle *style);
+
+ virtual void close ( );
+ virtual void updateFromElement();
+
+ // don't even think about making this method virtual!
+ TextAreaWidget *widget() const { return static_cast<TextAreaWidget*>(m_widget); }
+ DOM::HTMLTextAreaElementImpl* element() const
+ { return static_cast<DOM::HTMLTextAreaElementImpl*>(RenderObject::element()); }
+
+ TQString text();
+ void highLightWord( unsigned int length, unsigned int pos );
+
+ void select();
+
+ long selectionStart();
+ long selectionEnd();
+ void setSelectionStart(long pos);
+ void setSelectionEnd(long pos);
+ void setSelectionRange(long start, long end);
+protected slots:
+ void slotTextChanged();
+
+protected:
+ virtual void handleFocusOut();
+
+ virtual bool isEditable() const { return true; }
+ virtual bool canHaveBorder() const { return true; }
+
+ bool scrollbarsStyled;
+private:
+ //Convert para, index -> offset
+ long computeCharOffset(int para, int index);
+
+ //Convert offset -> para, index
+ void computeParagraphAndIndex(long offset, int* para, int* index);
+
+ //Helper for doing the conversion..
+ enum Mode { ParaLength, //Returns the length of the entire paragraph
+ ParaPortionLength, //Return length of paragraph portion set by threshold
+ ParaPortionOffset }; //Return offset that matches the length threshold.
+ int queryParagraphInfo(int para, Mode m, int param = -1);
+};
+
+// -------------------------------------------------------------------------
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_frames.cpp b/tdehtml/rendering/render_frames.cpp
new file mode 100644
index 000000000..03d55fbfd
--- /dev/null
+++ b/tdehtml/rendering/render_frames.cpp
@@ -0,0 +1,1025 @@
+/**
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ * (C) 2003 Apple Computer, Inc.
+ * (C) 2005 Niels Leenheer <niels.leenheer@gmail.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_LAYOUT
+
+#include "rendering/render_frames.h"
+#include "rendering/render_canvas.h"
+#include "html/html_baseimpl.h"
+#include "html/html_objectimpl.h"
+#include "html/htmltokenizer.h"
+#include "misc/htmlattrs.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmltags.h"
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "misc/knsplugininstaller.h"
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <tqtimer.h>
+#include <tqpainter.h>
+#include <tqcursor.h>
+
+#include <assert.h>
+
+using namespace tdehtml;
+using namespace DOM;
+
+RenderFrameSet::RenderFrameSet( HTMLFrameSetElementImpl *frameSet)
+ : RenderBox(frameSet)
+{
+ // init RenderObject attributes
+ setInline(false);
+
+ for (int k = 0; k < 2; ++k) {
+ m_gridLen[k] = -1;
+ m_gridDelta[k] = 0;
+ m_gridLayout[k] = 0;
+ }
+
+ m_resizing = m_clientresizing= false;
+
+ m_cursor = Qt::ArrowCursor;
+
+ m_hSplit = -1;
+ m_vSplit = -1;
+
+ m_hSplitVar = 0;
+ m_vSplitVar = 0;
+}
+
+RenderFrameSet::~RenderFrameSet()
+{
+ for (int k = 0; k < 2; ++k) {
+ delete [] m_gridLayout[k];
+ delete [] m_gridDelta[k];
+ }
+ delete [] m_hSplitVar;
+ delete [] m_vSplitVar;
+}
+
+bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox)
+{
+ RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
+
+ bool inside = m_resizing || canResize(_x, _y);
+
+ if ( inside && element() && !element()->noResize() && !info.readonly()) {
+ info.setInnerNode(element());
+ info.setInnerNonSharedNode(element());
+ }
+
+ return inside || m_clientresizing;
+}
+
+void RenderFrameSet::layout( )
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ if ( !parent()->isFrameSet() ) {
+ KHTMLView* view = canvas()->view();
+ m_width = view ? view->visibleWidth() : 0;
+ m_height = view ? view->visibleHeight() : 0;
+ }
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(FrameSet)::layout( ) width=" << width() << ", height=" << height() << endl;
+#endif
+
+ int remainingLen[2];
+ remainingLen[1] = m_width - (element()->totalCols()-1)*element()->border();
+ if(remainingLen[1]<0) remainingLen[1]=0;
+ remainingLen[0] = m_height - (element()->totalRows()-1)*element()->border();
+ if(remainingLen[0]<0) remainingLen[0]=0;
+
+ int availableLen[2];
+ availableLen[0] = remainingLen[0];
+ availableLen[1] = remainingLen[1];
+
+ if (m_gridLen[0] != element()->totalRows() || m_gridLen[1] != element()->totalCols()) {
+ // number of rows or cols changed
+ // need to zero out the deltas
+ m_gridLen[0] = element()->totalRows();
+ m_gridLen[1] = element()->totalCols();
+ for (int k = 0; k < 2; ++k) {
+ delete [] m_gridDelta[k];
+ m_gridDelta[k] = new int[m_gridLen[k]];
+ delete [] m_gridLayout[k];
+ m_gridLayout[k] = new int[m_gridLen[k]];
+ for (int i = 0; i < m_gridLen[k]; ++i)
+ m_gridDelta[k][i] = 0;
+ }
+ }
+
+ for (int k = 0; k < 2; ++k) {
+ int totalRelative = 0;
+ int totalFixed = 0;
+ int totalPercent = 0;
+ int countRelative = 0;
+ int countFixed = 0;
+ int countPercent = 0;
+ int gridLen = m_gridLen[k];
+ int* gridDelta = m_gridDelta[k];
+ tdehtml::Length* grid = k ? element()->m_cols : element()->m_rows;
+ int* gridLayout = m_gridLayout[k];
+
+ if (grid) {
+ // First we need to investigate how many columns of each type we have and
+ // how much space these columns are going to require.
+ for (int i = 0; i < gridLen; ++i) {
+ // Count the total length of all of the fixed columns/rows -> totalFixed
+ // Count the number of columns/rows which are fixed -> countFixed
+ if (grid[i].isFixed()) {
+ gridLayout[i] = kMax(grid[i].value(), 0);
+ totalFixed += gridLayout[i];
+ countFixed++;
+ }
+
+ // Count the total percentage of all of the percentage columns/rows -> totalPercent
+ // Count the number of columns/rows which are percentages -> countPercent
+ if (grid[i].isPercent()) {
+ gridLayout[i] = kMax(grid[i].width(availableLen[k]), 0);
+ totalPercent += gridLayout[i];
+ countPercent++;
+ }
+
+ // Count the total relative of all the relative columns/rows -> totalRelative
+ // Count the number of columns/rows which are relative -> countRelative
+ if (grid[i].isRelative()) {
+ totalRelative += kMax(grid[i].value(), 1);
+ countRelative++;
+ }
+ }
+
+ // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed
+ // columns/rows we need to proportionally adjust their size.
+ if (totalFixed > remainingLen[k]) {
+ int remainingFixed = remainingLen[k];
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isFixed()) {
+ gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed;
+ remainingLen[k] -= gridLayout[i];
+ }
+ }
+ } else {
+ remainingLen[k] -= totalFixed;
+ }
+
+ // Percentage columns/rows are our second priority. Divide the remaining space proportionally
+ // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative
+ // to 100%, but to the total percentage. For example, if there are three columns, each of 75%,
+ // and the available space is 300px, each column will become 100px in width.
+ if (totalPercent > remainingLen[k]) {
+ int remainingPercent = remainingLen[k];
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isPercent()) {
+ gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent;
+ remainingLen[k] -= gridLayout[i];
+ }
+ }
+ } else {
+ remainingLen[k] -= totalPercent;
+ }
+
+ // Relative columns/rows are our last priority. Divide the remaining space proportionally
+ // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*.
+ if (countRelative) {
+ int lastRelative = 0;
+ int remainingRelative = remainingLen[k];
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isRelative()) {
+ gridLayout[i] = (kMax(grid[i].value(), 1) * remainingRelative) / totalRelative;
+ remainingLen[k] -= gridLayout[i];
+ lastRelative = i;
+ }
+ }
+
+ // If we could not evently distribute the available space of all of the relative
+ // columns/rows, the remainder will be added to the last column/row.
+ // For example: if we have a space of 100px and three columns (*,*,*), the remainder will
+ // be 1px and will be added to the last column: 33px, 33px, 34px.
+ if (remainingLen[k]) {
+ gridLayout[lastRelative] += remainingLen[k];
+ remainingLen[k] = 0;
+ }
+ }
+
+ // If we still have some left over space we need to divide it over the already existing
+ // columns/rows
+ if (remainingLen[k]) {
+ // Our first priority is to spread if over the percentage columns. The remaining
+ // space is spread evenly, for example: if we have a space of 100px, the columns
+ // definition of 25%,25% used to result in two columns of 25px. After this the
+ // columns will each be 50px in width.
+ if (countPercent && totalPercent) {
+ int remainingPercent = remainingLen[k];
+ int changePercent = 0;
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isPercent()) {
+ changePercent = (remainingPercent * gridLayout[i]) / totalPercent;
+ gridLayout[i] += changePercent;
+ remainingLen[k] -= changePercent;
+ }
+ }
+ } else if (totalFixed) {
+ // Our last priority is to spread the remaining space over the fixed columns.
+ // For example if we have 100px of space and two column of each 40px, both
+ // columns will become exactly 50px.
+ int remainingFixed = remainingLen[k];
+ int changeFixed = 0;
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isFixed()) {
+ changeFixed = (remainingFixed * gridLayout[i]) / totalFixed;
+ gridLayout[i] += changeFixed;
+ remainingLen[k] -= changeFixed;
+ }
+ }
+ }
+ }
+
+ // If we still have some left over space we probably ended up with a remainder of
+ // a division. We can not spread it evenly anymore. If we have any percentage
+ // columns/rows simply spread the remainder equally over all available percentage columns,
+ // regardless of their size.
+ if (remainingLen[k] && countPercent) {
+ int remainingPercent = remainingLen[k];
+ int changePercent = 0;
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isPercent()) {
+ changePercent = remainingPercent / countPercent;
+ gridLayout[i] += changePercent;
+ remainingLen[k] -= changePercent;
+ }
+ }
+ }
+
+ // If we don't have any percentage columns/rows we only have fixed columns. Spread
+ // the remainder equally over all fixed columns/rows.
+ else if (remainingLen[k] && countFixed) {
+ int remainingFixed = remainingLen[k];
+ int changeFixed = 0;
+
+ for (int i = 0; i < gridLen; ++i) {
+ if (grid[i].isFixed()) {
+ changeFixed = remainingFixed / countFixed;
+ gridLayout[i] += changeFixed;
+ remainingLen[k] -= changeFixed;
+ }
+ }
+ }
+
+ // Still some left over... simply add it to the last column, because it is impossible
+ // spread it evenly or equally.
+ if (remainingLen[k]) {
+ gridLayout[gridLen - 1] += remainingLen[k];
+ }
+
+ // now we have the final layout, distribute the delta over it
+ bool worked = true;
+ for (int i = 0; i < gridLen; ++i) {
+ if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
+ worked = false;
+ gridLayout[i] += gridDelta[i];
+ }
+ // now the delta's broke something, undo it and reset deltas
+ if (!worked)
+ for (int i = 0; i < gridLen; ++i) {
+ gridLayout[i] -= gridDelta[i];
+ gridDelta[i] = 0;
+ }
+ }
+ else
+ gridLayout[0] = remainingLen[k];
+ }
+
+ positionFrames();
+
+ RenderObject *child = firstChild();
+ if ( !child )
+ goto end2;
+
+ if(!m_hSplitVar && !m_vSplitVar)
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "calculationg fixed Splitters" << endl;
+#endif
+ if(!m_vSplitVar && element()->totalCols() > 1)
+ {
+ m_vSplitVar = new bool[element()->totalCols()];
+ for(int i = 0; i < element()->totalCols(); i++) m_vSplitVar[i] = true;
+ }
+ if(!m_hSplitVar && element()->totalRows() > 1)
+ {
+ m_hSplitVar = new bool[element()->totalRows()];
+ for(int i = 0; i < element()->totalRows(); i++) m_hSplitVar[i] = true;
+ }
+
+ for(int r = 0; r < element()->totalRows(); r++)
+ {
+ for(int c = 0; c < element()->totalCols(); c++)
+ {
+ bool fixed = false;
+
+ if ( child->isFrameSet() )
+ fixed = static_cast<RenderFrameSet *>(child)->element()->noResize();
+ else
+ fixed = static_cast<RenderFrame *>(child)->element()->noResize();
+
+ if(fixed)
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "found fixed cell " << r << "/" << c << "!" << endl;
+#endif
+ if( element()->totalCols() > 1)
+ {
+ if(c>0) m_vSplitVar[c-1] = false;
+ m_vSplitVar[c] = false;
+ }
+ if( element()->totalRows() > 1)
+ {
+ if(r>0) m_hSplitVar[r-1] = false;
+ m_hSplitVar[r] = false;
+ }
+ child = child->nextSibling();
+ if(!child) goto end2;
+ }
+#ifdef DEBUG_LAYOUT
+ else
+ kdDebug( 6031 ) << "not fixed: " << r << "/" << c << "!" << endl;
+#endif
+ }
+ }
+
+ }
+ RenderContainer::layout();
+ end2:
+ setNeedsLayout(false);
+}
+
+void RenderFrameSet::positionFrames()
+{
+ int r;
+ int c;
+
+ RenderObject *child = firstChild();
+ if ( !child )
+ return;
+
+ // NodeImpl *child = _first;
+ // if(!child) return;
+
+ int yPos = 0;
+
+ for(r = 0; r < element()->totalRows(); r++)
+ {
+ int xPos = 0;
+ for(c = 0; c < element()->totalCols(); c++)
+ {
+ child->setPos( xPos, yPos );
+#ifdef DEBUG_LAYOUT
+ kdDebug(6040) << "child frame at (" << xPos << "/" << yPos << ") size (" << m_gridLayout[1][c] << "/" << m_gridLayout[0][r] << ")" << endl;
+#endif
+ // has to be resized and itself resize its contents
+ if ((m_gridLayout[1][c] != child->width()) || (m_gridLayout[0][r] != child->height())) {
+ child->setWidth( m_gridLayout[1][c] );
+ child->setHeight( m_gridLayout[0][r] );
+ child->setNeedsLayout(true);
+ child->layout();
+ }
+
+ xPos += m_gridLayout[1][c] + element()->border();
+ child = child->nextSibling();
+
+ if ( !child )
+ return;
+
+ }
+
+ yPos += m_gridLayout[0][r] + element()->border();
+ }
+
+ // all the remaining frames are hidden to avoid ugly
+ // spurious unflowed frames
+ while ( child ) {
+ child->setWidth( 0 );
+ child->setHeight( 0 );
+ child->setNeedsLayout(false);
+
+ child = child->nextSibling();
+ }
+}
+
+bool RenderFrameSet::userResize( MouseEventImpl *evt )
+{
+ if (needsLayout()) return false;
+
+ bool res = false;
+ int _x = evt->clientX();
+ int _y = evt->clientY();
+
+ if ( !m_resizing && evt->id() == EventImpl::MOUSEMOVE_EVENT || evt->id() == EventImpl::MOUSEDOWN_EVENT )
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "mouseEvent:check" << endl;
+#endif
+
+ m_hSplit = -1;
+ m_vSplit = -1;
+ //bool resizePossible = true;
+
+ // check if we're over a horizontal or vertical boundary
+ int pos = m_gridLayout[1][0] + xPos();
+ for(int c = 1; c < element()->totalCols(); c++)
+ {
+ if(_x >= pos && _x <= pos+element()->border())
+ {
+ if(m_vSplitVar && m_vSplitVar[c-1] == true) m_vSplit = c-1;
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "vsplit!" << endl;
+#endif
+ res = true;
+ break;
+ }
+ pos += m_gridLayout[1][c] + element()->border();
+ }
+
+ pos = m_gridLayout[0][0] + yPos();
+ for(int r = 1; r < element()->totalRows(); r++)
+ {
+ if( _y >= pos && _y <= pos+element()->border())
+ {
+ if(m_hSplitVar && m_hSplitVar[r-1] == true) m_hSplit = r-1;
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "hsplitvar = " << m_hSplitVar << endl;
+ kdDebug( 6031 ) << "hsplit!" << endl;
+#endif
+ res = true;
+ break;
+ }
+ pos += m_gridLayout[0][r] + element()->border();
+ }
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << m_hSplit << "/" << m_vSplit << endl;
+#endif
+ }
+
+
+ m_cursor = Qt::ArrowCursor;
+ if(m_hSplit != -1 && m_vSplit != -1)
+ m_cursor = Qt::SizeAllCursor;
+ else if( m_vSplit != -1 )
+ m_cursor = Qt::SizeHorCursor;
+ else if( m_hSplit != -1 )
+ m_cursor = Qt::SizeVerCursor;
+
+ if(!m_resizing && evt->id() == EventImpl::MOUSEDOWN_EVENT)
+ {
+ setResizing(true);
+ TDEApplication::setOverrideCursor(TQCursor(m_cursor));
+ m_vSplitPos = _x;
+ m_hSplitPos = _y;
+ m_oldpos = -1;
+ }
+
+ // ### check the resize is not going out of bounds.
+ if(m_resizing && evt->id() == EventImpl::MOUSEUP_EVENT)
+ {
+ setResizing(false);
+ TDEApplication::restoreOverrideCursor();
+
+ if(m_vSplit != -1 )
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "split xpos=" << _x << endl;
+#endif
+ int delta = m_vSplitPos - _x;
+ m_gridDelta[1][m_vSplit] -= delta;
+ m_gridDelta[1][m_vSplit+1] += delta;
+ }
+ if(m_hSplit != -1 )
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6031 ) << "split ypos=" << _y << endl;
+#endif
+ int delta = m_hSplitPos - _y;
+ m_gridDelta[0][m_hSplit] -= delta;
+ m_gridDelta[0][m_hSplit+1] += delta;
+ }
+
+ // this just schedules the relayout
+ // important, otherwise the moving indicator is not correctly erased
+ setNeedsLayout(true);
+ }
+
+ KHTMLView *view = canvas()->view();
+ if ((m_resizing || evt->id() == EventImpl::MOUSEUP_EVENT) && view) {
+ TQPainter paint( view );
+ paint.setPen( Qt::gray );
+ paint.setBrush( Qt::gray );
+ paint.setRasterOp( TQt::XorROP );
+ TQRect r(xPos(), yPos(), width(), height());
+ const int rBord = 3;
+ int sw = element()->border();
+ int p = m_resizing ? (m_vSplit > -1 ? _x : _y) : -1;
+ if (m_vSplit > -1) {
+ if ( m_oldpos >= 0 )
+ paint.drawRect( m_oldpos + sw/2 - rBord , r.y(),
+ 2*rBord, r.height() );
+ if ( p >= 0 )
+ paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() );
+ } else {
+ if ( m_oldpos >= 0 )
+ paint.drawRect( r.x(), m_oldpos + sw/2 - rBord,
+ r.width(), 2*rBord );
+ if ( p >= 0 )
+ paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord );
+ }
+ m_oldpos = p;
+ }
+
+ return res;
+}
+
+void RenderFrameSet::setResizing(bool e)
+{
+ m_resizing = e;
+ for (RenderObject* p = parent(); p; p = p->parent())
+ if (p->isFrameSet()) static_cast<RenderFrameSet*>(p)->m_clientresizing = m_resizing;
+}
+
+bool RenderFrameSet::canResize( int _x, int _y )
+{
+ // if we haven't received a layout, then the gridLayout doesn't contain useful data yet
+ if (needsLayout() || !m_gridLayout[0] || !m_gridLayout[1] ) return false;
+
+ // check if we're over a horizontal or vertical boundary
+ int pos = m_gridLayout[1][0];
+ for(int c = 1; c < element()->totalCols(); c++)
+ if(_x >= pos && _x <= pos+element()->border())
+ return true;
+
+ pos = m_gridLayout[0][0];
+ for(int r = 1; r < element()->totalRows(); r++)
+ if( _y >= pos && _y <= pos+element()->border())
+ return true;
+
+ return false;
+}
+
+#ifdef ENABLE_DUMP
+void RenderFrameSet::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderBox::dump(stream,ind);
+ stream << " totalrows=" << element()->totalRows();
+ stream << " totalcols=" << element()->totalCols();
+
+ if ( m_hSplitVar )
+ for (uint i = 0; i < (uint)element()->totalRows(); i++) {
+ stream << " hSplitvar(" << i << ")=" << m_hSplitVar[i];
+ }
+
+ if ( m_vSplitVar )
+ for (uint i = 0; i < (uint)element()->totalCols(); i++)
+ stream << " vSplitvar(" << i << ")=" << m_vSplitVar[i];
+}
+#endif
+
+/**************************************************************************************/
+
+RenderPart::RenderPart(DOM::HTMLElementImpl* node)
+ : RenderWidget(node)
+{
+ // init RenderObject attributes
+ setInline(false);
+}
+
+void RenderPart::setWidget( TQWidget *widget )
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug(6031) << "RenderPart::setWidget()" << endl;
+#endif
+
+ setQWidget( widget );
+ widget->setFocusPolicy(TQ_WheelFocus);
+ if(widget->inherits("KHTMLView"))
+ connect( widget, TQT_SIGNAL( cleared() ), this, TQT_SLOT( slotViewCleared() ) );
+
+ setNeedsLayoutAndMinMaxRecalc();
+
+ // make sure the scrollbars are set correctly for restore
+ // ### find better fix
+ slotViewCleared();
+}
+
+bool RenderPart::partLoadingErrorNotify(tdehtml::ChildFrame *, const KURL& , const TQString& )
+{
+ return false;
+}
+
+short RenderPart::intrinsicWidth() const
+{
+ return 300;
+}
+
+int RenderPart::intrinsicHeight() const
+{
+ return 150;
+}
+
+void RenderPart::slotViewCleared()
+{
+}
+
+/***************************************************************************************/
+
+RenderFrame::RenderFrame( DOM::HTMLFrameElementImpl *frame )
+ : RenderPart(frame)
+{
+ setInline( false );
+}
+
+void RenderFrame::slotViewCleared()
+{
+ if(m_widget->inherits(TQSCROLLVIEW_OBJECT_NAME_STRING)) {
+#ifdef DEBUG_LAYOUT
+ kdDebug(6031) << "frame is a scrollview!" << endl;
+#endif
+ TQScrollView *view = static_cast<TQScrollView *>(m_widget);
+ if(!element()->frameBorder || !((static_cast<HTMLFrameSetElementImpl *>(element()->parentNode()))->frameBorder()))
+ view->setFrameStyle(TQFrame::NoFrame);
+ view->setVScrollBarMode(element()->scrolling );
+ view->setHScrollBarMode(element()->scrolling );
+ if(view->inherits("KHTMLView")) {
+#ifdef DEBUG_LAYOUT
+ kdDebug(6031) << "frame is a KHTMLview!" << endl;
+#endif
+ KHTMLView *htmlView = static_cast<KHTMLView *>(view);
+ if(element()->marginWidth != -1) htmlView->setMarginWidth(element()->marginWidth);
+ if(element()->marginHeight != -1) htmlView->setMarginHeight(element()->marginHeight);
+ }
+ }
+}
+
+/****************************************************************************************/
+
+RenderPartObject::RenderPartObject( DOM::HTMLElementImpl* element )
+ : RenderPart( element )
+{
+ // init RenderObject attributes
+ setInline(true);
+}
+
+void RenderPartObject::updateWidget()
+{
+ TQString url;
+ KHTMLPart *part = m_view->part();
+
+ setNeedsLayoutAndMinMaxRecalc();
+
+ if (element()->id() == ID_IFRAME) {
+
+ HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
+ url = o->url.string();
+ if (!o->getDocument()->isURLAllowed(url)) return;
+ part->requestFrame( this, url, o->name.string(), TQStringList(), true );
+ // ### this should be constant true - move iframe to somewhere else
+ } else {
+
+ TQStringList params;
+ HTMLObjectBaseElementImpl * objbase = static_cast<HTMLObjectBaseElementImpl *>(element());
+ url = objbase->url;
+
+ for (NodeImpl* child = element()->firstChild(); child; child=child->nextSibling()) {
+ if ( child->id() == ID_PARAM ) {
+ HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
+
+ TQString aStr = p->name();
+ aStr += TQString::fromLatin1("=\"");
+ aStr += p->value();
+ aStr += TQString::fromLatin1("\"");
+ TQString name_lower = p->name().lower();
+ if (name_lower == TQString::fromLatin1("type") && objbase->id() != ID_APPLET) {
+ objbase->setServiceType(p->value());
+ } else if (url.isEmpty() &&
+ (name_lower == TQString::fromLatin1("src") ||
+ name_lower == TQString::fromLatin1("movie") ||
+ name_lower == TQString::fromLatin1("code"))) {
+ url = p->value();
+ }
+ params.append(aStr);
+ }
+ }
+ if (element()->id() != ID_OBJECT) {
+ // add all attributes set on the embed object
+ NamedAttrMapImpl* a = objbase->attributes();
+ if (a) {
+ for (unsigned long i = 0; i < a->length(); ++i) {
+ NodeImpl::Id id = a->idAt(i);
+ DOMString value = a->valueAt(i);
+ params.append(objbase->getDocument()->getName(NodeImpl::AttributeId, id).string() + "=\"" + value.string() + "\"");
+ }
+ }
+ }
+ params.append( TQString::fromLatin1("__KHTML__PLUGINEMBED=\"YES\"") );
+ params.append( TQString::fromLatin1("__KHTML__PLUGINBASEURL=\"%1\"").arg(element()->getDocument()->baseURL().url()));
+
+ HTMLEmbedElementImpl *embed = 0;
+ TQString classId;
+ TQString serviceType = objbase->serviceType;
+ if ( element()->id() == ID_EMBED ) {
+
+ embed = static_cast<HTMLEmbedElementImpl *>( objbase );
+
+ }
+ else { // if(element()->id() == ID_OBJECT || element()->id() == ID_APPLET)
+
+ // check for embed child object
+ for (NodeImpl *child = objbase->firstChild(); child; child = child->nextSibling())
+ if ( child->id() == ID_EMBED ) {
+ embed = static_cast<HTMLEmbedElementImpl *>( child );
+ break;
+ }
+ classId = objbase->classId;
+
+ params.append( TQString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( classId ) );
+ params.append( TQString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( objbase->getAttribute(ATTR_CODEBASE).string() ) );
+ if (!objbase->getAttribute(ATTR_WIDTH).isEmpty())
+ params.append( TQString::fromLatin1("WIDTH=\"%1\"").arg( objbase->getAttribute(ATTR_WIDTH).string() ) );
+ else if (embed && !embed->getAttribute(ATTR_WIDTH).isEmpty()) {
+ params.append( TQString::fromLatin1("WIDTH=\"%1\"").arg( embed->getAttribute(ATTR_WIDTH).string() ) );
+ objbase->setAttribute(ATTR_WIDTH, embed->getAttribute(ATTR_WIDTH));
+ }
+ if (!objbase->getAttribute(ATTR_HEIGHT).isEmpty())
+ params.append( TQString::fromLatin1("HEIGHT=\"%1\"").arg( objbase->getAttribute(ATTR_HEIGHT).string() ) );
+ else if (embed && !embed->getAttribute(ATTR_HEIGHT).isEmpty()) {
+ params.append( TQString::fromLatin1("HEIGHT=\"%1\"").arg( embed->getAttribute(ATTR_HEIGHT).string() ) );
+ objbase->setAttribute(ATTR_HEIGHT, embed->getAttribute(ATTR_HEIGHT));
+ }
+
+ if ( embed ) {
+ // render embed object
+ url = embed->url;
+ if (!embed->serviceType.isEmpty())
+ serviceType = embed->serviceType;
+ } else if (url.isEmpty() && objbase->classId.startsWith("java:")) {
+ serviceType = "application/x-java-applet";
+ url = objbase->classId.mid(5);
+ }
+ if ( (serviceType.isEmpty() ||
+ serviceType == "application/x-oleobject") &&
+ !objbase->classId.isEmpty())
+ {
+#if 0
+ // We have a clsid, means this is activex (Niko)
+ serviceType = "application/x-activex-handler";
+#endif
+
+ if(classId.find(TQString::fromLatin1("D27CDB6E-AE6D-11cf-96B8-444553540000")) >= 0) {
+ // It is ActiveX, but the nsplugin system handling
+ // should also work, that's why we don't override the
+ // serviceType with application/x-activex-handler
+ // but let the KTrader in tdehtmlpart::createPart() detect
+ // the user's preference: launch with activex viewer or
+ // with nspluginviewer (Niko)
+ serviceType = "application/x-shockwave-flash";
+ }
+ else if(classId.find(TQString::fromLatin1("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) >= 0)
+ serviceType = "audio/x-pn-realaudio-plugin";
+ else if(classId.find(TQString::fromLatin1("8AD9C840-044E-11D1-B3E9-00805F499D93")) >= 0 ||
+ objbase->classId.find(TQString::fromLatin1("CAFEEFAC-0014-0000-0000-ABCDEFFEDCBA")) >= 0)
+ serviceType = "application/x-java-applet";
+ // http://www.apple.com/quicktime/tools_tips/tutorials/activex.html
+ else if(classId.find(TQString::fromLatin1("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) >= 0)
+ serviceType = "video/quicktime";
+ // http://msdn.microsoft.com/library/en-us/dnwmt/html/adding_windows_media_to_web_pages__etse.asp?frame=true
+ else if(objbase->classId.find(TQString::fromLatin1("6BF52A52-394A-11d3-B153-00C04F79FAA6")) >= 0 ||
+ classId.find(TQString::fromLatin1("22D6f312-B0F6-11D0-94AB-0080C74C7E95")) >= 0)
+ serviceType = "video/x-msvideo";
+
+ else
+ kdDebug(6031) << "ActiveX classId " << objbase->classId << endl;
+
+ // TODO: add more plugins here
+ }
+ }
+ if ((url.isEmpty() && !embed &&
+ (serviceType.isEmpty() || classId.isEmpty())) ||
+ !document()->isURLAllowed(url) ||
+ !part->requestObject( this, url, serviceType, params ))
+ objbase->renderAlternative();
+ }
+}
+
+// ugly..
+void RenderPartObject::close()
+{
+ RenderPart::close();
+
+ if ( element()->id() != ID_IFRAME )
+ updateWidget();
+ // deleted here
+}
+
+
+bool RenderPartObject::partLoadingErrorNotify( tdehtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType )
+{
+ KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
+ kdDebug(6031) << "RenderPartObject::partLoadingErrorNotify serviceType=" << serviceType << endl;
+ // Check if we just tried with e.g. nsplugin
+ // and fallback to the activexhandler if there is a classid
+ // and a codebase, where we may download the ocx if it's missing
+ if( serviceType != "application/x-activex-handler" && element()->id()==ID_OBJECT ) {
+
+ // check for embed child object
+ HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
+ HTMLEmbedElementImpl *embed = 0;
+ NodeImpl *child = o->firstChild();
+ while ( child ) {
+ if ( child->id() == ID_EMBED )
+ embed = static_cast<HTMLEmbedElementImpl *>( child );
+
+ child = child->nextSibling();
+ }
+ if( embed && !o->classId.isEmpty() &&
+ !( static_cast<ElementImpl *>(o)->getAttribute(ATTR_CODEBASE).string() ).isEmpty() )
+ {
+ KParts::URLArgs args;
+ args.serviceType = "application/x-activex-handler";
+ kdDebug(6031) << "set to activex" << endl;
+ if (part->requestObject( childFrame, url, args ))
+ return true; // success
+
+ return false;
+ }
+ }
+ // Dissociate ourselves from the current event loop (to prevent crashes
+ // due to the message box staying up)
+ TQTimer::singleShot( 0, this, TQT_SLOT( slotPartLoadingErrorNotify() ) );
+#if 0
+ Tokenizer *tokenizer = static_cast<DOM::DocumentImpl *>(part->document().handle())->tokenizer();
+ if (tokenizer) tokenizer->setOnHold( true );
+ slotPartLoadingErrorNotify();
+ if (tokenizer) tokenizer->setOnHold( false );
+#endif
+ return false;
+}
+
+void RenderPartObject::slotPartLoadingErrorNotify()
+{
+ // First we need to find out the servicetype - again - this code is too duplicated !
+ HTMLEmbedElementImpl *embed = 0;
+ TQString serviceType;
+ if( element()->id()==ID_OBJECT ) {
+
+ // check for embed child object
+ HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
+ serviceType = o->serviceType;
+ NodeImpl *child = o->firstChild();
+ while ( child ) {
+ if ( child->id() == ID_EMBED )
+ embed = static_cast<HTMLEmbedElementImpl *>( child );
+
+ child = child->nextSibling();
+ }
+
+ } else if( element()->id()==ID_EMBED ) {
+ embed = static_cast<HTMLEmbedElementImpl *>(element());
+ }
+ if ( embed )
+ serviceType = embed->serviceType;
+
+ // prepare for the local eventloop in KMessageBox
+ ref();
+
+ KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if( embed && !embed->pluginPage.isEmpty() && ext ) {
+ // Prepare the mimetype to show in the question (comment if available, name as fallback)
+ TQString mimeName = serviceType;
+ KMimeType::Ptr mime = KMimeType::mimeType(serviceType);
+ if ( mime->name() != KMimeType::defaultMimeType() )
+ mimeName = mime->comment();
+
+ // Check if we already asked the user, for this page
+ if (!mimeName.isEmpty() && part->docImpl() && !part->pluginPageQuestionAsked( serviceType ) )
+ {
+ part->setPluginPageQuestionAsked( serviceType );
+ bool pluginAvailable;
+ pluginAvailable = false;
+ // check if a pluginList file is in the config
+ if(KNSPluginInstallEngine::isActive())
+ {
+ KNSPluginWizard pluginWizard(m_view, "pluginInstaller", mime);
+ if(pluginWizard.pluginAvailable()) {
+ pluginAvailable = true;
+ pluginWizard.exec();
+ }
+ }
+ if(!pluginAvailable) {
+ // Prepare the URL to show in the question (host only if http, to make it short)
+ KURL pluginPageURL( embed->pluginPage );
+ TQString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
+ int res = KMessageBox::questionYesNo( m_view,
+ i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
+ i18n("Missing Plugin"), i18n("Download"), i18n("Do Not Download"), TQString("plugin-")+serviceType);
+ if ( res == KMessageBox::Yes )
+ {
+ // Display vendor download page
+ ext->createNewWindow( pluginPageURL );
+ return;
+ }
+ }
+ }
+ }
+
+ // didn't work, render alternative content.
+ if ( element() && (
+ element()->id() == ID_OBJECT || element()->id() == ID_EMBED || element()->id() == ID_APPLET))
+ static_cast<HTMLObjectBaseElementImpl*>( element() )->renderAlternative();
+
+ deref();
+}
+
+void RenderPartObject::layout( )
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ calcWidth();
+ calcHeight();
+
+ RenderPart::layout();
+
+ setNeedsLayout(false);
+}
+
+void RenderPartObject::slotViewCleared()
+{
+ if(m_widget->inherits(TQSCROLLVIEW_OBJECT_NAME_STRING) ) {
+#ifdef DEBUG_LAYOUT
+ kdDebug(6031) << "iframe is a scrollview!" << endl;
+#endif
+ TQScrollView *view = static_cast<TQScrollView *>(m_widget);
+ int frameStyle = TQFrame::NoFrame;
+ TQScrollView::ScrollBarMode scroll = TQScrollView::Auto;
+ int marginw = -1;
+ int marginh = -1;
+ if ( element()->id() == ID_IFRAME) {
+ HTMLIFrameElementImpl *frame = static_cast<HTMLIFrameElementImpl *>(element());
+ if(frame->frameBorder)
+ frameStyle = TQFrame::Box;
+ scroll = frame->scrolling;
+ marginw = frame->marginWidth;
+ marginh = frame->marginHeight;
+ }
+ view->setFrameStyle(frameStyle);
+ view->setVScrollBarMode(scroll );
+ view->setHScrollBarMode(scroll );
+ if(view->inherits("KHTMLView")) {
+#ifdef DEBUG_LAYOUT
+ kdDebug(6031) << "frame is a KHTMLview!" << endl;
+#endif
+ KHTMLView *htmlView = static_cast<KHTMLView *>(view);
+ htmlView->setIgnoreWheelEvents( element()->id() == ID_IFRAME );
+ if(marginw != -1) htmlView->setMarginWidth(marginw);
+ if(marginh != -1) htmlView->setMarginHeight(marginh);
+ }
+ }
+}
+
+
+#include "render_frames.moc"
diff --git a/tdehtml/rendering/render_frames.h b/tdehtml/rendering/render_frames.h
new file mode 100644
index 000000000..79171c747
--- /dev/null
+++ b/tdehtml/rendering/render_frames.h
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the KDE project.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@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 __render_frames_h__
+#define __render_frames_h__
+
+#include "rendering/render_replaced.h"
+#include "xml/dom_nodeimpl.h"
+#include "html/html_baseimpl.h"
+class KHTMLView;
+
+namespace DOM
+{
+ class HTMLFrameElementImpl;
+ class HTMLElementImpl;
+ class MouseEventImpl;
+}
+
+namespace tdehtml
+{
+ class ChildFrame;
+
+class RenderFrameSet : public RenderBox
+{
+ friend class DOM::HTMLFrameSetElementImpl;
+public:
+ RenderFrameSet( DOM::HTMLFrameSetElementImpl *frameSet );
+
+ virtual ~RenderFrameSet();
+
+ virtual const char *renderName() const { return "RenderFrameSet"; }
+ virtual bool isFrameSet() const { return true; }
+
+ virtual void layout();
+
+ void positionFrames( );
+
+ bool resizing() const { return m_resizing; }
+ bool noResize() const { return element()->noResize(); }
+
+ bool userResize( DOM::MouseEventImpl *evt );
+ bool canResize( int _x, int _y);
+ void setResizing(bool e);
+
+ Qt::CursorShape cursorShape() const { return m_cursor; }
+
+ bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inside);
+
+ DOM::HTMLFrameSetElementImpl *element() const
+ { return static_cast<DOM::HTMLFrameSetElementImpl*>(RenderObject::element()); }
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+private:
+ Qt::CursorShape m_cursor;
+ int m_oldpos;
+ int m_gridLen[2];
+ int* m_gridDelta[2];
+ int* m_gridLayout[2];
+
+ bool *m_hSplitVar; // is this split variable?
+ bool *m_vSplitVar;
+
+ int m_hSplit; // the split currently resized
+ int m_vSplit;
+ int m_hSplitPos;
+ int m_vSplitPos;
+
+ bool m_resizing;
+ bool m_clientresizing;
+};
+
+class RenderPart : public tdehtml::RenderWidget
+{
+ Q_OBJECT
+public:
+ RenderPart(DOM::HTMLElementImpl* node);
+
+ virtual const char *renderName() const { return "RenderPart"; }
+
+ virtual void setWidget( TQWidget *widget );
+
+ /**
+ * Called by KHTMLPart to notify the frame object that loading the
+ * part was not successfuly. (called either asyncroniously after a
+ * after the servicetype of the given url (the one passed with requestObject)
+ * has been determined or syncroniously from within requestObject)
+ *
+ * The default implementation does nothing.
+ *
+ * Return false in the normal case, return true if a fallback was found
+ * and the url was successfully opened.
+ */
+ virtual bool partLoadingErrorNotify( tdehtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType );
+
+ virtual short intrinsicWidth() const;
+ virtual int intrinsicHeight() const;
+
+public slots:
+ virtual void slotViewCleared();
+};
+
+class RenderFrame : public tdehtml::RenderPart
+{
+ Q_OBJECT
+public:
+ RenderFrame( DOM::HTMLFrameElementImpl *frame );
+
+ virtual const char *renderName() const { return "RenderFrame"; }
+ virtual bool isFrame() const { return true; }
+
+ // frames never have padding
+ virtual int paddingTop() const { return 0; }
+ virtual int paddingBottom() const { return 0; }
+ virtual int paddingLeft() const { return 0; }
+ virtual int paddingRight() const { return 0; }
+
+ DOM::HTMLFrameElementImpl *element() const
+ { return static_cast<DOM::HTMLFrameElementImpl*>(RenderObject::element()); }
+
+public slots:
+ void slotViewCleared();
+};
+
+// I can hardly call the class RenderObject ;-)
+class RenderPartObject : public tdehtml::RenderPart
+{
+ Q_OBJECT
+public:
+ RenderPartObject( DOM::HTMLElementImpl * );
+
+ virtual const char *renderName() const { return "RenderPartObject"; }
+
+ virtual void close();
+
+ virtual void layout( );
+ virtual void updateWidget();
+
+ virtual bool canHaveBorder() const { return true; }
+
+ virtual bool partLoadingErrorNotify( tdehtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType );
+
+public slots:
+ void slotViewCleared();
+private slots:
+ void slotPartLoadingErrorNotify();
+};
+
+}
+
+#endif
diff --git a/tdehtml/rendering/render_generated.cpp b/tdehtml/rendering/render_generated.cpp
new file mode 100644
index 000000000..2b793e504
--- /dev/null
+++ b/tdehtml/rendering/render_generated.cpp
@@ -0,0 +1,392 @@
+/**
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2004-2005 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.
+ *
+ */
+
+#include "rendering/render_generated.h"
+#include "rendering/render_style.h"
+#include "rendering/enumerate.h"
+#include "rendering/counter_tree.h"
+#include "css/css_valueimpl.h"
+
+using namespace tdehtml;
+using namespace Enumerate;
+
+// -------------------------------------------------------------------------
+
+RenderCounterBase::RenderCounterBase(DOM::NodeImpl* node)
+ : RenderText(node,0), m_counterNode(0)
+{
+}
+
+void RenderCounterBase::layout()
+{
+ KHTMLAssert( needsLayout() );
+
+ if ( !minMaxKnown() )
+ calcMinMaxWidth();
+
+ RenderText::layout();
+}
+
+void RenderCounterBase::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ generateContent();
+
+ if (str) str->deref();
+ str = new DOM::DOMStringImpl(m_item.unicode(), m_item.length());
+ str->ref();
+
+ RenderText::calcMinMaxWidth();
+}
+
+
+void RenderCounterBase::updateContent()
+{
+ setMinMaxKnown(false);
+}
+
+// -------------------------------------------------------------------------
+
+RenderCounter::RenderCounter(DOM::NodeImpl* node, const DOM::CounterImpl* counter)
+ : RenderCounterBase(node), m_counter(counter)
+{
+}
+
+TQString RenderCounter::toListStyleType(int value, int total, EListStyleType type)
+{
+ TQString item;
+ switch(type)
+ {
+ case LNONE:
+ break;
+// Glyphs: (these values are not really used and instead handled by RenderGlyph)
+ case LDISC:
+ item = TQChar(0x2022);
+ break;
+ case LCIRCLE:
+ item = TQChar(0x25e6);
+ break;
+ case LSQUARE:
+ item = TQChar(0x25a0);
+ break;
+ case LBOX:
+ item = TQChar(0x25a1);
+ break;
+ case LDIAMOND:
+ item = TQChar(0x25c6);
+ break;
+// Numeric:
+ case LDECIMAL:
+ item.setNum ( value );
+ break;
+ case DECIMAL_LEADING_ZERO: {
+ int decimals = 2;
+ int t = total/100;
+ while (t>0) {
+ t = t/10;
+ decimals++;
+ }
+ decimals = kMax(decimals, 2);
+ TQString num = TQString::number(value);
+ item.fill('0',decimals-num.length());
+ item.append(num);
+ break;
+ }
+ case ARABIC_INDIC:
+ item = toArabicIndic( value );
+ break;
+ case LAO:
+ item = toLao( value );
+ break;
+ case PERSIAN:
+ case URDU:
+ item = toPersianUrdu( value );
+ break;
+ case THAI:
+ item = toThai( value );
+ break;
+ case TIBETAN:
+ item = toTibetan( value );
+ break;
+// Algoritmic:
+ case LOWER_ROMAN:
+ item = toRoman( value, false );
+ break;
+ case UPPER_ROMAN:
+ item = toRoman( value, true );
+ break;
+ case HEBREW:
+ item = toHebrew( value );
+ break;
+ case ARMENIAN:
+ item = toArmenian( value );
+ break;
+ case GEORGIAN:
+ item = toGeorgian( value );
+ break;
+// Alphabetic:
+ case LOWER_ALPHA:
+ case LOWER_LATIN:
+ item = toLowerLatin( value );
+ break;
+ case UPPER_ALPHA:
+ case UPPER_LATIN:
+ item = toUpperLatin( value );
+ break;
+ case LOWER_GREEK:
+ item = toLowerGreek( value );
+ break;
+ case UPPER_GREEK:
+ item = toUpperGreek( value );
+ break;
+ case HIRAGANA:
+ item = toHiragana( value );
+ break;
+ case HIRAGANA_IROHA:
+ item = toHiraganaIroha( value );
+ break;
+ case KATAKANA:
+ item = toKatakana( value );
+ break;
+ case KATAKANA_IROHA:
+ item = toKatakanaIroha( value );
+ break;
+// Ideographic:
+ case JAPANESE_FORMAL:
+ item = toJapaneseFormal( value );
+ break;
+ case JAPANESE_INFORMAL:
+ item = toJapaneseInformal( value );
+ break;
+ case SIMP_CHINESE_FORMAL:
+ item = toSimpChineseFormal( value );
+ break;
+ case SIMP_CHINESE_INFORMAL:
+ item = toSimpChineseInformal( value );
+ break;
+ case TRAD_CHINESE_FORMAL:
+ item = toTradChineseFormal( value );
+ break;
+ case CJK_IDEOGRAPHIC:
+ // CSS 3 List says treat as trad-chinese-informal
+ case TRAD_CHINESE_INFORMAL:
+ item = toTradChineseInformal( value );
+ break;
+ default:
+ item.setNum ( value );
+ break;
+ }
+ return item;
+}
+
+void RenderCounter::generateContent()
+{
+ bool counters;
+ counters = !m_counter->separator().isNull();
+
+ if (!m_counterNode)
+ m_counterNode = getCounter(m_counter->identifier().string(), true, counters);
+
+ int value = m_counterNode->count();
+ if (m_counterNode->isReset()) value = m_counterNode->value();
+ int total = value;
+ if (m_counterNode->parent()) total = m_counterNode->parent()->total();
+ m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle());
+
+ if (counters) {
+ CounterNode *counter = m_counterNode->parent();
+ // we deliberately do not render the root counter-node
+ while(counter->parent() && !(counter->isReset() && counter->parent()->isRoot())) {
+ value = counter->count();
+ total = counter->parent()->total();
+ m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle()) + m_counter->separator().string() + m_item;
+ counter = counter->parent();
+ };
+ }
+
+}
+
+// -------------------------------------------------------------------------
+
+RenderQuote::RenderQuote(DOM::NodeImpl* node, EQuoteContent type)
+ : RenderCounterBase(node), m_quoteType(type)
+{
+}
+
+
+int RenderQuote::quoteCount() const
+{
+ switch(m_quoteType) {
+ case OPEN_QUOTE:
+ case NO_OPEN_QUOTE:
+ return 1;
+ case CLOSE_QUOTE:
+ case NO_CLOSE_QUOTE:
+ return -1;
+ case NO_QUOTE:
+ return 0;
+ }
+ assert(false);
+ return 0;
+}
+
+void RenderQuote::generateContent()
+{
+ bool visual;
+ if (m_quoteType == NO_CLOSE_QUOTE || m_quoteType == NO_OPEN_QUOTE)
+ visual = false;
+ else
+ visual = true;
+
+ if (!m_counterNode)
+ m_counterNode = getCounter("-tdehtml-quotes", visual, false);
+
+ int value = m_counterNode->count();
+ if (m_counterNode->isReset()) value = m_counterNode->value();
+ switch (m_quoteType) {
+ case OPEN_QUOTE:
+ m_item = style()->openQuote( value );
+ break;
+ case CLOSE_QUOTE:
+ m_item = style()->closeQuote( value );
+ break;
+ case NO_OPEN_QUOTE:
+ case NO_CLOSE_QUOTE:
+ case NO_QUOTE:
+ m_item = TQString();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+RenderGlyph::RenderGlyph(DOM::NodeImpl* node, EListStyleType type)
+ : RenderBox(node), m_type(type)
+{
+ setInline(true);
+// setReplaced(true);
+}
+
+void RenderGlyph::setStyle(RenderStyle *_style)
+{
+ RenderBox::setStyle(_style);
+
+ const TQFontMetrics &fm = style()->fontMetrics();
+ TQRect xSize= fm.boundingRect('x');
+ m_height = xSize.height();
+ m_width = xSize.width();;
+
+ switch(m_type) {
+ // Glyphs:
+ case LDISC:
+ case LCIRCLE:
+ case LSQUARE:
+ case LBOX:
+ case LDIAMOND:
+ case LNONE:
+ break;
+ default:
+ // not a glyph !
+ assert(false);
+ break;
+ }
+}
+
+void RenderGlyph::calcMinMaxWidth()
+{
+ m_minWidth = m_width;
+ m_maxWidth = m_width;
+
+ setMinMaxKnown();
+}
+
+short RenderGlyph::lineHeight(bool /*b*/) const
+{
+ return height();
+}
+
+short RenderGlyph::baselinePosition(bool /*b*/) const
+{
+ return height();
+}
+
+void RenderGlyph::paint(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ if (paintInfo.phase != PaintActionForeground)
+ return;
+
+ if (style()->visibility() != VISIBLE) return;
+
+ _tx += m_x;
+ _ty += m_y;
+
+ if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()))
+ return;
+
+ TQPainter* p = paintInfo.p;
+
+ const TQColor color( style()->color() );
+ p->setPen( color );
+
+ int xHeight = m_height;
+ int bulletWidth = (xHeight+1)/2;
+ int yoff = (xHeight - 1)/4;
+ TQRect marker(_tx, _ty + yoff, bulletWidth, bulletWidth);
+
+ switch(m_type) {
+ case LDISC:
+ p->setBrush( color );
+ p->drawEllipse( marker );
+ return;
+ case LCIRCLE:
+ p->setBrush( Qt::NoBrush );
+ p->drawEllipse( marker );
+ return;
+ case LSQUARE:
+ p->setBrush( color );
+ p->drawRect( marker );
+ return;
+ case LBOX:
+ p->setBrush( Qt::NoBrush );
+ p->drawRect( marker );
+ return;
+ case LDIAMOND: {
+ static TQPointArray diamond(4);
+ int x = marker.x();
+ int y = marker.y();
+ int s = bulletWidth/2;
+ diamond[0] = TQPoint(x+s, y);
+ diamond[1] = TQPoint(x+2*s, y+s);
+ diamond[2] = TQPoint(x+s, y+2*s);
+ diamond[3] = TQPoint(x, y+s);
+ p->setBrush( color );
+ p->drawConvexPolygon( diamond, 0, 4 );
+ return;
+ }
+ case LNONE:
+ return;
+ default:
+ // not a glyph
+ assert(false);
+ }
+}
+
diff --git a/tdehtml/rendering/render_generated.h b/tdehtml/rendering/render_generated.h
new file mode 100644
index 000000000..4e6aa6053
--- /dev/null
+++ b/tdehtml/rendering/render_generated.h
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2004,2005 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.
+ *
+ */
+#ifndef RENDER_GENERATED_H
+#define RENDER_GENERATED_H
+
+#include "rendering/render_text.h"
+#include "rendering/render_box.h"
+
+namespace DOM {
+ class CounterImpl;
+}
+
+namespace tdehtml {
+ class CounterNode;
+
+// -----------------------------------------------------------------------------
+
+class RenderCounterBase : public RenderText
+{
+public:
+ RenderCounterBase(DOM::NodeImpl* node);
+
+ virtual const char *renderName() const { return "RenderCounterBase"; }
+
+ virtual void layout( );
+ virtual void calcMinMaxWidth();
+ virtual bool isCounter() const { return true; }
+
+ virtual void generateContent() = 0;
+ void updateContent();
+
+protected:
+ TQString m_item;
+ CounterNode *m_counterNode; // Cache of the counternode
+};
+
+// -----------------------------------------------------------------------------
+
+class RenderCounter : public RenderCounterBase
+{
+public:
+ RenderCounter(DOM::NodeImpl* node, const DOM::CounterImpl* counter);
+ virtual ~RenderCounter() {};
+
+ virtual const char *renderName() const { return "RenderCounter"; }
+
+ virtual void generateContent();
+
+protected:
+ TQString toListStyleType(int value, int total, EListStyleType type);
+
+ const DOM::CounterImpl* m_counter;
+};
+
+// -----------------------------------------------------------------------------
+
+class RenderQuote : public RenderCounterBase
+{
+public:
+ RenderQuote(DOM::NodeImpl* node, EQuoteContent type);
+ virtual ~RenderQuote() {};
+
+ virtual const char *renderName() const { return "RenderQuote"; }
+
+ virtual bool isQuote() const { return true; }
+ virtual int quoteCount() const;
+
+ virtual void generateContent();
+
+protected:
+ EQuoteContent m_quoteType;
+};
+
+// -----------------------------------------------------------------------------
+
+// Is actually a special case of renderCounter for non-counted list-styles
+// These have traditionally been drawn rather than use Unicode characters
+class RenderGlyph : public RenderBox
+{
+public:
+ RenderGlyph(DOM::NodeImpl* node, EListStyleType type);
+ virtual ~RenderGlyph() {};
+
+ virtual const char *renderName() const { return "RenderGlyph"; }
+
+ virtual void paint(PaintInfo& paintInfo, int _tx, int _ty);
+ virtual void calcMinMaxWidth();
+
+ virtual void setStyle(RenderStyle *_style);
+
+ virtual short lineHeight( bool firstLine ) const;
+ virtual short baselinePosition( bool firstLine ) const;
+
+ virtual bool isGlyph() const { return true; }
+
+ virtual void position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/) {
+ setPos( box->xPos(), box->yPos() );
+ }
+
+protected:
+ EListStyleType m_type;
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_image.cpp b/tdehtml/rendering/render_image.cpp
new file mode 100644
index 000000000..d382c9bd1
--- /dev/null
+++ b/tdehtml/rendering/render_image.cpp
@@ -0,0 +1,604 @@
+/**
+ * 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-2003 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.
+ *
+ */
+//#define DEBUG_LAYOUT
+
+#include "render_image.h"
+#include "render_canvas.h"
+
+#include <tqdrawutil.h>
+#include <tqpainter.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+
+#include "css/csshelper.h"
+#include "misc/helper.h"
+#include "misc/htmlattrs.h"
+#include "misc/loader.h"
+#include "misc/htmltags.h"
+#include "html/html_formimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/dtd.h"
+#include "xml/dom2_eventsimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_objectimpl.h"
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include <math.h>
+
+#include "loading_icon.cpp"
+
+using namespace DOM;
+using namespace tdehtml;
+
+// -------------------------------------------------------------------------
+
+RenderImage::RenderImage(NodeImpl *_element)
+ : RenderReplaced(_element)
+{
+ m_oldImage = m_cachedImage = 0;
+
+ m_selectionState = SelectionNone;
+ berrorPic = false;
+
+ const KHTMLSettings *settings = _element->getDocument()->view()->part()->settings();
+ bUnfinishedImageFrame = settings->unfinishedImageFrame();
+
+ setIntrinsicWidth( 0 );
+ setIntrinsicHeight( 0 );
+}
+
+RenderImage::~RenderImage()
+{
+ if(m_cachedImage) m_cachedImage->deref( this );
+ if(m_oldImage) m_oldImage->deref( this );
+}
+
+TQPixmap RenderImage::pixmap() const
+{
+ return m_cachedImage ? m_cachedImage->pixmap() : TQPixmap();
+}
+
+void RenderImage::setStyle(RenderStyle* _style)
+{
+ RenderReplaced::setStyle(_style);
+ // init RenderObject attributes
+ //setOverhangingContents(style()->height().isPercent());
+ setShouldPaintBackgroundOrBorder(true);
+}
+
+void RenderImage::setContentObject(CachedObject* co )
+{
+ if (co && m_cachedImage != co)
+ updateImage( static_cast<CachedImage*>( co ) );
+}
+
+void RenderImage::setPixmap( const TQPixmap &p, const TQRect& r, CachedImage *o)
+{
+ if ( o == m_oldImage )
+ return;
+
+ if(o != m_cachedImage) {
+ RenderReplaced::setPixmap(p, r, o);
+ return;
+ }
+
+ bool iwchanged = false;
+
+ if(o->isErrorImage()) {
+ int iw = p.width() + 8;
+ int ih = p.height() + 8;
+
+ // we have an alt and the user meant it (its not a text we invented)
+ if ( element() && !alt.isEmpty() && !element()->getAttribute( ATTR_ALT ).isNull()) {
+ const TQFontMetrics &fm = style()->fontMetrics();
+ TQRect br = fm.boundingRect ( 0, 0, 1024, 256, TQt::AlignAuto|TQt::WordBreak, alt.string() );
+ if ( br.width() > iw )
+ iw = br.width();
+ if ( br.height() > ih )
+ ih = br.height();
+ }
+
+ if ( iw != intrinsicWidth() ) {
+ setIntrinsicWidth( iw );
+ iwchanged = true;
+ }
+ if ( ih != intrinsicHeight() ) {
+ setIntrinsicHeight( ih );
+ iwchanged = true;
+ }
+ if ( element() && element()->id() == ID_OBJECT ) {
+ static_cast<HTMLObjectElementImpl*>( element() )->renderAlternative();
+ return;
+ }
+ }
+ berrorPic = o->isErrorImage();
+
+ bool needlayout = false;
+
+ // Image dimensions have been changed, see what needs to be done
+ if( o->pixmap_size().width() != intrinsicWidth() ||
+ o->pixmap_size().height() != intrinsicHeight() || iwchanged )
+ {
+// tqDebug("image dimensions have been changed, old: %d/%d new: %d/%d",
+// intrinsicWidth(), intrinsicHeight(),
+// o->pixmap_size().width(), o->pixmap_size().height());
+
+ if(!o->isErrorImage()) {
+ setIntrinsicWidth( o->pixmap_size().width() );
+ setIntrinsicHeight( o->pixmap_size().height() );
+ }
+
+ // lets see if we need to relayout at all..
+ int oldwidth = m_width;
+ int oldheight = m_height;
+ int oldminwidth = m_minWidth;
+ m_minWidth = 0;
+
+ if ( parent() ) {
+ calcWidth();
+ calcHeight();
+ }
+
+ if(iwchanged || m_width != oldwidth || m_height != oldheight)
+ needlayout = true;
+
+ m_minWidth = oldminwidth;
+ m_width = oldwidth;
+ m_height = oldheight;
+ }
+
+ // we're not fully integrated in the tree yet.. we'll come back.
+ if ( !parent() )
+ return;
+
+ if(needlayout)
+ {
+ if (!selfNeedsLayout())
+ setNeedsLayout(true);
+ if (minMaxKnown())
+ setMinMaxKnown(false);
+ }
+ else
+ {
+ bool completeRepaint = !resizeCache.isNull();
+ int cHeight = contentHeight();
+ int scaledHeight = intrinsicHeight() ? ((o->valid_rect().height()*cHeight)/intrinsicHeight()) : 0;
+
+ // don't bog down X server doing xforms
+ if(completeRepaint && cHeight >= 5 && o->valid_rect().height() < intrinsicHeight() &&
+ (scaledHeight / (cHeight/5) == resizeCache.height() / (cHeight/5)))
+ return;
+
+ resizeCache = TQPixmap(); // for resized animations
+
+ if(completeRepaint)
+ repaintRectangle(borderLeft()+paddingLeft(), borderTop()+paddingTop(), contentWidth(), contentHeight());
+ else
+ {
+ repaintRectangle(r.x() + borderLeft() + paddingLeft(), r.y() + borderTop() + paddingTop(),
+ r.width(), r.height());
+ }
+ }
+}
+
+void RenderImage::paint(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ if (paintInfo.phase == PaintActionOutline && style()->outlineWidth() && style()->visibility() == VISIBLE)
+ paintOutline(paintInfo.p, _tx + m_x, _ty + m_y, width(), height(), style());
+
+ if (paintInfo.phase != PaintActionForeground && paintInfo.phase != PaintActionSelection)
+ return;
+
+ // not visible or not even once layouted?
+ if (style()->visibility() != VISIBLE || m_y <= -500000) return;
+
+ _tx += m_x;
+ _ty += m_y;
+
+ if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top())) return;
+
+ if(shouldPaintBackgroundOrBorder())
+ paintBoxDecorations(paintInfo, _tx, _ty);
+
+ int cWidth = contentWidth();
+ int cHeight = contentHeight();
+ int leftBorder = borderLeft();
+ int topBorder = borderTop();
+ int leftPad = paddingLeft();
+ int topPad = paddingTop();
+
+ if (!canvas()->printImages())
+ return;
+
+ CachedImage* i = m_oldImage && m_oldImage->valid_rect().size() == m_oldImage->pixmap_size() &&
+ m_oldImage->pixmap_size().width() == intrinsicWidth() &&
+ m_oldImage->pixmap_size().height() == intrinsicHeight()
+ ? m_oldImage : m_cachedImage;
+
+ // paint frame around image as long as it is not completely loaded from web.
+ if (bUnfinishedImageFrame && paintInfo.phase == PaintActionForeground && cWidth > 2 && cHeight > 2 && !complete()) {
+ static TQPixmap *loadingIcon;
+ TQColor bg = tdehtml::retrieveBackgroundColor(this);
+ TQColor fg = tdehtml::hasSufficientContrast(Qt::gray, bg) ? Qt::gray :
+ (hasSufficientContrast(Qt::white, bg) ? Qt::white : Qt::black);
+ paintInfo.p->setPen(TQPen(fg, 1));
+ paintInfo.p->setBrush( Qt::NoBrush );
+ paintInfo.p->drawRect(_tx, _ty, m_width, m_height);
+ if (!(m_width <= 5 || m_height <= 5)) {
+ if (!loadingIcon) {
+ loadingIcon = new TQPixmap();
+ loadingIcon->loadFromData(loading_icon_data, loading_icon_len);
+ }
+ paintInfo.p->drawPixmap(_tx + 4, _ty + 4, *loadingIcon, 0, 0, m_width - 5, m_height - 5);
+ }
+
+ }
+
+ //kdDebug( 6040 ) << " contents (" << contentWidth << "/" << contentHeight << ") border=" << borderLeft() << " padding=" << paddingLeft() << endl;
+ if ( !i || berrorPic)
+ {
+ if(cWidth > 2 && cHeight > 2)
+ {
+ if ( !berrorPic ) {
+ //tqDebug("qDrawShadePanel %d/%d/%d/%d", _tx + leftBorder, _ty + topBorder, cWidth, cHeight);
+ qDrawShadePanel( paintInfo.p, _tx + leftBorder + leftPad, _ty + topBorder + topPad, cWidth, cHeight,
+ TDEApplication::palette().inactive(), true, 1 );
+ }
+ TQPixmap const* pix = i ? &i->pixmap() : 0;
+ if(berrorPic && pix && (cWidth >= pix->width()+4) && (cHeight >= pix->height()+4) )
+ {
+ TQRect r(pix->rect());
+ r = r.intersect(TQRect(0, 0, cWidth-4, cHeight-4));
+ paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad+2, _ty + topBorder + topPad+2), *pix, r );
+ }
+ if(!alt.isEmpty()) {
+ TQString text = alt.string();
+ paintInfo.p->setFont(style()->font());
+ paintInfo.p->setPen( style()->color() );
+ int ax = _tx + leftBorder + leftPad + 2;
+ int ay = _ty + topBorder + topPad + 2;
+ const TQFontMetrics &fm = style()->fontMetrics();
+ if (cWidth>5 && cHeight>=fm.height())
+ paintInfo.p->drawText(ax, ay+1, cWidth - 4, cHeight - 4, TQt::WordBreak, text );
+ }
+ }
+ }
+ else if (i && !i->isTransparent())
+ {
+ paintInfo.p->setPen( Qt::black ); // used for bitmaps
+ const TQPixmap& pix = i->pixmap();
+ if ( (cWidth != intrinsicWidth() || cHeight != intrinsicHeight()) &&
+ pix.width() > 0 && pix.height() > 0 && i->valid_rect().isValid())
+ {
+ if (resizeCache.isNull() && cWidth && cHeight && intrinsicWidth() && intrinsicHeight())
+ {
+ TQRect scaledrect(i->valid_rect());
+// kdDebug(6040) << "time elapsed: " << dt->elapsed() << endl;
+// kdDebug( 6040 ) << "have to scale: " << endl;
+// tqDebug("cw=%d ch=%d pw=%d ph=%d rcw=%d, rch=%d",
+// cWidth, cHeight, intrinsicWidth(), intrinsicHeight(), resizeCache.width(), resizeCache.height());
+ TQWMatrix matrix;
+ matrix.scale( (float)(cWidth)/intrinsicWidth(),
+ (float)(cHeight)/intrinsicHeight() );
+ resizeCache = pix.xForm( matrix );
+ scaledrect.setWidth( ( cWidth*scaledrect.width() ) / intrinsicWidth() );
+ scaledrect.setHeight( ( cHeight*scaledrect.height() ) / intrinsicHeight() );
+// tqDebug("resizeCache size: %d/%d", resizeCache.width(), resizeCache.height());
+// tqDebug("valid: %d/%d, scaled: %d/%d",
+// i->valid_rect().width(), i->valid_rect().height(),
+// scaledrect.width(), scaledrect.height());
+
+ // sometimes scaledrect.width/height are off by one because
+ // of rounding errors. if the i is fully loaded, we
+ // make sure that we don't do unnecessary resizes during painting
+ TQSize s(scaledrect.size());
+ if(i->valid_rect().size() == TQSize( intrinsicWidth(), intrinsicHeight() )) // fully loaded
+ s = TQSize(cWidth, cHeight);
+ if(kAbs(s.width() - cWidth) < 2) // rounding errors
+ s.setWidth(cWidth);
+ if(resizeCache.size() != s)
+ resizeCache.resize(s);
+
+ paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad, _ty + topBorder + topPad),
+ resizeCache, scaledrect );
+ }
+ else
+ paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad, _ty + topBorder + topPad), resizeCache );
+ }
+ else
+ {
+ // we might be just about switching images
+ TQRect rect(i->valid_rect().isValid() ? i->valid_rect()
+ : TQRect(0, 0, intrinsicWidth(), intrinsicHeight()));
+
+ TQPoint offs( _tx + leftBorder + leftPad, _ty + topBorder + topPad);
+// tqDebug("normal paint rect %d/%d/%d/%d", rect.x(), rect.y(), rect.width(), rect.height());
+// rect = rect & TQRect( 0 , y - offs.y() - 10, w, 10 + y + h - offs.y());
+
+// tqDebug("normal paint rect after %d/%d/%d/%d", rect.x(), rect.y(), rect.width(), rect.height());
+// tqDebug("normal paint: offs.y(): %d, y: %d, diff: %d", offs.y(), y, y - offs.y());
+// tqDebug("");
+
+// p->setClipRect(TQRect(x,y,w,h));
+
+
+// p->drawPixmap( offs.x(), y, pix, rect.x(), rect.y(), rect.width(), rect.height() );
+ paintInfo.p->drawPixmap(offs, pix, rect);
+
+ }
+ }
+ if (m_selectionState != SelectionNone) {
+// kdDebug(6040) << "_tx " << _tx << " _ty " << _ty << " _x " << _x << " _y " << _y << endl;
+ // Draw in any case if inside selection. For selection borders, the
+ // offset will decide whether to draw selection or not
+ bool draw = true;
+ if (m_selectionState != SelectionInside) {
+ int startPos, endPos;
+ selectionStartEnd(startPos, endPos);
+ if(selectionState() == SelectionStart)
+ endPos = 1;
+ else if(selectionState() == SelectionEnd)
+ startPos = 0;
+ draw = endPos - startPos > 0;
+ }
+ if (draw) {
+ // setting the brush origin is important for compatibility,
+ // don't touch it unless you know what you're doing
+ paintInfo.p->setBrushOrigin(_tx, _ty - paintInfo.r.y());
+ paintInfo.p->fillRect(_tx, _ty, width(), height(),
+ TQBrush(style()->palette().active().highlight(),
+ Qt::Dense4Pattern));
+ }
+ }
+}
+
+void RenderImage::layout()
+{
+ KHTMLAssert( needsLayout());
+ KHTMLAssert( minMaxKnown() );
+
+ short oldwidth = m_width;
+ int oldheight = m_height;
+
+ // minimum height
+ m_height = m_cachedImage && m_cachedImage->isErrorImage() ? intrinsicHeight() : 0;
+
+ calcWidth();
+ calcHeight();
+
+ // if they are variable width and we calculate a huge height or width, we assume they
+ // actually wanted the intrinsic width.
+ if ( m_width > 4096 && !style()->width().isFixed() )
+ m_width = intrinsicWidth() + paddingLeft() + paddingRight() + borderLeft() + borderRight();
+ if ( m_height > 2048 && !style()->height().isFixed() )
+ m_height = intrinsicHeight() + paddingTop() + paddingBottom() + borderTop() + borderBottom();
+
+ // limit total size to not run out of memory when doing the xform call.
+ if ( ( m_width * m_height > 4096*2048 ) &&
+ ( contentWidth() > intrinsicWidth() || contentHeight() > intrinsicHeight() ) ) {
+ float scale = sqrt( m_width*m_height / ( 4096.*2048. ) );
+ m_width = (int) (m_width/scale);
+ m_height = (int) (m_height/scale);
+ }
+
+ if ( m_width != oldwidth || m_height != oldheight )
+ resizeCache = TQPixmap();
+
+ setNeedsLayout(false);
+}
+
+void RenderImage::notifyFinished(CachedObject *finishedObj)
+{
+ if ( ( m_cachedImage == finishedObj || m_oldImage == finishedObj ) && m_oldImage ) {
+ m_oldImage->deref( this );
+ m_oldImage = 0;
+ repaint();
+ }
+
+ RenderReplaced::notifyFinished(finishedObj);
+}
+
+bool RenderImage::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
+{
+ inside |= RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
+
+ if (inside && element()) {
+ int tx = _tx + m_x;
+ int ty = _ty + m_y;
+ if (isRelPositioned())
+ relativePositionOffset(tx, ty);
+
+ HTMLImageElementImpl* i = element()->id() == ID_IMG ? static_cast<HTMLImageElementImpl*>(element()) : 0;
+ HTMLMapElementImpl* map;
+ if (i && i->getDocument()->isHTMLDocument() &&
+ (map = static_cast<HTMLDocumentImpl*>(i->getDocument())->getMap(i->imageMap()))) {
+ // we're a client side image map
+ inside = map->mapMouseEvent(_x - tx, _y - ty, contentWidth(), contentHeight(), info);
+ info.setInnerNonSharedNode(element());
+ }
+ }
+
+ return inside;
+}
+
+void RenderImage::updateImage(CachedImage* new_image)
+{
+ CachedImage* tempimage = m_oldImage;
+ m_oldImage = m_cachedImage;
+ m_cachedImage = new_image;
+ assert( m_cachedImage != m_oldImage );
+
+ if ( m_cachedImage )
+ m_cachedImage->ref(this);
+
+ if ( tempimage )
+ tempimage->deref(this);
+
+ // if the loading finishes we might get an error and then the image is deleted
+ if ( m_cachedImage )
+ berrorPic = m_cachedImage->isErrorImage();
+ else
+ berrorPic = true;
+}
+
+void RenderImage::updateFromElement()
+{
+ if (element()->id() == ID_INPUT)
+ alt = static_cast<HTMLInputElementImpl*>(element())->altText();
+ else if (element()->id() == ID_IMG)
+ alt = static_cast<HTMLImageElementImpl*>(element())->altText();
+
+ DOMString u = element()->id() == ID_OBJECT ?
+ element()->getAttribute(ATTR_DATA) : element()->getAttribute(ATTR_SRC);
+
+ if (!u.isEmpty() &&
+ ( !m_cachedImage || m_cachedImage->url() != u ) ) {
+ CachedImage *new_image = element()->getDocument()->docLoader()->
+ requestImage(tdehtml::parseURL(u));
+
+ if(new_image && new_image != m_cachedImage)
+ updateImage( new_image );
+ }
+}
+
+bool RenderImage::complete() const
+{
+ // "complete" means that the image has been loaded
+ // but also that its width/height (contentWidth(),contentHeight()) have been calculated.
+ return m_cachedImage && m_cachedImage->valid_rect().size() == m_cachedImage->pixmap_size() && !needsLayout();
+}
+
+bool RenderImage::isWidthSpecified() const
+{
+ switch (style()->width().type()) {
+ case Fixed:
+ case Percent:
+ return true;
+ default:
+ return false;
+ }
+ assert(false);
+ return false;
+}
+
+bool RenderImage::isHeightSpecified() const
+{
+ switch (style()->height().type()) {
+ case Fixed:
+ case Percent:
+ return true;
+ default:
+ return false;
+ }
+ assert(false);
+ return false;
+}
+
+short RenderImage::calcAspectRatioWidth() const
+{
+ if (intrinsicHeight() == 0)
+ return 0;
+ if (!m_cachedImage || m_cachedImage->isErrorImage())
+ return intrinsicWidth(); // Don't bother scaling.
+ return RenderReplaced::calcReplacedHeight() * intrinsicWidth() / intrinsicHeight();
+}
+
+int RenderImage::calcAspectRatioHeight() const
+{
+ if (intrinsicWidth() == 0)
+ return 0;
+ if (!m_cachedImage || m_cachedImage->isErrorImage())
+ return intrinsicHeight(); // Don't bother scaling.
+ return RenderReplaced::calcReplacedWidth() * intrinsicHeight() / intrinsicWidth();
+}
+
+short RenderImage::calcReplacedWidth() const
+{
+ int width;
+ if (isWidthSpecified())
+ width = calcReplacedWidthUsing(Width);
+ else
+ width = calcAspectRatioWidth();
+ int minW = calcReplacedWidthUsing(MinWidth);
+ int maxW = style()->maxWidth().value() == UNDEFINED ? width : calcReplacedWidthUsing(MaxWidth);
+
+ if (width > maxW)
+ width = maxW;
+
+ if (width < minW)
+ width = minW;
+
+ return width;
+}
+
+int RenderImage::calcReplacedHeight() const
+{
+ int height;
+ if (isHeightSpecified())
+ height = calcReplacedHeightUsing(Height);
+ else
+ height = calcAspectRatioHeight();
+
+ int minH = calcReplacedHeightUsing(MinHeight);
+ int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcReplacedHeightUsing(MaxHeight);
+
+ if (height > maxH)
+ height = maxH;
+
+ if (height < minH)
+ height = minH;
+
+ return height;
+}
+
+#if 0
+void RenderImage::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
+{
+ RenderReplaced::caretPos(offset, flags, _x, _y, width, height);
+
+#if 0 // doesn't work reliably
+ height = intrinsicHeight();
+ width = override && offset == 0 ? intrinsicWidth() : 0;
+ _x = xPos();
+ _y = yPos();
+ if (offset > 0) _x += intrinsicWidth();
+
+ RenderObject *cb = containingBlock();
+
+ int absx, absy;
+ if (cb && cb != this && cb->absolutePosition(absx,absy))
+ {
+ _x += absx;
+ _y += absy;
+ } else {
+ // we don't know our absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+#endif
+}
+#endif
diff --git a/tdehtml/rendering/render_image.h b/tdehtml/rendering/render_image.h
new file mode 100644
index 000000000..9bd0bce4c
--- /dev/null
+++ b/tdehtml/rendering/render_image.h
@@ -0,0 +1,105 @@
+/*
+ * 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)
+ *
+ * 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 RENDER_IMAGE_H
+#define RENDER_IMAGE_H
+
+#include "html/dtd.h"
+#include "html/html_elementimpl.h"
+#include "rendering/render_replaced.h"
+#include "dom/dom_string.h"
+
+#include <tqmap.h>
+#include <tqpixmap.h>
+
+namespace tdehtml {
+
+class DocLoader;
+class CachedObject;
+
+class RenderImage : public RenderReplaced
+{
+public:
+ RenderImage(DOM::NodeImpl* _element);
+ virtual ~RenderImage();
+
+ virtual const char *renderName() const { return "RenderImage"; }
+ virtual void paint( PaintInfo& i, int tx, int ty );
+
+ virtual void layout();
+
+ virtual void setPixmap( const TQPixmap &, const TQRect&, CachedImage *);
+
+ // don't even think about making these methods virtual!
+ TQPixmap pixmap() const;
+ DOM::HTMLElementImpl* element() const
+ { return static_cast<DOM::HTMLElementImpl*>(RenderObject::element()); }
+
+ bool complete() const;
+
+ CachedObject *contentObject() { return m_cachedImage; }
+ void setContentObject( CachedObject* );
+
+ // hook to keep RendeObject::m_inline() up to date
+ virtual void setStyle(RenderStyle *style);
+ virtual void updateFromElement();
+
+ virtual void notifyFinished(CachedObject *finishedObj);
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inside);
+
+ bool isWidthSpecified() const;
+ bool isHeightSpecified() const;
+
+ short calcAspectRatioWidth() const;
+ int calcAspectRatioHeight() const;
+
+ virtual short calcReplacedWidth() const;
+ virtual int calcReplacedHeight() const;
+
+ virtual SelectionState selectionState() const {return m_selectionState;}
+ virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
+#if 0
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+#endif
+
+private:
+ void updateImage(CachedImage* new_image);
+ /*
+ * Cache for images that need resizing
+ */
+ TQPixmap resizeCache;
+
+ // text to display as long as the image isn't available
+ DOM::DOMString alt;
+
+ CachedImage *m_cachedImage;
+ CachedImage *m_oldImage;
+
+ bool berrorPic : 1;
+ bool bUnfinishedImageFrame :1;
+ SelectionState m_selectionState : 3; // FIXME: don't forget to enlarge this as the enum grows
+};
+
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_inline.cpp b/tdehtml/rendering/render_inline.cpp
new file mode 100644
index 000000000..96841eb43
--- /dev/null
+++ b/tdehtml/rendering/render_inline.cpp
@@ -0,0 +1,935 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 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.
+ *
+ */
+
+#include <kglobal.h>
+
+#include "rendering/render_arena.h"
+#include "rendering/render_inline.h"
+#include "rendering/render_block.h"
+#include "xml/dom_docimpl.h"
+
+#include <tqvaluevector.h>
+
+using namespace tdehtml;
+
+void RenderInline::setStyle(RenderStyle* _style)
+{
+ RenderFlow::setStyle(_style);
+ setInline(true);
+
+ // Ensure that all of the split inlines pick up the new style. We
+ // only do this if we're an inline, since we don't want to propagate
+ // a block's style to the other inlines.
+ // e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
+ // and after the block share the same style, but the block doesn't
+ // need to pass its style on to anyone else.
+ RenderFlow* currCont = continuation();
+ while (currCont) {
+ if (currCont->isInline()) {
+ RenderFlow* nextCont = currCont->continuation();
+ currCont->setContinuation(0);
+ currCont->setStyle(style());
+ currCont->setContinuation(nextCont);
+ }
+ currCont = currCont->continuation();
+ }
+
+ if (attached()) {
+ // Update replaced content
+ updateReplacedContent();
+ // Update pseudos for ::before and ::after
+ updatePseudoChildren();
+ }
+}
+
+// Attach handles initial setStyle that requires parent nodes
+void RenderInline::attach()
+{
+ RenderFlow::attach();
+
+ updateReplacedContent();
+ updatePseudoChildren();
+}
+
+bool RenderInline::isInlineContinuation() const
+{
+ return m_isContinuation;
+}
+
+void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+{
+ // Make sure we don't append things after :after-generated content if we have it.
+ if (!beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER)
+ beforeChild = lastChild();
+
+ if (!newChild->isText() && newChild->style()->position() != STATIC)
+ setOverhangingContents();
+
+ if (!newChild->isInline() && !newChild->isFloatingOrPositioned() )
+ {
+ // We are placing a block inside an inline. We have to perform a split of this
+ // inline into continuations. This involves creating an anonymous block box to hold
+ // |newChild|. We then make that block box a continuation of this inline. We take all of
+ // the children after |beforeChild| and put them in a clone of this object.
+
+ RenderBlock *newBox = createAnonymousBlock();
+ RenderFlow* oldContinuation = continuation();
+ setContinuation(newBox);
+
+ splitFlow(beforeChild, newBox, newChild, oldContinuation);
+ return;
+ }
+
+ RenderBox::addChild(newChild,beforeChild);
+
+ newChild->setNeedsLayoutAndMinMaxRecalc();
+}
+
+RenderInline* RenderInline::cloneInline(RenderFlow* src)
+{
+ RenderInline *o = new (src->renderArena()) RenderInline(src->element());
+ o->m_isContinuation = true;
+ o->setStyle(src->style());
+ return o;
+}
+
+void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
+ RenderBlock* middleBlock,
+ RenderObject* beforeChild, RenderFlow* oldCont)
+{
+ // Create a clone of this inline.
+ RenderInline* clone = cloneInline(this);
+ clone->setContinuation(oldCont);
+
+ // Now take all of the children from beforeChild to the end and remove
+ // then from |this| and place them in the clone.
+ RenderObject* o = beforeChild;
+ while (o) {
+ RenderObject* tmp = o;
+ o = tmp->nextSibling();
+ clone->addChildToFlow(removeChildNode(tmp), 0);
+ tmp->setNeedsLayoutAndMinMaxRecalc();
+ }
+
+ // Hook |clone| up as the continuation of the middle block.
+ middleBlock->setContinuation(clone);
+
+ // We have been reparented and are now under the fromBlock. We need
+ // to walk up our inline parent chain until we hit the containing block.
+ // Once we hit the containing block we're done.
+ RenderFlow* curr = static_cast<RenderFlow*>(parent());
+ RenderFlow* currChild = this;
+ while (curr && curr != fromBlock) {
+ // Create a new clone.
+ RenderInline* cloneChild = clone;
+ clone = cloneInline(curr);
+
+ // Insert our child clone as the first child.
+ clone->addChildToFlow(cloneChild, 0);
+
+ // Hook the clone up as a continuation of |curr|.
+ RenderFlow* oldCont = curr->continuation();
+ curr->setContinuation(clone);
+ clone->setContinuation(oldCont);
+
+ // Now we need to take all of the children starting from the first child
+ // *after* currChild and append them all to the clone.
+ o = currChild->nextSibling();
+ while (o) {
+ RenderObject* tmp = o;
+ o = tmp->nextSibling();
+ clone->appendChildNode(curr->removeChildNode(tmp));
+ tmp->setNeedsLayoutAndMinMaxRecalc();
+ }
+
+ // Keep walking up the chain.
+ currChild = curr;
+ curr = static_cast<RenderFlow*>(curr->parent());
+ }
+
+ // Now we are at the block level. We need to put the clone into the toBlock.
+ toBlock->appendChildNode(clone);
+
+ // Now take all the children after currChild and remove them from the fromBlock
+ // and put them in the toBlock.
+ o = currChild->nextSibling();
+ while (o) {
+ RenderObject* tmp = o;
+ o = tmp->nextSibling();
+ toBlock->appendChildNode(fromBlock->removeChildNode(tmp));
+ }
+}
+
+void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+ RenderObject* newChild, RenderFlow* oldCont)
+{
+ RenderBlock* pre = 0;
+ RenderBlock* block = containingBlock();
+ bool madeNewBeforeBlock = false;
+ if (block->isAnonymousBlock()) {
+ // We can reuse this block and make it the preBlock of the next continuation.
+ pre = block;
+ block = block->containingBlock();
+ }
+ else {
+ // No anonymous block available for use. Make one.
+ pre = block->createAnonymousBlock();
+ madeNewBeforeBlock = true;
+ }
+
+ RenderBlock* post = block->createAnonymousBlock();
+
+ RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
+ if (madeNewBeforeBlock)
+ block->insertChildNode(pre, boxFirst);
+ block->insertChildNode(newBlockBox, boxFirst);
+ block->insertChildNode(post, boxFirst);
+ block->setChildrenInline(false);
+
+ if (madeNewBeforeBlock) {
+ RenderObject* o = boxFirst;
+ while (o)
+ {
+ RenderObject* no = o;
+ o = no->nextSibling();
+ pre->appendChildNode(block->removeChildNode(no));
+ no->setNeedsLayoutAndMinMaxRecalc();
+ }
+ }
+
+ splitInlines(pre, post, newBlockBox, beforeChild, oldCont);
+
+ // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
+ // time in makeChildrenNonInline by just setting this explicitly up front.
+ newBlockBox->setChildrenInline(false);
+
+ // We don't just call addChild, since it would pass things off to the
+ // continuation, so we call addChildToFlow explicitly instead. We delayed
+ // adding the newChild until now so that the |newBlockBox| would be fully
+ // connected, thus allowing newChild access to a renderArena should it need
+ // to wrap itself in additional boxes (e.g., table construction).
+ newBlockBox->addChildToFlow(newChild, 0);
+
+ // XXXdwh is any of this even necessary? I don't think it is.
+ pre->close();
+ pre->setPos(0, -500000);
+ pre->setNeedsLayout(true);
+ newBlockBox->close();
+ newBlockBox->setPos(0, -500000);
+ newBlockBox->setNeedsLayout(true);
+ post->close();
+ post->setPos(0, -500000);
+ post->setNeedsLayout(true);
+
+ updatePseudoChildren();
+
+ block->setNeedsLayoutAndMinMaxRecalc();
+}
+
+void RenderInline::paint(PaintInfo& i, int _tx, int _ty)
+{
+ paintLines(i, _tx, _ty);
+}
+
+/**
+ * Appends the given coordinate-pair to the point-array if it is not
+ * equal to the last element.
+ * @param pointArray point-array
+ * @param pnt point to append
+ * @return \c true if \c pnt has actually been appended
+ */
+inline static bool appendIfNew(TQValueVector<TQPoint> &pointArray, const TQPoint &pnt)
+{
+// if (!pointArray.isEmpty()) kdDebug(6040) << "appifnew: " << pointArray.back() << " == " << pnt << ": " << (pointArray.back() == pnt) << endl;
+// else kdDebug(6040) << "appifnew: " << pnt << " (unconditional)" << endl;
+ if (!pointArray.isEmpty() && pointArray.back() == pnt) return false;
+ pointArray.append(pnt);
+ return true;
+}
+
+/**
+ * Does spike-reduction on the given point-array's stack-top.
+ *
+ * Spikes are path segments of which one goes forward, and the sucessor
+ * goes backward on the predecessor's segment:
+ *
+ * 2 0 1
+ * x------x<-----x
+ * (0 is stack-top in point-array)
+ *
+ * This will be reduced to
+ * 1 0
+ * x------x
+ *
+ * Preconditions:
+ * - No other spikes exist in the whole point-array except at most
+ * one at the end
+ * - No two succeeding points are ever equal
+ * - For each two succeeding points either p1.x == p2.x or p1.y == p2.y holds
+ * true
+ * - No such spike exists where 2 is situated between 0 and 1.
+ *
+ * Postcondition:
+ * - No spikes exist in the whole point-array
+ *
+ * If no spike is found, the point-array is left unchanged.
+ * @return \c true if an actual reduction was done
+ */
+inline static bool reduceSpike(TQValueVector<TQPoint> &pointArray)
+{
+ if (pointArray.size() < 3) return false;
+ TQValueVector<TQPoint>::Iterator it = pointArray.end();
+ TQPoint p0 = *--it;
+ TQPoint p1 = *--it;
+ TQPoint p2 = *--it;
+
+ bool elide = false;
+
+ if (p0.x() == p1.x() && p1.x() == p2.x()
+ && (p1.y() < p0.y() && p0.y() < p2.y()
+ || p2.y() < p0.y() && p0.y() < p1.y()
+ || p1.y() < p2.y() && p2.y() < p0.y()
+ || p0.y() < p2.y() && p2.y() < p1.y()
+ || (elide = p2.y() == p0.y() && p0.y() < p1.y())
+ || (elide = p1.y() < p0.y() && p0.y() == p2.y()))
+ || p0.y() == p1.y() && p1.y() == p2.y()
+ && (p1.x() < p0.x() && p0.x() < p2.x()
+ || p2.x() < p0.x() && p0.x() < p1.x()
+ || p1.x() < p2.x() && p2.x() < p0.x()
+ || p0.x() < p2.x() && p2.x() < p1.x()
+ || (elide = p2.x() == p0.x() && p0.x() < p1.x())
+ || (elide = p1.x() < p0.x() && p0.x() == p2.x())))
+ {
+// kdDebug(6040) << "spikered p2" << (elide ? " (elide)" : "") << ": " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
+ pointArray.pop_back(); pointArray.pop_back();
+ if (!elide)
+ pointArray.push_back(p0);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Reduces segment separators.
+ *
+ * A segment separator separates a segment into two segments, thus causing
+ * two adjacent segment with the same orientation.
+ *
+ * 2 1 0
+ * x-------x---->x
+ * (0 means stack-top)
+ *
+ * Here, 1 is a segment separator. As segment separators not only make
+ * the line drawing algorithm inefficient, but also make the spike-reduction
+ * fail, they must be eliminated:
+ *
+ * 1 0
+ * x------------>x
+ *
+ * Preconditions:
+ * - No other segment separators exist in the whole point-array except
+ * at most one at the end
+ * - No two succeeding points are ever equal
+ * - For each two succeeding points either p1.x == p2.x or p1.y == p2.y holds
+ * true
+ * - No such spike exists where 2 is situated between 0 and 1.
+ *
+ * Postcondition:
+ * - No segment separators exist in the whole point-array
+ *
+ * If no segment separator is found at the end of the point-array, it is
+ * left unchanged.
+ * @return \c true if a segment separator was actually reduced.
+ */
+inline static bool reduceSegmentSeparator(TQValueVector<TQPoint> &pointArray)
+{
+ if (pointArray.size() < 3) return false;
+ TQValueVector<TQPoint>::Iterator it = pointArray.end();
+ TQPoint p0 = *--it;
+ TQPoint p1 = *--it;
+ TQPoint p2 = *--it;
+// kdDebug(6040) << "checking p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
+
+ if (p0.x() == p1.x() && p1.x() == p2.x()
+ && (p2.y() < p1.y() && p1.y() < p0.y()
+ || p0.y() < p1.y() && p1.y() < p2.y())
+ || p0.y() == p1.y() && p1.y() == p2.y()
+ && (p2.x() < p1.x() && p1.x() < p0.x()
+ || p0.x() < p1.x() && p1.x() < p2.x()))
+ {
+// kdDebug(6040) << "segred p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
+ pointArray.pop_back(); pointArray.pop_back();
+ pointArray.push_back(p0);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Appends the given point to the point-array, doing necessary reductions to
+ * produce a path without spikes and segment separators.
+ */
+static void appendPoint(TQValueVector<TQPoint> &pointArray, TQPoint &pnt)
+{
+ if (!appendIfNew(pointArray, pnt)) return;
+// kdDebug(6040) << "appendPoint: appended " << pnt << endl;
+ reduceSegmentSeparator(pointArray)
+ || reduceSpike(pointArray);
+}
+
+/**
+ * Traverses the horizontal inline boxes and appends the point coordinates to
+ * the given array.
+ * @param box inline box
+ * @param pointArray array collecting coordinates
+ * @param bottom \c true, collect bottom coordinates, \c false, collect top
+ * coordinates.
+ * @param limit lower limit that an y-coordinate must at least reach. Note
+ * that limit designates the highest y-coordinate for \c bottom, and
+ * the lowest for !\c bottom.
+ */
+static void collectHorizontalBoxCoordinates(InlineBox *box,
+ TQValueVector<TQPoint> &pointArray,
+ bool bottom, int offset, int limit = -500000)
+{
+// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << endl;
+ offset = bottom ? offset:-offset;
+ int y = box->yPos() + bottom*box->height() + offset;
+ if (limit != -500000 && (bottom ? y < limit : y > limit))
+ y = limit;
+ int x = box->xPos() + bottom*box->width() + offset;
+ TQPoint newPnt(x, y);
+ // Add intersection point if point-array not empty.
+ if (!pointArray.isEmpty()) {
+ TQPoint lastPnt = pointArray.back();
+ TQPoint insPnt(newPnt.x(), lastPnt.y());
+ if (offset && ((bottom && lastPnt.y() > y) || (!bottom && lastPnt.y() < y))) {
+ insPnt.rx() = lastPnt.x();
+ insPnt.ry() = y;
+ }
+// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
+ appendPoint(pointArray, insPnt);
+ }
+ // Insert starting point of box
+ appendPoint(pointArray, newPnt);
+
+ newPnt.rx() += (bottom ? -box->width() : box->width()) - 2*offset;
+
+ if (box->isInlineFlowBox()) {
+ InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(box);
+ for (InlineBox *b = bottom ? flowBox->lastChild() : flowBox->firstChild(); b; b = bottom ? b->prevOnLine() : b->nextOnLine()) {
+ // Don't let boxes smaller than this flow box' height influence
+ // the vertical position of the outline if they have a different
+ // x-coordinate
+ int l2;
+ if (b->xPos() != box->xPos() && b->xPos() + b->width() != box->xPos() + box->width())
+ l2 = y;
+ else
+ l2 = limit;
+ collectHorizontalBoxCoordinates(b, pointArray, bottom, kAbs(offset), l2);
+ }
+
+ // Add intersection point if flow box contained any children
+ if (flowBox->firstChild()) {
+ TQPoint lastPnt = pointArray.back();
+ TQPoint insPnt(lastPnt.x(), newPnt.y());
+// kdDebug(6040) << "right: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
+ appendPoint(pointArray, insPnt);
+ }
+ }
+
+ // Insert ending point of box
+ appendPoint(pointArray, newPnt);
+
+// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << "ende" << endl;
+}
+
+/**
+ * Checks whether the given line box' extents and the following line box'
+ * extents are disjount (i. e. do not share the same x-coordinate range).
+ * @param line line box
+ * @param toBegin \c true, compare with preceding line box, \c false, with
+ * succeeding
+ * @return \c true if this and the next box are disjoint
+ */
+inline static bool lineBoxesDisjoint(InlineRunBox *line, int offset, bool toBegin)
+{
+ InlineRunBox *next = toBegin ? line->prevLineBox() : line->nextLineBox();
+ return !next || next->xPos() + next->width() + 2*offset < line->xPos()
+ || next->xPos() > line->xPos() + line->width() + 2*offset;
+}
+
+/**
+ * Traverses the vertical outer borders of the given render flow's line
+ * boxes and appends the point coordinates to the given point array.
+ * @param line line box to begin traversal
+ * @param pointArray point array
+ * @param left \c true, traverse the left vertical coordinates,
+ * \c false, traverse the right vertical coordinates.
+ * @param lastline if not 0, returns the pointer to the last line box traversed
+ */
+static void collectVerticalBoxCoordinates(InlineRunBox *line,
+ TQValueVector<TQPoint> &pointArray,
+ bool left, int offset, InlineRunBox **lastline = 0)
+{
+ InlineRunBox *last = 0;
+ offset = left ? -offset:offset;
+ for (InlineRunBox* curr = line; curr && !last; curr = left ? curr->prevLineBox() : curr->nextLineBox()) {
+ InlineBox *root = curr;
+
+ bool isLast = lineBoxesDisjoint(curr, kAbs(offset), left);
+ if (isLast) last = curr;
+
+ if (root != line && !isLast)
+ while (root->parent()) root = root->parent();
+ TQPoint newPnt(curr->xPos() + !left*curr->width() + offset,
+ (left ? root->topOverflow() : root->bottomOverflow()) + offset);
+ if (!pointArray.isEmpty()) {
+ TQPoint lastPnt = pointArray.back();
+ if (newPnt.x()>lastPnt.x() && !left)
+ pointArray.back().setY( kMin(lastPnt.y(), root->topOverflow()-offset) );
+ else if (newPnt.x()<lastPnt.x() && left)
+ pointArray.back().setY( kMax(lastPnt.y(), root->bottomOverflow()+offset) );
+ TQPoint insPnt(newPnt.x(), pointArray.back().y());
+// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
+ appendPoint(pointArray, insPnt);
+ }
+ appendPoint(pointArray, newPnt);
+ }
+ if (lastline) *lastline = last;
+}
+
+/**
+ * Links up the end of the given point-array such that the starting point
+ * is not a segment separator.
+ *
+ * To achieve this, improper points are removed from the beginning of
+ * the point-array (by changing the array's starting iterator), and
+ * proper ones appended to the point-array's back.
+ *
+ * @param pointArray point-array
+ * @return actual begin of point array
+ */
+static TQPoint *linkEndToBegin(TQValueVector<TQPoint> &pointArray)
+{
+ uint index = 0;
+ assert(pointArray.size() >= 3);
+
+ // if first and last points match, ignore the last one.
+ bool linkup = false; TQPoint linkupPnt;
+ if (pointArray.front() == pointArray.back()) {
+ linkupPnt = pointArray.back();
+ pointArray.pop_back();
+ linkup = true;
+ }
+
+ const TQPoint *it = pointArray.begin() + index;
+ TQPoint pfirst = *it;
+ TQPoint pnext = *++it;
+ TQPoint plast = pointArray.back();
+// kdDebug(6040) << "linkcheck plast: " << plast << " pfirst: " << pfirst << " pnext: " << pnext << endl;
+
+ if (plast.x() == pfirst.x() && pfirst.x() == pnext.x()
+ || plast.y() == pfirst.y() && pfirst.y() == pnext.y()) {
+
+ ++index;
+ appendPoint(pointArray, pfirst);
+ appendPoint(pointArray, pnext);
+ } else if (linkup)
+ pointArray.push_back(linkupPnt);
+ return pointArray.begin() + index;
+}
+
+void RenderInline::paintOutlines(TQPainter *p, int _tx, int _ty)
+{
+ if (style()->outlineWidth() == 0 || style()->outlineStyle() <= BHIDDEN)
+ return;
+ int offset = style()->outlineOffset();
+
+ // We may have to draw more than one outline path as they may be
+ // disjoint.
+ for (InlineRunBox *curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+ TQValueVector<TQPoint> path;
+
+ // collect topmost outline
+ collectHorizontalBoxCoordinates(curr, path, false, offset);
+ // collect right outline
+ collectVerticalBoxCoordinates(curr, path, false, offset, &curr);
+ // collect bottommost outline
+ collectHorizontalBoxCoordinates(curr, path, true, offset);
+ // collect left outline
+ collectVerticalBoxCoordinates(curr, path, true, offset);
+
+ if (path.size() < 3) continue;
+
+ const TQPoint *begin = linkEndToBegin(path);
+
+ // paint the outline
+ paintOutlinePath(p, _tx, _ty, begin, path.end(), BSLeft, -1, BSTop);
+ }
+}
+
+template<class T> inline void kSwap(T &a1, T &a2)
+{
+ T tmp = a2;
+ a2 = a1;
+ a1 = tmp;
+}
+
+enum BSOrientation { BSHorizontal, BSVertical };
+
+/**
+ * Returns the orientation of the given border side.
+ */
+inline BSOrientation bsOrientation(RenderObject::BorderSide bs)
+{
+ switch (bs) {
+ case RenderObject::BSTop:
+ case RenderObject::BSBottom:
+ return BSHorizontal;
+ case RenderObject::BSLeft:
+ case RenderObject::BSRight:
+ return BSVertical;
+ }
+ return BSHorizontal; // make gcc happy (sigh)
+}
+
+/**
+ * Determines the new border side by evaluating the new direction as determined
+ * by the given coordinates, the old border side, and the relative direction.
+ *
+ * The relative direction specifies whether the old border side meets with the
+ * straight given by the coordinates from below (negative), or above (positive).
+ */
+inline RenderObject::BorderSide newBorderSide(RenderObject::BorderSide oldBS, int direction, const TQPoint &last, const TQPoint &cur)
+{
+ bool below = direction < 0;
+ if (last.x() == cur.x()) { // new segment is vertical
+ bool t = oldBS == RenderObject::BSTop;
+ bool b = oldBS == RenderObject::BSBottom;
+ if ((t || b) && last.y() != cur.y())
+ return (cur.y() < last.y()) ^ (t && below || b && !below)
+ ? RenderObject::BSLeft : RenderObject::BSRight;
+ } else /*if (last.y() == cur.y())*/ { // new segment is horizontal
+ bool l = oldBS == RenderObject::BSLeft;
+ bool r = oldBS == RenderObject::BSRight;
+ if ((l || r) && last.x() != cur.x())
+ return (cur.x() < last.x()) ^ (l && below || r && !below)
+ ? RenderObject::BSTop : RenderObject::BSBottom;
+ }
+ return oldBS; // same direction
+}
+
+/**
+ * Draws an outline segment between the given two points.
+ * @param o render object
+ * @param p painter
+ * @param tx absolute x-coordinate of containing block
+ * @param ty absolute y-coordinate of containing block
+ * @param p1 starting point
+ * @param p2 end point
+ * @param prevBS border side of previous segment
+ * @param curBS border side of this segment
+ * @param nextBS border side of next segment
+ */
+static void paintOutlineSegment(RenderObject *o, TQPainter *p, int tx, int ty,
+ const TQPoint &p1, const TQPoint &p2,
+ RenderObject::BorderSide prevBS,
+ RenderObject::BorderSide curBS,
+ RenderObject::BorderSide nextBS)
+{
+ int ow = o->style()->outlineWidth();
+ EBorderStyle os = o->style()->outlineStyle();
+ TQColor oc = o->style()->outlineColor();
+
+ int x1 = tx + p1.x();
+ int y1 = ty + p1.y();
+ int x2 = tx + p2.x();
+ int y2 = ty + p2.y();
+ if (x1 > x2) {
+ kSwap(x1, x2);
+ if (bsOrientation(curBS) == BSHorizontal) kSwap(prevBS, nextBS);
+ }
+ if (y1 > y2) {
+ kSwap(y1, y2);
+ if (bsOrientation(curBS) == BSVertical) kSwap(prevBS, nextBS);
+ }
+
+// kdDebug(6040) << "segment(" << x1 << "," << y1 << ") - (" << x2 << "," << y2 << ")" << endl;
+/* p->setPen(Qt::gray);
+ p->drawLine(x1,y1,x2,y2);*/
+ switch (curBS) {
+ case RenderObject::BSLeft:
+ case RenderObject::BSRight:
+/* p->setPen(TQColor("#ffe4dd"));
+ p->drawLine(
+ x1 - (curBS == RenderObject::BSLeft ? ow : 0),
+ y1 - (prevBS == RenderObject::BSTop ? ow : 0),
+ x2 + (curBS == RenderObject::BSRight ? ow : 0),
+ y2 + (nextBS == RenderObject::BSBottom ? ow : 0)
+ );*/
+ o->drawBorder(p,
+ x1 - (curBS == RenderObject::BSLeft ? ow : 0),
+ y1 - (prevBS == RenderObject::BSTop ? ow : 0),
+ x2 + (curBS == RenderObject::BSRight ? ow : 0),
+ y2 + (nextBS == RenderObject::BSBottom ? ow : 0),
+ curBS, oc, o->style()->color(), os,
+ prevBS == RenderObject::BSTop ? ow
+ : prevBS == RenderObject::BSBottom ? -ow : 0,
+ nextBS == RenderObject::BSTop ? -ow
+ : nextBS == RenderObject::BSBottom ? ow : 0,
+ true);
+ break;
+ case RenderObject::BSBottom:
+ case RenderObject::BSTop:
+// kdDebug(6040) << "BSTop/BSBottom: prevBS " << prevBS << " curBS " << curBS << " nextBS " << nextBS << endl;
+ o->drawBorder(p,
+ x1 - (prevBS == RenderObject::BSLeft ? ow : 0),
+ y1 - (curBS == RenderObject::BSTop ? ow : 0),
+ x2 + (nextBS == RenderObject::BSRight ? ow : 0),
+ y2 + (curBS == RenderObject::BSBottom ? ow : 0),
+ curBS, oc, o->style()->color(), os,
+ prevBS == RenderObject::BSLeft ? ow
+ : prevBS == RenderObject::BSRight ? -ow : 0,
+ nextBS == RenderObject::BSLeft ? -ow
+ : nextBS == RenderObject::BSRight ? ow : 0,
+ true);
+ break;
+ }
+}
+
+void RenderInline::paintOutlinePath(TQPainter *p, int tx, int ty, const TQPoint *begin, const TQPoint *end, BorderSide bs, int direction, BorderSide endingBS)
+{
+ int ow = style()->outlineWidth();
+ if (ow == 0 || m_isContinuation) // Continuations get painted by the original inline.
+ return;
+
+ TQPoint last = *begin;
+ BorderSide lastBS = bs;
+ Q_ASSERT(begin != end);
+ ++begin;
+
+// kdDebug(6040) << "last: " << last << endl;
+
+ bs = newBorderSide(bs, direction, last, *begin);
+// kdDebug(6040) << "newBorderSide: " << lastBS << " " << direction << "d " << last << " - " << *begin << " => " << bs << endl;
+
+ for (const TQPoint *it = begin; it != end; ++it) {
+ TQPoint cur = *it;
+// kdDebug(6040) << "cur: " << cur << endl;
+ BorderSide nextBS;
+ if (it + 1 != end) {
+ TQPoint diff = cur - last;
+ direction = diff.x() + diff.y();
+ nextBS = newBorderSide(bs, direction, cur, *(it + 1));
+// kdDebug(6040) << "newBorderSide*: " << bs << " " << direction << "d " << cur << " - " << *(it + 1) << " => " << nextBS << endl;
+ } else
+ nextBS = endingBS;
+
+ Q_ASSERT(bsOrientation(bs) != bsOrientation(nextBS));
+ paintOutlineSegment(this, p, tx, ty, last, cur,
+ lastBS, bs, nextBS);
+ lastBS = bs;
+ last = cur;
+ bs = nextBS;
+ }
+
+}
+
+void RenderInline::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderInline)::calcMinMaxWidth() this=" << this << endl;
+#endif
+
+ // Irrelevant, since some enclosing block will actually measure us and our children.
+ m_minWidth = 0;
+ m_maxWidth = 0;
+
+ setMinMaxKnown();
+}
+
+short RenderInline::width() const
+{
+ // Return the width of the minimal left side and the maximal right side.
+ short leftSide = 0;
+ short rightSide = 0;
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+ if (curr == firstLineBox() || curr->xPos() < leftSide)
+ leftSide = curr->xPos();
+ if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide)
+ rightSide = curr->xPos() + curr->width();
+ }
+
+ return rightSide - leftSide;
+}
+
+int RenderInline::height() const
+{
+ int h = 0;
+ if (firstLineBox())
+ h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
+ return h;
+}
+
+int RenderInline::offsetLeft() const
+{
+ int x = RenderFlow::offsetLeft();
+ if (firstLineBox())
+ x += firstLineBox()->xPos();
+ return x;
+}
+
+int RenderInline::offsetTop() const
+{
+ int y = RenderFlow::offsetTop();
+ if (firstLineBox())
+ y += firstLineBox()->yPos();
+ return y;
+}
+
+const char *RenderInline::renderName() const
+{
+ if (isRelPositioned())
+ return "RenderInline (relative positioned)";
+ if (isAnonymous())
+ return "RenderInline (anonymous)";
+ return "RenderInline";
+}
+
+bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
+{
+/*
+ if ( hitTestAction != HitTestSelfOnly ) {
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling())
+ if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty, HitTestAll))
+ inside = true;
+ }
+*/
+ // Check our line boxes if we're still not inside.
+ if (/*hitTestAction != HitTestChildrenOnly &&*/ !inside && style()->visibility() != HIDDEN) {
+ // See if we're inside one of our line boxes.
+ inside = hitTestLines(info, _x, _y, _tx, _ty, hitTestAction);
+ }
+
+ if (inside && element()) {
+ if (info.innerNode() && info.innerNode()->renderer() &&
+ !info.innerNode()->renderer()->isInline()) {
+ // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node.
+ info.setInnerNode(element());
+
+ // Clear everything else.
+ info.setInnerNonSharedNode(0);
+ info.setURLElement(0);
+ }
+
+ if (!info.innerNode())
+ info.setInnerNode(element());
+
+ if(!info.innerNonSharedNode())
+ info.setInnerNonSharedNode(element());
+ }
+
+ return inside;
+}
+
+void RenderInline::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
+{
+ _x = -1;
+
+ RenderBlock *cb = containingBlock();
+ bool rtl = cb->style()->direction() == RTL;
+ bool outsideEnd = flags & CFOutsideEnd;
+ // I need to explain that: outsideEnd contains a meaningful value if
+ // and only if flags & CFOutside is set. If it is not, then randomly
+ // either the first or the last line box is returned.
+ // This doesn't matter because the only case this can happen is on an
+ // empty inline element, whose first and last line boxes are actually
+ // the same.
+ InlineFlowBox *line = !outsideEnd ^ rtl ? firstLineBox() : lastLineBox();
+
+ if (!line) { // umpf, handle "gracefully"
+ RenderFlow::caretPos(offset, flags, _x, _y, width, height);
+ return;
+ }
+
+ _x = line->xPos();
+ width = 1; // ### regard CFOverride
+
+ // Place caret outside the border
+ if (flags & CFOutside) {
+ RenderStyle *s = element() && element()->parent()
+ && element()->parent()->renderer()
+ ? element()->parent()->renderer()->style()
+ : style();
+ const TQFontMetrics &fm = s->fontMetrics();
+ _y = line->yPos() + line->baseline() - fm.ascent();
+ height = fm.height();
+
+ if (!outsideEnd ^ rtl) {
+ _x -= line->marginBorderPaddingLeft();
+ } else {
+ _x += line->width() + line->marginBorderPaddingRight();
+ }
+
+ } else {
+ const TQFontMetrics &fm = style()->fontMetrics();
+ _y = line->yPos() + line->baseline() - fm.ascent();
+ height = fm.height();
+ }
+
+ int absx, absy;
+ if (cb && cb->absolutePosition(absx,absy)) {
+ //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
+ _x += absx;
+ _y += absy;
+ } else {
+ // we don't know our absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+}
+
+inline int minXPos(const RenderInline *o)
+{
+ int retval=6666666;
+ if (!o->firstLineBox()) return 0;
+ for (InlineRunBox* curr = o->firstLineBox(); curr; curr = curr->nextLineBox())
+ retval = kMin( retval, int( curr->m_x ));
+ return retval;
+}
+
+int RenderInline::inlineXPos() const
+{
+ return minXPos(this);
+}
+
+int RenderInline::inlineYPos() const
+{
+ return firstLineBox() ? firstLineBox()->yPos() : 0;
+}
+
diff --git a/tdehtml/rendering/render_inline.h b/tdehtml/rendering/render_inline.h
new file mode 100644
index 000000000..97392999e
--- /dev/null
+++ b/tdehtml/rendering/render_inline.h
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
+ * (C) 2002-2003 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.
+ *
+ */
+
+#ifndef RENDER_INLINE_H
+#define RENDER_INLINE_H
+
+#include "render_flow.h"
+
+namespace tdehtml {
+
+class RenderInline : public RenderFlow
+{
+public:
+ RenderInline(DOM::NodeImpl* node) : RenderFlow( node ), m_isContinuation( false ) {}
+
+ virtual const char *renderName() const;
+
+ virtual bool isRenderInline() const { return true; }
+ virtual bool isInlineFlow() const { return true; }
+ virtual bool childrenInline() const { return true; }
+
+ virtual bool isInlineContinuation() const;
+
+ virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
+
+ void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
+ RenderObject* beforeChild, RenderFlow* oldCont);
+
+ void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+ RenderObject* newChild, RenderFlow* oldCont);
+
+ virtual void setStyle(RenderStyle* _style);
+ virtual void attach();
+
+ virtual void layout() {} // Do nothing for layout()
+
+ virtual void paint(PaintInfo&, int tx, int ty);
+
+ virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside);
+
+ virtual void calcMinMaxWidth();
+
+ // overrides RenderObject
+ virtual bool requiresLayer() const { return isRelPositioned(); }
+
+ virtual short width() const;
+ virtual int height() const;
+
+ virtual int inlineXPos() const;
+ virtual int inlineYPos() const;
+
+ // used to calculate offsetWidth/Height. Overridden by inlines (render_flow) to return
+ // the remaining width on a given line (and the height of a single line).
+ virtual int offsetLeft() const;
+ virtual int offsetTop() const;
+
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+ void paintOutlines(TQPainter *p, int tx, int ty);
+
+protected:
+ static RenderInline* cloneInline(RenderFlow* src);
+ void paintOutlinePath(TQPainter *p, int tx, int ty, const TQPoint *begin, const TQPoint *end, BorderSide startingBS, int initialDirection, BorderSide endingBS);
+
+private:
+ bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
+
+};
+
+} // namespace
+
+#endif // RENDER_BLOCK_H
+
diff --git a/tdehtml/rendering/render_layer.cpp b/tdehtml/rendering/render_layer.cpp
new file mode 100644
index 000000000..2b6bbf027
--- /dev/null
+++ b/tdehtml/rendering/render_layer.cpp
@@ -0,0 +1,1830 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ * (C) 2006 Germain Garand <germain@ebooksfrance.org>
+ * (C) 2006 Allan Sandfeld Jense <kde@carewolf.com>
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+//#define BOX_DEBUG
+
+#include "render_layer.h"
+#include <kdebug.h>
+#include <assert.h>
+#include "tdehtmlview.h"
+#include "render_canvas.h"
+#include "render_arena.h"
+#include "render_replaced.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "misc/htmltags.h"
+#include "html/html_blockimpl.h"
+#include "xml/dom_restyler.h"
+
+#include <tqscrollbar.h>
+#include <tqptrvector.h>
+#include <tqstyle.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+#ifdef APPLE_CHANGES
+TQScrollBar* RenderLayer::gScrollBar = 0;
+#endif
+
+#ifndef NDEBUG
+static bool inRenderLayerDetach;
+#endif
+
+void
+RenderScrollMediator::slotValueChanged()
+{
+ m_layer->updateScrollPositionFromScrollbars();
+}
+
+RenderLayer::RenderLayer(RenderObject* object)
+: m_object( object ),
+m_parent( 0 ),
+m_previous( 0 ),
+m_next( 0 ),
+m_first( 0 ),
+m_last( 0 ),
+m_x( 0 ),
+m_y( 0 ),
+m_scrollX( 0 ),
+m_scrollY( 0 ),
+m_scrollWidth( 0 ),
+m_scrollHeight( 0 ),
+m_hBar( 0 ),
+m_vBar( 0 ),
+m_scrollMediator( 0 ),
+m_posZOrderList( 0 ),
+m_negZOrderList( 0 ),
+m_overflowList(0),
+m_zOrderListsDirty( true ),
+m_overflowListDirty(true),
+m_isOverflowOnly( shouldBeOverflowOnly() ),
+m_markedForRepaint( false ),
+m_hasOverlaidWidgets( false ),
+m_marquee( 0 )
+{
+}
+
+RenderLayer::~RenderLayer()
+{
+ // Child layers will be deleted by their corresponding render objects, so
+ // our destructor doesn't have to do anything.
+ delete m_hBar;
+ delete m_vBar;
+ delete m_scrollMediator;
+ delete m_posZOrderList;
+ delete m_negZOrderList;
+ delete m_overflowList;
+ delete m_marquee;
+}
+
+void RenderLayer::updateLayerPosition()
+{
+
+ // The canvas is sized to the docWidth/Height over in RenderCanvas::layout, so we
+ // don't need to ever update our layer position here.
+ if (renderer()->isCanvas())
+ return;
+
+ int x = m_object->xPos();
+ int y = m_object->yPos() - m_object->borderTopExtra();
+
+ if (!m_object->isPositioned()) {
+ // We must adjust our position by walking up the render tree looking for the
+ // nearest enclosing object with a layer.
+ RenderObject* curr = m_object->parent();
+ while (curr && !curr->layer()) {
+ x += curr->xPos();
+ y += curr->yPos();
+ curr = curr->parent();
+ }
+ if (curr)
+ y += curr->borderTopExtra();
+ }
+
+ if (m_object->isRelPositioned())
+ static_cast<RenderBox*>(m_object)->relativePositionOffset(x, y);
+
+ // Subtract our parent's scroll offset.
+ if (m_object->isPositioned() && enclosingPositionedAncestor()) {
+ RenderLayer* positionedParent = enclosingPositionedAncestor();
+
+ // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
+ positionedParent->subtractScrollOffset(x, y);
+ positionedParent->checkInlineRelOffset(m_object, x, y);
+ }
+ else if (parent())
+ parent()->subtractScrollOffset(x, y);
+
+ setPos(x,y);
+}
+
+TQRegion RenderLayer::paintedRegion(RenderLayer* rootLayer)
+{
+ updateZOrderLists();
+ TQRegion r;
+ if (m_negZOrderList) {
+ uint count = m_negZOrderList->count();
+ for (uint i = 0; i < count; i++) {
+ RenderLayer* child = m_negZOrderList->at(i);
+ r += child->paintedRegion(rootLayer);
+ }
+ }
+ const RenderStyle *s= renderer()->style();
+ if (s->visibility() == VISIBLE) {
+ int x = 0; int y = 0;
+ convertToLayerCoords(rootLayer,x,y);
+ TQRect cr(x,y,width(),height());
+ if ( s->backgroundImage() || s->backgroundColor().isValid() || s->hasBorder() ||
+ renderer()->scrollsOverflow() || renderer()->isReplaced() ) {
+ r += cr;
+ } else {
+ r += renderer()->visibleFlowRegion(x, y);
+ }
+ }
+
+ if (m_posZOrderList) {
+ uint count = m_posZOrderList->count();
+ for (uint i = 0; i < count; i++) {
+ RenderLayer* child = m_posZOrderList->at(i);
+ r += child->paintedRegion(rootLayer);
+ }
+ }
+ return r;
+}
+
+void RenderLayer::repaint( Priority p, bool markForRepaint )
+{
+ if (markForRepaint && m_markedForRepaint)
+ return;
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->repaint( p, markForRepaint );
+ TQRect layerBounds, damageRect, fgrect;
+ calculateRects(renderer()->canvas()->layer(), renderer()->viewRect(), layerBounds, damageRect, fgrect);
+ m_visibleRect = damageRect.intersect( layerBounds );
+ if (m_visibleRect.isValid())
+ renderer()->canvas()->repaintViewRectangle( m_visibleRect.x(), m_visibleRect.y(), m_visibleRect.width(), m_visibleRect.height(), (p > NormalPriority) );
+ if (markForRepaint)
+ m_markedForRepaint = true;
+}
+
+void RenderLayer::updateLayerPositions(RenderLayer* rootLayer, bool doFullRepaint, bool checkForRepaint)
+{
+ if (doFullRepaint) {
+ m_object->repaint();
+ checkForRepaint = doFullRepaint = false;
+ }
+
+ updateLayerPosition(); // For relpositioned layers or non-positioned layers,
+ // we need to keep in sync, since we may have shifted relative
+ // to our parent layer.
+
+ if (m_hBar || m_vBar) {
+ // Need to position the scrollbars.
+ int x = 0;
+ int y = 0;
+ convertToLayerCoords(rootLayer, x, y);
+ TQRect layerBounds = TQRect(x,y,width(),height());
+ positionScrollbars(layerBounds);
+ }
+
+#ifdef APPLE_CHANGES
+ // FIXME: Child object could override visibility.
+ if (checkForRepaint && (m_object->style()->visibility() == VISIBLE))
+ m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_fullRepaintRect);
+#else
+ if (checkForRepaint && m_markedForRepaint) {
+ TQRect layerBounds, damageRect, fgrect;
+ calculateRects(rootLayer, renderer()->viewRect(), layerBounds, damageRect, fgrect);
+ TQRect vr = damageRect.intersect( layerBounds );
+ if (vr != m_visibleRect && vr.isValid()) {
+ renderer()->canvas()->repaintViewRectangle( vr.x(), vr.y(), vr.width(), vr.height() );
+ m_visibleRect = vr;
+ }
+ }
+ m_markedForRepaint = false;
+#endif
+
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->updateLayerPositions(rootLayer, doFullRepaint, checkForRepaint);
+
+ // With all our children positioned, now update our marquee if we need to.
+ if (m_marquee)
+ m_marquee->updateMarqueePosition();
+}
+
+void RenderLayer::updateWidgetMasks(RenderLayer* rootLayer)
+{
+ if (hasOverlaidWidgets() && !renderer()->canvas()->pagedMode()) {
+ updateZOrderLists();
+ uint count = m_posZOrderList ? m_posZOrderList->count() : 0;
+ bool needUpdate = (count || !m_region.isNull());
+ if (count) {
+ TQScrollView* sv = m_object->document()->view();
+ m_region = TQRect(0,0,sv->contentsWidth(),sv->contentsHeight());
+
+ for (uint i = 0; i < count; i++) {
+ RenderLayer* child = m_posZOrderList->at(i);
+ if (child->zIndex() == 0 && child->renderer()->style()->position() == STATIC)
+ continue; // we don't know the widget's exact stacking position within flow
+ m_region -= child->paintedRegion(rootLayer);
+ }
+ } else {
+ m_region = TQRegion();
+ }
+ if (needUpdate)
+ renderer()->updateWidgetMasks();
+ }
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->updateWidgetMasks(rootLayer);
+}
+
+short RenderLayer::width() const
+{
+ int w = m_object->width();
+ if (!m_object->hasOverflowClip())
+ w = kMax(m_object->overflowWidth(), w);
+ return w;
+}
+
+int RenderLayer::height() const
+{
+ int h = m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra();
+ if (!m_object->hasOverflowClip())
+ h = kMax(m_object->overflowHeight(), h);
+ return h;
+}
+
+
+RenderLayer *RenderLayer::stackingContext() const
+{
+ RenderLayer* curr = parent();
+ for ( ; curr && !curr->m_object->isCanvas() &&
+ curr->m_object->style()->hasAutoZIndex();
+ curr = curr->parent());
+ return curr;
+}
+
+RenderLayer* RenderLayer::enclosingPositionedAncestor() const
+{
+ RenderLayer* curr = parent();
+ for ( ; curr && !curr->m_object->isCanvas() &&
+ !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
+ curr = curr->parent());
+
+ return curr;
+}
+
+#ifdef APPLE_CHANGES
+bool RenderLayer::isTransparent()
+{
+ return m_object->style()->opacity() < 1.0f;
+}
+
+RenderLayer* RenderLayer::transparentAncestor()
+{
+ RenderLayer* curr = parent();
+ for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
+ return curr;
+}
+#endif
+
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void RenderLayer::operator delete(void* ptr, size_t sz)
+{
+ assert(inRenderLayerDetach);
+
+ // Stash size where detach can find it.
+ *(size_t *)ptr = sz;
+}
+
+void RenderLayer::detach(RenderArena* renderArena)
+{
+#ifndef NDEBUG
+ inRenderLayerDetach = true;
+#endif
+ delete this;
+#ifndef NDEBUG
+ inRenderLayerDetach = false;
+#endif
+
+ // Recover the size left there for us by operator delete and free the memory.
+ renderArena->free(*(size_t *)this, this);
+}
+
+void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
+{
+ RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
+ if (prevSibling) {
+ child->setPreviousSibling(prevSibling);
+ prevSibling->setNextSibling(child);
+ }
+ else
+ setFirstChild(child);
+
+ if (beforeChild) {
+ beforeChild->setPreviousSibling(child);
+ child->setNextSibling(beforeChild);
+ }
+ else
+ setLastChild(child);
+
+ child->setParent(this);
+
+ if (child->isOverflowOnly())
+ dirtyOverflowList();
+ else {
+ // Dirty the z-order list in which we are contained. The stackingContext() can be null in the
+ // case where we're building up generated content layers. This is ok, since the lists will start
+ // off dirty in that case anyway.
+ RenderLayer* stackingContext = child->stackingContext();
+ if (stackingContext)
+ stackingContext->dirtyZOrderLists();
+ }
+}
+
+RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
+{
+ // remove the child
+ if (oldChild->previousSibling())
+ oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+ if (oldChild->nextSibling())
+ oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+ if (m_first == oldChild)
+ m_first = oldChild->nextSibling();
+ if (m_last == oldChild)
+ m_last = oldChild->previousSibling();
+
+ if (oldChild->isOverflowOnly())
+ dirtyOverflowList();
+ else {
+ // Dirty the z-order list in which we are contained. When called via the
+ // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
+ // from the main layer tree, so we need to null-check the |stackingContext| value.
+ RenderLayer* stackingContext = oldChild->stackingContext();
+ if (stackingContext)
+ stackingContext->dirtyZOrderLists();
+ }
+
+ oldChild->setPreviousSibling(0);
+ oldChild->setNextSibling(0);
+ oldChild->setParent(0);
+
+ return oldChild;
+}
+
+void RenderLayer::removeOnlyThisLayer()
+{
+ if (!m_parent)
+ return;
+
+ // Remove us from the parent.
+ RenderLayer* parent = m_parent;
+ RenderLayer* nextSib = nextSibling();
+ parent->removeChild(this);
+
+ // Now walk our kids and reattach them to our parent.
+ RenderLayer* current = m_first;
+ while (current) {
+ RenderLayer* next = current->nextSibling();
+ removeChild(current);
+ parent->addChild(current, nextSib);
+ current = next;
+ }
+
+ detach(renderer()->renderArena());
+}
+
+void RenderLayer::insertOnlyThisLayer()
+{
+ if (!m_parent && renderer()->parent()) {
+ // We need to connect ourselves when our renderer() has a parent.
+ // Find our enclosingLayer and add ourselves.
+ RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
+ if (parentLayer)
+ parentLayer->addChild(this,
+ renderer()->parent()->findNextLayer(parentLayer, renderer()));
+ }
+
+ // Remove all descendant layers from the hierarchy and add them to the new position.
+ for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
+ curr->moveLayers(m_parent, this);
+}
+
+void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
+{
+ if (ancestorLayer == this)
+ return;
+
+ if (m_object->style()->position() == FIXED) {
+ // Add in the offset of the view. We can obtain this by calling
+ // absolutePosition() on the RenderCanvas.
+ int xOff, yOff;
+ m_object->absolutePosition(xOff, yOff, true);
+ x += xOff;
+ y += yOff;
+ return;
+ }
+
+ RenderLayer* parentLayer;
+ if (m_object->style()->position() == ABSOLUTE)
+ parentLayer = enclosingPositionedAncestor();
+ else
+ parentLayer = parent();
+
+ if (!parentLayer) return;
+
+ parentLayer->convertToLayerCoords(ancestorLayer, x, y);
+
+ x += xPos();
+ y += yPos();
+}
+
+void RenderLayer::scrollOffset(int& x, int& y)
+{
+ x += scrollXOffset();
+ y += scrollYOffset();
+}
+
+void RenderLayer::subtractScrollOffset(int& x, int& y)
+{
+ x -= scrollXOffset();
+ y -= scrollYOffset();
+}
+
+void RenderLayer::checkInlineRelOffset(const RenderObject* o, int& x, int& y)
+{
+ if(o->style()->position() != ABSOLUTE || !renderer()->isRelPositioned() || !renderer()->isInlineFlow())
+ return;
+
+ // Our renderer is an enclosing relpositioned inline, we need to add in the offset of the first line
+ // box from the rest of the content, but only in the cases where we know our descendant is positioned
+ // relative to the inline itself.
+ assert( o->container() == m_object );
+
+ RenderFlow* flow = static_cast<RenderFlow*>(m_object);
+ int sx = 0, sy = 0;
+ if (flow->firstLineBox()) {
+ if (flow->style()->direction() == LTR)
+ sx = flow->firstLineBox()->xPos();
+ else
+ sx = flow->lastLineBox()->xPos();
+ sy = flow->firstLineBox()->yPos();
+ } else {
+ sx = flow->staticX(); // ###
+ sy = flow->staticY();
+ }
+ bool isInlineType = o->style()->isOriginalDisplayInlineType();
+
+ if (!o->hasStaticX())
+ x += sx;
+
+ // Despite the positioned child being a block display type inside an inline, we still keep
+ // its x locked to our left. Arguably the correct behavior would be to go flush left to
+ // the block that contains us, but that isn't what other browsers do.
+ if (o->hasStaticX() && !isInlineType)
+ // Avoid adding in the left border/padding of the containing block twice. Subtract it out.
+ x += sx - (o->containingBlock()->borderLeft() + o->containingBlock()->paddingLeft());
+
+ if (!o->hasStaticY())
+ y += sy;
+}
+
+void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
+{
+ if (renderer()->style()->overflowX() != OMARQUEE || !renderer()->hasOverflowClip()) {
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
+ // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
+ // to be (for overflow:hidden blocks).
+ // ### merge the scrollWidth()/scrollHeight() methods
+ int maxX = m_scrollWidth - m_object->clientWidth();
+ int maxY = m_scrollHeight - m_object->clientHeight();
+
+ if (x > maxX) x = maxX;
+ if (y > maxY) y = maxY;
+ }
+
+ // FIXME: Eventually, we will want to perform a blit. For now never
+ // blit, since the check for blitting is going to be very
+ // complicated (since it will involve testing whether our layer
+ // is either occluded by another layer or clipped by an enclosing
+ // layer or contains fixed backgrounds, etc.).
+ m_scrollX = x;
+ m_scrollY = y;
+
+ // Update the positions of our child layers.
+ RenderLayer* rootLayer = root();
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->updateLayerPositions(rootLayer);
+
+ // Fire the scroll DOM event.
+ m_object->element()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
+
+ // Just schedule a full repaint of our object.
+ if (repaint)
+ m_object->repaint(RealtimePriority);
+
+ if (updateScrollbars) {
+ if (m_hBar)
+ m_hBar->setValue(m_scrollX);
+ if (m_vBar)
+ m_vBar->setValue(m_scrollY);
+ }
+}
+
+void RenderLayer::updateScrollPositionFromScrollbars()
+{
+ bool needUpdate = false;
+ int newX = m_scrollX;
+ int newY = m_scrollY;
+
+ if (m_hBar) {
+ newX = m_hBar->value();
+ if (newX != m_scrollX)
+ needUpdate = true;
+ }
+
+ if (m_vBar) {
+ newY = m_vBar->value();
+ if (newY != m_scrollY)
+ needUpdate = true;
+ }
+
+ if (needUpdate)
+ scrollToOffset(newX, newY, false);
+}
+
+void
+RenderLayer::showScrollbar(Qt::Orientation o, bool show)
+{
+ TQScrollBar *sb = (o == Qt::Horizontal) ? m_hBar : m_vBar;
+
+ if (show && !sb) {
+ TQScrollView* scrollView = m_object->document()->view();
+ sb = new TQScrollBar(o, scrollView, "__tdehtml");
+ scrollView->addChild(sb, 0, -50000);
+ sb->setBackgroundMode(TQWidget::NoBackground);
+ sb->show();
+ if (!m_scrollMediator)
+ m_scrollMediator = new RenderScrollMediator(this);
+ m_scrollMediator->connect(sb, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotValueChanged()));
+ }
+ else if (!show && sb) {
+ delete sb;
+ sb = 0;
+ }
+
+ if (o == Qt::Horizontal)
+ m_hBar = sb;
+ else
+ m_vBar = sb;
+}
+
+int RenderLayer::verticalScrollbarWidth()
+{
+ if (!m_vBar)
+ return 0;
+
+#ifdef APPLE_CHANGES
+ return m_vBar->width();
+#else
+ return m_vBar->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
+#endif
+
+}
+
+int RenderLayer::horizontalScrollbarHeight()
+{
+ if (!m_hBar)
+ return 0;
+
+#ifdef APPLE_CHANGES
+ return m_hBar->height();
+#else
+ return m_hBar->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
+#endif
+
+}
+
+void RenderLayer::positionScrollbars(const TQRect& absBounds)
+{
+#ifdef APPLE_CHANGES
+ if (m_vBar) {
+ scrollView->addChild(m_vBar, absBounds.x()+absBounds.width()-m_object->borderRight()-m_vBar->width(),
+ absBounds.y()+m_object->borderTop());
+ m_vBar->resize(m_vBar->width(), absBounds.height() -
+ (m_object->borderTop()+m_object->borderBottom()) -
+ (m_hBar ? m_hBar->height()-1 : 0));
+ }
+
+ if (m_hBar) {
+ scrollView->addChild(m_hBar, absBounds.x()+m_object->borderLeft(),
+ absBounds.y()+absBounds.height()-m_object->borderBottom()-m_hBar->height());
+ m_hBar->resize(absBounds.width() - (m_object->borderLeft()+m_object->borderRight()) -
+ (m_vBar ? m_vBar->width()-1 : 0), m_hBar->height());
+ }
+#else
+ int tx = absBounds.x();
+ int ty = absBounds.y();
+ int bl = m_object->borderLeft();
+ int bt = m_object->borderTop();
+ int w = width() - bl - m_object->borderRight();
+ int h = height() - bt - m_object->borderBottom();
+
+ if (w <= 0 || h <= 0 || (!m_vBar && !m_hBar))
+ return;
+
+ TQScrollView* scrollView = m_object->document()->view();
+
+ tx += bl;
+ ty += bt;
+
+ TQScrollBar *b = m_hBar;
+ if (!m_hBar)
+ b = m_vBar;
+ int sw = b->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
+
+ if (m_vBar) {
+ TQRect vBarRect = TQRect(tx + w - sw + 1, ty, sw, h - (m_hBar ? sw : 0) + 1);
+ m_vBar->resize(vBarRect.width(), vBarRect.height());
+ scrollView->addChild(m_vBar, vBarRect.x(), vBarRect.y());
+ }
+
+ if (m_hBar) {
+ TQRect hBarRect = TQRect(tx, ty + h - sw + 1, w - (m_vBar ? sw : 0) + 1, sw);
+ m_hBar->resize(hBarRect.width(), hBarRect.height());
+ scrollView->addChild(m_hBar, hBarRect.x(), hBarRect.y());
+ }
+#endif
+}
+
+#define LINE_STEP 10
+#define PAGE_KEEP 40
+
+void RenderLayer::checkScrollbarsAfterLayout()
+{
+ int rightPos = m_object->rightmostPosition(true);
+ int bottomPos = m_object->lowestPosition(true);
+
+/* TODO
+ m_scrollLeft = m_object->leftmostPosition(true);
+ m_scrollTop = m_object->highestPosition(true);
+*/
+
+ int clientWidth = m_object->clientWidth();
+ int clientHeight = m_object->clientHeight();
+ m_scrollWidth = clientWidth;
+ m_scrollHeight = clientHeight;
+
+ if (rightPos - m_object->borderLeft() > m_scrollWidth)
+ m_scrollWidth = rightPos - m_object->borderLeft();
+ if (bottomPos - m_object->borderTop() > m_scrollHeight)
+ m_scrollHeight = bottomPos - m_object->borderTop();
+
+ bool needHorizontalBar = rightPos > width();
+ bool needVerticalBar = bottomPos > height();
+
+ bool haveHorizontalBar = m_hBar && m_hBar->isEnabled();
+ bool haveVerticalBar = m_vBar && m_vBar->isEnabled();
+
+ bool hasOvf = m_object->hasOverflowClip();
+
+ // overflow:scroll should just enable/disable.
+ if (hasOvf && m_object->style()->overflowX() == OSCROLL)
+ m_hBar->setEnabled(needHorizontalBar);
+ if (hasOvf && m_object->style()->overflowY() == OSCROLL)
+ m_vBar->setEnabled(needVerticalBar);
+
+ // overflow:auto may need to lay out again if scrollbars got added/removed.
+ bool scrollbarsChanged = (hasOvf && m_object->style()->overflowX() == OAUTO && haveHorizontalBar != needHorizontalBar)
+ || (hasOvf && m_object->style()->overflowY() == OAUTO && haveVerticalBar != needVerticalBar);
+ if (scrollbarsChanged) {
+ if (m_object->style()->overflowX() == OAUTO) {
+ showScrollbar(Qt::Horizontal, needHorizontalBar);
+ if (m_hBar)
+ m_hBar->setEnabled(true);
+ }
+ if (m_object->style()->overflowY() == OAUTO) {
+ showScrollbar(Qt::Vertical, needVerticalBar);
+ if (m_vBar)
+ m_vBar->setEnabled(true);
+ }
+
+ m_object->setNeedsLayout(true);
+ if (m_object->isRenderBlock())
+ static_cast<RenderBlock*>(m_object)->layoutBlock(true);
+ else
+ m_object->layout();
+ return;
+ }
+
+ // Set up the range (and page step/line step).
+ if (m_hBar) {
+ int pageStep = (clientWidth-PAGE_KEEP);
+ if (pageStep < 0) pageStep = clientWidth;
+ m_hBar->setSteps(LINE_STEP, pageStep);
+#ifdef APPLE_CHANGES
+ m_hBar->setKnobProportion(clientWidth, m_scrollWidth);
+#else
+ m_hBar->setRange(0, needHorizontalBar ? m_scrollWidth-clientWidth : 0);
+#endif
+ }
+ if (m_vBar) {
+ int pageStep = (clientHeight-PAGE_KEEP);
+ if (pageStep < 0) pageStep = clientHeight;
+ m_vBar->setSteps(LINE_STEP, pageStep);
+#ifdef APPLE_CHANGES
+ m_vBar->setKnobProportion(clientHeight, m_scrollHeight);
+#else
+ m_vBar->setRange(0, needVerticalBar ? m_scrollHeight-clientHeight : 0);
+#endif
+ }
+}
+
+void RenderLayer::paintScrollbars(RenderObject::PaintInfo& pI)
+{
+#ifdef APPLE_CHANGES
+ if (m_hBar)
+ m_hBar->paint(p, damageRect);
+ if (m_vBar)
+ m_vBar->paint(p, damageRect);
+#else
+ if (!m_object->element())
+ return;
+
+ TQScrollView* scrollView = m_object->document()->view();
+ if (m_hBar) {
+ int x = m_hBar->x();
+ int y = m_hBar->y();
+ scrollView->viewportToContents(x, y, x, y);
+ RenderWidget::paintWidget(pI, m_hBar, x, y);
+ }
+ if (m_vBar) {
+ int x = m_vBar->x();
+ int y = m_vBar->y();
+ scrollView->viewportToContents(x, y, x, y);
+ RenderWidget::paintWidget(pI, m_vBar, x, y);
+ }
+#endif
+}
+
+void RenderLayer::paint(TQPainter *p, const TQRect& damageRect, bool selectionOnly)
+{
+ paintLayer(this, p, damageRect, selectionOnly);
+}
+
+static void setClip(TQPainter* p, const TQRect& paintDirtyRect, const TQRect& clipRect)
+{
+ if (paintDirtyRect == clipRect)
+ return;
+ p->save();
+
+#ifdef APPLE_CHANGES
+ p->addClip(clipRect);
+#else
+
+ TQRect clippedRect = p->xForm(clipRect);
+ TQRegion creg(clippedRect);
+ TQRegion old = p->clipRegion();
+ if (!old.isNull())
+ creg = old.intersect(creg);
+ p->setClipRegion(creg);
+#endif
+
+}
+
+static void restoreClip(TQPainter* p, const TQRect& paintDirtyRect, const TQRect& clipRect)
+{
+ if (paintDirtyRect == clipRect)
+ return;
+ p->restore();
+}
+
+void RenderLayer::paintLayer(RenderLayer* rootLayer, TQPainter *p,
+ const TQRect& paintDirtyRect, bool selectionOnly)
+{
+ // Calculate the clip rects we should use.
+ TQRect layerBounds, damageRect, clipRectToApply;
+ calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
+ int x = layerBounds.x();
+ int y = layerBounds.y();
+
+ // Ensure our lists are up-to-date.
+ updateZOrderLists();
+ updateOverflowList();
+
+#ifdef APPLE_CHANGES
+ // Set our transparency if we need to.
+ if (isTransparent())
+ p->beginTransparencyLayer(renderer()->style()->opacity());
+#endif
+
+ // We want to paint our layer, but only if we intersect the damage rect.
+ bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
+ if (shouldPaint && !selectionOnly) {
+ // Paint our background first, before painting any child layers.
+ if (!damageRect.isEmpty()) {
+ // Establish the clip used to paint our background.
+ setClip(p, paintDirtyRect, damageRect);
+
+ // Paint the background.
+ RenderObject::PaintInfo paintInfo(p, damageRect, PaintActionElementBackground);
+ renderer()->paint(paintInfo,
+ x - renderer()->xPos(), y - renderer()->yPos() + renderer()->borderTopExtra());
+
+ // Position our scrollbars.
+ positionScrollbars(layerBounds);
+
+ // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+ // z-index. We paint after we painted the background/border, so that the scrollbars will
+ // sit above the background/border.
+ paintScrollbars(paintInfo);
+
+ // Restore the clip.
+ restoreClip(p, paintDirtyRect, damageRect);
+ }
+ }
+
+ // Now walk the sorted list of children with negative z-indices.
+ if (m_negZOrderList) {
+ uint count = m_negZOrderList->count();
+ for (uint i = 0; i < count; i++) {
+ RenderLayer* child = m_negZOrderList->at(i);
+ child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
+ }
+ }
+
+ // Now establish the appropriate clip and paint our child RenderObjects.
+ if (shouldPaint && !clipRectToApply.isEmpty()) {
+ // Set up the clip used when painting our children.
+ setClip(p, paintDirtyRect, clipRectToApply);
+
+ RenderObject::PaintInfo paintInfo(p, clipRectToApply, PaintActionSelection);
+
+ int tx = x - renderer()->xPos();
+ int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
+
+ if (selectionOnly)
+ renderer()->paint(paintInfo, tx, ty);
+ else {
+ paintInfo.phase = PaintActionChildBackgrounds;
+ renderer()->paint(paintInfo, tx, ty);
+ paintInfo.phase = PaintActionFloat;
+ renderer()->paint(paintInfo, tx, ty);
+ paintInfo.phase = PaintActionForeground;
+ renderer()->paint(paintInfo, tx, ty);
+ RenderCanvas *rc = static_cast<RenderCanvas*>(renderer()->document()->renderer());
+ if (rc->maximalOutlineSize()) {
+ paintInfo.phase = PaintActionOutline;
+ renderer()->paint(paintInfo, tx, ty);
+ }
+ if (rc->selectionStart() && rc->selectionEnd()) {
+ paintInfo.phase = PaintActionSelection;
+ renderer()->paint(paintInfo, tx, ty);
+ }
+ }
+
+ // Now restore our clip.
+ restoreClip(p, paintDirtyRect, clipRectToApply);
+ }
+
+ // Paint any child layers that have overflow.
+ if (m_overflowList)
+ for (TQValueList<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
+ (*it)->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
+
+ // Now walk the sorted list of children with positive z-indices.
+ if (m_posZOrderList) {
+ uint count = m_posZOrderList->count();
+ for (uint i = 0; i < count; i++) {
+ RenderLayer* child = m_posZOrderList->at(i);
+ child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
+ }
+ }
+
+#ifdef BOX_DEBUG
+ {
+ int ax=0;
+ int ay=0;
+ renderer()->absolutePosition( ax, ay );
+ p->setPen(TQPen(TQColor("yellow"), 1, Qt::DotLine));
+ p->setBrush( Qt::NoBrush );
+ p->drawRect(ax, ay, width(), height());
+ }
+#endif
+
+#ifdef APPLE_CHANGES
+ // End our transparency layer
+ if (isTransparent())
+ p->endTransparencyLayer();
+#endif
+}
+
+bool RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
+{
+#ifdef APPLE_CHANGES
+ // Clear our our scrollbar variable
+ RenderLayer::gScrollBar = 0;
+#endif
+
+ int stx = m_x;
+ int sty = m_y;
+
+#ifdef __GNUC__
+#warning HACK
+#endif
+ if (renderer()->isCanvas()) {
+ stx += static_cast<RenderCanvas*>(renderer())->view()->contentsX();
+ sty += static_cast<RenderCanvas*>(renderer())->view()->contentsY();
+ }
+
+ TQRect damageRect(stx,sty, width(), height());
+ RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);
+
+ // Now determine if the result is inside an anchor.
+ DOM::NodeImpl* node = info.innerNode();
+ while (node) {
+ if (node->hasAnchor() && !info.URLElement())
+ info.setURLElement(node);
+ node = node->parentNode();
+ }
+
+ // Next set up the correct :hover/:active state along the new chain.
+ updateHoverActiveState(info);
+
+ // Now return whether we were inside this layer (this will always be true for the root
+ // layer).
+ return insideLayer;
+}
+
+RenderLayer* RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+ int xMousePos, int yMousePos, const TQRect& hitTestRect)
+{
+ // Calculate the clip rects we should use.
+ TQRect layerBounds, bgRect, fgRect;
+ calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
+
+ // Ensure our lists are up-to-date.
+ updateZOrderLists();
+ updateOverflowList();
+
+ // This variable tracks which layer the mouse ends up being inside. The minute we find an insideLayer,
+ // we are done and can return it.
+ RenderLayer* insideLayer = 0;
+
+ // Begin by walking our list of positive layers from highest z-index down to the lowest
+ // z-index.
+ if (m_posZOrderList) {
+ uint count = m_posZOrderList->count();
+ for (int i = count-1; i >= 0; i--) {
+ RenderLayer* child = m_posZOrderList->at(i);
+ insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+ if (insideLayer)
+ return insideLayer;
+ }
+ }
+
+ // Now check our overflow objects.
+ if (m_overflowList) {
+ TQValueList<RenderLayer*>::iterator it = m_overflowList->end();
+ for (--it; it != m_overflowList->end(); --it) {
+ insideLayer = (*it)->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+ if (insideLayer)
+ return insideLayer;
+ }
+ }
+
+ // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
+ if (containsPoint(xMousePos, yMousePos, fgRect) &&
+ renderer()->nodeAtPoint(info, xMousePos, yMousePos,
+ layerBounds.x() - renderer()->xPos(),
+ layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
+ HitTestChildrenOnly)) {
+ if (info.innerNode() != m_object->element())
+ return this;
+ }
+
+ // Now check our negative z-index children.
+ if (m_negZOrderList) {
+ uint count = m_negZOrderList->count();
+ for (int i = count-1; i >= 0; i--) {
+ RenderLayer* child = m_negZOrderList->at(i);
+ insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+ if (insideLayer)
+ return insideLayer;
+ }
+ }
+
+ // Next we want to see if the mouse pos is inside this layer but not any of its children.
+ if (containsPoint(xMousePos, yMousePos, bgRect) &&
+ renderer()->nodeAtPoint(info, xMousePos, yMousePos,
+ layerBounds.x() - renderer()->xPos(),
+ layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
+ HitTestSelfOnly))
+ return this;
+
+ // No luck.
+ return 0;
+}
+
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, TQRect& overflowClipRect,
+ TQRect& posClipRect, TQRect& fixedClipRect)
+{
+ if (parent())
+ parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
+
+ switch (m_object->style()->position()) {
+ // A fixed object is essentially the root of its containing block hierarchy, so when
+ // we encounter such an object, we reset our clip rects to the fixedClipRect.
+ case FIXED:
+ posClipRect = fixedClipRect;
+ overflowClipRect = fixedClipRect;
+ break;
+ case ABSOLUTE:
+ overflowClipRect = posClipRect;
+ break;
+ case RELATIVE:
+ posClipRect = overflowClipRect;
+ break;
+ default:
+ break;
+ }
+
+ // Update the clip rects that will be passed to child layers.
+ if (m_object->hasOverflowClip() || m_object->hasClip()) {
+ // This layer establishes a clip of some kind.
+ int x = 0;
+ int y = 0;
+ convertToLayerCoords(rootLayer, x, y);
+
+ if (m_object->hasOverflowClip()) {
+ TQRect newOverflowClip = m_object->getOverflowClipRect(x,y);
+ overflowClipRect = newOverflowClip.intersect(overflowClipRect);
+ if (m_object->isPositioned() || m_object->isRelPositioned())
+ posClipRect = newOverflowClip.intersect(posClipRect);
+ }
+ if (m_object->hasClip()) {
+ TQRect newPosClip = m_object->getClipRect(x,y);
+ posClipRect = posClipRect.intersect(newPosClip);
+ overflowClipRect = overflowClipRect.intersect(newPosClip);
+ fixedClipRect = fixedClipRect.intersect(newPosClip);
+ }
+ }
+}
+
+void RenderLayer::calculateRects(const RenderLayer* rootLayer, const TQRect& paintDirtyRect, TQRect& layerBounds,
+ TQRect& backgroundRect, TQRect& foregroundRect)
+{
+ TQRect overflowClipRect = paintDirtyRect;
+ TQRect posClipRect = paintDirtyRect;
+ TQRect fixedClipRect = paintDirtyRect;
+ if (parent())
+ parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
+
+ int x = 0;
+ int y = 0;
+ convertToLayerCoords(rootLayer, x, y);
+ layerBounds = TQRect(x,y,width(),height());
+
+ backgroundRect = m_object->style()->position() == FIXED ? fixedClipRect :
+ (m_object->isPositioned() ? posClipRect : overflowClipRect);
+ foregroundRect = backgroundRect;
+
+ // Update the clip rects that will be passed to child layers.
+ if (m_object->hasOverflowClip() || m_object->hasClip()) {
+ // This layer establishes a clip of some kind.
+ if (m_object->hasOverflowClip())
+ foregroundRect = foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
+
+ if (m_object->hasClip()) {
+ // Clip applies to *us* as well, so go ahead and update the damageRect.
+ TQRect newPosClip = m_object->getClipRect(x,y);
+ backgroundRect = backgroundRect.intersect(newPosClip);
+ foregroundRect = foregroundRect.intersect(newPosClip);
+ }
+
+ // If we establish a clip at all, then go ahead and make sure our background
+ // rect is intersected with our layer's bounds.
+ backgroundRect = backgroundRect.intersect(layerBounds);
+ }
+}
+
+bool RenderLayer::intersectsDamageRect(const TQRect& layerBounds, const TQRect& damageRect) const
+{
+ return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
+ (renderer()->hasOverhangingFloats() && !renderer()->hasOverflowClip()) ||
+ (renderer()->isInline() && !renderer()->isReplaced()) ||
+ layerBounds.intersects(damageRect));
+}
+
+bool RenderLayer::containsPoint(int x, int y, const TQRect& damageRect) const
+{
+ return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
+ renderer()->hasOverhangingFloats() ||
+ (renderer()->isInline() && !renderer()->isReplaced()) ||
+ damageRect.contains(x, y));
+}
+
+// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
+// content (and perhaps XBL). That's why it uses the render tree and not the DOM tree.
+static RenderObject* hoverAncestor(RenderObject* obj)
+{
+ return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();
+}
+
+static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
+{
+ if (!obj1 || !obj2)
+ return 0;
+
+ for (RenderObject* currObj1 = obj1; currObj1; currObj1 = hoverAncestor(currObj1))
+ for (RenderObject* currObj2 = obj2; currObj2; currObj2 = hoverAncestor(currObj2))
+ if (currObj1 == currObj2)
+ return currObj1;
+
+ return 0;
+}
+
+
+void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
+{
+ // We don't update :hover/:active state when the info is marked as readonly.
+ if (info.readonly())
+ return;
+
+ DOM::NodeImpl *e = m_object->element();
+ DOM::DocumentImpl *doc = e ? e->getDocument() : 0;
+ if (!doc) return;
+
+ // Check to see if the hovered node has changed. If not, then we don't need to
+ // do anything.
+ DOM::NodeImpl* oldHoverNode = doc->hoverNode();
+ DOM::NodeImpl* newHoverNode = info.innerNode();
+
+ if (oldHoverNode == newHoverNode && (!oldHoverNode || oldHoverNode->active() == info.active()))
+ return;
+
+ // Update our current hover node.
+ doc->setHoverNode(newHoverNode);
+ if (info.active())
+ doc->setActiveNode(newHoverNode);
+ else
+ doc->setActiveNode(0);
+
+ // We have two different objects. Fetch their renderers.
+ RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
+ RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
+
+ // Locate the common ancestor render object for the two renderers.
+ RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
+
+ // The old hover path only needs to be cleared up to (and not including) the common ancestor;
+ for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = hoverAncestor(curr)) {
+ curr->setMouseInside(false);
+ if (curr->element()) {
+ curr->element()->setActive(false);
+ curr->element()->setHovered(false);
+ }
+ }
+
+ // Now set the hover state for our new object up to the root.
+ for (RenderObject* curr = newHoverObj; curr; curr = hoverAncestor(curr)) {
+ curr->setMouseInside(true);
+ if (curr->element()) {
+ curr->element()->setActive(info.active());
+ curr->element()->setHovered(true);
+ }
+ }
+}
+
+// Sort the buffer from lowest z-index to highest. The common scenario will have
+// most z-indices equal, so we optimize for that case (i.e., the list will be mostly
+// sorted already).
+static void sortByZOrder(TQPtrVector<RenderLayer>* buffer,
+ TQPtrVector<RenderLayer>* mergeBuffer,
+ uint start, uint end)
+{
+ if (start >= end)
+ return; // Sanity check.
+
+ if (end - start <= 6) {
+ // Apply a bubble sort for smaller lists.
+ for (uint i = end-1; i > start; i--) {
+ bool sorted = true;
+ for (uint j = start; j < i; j++) {
+ RenderLayer* elt = buffer->at(j);
+ RenderLayer* elt2 = buffer->at(j+1);
+ if (elt->zIndex() > elt2->zIndex()) {
+ sorted = false;
+ buffer->insert(j, elt2);
+ buffer->insert(j+1, elt);
+ }
+ }
+ if (sorted)
+ return;
+ }
+ }
+ else {
+ // Peform a merge sort for larger lists.
+ uint mid = (start+end)/2;
+ sortByZOrder(buffer, mergeBuffer, start, mid);
+ sortByZOrder(buffer, mergeBuffer, mid, end);
+
+ RenderLayer* elt = buffer->at(mid-1);
+ RenderLayer* elt2 = buffer->at(mid);
+
+ // Handle the fast common case (of equal z-indices). The list may already
+ // be completely sorted.
+ if (elt->zIndex() <= elt2->zIndex())
+ return;
+
+ // We have to merge sort. Ensure our merge buffer is big enough to hold
+ // all the items.
+ mergeBuffer->resize(end - start);
+ uint i1 = start;
+ uint i2 = mid;
+
+ elt = buffer->at(i1);
+ elt2 = buffer->at(i2);
+
+ while (i1 < mid || i2 < end) {
+ if (i1 < mid && (i2 == end || elt->zIndex() <= elt2->zIndex())) {
+ mergeBuffer->insert(mergeBuffer->count(), elt);
+ i1++;
+ if (i1 < mid)
+ elt = buffer->at(i1);
+ }
+ else {
+ mergeBuffer->insert(mergeBuffer->count(), elt2);
+ i2++;
+ if (i2 < end)
+ elt2 = buffer->at(i2);
+ }
+ }
+
+ for (uint i = start; i < end; i++)
+ buffer->insert(i, mergeBuffer->at(i-start));
+
+ mergeBuffer->clear();
+ }
+}
+
+void RenderLayer::dirtyZOrderLists()
+{
+ if (m_posZOrderList)
+ m_posZOrderList->clear();
+ if (m_negZOrderList)
+ m_negZOrderList->clear();
+ m_zOrderListsDirty = true;
+}
+
+void RenderLayer::dirtyOverflowList()
+{
+ if (m_overflowList)
+ m_overflowList->clear();
+ m_overflowListDirty = true;
+}
+
+void RenderLayer::updateZOrderLists()
+{
+ if (!isStackingContext() || !m_zOrderListsDirty)
+ return;
+
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->collectLayers(m_posZOrderList, m_negZOrderList);
+
+ // Sort the two lists.
+ if (m_posZOrderList) {
+ TQPtrVector<RenderLayer> mergeBuffer;
+ sortByZOrder(m_posZOrderList, &mergeBuffer, 0, m_posZOrderList->count());
+ }
+ if (m_negZOrderList) {
+ TQPtrVector<RenderLayer> mergeBuffer;
+ sortByZOrder(m_negZOrderList, &mergeBuffer, 0, m_negZOrderList->count());
+ }
+
+ m_zOrderListsDirty = false;
+}
+
+void RenderLayer::updateOverflowList()
+{
+ if (!m_overflowListDirty)
+ return;
+
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isOverflowOnly()) {
+ if (!m_overflowList)
+ m_overflowList = new TQValueList<RenderLayer*>;
+ m_overflowList->append(child);
+ }
+ }
+
+ m_overflowListDirty = false;
+}
+
+void RenderLayer::collectLayers(TQPtrVector<RenderLayer>*& posBuffer, TQPtrVector<RenderLayer>*& negBuffer)
+{
+ // FIXME: A child render object or layer could override visibility. Don't remove this
+ // optimization though until RenderObject's nodeAtPoint is patched to understand what to do
+ // when visibility is overridden by a child.
+ if (renderer()->style()->visibility() != VISIBLE)
+ return;
+
+ // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
+ if (!isOverflowOnly()) {
+
+ // Determine which buffer the child should be in.
+ TQPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+
+ // Create the buffer if it doesn't exist yet.
+ if (!buffer)
+ buffer = new TQPtrVector<RenderLayer>();
+
+ // Resize by a power of 2 when our buffer fills up.
+ if (buffer->count() == buffer->size())
+ buffer->resize(2*(buffer->size()+1));
+
+ // Append ourselves at the end of the appropriate buffer.
+ buffer->insert(buffer->count(), this);
+ }
+
+ // Recur into our children to collect more layers, but only if we don't establish
+ // a stacking context.
+ if (!isStackingContext()) {
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->collectLayers(posBuffer, negBuffer);
+ }
+}
+
+#ifdef ENABLE_DUMP
+#ifndef KDE_USE_FINAL
+static TQTextStream &operator<<(TQTextStream &ts, const TQRect &r)
+{
+ return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
+}
+#endif
+
+static void write(TQTextStream &ts, RenderObject& o, const TQString& indent )
+{
+ o.dump(ts, indent);
+
+ for (RenderObject *child = o.firstChild(); child; child = child->nextSibling()) {
+ if (child->layer()) continue;
+ write( ts, *child, indent + " " );
+ }
+}
+
+static void write(TQTextStream &ts, const RenderLayer &l,
+ const TQRect& layerBounds, const TQRect& backgroundClipRect, const TQRect& clipRect,
+ int layerType = 0, const TQString& indent = TQString::null)
+
+{
+ ts << indent << "layer";
+
+ ts << " at (" << l.xPos() << "," << l.yPos() << ") size " << l.width() << "x" << l.height();
+
+ if (layerBounds != layerBounds.intersect(backgroundClipRect)) {
+ ts << " backgroundClip " << backgroundClipRect;
+ }
+ if (layerBounds != layerBounds.intersect(clipRect)) {
+ ts << " clip " << clipRect;
+ }
+
+ if (layerType == -1)
+ ts << " layerType: background only";
+ else if (layerType == 1)
+ ts << " layerType: foreground only";
+
+ ts << "\n";
+
+ if (layerType != -1)
+ write( ts, *l.renderer(), indent + " " );
+
+ ts << "\n";
+}
+
+static void writeLayers(TQTextStream &ts, const RenderLayer* rootLayer, RenderLayer* l,
+ const TQRect& paintDirtyRect, const TQString& indent)
+{
+ // Calculate the clip rects we should use.
+ TQRect layerBounds, damageRect, clipRectToApply;
+ l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
+
+ // Ensure our lists are up-to-date.
+ l->updateZOrderLists();
+ l->updateOverflowList();
+
+ bool shouldPaint = l->intersectsDamageRect(layerBounds, damageRect);
+ TQPtrVector<RenderLayer>* negList = l->negZOrderList();
+ TQValueList<RenderLayer*>* ovfList = l->overflowList();
+ if (shouldPaint && negList && negList->count() > 0)
+ write(ts, *l, layerBounds, damageRect, clipRectToApply, -1, indent);
+
+ if (negList) {
+ for (unsigned i = 0; i != negList->count(); ++i)
+ writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, indent );
+ }
+
+ if (shouldPaint)
+ write(ts, *l, layerBounds, damageRect, clipRectToApply, negList && negList->count() > 0, indent);
+
+ if (ovfList) {
+ for (TQValueList<RenderLayer*>::iterator it = ovfList->begin(); it != ovfList->end(); ++it)
+ writeLayers(ts, rootLayer, *it, paintDirtyRect, indent);
+ }
+
+ TQPtrVector<RenderLayer>* posList = l->posZOrderList();
+ if (posList) {
+ for (unsigned i = 0; i != posList->count(); ++i)
+ writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, indent);
+ }
+}
+
+
+void RenderLayer::dump(TQTextStream &ts, const TQString &ind)
+{
+ assert( renderer()->isCanvas() );
+
+ writeLayers(ts, this, this, TQRect(xPos(), yPos(), width(), height()), ind);
+}
+
+
+#endif
+
+bool RenderLayer::shouldBeOverflowOnly() const
+{
+ return renderer()->style() && renderer()->hasOverflowClip() &&
+ !renderer()->isPositioned() && !renderer()->isRelPositioned();
+ /* && !isTransparent(); */
+}
+
+void RenderLayer::styleChanged()
+{
+ bool isOverflowOnly = shouldBeOverflowOnly();
+ if (isOverflowOnly != m_isOverflowOnly) {
+ m_isOverflowOnly = isOverflowOnly;
+ RenderLayer* p = parent();
+ RenderLayer* sc = stackingContext();
+ if (p)
+ p->dirtyOverflowList();
+ if (sc)
+ sc->dirtyZOrderLists();
+ }
+
+ if (m_object->hasOverflowClip() &&
+ m_object->style()->overflowX() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
+ if (!m_marquee)
+ m_marquee = new Marquee(this);
+ m_marquee->updateMarqueeStyle();
+ }
+ else if (m_marquee) {
+ delete m_marquee;
+ m_marquee = 0;
+ }
+}
+
+void RenderLayer::suspendMarquees()
+{
+ if (m_marquee)
+ m_marquee->suspend();
+
+ for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+ curr->suspendMarquees();
+}
+
+// --------------------------------------------------------------------------
+// Marquee implementation
+
+Marquee::Marquee(RenderLayer* l)
+:m_layer(l), m_currentLoop(0), m_totalLoops(0), m_timerId(0), m_start(0), m_end(0), m_speed(0), m_unfurlPos(0), m_reset(false),
+ m_suspended(false), m_stopped(false), m_whiteSpace(NORMAL), m_direction(MAUTO)
+{
+}
+
+int Marquee::marqueeSpeed() const
+{
+ int result = m_layer->renderer()->style()->marqueeSpeed();
+ DOM::NodeImpl* elt = m_layer->renderer()->element();
+ if (elt && elt->id() == ID_MARQUEE) {
+ HTMLMarqueeElementImpl* marqueeElt = static_cast<HTMLMarqueeElementImpl*>(elt);
+ result = kMax(result, marqueeElt->minimumDelay());
+ }
+ return result;
+}
+
+EMarqueeDirection Marquee::direction() const
+{
+ // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
+ // For now just map MAUTO to MBACKWARD
+ EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
+ EDirection dir = m_layer->renderer()->style()->direction();
+ if (result == MAUTO)
+ result = MBACKWARD;
+ if (result == MFORWARD)
+ result = (dir == LTR) ? MRIGHT : MLEFT;
+ if (result == MBACKWARD)
+ result = (dir == LTR) ? MLEFT : MRIGHT;
+
+ // Now we have the real direction. Next we check to see if the increment is negative.
+ // If so, then we reverse the direction.
+ Length increment = m_layer->renderer()->style()->marqueeIncrement();
+ if (increment.value() < 0)
+ result = static_cast<EMarqueeDirection>(-result);
+
+ return result;
+}
+
+bool Marquee::isHorizontal() const
+{
+ return direction() == MLEFT || direction() == MRIGHT;
+}
+
+bool Marquee::isUnfurlMarquee() const
+{
+ EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
+ return (behavior == MUNFURL);
+}
+
+int Marquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
+{
+ RenderObject* o = m_layer->renderer();
+ RenderStyle* s = o->style();
+ if (isHorizontal()) {
+ bool ltr = s->direction() == LTR;
+ int clientWidth = o->clientWidth();
+ int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
+ if (ltr)
+ contentWidth += (o->paddingRight() - o->borderLeft());
+ else {
+ contentWidth = o->width() - contentWidth;
+ contentWidth += (o->paddingLeft() - o->borderRight());
+ }
+ if (dir == MRIGHT) {
+ if (stopAtContentEdge)
+ return kMax(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+ else
+ return ltr ? contentWidth : clientWidth;
+ }
+ else {
+ if (stopAtContentEdge)
+ return kMin(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+ else
+ return ltr ? -clientWidth : -contentWidth;
+ }
+ }
+ else {
+ int contentHeight = m_layer->renderer()->lowestPosition(true, false) -
+ m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
+ int clientHeight = m_layer->renderer()->clientHeight();
+ if (dir == MUP) {
+ if (stopAtContentEdge)
+ return kMin(contentHeight - clientHeight, 0);
+ else
+ return -clientHeight;
+ }
+ else {
+ if (stopAtContentEdge)
+ return kMax(contentHeight - clientHeight, 0);
+ else
+ return contentHeight;
+ }
+ }
+}
+
+void Marquee::start()
+{
+ if (m_timerId || m_layer->renderer()->style()->marqueeIncrement().value() == 0)
+ return;
+
+ if (!m_suspended && !m_stopped) {
+ if (isUnfurlMarquee()) {
+ bool forward = direction() == MDOWN || direction() == MRIGHT;
+ bool isReversed = (forward && m_currentLoop % 2) || (!forward && !(m_currentLoop % 2));
+ m_unfurlPos = isReversed ? m_end : m_start;
+ m_layer->renderer()->setChildNeedsLayout(true);
+ }
+ else {
+ if (isHorizontal())
+ m_layer->scrollToOffset(m_start, 0, false, false);
+ else
+ m_layer->scrollToOffset(0, m_start, false, false);
+ }
+ }
+ else
+ m_suspended = false;
+
+ m_stopped = false;
+ m_timerId = startTimer(speed());
+}
+
+void Marquee::suspend()
+{
+ if (m_timerId) {
+ killTimer(m_timerId);
+ m_timerId = 0;
+ }
+
+ m_suspended = true;
+}
+
+void Marquee::stop()
+{
+ if (m_timerId) {
+ killTimer(m_timerId);
+ m_timerId = 0;
+ }
+
+ m_stopped = true;
+}
+
+void Marquee::updateMarqueePosition()
+{
+ bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+ if (activate) {
+ if (isUnfurlMarquee()) {
+ if (m_unfurlPos < m_start) {
+ m_unfurlPos = m_start;
+ m_layer->renderer()->setChildNeedsLayout(true);
+ }
+ else if (m_unfurlPos > m_end) {
+ m_unfurlPos = m_end;
+ m_layer->renderer()->setChildNeedsLayout(true);
+ }
+ }
+ else {
+ EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
+ m_start = computePosition(direction(), behavior == MALTERNATE);
+ m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
+ }
+ if (!m_stopped) start();
+ }
+}
+
+void Marquee::updateMarqueeStyle()
+{
+ RenderStyle* s = m_layer->renderer()->style();
+
+ if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
+ m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
+
+ m_totalLoops = s->marqueeLoopCount();
+ m_direction = s->marqueeDirection();
+ m_whiteSpace = s->whiteSpace();
+
+ if (m_layer->renderer()->isHTMLMarquee()) {
+ // Hack for WinIE. In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
+ // one loop.
+ if (m_totalLoops <= 0 && (s->marqueeBehavior() == MSLIDE || s->marqueeBehavior() == MUNFURL))
+ m_totalLoops = 1;
+
+ // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
+ // all the text ends up on one line by default. Limit this hack to the <marquee> element to emulate
+ // WinIE's behavior. Someone using CSS3 can use white-space: nowrap on their own to get this effect.
+ // Second hack alert: Set the text-align back to auto. WinIE completely ignores text-align on the
+ // marquee element.
+ // FIXME: Bring these up with the CSS WG.
+ if (isHorizontal() && m_layer->renderer()->childrenInline()) {
+ s->setWhiteSpace(NOWRAP);
+ s->setTextAlign(TAAUTO);
+ }
+ }
+
+ if (speed() != marqueeSpeed()) {
+ m_speed = marqueeSpeed();
+ if (m_timerId) {
+ killTimer(m_timerId);
+ m_timerId = startTimer(speed());
+ }
+ }
+
+ // Check the loop count to see if we should now stop.
+ bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
+ if (activate && !m_timerId)
+ m_layer->renderer()->setNeedsLayout(true);
+ else if (!activate && m_timerId) {
+ // Destroy the timer.
+ killTimer(m_timerId);
+ m_timerId = 0;
+ }
+}
+
+void Marquee::timerEvent(TQTimerEvent* /*evt*/)
+{
+ if (m_layer->renderer()->needsLayout())
+ return;
+
+ if (m_reset) {
+ m_reset = false;
+ if (isHorizontal())
+ m_layer->scrollToXOffset(m_start);
+ else
+ m_layer->scrollToYOffset(m_start);
+ return;
+ }
+
+ RenderStyle* s = m_layer->renderer()->style();
+
+ int endPoint = m_end;
+ int range = m_end - m_start;
+ int newPos;
+ if (range == 0)
+ newPos = m_end;
+ else {
+ bool addIncrement = direction() == MUP || direction() == MLEFT;
+ bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
+ if (isUnfurlMarquee()) {
+ isReversed = (!addIncrement && m_currentLoop % 2) || (addIncrement && !(m_currentLoop % 2));
+ addIncrement = !isReversed;
+ }
+ if (isReversed) {
+ // We're going in the reverse direction.
+ endPoint = m_start;
+ range = -range;
+ if (!isUnfurlMarquee())
+ addIncrement = !addIncrement;
+ }
+ bool positive = range > 0;
+ int clientSize = isUnfurlMarquee() ? abs(range) :
+ (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
+ int increment = kMax(1, abs(m_layer->renderer()->style()->marqueeIncrement().width(clientSize)));
+ int currentPos = isUnfurlMarquee() ? m_unfurlPos :
+ (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
+ newPos = currentPos + (addIncrement ? increment : -increment);
+ if (positive)
+ newPos = kMin(newPos, endPoint);
+ else
+ newPos = kMax(newPos, endPoint);
+ }
+
+ if (newPos == endPoint) {
+ m_currentLoop++;
+ if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops) {
+ killTimer(m_timerId);
+ m_timerId = 0;
+ }
+ else if (s->marqueeBehavior() != MALTERNATE && s->marqueeBehavior() != MUNFURL)
+ m_reset = true;
+ }
+
+ if (isUnfurlMarquee()) {
+ m_unfurlPos = newPos;
+ m_layer->renderer()->setChildNeedsLayout(true);
+ }
+ else {
+ if (isHorizontal())
+ m_layer->scrollToXOffset(newPos);
+ else
+ m_layer->scrollToYOffset(newPos);
+ }
+}
+
+#include "render_layer.moc"
diff --git a/tdehtml/rendering/render_layer.h b/tdehtml/rendering/render_layer.h
new file mode 100644
index 000000000..ae5ddff65
--- /dev/null
+++ b/tdehtml/rendering/render_layer.h
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef render_layer_h
+#define render_layer_h
+
+#include <tqcolor.h>
+#include <tqrect.h>
+#include <assert.h>
+
+#include "render_object.h"
+
+class TQScrollBar;
+template <class T> class TQPtrVector;
+
+namespace tdehtml {
+ class RenderStyle;
+ class RenderTable;
+ class CachedObject;
+ class RenderCanvas;
+ class RenderText;
+ class RenderFrameSet;
+ class RenderObject;
+ class RenderScrollMediator;
+
+class RenderScrollMediator: public TQObject
+{
+ Q_OBJECT
+public:
+ RenderScrollMediator(RenderLayer* layer)
+ :m_layer(layer) {}
+
+public slots:
+ void slotValueChanged();
+
+private:
+ RenderLayer* m_layer;
+};
+
+// This class handles the auto-scrolling of layers with overflow: marquee.
+class Marquee: public TQObject
+{
+ Q_OBJECT
+
+public:
+ Marquee(RenderLayer* l);
+
+ void timerEvent(TQTimerEvent*);
+
+ int speed() const { return m_speed; }
+ int marqueeSpeed() const;
+ EMarqueeDirection direction() const;
+ EMarqueeDirection reverseDirection() const { return static_cast<EMarqueeDirection>(-direction()); }
+ bool isHorizontal() const;
+ bool isUnfurlMarquee() const;
+ int unfurlPos() const { return m_unfurlPos; }
+
+ EWhiteSpace whiteSpace() { return m_whiteSpace; }
+
+ int computePosition(EMarqueeDirection dir, bool stopAtClientEdge);
+
+ void setEnd(int end) { m_end = end; }
+
+ void start();
+ void suspend();
+ void stop();
+
+ void updateMarqueeStyle();
+ void updateMarqueePosition();
+
+private:
+ RenderLayer* m_layer;
+ int m_currentLoop;
+ int m_totalLoops;
+ int m_timerId;
+ int m_start;
+ int m_end;
+ int m_speed;
+ int m_unfurlPos;
+ bool m_reset:1;
+ bool m_suspended:1;
+ bool m_stopped:1;
+ EWhiteSpace m_whiteSpace : 3;
+ EMarqueeDirection m_direction : 4;
+};
+
+class RenderLayer
+{
+public:
+#ifdef APPLE_CHANGES
+ static TQScrollBar* gScrollBar;
+#endif
+
+ RenderLayer(RenderObject* object);
+ ~RenderLayer();
+
+ RenderObject* renderer() const { return m_object; }
+ RenderLayer *parent() const { return m_parent; }
+ RenderLayer *previousSibling() const { return m_previous; }
+ RenderLayer *nextSibling() const { return m_next; }
+
+ RenderLayer *firstChild() const { return m_first; }
+ RenderLayer *lastChild() const { return m_last; }
+
+ void addChild(RenderLayer *newChild, RenderLayer* beforeChild = 0);
+ RenderLayer* removeChild(RenderLayer *oldChild);
+
+ void removeOnlyThisLayer();
+ void insertOnlyThisLayer();
+
+ void styleChanged();
+
+ Marquee* marquee() const { return m_marquee; }
+ void suspendMarquees();
+
+ bool isOverflowOnly() const { return m_isOverflowOnly; }
+
+#ifdef APPLE_CHANGES
+ bool isTransparent();
+ RenderLayer* transparentAncestor();
+#endif
+
+ RenderLayer* root() {
+ RenderLayer* curr = this;
+ while (curr->parent()) curr = curr->parent();
+ return curr;
+ }
+
+ int xPos() const { return m_x; }
+ int yPos() const { return m_y; }
+
+ short width() const;
+ int height() const;
+
+ short scrollWidth() const { return m_scrollWidth; }
+ int scrollHeight() const { return m_scrollHeight; }
+
+ void resize( int w, int h ) {
+ m_scrollWidth = w; m_scrollHeight = h;
+ }
+
+ void setPos( int xPos, int yPos ) {
+ m_x = xPos;
+ m_y = yPos;
+ }
+
+ // Scrolling methods for layers that can scroll their overflow.
+ void scrollOffset(int& x, int& y);
+ void subtractScrollOffset(int& x, int& y);
+ void checkInlineRelOffset(const RenderObject* o, int& x, int& y);
+ short scrollXOffset() { return m_scrollX; }
+ int scrollYOffset() { return m_scrollY; }
+ void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true);
+ void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); }
+ void scrollToYOffset(int y) { scrollToOffset(m_scrollX, y); }
+ void showScrollbar(Qt::Orientation, bool);
+ TQScrollBar* horizontalScrollbar() { return m_hBar; }
+ TQScrollBar* verticalScrollbar() { return m_vBar; }
+ int verticalScrollbarWidth();
+ int horizontalScrollbarHeight();
+ void positionScrollbars(const TQRect &damageRect);
+ void paintScrollbars(RenderObject::PaintInfo& pI);
+ void checkScrollbarsAfterLayout();
+ void slotValueChanged(int);
+ void repaint(Priority p=NormalPriority, bool markForRepaint = false);
+ void updateScrollPositionFromScrollbars();
+
+ void updateLayerPosition();
+ void updateLayerPositions( RenderLayer* rootLayer, bool doFullRepaint = false, bool checkForRepaint = false);
+
+ // Get the enclosing stacking context for this layer. A stacking context is a layer
+ // that has a non-auto z-index.
+ RenderLayer* stackingContext() const;
+ bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isCanvas(); }
+
+ void dirtyZOrderLists();
+ void updateZOrderLists();
+ TQPtrVector<RenderLayer>* posZOrderList() const { return m_posZOrderList; }
+ TQPtrVector<RenderLayer>* negZOrderList() const { return m_negZOrderList; }
+
+ void dirtyOverflowList();
+ void updateOverflowList();
+ TQValueList<RenderLayer*>* overflowList() const { return m_overflowList; }
+
+ void setHasOverlaidWidgets(bool b=true) { m_hasOverlaidWidgets = b; }
+ bool hasOverlaidWidgets() const { return m_hasOverlaidWidgets; }
+ TQRegion getMask() const { return m_region; }
+ TQRegion paintedRegion(RenderLayer* rootLayer);
+ void updateWidgetMasks(RenderLayer* rootLayer);
+
+ // Gets the nearest enclosing positioned ancestor layer (also includes
+ // the <html> layer and the root layer).
+ RenderLayer* enclosingPositionedAncestor() const;
+
+ void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
+
+ bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
+ int zIndex() const { return renderer()->style()->zIndex(); }
+
+ // The two main functions that use the layer system. The paint method
+ // paints the layers that intersect the damage rect from back to
+ // front. The nodeAtPoint method looks for mouse events by walking
+ // layers that intersect the point from front to back.
+ KDE_EXPORT void paint(TQPainter *p, const TQRect& damageRect, bool selectionOnly=false);
+ bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
+
+ // This method figures out our layerBounds in coordinates relative to
+ // |rootLayer}. It also computes our background and foreground clip rects
+ // for painting/event handling.
+ void calculateRects(const RenderLayer* rootLayer, const TQRect& paintDirtyRect, TQRect& layerBounds,
+ TQRect& backgroundRect, TQRect& foregroundRect);
+ void calculateClipRects(const RenderLayer* rootLayer, TQRect& overflowClipRect,
+ TQRect& posClipRect, TQRect& fixedClipRect);
+
+ bool intersectsDamageRect(const TQRect& layerBounds, const TQRect& damageRect) const;
+ bool containsPoint(int x, int y, const TQRect& damageRect) const;
+
+ void updateHoverActiveState(RenderObject::NodeInfo& info);
+
+ void detach(RenderArena* renderArena);
+
+#ifdef ENABLE_DUMP
+ KDE_EXPORT void dump(TQTextStream &stream, const TQString &ind = TQString::null);
+#endif
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed on all render objects.
+ void* operator new(size_t sz) throw();
+
+private:
+ void setNextSibling(RenderLayer* next) { m_next = next; }
+ void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
+ void setParent(RenderLayer* parent) { m_parent = parent; }
+ void setFirstChild(RenderLayer* first) { m_first = first; }
+ void setLastChild(RenderLayer* last) { m_last = last; }
+
+ void collectLayers(TQPtrVector<RenderLayer>*&, TQPtrVector<RenderLayer>*&);
+
+ KDE_EXPORT void paintLayer(RenderLayer* rootLayer, TQPainter *p, const TQRect& paintDirtyRect, bool selectionOnly=false);
+ RenderLayer* nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+ int x, int y, const TQRect& hitTestRect);
+ bool shouldBeOverflowOnly() const;
+
+protected:
+ RenderObject* m_object;
+
+ RenderLayer* m_parent;
+ RenderLayer* m_previous;
+ RenderLayer* m_next;
+
+ RenderLayer* m_first;
+ RenderLayer* m_last;
+
+ // Our (x,y) coordinates are in our parent layer's coordinate space.
+ short m_x;
+ int m_y;
+
+ // Our scroll offsets if the view is scrolled.
+ short m_scrollX;
+ int m_scrollY;
+
+ // The width/height of our scrolled area.
+ short m_scrollWidth;
+ int m_scrollHeight;
+
+ // For layers with overflow, we have a pair of scrollbars.
+ TQScrollBar* m_hBar;
+ TQScrollBar* m_vBar;
+ RenderScrollMediator* m_scrollMediator;
+
+ // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
+ // descendant layers within the stacking context that have z-indices of 0 or greater
+ // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative
+ // z-indices.
+ TQPtrVector<RenderLayer>* m_posZOrderList;
+ TQPtrVector<RenderLayer>* m_negZOrderList;
+
+ // This list contains our overflow child layers.
+ TQValueList<RenderLayer*>* m_overflowList;
+
+ bool m_zOrderListsDirty: 1;
+ bool m_overflowListDirty: 1;
+ bool m_isOverflowOnly: 1;
+ bool m_markedForRepaint: 1;
+ bool m_hasOverlaidWidgets: 1;
+
+ TQRect m_visibleRect;
+
+ TQRegion m_region; // used by overlaid (non z-order aware) widgets
+
+ Marquee* m_marquee; // Used by layers with overflow:marquee
+};
+
+} // namespace
+#endif
diff --git a/tdehtml/rendering/render_line.cpp b/tdehtml/rendering/render_line.cpp
new file mode 100644
index 000000000..b518d3a43
--- /dev/null
+++ b/tdehtml/rendering/render_line.cpp
@@ -0,0 +1,996 @@
+/**
+* This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2003-2006 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.
+ */
+// -------------------------------------------------------------------------
+
+#include <kdebug.h>
+#include <assert.h>
+#include <tqpainter.h>
+#include <kglobal.h>
+
+#include "rendering/render_flow.h"
+#include "rendering/render_text.h"
+#include "rendering/render_table.h"
+#include "rendering/render_inline.h"
+#include "rendering/render_block.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_line.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "html/html_formimpl.h"
+#include "misc/htmltags.h"
+#include "tdehtmlview.h"
+
+using namespace DOM;
+using namespace tdehtml;
+
+#ifndef NDEBUG
+static bool inInlineBoxDetach;
+#endif
+
+class tdehtml::EllipsisBox : public InlineBox
+{
+public:
+ EllipsisBox(RenderObject* obj, const DOM::DOMString& ellipsisStr, InlineFlowBox* p,
+ int w, int y, int h, int b, bool firstLine, InlineBox* markupBox)
+ :InlineBox(obj), m_str(ellipsisStr) {
+ m_parent = p;
+ m_width = w;
+ m_y = y;
+ m_height = h;
+ m_baseline = b;
+ m_firstLine = firstLine;
+ m_constructed = true;
+ m_markupBox = markupBox;
+ }
+
+ void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+ bool nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
+
+private:
+ DOM::DOMString m_str;
+ InlineBox* m_markupBox;
+};
+
+void InlineBox::detach(RenderArena* renderArena)
+{
+ if (m_parent)
+ m_parent->removeFromLine(this);
+#ifndef NDEBUG
+ inInlineBoxDetach = true;
+#endif
+ delete this;
+#ifndef NDEBUG
+ inInlineBoxDetach = false;
+#endif
+
+ // Recover the size left there for us by operator delete and free the memory.
+ renderArena->free(*(size_t *)this, this);
+}
+
+void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void InlineBox::operator delete(void* ptr, size_t sz)
+{
+ assert(inInlineBoxDetach);
+
+ // Stash size where detach can find it.
+ *(size_t *)ptr = sz;
+}
+
+static bool needsOutlinePhaseRepaint(RenderObject* o, RenderObject::PaintInfo& i, int tx, int ty) {
+ if (o->style()->outlineWidth() <= 0)
+ return false;
+ TQRect r(tx+o->xPos(),ty+o->yPos(),o->width(),o->height());
+ if (r.intersects(i.r))
+ return false;
+ r.addCoords(-o->style()->outlineSize(),
+ -o->style()->outlineSize(),
+ o->style()->outlineSize(),
+ o->style()->outlineSize());
+ if (!r.intersects(i.r))
+ return false;
+ return true;
+}
+
+void InlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+ if ( i.phase == PaintActionOutline && !needsOutlinePhaseRepaint(object(), i, tx, ty) )
+ return;
+
+ // Paint all phases of replaced elements atomically, as though the replaced element established its
+ // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+ // specification.)
+ bool paintSelectionOnly = i.phase == PaintActionSelection;
+ RenderObject::PaintInfo info(i.p, i.r, paintSelectionOnly ? i.phase : PaintActionElementBackground);
+ object()->paint(info, tx, ty);
+ if (!paintSelectionOnly) {
+ info.phase = PaintActionChildBackgrounds;
+ object()->paint(info, tx, ty);
+ info.phase = PaintActionFloat;
+ object()->paint(info, tx, ty);
+ info.phase = PaintActionForeground;
+ object()->paint(info, tx, ty);
+ info.phase = PaintActionOutline;
+ object()->paint(info, tx, ty);
+ }
+}
+
+bool InlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+ // Hit test all phases of replaced elements atomically, as though the replaced element established its
+ // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
+ // specification.)
+ bool inside = false;
+ return object()->nodeAtPoint(i, x, y, tx, ty, HitTestAll, inside); // ### port hitTest
+}
+
+RootInlineBox* InlineBox::root()
+{
+ if (m_parent)
+ return m_parent->root();
+ return static_cast<RootInlineBox*>(this);
+}
+
+InlineFlowBox::~InlineFlowBox()
+{
+ /* If we're destroyed, set the children free, and break their links */
+ while (m_firstChild)
+ removeFromLine(m_firstChild);
+}
+
+void InlineFlowBox::removeFromLine(InlineBox *child)
+{
+ if (child == m_firstChild) {
+ m_firstChild = child->nextOnLine();
+ }
+ if (child == m_lastChild) {
+ m_lastChild = child->prevOnLine();
+ }
+ if (child->nextOnLine()) {
+ child->nextOnLine()->m_prev = child->prevOnLine();
+ }
+ if (child->prevOnLine()) {
+ child->prevOnLine()->m_next = child->nextOnLine();
+ }
+
+ child->setParent(0);
+}
+
+bool InlineBox::canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth)
+{
+ // Non-replaced elements can always accommodate an ellipsis.
+ if (!m_object || !m_object->isReplaced())
+ return true;
+
+ TQRect boxRect(m_x, 0, m_width, 10);
+ TQRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
+ return !(boxRect.intersects(ellipsisRect));
+}
+
+int InlineBox::placeEllipsisBox(bool /*ltr*/, int /*blockEdge*/, int /*ellipsisWidth*/, bool&)
+{
+ // Use -1 to mean "we didn't set the position."
+ return -1;
+}
+
+int InlineFlowBox::marginLeft() const
+{
+ if (!includeLeftEdge())
+ return 0;
+
+ RenderStyle* cstyle = object()->style();
+ Length margin = cstyle->marginLeft();
+ if (!margin.isVariable())
+ return (margin.isFixed() ? margin.value() : object()->marginLeft());
+ return 0;
+}
+
+int InlineFlowBox::marginRight() const
+{
+ if (!includeRightEdge())
+ return 0;
+
+ RenderStyle* cstyle = object()->style();
+ Length margin = cstyle->marginRight();
+ if (!margin.isVariable())
+ return (margin.isFixed() ? margin.value() : object()->marginRight());
+ return 0;
+}
+
+int InlineFlowBox::marginBorderPaddingLeft() const
+{
+ return marginLeft() + borderLeft() + paddingLeft();
+}
+
+int InlineFlowBox::marginBorderPaddingRight() const
+{
+ return marginRight() + borderRight() + paddingRight();
+}
+
+int InlineFlowBox::getFlowSpacingWidth() const
+{
+ int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (curr->isInlineFlowBox())
+ totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();
+ }
+ return totWidth;
+}
+
+bool InlineFlowBox::nextOnLineExists()
+{
+ if (!parent())
+ return false;
+
+ if (nextOnLine())
+ return true;
+
+ return parent()->nextOnLineExists();
+}
+
+bool InlineFlowBox::prevOnLineExists()
+{
+ if (!parent())
+ return false;
+
+ if (prevOnLine())
+ return true;
+
+ return parent()->prevOnLineExists();
+}
+
+bool InlineFlowBox::onEndChain(RenderObject* endObject)
+{
+ if (!endObject)
+ return false;
+
+ if (endObject == object())
+ return true;
+
+ RenderObject* curr = endObject;
+ RenderObject* parent = curr->parent();
+ while (parent && !parent->isRenderBlock()) {
+ if (parent->lastChild() != curr || parent == object())
+ return false;
+
+ curr = parent;
+ parent = curr->parent();
+ }
+
+ return true;
+}
+
+void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
+{
+ // All boxes start off open. They will not apply any margins/border/padding on
+ // any side.
+ bool includeLeftEdge = false;
+ bool includeRightEdge = false;
+
+ RenderFlow* flow = static_cast<RenderFlow*>(object());
+
+ if (!flow->firstChild())
+ includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
+ else if (parent()) { // The root inline box never has borders/margins/padding.
+ bool ltr = flow->style()->direction() == LTR;
+
+ // Check to see if all initial lines are unconstructed. If so, then
+ // we know the inline began on this line.
+ if (!flow->firstLineBox()->isConstructed()) {
+ if (ltr && flow->firstLineBox() == this)
+ includeLeftEdge = true;
+ else if (!ltr && flow->lastLineBox() == this)
+ includeRightEdge = true;
+ }
+
+ // In order to determine if the inline ends on this line, we check three things:
+ // (1) If we are the last line and we don't have a continuation(), then we can
+ // close up.
+ // (2) If the last line box for the flow has an object following it on the line (ltr,
+ // reverse for rtl), then the inline has closed.
+ // (3) The line may end on the inline. If we are the last child (climbing up
+ // the end object's chain), then we just closed as well.
+ if (!flow->lastLineBox()->isConstructed()) {
+ if (ltr) {
+ if (!nextLineBox() &&
+ ((lastLine && !object()->continuation()) || nextOnLineExists()
+ || onEndChain(endObject)))
+ includeRightEdge = true;
+ }
+ else {
+ if ((!prevLineBox() || !prevLineBox()->isConstructed()) &&
+ ((lastLine && !object()->continuation()) ||
+ prevOnLineExists() || onEndChain(endObject)))
+ includeLeftEdge = true;
+ }
+
+ }
+ }
+
+ setEdges(includeLeftEdge, includeRightEdge);
+
+ // Recur into our children.
+ for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
+ if (currChild->isInlineFlowBox()) {
+ InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
+ currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
+ }
+ }
+}
+
+int InlineFlowBox::placeBoxesHorizontally(int x)
+{
+ // Set our x position.
+ setXPos(x);
+
+ int startX = x;
+ x += borderLeft() + paddingLeft();
+
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (curr->object()->isText()) {
+ InlineTextBox* text = static_cast<InlineTextBox*>(curr);
+ text->setXPos(x);
+ x += curr->width();
+ }
+ else {
+ if (curr->object()->isPositioned()) {
+ if (curr->object()->parent()->style()->direction() == LTR)
+ curr->setXPos(x);
+ else {
+ // Our offset that we cache needs to be from the edge of the right border box and
+ // not the left border box. We have to subtract |x| from the width of the block
+ // (which can be obtained by walking up to the root line box).
+ InlineBox* root = this;
+ while (!root->isRootInlineBox())
+ root = root->parent();
+ curr->setXPos(root->object()->width()-x);
+ }
+ continue; // The positioned object has no effect on the width.
+ }
+ if (curr->object()->isInlineFlow()) {
+ InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
+ x += flow->marginLeft();
+ x = flow->placeBoxesHorizontally(x);
+ x += flow->marginRight();
+ }
+ else {
+ x += curr->object()->marginLeft();
+ curr->setXPos(x);
+ x += curr->width() + curr->object()->marginRight();
+ }
+ }
+ }
+
+ x += borderRight() + paddingRight();
+ setWidth(x-startX);
+ return x;
+}
+
+void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+{
+ int maxPositionTop = 0;
+ int maxPositionBottom = 0;
+ int maxAscent = 0;
+ int maxDescent = 0;
+
+ // Figure out if we're in strict mode.
+ RenderObject* curr = object();
+ while (curr && !curr->element())
+ curr = curr->container();
+ bool strictMode = (curr && curr->element()->getDocument()->inStrictMode());
+
+ computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+
+ if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom))
+ adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+
+ int maxHeight = maxAscent + maxDescent;
+ int topPosition = heightOfBlock;
+ int bottomPosition = heightOfBlock;
+ placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition);
+
+ setOverflowPositions(topPosition, bottomPosition);
+
+ // Shrink boxes with no text children in quirks and almost strict mode.
+ if (!strictMode)
+ shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
+
+ heightOfBlock += maxHeight;
+}
+
+void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
+ int maxPositionTop, int maxPositionBottom)
+{
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ // The computed lineheight needs to be extended for the
+ // positioned elements
+ // see tdehtmltests/rendering/html_align.html
+
+ if (curr->object()->isPositioned())
+ continue; // Positioned placeholders don't affect calculations.
+ if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) {
+ if (curr->yPos() == PositionTop) {
+ if (maxAscent + maxDescent < curr->height())
+ maxDescent = curr->height() - maxAscent;
+ }
+ else {
+ if (maxAscent + maxDescent < curr->height())
+ maxAscent = curr->height() - maxDescent;
+ }
+
+ if ( maxAscent + maxDescent >= kMax( maxPositionTop, maxPositionBottom ) )
+ break;
+ }
+
+ if (curr->isInlineFlowBox())
+ static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+ }
+}
+
+void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
+ int& maxAscent, int& maxDescent, bool strictMode)
+{
+ if (isRootInlineBox()) {
+ // Examine our root box.
+ setHeight(object()->lineHeight(m_firstLine));
+ bool isTableCell = object()->isTableCell();
+ if (isTableCell) {
+ RenderTableCell* tableCell = static_cast<RenderTableCell*>(object());
+ setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine));
+ }
+ else
+ setBaseline(object()->baselinePosition(m_firstLine));
+ if (hasTextChildren() || strictMode) {
+ int ascent = baseline();
+ int descent = height() - ascent;
+ if (maxAscent < ascent)
+ maxAscent = ascent;
+ if (maxDescent < descent)
+ maxDescent = descent;
+ }
+ }
+
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (curr->object()->isPositioned())
+ continue; // Positioned placeholders don't affect calculations.
+
+ curr->setHeight(curr->object()->lineHeight(m_firstLine));
+ curr->setBaseline(curr->object()->baselinePosition(m_firstLine));
+ curr->setYPos(curr->object()->verticalPositionHint(m_firstLine));
+ if (curr->yPos() == PositionTop) {
+ if (maxPositionTop < curr->height())
+ maxPositionTop = curr->height();
+ }
+ else if (curr->yPos() == PositionBottom) {
+ if (maxPositionBottom < curr->height())
+ maxPositionBottom = curr->height();
+ }
+ else if (curr->hasTextChildren() || strictMode) {
+ int ascent = curr->baseline() - curr->yPos();
+ int descent = curr->height() - ascent;
+ if (maxAscent < ascent)
+ maxAscent = ascent;
+ if (maxDescent < descent)
+ maxDescent = descent;
+ }
+
+ if (curr->isInlineFlowBox())
+ static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
+ }
+}
+
+void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
+ int& topPosition, int& bottomPosition)
+{
+ if (isRootInlineBox()) {
+ setYPos(y + maxAscent - baseline());// Place our root box.
+ // CSS2: 10.8.1 - line-height on the block level element specifies the *minimum*
+ // height of the generated line box
+ if (hasTextChildren() && maxHeight < object()->lineHeight(m_firstLine))
+ maxHeight = object()->lineHeight(m_firstLine);
+ }
+
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (curr->object()->isPositioned())
+ continue; // Positioned placeholders don't affect calculations.
+
+ // Adjust boxes to use their real box y/height and not the logical height (as dictated by
+ // line-height).
+ if (curr->isInlineFlowBox())
+ static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode,
+ topPosition, bottomPosition);
+
+ bool childAffectsTopBottomPos = true;
+
+ if (curr->yPos() == PositionTop)
+ curr->setYPos(y);
+ else if (curr->yPos() == PositionBottom)
+ curr->setYPos(y + maxHeight - curr->height());
+ else {
+ if (!strictMode && !curr->hasTextDescendant())
+ childAffectsTopBottomPos = false;
+ curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
+ }
+ int newY = curr->yPos();
+ int newHeight = curr->height();
+ int newBaseline = curr->baseline();
+ int overflowTop = 0;
+ int overflowBottom = 0;
+ if (curr->isInlineTextBox() || curr->isInlineFlowBox()) {
+ const TQFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );
+#ifdef APPLE_CHANGES
+ newBaseline = fm.ascent();
+ newY += curr->baseline() - newBaseline;
+ newHeight = newBaseline+fm.descent();
+#else
+ // only adjust if the leading delta is superior to the font's natural leading
+ if ( kAbs(fm.ascent() - curr->baseline()) > fm.leading()/2 ) {
+ int ascent = fm.ascent()+fm.leading()/2;
+ newBaseline = ascent;
+ newY += curr->baseline() - newBaseline;
+ newHeight = fm.lineSpacing();
+ }
+#endif
+ for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) {
+ overflowTop = kMin(overflowTop, shadow->y - shadow->blur);
+ overflowBottom = kMax(overflowBottom, shadow->y + shadow->blur);
+ }
+ if (curr->isInlineFlowBox()) {
+ newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
+ curr->object()->borderBottom() + curr->object()->paddingBottom();
+ newY -= curr->object()->borderTop() + curr->object()->paddingTop();
+ newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
+ }
+ } else {
+ newY += curr->object()->marginTop();
+ newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
+ overflowTop = curr->object()->overflowTop();
+ overflowBottom = curr->object()->overflowHeight() - newHeight;
+ }
+ curr->setYPos(newY);
+ curr->setHeight(newHeight);
+ curr->setBaseline(newBaseline);
+
+ if (childAffectsTopBottomPos) {
+ topPosition = kMin(topPosition, newY + overflowTop);
+ bottomPosition = kMax(bottomPosition, newY + newHeight + overflowBottom);
+ }
+ }
+
+ if (isRootInlineBox()) {
+ const TQFontMetrics &fm = object()->fontMetrics( m_firstLine );
+#ifdef APPLE_CHANGES
+ setHeight(fm.ascent()+fm.descent());
+ setYPos(yPos() + baseline() - fm.ascent());
+ setBaseline(fm.ascent());
+#else
+ if ( kAbs(fm.ascent() - baseline()) > fm.leading()/2 ) {
+ int ascent = fm.ascent()+fm.leading()/2;
+ setHeight(fm.lineSpacing());
+ setYPos(yPos() + baseline() - ascent);
+ setBaseline(ascent);
+ }
+#endif
+ if (hasTextDescendant() || strictMode) {
+ if (yPos() < topPosition)
+ topPosition = yPos();
+ if (yPos() + height() > bottomPosition)
+ bottomPosition = yPos() + height();
+ }
+ }
+}
+
+void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
+{
+ // First shrink our kids.
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (curr->object()->isPositioned())
+ continue; // Positioned placeholders don't affect calculations.
+
+ if (curr->isInlineFlowBox())
+ static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos);
+ }
+
+ // See if we have text children. If not, then we need to shrink ourselves to fit on the line.
+ if (!hasTextDescendant()) {
+ if (yPos() < topPos)
+ setYPos(topPos);
+ if (yPos() + height() > bottomPos)
+ setHeight(bottomPos - yPos());
+ if (baseline() > height())
+ setBaseline(height());
+ }
+}
+
+bool InlineFlowBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+ // Check children first.
+ for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
+ if (!curr->object()->layer() && curr->nodeAtPoint(i, x, y, tx, ty)) {
+ object()->setInnerNode(i);
+ return true;
+ }
+ }
+
+ // Now check ourselves.
+ TQRect rect(tx + m_x, ty + m_y, m_width, m_height);
+ if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+ object()->setInnerNode(i);
+ return true;
+ }
+
+ return false;
+}
+
+
+void InlineFlowBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+ bool intersectsDamageRect = true;
+ int xPos = tx + m_x - object()->maximalOutlineSize(i.phase);
+ int w = width() + 2 * object()->maximalOutlineSize(i.phase);
+ if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
+ intersectsDamageRect = false;
+
+ if (intersectsDamageRect) {
+ if (i.phase == PaintActionOutline) {
+ // Add ourselves to the paint info struct's list of inlines that need to paint their
+ // outlines.
+ if (object()->style()->visibility() == VISIBLE && object()->style()->outlineWidth() > 0 &&
+ !object()->isInlineContinuation() && !isRootInlineBox()) {
+ if (!i.outlineObjects)
+ i.outlineObjects = new TQValueList<RenderFlow*>;
+ i.outlineObjects->append(static_cast<RenderFlow*>(object()));
+ }
+ }
+ else {
+ // 1. Paint our background and border.
+ paintBackgroundAndBorder(i, tx, ty);
+
+ // 2. Paint our underline and overline.
+ paintDecorations(i, tx, ty, false);
+ }
+ }
+
+ // 3. Paint our children.
+ for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+ if (!curr->object()->layer())
+ curr->paint(i, tx, ty);
+ }
+
+ // 4. Paint our strike-through
+ if (intersectsDamageRect && i.phase != PaintActionOutline)
+ paintDecorations(i, tx, ty, true);
+}
+
+
+void InlineFlowBox::paintBackgrounds(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
+ int my, int mh, int _tx, int _ty, int w, int h)
+{
+ if (!bgLayer)
+ return;
+ paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h);
+ paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h);
+}
+
+void InlineFlowBox::paintBackground(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
+ int my, int mh, int _tx, int _ty, int w, int h)
+{
+ CachedImage* bg = bgLayer->backgroundImage();
+ bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) &&
+ !bg->isTransparent() && !bg->isErrorImage();
+ if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent())
+ object()->paintBackgroundExtended(p, c, bgLayer, my, mh, _tx, _ty, w, h, borderLeft(), borderRight(), paddingLeft(), paddingRight());
+ else {
+ // We have a background image that spans multiple lines.
+ // We need to adjust _tx and _ty by the width of all previous lines.
+ // Think of background painting on inlines as though you had one long line, a single continuous
+ // strip. Even though that strip has been broken up across multiple lines, you still paint it
+ // as though you had one single line. This means each line has to pick up the background where
+ // the previous line left off.
+ // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
+ // but it isn't even clear how this should work at all.
+ int xOffsetOnLine = 0;
+ for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+ xOffsetOnLine += curr->width();
+ int startX = _tx - xOffsetOnLine;
+ int totalWidth = xOffsetOnLine;
+ for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
+ totalWidth += curr->width();
+ p->save();
+ p->setClipRect(TQRect(_tx, _ty, width(), height()), TQPainter::CoordPainter);
+ object()->paintBackgroundExtended(p, c, bgLayer, my, mh, startX, _ty,
+ totalWidth, h, borderLeft(), borderRight(), paddingLeft(), paddingRight());
+ p->restore();
+ }
+}
+
+void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& pI, int _tx, int _ty)
+{
+ if (object()->style()->visibility() != VISIBLE || pI.phase != PaintActionForeground)
+ return;
+
+ // Move x/y to our coordinates.
+ _tx += m_x;
+ _ty += m_y;
+
+ int w = width();
+ int h = height();
+
+ int my = kMax(_ty, pI.r.y());
+ int mh;
+ if (_ty<pI.r.y())
+ mh= kMax(0,h-(pI.r.y()-_ty));
+ else
+ mh = kMin(pI.r.height(),h);
+
+ // You can use p::first-line to specify a background. If so, the root line boxes for
+ // a line may actually have to paint a background.
+ RenderStyle* styleToUse = object()->style(m_firstLine);
+ if ((!parent() && m_firstLine && styleToUse != object()->style()) ||
+ (parent() && object()->shouldPaintBackgroundOrBorder())) {
+ TQColor c = styleToUse->backgroundColor();
+ paintBackgrounds(pI.p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h);
+
+ // :first-line cannot be used to put borders on a line. Always paint borders with our
+ // non-first-line style.
+ if (parent() && object()->style()->hasBorder())
+ object()->paintBorder(pI.p, _tx, _ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge());
+ }
+}
+
+static bool shouldDrawDecoration(RenderObject* obj)
+{
+ bool shouldDraw = false;
+ for (RenderObject* curr = obj->firstChild();
+ curr; curr = curr->nextSibling()) {
+ if (curr->isInlineFlow()) {
+ shouldDraw = true;
+ break;
+ }
+ else if (curr->isText() && !curr->isBR() && (curr->style()->preserveWS() ||
+ !curr->element() || !curr->element()->containsOnlyWhitespace())) {
+ shouldDraw = true;
+ break;
+ }
+ }
+ return shouldDraw;
+}
+
+void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& pI, int _tx, int _ty, bool paintedChildren)
+{
+ // Now paint our text decorations. We only do this if we aren't in quirks mode (i.e., in
+ // almost-strict mode or strict mode).
+ if (object()->style()->htmlHacks() || object()->style()->visibility() != VISIBLE)
+ return;
+
+ _tx += m_x;
+ _ty += m_y;
+ RenderStyle* styleToUse = object()->style(m_firstLine);
+ int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
+ if (deco != TDNONE &&
+ ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
+ shouldDrawDecoration(object())) {
+ // We must have child boxes and have decorations defined.
+ _tx += borderLeft() + paddingLeft();
+ int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
+ if ( !w )
+ return;
+ const TQFontMetrics &fm = object()->fontMetrics( m_firstLine );
+ // thick lines on small fonts look ugly
+ int thickness = fm.height() > 20 ? fm.lineWidth() : 1;
+ TQColor underline, overline, linethrough;
+ underline = overline = linethrough = styleToUse->color();
+ if (!parent())
+ object()->getTextDecorationColors(deco, underline, overline, linethrough);
+
+ if (styleToUse->font() != pI.p->font())
+ pI.p->setFont(styleToUse->font());
+
+ if (deco & UNDERLINE && !paintedChildren) {
+ int underlineOffset = ( fm.height() + m_baseline ) / 2;
+ if (underlineOffset <= m_baseline) underlineOffset = m_baseline+1;
+
+ pI.p->fillRect(_tx, _ty + underlineOffset, w, thickness, underline );
+ }
+ if (deco & OVERLINE && !paintedChildren) {
+ pI.p->fillRect(_tx, _ty, w, thickness, overline );
+ }
+ if (deco & LINE_THROUGH && paintedChildren) {
+ pI.p->fillRect(_tx, _ty + 2*m_baseline/3, w, thickness, linethrough );
+ }
+ }
+}
+
+bool InlineFlowBox::canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth)
+{
+ for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
+ if (!box->canAccommodateEllipsisBox(ltr, blockEdge, ellipsisWidth))
+ return false;
+ }
+ return true;
+}
+
+int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+ int result = -1;
+ for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
+ int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+ if (currResult != -1 && result == -1)
+ result = currResult;
+ }
+ return result;
+}
+
+void InlineFlowBox::clearTruncation()
+{
+ for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
+ box->clearTruncation();
+}
+
+void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty)
+{
+ TQPainter* p = i.p;
+ RenderStyle* _style = m_firstLine ? m_object->style(true) : m_object->style();
+ if (_style->font() != p->font())
+ p->setFont(_style->font());
+
+ const Font* font = &_style->htmlFont();
+ TQColor textColor = _style->color();
+ if (textColor != p->pen().color())
+ p->setPen(textColor);
+ /*
+ bool setShadow = false;
+ if (_style->textShadow()) {
+ p->setShadow(_style->textShadow()->x, _style->textShadow()->y,
+ _style->textShadow()->blur, _style->textShadow()->color);
+ setShadow = true;
+ }*/
+
+ const DOMString& str = m_str.string();
+ font->drawText(p, m_x + _tx,
+ m_y + _ty + m_baseline,
+ (str.implementation())->s,
+ str.length(), 0, str.length(),
+ 0,
+ TQPainter::LTR, _style->visuallyOrdered());
+
+ /*
+ if (setShadow)
+ p->clearShadow();
+ */
+
+ if (m_markupBox) {
+ // Paint the markup box
+ _tx += m_x + m_width - m_markupBox->xPos();
+ _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+ m_markupBox->object()->paint(i, _tx, _ty);
+ }
+}
+
+bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty)
+{
+ // Hit test the markup box.
+ if (m_markupBox) {
+ _tx += m_x + m_width - m_markupBox->xPos();
+ _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+ if (m_markupBox->nodeAtPoint(info, _x, _y, _tx, _ty)) {
+ object()->setInnerNode(info);
+ return true;
+ }
+ }
+
+ TQRect rect(_tx + m_x, _ty + m_y, m_width, m_height);
+ if (object()->style()->visibility() == VISIBLE && rect.contains(_x, _y)) {
+ object()->setInnerNode(info);
+ return true;
+ }
+ return false;
+}
+
+void RootInlineBox::detach(RenderArena* arena)
+{
+ detachEllipsisBox(arena);
+ InlineFlowBox::detach(arena);
+}
+
+void RootInlineBox::detachEllipsisBox(RenderArena* arena)
+{
+ if (m_ellipsisBox) {
+ m_ellipsisBox->detach(arena);
+ m_ellipsisBox = 0;
+ }
+}
+
+void RootInlineBox::clearTruncation()
+{
+ if (m_ellipsisBox) {
+ detachEllipsisBox(m_object->renderArena());
+ InlineFlowBox::clearTruncation();
+ }
+}
+
+bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
+{
+ // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
+ int delta = ltr ? lineBoxEdge - blockEdge : blockEdge - lineBoxEdge;
+ if (width() - delta < ellipsisWidth)
+ return false;
+
+ // Next iterate over all the line boxes on the line. If we find a replaced element that intersects
+ // then we refuse to accommodate the ellipsis. Otherwise we're ok.
+ return InlineFlowBox::canAccommodateEllipsisBox(ltr, blockEdge, ellipsisWidth);
+}
+
+void RootInlineBox::placeEllipsis(const DOMString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox)
+{
+ // Create an ellipsis box.
+ m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
+ ellipsisWidth - (markupBox ? markupBox->width() : 0),
+ yPos(), height(), baseline(), !prevRootBox(),
+ markupBox);
+
+ if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
+ m_ellipsisBox->m_x = xPos() + width();
+ return;
+ }
+
+ // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL)
+ // of that glyph. Mark all of the objects that intersect the ellipsis box as not painting (as being
+ // truncated).
+ bool foundBox = false;
+ m_ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+}
+
+int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+ int result = InlineFlowBox::placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+ if (result == -1)
+ result = ltr ? blockEdge - ellipsisWidth : blockEdge;
+ return result;
+}
+
+void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const
+{
+ if (m_ellipsisBox)
+ m_ellipsisBox->paint(i, _tx, _ty);
+}
+
+void RootInlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+ InlineFlowBox::paint(i, tx, ty);
+ paintEllipsisBox(i, tx, ty);
+}
+
+bool RootInlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
+{
+ if (m_ellipsisBox && object()->style()->visibility() == VISIBLE) {
+ if (m_ellipsisBox->nodeAtPoint(i, x, y, tx, ty)) {
+ object()->setInnerNode(i);
+ return true;
+ }
+ }
+ return InlineFlowBox::nodeAtPoint(i, x, y, tx, ty);
+}
+
diff --git a/tdehtml/rendering/render_line.h b/tdehtml/rendering/render_line.h
new file mode 100644
index 000000000..3dc066e10
--- /dev/null
+++ b/tdehtml/rendering/render_line.h
@@ -0,0 +1,310 @@
+/*
+ * This file is part of the line box implementation for KDE.
+ *
+ * Copyright (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 RENDER_LINE_H
+#define RENDER_LINE_H
+
+namespace tdehtml {
+
+class EllipsisBox;
+class InlineFlowBox;
+class RootInlineBox;
+
+// InlineBox represents a rectangle that occurs on a line. It corresponds to
+// some RenderObject (i.e., it represents a portion of that RenderObject).
+class InlineBox
+{
+public:
+ InlineBox(RenderObject* obj)
+ :m_object(obj), m_x(0), m_width(0), m_y(0), m_height(0), m_baseline(0),
+ m_firstLine(false), m_constructed(false)
+ {
+ m_next = 0;
+ m_prev = 0;
+ m_parent = 0;
+ }
+
+ virtual ~InlineBox() {}
+
+ void detach(RenderArena* renderArena);
+
+ virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+ virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
+ // Overloaded new operator.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw();
+
+public:
+ virtual bool isInlineBox() const { return false; }
+ virtual bool isInlineFlowBox() const { return false; }
+ virtual bool isContainer() const { return false; }
+ virtual bool isInlineTextBox() const { return false; }
+ virtual bool isRootInlineBox() const { return false; }
+
+ bool isConstructed() const { return m_constructed; }
+ virtual void setConstructed() {
+ m_constructed = true;
+ if (m_next)
+ m_next->setConstructed();
+ }
+
+ void setFirstLineStyleBit(bool f) { m_firstLine = f; }
+
+ InlineBox* nextOnLine() { return m_next; }
+ InlineBox* prevOnLine() { return m_prev; }
+ RenderObject* object() const { return m_object; }
+
+ InlineFlowBox* parent() { return m_parent; }
+ void setParent(InlineFlowBox* par) { m_parent = par; }
+
+ RootInlineBox* root();
+
+ void setWidth(short w) { m_width = w; }
+ short width() const { return m_width; }
+
+ void setXPos(short x) { m_x = x; }
+ short xPos() const { return m_x; }
+
+ void setYPos(int y) { m_y = y; }
+ int yPos() const { return m_y; }
+
+ void setHeight(int h) { m_height = h; }
+ int height() const { return m_height; }
+
+ void setBaseline(int b) { m_baseline = b; }
+ int baseline() const { return m_baseline; }
+
+ virtual bool hasTextChildren() const { return true; }
+ virtual bool hasTextDescendant() const { return true; }
+
+ virtual int topOverflow() const { return yPos(); }
+ virtual int bottomOverflow() const { return yPos()+height(); }
+
+ virtual long minOffset() const { return 0; }
+ virtual long maxOffset() const { return 0; }
+
+ virtual void clearTruncation() {};
+
+ virtual bool canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth);
+ virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+
+public: // FIXME: Would like to make this protected, but methods are accessing these
+ // members over in the part.
+ RenderObject* m_object;
+
+ short m_x;
+ short m_width;
+ int m_y;
+ int m_height;
+ int m_baseline;
+
+ bool m_firstLine : 1;
+ bool m_constructed : 1;
+
+ InlineBox* m_next; // The next element on the same line as us.
+ InlineBox* m_prev; // The previous element on the same line as us.
+
+ InlineFlowBox* m_parent; // The box that contains us.
+};
+
+class InlineRunBox : public InlineBox
+{
+public:
+ InlineRunBox(RenderObject* obj)
+ :InlineBox(obj)
+ {
+ m_prevLine = 0;
+ m_nextLine = 0;
+ }
+
+ InlineRunBox* prevLineBox() { return m_prevLine; }
+ InlineRunBox* nextLineBox() { return m_nextLine; }
+ void setNextLineBox(InlineRunBox* n) { m_nextLine = n; }
+ void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; }
+
+ virtual void paintBackgroundAndBorder(RenderObject::PaintInfo&, int /*_tx*/, int /*_ty*/) {}
+ virtual void paintDecorations(RenderObject::PaintInfo&, int /*_tx*/, int /*_ty*/, bool /*paintedChildren*/ = false) {}
+
+protected:
+ InlineRunBox* m_prevLine; // The previous box that also uses our RenderObject
+ InlineRunBox* m_nextLine; // The next box that also uses our RenderObject
+};
+
+class InlineFlowBox : public InlineRunBox
+{
+public:
+ InlineFlowBox(RenderObject* obj)
+ :InlineRunBox(obj)
+ {
+ m_firstChild = 0;
+ m_lastChild = 0;
+ m_includeLeftEdge = m_includeRightEdge = false;
+ m_hasTextChildren = false;
+ m_hasTextDescendant = false;
+ m_afterPageBreak = false;
+ }
+
+ ~InlineFlowBox();
+
+ virtual bool isInlineFlowBox() const { return true; }
+
+ InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
+ InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
+
+ InlineBox* firstChild() const { return m_firstChild; }
+ InlineBox* lastChild() const { return m_lastChild; }
+
+ virtual void setConstructed() {
+ InlineBox::setConstructed();
+ if (m_firstChild)
+ m_firstChild->setConstructed();
+ }
+ void addToLine(InlineBox* child) {
+ if (!m_firstChild)
+ m_firstChild = m_lastChild = child;
+ else {
+ m_lastChild->m_next = child;
+ child->m_prev = m_lastChild;
+ m_lastChild = child;
+ }
+ child->setFirstLineStyleBit(m_firstLine);
+ child->setParent(this);
+ if (!m_hasTextChildren && child->isInlineTextBox()) {
+ m_hasTextDescendant = m_hasTextChildren = true;
+ for (InlineFlowBox* p = m_parent; p && !p->hasTextDescendant(); p = p->parent())
+ p->m_hasTextDescendant = true;
+ }
+ }
+
+ virtual void clearTruncation();
+
+ void removeFromLine(InlineBox* child);
+ virtual void paintBackgroundAndBorder(RenderObject::PaintInfo&, int _tx, int _ty);
+ void paintBackgrounds(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
+ int my, int mh, int _tx, int _ty, int w, int h);
+ void paintBackground(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
+ int my, int mh, int _tx, int _ty, int w, int h);
+ virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+ virtual void paintDecorations(RenderObject::PaintInfo&, int _tx, int _ty, bool paintedChildren = false);
+ virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
+ int marginBorderPaddingLeft() const;
+ int marginBorderPaddingRight() const;
+ int marginLeft() const;
+ int marginRight( )const;
+ int borderLeft() const { if (includeLeftEdge()) return object()->borderLeft(); return 0; }
+ int borderRight() const { if (includeRightEdge()) return object()->borderRight(); return 0; }
+ int paddingLeft() const { if (includeLeftEdge()) return object()->paddingLeft(); return 0; }
+ int paddingRight() const { if (includeRightEdge()) return object()->paddingRight(); return 0; }
+
+ bool includeLeftEdge() const { return m_includeLeftEdge; }
+ bool includeRightEdge() const { return m_includeRightEdge; }
+ void setEdges(bool includeLeft, bool includeRight) {
+ m_includeLeftEdge = includeLeft;
+ m_includeRightEdge = includeRight;
+ }
+ virtual bool hasTextChildren() const { return m_hasTextChildren; }
+ bool hasTextDescendant() const { return m_hasTextDescendant; }
+
+ // Helper functions used during line construction and placement.
+ void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
+ int getFlowSpacingWidth() const;
+ bool nextOnLineExists();
+ bool prevOnLineExists();
+ bool onEndChain(RenderObject* endObject);
+ int placeBoxesHorizontally(int x);
+ void verticallyAlignBoxes(int& heightOfBlock);
+ void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
+ int& maxAscent, int& maxDescent, bool strictMode);
+ void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
+ int maxPositionTop, int maxPositionBottom);
+ void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
+ int& topPosition, int& bottomPosition);
+ void shrinkBoxesWithNoTextChildren(int topPosition, int bottomPosition);
+
+ virtual void setOverflowPositions(int /*top*/, int /*bottom*/) {}
+
+ void setAfterPageBreak(bool b = true) { m_afterPageBreak = b; }
+ bool afterPageBreak() const { return m_afterPageBreak; }
+
+ virtual bool canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth);
+ virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+
+protected:
+ InlineBox* m_firstChild;
+ InlineBox* m_lastChild;
+ bool m_includeLeftEdge : 1;
+ bool m_includeRightEdge : 1;
+ bool m_hasTextChildren : 1;
+ bool m_hasTextDescendant : 1;
+ bool m_afterPageBreak : 1;
+};
+
+class RootInlineBox : public InlineFlowBox
+{
+public:
+ RootInlineBox(RenderObject* obj) : InlineFlowBox(obj), m_ellipsisBox(0)
+ {
+ m_topOverflow = m_bottomOverflow = 0;
+ }
+
+ virtual void detach(RenderArena* renderArena);
+ void detachEllipsisBox(RenderArena* renderArena);
+
+ RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); }
+ RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); }
+
+ virtual bool isRootInlineBox() const { return true; }
+ virtual int topOverflow() const { return m_topOverflow; }
+ virtual int bottomOverflow() const { return m_bottomOverflow; }
+ virtual void setOverflowPositions(int top, int bottom) { m_topOverflow = top; m_bottomOverflow = bottom; }
+
+ bool canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
+ void placeEllipsis(const DOM::DOMString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox = 0);
+ virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+
+ EllipsisBox* ellipsisBox() const { return m_ellipsisBox; }
+ void paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const;
+ bool hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
+
+ virtual void clearTruncation();
+
+ virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
+ virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
+
+protected:
+ int m_topOverflow;
+ int m_bottomOverflow;
+
+ // An inline text box that represents our text truncation string.
+ EllipsisBox* m_ellipsisBox;
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_list.cpp b/tdehtml/rendering/render_list.cpp
new file mode 100644
index 000000000..08ee1a88b
--- /dev/null
+++ b/tdehtml/rendering/render_list.cpp
@@ -0,0 +1,586 @@
+/**
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000-2002 Dirk Mueller (mueller@kde.org)
+ * (C) 2003 Apple Computer, Inc.
+ * (C) 2004-2005 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.
+ *
+ */
+
+#include "rendering/render_list.h"
+#include "rendering/render_canvas.h"
+#include "rendering/enumerate.h"
+#include "rendering/counter_tree.h"
+#include "html/html_listimpl.h"
+#include "misc/helper.h"
+#include "misc/htmltags.h"
+#include "misc/loader.h"
+#include "xml/dom_docimpl.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <tqvaluelist.h>
+
+//#define BOX_DEBUG
+
+using namespace tdehtml;
+using namespace Enumerate;
+
+const int cMarkerPadding = 7;
+
+// -------------------------------------------------------------------------
+
+RenderListItem::RenderListItem(DOM::NodeImpl* node)
+ : RenderBlock(node)
+{
+ // init RenderObject attributes
+ setInline(false); // our object is not Inline
+
+ predefVal = -1;
+ m_marker = 0;
+ m_counter = 0;
+ m_insideList = false;
+ m_deleteMarker = false;
+}
+
+void RenderListItem::setStyle(RenderStyle *_style)
+{
+ RenderBlock::setStyle(_style);
+
+ RenderStyle *newStyle = new RenderStyle();
+ newStyle->ref();
+
+ newStyle->inheritFrom(style());
+
+ if(!m_marker && style()->listStyleType() != LNONE) {
+ m_marker = new (renderArena()) RenderListMarker(element());
+ m_marker->setIsAnonymous( true );
+ m_marker->setStyle(newStyle);
+ m_marker->setListItem( this );
+ m_deleteMarker = true;
+ } else if ( m_marker && style()->listStyleType() == LNONE) {
+ m_marker->detach();
+ m_marker = 0;
+ }
+ else if ( m_marker ) {
+ m_marker->setStyle(newStyle);
+ }
+
+ newStyle->deref();
+}
+
+void RenderListItem::detach()
+{
+ if ( m_marker && m_deleteMarker )
+ m_marker->detach();
+ RenderBlock::detach();
+}
+
+static RenderObject* getParentOfFirstLineBox(RenderObject* curr, RenderObject* marker)
+{
+ RenderObject* firstChild = curr->firstChild();
+ if (!firstChild)
+ return 0;
+
+ for (RenderObject* currChild = firstChild;
+ currChild; currChild = currChild->nextSibling()) {
+ if (currChild == marker)
+ continue;
+
+ if (currChild->isInline())
+ return curr;
+
+ if (currChild->isFloating() || currChild->isPositioned())
+ continue;
+
+ if (currChild->isTable() || !currChild->isRenderBlock())
+ break;
+
+ if (currChild->style()->htmlHacks() && currChild->element() &&
+ (currChild->element()->id() == ID_UL || currChild->element()->id() == ID_OL))
+ break;
+
+ RenderObject* lineBox = getParentOfFirstLineBox(currChild, marker);
+ if (lineBox)
+ return lineBox;
+ }
+
+ return 0;
+}
+
+
+void RenderListItem::updateMarkerLocation()
+{
+ // Sanity check the location of our marker.
+ if (m_marker) {
+ RenderObject* markerPar = m_marker->parent();
+ RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
+ if (!lineBoxParent) {
+ // If the marker is currently contained inside an anonymous box,
+ // then we are the only item in that anonymous box (since no line box
+ // parent was found). It's ok to just leave the marker where it is
+ // in this case.
+ if (markerPar && markerPar->isAnonymousBlock())
+ lineBoxParent = markerPar;
+ else
+ lineBoxParent = this;
+ }
+ if (markerPar != lineBoxParent)
+ {
+ if (markerPar)
+ markerPar->removeChild(m_marker);
+ if (!lineBoxParent)
+ lineBoxParent = this;
+ lineBoxParent->addChild(m_marker, lineBoxParent->firstChild());
+ m_deleteMarker = false;
+ if (!m_marker->minMaxKnown())
+ m_marker->calcMinMaxWidth();
+ recalcMinMaxWidths();
+ }
+ }
+}
+
+void RenderListItem::calcMinMaxWidth()
+{
+ // Make sure our marker is in the correct location.
+ updateMarkerLocation();
+ if (!minMaxKnown())
+ RenderBlock::calcMinMaxWidth();
+}
+/*
+short RenderListItem::marginLeft() const
+{
+ if (m_insideList)
+ return RenderBlock::marginLeft();
+ else
+ return kMax(m_marker->markerWidth(), RenderBlock::marginLeft());
+}
+
+short RenderListItem::marginRight() const
+{
+ return RenderBlock::marginRight();
+}*/
+
+void RenderListItem::layout( )
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ updateMarkerLocation();
+ RenderBlock::layout();
+}
+
+// -----------------------------------------------------------
+
+RenderListMarker::RenderListMarker(DOM::NodeImpl* node)
+ : RenderBox(node), m_listImage(0), m_markerWidth(0)
+{
+ // init RenderObject attributes
+ setInline(true); // our object is Inline
+ setReplaced(true); // pretend to be replaced
+ // val = -1;
+ // m_listImage = 0;
+}
+
+RenderListMarker::~RenderListMarker()
+{
+ if(m_listImage)
+ m_listImage->deref(this);
+ if (m_listItem)
+ m_listItem->resetListMarker();
+}
+
+void RenderListMarker::setStyle(RenderStyle *s)
+{
+ if ( s && style() && s->listStylePosition() != style()->listStylePosition() )
+ setNeedsLayoutAndMinMaxRecalc();
+
+ RenderBox::setStyle(s);
+
+ if ( m_listImage != style()->listStyleImage() ) {
+ if(m_listImage) m_listImage->deref(this);
+ m_listImage = style()->listStyleImage();
+ if(m_listImage) m_listImage->ref(this);
+ }
+}
+
+
+void RenderListMarker::paint(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ if (paintInfo.phase != PaintActionForeground)
+ return;
+
+ if (style()->visibility() != VISIBLE) return;
+
+ _tx += m_x;
+ _ty += m_y;
+
+ if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()))
+ return;
+
+ if(shouldPaintBackgroundOrBorder())
+ paintBoxDecorations(paintInfo, _tx, _ty);
+
+ TQPainter* p = paintInfo.p;
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << nodeName().string() << "(ListMarker)::paintObject(" << _tx << ", " << _ty << ")" << endl;
+#endif
+ p->setFont(style()->font());
+ const TQFontMetrics fm = p->fontMetrics();
+
+
+ // The marker needs to adjust its tx, for the case where it's an outside marker.
+ RenderObject* listItem = 0;
+ int leftLineOffset = 0;
+ int rightLineOffset = 0;
+ if (!listPositionInside()) {
+ listItem = this;
+ int yOffset = 0;
+ int xOffset = 0;
+ while (listItem && listItem != m_listItem) {
+ yOffset += listItem->yPos();
+ xOffset += listItem->xPos();
+ listItem = listItem->parent();
+ }
+
+ // Now that we have our xoffset within the listbox, we need to adjust ourselves by the delta
+ // between our current xoffset and our desired position (which is just outside the border box
+ // of the list item).
+ if (style()->direction() == LTR) {
+ leftLineOffset = m_listItem->leftRelOffset(yOffset, m_listItem->leftOffset(yOffset));
+ _tx -= (xOffset - leftLineOffset) + m_listItem->paddingLeft() + m_listItem->borderLeft();
+ }
+ else {
+ rightLineOffset = m_listItem->rightRelOffset(yOffset, m_listItem->rightOffset(yOffset));
+ _tx += (rightLineOffset-xOffset) + m_listItem->paddingRight() + m_listItem->borderRight();
+ }
+ }
+
+ int offset = fm.ascent()*2/3;
+ bool haveImage = m_listImage && !m_listImage->isErrorImage();
+ if (haveImage)
+ offset = m_listImage->pixmap().width();
+
+ int xoff = 0;
+ int yoff = fm.ascent() - offset;
+
+ int bulletWidth = offset/2;
+ if (offset%2)
+ bulletWidth++;
+ if (!listPositionInside()) {
+ if (listItem && listItem->style()->direction() == LTR)
+ xoff = -cMarkerPadding - offset;
+ else
+ xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth));
+ }
+ else if (style()->direction() == RTL)
+ xoff += haveImage ? cMarkerPadding : (m_width - bulletWidth);
+
+ if ( m_listImage && !m_listImage->isErrorImage()) {
+ p->drawPixmap( TQPoint( _tx + xoff, _ty ), m_listImage->pixmap());
+ return;
+ }
+
+#ifdef BOX_DEBUG
+ p->setPen( Qt::red );
+ p->drawRect( _tx + xoff, _ty + yoff, offset, offset );
+#endif
+
+ const TQColor color( style()->color() );
+ p->setPen( color );
+
+ switch(style()->listStyleType()) {
+ case LDISC:
+ p->setBrush( color );
+ p->drawEllipse( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
+ return;
+ case LCIRCLE:
+ p->setBrush( Qt::NoBrush );
+ p->drawEllipse( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
+ return;
+ case LSQUARE:
+ p->setBrush( color );
+ p->drawRect( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
+ return;
+ case LBOX:
+ p->setBrush( Qt::NoBrush );
+ p->drawRect( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
+ return;
+ case LDIAMOND: {
+ static TQPointArray diamond(4);
+ int x = _tx + xoff;
+ int y = _ty + (3 * yoff)/2 - 1;
+ int s = (offset>>2)+1;
+ diamond[0] = TQPoint(x+s, y);
+ diamond[1] = TQPoint(x+2*s, y+s);
+ diamond[2] = TQPoint(x+s, y+2*s);
+ diamond[3] = TQPoint(x, y+s);
+ p->setBrush( color );
+ p->drawConvexPolygon( diamond, 0, 4 );
+ return;
+ }
+ case LNONE:
+ return;
+ default:
+ if (!m_item.isEmpty()) {
+ if(listPositionInside()) {
+ if( style()->direction() == LTR) {
+ p->drawText(_tx, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
+ p->drawText(_tx + fm.width(m_item), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip,
+ TQString::fromLatin1(". "));
+ }
+ else {
+ const TQString& punct(TQString::fromLatin1(" ."));
+ p->drawText(_tx, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, punct);
+ p->drawText(_tx + fm.width(punct), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
+ }
+ } else {
+ if (style()->direction() == LTR) {
+ const TQString& punct(TQString::fromLatin1(". "));
+ p->drawText(_tx-offset/2, _ty, 0, 0, Qt::AlignRight|TQt::DontClip, punct);
+ p->drawText(_tx-offset/2-fm.width(punct), _ty, 0, 0, Qt::AlignRight|TQt::DontClip, m_item);
+ }
+ else {
+ const TQString& punct(TQString::fromLatin1(" ."));
+ p->drawText(_tx+offset/2, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, punct);
+ p->drawText(_tx+offset/2+fm.width(punct), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
+ }
+ }
+ }
+ }
+}
+
+void RenderListMarker::layout()
+{
+ KHTMLAssert( needsLayout() );
+
+ if ( !minMaxKnown() )
+ calcMinMaxWidth();
+
+ setNeedsLayout(false);
+}
+
+void RenderListMarker::setPixmap( const TQPixmap &p, const TQRect& r, CachedImage *o)
+{
+ if(o != m_listImage) {
+ RenderBox::setPixmap(p, r, o);
+ return;
+ }
+
+ if(m_width != m_listImage->pixmap_size().width() || m_height != m_listImage->pixmap_size().height())
+ setNeedsLayoutAndMinMaxRecalc();
+ else
+ repaintRectangle(0, 0, m_width, m_height);
+}
+
+void RenderListMarker::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ m_markerWidth = m_width = 0;
+
+ if(m_listImage && !m_listImage->isErrorImage()) {
+ m_markerWidth = m_listImage->pixmap().width() + cMarkerPadding;
+ if (listPositionInside())
+ m_width = m_markerWidth;
+ m_height = m_listImage->pixmap().height();
+ m_minWidth = m_maxWidth = m_width;
+ setMinMaxKnown();
+ return;
+ }
+
+ const TQFontMetrics &fm = style()->fontMetrics();
+ m_height = fm.ascent();
+
+ // Skip uncounted elements
+ switch(style()->listStyleType()) {
+ // Glyphs:
+ case LDISC:
+ case LCIRCLE:
+ case LSQUARE:
+ case LBOX:
+ case LDIAMOND:
+ m_markerWidth = fm.ascent();
+ goto end;
+ default:
+ break;
+ }
+
+ { // variable scope
+ CounterNode *counter = m_listItem->m_counter;
+ if (!counter) {
+ counter = m_listItem->getCounter("list-item", true);
+ counter->setRenderer(this);
+ m_listItem->m_counter = counter;
+ }
+
+
+ assert(counter);
+ int value = counter->count();
+ if (counter->isReset()) value = counter->value();
+ int total = value;
+ if (counter->parent()) total = counter->parent()->total();
+
+ switch(style()->listStyleType())
+ {
+// Numeric:
+ case LDECIMAL:
+ m_item.setNum ( value );
+ break;
+ case DECIMAL_LEADING_ZERO: {
+ int decimals = 2;
+ int t = total/100;
+ while (t>0) {
+ t = t/10;
+ decimals++;
+ }
+ decimals = kMax(decimals, 2);
+ TQString num = TQString::number(value);
+ m_item.fill('0',decimals-num.length());
+ m_item.append(num);
+ break;
+ }
+ case ARABIC_INDIC:
+ m_item = toArabicIndic( value );
+ break;
+ case LAO:
+ m_item = toLao( value );
+ break;
+ case PERSIAN:
+ case URDU:
+ m_item = toPersianUrdu( value );
+ break;
+ case THAI:
+ m_item = toThai( value );
+ break;
+ case TIBETAN:
+ m_item = toTibetan( value );
+ break;
+// Algoritmic:
+ case LOWER_ROMAN:
+ m_item = toRoman( value, false );
+ break;
+ case UPPER_ROMAN:
+ m_item = toRoman( value, true );
+ break;
+ case HEBREW:
+ m_item = toHebrew( value );
+ break;
+ case ARMENIAN:
+ m_item = toArmenian( value );
+ break;
+ case GEORGIAN:
+ m_item = toGeorgian( value );
+ break;
+// Alphabetic:
+ case LOWER_ALPHA:
+ case LOWER_LATIN:
+ m_item = toLowerLatin( value );
+ break;
+ case UPPER_ALPHA:
+ case UPPER_LATIN:
+ m_item = toUpperLatin( value );
+ break;
+ case LOWER_GREEK:
+ m_item = toLowerGreek( value );
+ break;
+ case UPPER_GREEK:
+ m_item = toUpperGreek( value );
+ break;
+ case HIRAGANA:
+ m_item = toHiragana( value );
+ break;
+ case HIRAGANA_IROHA:
+ m_item = toHiraganaIroha( value );
+ break;
+ case KATAKANA:
+ m_item = toKatakana( value );
+ break;
+ case KATAKANA_IROHA:
+ m_item = toKatakanaIroha( value );
+ break;
+// Ideographic:
+ case JAPANESE_FORMAL:
+ m_item = toJapaneseFormal( value );
+ break;
+ case JAPANESE_INFORMAL:
+ m_item = toJapaneseInformal( value );
+ break;
+ case SIMP_CHINESE_FORMAL:
+ m_item = toSimpChineseFormal( value );
+ break;
+ case SIMP_CHINESE_INFORMAL:
+ m_item = toSimpChineseInformal( value );
+ break;
+ case TRAD_CHINESE_FORMAL:
+ m_item = toTradChineseFormal( value );
+ break;
+ case CJK_IDEOGRAPHIC:
+ // CSS 3 List says treat as trad-chinese-informal
+ case TRAD_CHINESE_INFORMAL:
+ m_item = toTradChineseInformal( value );
+ break;
+// special:
+ case LNONE:
+ break;
+ default:
+ KHTMLAssert(false);
+ }
+ m_markerWidth = fm.width(m_item) + fm.width(TQString::fromLatin1(". "));
+ }
+
+end:
+ if(listPositionInside())
+ m_width = m_markerWidth;
+
+ m_minWidth = m_width;
+ m_maxWidth = m_width;
+
+ setMinMaxKnown();
+}
+
+short RenderListMarker::lineHeight(bool /*b*/) const
+{
+ return height();
+}
+
+short RenderListMarker::baselinePosition(bool /*b*/) const
+{
+ return height();
+}
+
+void RenderListMarker::calcWidth()
+{
+ RenderBox::calcWidth();
+}
+
+/*
+int CounterListItem::recount() const
+{
+ static_cast<RenderListItem*>(m_renderer)->m_marker->setNeedsLayoutAndMinMaxRecalc();
+}
+
+void CounterListItem::setSelfDirty()
+{
+
+}*/
+
+
+#undef BOX_DEBUG
diff --git a/tdehtml/rendering/render_list.h b/tdehtml/rendering/render_list.h
new file mode 100644
index 000000000..9797d5114
--- /dev/null
+++ b/tdehtml/rendering/render_list.h
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (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.
+ *
+ */
+#ifndef RENDER_LIST_H
+#define RENDER_LIST_H
+
+#include "rendering/render_block.h"
+
+// ### list-style-position, list-style-image is still missing
+
+namespace DOM
+{
+ class DocumentImpl;
+}
+
+namespace tdehtml
+{
+
+class RenderListItem;
+class RenderListMarker;
+class CounterNode;
+
+// -----------------------------------------------------------------------------
+
+class RenderListItem : public RenderBlock
+{
+ friend class RenderListMarker;
+// friend class CounterListItem;
+
+public:
+ RenderListItem(DOM::NodeImpl*);
+
+ virtual const char *renderName() const { return "RenderListItem"; }
+
+ virtual void setStyle(RenderStyle *style);
+
+ virtual bool isListItem() const { return true; }
+
+ void setValue( long v ) { predefVal = v; }
+
+ virtual void layout( );
+ virtual void detach( );
+ virtual void calcMinMaxWidth();
+ //virtual short marginLeft() const;
+ //virtual short marginRight() const;
+
+ void setInsideList(bool b ) { m_insideList = b; }
+
+protected:
+
+ void updateMarkerLocation();
+ void resetListMarker() { m_marker = 0; }
+
+ RenderListMarker *m_marker;
+ CounterNode *m_counter;
+ signed long predefVal : 30;
+ bool m_insideList : 1;
+ bool m_deleteMarker: 1;
+};
+
+// -----------------------------------------------------------------------------
+
+class RenderListMarker : public RenderBox
+{
+public:
+ RenderListMarker(DOM::NodeImpl* node);
+ ~RenderListMarker();
+
+ virtual void setStyle(RenderStyle *style);
+
+ virtual const char *renderName() const { return "RenderListMarker"; }
+ // so the marker gets to layout itself. Only needed for
+ // list-style-position: inside
+
+ virtual void paint(PaintInfo& i, int xoff, int yoff);
+ virtual void layout( );
+ virtual void calcMinMaxWidth();
+
+ virtual short lineHeight( bool firstLine ) const;
+ virtual short baselinePosition( bool firstLine ) const;
+
+ virtual void setPixmap( const TQPixmap &, const TQRect&, CachedImage *);
+
+ virtual void calcWidth();
+
+ virtual bool isListMarker() const { return true; }
+
+ virtual short markerWidth() const { return m_markerWidth; }
+
+ RenderListItem* listItem() const { return m_listItem; }
+ void setListItem(RenderListItem* listItem) { m_listItem = listItem; }
+
+ bool listPositionInside() const
+ { return !m_listItem->m_insideList || style()->listStylePosition() == INSIDE; }
+
+protected:
+ friend class RenderListItem;
+
+ TQString m_item;
+ CachedImage *m_listImage;
+ short m_markerWidth;
+ RenderListItem* m_listItem;
+};
+
+// Implementation of list-item counter
+// ### should replace most list-item specific code in renderObject::getCounter
+/*
+class CounterListItem : public CounterNode
+{
+public:
+ int count() const;
+
+ virtual void recount( bool first = false );
+ virtual void setSelfDirty();
+
+}; */
+
+} //namespace
+
+#endif
diff --git a/tdehtml/rendering/render_object.cpp b/tdehtml/rendering/render_object.cpp
new file mode 100644
index 000000000..a3eb1565e
--- /dev/null
+++ b/tdehtml/rendering/render_object.cpp
@@ -0,0 +1,2330 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2002-2006 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.
+ *
+ */
+
+#include "rendering/render_object.h"
+#include "rendering/render_table.h"
+#include "rendering/render_list.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_block.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_layer.h"
+#include "rendering/render_line.h"
+#include "rendering/render_inline.h"
+#include "rendering/render_text.h"
+#include "rendering/render_replaced.h"
+#include "rendering/render_generated.h"
+#include "rendering/counter_tree.h"
+
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_docimpl.h"
+#include "dom/dom_doc.h"
+#include "misc/htmlhashes.h"
+#include "misc/loader.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <tqpainter.h>
+#include "tdehtmlview.h"
+#include <tdehtml_part.h>
+
+#include <assert.h>
+using namespace DOM;
+using namespace tdehtml;
+
+#define RED_LUMINOSITY 30
+#define GREEN_LUMINOSITY 59
+#define BLUE_LUMINOSITY 11
+#define INTENSITY_FACTOR 25
+#define LIGHT_FACTOR 0
+#define LUMINOSITY_FACTOR 75
+
+#define MAX_COLOR 255
+#define COLOR_DARK_THRESHOLD 51
+#define COLOR_LIGHT_THRESHOLD 204
+
+#define COLOR_LITE_BS_FACTOR 45
+#define COLOR_LITE_TS_FACTOR 70
+
+#define COLOR_DARK_BS_FACTOR 30
+#define COLOR_DARK_TS_FACTOR 50
+
+#define LIGHT_GRAY tqRgb(192, 192, 192)
+#define DARK_GRAY tqRgb(96, 96, 96)
+
+#ifndef NDEBUG
+static void *baseOfRenderObjectBeingDeleted;
+#endif
+
+//#define MASK_DEBUG
+
+void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void RenderObject::operator delete(void* ptr, size_t sz)
+{
+ assert(baseOfRenderObjectBeingDeleted == ptr);
+
+ // Stash size where detach can find it.
+ *(size_t *)ptr = sz;
+}
+
+RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* style)
+{
+ RenderObject *o = 0;
+ tdehtml::RenderArena* arena = node->getDocument()->renderArena();
+ switch(style->display())
+ {
+ case NONE:
+ break;
+ case INLINE:
+ o = new (arena) RenderInline(node);
+ break;
+ case BLOCK:
+ o = new (arena) RenderBlock(node);
+ break;
+ case INLINE_BLOCK:
+ o = new (arena) RenderBlock(node);
+ break;
+ case LIST_ITEM:
+ o = new (arena) RenderListItem(node);
+ break;
+ case RUN_IN:
+ case COMPACT:
+ o = new (arena) RenderBlock(node);
+ break;
+ case TABLE:
+ case INLINE_TABLE:
+ style->setFlowAroundFloats(true);
+ o = new (arena) RenderTable(node);
+ break;
+ case TABLE_ROW_GROUP:
+ case TABLE_HEADER_GROUP:
+ case TABLE_FOOTER_GROUP:
+ o = new (arena) RenderTableSection(node);
+ break;
+ case TABLE_ROW:
+ o = new (arena) RenderTableRow(node);
+ break;
+ case TABLE_COLUMN_GROUP:
+ case TABLE_COLUMN:
+ o = new (arena) RenderTableCol(node);
+ break;
+ case TABLE_CELL:
+ o = new (arena) RenderTableCell(node);
+ break;
+ case TABLE_CAPTION:
+ o = new (arena) RenderBlock(node);
+ break;
+ }
+ return o;
+}
+
+
+RenderObject::RenderObject(DOM::NodeImpl* node)
+ : CachedObjectClient(),
+ m_style( 0 ),
+ m_node( node ),
+ m_parent( 0 ),
+ m_previous( 0 ),
+ m_next( 0 ),
+ m_verticalPosition( PositionUndefined ),
+ m_needsLayout( false ),
+ m_normalChildNeedsLayout( false ),
+ m_markedForRepaint( false ),
+ m_posChildNeedsLayout( false ),
+ m_minMaxKnown( false ),
+ m_floating( false ),
+
+ m_positioned( false ),
+ m_overhangingContents( false ),
+ m_relPositioned( false ),
+ m_paintBackground( false ),
+
+ m_isAnonymous( node->isDocumentNode() ),
+ m_recalcMinMax( false ),
+ m_isText( false ),
+ m_inline( true ),
+ m_attached( false ),
+
+ m_replaced( false ),
+ m_mouseInside( false ),
+ m_hasFirstLine( false ),
+ m_isSelectionBorder( false ),
+ m_isRoot( false ),
+ m_afterPageBreak( false ),
+ m_needsPageClear( false ),
+ m_containsPageBreak( false ),
+ m_hasOverflowClip( false ),
+ m_doNotDelete( false )
+{
+ assert( node );
+ if (node->getDocument()->documentElement() == node) setIsRoot(true);
+}
+
+RenderObject::~RenderObject()
+{
+ const BackgroundLayer* bgLayer = m_style->backgroundLayers();
+ while (bgLayer) {
+ if(bgLayer->backgroundImage())
+ bgLayer->backgroundImage()->deref(this);
+ bgLayer = bgLayer->next();
+ }
+
+ if (m_style)
+ m_style->deref();
+}
+
+
+
+RenderObject* RenderObject::objectBelow() const
+{
+ RenderObject* obj = firstChild();
+ if ( !obj ) {
+ obj = nextSibling();
+ if ( !obj )
+ {
+ obj = parent();
+ while (obj && !obj->nextSibling())
+ obj = obj->parent();
+ if (obj)
+ obj = obj->nextSibling();
+ }
+ }
+ return obj;
+}
+
+RenderObject* RenderObject::objectAbove() const
+{
+ RenderObject* obj = previousSibling();
+ if ( !obj )
+ return parent();
+
+ RenderObject* last = obj->lastChild();
+ while ( last )
+ {
+ obj = last;
+ last = last->lastChild();
+ }
+ return obj;
+}
+/*
+bool RenderObject::isRoot() const
+{
+ return !isAnonymous() &&
+ element()->getDocument()->documentElement() == element();
+}*/
+
+bool RenderObject::isHR() const
+{
+ return element() && element()->id() == ID_HR;
+}
+
+bool RenderObject::isWordBreak() const
+{
+ return element() && element()->id() == ID_WBR;
+}
+
+bool RenderObject::isHTMLMarquee() const
+{
+ return element() && element()->renderer() == this && element()->id() == ID_MARQUEE;
+}
+
+void RenderObject::addChild(RenderObject* , RenderObject *)
+{
+ KHTMLAssert(0);
+}
+
+RenderObject* RenderObject::removeChildNode(RenderObject* )
+{
+ KHTMLAssert(0);
+ return 0;
+}
+
+void RenderObject::removeChild(RenderObject *o )
+{
+ setNeedsLayout(true);
+ removeChildNode( o );
+}
+
+void RenderObject::appendChildNode(RenderObject*)
+{
+ KHTMLAssert(0);
+}
+
+void RenderObject::insertChildNode(RenderObject*, RenderObject*)
+{
+ KHTMLAssert(0);
+}
+
+RenderObject *RenderObject::nextRenderer() const
+{
+ if (firstChild())
+ return firstChild();
+ else if (nextSibling())
+ return nextSibling();
+ else {
+ const RenderObject *r = this;
+ while (r && !r->nextSibling())
+ r = r->parent();
+ if (r)
+ return r->nextSibling();
+ }
+ return 0;
+}
+
+RenderObject *RenderObject::previousRenderer() const
+{
+ if (previousSibling()) {
+ RenderObject *r = previousSibling();
+ while (r->lastChild())
+ r = r->lastChild();
+ return r;
+ }
+ else if (parent()) {
+ return parent();
+ }
+ else {
+ return 0;
+ }
+}
+
+static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
+ RenderLayer*& beforeChild)
+{
+ if (obj->layer()) {
+ if (!beforeChild && newObject) {
+ // We need to figure out the layer that follows newObject. We only do
+ // this the first time we find a child layer, and then we update the
+ // pointer values for newObject and beforeChild used by everyone else.
+ beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
+ newObject = 0;
+ }
+ parentLayer->addChild(obj->layer(), beforeChild);
+ return;
+ }
+
+ for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
+ addLayers(curr, parentLayer, newObject, beforeChild);
+}
+
+void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
+{
+ if (!parentLayer)
+ return;
+
+ RenderObject* object = newObject;
+ RenderLayer* beforeChild = 0;
+ ::addLayers(this, parentLayer, object, beforeChild);
+}
+
+void RenderObject::removeLayers(RenderLayer* parentLayer)
+{
+ if (!parentLayer)
+ return;
+
+ if (layer()) {
+ parentLayer->removeChild(layer());
+ return;
+ }
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ curr->removeLayers(parentLayer);
+}
+
+void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
+{
+ if (!newParent)
+ return;
+
+ if (layer()) {
+ if (oldParent)
+ oldParent->removeChild(layer());
+ newParent->addChild(layer());
+ return;
+ }
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ curr->moveLayers(oldParent, newParent);
+}
+
+RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
+ bool checkParent)
+{
+ // Error check the parent layer passed in. If it's null, we can't find anything.
+ if (!parentLayer)
+ return 0;
+
+ // Step 1: If our layer is a child of the desired parent, then return our layer.
+ RenderLayer* ourLayer = layer();
+ if (ourLayer && ourLayer->parent() == parentLayer)
+ return ourLayer;
+
+ // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
+ // into our siblings trying to find the next layer whose parent is the desired parent.
+ if (!ourLayer || ourLayer == parentLayer) {
+ for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
+ curr; curr = curr->nextSibling()) {
+ RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
+ if (nextLayer)
+ return nextLayer;
+ }
+ }
+
+ // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
+ // find anything.
+ if (parentLayer == ourLayer)
+ return 0;
+
+ // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
+ // follow us to see if we can locate a layer.
+ if (checkParent && parent())
+ return parent()->findNextLayer(parentLayer, this, true);
+
+ return 0;
+}
+
+RenderLayer* RenderObject::enclosingLayer() const
+{
+ const RenderObject* curr = this;
+ while (curr) {
+ RenderLayer *layer = curr->layer();
+ if (layer)
+ return layer;
+ curr = curr->parent();
+ }
+ return 0;
+}
+
+RenderLayer* RenderObject::enclosingStackingContext() const
+{
+ RenderLayer* l = enclosingLayer();
+ while (l && !l->isStackingContext())
+ l = l->parent();
+ return l;
+}
+
+int RenderObject::offsetLeft() const
+{
+ if ( isPositioned() )
+ return xPos();
+
+ if ( isBody() && style()->htmlHacks() )
+ return 0;
+
+ int x = xPos();
+ if (isRelPositioned()) {
+ int y = 0;
+ static_cast<const RenderBox*>(this)->relativePositionOffset(x, y);
+ }
+
+ RenderObject* offsetPar = offsetParent();
+ for( RenderObject* curr = parent();
+ curr && curr != offsetPar;
+ curr = curr->parent() )
+ x += curr->xPos();
+
+ if ( offsetPar && offsetPar->isBody() && style()->htmlHacks() )
+ x += offsetPar->xPos();
+
+ return x;
+}
+
+int RenderObject::offsetTop() const
+{
+ if ( isPositioned() )
+ return yPos();
+
+ if ( isBody() && style()->htmlHacks() )
+ return 0;
+
+ int y = yPos();
+ if (isRelPositioned()) {
+ int x = 0;
+ static_cast<const RenderBox*>(this)->relativePositionOffset(x, y);
+ }
+ RenderObject* offsetPar = offsetParent();
+ for( RenderObject* curr = parent();
+ curr && curr != offsetPar;
+ curr = curr->parent() )
+ y += curr->yPos();
+
+ if ( offsetPar && offsetPar->isBody() && style()->htmlHacks() )
+ y += offsetPar->yPos();
+
+ return y;
+}
+
+RenderObject* RenderObject::offsetParent() const
+{
+ if (isBody())
+ return 0;
+
+ // can't really use containing blocks here (#113280)
+ bool skipTables = isPositioned() || isRelPositioned();
+ bool strict = !style()->htmlHacks();
+ RenderObject* curr = parent();
+ while (curr && (!curr->element() ||
+ (!curr->isPositioned() && !curr->isRelPositioned() &&
+ !(strict && skipTables ? curr->isRoot() : curr->isBody())))) {
+ if (!skipTables && curr->element() && (curr->isTableCell() || curr->isTable()))
+ break;
+ curr = curr->parent();
+ }
+ return curr;
+}
+
+// IE extensions.
+// clientWidth and clientHeight represent the interior of an object
+short RenderObject::clientWidth() const
+{
+ return width() - borderLeft() - borderRight() -
+ (layer() ? layer()->verticalScrollbarWidth() : 0);
+}
+
+int RenderObject::clientHeight() const
+{
+ return height() - borderTop() - borderBottom() -
+ (layer() ? layer()->horizontalScrollbarHeight() : 0);
+}
+
+// scrollWidth/scrollHeight is the size including the overflow area
+short RenderObject::scrollWidth() const
+{
+ return (hasOverflowClip() && layer()) ? layer()->scrollWidth() : overflowWidth() - overflowLeft();
+}
+
+int RenderObject::scrollHeight() const
+{
+ return (hasOverflowClip() && layer()) ? layer()->scrollHeight() : overflowHeight() - overflowTop();
+}
+
+bool RenderObject::hasStaticX() const
+{
+ return (style()->left().isVariable() && style()->right().isVariable());
+}
+
+bool RenderObject::hasStaticY() const
+{
+ return (style()->top().isVariable() && style()->bottom().isVariable());
+}
+
+void RenderObject::setPixmap(const TQPixmap&, const TQRect& /*r*/, CachedImage* image)
+{
+ //repaint bg when it finished loading
+ if(image && parent() && style() && style()->backgroundLayers()->containsImage(image)) {
+ isBody() ? canvas()->repaint() : repaint();
+ }
+}
+
+void RenderObject::setNeedsLayout(bool b, bool markParents)
+{
+ bool alreadyNeededLayout = m_needsLayout;
+ m_needsLayout = b;
+ if (b) {
+ if (!alreadyNeededLayout && markParents && m_parent) {
+ dirtyFormattingContext( false );
+ markContainingBlocksForLayout();
+ }
+ }
+ else {
+ m_posChildNeedsLayout = false;
+ m_normalChildNeedsLayout = false;
+ }
+}
+
+void RenderObject::setChildNeedsLayout(bool b, bool markParents)
+{
+ bool alreadyNeededLayout = m_normalChildNeedsLayout;
+ m_normalChildNeedsLayout = b;
+ if (b) {
+ if (!alreadyNeededLayout && markParents)
+ markContainingBlocksForLayout();
+ }
+ else {
+ m_posChildNeedsLayout = false;
+ m_normalChildNeedsLayout = false;
+ }
+}
+
+void RenderObject::markContainingBlocksForLayout()
+{
+ RenderObject *o = container();
+ RenderObject *last = this;
+
+ while (o) {
+ if (!last->isText() && (last->style()->position() == FIXED || last->style()->position() == ABSOLUTE)) {
+ if (o->m_posChildNeedsLayout)
+ return;
+ o->m_posChildNeedsLayout = true;
+ }
+ else {
+ if (o->m_normalChildNeedsLayout)
+ return;
+ o->m_normalChildNeedsLayout = true;
+ }
+
+ last = o;
+ o = o->container();
+ }
+
+ last->scheduleRelayout();
+}
+
+RenderBlock *RenderObject::containingBlock() const
+{
+ if(isTableCell())
+ return static_cast<RenderBlock*>( parent()->parent()->parent() );
+ if (isCanvas())
+ return const_cast<RenderBlock*>( static_cast<const RenderBlock*>(this) );
+
+ RenderObject *o = parent();
+ if(m_style->position() == FIXED) {
+ while ( o && !o->isCanvas() )
+ o = o->parent();
+ }
+ else if(m_style->position() == ABSOLUTE) {
+ while (o &&
+ ( o->style()->position() == STATIC || ( o->isInline() && !o->isReplaced() ) ) && !o->isCanvas()) {
+ // for relpos inlines, return the nearest block - it will host the positioned objects list
+ if (o->isInline() && !o->isReplaced() && o->style()->position() == RELATIVE)
+ return o->containingBlock();
+ o = o->parent();
+ }
+ } else {
+ while(o && ( ( o->isInline() && !o->isReplaced() ) || o->isTableRow() || o->isTableSection() ||
+ o->isTableCol() || o->isFrameSet() ) )
+ o = o->parent();
+ }
+ // this is just to make sure we return a valid element.
+ // the case below should never happen...
+ if(!o || !o->isRenderBlock()) {
+ if(!isCanvas()) {
+#ifndef NDEBUG
+ kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject): No containingBlock!" << endl;
+ kdDebug( 6040 ) << kdBacktrace() << endl;
+ const RenderObject* p = this;
+ while (p->parent()) p = p->parent();
+ p->printTree();
+#endif
+ }
+ return 0L;
+ }
+
+ return static_cast<RenderBlock*>( o );
+}
+
+short RenderObject::containingBlockWidth() const
+{
+ // ###
+ return containingBlock()->contentWidth();
+}
+
+int RenderObject::containingBlockHeight() const
+{
+ // ###
+ return containingBlock()->contentHeight();
+}
+
+bool RenderObject::sizesToMaxWidth() const
+{
+ // Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
+ // but they allow text to sit on the same line as the marquee.
+ if (isFloating() || isCompact() ||
+ (isInlineBlockOrInlineTable() && !isHTMLMarquee()) ||
+ (element() && (element()->id() == ID_BUTTON || element()->id() == ID_LEGEND)))
+ return true;
+
+ // Children of a horizontal marquee do not fill the container by default.
+ // FIXME: Need to deal with MAUTO value properly. It could be vertical.
+ if (parent()->style()->overflowX() == OMARQUEE) {
+ EMarqueeDirection dir = parent()->style()->marqueeDirection();
+ if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
+ return true;
+ }
+
+#ifdef APPLE_CHANGES // ### what the heck is a flexbox?
+ // Flexible horizontal boxes lay out children at their maxwidths. Also vertical boxes
+ // that don't stretch their kids lay out their children at their maxwidths.
+ if (parent()->isFlexibleBox() &&
+ (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
+ return true;
+#endif
+
+ return false;
+}
+
+// from Mozilla's nsCSSColorUtils.cpp
+static int brightness(int red, int green, int blue)
+{
+
+ int intensity = (red + green + blue) / 3;
+
+ int luminosity =
+ ((RED_LUMINOSITY * red) / 100) +
+ ((GREEN_LUMINOSITY * green) / 100) +
+ ((BLUE_LUMINOSITY * blue) / 100);
+
+ return ((intensity * INTENSITY_FACTOR) +
+ (luminosity * LUMINOSITY_FACTOR)) / 100;
+}
+
+static void calc3DColor(TQColor &color, bool darken)
+{
+ int rb = color.red();
+ int gb = color.green();
+ int bb = color.blue();
+
+ int brightness_ = brightness(rb,gb,bb);
+
+ int f0, f1;
+ if (brightness_ < COLOR_DARK_THRESHOLD) {
+ f0 = COLOR_DARK_BS_FACTOR;
+ f1 = COLOR_DARK_TS_FACTOR;
+ } else if (brightness_ > COLOR_LIGHT_THRESHOLD) {
+ f0 = COLOR_LITE_BS_FACTOR;
+ f1 = COLOR_LITE_TS_FACTOR;
+ } else {
+ f0 = COLOR_DARK_BS_FACTOR +
+ (brightness_ *
+ (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
+ f1 = COLOR_DARK_TS_FACTOR +
+ (brightness_ *
+ (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
+ }
+
+ if (darken) {
+ int r = rb - (f0 * rb / 100);
+ int g = gb - (f0 * gb / 100);
+ int b = bb - (f0 * bb / 100);
+ if ((r == rb) && (g == gb) && (b == bb))
+ color = (color == Qt::black) ? DARK_GRAY : Qt::black;
+ else
+ color.setRgb(r, g, b);
+ } else {
+ int r = kMin(rb + (f1 * (MAX_COLOR - rb) / 100), 255);
+ int g = kMin(gb + (f1 * (MAX_COLOR - gb) / 100), 255);
+ int b = kMin(bb + (f1 * (MAX_COLOR - bb) / 100), 255);
+ if ((r == rb) && (g == gb) && (b == bb))
+ color = (color == Qt::white) ? LIGHT_GRAY : Qt::white;
+ else
+ color.setRgb(r, g, b);
+ }
+}
+
+void RenderObject::drawBorder(TQPainter *p, int x1, int y1, int x2, int y2,
+ BorderSide s, TQColor c, const TQColor& textcolor, EBorderStyle style,
+ int adjbw1, int adjbw2, bool invalidisInvert)
+{
+ int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
+
+ if(style == DOUBLE && width < 3)
+ style = SOLID;
+
+ if(!c.isValid()) {
+ if(invalidisInvert)
+ {
+ p->setRasterOp(TQt::XorROP);
+ c = Qt::white;
+ }
+ else {
+ if(style == INSET || style == OUTSET || style == RIDGE || style ==
+ GROOVE)
+ c = Qt::white;
+ else
+ c = textcolor;
+ }
+ }
+
+ switch(style)
+ {
+ case BNATIVE:
+ case BNONE:
+ case BHIDDEN:
+ // should not happen
+ if(invalidisInvert && p->rasterOp() == TQt::XorROP)
+ p->setRasterOp(TQt::CopyROP);
+
+ return;
+ case DOTTED:
+ if ( width == 1 ) {
+ // workaround Qt brokenness
+ p->setPen(TQPen(c, width, Qt::SolidLine));
+ switch(s) {
+ case BSBottom:
+ case BSTop:
+ for ( ; x1 < x2; x1 += 2 )
+ p->drawPoint( x1, y1 );
+ break;
+ case BSRight:
+ case BSLeft:
+ for ( ; y1 < y2; y1 += 2 )
+ p->drawPoint( x1, y1 );
+ }
+ break;
+ }
+
+ p->setPen(TQPen(c, width, Qt::DotLine));
+ /* nobreak; */
+ case DASHED:
+ if(style == DASHED)
+ p->setPen(TQPen(c, width == 1 ? 0 : width, width == 1 ? Qt::DotLine : Qt::DashLine));
+
+ if (width > 0)
+ switch(s) {
+ case BSBottom:
+ case BSTop:
+ p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
+ break;
+ case BSRight:
+ case BSLeft:
+ p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
+ break;
+ }
+
+ break;
+ case DOUBLE:
+ {
+ int third = (width+1)/3;
+
+ if (adjbw1 == 0 && adjbw2 == 0)
+ {
+ p->setPen(Qt::NoPen);
+ p->setBrush(c);
+ switch(s)
+ {
+ case BSTop:
+ case BSBottom:
+ p->drawRect(x1, y1 , x2-x1, third);
+ p->drawRect(x1, y2-third, x2-x1, third);
+ break;
+ case BSLeft:
+ p->drawRect(x1 , y1+1, third, y2-y1-1);
+ p->drawRect(x2-third, y1+1, third, y2-y1-1);
+ break;
+ case BSRight:
+ p->drawRect(x1 , y1+1, third, y2-y1-1);
+ p->drawRect(x2-third, y1+1, third, y2-y1-1);
+ break;
+ }
+ }
+ else
+ {
+ int adjbw1bigthird;
+ if (adjbw1>0) adjbw1bigthird = adjbw1+1;
+ else adjbw1bigthird = adjbw1 - 1;
+ adjbw1bigthird /= 3;
+
+ int adjbw2bigthird;
+ if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
+ else adjbw2bigthird = adjbw2 - 1;
+ adjbw2bigthird /= 3;
+
+ switch(s)
+ {
+ case BSTop:
+ drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y1 , x2-kMax((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y2 - third, x2-kMax(( adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ break;
+ case BSLeft:
+ drawBorder(p, x1 , y1+kMax((-adjbw1*2+1)/3,0), x1+third, y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawBorder(p, x2 - third, y1+kMax(( adjbw1*2+1)/3,0), x2 , y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ break;
+ case BSBottom:
+ drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y1 , x2-kMax(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y2-third, x2-kMax((-adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ break;
+ case BSRight:
+ drawBorder(p, x1 , y1+kMax(( adjbw1*2+1)/3,0), x1+third, y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawBorder(p, x2-third, y1+kMax((-adjbw1*2+1)/3,0), x2 , y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ case RIDGE:
+ case GROOVE:
+ {
+ EBorderStyle s1;
+ EBorderStyle s2;
+ if (style==GROOVE)
+ {
+ s1 = INSET;
+ s2 = OUTSET;
+ }
+ else
+ {
+ s1 = OUTSET;
+ s2 = INSET;
+ }
+
+ int adjbw1bighalf;
+ int adjbw2bighalf;
+ if (adjbw1>0) adjbw1bighalf=adjbw1+1;
+ else adjbw1bighalf=adjbw1-1;
+ adjbw1bighalf/=2;
+
+ if (adjbw2>0) adjbw2bighalf=adjbw2+1;
+ else adjbw2bighalf=adjbw2-1;
+ adjbw2bighalf/=2;
+
+ switch (s)
+ {
+ case BSTop:
+ drawBorder(p, x1+kMax(-adjbw1 ,0)/2, y1 , x2-kMax(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
+ drawBorder(p, x1+kMax( adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax( adjbw2+1,0)/2, y2 , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
+ break;
+ case BSLeft:
+ drawBorder(p, x1 , y1+kMax(-adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
+ drawBorder(p, (x1+x2+1)/2, y1+kMax( adjbw1+1,0)/2, x2 , y2-kMax( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
+ break;
+ case BSBottom:
+ drawBorder(p, x1+kMax( adjbw1 ,0)/2, y1 , x2-kMax( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
+ drawBorder(p, x1+kMax(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax(-adjbw2+1,0)/2, y2 , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
+ break;
+ case BSRight:
+ drawBorder(p, x1 , y1+kMax( adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
+ drawBorder(p, (x1+x2+1)/2, y1+kMax(-adjbw1+1,0)/2, x2 , y2-kMax(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
+ break;
+ }
+ break;
+ }
+ case INSET:
+ case OUTSET:
+ calc3DColor(c, (style == OUTSET && (s == BSBottom || s == BSRight)) ||
+ (style == INSET && ( s == BSTop || s == BSLeft ) ) );
+ /* nobreak; */
+ case SOLID:
+ p->setPen(Qt::NoPen);
+ p->setBrush(c);
+ Q_ASSERT(x2>=x1);
+ Q_ASSERT(y2>=y1);
+ if (adjbw1==0 && adjbw2 == 0) {
+ p->drawRect(x1,y1,x2-x1,y2-y1);
+ return;
+ }
+ TQPointArray quad(4);
+ switch(s) {
+ case BSTop:
+ quad.setPoints(4,
+ x1+kMax(-adjbw1,0), y1,
+ x1+kMax( adjbw1,0), y2,
+ x2-kMax( adjbw2,0), y2,
+ x2-kMax(-adjbw2,0), y1);
+ break;
+ case BSBottom:
+ quad.setPoints(4,
+ x1+kMax( adjbw1,0), y1,
+ x1+kMax(-adjbw1,0), y2,
+ x2-kMax(-adjbw2,0), y2,
+ x2-kMax( adjbw2,0), y1);
+ break;
+ case BSLeft:
+ quad.setPoints(4,
+ x1, y1+kMax(-adjbw1,0),
+ x1, y2-kMax(-adjbw2,0),
+ x2, y2-kMax( adjbw2,0),
+ x2, y1+kMax( adjbw1,0));
+ break;
+ case BSRight:
+ quad.setPoints(4,
+ x1, y1+kMax( adjbw1,0),
+ x1, y2-kMax( adjbw2,0),
+ x2, y2-kMax(-adjbw2,0),
+ x2, y1+kMax(-adjbw1,0));
+ break;
+ }
+ p->drawConvexPolygon(quad);
+ break;
+ }
+
+ if(invalidisInvert && p->rasterOp() == TQt::XorROP)
+ p->setRasterOp(TQt::CopyROP);
+}
+
+void RenderObject::paintBorder(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
+{
+ const TQColor& tc = style->borderTopColor();
+ const TQColor& bc = style->borderBottomColor();
+ const TQColor& lc = style->borderLeftColor();
+ const TQColor& rc = style->borderRightColor();
+
+ bool tt = style->borderTopIsTransparent();
+ bool bt = style->borderBottomIsTransparent();
+ bool rt = style->borderRightIsTransparent();
+ bool lt = style->borderLeftIsTransparent();
+
+ EBorderStyle ts = style->borderTopStyle();
+ EBorderStyle bs = style->borderBottomStyle();
+ EBorderStyle ls = style->borderLeftStyle();
+ EBorderStyle rs = style->borderRightStyle();
+
+ bool render_t = ts > BHIDDEN && !tt;
+ bool render_l = ls > BHIDDEN && begin && !lt;
+ bool render_r = rs > BHIDDEN && end && !rt;
+ bool render_b = bs > BHIDDEN && !bt;
+
+ if(render_t) {
+ bool ignore_left =
+ (tc == lc) && (tt == lt) &&
+ (ts >= OUTSET) &&
+ (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
+
+ bool ignore_right =
+ (tc == rc) && (tt == rt) &&
+ (ts >= OUTSET) &&
+ (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
+
+ drawBorder(p, _tx, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+ ignore_left?0:style->borderLeftWidth(),
+ ignore_right?0:style->borderRightWidth());
+ }
+
+ if(render_b) {
+ bool ignore_left =
+ (bc == lc) && (bt == lt) &&
+ (bs >= OUTSET) &&
+ (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
+
+ bool ignore_right =
+ (bc == rc) && (bt == rt) &&
+ (bs >= OUTSET) &&
+ (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
+
+ drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
+ ignore_left?0:style->borderLeftWidth(),
+ ignore_right?0:style->borderRightWidth());
+ }
+
+ if(render_l)
+ {
+ bool ignore_top =
+ (tc == lc) && (tt == lt) &&
+ (ls >= OUTSET) &&
+ (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+ bool ignore_bottom =
+ (bc == lc) && (bt == lt) &&
+ (ls >= OUTSET) &&
+ (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+ drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
+ ignore_top?0:style->borderTopWidth(),
+ ignore_bottom?0:style->borderBottomWidth());
+ }
+
+ if(render_r)
+ {
+ bool ignore_top =
+ (tc == rc) && (tt == rt) &&
+ (rs >= DOTTED || rs == INSET) &&
+ (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
+
+ bool ignore_bottom =
+ (bc == rc) && (bt == rt) &&
+ (rs >= DOTTED || rs == INSET) &&
+ (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
+
+ drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
+ ignore_top?0:style->borderTopWidth(),
+ ignore_bottom?0:style->borderBottomWidth());
+ }
+}
+
+void RenderObject::paintOutline(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style)
+{
+ int ow = style->outlineWidth();
+ if(!ow) return;
+
+ const TQColor& oc = style->outlineColor();
+ EBorderStyle os = style->outlineStyle();
+ int offset = style->outlineOffset();
+
+#ifdef APPLE_CHANGES
+ if (style->outlineStyleIsAuto()) {
+ p->initFocusRing(ow, offset, oc);
+ addFocusRingRects(p, _tx, _ty);
+ p->drawFocusRing();
+ p->clearFocusRing();
+ return;
+ }
+#endif
+
+ _tx -= offset;
+ _ty -= offset;
+ w += 2*offset;
+ h += 2*offset;
+
+ drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
+ TQColor(oc), style->color(),
+ os, ow, ow, true);
+
+ drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
+ TQColor(oc), style->color(),
+ os, ow, ow, true);
+
+ drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
+ TQColor(oc), style->color(),
+ os, ow, ow, true);
+
+ drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
+ TQColor(oc), style->color(),
+ os, ow, ow, true);
+
+}
+
+void RenderObject::paint( PaintInfo&, int /*tx*/, int /*ty*/)
+{
+}
+
+void RenderObject::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
+{
+ if(parent()) parent()->repaintRectangle(x, y, w, h, p, f);
+}
+
+#ifdef ENABLE_DUMP
+
+TQString RenderObject::information() const
+{
+ TQString str;
+ int x; int y;
+ absolutePosition(x,y);
+ x += inlineXPos();
+ y += inlineYPos();
+ TQTextStream ts( &str, IO_WriteOnly );
+ ts << renderName()
+ << "(" << (style() ? style()->refCount() : 0) << ")"
+ << ": " << (void*)this << " ";
+ ts << "{" << x << " " << y << "} ";
+ if (isInline()) ts << "il ";
+ if (childrenInline()) ts << "ci ";
+ if (isFloating()) ts << "fl ";
+ if (isAnonymous()) ts << "an ";
+ if (isRelPositioned()) ts << "rp ";
+ if (isPositioned()) ts << "ps ";
+ if (isReplaced()) ts << "rp ";
+ if (overhangingContents()) ts << "oc ";
+ if (needsLayout()) ts << "nl ";
+ if (minMaxKnown()) ts << "mmk ";
+ if (m_recalcMinMax) ts << "rmm ";
+ if (mouseInside()) ts << "mi ";
+ if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
+ if (style() && style()->hasAutoZIndex()) ts << "zI: auto ";
+ if (element()) {
+ if (element()->active()) ts << "act ";
+ if (element()->hasAnchor()) ts << "anchor ";
+ if (element()->focused()) ts << "focus ";
+ ts << " <" << getTagName(element()->id()) << ">";
+
+ } else if (isPseudoAnonymous() && style() && style()->styleType() != RenderStyle::NOPSEUDO) {
+ ts << " <" << getTagName(node()->id());
+ TQString pseudo;
+ switch (style()->styleType()) {
+ case RenderStyle::FIRST_LETTER:
+ pseudo = ":first-letter"; break;
+ case RenderStyle::BEFORE:
+ pseudo = ":before"; break;
+ case RenderStyle::AFTER:
+ pseudo = ":after"; break;
+ default:
+ pseudo = ":pseudo-element";
+ }
+ ts << pseudo;
+ ts << ">";
+ }
+ ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
+ << " [" << minWidth() << "-" << maxWidth() << "]"
+ << " { mT: " << marginTop() << " qT: " << isTopMarginQuirk()
+ << " mB: " << marginBottom() << " qB: " << isBottomMarginQuirk()
+ << "}"
+ << (isTableCell() ?
+ ( TQString::fromLatin1(" [r=") +
+ TQString::number( static_cast<const RenderTableCell *>(this)->row() ) +
+ TQString::fromLatin1(" c=") +
+ TQString::number( static_cast<const RenderTableCell *>(this)->col() ) +
+ TQString::fromLatin1(" rs=") +
+ TQString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
+ TQString::fromLatin1(" cs=") +
+ TQString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
+ TQString::fromLatin1("]") ) : TQString::null );
+ if ( layer() )
+ ts << " layer=" << layer();
+ if ( continuation() )
+ ts << " continuation=" << continuation();
+ if (isText())
+ ts << " \"" << TQConstString(static_cast<const RenderText *>(this)->text(), kMin(static_cast<const RenderText *>(this)->length(), 10u)).string() << "\"";
+ return str;
+}
+
+void RenderObject::printTree(int indent) const
+{
+ TQString ind;
+ ind.fill(' ', indent);
+
+ kdDebug() << ind << information() << endl;
+
+ RenderObject *child = firstChild();
+ while( child != 0 )
+ {
+ child->printTree(indent+2);
+ child = child->nextSibling();
+ }
+}
+
+static TQTextStream &operator<<(TQTextStream &ts, const TQRect &r)
+{
+ return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
+}
+
+//A bit like getTagName, but handles XML, too.
+static TQString lookupTagName(NodeImpl* node) {
+ return node->getDocument()->getName(NodeImpl::ElementId, node->id()).string();
+}
+
+void RenderObject::dump(TQTextStream &ts, const TQString &ind) const
+{
+ if ( !layer() )
+ ts << endl;
+
+ ts << ind << renderName();
+
+ if (style() && style()->zIndex()) {
+ ts << " zI: " << style()->zIndex();
+ }
+
+ if (element()) {
+ TQString tagName(lookupTagName(element()));
+ if (!tagName.isEmpty()) {
+ ts << " {" << tagName << "}";
+ }
+ } else if (isPseudoAnonymous() && style() && style()->styleType() != RenderStyle::NOPSEUDO) {
+ TQString pseudo;
+ TQString tagName(lookupTagName(node()));
+ switch (style()->styleType()) {
+ case RenderStyle::FIRST_LETTER:
+ pseudo = ":first-letter"; break;
+ case RenderStyle::BEFORE:
+ pseudo = ":before"; break;
+ case RenderStyle::AFTER:
+ pseudo = ":after"; break;
+ default:
+ pseudo = ":pseudo-element";
+ }
+ ts << " {" << tagName << pseudo << "}";
+ }
+
+ TQRect r(xPos(), yPos(), width(), height());
+ ts << " " << r;
+
+ if ( parent() )
+ ts << style()->createDiff( *parent()->style() );
+
+ if (isAnonymous()) { ts << " anonymousBox"; }
+ if (isFloating()) { ts << " floating"; }
+ if (isPositioned()) { ts << " positioned"; }
+ if (isRelPositioned()) { ts << " relPositioned"; }
+ if (isText()) { ts << " text"; }
+ if (isInline()) { ts << " inline"; }
+ if (isReplaced()) { ts << " replaced"; }
+ if (shouldPaintBackgroundOrBorder()) { ts << " paintBackground"; }
+ if (needsLayout()) { ts << " needsLayout"; }
+ if (minMaxKnown()) { ts << " minMaxKnown"; }
+ if (overhangingContents()) { ts << " overhangingContents"; }
+ if (hasFirstLine()) { ts << " hasFirstLine"; }
+ if (afterPageBreak()) { ts << " afterPageBreak"; }
+}
+#endif
+
+void RenderObject::selectionStartEnd(int& spos, int& epos)
+{
+ if (parent())
+ parent()->selectionStartEnd(spos, epos);
+}
+
+void RenderObject::setStyle(RenderStyle *style)
+{
+ if (m_style == style)
+ return;
+
+ RenderStyle::Diff d = m_style ? m_style->diff( style ) : RenderStyle::Layout;
+ //tqDebug("m_style: %p new style, diff=%d", m_style, d);
+
+ Priority pri = NormalPriority;
+ if (m_style) {
+ pri = HighPriority;
+ if ( d >= RenderStyle::Visible && !isText() && m_parent &&
+ ( d == RenderStyle::Position ||
+ m_style->outlineWidth() > style->outlineWidth() ||
+ (!m_style->hidesOverflow() && style->hidesOverflow()) ||
+ ( m_style->hasClip() && !(m_style->clip() == style->clip()) ) ) ) {
+ // schedule a repaint with the old style
+ if (layer() && !isInlineFlow())
+ layer()->repaint(pri);
+ else
+ repaint(pri);
+ }
+
+ if ( ( isFloating() && m_style->floating() != style->floating() ) ||
+ ( isPositioned() && m_style->position() != style->position() &&
+ style->position() != ABSOLUTE && style->position() != FIXED ) )
+ removeFromObjectLists();
+
+ if ( layer() ) {
+ if ( ( m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
+ m_style->zIndex() != style->zIndex() ||
+ m_style->visibility() != style->visibility() ) ) {
+ layer()->stackingContext()->dirtyZOrderLists();
+ layer()->dirtyZOrderLists();
+ }
+ }
+
+ // reset style flags
+ m_floating = false;
+ m_positioned = false;
+ m_relPositioned = false;
+ m_paintBackground = false;
+ m_hasOverflowClip = false;
+ }
+
+ // only honour z-index for non-static objects
+ // ### and objects with opacity
+ if ( style->position() == STATIC ) {
+ if ( isRoot() )
+ style->setZIndex( 0 );
+ else
+ style->setHasAutoZIndex();
+ }
+
+ RenderStyle *oldStyle = m_style;
+ m_style = style;
+
+ updateBackgroundImages(oldStyle);
+
+ m_style->ref();
+
+ if (oldStyle)
+ oldStyle->deref();
+
+ setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground());
+
+ m_hasFirstLine = (style->getPseudoStyle(RenderStyle::FIRST_LINE) != 0);
+ if (m_parent) {
+ if (d == RenderStyle::Position && !attemptDirectLayerTranslation())
+ d = RenderStyle::Layout;
+
+ if ( d > RenderStyle::Position) {
+ // we must perform a full layout
+ if (!isText() && d == RenderStyle::CbLayout) {
+ dirtyFormattingContext( true );
+ }
+ setNeedsLayoutAndMinMaxRecalc();
+ } else if (!isText() && d >= RenderStyle::Visible) {
+ // a repaint is enough
+ if (layer()) {
+ if (canvas() && canvas()->needsWidgetMasks()) {
+ // update our widget masks
+ RenderLayer *p, *d = 0;
+ for (p=layer()->parent();p;p=p->parent())
+ if (p->hasOverlaidWidgets()) d=p;
+ if (d) // deepest
+ d->updateWidgetMasks( canvas()->layer() );
+ }
+ }
+ if (layer() && !isInlineFlow())
+ layer()->repaint(pri);
+ else
+ repaint(pri);
+ }
+ }
+}
+
+bool RenderObject::attemptDirectLayerTranslation()
+{
+ // When the difference between two successive styles is only 'Position'
+ // we may attempt to save a layout by directly updating the object position.
+
+ KHTMLAssert( m_style->position() != STATIC );
+ if (!layer())
+ return false;
+ setInline(m_style->isDisplayInlineType());
+ setPositioned(m_style->position() != RELATIVE);
+ setRelPositioned(m_style->position() == RELATIVE);
+ int oldXPos = xPos();
+ int oldYPos = yPos();
+ int oldWidth = width();
+ int oldHeight = height();
+ calcWidth();
+ calcHeight();
+ if (oldWidth != width() || oldHeight != height()) {
+ // implicit size change or overconstrained dimensions:
+ // we'll need a layout.
+ setWidth(oldWidth);
+ setHeight(oldHeight);
+ // kdDebug() << "Layer translation failed for " << information() << endl;
+ return false;
+ }
+ layer()->updateLayerPosition();
+ if (m_style->position() != FIXED) {
+ bool needsDocSizeUpdate = true;
+ RenderObject *cb = container();
+ while (cb) {
+ if (cb->hasOverflowClip() && cb->layer()) {
+ cb->layer()->checkScrollbarsAfterLayout();
+ needsDocSizeUpdate = false;
+ break;
+ }
+ cb = cb->container();
+ }
+ if (needsDocSizeUpdate && canvas()) {
+ bool posXOffset = (xPos()-oldXPos >= 0);
+ bool posYOffset = (yPos()-oldYPos >= 0);
+ canvas()->updateDocSizeAfterLayerTranslation(this, posXOffset, posYOffset);
+ }
+ }
+ // success
+ return true;
+}
+
+void RenderObject::dirtyFormattingContext( bool checkContainer )
+{
+ if (m_markedForRepaint && !checkContainer)
+ return;
+ m_markedForRepaint = true;
+ if (layer() && (style()->position() == FIXED || style()->position() == ABSOLUTE))
+ return;
+ if (m_parent && (checkContainer || style()->width().isVariable() || style()->height().isVariable() ||
+ !(isFloating() || flowAroundFloats() || isTableCell())))
+ m_parent->dirtyFormattingContext(false);
+}
+
+void RenderObject::repaintDuringLayout()
+{
+ if (canvas()->needsFullRepaint() || isText())
+ return;
+ if (layer() && !isInlineFlow()) {
+ layer()->repaint( NormalPriority, true );
+ } else {
+ repaint();
+ canvas()->deferredRepaint( this );
+ }
+}
+
+void RenderObject::setOverhangingContents(bool p)
+{
+ if (m_overhangingContents == p)
+ return;
+
+ RenderBlock *cb = containingBlock();
+ if (p)
+ {
+ m_overhangingContents = true;
+ KHTMLAssert( cb != this || isCanvas());
+ if (cb && cb != this)
+ cb->setOverhangingContents();
+ }
+ else
+ {
+ RenderObject *n;
+ bool c=false;
+
+ for( n = firstChild(); n != 0; n = n->nextSibling() )
+ {
+ if (n->isPositioned() || n->overhangingContents())
+ c=true;
+ }
+
+ if (c)
+ return;
+ else
+ {
+ m_overhangingContents = false;
+ KHTMLAssert( cb != this );
+ if (cb && cb != this)
+ cb->setOverhangingContents(false);
+ }
+ }
+}
+
+void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
+{
+ // FIXME: This will be slow when a large number of images is used. Fix by using a dict.
+ const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
+ const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
+ for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
+ if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
+ currOld->backgroundImage()->deref(this);
+ }
+ for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
+ if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
+ currNew->backgroundImage()->ref(this);
+ }
+}
+
+TQRect RenderObject::viewRect() const
+{
+ return containingBlock()->viewRect();
+}
+
+bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f) const
+{
+ RenderObject* p = parent();
+ if (p) {
+ p->absolutePosition(xPos, yPos, f);
+ if ( p->hasOverflowClip() )
+ p->layer()->subtractScrollOffset( xPos, yPos );
+ return true;
+ }
+ else
+ {
+ xPos = yPos = 0;
+ return false;
+ }
+}
+
+void RenderObject::caretPos(int /*offset*/, int /*flags*/, int &_x, int &_y, int &width, int &height)
+{
+ _x = _y = height = -1;
+ width = 1; // the caret has a default width of one pixel. If you want
+ // to check for validity, only test the x-coordinate for >= 0.
+}
+
+int RenderObject::paddingTop() const
+{
+ int w = 0;
+ Length padding = m_style->paddingTop();
+ if (padding.isPercent())
+ w = containingBlock()->contentWidth();
+ w = padding.minWidth(w);
+ if ( isTableCell() && padding.isVariable() )
+ w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
+ return w;
+}
+
+int RenderObject::paddingBottom() const
+{
+ int w = 0;
+ Length padding = style()->paddingBottom();
+ if (padding.isPercent())
+ w = containingBlock()->contentWidth();
+ w = padding.minWidth(w);
+ if ( isTableCell() && padding.isVariable() )
+ w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
+ return w;
+}
+
+int RenderObject::paddingLeft() const
+{
+ int w = 0;
+ Length padding = style()->paddingLeft();
+ if (padding.isPercent())
+ w = containingBlock()->contentWidth();
+ w = padding.minWidth(w);
+ if ( isTableCell() && padding.isVariable() )
+ w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
+ return w;
+}
+
+int RenderObject::paddingRight() const
+{
+ int w = 0;
+ Length padding = style()->paddingRight();
+ if (padding.isPercent())
+ w = containingBlock()->contentWidth();
+ w = padding.minWidth(w);
+ if ( isTableCell() && padding.isVariable() )
+ w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
+ return w;
+}
+
+RenderObject *RenderObject::container() const
+{
+ // This method is extremely similar to containingBlock(), but with a few notable
+ // exceptions.
+ // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
+ // the object is not part of the primary document subtree yet.
+ // (2) For normal flow elements, it just returns the parent.
+ // (3) For absolute positioned elements, it will return a relative positioned inline.
+ // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
+ // the layout of the positioned object. This does mean that calcAbsoluteHorizontal and
+ // calcAbsoluteVertical have to use container().
+ EPosition pos = m_style->position();
+ RenderObject *o = 0;
+ if( pos == FIXED ) {
+ // container() can be called on an object that is not in the
+ // tree yet. We don't call canvas() since it will assert if it
+ // can't get back to the canvas. Instead we just walk as high up
+ // as we can. If we're in the tree, we'll get the root. If we
+ // aren't we'll get the root of our little subtree (most likely
+ // we'll just return 0).
+ o = parent();
+ while ( o && o->parent() ) o = o->parent();
+ }
+ else if ( pos == ABSOLUTE ) {
+ // Same goes here. We technically just want our containing block, but
+ // we may not have one if we're part of an uninstalled subtree. We'll
+ // climb as high as we can though.
+ o = parent();
+ while (o && o->style()->position() == STATIC && !o->isCanvas())
+ o = o->parent();
+ }
+ else
+ o = parent();
+ return o;
+}
+
+DOM::DocumentImpl* RenderObject::document() const
+{
+ return m_node->getDocument();
+}
+
+void RenderObject::remove()
+{
+ if ( parent() )
+ //have parent, take care of the tree integrity
+ parent()->removeChild(this);
+}
+
+void RenderObject::removeFromObjectLists()
+{
+ // in destruction mode, don't care.
+ if ( !document()->renderer() ) return;
+
+ if (isFloating()) {
+ RenderBlock* outermostBlock = containingBlock();
+ for (RenderBlock* p = outermostBlock; p && !p->isCanvas() && p->containsFloat(this);) {
+ outermostBlock = p;
+ if (p->isFloatingOrPositioned())
+ break;
+ p = p->containingBlock();
+ }
+
+ if (outermostBlock)
+ outermostBlock->markAllDescendantsWithFloatsForLayout(this);
+ }
+
+ if (isPositioned()) {
+ RenderObject *p;
+ for (p = parent(); p; p = p->parent()) {
+ if (p->isRenderBlock())
+ static_cast<RenderBlock*>(p)->removePositionedObject(this);
+ }
+ }
+}
+
+RenderArena* RenderObject::renderArena() const
+{
+ return m_node->getDocument()->renderArena();
+}
+
+void RenderObject::detach()
+{
+ detachCounters();
+
+ deleteInlineBoxes();
+ remove();
+
+ // make sure our DOM-node don't think we exist
+ if ( node() && node()->renderer() == this)
+ node()->setRenderer(0);
+
+ // by default no refcounting
+ arenaDelete(renderArena(), this);
+}
+
+void RenderObject::arenaDelete(RenderArena *arena, void *base)
+{
+#ifndef NDEBUG
+ void *savedBase = baseOfRenderObjectBeingDeleted;
+ baseOfRenderObjectBeingDeleted = base;
+#endif
+ delete this;
+#ifndef NDEBUG
+ baseOfRenderObjectBeingDeleted = savedBase;
+#endif
+
+ // Recover the size left there for us by operator delete and free the memory.
+ arena->free(*(size_t *)base, base);
+}
+
+void RenderObject::arenaDelete(RenderArena *arena)
+{
+ // static_cast unfortunately doesn't work, since we multiple inherit
+ // in eg. RenderWidget.
+ arenaDelete(arena, dynamic_cast<void *>(this));
+}
+
+FindSelectionResult RenderObject::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
+{
+#if 0
+ NodeInfo info(true, false);
+ if ( nodeAtPoint( info, _x, _y, _tx, _ty ) && info.innerNode() )
+ {
+ RenderObject* r = info.innerNode()->renderer();
+ if ( r ) {
+ if ( r == this ) {
+ node = info.innerNode();
+ offset = 0; // we have no text...
+ return SelectionPointInside;
+ }
+ else
+ return r->checkSelectionPoint( _x, _y, _tx, _ty, node, offset, state );
+ }
+ }
+ //kdDebug(6030) << "nodeAtPoint Failed. Fallback - hmm, SelectionPointAfter" << endl;
+ node = 0;
+ offset = 0;
+ return SelectionPointAfter;
+#endif
+ int off = offset;
+ DOM::NodeImpl* nod = node;
+
+ for (RenderObject *child = firstChild(); child; child=child->nextSibling()) {
+ // ignore empty text boxes, they produce totally bogus information
+ // for caret navigation (LS)
+ if (child->isText() && !static_cast<RenderText *>(child)->inlineTextBoxCount())
+ continue;
+
+// kdDebug(6040) << "iterating " << (child ? child->renderName() : "") << "@" << child << (child->isText() ? " contains: \"" + TQConstString(static_cast<RenderText *>(child)->text(), kMin(static_cast<RenderText *>(child)->length(), 10u)).string() + "\"" : TQString::null) << endl;
+// kdDebug(6040) << "---------- checkSelectionPoint recursive -----------" << endl;
+ tdehtml::FindSelectionResult pos = child->checkSelectionPoint(_x, _y, _tx+xPos(), _ty+yPos(), nod, off, state);
+// kdDebug(6040) << "-------- end checkSelectionPoint recursive ---------" << endl;
+// kdDebug(6030) << this << " child->findSelectionNode returned result=" << pos << " nod=" << nod << " off=" << off << endl;
+ switch(pos) {
+ case SelectionPointBeforeInLine:
+ case SelectionPointInside:
+ //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " returning SelectionPointInside offset=" << offset << endl;
+ node = nod;
+ offset = off;
+ return SelectionPointInside;
+ case SelectionPointBefore:
+ //x,y is before this element -> stop here
+ if ( state.m_lastNode ) {
+ node = state.m_lastNode;
+ offset = state.m_lastOffset;
+ //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before this child "
+ // << node << "-> returning SelectionPointInside, offset=" << offset << endl;
+ return SelectionPointInside;
+ } else {
+ node = nod;
+ offset = off;
+ //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl;
+ return SelectionPointBefore;
+ }
+ break;
+ case SelectionPointAfter:
+ if (state.m_afterInLine) break;
+ // fall through
+ case SelectionPointAfterInLine:
+ if (pos == SelectionPointAfterInLine) state.m_afterInLine = true;
+ //kdDebug(6030) << "RenderObject::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl;
+ state.m_lastNode = nod;
+ state.m_lastOffset = off;
+ // No "return" here, obviously. We must keep looking into the children.
+ break;
+ }
+ }
+ // If we are after the last child, return lastNode/lastOffset
+ // But lastNode can be 0L if there is no child, for instance.
+ if ( state.m_lastNode )
+ {
+ node = state.m_lastNode;
+ offset = state.m_lastOffset;
+ }
+ //kdDebug(6030) << "fallback - SelectionPointAfter node=" << node << " offset=" << offset << endl;
+ return SelectionPointAfter;
+}
+
+bool RenderObject::mouseInside() const
+{
+ if (!m_mouseInside && continuation())
+ return continuation()->mouseInside();
+ return m_mouseInside;
+}
+
+bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
+{
+ int tx = _tx + xPos();
+ int ty = _ty + yPos();
+
+ inside |= ( style()->visibility() != HIDDEN &&
+ (_y >= ty) && (_y < ty + height()) && (_x >= tx) && (_x < tx + width())) || isRoot() || isBody();
+ bool inOverflowRect = inside;
+ if ( !inOverflowRect ) {
+ int ol = overflowLeft();
+ int ot = overflowTop();
+ TQRect overflowRect( tx+ol, ty+ot, overflowWidth()-ol, overflowHeight()-ot );
+ inOverflowRect = overflowRect.contains( _x, _y );
+ }
+
+ // ### table should have its own, more performant method
+ if (hitTestAction != HitTestSelfOnly &&
+ (( !isRenderBlock() ||
+ !static_cast<RenderBlock*>( this )->isPointInScrollbar( _x, _y, _tx, _ty )) &&
+ (overhangingContents() || inOverflowRect || isInline() || isRoot() || isCanvas() ||
+ isTableRow() || isTableSection() || inside || mouseInside() ))) {
+ if ( hitTestAction == HitTestChildrenOnly )
+ inside = false;
+ if ( hasOverflowClip() && layer() )
+ layer()->subtractScrollOffset(tx, ty);
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling())
+ if (!child->layer() && child->nodeAtPoint(info, _x, _y, tx, ty, HitTestAll))
+ inside = true;
+ }
+
+ if (inside)
+ setInnerNode(info);
+
+ return inside;
+}
+
+
+void RenderObject::setInnerNode(NodeInfo& info)
+{
+ if (!info.innerNode() && !isInline() && continuation()) {
+ // We are in the margins of block elements that are part of a continuation. In
+ // this case we're actually still inside the enclosing inline element that was
+ // split. Go ahead and set our inner node accordingly.
+ info.setInnerNode(continuation()->element());
+ if (!info.innerNonSharedNode())
+ info.setInnerNonSharedNode(continuation()->element());
+ }
+
+ if (!info.innerNode() && element())
+ info.setInnerNode(element());
+
+ if(!info.innerNonSharedNode() && element())
+ info.setInnerNonSharedNode(element());
+}
+
+
+short RenderObject::verticalPositionHint( bool firstLine ) const
+{
+ short vpos = m_verticalPosition;
+ if ( m_verticalPosition == PositionUndefined || firstLine ) {
+ vpos = getVerticalPosition( firstLine );
+ if ( !firstLine )
+ const_cast<RenderObject *>(this)->m_verticalPosition = vpos;
+ }
+ return vpos;
+
+}
+
+short RenderObject::getVerticalPosition( bool firstLine, RenderObject* ref ) const
+{
+ // vertical align for table cells has a different meaning
+ int vpos = 0;
+ if ( !isTableCell() && isInline() ) {
+ EVerticalAlign va = style()->verticalAlign();
+ if ( va == TOP ) {
+ vpos = PositionTop;
+ } else if ( va == BOTTOM ) {
+ vpos = PositionBottom;
+ } else {
+ if (!ref) ref = parent();
+ bool checkParent = ref->isInline() && !ref->isReplacedBlock() &&
+ !( ref->style()->verticalAlign() == TOP || ref->style()->verticalAlign() == BOTTOM );
+ vpos = checkParent ? ref->verticalPositionHint( firstLine ) : 0;
+ // don't allow elements nested inside text-top to have a different valignment.
+ if ( va == BASELINE )
+ return vpos;
+ else if ( va == LENGTH )
+ return vpos - style()->verticalAlignLength().width( lineHeight( firstLine ) );
+
+ const TQFont &f = ref->font( firstLine );
+ int fontsize = f.pixelSize();
+
+ if ( va == SUB )
+ vpos += fontsize/5 + 1;
+ else if ( va == SUPER )
+ vpos -= fontsize/3 + 1;
+ else if ( va == TEXT_TOP ) {
+ vpos += baselinePosition( firstLine ) - (TQFontMetrics(f).ascent() + TQFontMetrics(f).leading()/2);
+ } else if ( va == MIDDLE ) {
+ TQRect b = TQFontMetrics(f).boundingRect('x');
+ vpos += -b.height()/2 - lineHeight( firstLine )/2 + baselinePosition( firstLine );
+ } else if ( va == TEXT_BOTTOM ) {
+ vpos += TQFontMetrics(f).descent() + TQFontMetrics(f).leading()/2;
+ if ( !isReplaced() )
+ vpos -= fontMetrics(firstLine).descent();
+ } else if ( va == BASELINE_MIDDLE )
+ vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
+ }
+ }
+ return vpos;
+}
+
+short RenderObject::lineHeight( bool firstLine ) const
+{
+ // Inline blocks are replaced elements. Otherwise, just pass off to
+ // the base class. If we're being queried as though we're the root line
+ // box, then the fact that we're an inline-block is irrelevant, and we behave
+ // just like a block.
+
+ if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout()))
+ return height()+marginTop()+marginBottom();
+
+ Length lh;
+ if( firstLine && hasFirstLine() ) {
+ RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+ if ( pseudoStyle )
+ lh = pseudoStyle->lineHeight();
+ }
+ else
+ lh = style()->lineHeight();
+
+ // its "unset", choose nice default
+ if ( lh.value() < 0 )
+ return style()->fontMetrics().lineSpacing();
+
+ if ( lh.isPercent() )
+ return lh.minWidth( style()->font().pixelSize() );
+
+ // its fixed
+ return lh.value();
+}
+
+short RenderObject::baselinePosition( bool firstLine ) const
+{
+ // Inline blocks are replaced elements. Otherwise, just pass off to
+ // the base class. If we're being queried as though we're the root line
+ // box, then the fact that we're an inline-block is irrelevant, and we behave
+ // just like a block.
+
+ if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout()))
+ return height()+marginTop()+marginBottom();
+
+ const TQFontMetrics &fm = fontMetrics( firstLine );
+ return fm.ascent() + ( lineHeight( firstLine) - fm.height() ) / 2;
+}
+
+void RenderObject::invalidateVerticalPositions()
+{
+ m_verticalPosition = PositionUndefined;
+ RenderObject *child = firstChild();
+ while( child ) {
+ child->invalidateVerticalPositions();
+ child = child->nextSibling();
+ }
+}
+
+void RenderObject::recalcMinMaxWidths()
+{
+ KHTMLAssert( m_recalcMinMax );
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
+#endif
+
+ RenderObject *child = firstChild();
+ int cmin=0;
+ int cmax=0;
+
+ while( child ) {
+ bool test = false;
+ if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
+ cmin = child->minWidth();
+ cmax = child->maxWidth();
+ test = true;
+ }
+ if ( child->m_recalcMinMax )
+ child->recalcMinMaxWidths();
+ if ( !child->m_minMaxKnown )
+ child->calcMinMaxWidth();
+ if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
+ m_minMaxKnown = false;
+ child = child->nextSibling();
+ }
+
+ // we need to recalculate, if the contains inline children, as the change could have
+ // happened somewhere deep inside the child tree
+ if ( ( !isInline() || isReplacedBlock() ) && childrenInline() )
+ m_minMaxKnown = false;
+
+ if ( !m_minMaxKnown )
+ calcMinMaxWidth();
+ m_recalcMinMax = false;
+}
+
+void RenderObject::scheduleRelayout(RenderObject *clippedObj)
+{
+ if (!isCanvas()) return;
+ KHTMLView *view = static_cast<RenderCanvas *>(this)->view();
+ if ( view )
+ view->scheduleRelayout(clippedObj);
+}
+
+
+void RenderObject::removeLeftoverAnonymousBoxes()
+{
+}
+
+InlineBox* RenderObject::createInlineBox(bool /*makePlaceHolderBox*/, bool /*isRootLineBox*/)
+{
+ KHTMLAssert(false);
+ return 0;
+}
+
+void RenderObject::getTextDecorationColors(int decorations, TQColor& underline, TQColor& overline,
+ TQColor& linethrough, bool quirksMode)
+{
+ RenderObject* curr = this;
+ do {
+ RenderStyle *st = curr->style();
+ int currDecs = st->textDecoration();
+ if (currDecs) {
+ if (currDecs & UNDERLINE) {
+ decorations &= ~UNDERLINE;
+ underline = st->color();
+ }
+ if (currDecs & OVERLINE) {
+ decorations &= ~OVERLINE;
+ overline = st->color();
+ }
+ if (currDecs & LINE_THROUGH) {
+ decorations &= ~LINE_THROUGH;
+ linethrough = st->color();
+ }
+ }
+ curr = curr->parent();
+ if (curr && curr->isRenderBlock() && curr->continuation())
+ curr = curr->continuation();
+ } while (curr && decorations && (!quirksMode || !curr->element() ||
+ (curr->element()->id() != ID_A && curr->element()->id() != ID_FONT)));
+
+ // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
+ if (decorations && curr) {
+ RenderStyle *st = curr->style();
+ if (decorations & UNDERLINE)
+ underline = st->color();
+ if (decorations & OVERLINE)
+ overline = st->color();
+ if (decorations & LINE_THROUGH)
+ linethrough = st->color();
+ }
+}
+
+int RenderObject::maximalOutlineSize(PaintAction p) const
+{
+ if (p != PaintActionOutline)
+ return 0;
+ return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();
+}
+
+void RenderObject::collectBorders(TQValueList<CollapsedBorderValue>& borderStyles)
+{
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+ curr->collectBorders(borderStyles);
+}
+
+bool RenderObject::flowAroundFloats() const
+{
+ return isReplaced() || hasOverflowClip() || style()->flowAroundFloats();
+}
+
+bool RenderObject::usesLineWidth() const
+{
+ // 1. All auto-width objects that avoid floats should always use lineWidth
+ // 2. For objects with a specified width, we match WinIE's behavior:
+ // (a) tables use contentWidth
+ // (b) <hr>s use lineWidth
+ // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
+ return (flowAroundFloats() && (style()->width().isVariable() || isHR() || (style()->htmlHacks() && !isTable())));
+}
+
+bool RenderObject::hasCounter(const TQString& counter) const
+{
+ if (style() && (!isText() || isCounter())) {
+ if (lookupCounter(counter)) return true;
+ if (style()->hasCounterReset(counter)) {
+ return true;
+ }
+ else if (style()->hasCounterIncrement(counter)) {
+ return true;
+ }
+ }
+ if (counter == "list-item") {
+ if (isListItem()) return true;
+ if (element() && (
+ element()->id() == ID_OL ||
+ element()->id() == ID_UL ||
+ element()->id() == ID_MENU ||
+ element()->id() == ID_DIR))
+ return true;
+ } else
+ if (counter == "-tdehtml-quotes" && isQuote()) {
+ return (static_cast<const RenderQuote*>(this)->quoteCount() != 0);
+ }
+ return false;
+}
+
+CounterNode* RenderObject::getCounter(const TQString& counter, bool view, bool counters)
+{
+// kdDebug( 6040 ) << renderName() << " getCounter(" << counter << ")" << endl;
+
+ if (!style()) return 0;
+
+ if (isText() && !isCounter()) return 0;
+
+ CounterNode *i = lookupCounter(counter);
+ if (i) return i;
+ int val = 0;
+
+ if (style()->hasCounterReset(counter) || isRoot()) {
+ i = new CounterReset(this);
+ val = style()->counterReset(counter);
+ if (style()->hasCounterIncrement(counter)) {
+ val += style()->counterIncrement(counter);
+ }
+// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
+ }
+ else
+ if (style()->hasCounterIncrement(counter)) {
+ i = new CounterNode(this);
+ val = style()->counterIncrement(counter);
+// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
+ }
+ else if (counter == "list-item") {
+ if (isListItem()) {
+ if (element() && element()->id() == ID_LI) {
+ DOMString v = static_cast<ElementImpl*>(element())->getAttribute(ATTR_VALUE);
+ if ( !v.isEmpty() ) {
+ i = new CounterReset(this);
+ val = v.toInt();
+// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
+ }
+ }
+ if (!i) {
+ i = new CounterNode(this);
+ val = 1;
+// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
+ }
+ }
+ else
+ if (element() && element()->id() == ID_OL) {
+ i = new CounterReset(this);
+ DOMString v = static_cast<ElementImpl*>(element())->getAttribute(ATTR_START);
+ if ( !v.isEmpty() )
+ val = v.toInt()-1;
+ else
+ val = 0;
+// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
+ }
+ else
+ if (element() &&
+ (element()->id() == ID_UL ||
+ element()->id() == ID_MENU||
+ element()->id() == ID_DIR))
+ {
+ i = new CounterReset(this);
+ val = 0;
+// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
+ }
+ }
+ else if (counter == "-tdehtml-quotes" && isQuote()) {
+ i = new CounterNode(this);
+ val = static_cast<RenderQuote*>(this)->quoteCount();
+ }
+
+ if (!i) {
+ i = new CounterNode(this);
+ val = 0;
+// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
+ }
+ i->setValue(val);
+ if (view) i->setIsVisual();
+ if (counters) i->setHasCounters();
+
+ insertCounter(counter, i);
+
+ if (!isRoot()) {
+ CounterNode *last=0, *current=0;
+ RenderObject *n = previousSibling();
+ while(n) {
+ if (n->hasCounter(counter)) {
+ current = n->getCounter(counter);
+ break;
+ }
+ else
+ n = n->previousSibling();
+ }
+ last = current;
+
+ CounterNode *sibling = current;
+ // counter-reset on same render-level is our counter-parent
+ if (last) {
+ // Found render-sibling, now search for later counter-siblings among its render-children
+ n = n->lastChild();
+ while (n) {
+ if (n->hasCounter(counter)) {
+ current = n->getCounter(counter);
+ if (last->parent() == current->parent() || sibling == current->parent()) {
+ last = current;
+ // If the current counter is not the last, search deeper
+ if (current->nextSibling()) {
+ n = n->lastChild();
+ continue;
+ }
+ else
+ break;
+ }
+ }
+ n = n->previousSibling();
+ }
+ if (sibling->isReset())
+ {
+ if (last != sibling)
+ sibling->insertAfter(i, last);
+ else
+ sibling->insertAfter(i, 0);
+ }
+ else if (last->parent())
+ last->parent()->insertAfter(i, last);
+ }
+ else if (parent()) {
+ // Nothing found among siblings, let our parent search
+ last = parent()->getCounter(counter, false);
+ if (last->isReset())
+ last->insertAfter(i, 0);
+ else if (last->parent())
+ last->parent()->insertAfter(i, last);
+ }
+ }
+
+ return i;
+}
+
+CounterNode* RenderObject::lookupCounter(const TQString& counter) const
+{
+ TQDict<tdehtml::CounterNode>* counters = document()->counters(this);
+ if (counters)
+ return counters->find(counter);
+ else
+ return 0;
+}
+
+void RenderObject::detachCounters()
+{
+ TQDict<tdehtml::CounterNode>* counters = document()->counters(this);
+ if (!counters) return;
+
+ TQDictIterator<tdehtml::CounterNode> i(*counters);
+
+ while (i.current()) {
+ (*i)->remove();
+ delete (*i);
+ ++i;
+ }
+ document()->removeCounters(this);
+}
+
+void RenderObject::insertCounter(const TQString& counter, CounterNode* val)
+{
+ TQDict<tdehtml::CounterNode>* counters = document()->counters(this);
+
+ if (!counters) {
+ counters = new TQDict<tdehtml::CounterNode>(11);
+ document()->setCounters(this, counters);
+ }
+
+ counters->insert(counter, val);
+}
+
+void RenderObject::updateWidgetMasks() {
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if ( curr->isWidget() && static_cast<RenderWidget*>(curr)->needsMask() ) {
+ TQWidget* w = static_cast<RenderWidget*>(curr)->widget();
+ if (!w)
+ return;
+ RenderLayer* l = curr->enclosingStackingContext();
+ TQRegion r = l ? l->getMask() : TQRegion();
+ int x,y;
+ if (!r.isNull() && curr->absolutePosition(x,y)) {
+ int pbx = curr->borderLeft()+curr->paddingLeft();
+ int pby = curr->borderTop()+curr->paddingTop();
+ x+= pbx;
+ y+= pby;
+ r = r.intersect(TQRect(x,y,
+ curr->width()-pbx-curr->borderRight()-curr->paddingRight(),
+ curr->height()-pby-curr->borderBottom()-curr->paddingBottom()));
+#ifdef MASK_DEBUG
+ TQMemArray<TQRect> ar = r.rects();
+ kdDebug(6040) << "|| Setting widget mask for " << curr->information() << endl;
+ for (int i = 0; i < ar.size() ; ++i) {
+ kdDebug(6040) << " " << ar[i] << endl;
+ }
+#endif
+ r.translate(-x,-y);
+ w->setMask(r);
+ } else {
+ w->clearMask();
+ }
+ }
+ else if (!curr->layer() || !curr->layer()->isStackingContext())
+ curr->updateWidgetMasks();
+
+ }
+}
+
+TQRegion RenderObject::visibleFlowRegion(int x, int y) const
+{
+ TQRegion r;
+ for (RenderObject* ro=firstChild();ro;ro=ro->nextSibling()) {
+ if( !ro->layer() && !ro->isInlineFlow() && ro->style()->visibility() == VISIBLE) {
+ const RenderStyle *s = ro->style();
+ if (ro->isRelPositioned())
+ static_cast<const RenderBox*>(ro)->relativePositionOffset(x,y);
+ if ( s->backgroundImage() || s->backgroundColor().isValid() || s->hasBorder() )
+ r += TQRect(x + ro->effectiveXPos(),y + ro->effectiveYPos(), ro->effectiveWidth(), ro->effectiveHeight());
+ else
+ r += ro->visibleFlowRegion(x+ro->xPos(), y+ro->yPos());
+ }
+ }
+ return r;
+}
+
+#undef RED_LUMINOSITY
+#undef GREEN_LUMINOSITY
+#undef BLUE_LUMINOSITY
+#undef INTENSITY_FACTOR
+#undef LIGHT_FACTOR
+#undef LUMINOSITY_FACTOR
+
+#undef MAX_COLOR
+#undef COLOR_DARK_THRESHOLD
+#undef COLOR_LIGHT_THRESHOLD
+
+#undef COLOR_LITE_BS_FACTOR
+#undef COLOR_LITE_TS_FACTOR
+
+#undef COLOR_DARK_BS_FACTOR
+#undef COLOR_DARK_TS_FACTOR
+
+#undef LIGHT_GRAY
+#undef DARK_GRAY
+
diff --git a/tdehtml/rendering/render_object.h b/tdehtml/rendering/render_object.h
new file mode 100644
index 000000000..9dd064932
--- /dev/null
+++ b/tdehtml/rendering/render_object.h
@@ -0,0 +1,866 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2002-2003 Apple Computer, Inc.
+ * (C) 2004 Allan Sandfeld Jensen
+ *
+ * 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 render_object_h
+#define render_object_h
+
+#include <tqcolor.h>
+#include <tqrect.h>
+#include <assert.h>
+#include <tqvaluelist.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include "xml/dom_docimpl.h"
+#include "misc/tdehtmllayout.h"
+#include "misc/loader_client.h"
+#include "misc/helper.h"
+#include "rendering/render_style.h"
+
+class TQPainter;
+class TQTextStream;
+class CSSStyle;
+class KHTMLView;
+
+#ifndef NDEBUG
+#define KHTMLAssert( x ) if( !(x) ) { \
+ const RenderObject *o = this; while( o->parent() ) o = o->parent(); \
+ o->printTree(); \
+ tqDebug(" this object = %p, %s", (void*) this, kdBacktrace().latin1() ); \
+ assert( x ); \
+}
+#else
+#define KHTMLAssert( x )
+#endif
+
+/*
+ * The painting of a layer occurs in three distinct phases. Each phase involves
+ * a recursive descent into the layer's render objects. The first phase is the background phase.
+ * The backgrounds and borders of all blocks are painted. Inlines are not painted at all.
+ * Floats must paint above block backgrounds but entirely below inline content that can overlap them.
+ * In the foreground phase, all inlines are fully painted. Inline replaced elements will get all
+ * three phases invoked on them during this phase.
+ */
+
+typedef enum {
+ PaintActionElementBackground = 0,
+ PaintActionChildBackground,
+ PaintActionChildBackgrounds,
+ PaintActionFloat,
+ PaintActionForeground,
+ PaintActionOutline,
+ PaintActionSelection,
+ PaintActionCollapsedTableBorders
+} PaintAction;
+
+typedef enum {
+ HitTestAll = 0,
+ HitTestSelfOnly = 1,
+ HitTestChildrenOnly = 2
+} HitTestAction;
+
+typedef enum {
+ PageBreakNormal = 0, // all rules apply
+ PageBreakHarder = 1, // page-break-inside: avoid is ignored
+ PageBreakForced = 2 // page-break-after/before: avoid, orphans and widows ignored
+} PageBreakLevel;
+
+typedef enum {
+ LowPriority = 0,
+ NormalPriority = 1,
+ HighPriority = 2,
+ RealtimePriority = 3
+} Priority;
+
+inline PageBreakLevel operator| (PageBreakLevel a, PageBreakLevel b) {
+ if (a == PageBreakForced || b == PageBreakForced)
+ return PageBreakForced;
+ if (a == PageBreakHarder || b == PageBreakHarder)
+ return PageBreakHarder;
+ return PageBreakNormal;
+}
+
+namespace DOM {
+ class HTMLAreaElementImpl;
+ class DOMString;
+ class NodeImpl;
+ class DocumentImpl;
+ class ElementImpl;
+ class EventImpl;
+}
+
+namespace tdehtml {
+ class RenderFlow;
+ class RenderStyle;
+ class RenderTable;
+ class CachedObject;
+ class RenderObject;
+ class RenderCanvas;
+ class RenderText;
+ class RenderFrameSet;
+ class RenderArena;
+ class RenderLayer;
+ class RenderBlock;
+ class InlineBox;
+ class InlineFlowBox;
+ class CounterNode;
+
+/**
+ * Base Class for all rendering tree objects.
+ */
+class RenderObject : public CachedObjectClient
+{
+ RenderObject(const RenderObject&);
+ RenderObject& operator=(const RenderObject&);
+public:
+
+ RenderObject(DOM::NodeImpl* node);
+ virtual ~RenderObject();
+
+ RenderObject *parent() const { return m_parent; }
+
+ RenderObject *previousSibling() const { return m_previous; }
+ RenderObject *nextSibling() const { return m_next; }
+
+ virtual RenderObject *firstChild() const { return 0; }
+ virtual RenderObject *lastChild() const { return 0; }
+
+ RenderObject *nextRenderer() const;
+ RenderObject *previousRenderer() const;
+
+ virtual bool childAllowed() const { return false; }
+ virtual int borderTopExtra() const { return 0; }
+ virtual int borderBottomExtra() const { return 0; }
+
+ virtual RenderLayer* layer() const { return 0; }
+ RenderLayer* enclosingLayer() const;
+ RenderLayer* enclosingStackingContext() const;
+ void addLayers(RenderLayer* parentLayer, RenderObject* newObject);
+ void removeLayers(RenderLayer* parentLayer);
+ void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
+ RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
+ bool checkParent=true);
+ virtual void positionChildLayers() { }
+ virtual bool requiresLayer() const {
+ return isRoot()/* ### */ || isPositioned() || isRelPositioned() || hasOverflowClip();
+ }
+
+ // ### rename to overflowClipRect and clipRect
+ virtual TQRect getOverflowClipRect(int /*tx*/, int /*ty*/)
+ { return TQRect(0,0,0,0); }
+ virtual TQRect getClipRect(int /*tx*/, int /*ty*/) { return TQRect(0,0,0,0); }
+ bool hasClip() const { return isPositioned() && style()->hasClip(); }
+ bool hasOverflowClip() const { return m_hasOverflowClip; }
+
+ bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
+ bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); }
+ bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); }
+
+ virtual int getBaselineOfFirstLineBox() { return -1; } // Tables and blocks implement this.
+ virtual InlineFlowBox* getFirstLineBox() { return 0; } // Tables and blocks implement this.
+
+ // Whether or not a positioned element requires normal flow x/y to be computed
+ // to determine its position.
+ bool hasStaticX() const;
+ bool hasStaticY() const;
+
+ // Linear tree traversal
+ RenderObject *objectBelow() const;
+ RenderObject *objectAbove() const;
+
+ // Returns if an object has counter-increment or counter-reset
+ bool hasCounter(const TQString& counter) const;
+ // Calculates the value of the counter
+ CounterNode* getCounter(const TQString& counter, bool view = false, bool counters = false);
+ // Detaches all counterNodes
+ void detachCounters();
+
+
+protected:
+ // Helper functions for counter-cache
+ void insertCounter(const TQString& counter, CounterNode* value);
+ CounterNode* lookupCounter(const TQString& counter) const;
+
+public:
+ //////////////////////////////////////////
+ // RenderObject tree manipulation
+ virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
+ void removeChild(RenderObject *oldChild);
+
+ // raw tree manipulation
+ virtual RenderObject* removeChildNode(RenderObject* child);
+ virtual void appendChildNode(RenderObject* child);
+ virtual void insertChildNode(RenderObject* child, RenderObject* before);
+ //////////////////////////////////////////
+
+ //////////////////////////////////////////
+ // Helper functions. Dangerous to use!
+ void setPreviousSibling(RenderObject *previous) { m_previous = previous; }
+ void setNextSibling(RenderObject *next) { m_next = next; }
+ void setParent(RenderObject *parent) { m_parent = parent; }
+ //////////////////////////////////////////
+
+public:
+ virtual const char *renderName() const { return "RenderObject"; }
+#ifdef ENABLE_DUMP
+ TQString information() const;
+ virtual void printTree(int indent=0) const;
+ virtual void dump(TQTextStream &stream, const TQString &ind = TQString::null) const;
+#endif
+
+ static RenderObject *createObject(DOM::NodeImpl* node, RenderStyle* style);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed on all render objects.
+ void* operator new(size_t sz);
+
+public:
+ RenderArena* renderArena() const;
+ virtual RenderFlow* continuation() const { return 0; }
+ virtual bool isInlineContinuation() const { return false; }
+
+
+ bool isRoot() const { return m_isRoot && !m_isAnonymous; }
+ void setIsRoot(bool b) { m_isRoot = b; }
+ bool isHR() const;
+ // some helper functions...
+ virtual bool isRenderBlock() const { return false; }
+ virtual bool isRenderInline() const { return false; }
+ virtual bool isInlineFlow() const { return false; }
+ virtual bool isBlockFlow() const { return false; }
+ virtual bool isInlineBlockOrInlineTable() const { return false; }
+ virtual bool childrenInline() const { return false; }
+ virtual bool isBox() const { return false; }
+ virtual bool isRenderReplaced() const { return false; }
+
+ virtual bool isGlyph() const { return false; }
+ virtual bool isCounter() const { return false; }
+ virtual bool isQuote() const { return false; }
+ virtual bool isListItem() const { return false; }
+ virtual bool isListMarker() const { return false; }
+ virtual bool isCanvas() const { return false; }
+ virtual bool isBR() const { return false; }
+ virtual bool isTableCell() const { return false; }
+ virtual bool isTableRow() const { return false; }
+ virtual bool isTableSection() const { return false; }
+ virtual bool isTableCol() const { return false; }
+ virtual bool isTable() const { return false; }
+ virtual bool isWidget() const { return false; }
+ virtual bool isBody() const { return false; }
+ virtual bool isFormElement() const { return false; }
+ virtual bool isFrameSet() const { return false; }
+ virtual bool isApplet() const { return false; }
+
+ bool isHTMLMarquee() const;
+ bool isWordBreak() const;
+
+ bool isAnonymous() const { return m_isAnonymous; }
+ void setIsAnonymous(bool b) { m_isAnonymous = b; }
+ bool isAnonymousBlock() const { return isAnonymous() && style()->display() == BLOCK && node()->isDocumentNode(); }
+ bool isPseudoAnonymous() const { return isAnonymous() && !node()->isDocumentNode(); }
+
+ bool isFloating() const { return m_floating; }
+ bool isPositioned() const { return m_positioned; }
+ bool isRelPositioned() const { return m_relPositioned; }
+ bool isText() const { return m_isText; }
+ bool isInline() const { return m_inline; }
+ bool isCompact() const { return style()->display() == COMPACT; } // compact
+ bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object
+ bool mouseInside() const;
+ bool isReplaced() const { return m_replaced; }
+ bool isReplacedBlock() const { return isInline() && isReplaced() && isRenderBlock(); }
+ bool shouldPaintBackgroundOrBorder() const { return m_paintBackground; }
+ bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; }
+ bool markedForRepaint() const { return m_markedForRepaint; }
+ void setMarkedForRepaint(bool m) { m_markedForRepaint = m; }
+ bool selfNeedsLayout() const { return m_needsLayout; }
+ bool posChildNeedsLayout() const { return m_posChildNeedsLayout; }
+ bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; }
+ bool minMaxKnown() const{ return m_minMaxKnown; }
+ bool overhangingContents() const { return m_overhangingContents; }
+ bool hasFirstLine() const { return m_hasFirstLine; }
+ bool isSelectionBorder() const { return m_isSelectionBorder; }
+ bool recalcMinMax() const { return m_recalcMinMax; }
+
+ RenderCanvas* canvas() const;
+ // don't even think about making this method virtual!
+ DOM::DocumentImpl* document() const;
+ DOM::NodeImpl* element() const { return isAnonymous() ? 0L : m_node; }
+ DOM::NodeImpl* node() const { return m_node; }
+
+ /**
+ * returns the object containing this one. can be different from parent for
+ * positioned elements
+ */
+ RenderObject *container() const;
+
+ void setOverhangingContents(bool p=true);
+ void markContainingBlocksForLayout();
+ void dirtyFormattingContext( bool checkContainer );
+ void repaintDuringLayout();
+ void setNeedsLayout(bool b, bool markParents = true);
+ void setChildNeedsLayout(bool b, bool markParents = true);
+ void setMinMaxKnown(bool b=true) {
+ m_minMaxKnown = b;
+ if ( !b ) {
+ RenderObject *o = this;
+ RenderObject *root = this;
+ while( o ) { // ### && !o->m_recalcMinMax ) {
+ o->m_recalcMinMax = true;
+ root = o;
+ o = o->m_parent;
+ }
+ }
+ }
+ void setNeedsLayoutAndMinMaxRecalc() {
+ setMinMaxKnown(false);
+ setNeedsLayout(true);
+ }
+ void setPositioned(bool b=true) { m_positioned = b; }
+ void setRelPositioned(bool b=true) { m_relPositioned = b; }
+ void setFloating(bool b=true) { m_floating = b; }
+ void setInline(bool b=true) { m_inline = b; }
+ void setMouseInside(bool b=true) { m_mouseInside = b; }
+ void setShouldPaintBackgroundOrBorder(bool b=true) { m_paintBackground = b; }
+ void setRenderText() { m_isText = true; }
+ void setReplaced(bool b=true) { m_replaced = b; }
+ void setHasOverflowClip(bool b = true) { m_hasOverflowClip = b; }
+ void setIsSelectionBorder(bool b=true) { m_isSelectionBorder = b; }
+
+ void scheduleRelayout(RenderObject *clippedObj = 0);
+
+ void updateBackgroundImages(RenderStyle* oldStyle);
+
+ virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
+
+ virtual short lineHeight( bool firstLine ) const;
+ virtual short verticalPositionHint( bool firstLine ) const;
+ virtual short baselinePosition( bool firstLine ) const;
+ short getVerticalPosition( bool firstLine, RenderObject* ref=0 ) const;
+
+ /*
+ * Print the object and its children, clipped by (x|y|w|h).
+ * (tx|ty) is the calculated position of the parent
+ */
+ struct PaintInfo {
+ PaintInfo(TQPainter* _p, const TQRect& _r, PaintAction _phase)
+ : p(_p), r(_r), phase(_phase), outlineObjects(0) {}
+ ~PaintInfo() { delete outlineObjects; }
+ TQPainter* p;
+ TQRect r;
+ PaintAction phase;
+ TQValueList<RenderFlow *>* outlineObjects; // used to list which outlines should be painted by a block with inline children
+ };
+ virtual void paint( PaintInfo& i, int tx, int ty);
+
+ void paintBorder(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin=true, bool end=true);
+ void paintOutline(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style);
+
+ virtual void paintBoxDecorations(PaintInfo&, int /*_tx*/, int /*_ty*/) {}
+
+ virtual void paintBackgroundExtended(TQPainter* /*p*/, const TQColor& /*c*/, const BackgroundLayer */*bgLayer*/,
+ int /*clipy*/, int /*cliph*/, int /*_tx*/, int /*_ty*/,
+ int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/ ) {}
+
+
+ /*
+ * This function calculates the minimum & maximum width that the object
+ * can be set to.
+ *
+ * when the Element calls setMinMaxKnown(true), calcMinMaxWidth() will
+ * be no longer called.
+ *
+ * when a element has a fixed size, m_minWidth and m_maxWidth should be
+ * set to the same value. This has the special meaning that m_width,
+ * contains the actual value.
+ *
+ * assumes calcMinMaxWidth has already been called for all children.
+ */
+ virtual void calcMinMaxWidth() { }
+
+ /*
+ * Does the min max width recalculations after changes.
+ */
+ void recalcMinMaxWidths();
+
+ /*
+ * Calculates the actual width of the object (only for non inline
+ * objects)
+ */
+ virtual void calcWidth() {}
+
+ /*
+ * Calculates the actual width of the object (only for non inline
+ * objects)
+ */
+ virtual void calcHeight() {}
+
+ /*
+ * This function should cause the Element to calculate its
+ * width and height and the layout of its content
+ *
+ * when the Element calls setNeedsLayout(false), layout() is no
+ * longer called during relayouts, as long as there is no
+ * style sheet change. When that occurs, m_needsLayout will be
+ * set to true and the Element receives layout() calls
+ * again.
+ */
+ virtual void layout() = 0;
+
+ /* This function performs a layout only if one is needed. */
+ void layoutIfNeeded() { if (needsLayout()) layout(); }
+
+ // used for element state updates that can not be fixed with a
+ // repaint and do not need a relayout
+ virtual void updateFromElement() {}
+
+ // Called immediately after render-object is inserted
+ virtual void attach() { m_attached = true; }
+ bool attached() { return m_attached; }
+ // The corresponding closing element has been parsed. ### remove me
+ virtual void close() { }
+
+ virtual int availableHeight() const { return 0; }
+
+ // Whether or not the element shrinks to its max width (rather than filling the width
+ // of a containing block). HTML4 buttons, legends, and floating/compact elements do this.
+ bool sizesToMaxWidth() const;
+
+ /*
+ * NeesPageClear indicates the object crossed a page-break but could not break itself and now
+ * needs to be moved clear by its parent.
+ */
+ void setNeedsPageClear(bool b = true) { m_needsPageClear = b; }
+ virtual bool needsPageClear() const { return m_needsPageClear; }
+
+ /*
+ * ContainsPageBreak indicates the object contains a clean page-break.
+ * ### should be removed and replaced with (crossesPageBreak && !needsPageClear)
+ */
+ void setContainsPageBreak(bool b = true) { m_containsPageBreak = b; }
+ virtual bool containsPageBreak() const { return m_containsPageBreak; }
+
+ virtual int pageTopAfter(int y) const { if (parent()) return parent()->pageTopAfter(y); else return 0; }
+
+ virtual int crossesPageBreak(int top, int bottom) const
+ { if (parent()) return parent()->crossesPageBreak(top, bottom); else return 0; }
+
+ // Checks if a page-break before child is possible at the given page-break level
+ // false means the child should attempt the break self.
+ virtual bool canClear(RenderObject */*child*/, PageBreakLevel level)
+ { if (parent()) return parent()->canClear(this, level); else return false; }
+
+ void setAfterPageBreak(bool b = true) { m_afterPageBreak = b; };
+ void setBeforePageBreak(bool b = true) { m_beforePageBreak = b; };
+ virtual bool afterPageBreak() const { return m_afterPageBreak; }
+ virtual bool beforePageBreak() const { return m_beforePageBreak; }
+
+ // does a query on the rendertree and finds the innernode
+ // and overURL for the given position
+ // if readonly == false, it will recalc hover styles accordingly
+ class NodeInfo
+ {
+ friend class RenderImage;
+ friend class RenderFlow;
+ friend class RenderInline;
+ friend class RenderText;
+ friend class RenderWidget;
+ friend class RenderObject;
+ friend class RenderFrameSet;
+ friend class RenderLayer;
+ friend class DOM::HTMLAreaElementImpl;
+ public:
+ NodeInfo(bool readonly, bool active)
+ : m_innerNode(0), m_innerNonSharedNode(0), m_innerURLElement(0), m_readonly(readonly), m_active(active)
+ { }
+
+ DOM::NodeImpl* innerNode() const { return m_innerNode; }
+ DOM::NodeImpl* innerNonSharedNode() const { return m_innerNonSharedNode; }
+ DOM::NodeImpl* URLElement() const { return m_innerURLElement; }
+ bool readonly() const { return m_readonly; }
+ bool active() const { return m_active; }
+
+ private:
+ void setInnerNode(DOM::NodeImpl* n) { m_innerNode = n; }
+ void setInnerNonSharedNode(DOM::NodeImpl* n) { m_innerNonSharedNode = n; }
+ void setURLElement(DOM::NodeImpl* n) { m_innerURLElement = n; }
+
+ DOM::NodeImpl* m_innerNode;
+ DOM::NodeImpl* m_innerNonSharedNode;
+ DOM::NodeImpl* m_innerURLElement;
+ bool m_readonly;
+ bool m_active;
+ };
+
+ /** contains stateful information for a checkSelectionPoint call
+ */
+ struct SelPointState {
+ /** last node that was before the current position */
+ DOM::NodeImpl *m_lastNode;
+ /** offset of last node */
+ long m_lastOffset;
+ /** true when the last node had the result SelectionAfterInLine */
+ bool m_afterInLine;
+
+ SelPointState() : m_lastNode(0), m_lastOffset(0), m_afterInLine(false)
+ {}
+ };
+
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*&, int & offset,
+ SelPointState & );
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction, bool inside = false);
+ void setInnerNode(NodeInfo& info);
+
+ // set the style of the object.
+ virtual void setStyle(RenderStyle *style);
+
+ // returns the containing block level element for this element.
+ RenderBlock *containingBlock() const;
+
+ // return just the width of the containing block
+ virtual short containingBlockWidth() const;
+ // return just the height of the containing block
+ virtual int containingBlockHeight() const;
+
+ // size of the content area (box size minus padding/border)
+ virtual short contentWidth() const { return 0; }
+ virtual int contentHeight() const { return 0; }
+
+ // intrinsic extend of replaced elements. undefined otherwise
+ virtual short intrinsicWidth() const { return 0; }
+ virtual int intrinsicHeight() const { return 0; }
+
+ // relative to parent node
+ virtual void setPos( int /*xPos*/, int /*yPos*/ ) { }
+ virtual void setWidth( int /*width*/ ) { }
+ virtual void setHeight( int /*height*/ ) { }
+
+ virtual int xPos() const { return 0; }
+ virtual int yPos() const { return 0; }
+
+ /** the position of the object from where it begins drawing, including
+ * its negative overflow
+ */
+ int effectiveXPos() const { return xPos() + (hasOverflowClip() ? 0 : overflowLeft()); }
+
+ /** the position of the object from where it begins drawing, including
+ * its negative overflow
+ */
+ int effectiveYPos() const { return yPos() + (hasOverflowClip() ? -borderTopExtra() : kMin(overflowTop(), -borderTopExtra())); }
+
+ /** Leftmost coordinate of this inline element relative to containing
+ * block. Always zero for non-inline elements.
+ */
+ virtual int inlineXPos() const { return 0; }
+ /** Topmost coordinate of this inline element relative to containing
+ * block. Always zero for non-inline elements.
+ */
+ virtual int inlineYPos() const { return 0; }
+
+ // calculate client position of box
+ virtual bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool fixed = false) const;
+
+ // width and height are without margins but include paddings and borders
+ virtual short width() const { return 0; }
+ virtual int height() const { return 0; }
+
+ // The height of a block when you include overflow spillage out of
+ // the bottom of the block (e.g., a <div style="height:25px"> that
+ // has a 100px tall image inside it would have an overflow height
+ // of borderTop() + paddingTop() + 100px.
+ virtual int overflowHeight() const { return height(); }
+ virtual int overflowWidth() const { return width(); }
+ // how much goes over the left hand side (0 or a negative number)
+ virtual int overflowTop() const { return 0; }
+ virtual int overflowLeft() const { return 0; }
+
+ /**
+ * Returns the height that is effectively considered when contemplating the
+ * object as a whole -- usually the overflow height, or the height if clipped.
+ */
+ int effectiveHeight() const { return hasOverflowClip() ? height() + borderTopExtra() + borderBottomExtra() :
+ kMax(overflowHeight() - overflowTop(), height() + borderTopExtra() + borderBottomExtra()); }
+ /**
+ * Returns the width that is effectively considered when contemplating the
+ * object as a whole -- usually the overflow width, or the width if clipped.
+ */
+ int effectiveWidth() const { return hasOverflowClip() ? width() : overflowWidth() - overflowLeft(); }
+
+ // IE extensions, heavily used in ECMA
+ virtual short offsetWidth() const { return width(); }
+ virtual int offsetHeight() const { return height() + borderTopExtra() + borderBottomExtra(); }
+ virtual int offsetLeft() const;
+ virtual int offsetTop() const;
+ virtual RenderObject* offsetParent() const;
+ short clientWidth() const;
+ int clientHeight() const;
+ short scrollWidth() const;
+ int scrollHeight() const;
+
+ virtual bool isSelfCollapsingBlock() const { return false; }
+ short collapsedMarginTop() const { return maxTopMargin(true)-maxTopMargin(false); }
+ short collapsedMarginBottom() const { return maxBottomMargin(true)-maxBottomMargin(false); }
+
+ virtual bool isTopMarginQuirk() const { return false; }
+ virtual bool isBottomMarginQuirk() const { return false; }
+ virtual short maxTopMargin(bool positive) const
+ { return positive ? kMax( int( marginTop() ), 0 ) : - kMin( int( marginTop() ), 0 ); }
+ virtual short maxBottomMargin(bool positive) const
+ { return positive ? kMax( int( marginBottom() ), 0 ) : - kMin( int( marginBottom() ), 0 ); }
+
+ virtual short marginTop() const { return 0; }
+ virtual short marginBottom() const { return 0; }
+ virtual short marginLeft() const { return 0; }
+ virtual short marginRight() const { return 0; }
+
+ virtual int paddingTop() const;
+ virtual int paddingBottom() const;
+ virtual int paddingLeft() const;
+ virtual int paddingRight() const;
+
+ virtual int borderTop() const { return style()->borderTopWidth(); }
+ virtual int borderBottom() const { return style()->borderBottomWidth(); }
+ virtual int borderLeft() const { return style()->borderLeftWidth(); }
+ virtual int borderRight() const { return style()->borderRightWidth(); }
+
+ virtual short minWidth() const { return 0; }
+ virtual int maxWidth() const { return 0; }
+
+ RenderStyle* style() const { return m_style; }
+ RenderStyle* style( bool firstLine ) const {
+ RenderStyle *s = m_style;
+ if( firstLine && hasFirstLine() ) {
+ RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+ if ( pseudoStyle )
+ s = pseudoStyle;
+ }
+ return s;
+ }
+
+ void getTextDecorationColors(int decorations, TQColor& underline, TQColor& overline,
+ TQColor& linethrough, bool quirksMode=false);
+
+ enum BorderSide {
+ BSTop, BSBottom, BSLeft, BSRight
+ };
+ void drawBorder(TQPainter *p, int x1, int y1, int x2, int y2, BorderSide s,
+ TQColor c, const TQColor& textcolor, EBorderStyle style,
+ int adjbw1, int adjbw2, bool invalidisInvert = false);
+
+ // Used by collapsed border tables.
+ virtual void collectBorders(TQValueList<CollapsedBorderValue>& borderStyles);
+
+ // force a complete repaint
+ virtual void repaint(Priority p = NormalPriority) { if(m_parent) m_parent->repaint(p); }
+ virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
+
+ virtual unsigned int length() const { return 1; }
+
+ virtual bool isHidden() const { return isFloating() || isPositioned(); }
+
+ // Special objects are objects that are neither really inline nor blocklevel
+ bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); };
+ virtual bool hasOverhangingFloats() const { return false; }
+ virtual bool hasFloats() const { return false; }
+ virtual bool containsFloat(RenderObject* /*o*/) const { return false; }
+ virtual void markAllDescendantsWithFloatsForLayout(RenderObject* /*floatToRemove*/ = 0) {}
+
+ bool flowAroundFloats() const;
+ bool usesLineWidth() const;
+
+ // positioning of inline children (bidi)
+ virtual void position(InlineBox*, int, int, bool) {}
+// virtual void position(int, int, int, int, int, bool, bool, int) {}
+
+ // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
+ int maximalOutlineSize(PaintAction p) const;
+
+ enum SelectionState {
+ SelectionNone,
+ SelectionStart,
+ SelectionInside,
+ SelectionEnd,
+ SelectionBoth
+ };
+
+ virtual SelectionState selectionState() const { return SelectionNone;}
+ virtual void setSelectionState(SelectionState) {}
+
+ /**
+ * Flags which influence the appearence and position
+ * @param CFOverride input overrides existing character, caret should be
+ * cover the whole character
+ * @param CFOutside coordinates are to be interpreted outside of the
+ * render object
+ * @param CFOutsideEnd coordinates are to be interpreted at the outside
+ * end of the render object (only valid if CFOutside is also set)
+ */
+ enum CaretFlags { CFOverride = 0x01, CFOutside = 0x02, CFOutsideEnd = 0x04 };
+
+ /**
+ * Returns the content coordinates of the caret within this render object.
+ * @param offset zero-based offset determining position within the render object.
+ * @param flags combination of enum CaretFlags
+ * @param _x returns the left coordinate
+ * @param _y returns the top coordinate
+ * @param width returns the caret's width
+ * @param height returns the caret's height
+ */
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+
+ // returns the lowest position of the lowest object in that particular object.
+ // This 'height' is relative to the topleft of the margin box of the object.
+ // Implemented in RenderFlow.
+ virtual int lowestPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
+ virtual int rightmostPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
+ virtual int leftmostPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
+ virtual int highestPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
+
+ // recursively invalidate current layout
+ // unused: void invalidateLayout();
+
+ virtual void calcVerticalMargins() {}
+ void removeFromObjectLists();
+
+ virtual void deleteInlineBoxes(RenderArena* arena=0) {(void)arena;}
+ virtual void detach( );
+
+ void setDoNotDelete(bool b) { m_doNotDelete = b; }
+ bool doNotDelete() const { return m_doNotDelete; }
+
+ const TQFont &font(bool firstLine) const {
+ return style( firstLine )->font();
+ }
+
+ const TQFontMetrics &fontMetrics(bool firstLine) const {
+ return style( firstLine )->fontMetrics();
+ }
+
+ /** returns the lowest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns 0 by default.
+ */
+ virtual long minOffset() const { return 0; }
+ /** returns the highest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns 0 by default, as generic elements are considered to have no
+ * width.
+ */
+ virtual long maxOffset() const { return 0; }
+
+ virtual void setPixmap(const TQPixmap &, const TQRect&, CachedImage *);
+
+ TQRegion visibleFlowRegion(int x, int y) const;
+
+protected:
+ virtual void selectionStartEnd(int& spos, int& epos);
+
+ virtual TQRect viewRect() const;
+ void remove();
+ void invalidateVerticalPositions();
+ bool attemptDirectLayerTranslation();
+ void updateWidgetMasks();
+
+ virtual void removeLeftoverAnonymousBoxes();
+
+ void arenaDelete(RenderArena *arena);
+
+private:
+ RenderStyle* m_style;
+ DOM::NodeImpl* m_node;
+ RenderObject *m_parent;
+ RenderObject *m_previous;
+ RenderObject *m_next;
+
+ short m_verticalPosition;
+
+ bool m_needsLayout : 1;
+ bool m_normalChildNeedsLayout : 1;
+ bool m_markedForRepaint : 1;
+ bool m_posChildNeedsLayout : 1;
+
+ bool m_minMaxKnown : 1;
+ bool m_floating : 1;
+
+ bool m_positioned : 1;
+ bool m_overhangingContents : 1;
+ bool m_relPositioned : 1;
+ bool m_paintBackground : 1; // if the box has something to paint in the
+ // background painting phase (background, border, etc)
+
+ bool m_isAnonymous : 1;
+ bool m_recalcMinMax : 1;
+ bool m_isText : 1;
+ bool m_inline : 1;
+ bool m_attached : 1;
+
+ bool m_replaced : 1;
+ bool m_mouseInside : 1;
+ bool m_hasFirstLine : 1;
+ bool m_isSelectionBorder : 1;
+
+ bool m_isRoot : 1;
+
+ bool m_beforePageBreak : 1;
+ bool m_afterPageBreak : 1;
+
+ bool m_needsPageClear : 1;
+ bool m_containsPageBreak : 1;
+
+ bool m_hasOverflowClip : 1;
+
+ bool m_doNotDelete : 1; // This object should not be auto-deleted
+
+ // ### we have 16 + 26 bits.
+
+
+ void arenaDelete(RenderArena *arena, void *objectBase);
+
+ friend class RenderLayer;
+ friend class RenderListItem;
+ friend class RenderContainer;
+ friend class RenderCanvas;
+};
+
+
+enum VerticalPositionHint {
+ PositionTop = -0x4000,
+ PositionBottom = 0x4000,
+ PositionUndefined = 0x3fff
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/rendering/render_replaced.cpp b/tdehtml/rendering/render_replaced.cpp
new file mode 100644
index 000000000..42fce027e
--- /dev/null
+++ b/tdehtml/rendering/render_replaced.cpp
@@ -0,0 +1,940 @@
+/**
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) 2004 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.
+ *
+ */
+#include "render_replaced.h"
+#include "render_layer.h"
+#include "render_canvas.h"
+#include "render_line.h"
+
+#include "render_arena.h"
+
+#include <assert.h>
+#include <tqwidget.h>
+#include <tqpainter.h>
+#include <tqevent.h>
+#include <tqapplication.h>
+#include <tqlineedit.h>
+#include <kglobalsettings.h>
+#include <tqobjectlist.h>
+#include <tqvaluevector.h>
+
+#include "tdehtml_ext.h"
+#include "tdehtmlview.h"
+#include "xml/dom2_eventsimpl.h"
+#include "tdehtml_part.h"
+#include "xml/dom_docimpl.h"
+#include <kdebug.h>
+
+bool tdehtml::allowWidgetPaintEvents = false;
+
+using namespace tdehtml;
+using namespace DOM;
+
+
+RenderReplaced::RenderReplaced(DOM::NodeImpl* node)
+ : RenderBox(node)
+{
+ // init RenderObject attributes
+ setReplaced(true);
+
+ m_intrinsicWidth = 300;
+ m_intrinsicHeight = 150;
+}
+
+void RenderReplaced::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown());
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "RenderReplaced::calcMinMaxWidth() known=" << minMaxKnown() << endl;
+#endif
+
+ m_width = calcReplacedWidth();
+ m_width = calcBoxWidth( m_width );
+
+ if ( style()->width().isPercent() || style()->height().isPercent() ||
+ style()->maxWidth().isPercent() || style()->maxHeight().isPercent() ||
+ style()->minWidth().isPercent() || style()->minHeight().isPercent() ) {
+ m_minWidth = 0;
+ m_maxWidth = m_width;
+ }
+ else
+ m_minWidth = m_maxWidth = m_width;
+
+ setMinMaxKnown();
+}
+
+void RenderReplaced::position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/)
+{
+ setPos( box->xPos(), box->yPos() );
+}
+
+// -----------------------------------------------------------------------------
+
+RenderWidget::RenderWidget(DOM::NodeImpl* node)
+ : RenderReplaced(node)
+{
+ m_widget = 0;
+ // a widget doesn't support being anonymous
+ assert(!isAnonymous());
+ m_view = node->getDocument()->view();
+ m_arena.reset(renderArena());
+ m_resizePending = false;
+ m_discardResizes = false;
+ m_isKHTMLWidget = false;
+ m_needsMask = false;
+
+ // this is no real reference counting, its just there
+ // to make sure that we're not deleted while we're recursed
+ // in an eventFilter of the widget
+ ref();
+}
+
+void RenderWidget::detach()
+{
+ remove();
+ deleteInlineBoxes();
+
+ if ( m_widget ) {
+ if ( m_view ) {
+ m_view->setWidgetVisible(this, false);
+ m_view->removeChild( m_widget );
+ }
+
+ m_widget->removeEventFilter( this );
+ m_widget->setMouseTracking( false );
+ }
+
+ deref();
+}
+
+RenderWidget::~RenderWidget()
+{
+ KHTMLAssert( refCount() <= 0 );
+
+ if(m_widget) {
+ m_widget->hide();
+ m_widget->deleteLater();
+ }
+}
+
+class TQWidgetResizeEvent : public TQEvent
+{
+public:
+ enum { Type = TQEvent::User + 0xbee };
+ TQWidgetResizeEvent( int _w, int _h ) :
+ TQEvent( ( TQEvent::Type ) Type ), w( _w ), h( _h ) {}
+ int w;
+ int h;
+};
+
+void RenderWidget::resizeWidget( int w, int h )
+{
+ // ugly hack to limit the maximum size of the widget ( as X11 has problems if
+ // its bigger )
+ h = kMin( h, 3072 );
+ w = kMin( w, 2000 );
+
+ if (m_widget->width() != w || m_widget->height() != h) {
+ m_resizePending = isKHTMLWidget();
+ ref();
+ element()->ref();
+ TQApplication::postEvent( this, new TQWidgetResizeEvent( w, h ) );
+ element()->deref();
+ deref();
+ }
+}
+
+void RenderWidget::cancelPendingResize()
+{
+ if (!m_widget)
+ return;
+ m_discardResizes = true;
+ TQApplication::sendPostedEvents(this, TQWidgetResizeEvent::Type);
+ m_discardResizes = false;
+}
+
+bool RenderWidget::event( TQEvent *e )
+{
+ if ( m_widget && (e->type() == (TQEvent::Type)TQWidgetResizeEvent::Type) ) {
+ m_resizePending = false;
+ if (m_discardResizes)
+ return true;
+ TQWidgetResizeEvent *re = static_cast<TQWidgetResizeEvent *>(e);
+ m_widget->resize( re->w, re->h );
+ repaint();
+ }
+ // eat all events - except if this is a frame (in which case KHTMLView handles it all)
+ if ( ::tqqt_cast<KHTMLView *>( m_widget ) )
+ return TQObject::event( e );
+ return true;
+}
+
+void RenderWidget::flushWidgetResizes() //static
+{
+ TQApplication::sendPostedEvents( 0, TQWidgetResizeEvent::Type );
+}
+
+void RenderWidget::setQWidget(TQWidget *widget)
+{
+ if (widget != m_widget)
+ {
+ if (m_widget) {
+ m_widget->removeEventFilter(this);
+ disconnect( m_widget, TQT_SIGNAL( destroyed()), this, TQT_SLOT( slotWidgetDestructed()));
+ m_widget->hide();
+ m_widget->deleteLater(); //Might happen due to event on the widget, so be careful
+ m_widget = 0;
+ }
+ m_widget = widget;
+ if (m_widget) {
+ connect( m_widget, TQT_SIGNAL( destroyed()), this, TQT_SLOT( slotWidgetDestructed()));
+ m_widget->installEventFilter(this);
+
+ if ( (m_isKHTMLWidget = !strcmp(m_widget->name(), "__tdehtml")) && !::tqqt_cast<TQFrame*>(m_widget))
+ m_widget->setBackgroundMode( TQWidget::NoBackground );
+
+ if (m_widget->focusPolicy() > TQ_StrongFocus)
+ m_widget->setFocusPolicy(TQ_StrongFocus);
+ // if we've already received a layout, apply the calculated space to the
+ // widget immediately, but we have to have really been full constructed (with a non-null
+ // style pointer).
+ if (!needsLayout() && style()) {
+ resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
+ m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
+ }
+ else
+ setPos(xPos(), -500000);
+ }
+ m_view->setWidgetVisible(this, false);
+ m_view->addChild( m_widget, 0, -500000);
+ if ( m_widget ) m_widget->hide();
+ m_resizePending = false;
+ }
+}
+
+void RenderWidget::layout( )
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+ if ( m_widget ) {
+ resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
+ m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
+ if (!isKHTMLWidget() && !isFrame() && !m_needsMask) {
+ m_needsMask = true;
+ RenderLayer* rl = enclosingStackingContext();
+ RenderLayer* el = enclosingLayer();
+ while (rl && el && el != rl) {
+ if (el->renderer()->style()->position() != STATIC) {
+ m_needsMask = false;
+ break;
+ }
+ el = el->parent();
+ }
+ if (m_needsMask) {
+ if (rl) rl->setHasOverlaidWidgets();
+ canvas()->setNeedsWidgetMasks();
+ }
+ }
+ }
+
+ setNeedsLayout(false);
+}
+
+void RenderWidget::updateFromElement()
+{
+ if (m_widget) {
+ // Color:
+ TQColor color = style()->color();
+ TQColor backgroundColor = style()->backgroundColor();
+
+ if ( color.isValid() || backgroundColor.isValid() ) {
+ TQPalette pal(TQApplication::palette(m_widget));
+
+ int contrast_ = TDEGlobalSettings::contrast();
+ int highlightVal = 100 + (2*contrast_+4)*16/10;
+ int lowlightVal = 100 + (2*contrast_+4)*10;
+
+ if (backgroundColor.isValid()) {
+ if (!isKHTMLWidget())
+ widget()->setEraseColor(backgroundColor );
+ for ( int i = 0; i < TQPalette::NColorGroups; ++i ) {
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Background, backgroundColor );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Light, backgroundColor.light(highlightVal) );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Dark, backgroundColor.dark(lowlightVal) );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Mid, backgroundColor.dark(120) );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Midlight, backgroundColor.light(110) );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Button, backgroundColor );
+ pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Base, backgroundColor );
+ }
+ }
+ if ( color.isValid() ) {
+ struct ColorSet {
+ TQPalette::ColorGroup cg;
+ TQColorGroup::ColorRole cr;
+ };
+ const struct ColorSet toSet [] = {
+ { TQPalette::Active, TQColorGroup::Foreground },
+ { TQPalette::Active, TQColorGroup::ButtonText },
+ { TQPalette::Active, TQColorGroup::Text },
+ { TQPalette::Inactive, TQColorGroup::Foreground },
+ { TQPalette::Inactive, TQColorGroup::ButtonText },
+ { TQPalette::Inactive, TQColorGroup::Text },
+ { TQPalette::Disabled,TQColorGroup::ButtonText },
+ { TQPalette::NColorGroups, TQColorGroup::NColorRoles },
+ };
+ const ColorSet *set = toSet;
+ while( set->cg != TQPalette::NColorGroups ) {
+ pal.setColor( set->cg, set->cr, color );
+ ++set;
+ }
+
+ TQColor disfg = color;
+ int h, s, v;
+ disfg.hsv( &h, &s, &v );
+ if (v > 128)
+ // dark bg, light fg - need a darker disabled fg
+ disfg = disfg.dark(lowlightVal);
+ else if (disfg != Qt::black)
+ // light bg, dark fg - need a lighter disabled fg - but only if !black
+ disfg = disfg.light(highlightVal);
+ else
+ // black fg - use darkgray disabled fg
+ disfg = Qt::darkGray;
+ pal.setColor(TQPalette::Disabled,TQColorGroup::Foreground,disfg);
+ }
+
+ m_widget->setPalette(pal);
+ }
+ else
+ m_widget->unsetPalette();
+ // Border:
+ TQFrame* frame = ::tqqt_cast<TQFrame*>(m_widget);
+ if (frame) {
+ if (shouldPaintBackgroundOrBorder())
+ {
+ frame->setFrameShape(TQFrame::NoFrame);
+ }
+ }
+
+ }
+
+ RenderReplaced::updateFromElement();
+}
+
+void RenderWidget::slotWidgetDestructed()
+{
+ if (m_view)
+ m_view->setWidgetVisible(this, false);
+ m_widget = 0;
+}
+
+void RenderWidget::setStyle(RenderStyle *_style)
+{
+ RenderReplaced::setStyle(_style);
+ if(m_widget)
+ {
+ m_widget->setFont(style()->font());
+ if (style()->visibility() != VISIBLE) {
+ if (m_view)
+ m_view->setWidgetVisible(this, false);
+ m_widget->hide();
+ }
+ }
+
+ // Don't paint borders if the border-style is native
+ // or borders are not supported on this widget
+ if (!canHaveBorder() ||
+ (style()->borderLeftStyle() == BNATIVE &&
+ style()->borderRightStyle() == BNATIVE &&
+ style()->borderTopStyle() == BNATIVE &&
+ style()->borderBottomStyle() == BNATIVE))
+ {
+ setShouldPaintBackgroundOrBorder(false);
+ }
+}
+
+void RenderWidget::paint(PaintInfo& paintInfo, int _tx, int _ty)
+{
+ _tx += m_x;
+ _ty += m_y;
+
+ if (shouldPaintBackgroundOrBorder() &&
+ (paintInfo.phase == PaintActionChildBackground || paintInfo.phase == PaintActionChildBackgrounds))
+ paintBoxDecorations(paintInfo, _tx, _ty);
+
+ if (!m_widget || !m_view || paintInfo.phase != PaintActionForeground)
+ return;
+
+ // not visible or not even once layouted
+ if (style()->visibility() != VISIBLE || m_y <= -500000 || m_resizePending )
+ return;
+
+ if ( (_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()) ||
+ (_tx + m_width <= paintInfo.r.left()) || (_tx > paintInfo.r.right()) )
+ return;
+
+ int xPos = _tx+borderLeft()+paddingLeft();
+ int yPos = _ty+borderTop()+paddingTop();
+
+ bool tdehtmlw = isKHTMLWidget();
+ int childw = m_widget->width();
+ int childh = m_widget->height();
+ if ( (childw == 2000 || childh == 3072) && m_widget->inherits( "KHTMLView" ) ) {
+ KHTMLView *vw = static_cast<KHTMLView *>(m_widget);
+ int cy = m_view->contentsY();
+ int ch = m_view->visibleHeight();
+
+
+ int childx = m_view->childX( m_widget );
+ int childy = m_view->childY( m_widget );
+
+ int xNew = xPos;
+ int yNew = childy;
+
+ // tqDebug("cy=%d, ch=%d, childy=%d, childh=%d", cy, ch, childy, childh );
+ if ( childh == 3072 ) {
+ if ( cy + ch > childy + childh ) {
+ yNew = cy + ( ch - childh )/2;
+ } else if ( cy < childy ) {
+ yNew = cy + ( ch - childh )/2;
+ }
+// tqDebug("calculated yNew=%d", yNew);
+ }
+ yNew = kMin( yNew, yPos + m_height - childh );
+ yNew = kMax( yNew, yPos );
+ if ( yNew != childy || xNew != childx ) {
+ if ( vw->contentsHeight() < yNew - yPos + childh )
+ vw->resizeContents( vw->contentsWidth(), yNew - yPos + childh );
+ vw->setContentsPos( xNew - xPos, yNew - yPos );
+ }
+ xPos = xNew;
+ yPos = yNew;
+ }
+ m_view->setWidgetVisible(this, true);
+ m_view->addChild(m_widget, xPos, yPos );
+ m_widget->show();
+ if (tdehtmlw)
+ paintWidget(paintInfo, m_widget, xPos, yPos);
+}
+
+#include <tqinternal_p.h>
+
+// The PaintBuffer class provides a shared buffer for widget painting.
+//
+// It will grow to encompass the biggest widget encountered, in order to avoid
+// constantly resizing.
+// When it grows over maxPixelBuffering, it periodically checks if such a size
+// is still needed. If not, it shrinks down to the biggest size < maxPixelBuffering
+// that was requested during the overflow lapse.
+
+class PaintBuffer: public TQObject
+{
+public:
+ static const int maxPixelBuffering = 320*200;
+ static const int leaseTime = 20*1000;
+
+ static TQPixmap *grab( TQSize s = TQSize() ) {
+ if (!m_inst)
+ m_inst = new PaintBuffer;
+ return m_inst->getBuf( s );
+ }
+ static void release() { m_inst->m_grabbed = false; }
+protected:
+ PaintBuffer(): m_overflow(false), m_grabbed(false),
+ m_timer(0), m_resetWidth(0), m_resetHeight(0) {};
+ void timerEvent(TQTimerEvent* e) {
+ assert( m_timer == e->timerId() );
+ if (m_grabbed)
+ return;
+ m_buf.resize(m_resetWidth, m_resetHeight);
+ m_resetWidth = m_resetHeight = 0;
+ killTimer( m_timer );
+ m_timer = 0;
+ }
+
+ TQPixmap *getBuf( TQSize s ) {
+ assert( !m_grabbed );
+ if (s.isEmpty())
+ return 0;
+
+ m_grabbed = true;
+ bool cur_overflow = false;
+
+ int nw = kMax(m_buf.width(), s.width());
+ int nh = kMax(m_buf.height(), s.height());
+
+ if (!m_overflow && (nw*nh > maxPixelBuffering))
+ cur_overflow = true;
+
+ if (nw != m_buf.width() || nh != m_buf.height())
+ m_buf.resize(nw, nh);
+
+ if (cur_overflow) {
+ m_overflow = true;
+ m_timer = startTimer( leaseTime );
+ } else if (m_overflow) {
+ if( s.width()*s.height() > maxPixelBuffering ) {
+ killTimer( m_timer );
+ m_timer = startTimer( leaseTime );
+ } else {
+ if (s.width() > m_resetWidth)
+ m_resetWidth = s.width();
+ if (s.height() > m_resetHeight)
+ m_resetHeight = s.height();
+ }
+ }
+ return &m_buf;
+ }
+private:
+ static PaintBuffer* m_inst;
+ TQPixmap m_buf;
+ bool m_overflow;
+ bool m_grabbed;
+ int m_timer;
+ int m_resetWidth;
+ int m_resetHeight;
+};
+
+PaintBuffer *PaintBuffer::m_inst = 0;
+
+static void copyWidget(const TQRect& r, TQPainter *p, TQWidget *widget, int tx, int ty)
+{
+ if (r.isNull() || r.isEmpty() )
+ return;
+ TQRegion blit(r);
+ TQValueVector<TQWidget*> cw;
+ TQValueVector<TQRect> cr;
+
+ if (!widget->childrenListObject().isEmpty()) {
+ // build region
+ TQObjectList childWidgets = widget->childrenListObject();
+ TQObjectListIterator it(childWidgets);
+ for (; it.current(); ++it) {
+ TQWidget* const w = ::tqqt_cast<TQWidget *>(it.current());
+ if ( w && !w->isTopLevel() && !w->isHidden()) {
+ TQRect r2 = w->geometry();
+ blit -= r2;
+ r2 = r2.intersect( r );
+ r2.moveBy(-w->x(), -w->y());
+ cr.append(r2);
+ cw.append(w);
+ }
+ }
+ }
+ TQMemArray<TQRect> br = blit.rects();
+
+ const int cnt = br.size();
+ const bool external = p->device()->isExtDev();
+ TQPixmap* const pm = PaintBuffer::grab( widget->size() );
+ if (!pm)
+ {
+ kdWarning(6040) << "Rendering widget [ " << widget->className() << " ] failed due to invalid size." << endl;
+ return;
+ }
+
+ // fill background
+ if ( external ) {
+ // even hackier!
+ TQPainter pt( pm );
+ const TQColor c = widget->colorGroup().base();
+ for (int i = 0; i < cnt; ++i)
+ pt.fillRect( br[i], c );
+ } else {
+ TQRect dr;
+ for (int i = 0; i < cnt; ++i ) {
+ dr = br[i];
+ dr.moveBy( tx, ty );
+ dr = p->xForm( dr );
+ bitBlt(pm, br[i].topLeft(), p->device(), dr);
+ }
+ }
+
+ // send paint event
+ TQPainter::redirect(widget, pm);
+ TQPaintEvent e( r, false );
+ TQApplication::sendEvent( widget, &e );
+ TQPainter::redirect(widget, 0);
+
+ // transfer result
+ if ( external )
+ for ( int i = 0; i < cnt; ++i )
+ p->drawPixmap(TQPoint(tx+br[i].x(), ty+br[i].y()), *pm, br[i]);
+ else
+ for ( int i = 0; i < cnt; ++i )
+ bitBlt(p->device(), p->xForm( TQPoint(tx, ty) + br[i].topLeft() ), pm, br[i]);
+
+ // cleanup and recurse
+ PaintBuffer::release();
+ TQValueVector<TQWidget*>::iterator cwit = cw.begin();
+ TQValueVector<TQWidget*>::iterator cwitEnd = cw.end();
+ TQValueVector<TQRect>::const_iterator crit = cr.begin();
+ for (; cwit != cwitEnd; ++cwit, ++crit)
+ copyWidget(*crit, p, *cwit, tx+(*cwit)->x(), ty+(*cwit)->y());
+}
+
+void RenderWidget::paintWidget(PaintInfo& pI, TQWidget *widget, int tx, int ty)
+{
+ TQPainter* const p = pI.p;
+ allowWidgetPaintEvents = true;
+
+ const bool dsbld = TQSharedDoubleBuffer::isDisabled();
+ TQSharedDoubleBuffer::setDisabled(true);
+ TQRect rr = pI.r;
+ rr.moveBy(-tx, -ty);
+ const TQRect r = widget->rect().intersect( rr );
+ copyWidget(r, p, widget, tx, ty);
+ TQSharedDoubleBuffer::setDisabled(dsbld);
+
+ allowWidgetPaintEvents = false;
+}
+
+bool RenderWidget::eventFilter(TQObject* /*o*/, TQEvent* e)
+{
+ // no special event processing if this is a frame (in which case KHTMLView handles it all)
+ if ( ::tqqt_cast<KHTMLView *>( m_widget ) )
+ return false;
+ if ( !element() ) return true;
+
+
+ static bool directToWidget = false;
+ if (directToWidget) {
+ //We're trying to get the event to the widget
+ //promptly. So get out of here..
+ return false;
+ }
+
+ ref();
+ element()->ref();
+
+ bool filtered = false;
+
+ //kdDebug() << "RenderWidget::eventFilter type=" << e->type() << endl;
+ switch(e->type()) {
+ case TQEvent::FocusOut:
+ // First, forward it to the widget, so that Qt gets a precise
+ // state of the focus before pesky JS can try changing it..
+ directToWidget = true;
+ TQApplication::sendEvent(m_widget, e);
+ directToWidget = false;
+ filtered = true; //We already delivered it!
+
+ // 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 ( TQT_TQFOCUSEVENT(e)->reason() != TQFocusEvent::Popup )
+ handleFocusOut();
+ break;
+ case TQEvent::FocusIn:
+ //As above, forward to the widget first...
+ directToWidget = true;
+ TQApplication::sendEvent(m_widget, e);
+ directToWidget = false;
+ filtered = true; //We already delivered it!
+
+ //kdDebug(6000) << "RenderWidget::eventFilter captures FocusIn" << endl;
+ element()->getDocument()->setFocusNode(element());
+// if ( isEditable() ) {
+// KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>( element()->view->part()->browserExtension() );
+// if ( ext ) ext->editableWidgetFocused( m_widget );
+// }
+ break;
+ case TQEvent::KeyPress:
+ case TQEvent::KeyRelease:
+ // TODO this seems wrong - Qt events are not correctly translated to DOM ones,
+ // like in KHTMLView::dispatchKeyEvent()
+ if (element()->dispatchKeyEvent(TQT_TQKEYEVENT(e),false))
+ filtered = true;
+ break;
+
+ case TQEvent::Wheel:
+ if (widget()->parentWidget() == view()->viewport()) {
+ // don't allow the widget to react to wheel event unless its
+ // currently focused. this avoids accidentally changing a select box
+ // or something while wheeling a webpage.
+ if (tqApp->focusWidget() != widget() &&
+ widget()->focusPolicy() <= TQ_StrongFocus) {
+ TQT_TQWHEELEVENT(e)->ignore();
+ TQApplication::sendEvent(view(), e);
+ filtered = true;
+ }
+ }
+ break;
+ default:
+ break;
+ };
+
+ element()->deref();
+
+ // stop processing if the widget gets deleted, but continue in all other cases
+ if (hasOneRef())
+ filtered = true;
+ deref();
+
+ return filtered;
+}
+
+void RenderWidget::EventPropagator::sendEvent(TQEvent *e) {
+ switch(e->type()) {
+ case TQEvent::MouseButtonPress:
+ mousePressEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseButtonRelease:
+ mouseReleaseEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseButtonDblClick:
+ mouseDoubleClickEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseMove:
+ mouseMoveEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::KeyPress:
+ keyPressEvent(TQT_TQKEYEVENT(e));
+ break;
+ case TQEvent::KeyRelease:
+ keyReleaseEvent(TQT_TQKEYEVENT(e));
+ break;
+ default:
+ break;
+ }
+}
+
+void RenderWidget::ScrollViewEventPropagator::sendEvent(TQEvent *e) {
+ switch(e->type()) {
+ case TQEvent::MouseButtonPress:
+ viewportMousePressEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseButtonRelease:
+ viewportMouseReleaseEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseButtonDblClick:
+ viewportMouseDoubleClickEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::MouseMove:
+ viewportMouseMoveEvent(TQT_TQMOUSEEVENT(e));
+ break;
+ case TQEvent::KeyPress:
+ keyPressEvent(TQT_TQKEYEVENT(e));
+ break;
+ case TQEvent::KeyRelease:
+ keyReleaseEvent(TQT_TQKEYEVENT(e));
+ break;
+ default:
+ break;
+ }
+}
+
+bool RenderWidget::handleEvent(const DOM::EventImpl& ev)
+{
+ bool ret = false;
+ switch(ev.id()) {
+ case EventImpl::MOUSEDOWN_EVENT:
+ case EventImpl::MOUSEUP_EVENT:
+ case EventImpl::MOUSEMOVE_EVENT: {
+ if (!ev.isMouseEvent()) break;
+ const MouseEventImpl &me = static_cast<const MouseEventImpl &>(ev);
+ TQMouseEvent* const qme = me.qEvent();
+
+ int absx = 0;
+ int absy = 0;
+
+ absolutePosition(absx, absy);
+ TQPoint p(me.clientX() - absx + m_view->contentsX(),
+ me.clientY() - absy + m_view->contentsY());
+ TQMouseEvent::Type type;
+ int button = 0;
+ int state = 0;
+
+ if (qme) {
+ button = qme->button();
+ state = qme->state();
+ type = qme->type();
+ } else {
+ switch(me.id()) {
+ case EventImpl::MOUSEDOWN_EVENT:
+ type = TQMouseEvent::MouseButtonPress;
+ break;
+ case EventImpl::MOUSEUP_EVENT:
+ type = TQMouseEvent::MouseButtonRelease;
+ break;
+ case EventImpl::MOUSEMOVE_EVENT:
+ default:
+ type = TQMouseEvent::MouseMove;
+ break;
+ }
+ switch (me.button()) {
+ case 0:
+ button = Qt::LeftButton;
+ break;
+ case 1:
+ button = Qt::MidButton;
+ break;
+ case 2:
+ button = Qt::RightButton;
+ break;
+ default:
+ break;
+ }
+ if (me.ctrlKey())
+ state |= ControlButton;
+ if (me.altKey())
+ state |= AltButton;
+ if (me.shiftKey())
+ state |= ShiftButton;
+ if (me.metaKey())
+ state |= MetaButton;
+ }
+
+// kdDebug(6000) << "sending event to widget "
+// << " pos=" << p << " type=" << type
+// << " button=" << button << " state=" << state << endl;
+ TQMouseEvent e(type, p, button, state);
+ TQScrollView * sc = ::tqqt_cast<TQScrollView*>(m_widget);
+ if (sc && !::tqqt_cast<TQListBox*>(m_widget))
+ static_cast<ScrollViewEventPropagator *>(sc)->sendEvent(TQT_TQEVENT(&e));
+ else
+ static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(&e));
+ ret = e.isAccepted();
+ break;
+ }
+ case EventImpl::KEYDOWN_EVENT:
+ // do nothing; see the mapping table below
+ break;
+ case EventImpl::KEYUP_EVENT: {
+ if (!ev.isKeyRelatedEvent()) break;
+
+ const KeyEventBaseImpl& domKeyEv = static_cast<const KeyEventBaseImpl &>(ev);
+ if (domKeyEv.isSynthetic() && !acceptsSyntheticEvents()) break;
+
+ TQKeyEvent* const ke = domKeyEv.qKeyEvent();
+ static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(ke));
+ ret = ke->isAccepted();
+ break;
+ }
+ case EventImpl::KEYPRESS_EVENT: {
+ if (!ev.isKeyRelatedEvent()) break;
+
+ const KeyEventBaseImpl& domKeyEv = static_cast<const KeyEventBaseImpl &>(ev);
+ if (domKeyEv.isSynthetic() && !acceptsSyntheticEvents()) break;
+
+ // See KHTMLView::dispatchKeyEvent: autorepeat is just keypress in the DOM
+ // but it's keyrelease+keypress in Qt. So here we do the inverse mapping as
+ // the one done in KHTMLView: generate two events for one DOM auto-repeat keypress.
+ // Similarly, DOM keypress events with non-autorepeat Qt event do nothing here,
+ // because the matching Qt keypress event was already sent from DOM keydown event.
+
+ // Reverse drawing as the one in KHTMLView:
+ // DOM: Down Press | Press | Up
+ // Qt: (nothing) Press | Release(autorepeat) + Press(autorepeat) | Release
+ //
+ // Qt::KeyPress is sent for DOM keypress and not DOM keydown to allow
+ // sites to block a key with onkeypress, #99749
+
+ TQKeyEvent* const ke = domKeyEv.qKeyEvent();
+ if (ke->isAutoRepeat()) {
+ TQKeyEvent releaseEv( TQEvent::KeyRelease, ke->key(), ke->ascii(), ke->state(),
+ ke->text(), ke->isAutoRepeat(), ke->count() );
+ static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(&releaseEv));
+ }
+ static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(ke));
+ ret = ke->isAccepted();
+ break;
+ }
+ case EventImpl::MOUSEOUT_EVENT: {
+ TQEvent moe( TQEvent::Leave );
+ TQApplication::sendEvent(m_widget, &moe);
+ break;
+ }
+ case EventImpl::MOUSEOVER_EVENT: {
+ TQEvent moe( TQEvent::Enter );
+ TQApplication::sendEvent(m_widget, &moe);
+ view()->part()->resetHoverText();
+ break;
+ }
+ default:
+ break;
+ }
+ return ret;
+}
+
+void RenderWidget::deref()
+{
+ if (_ref) _ref--;
+// tqDebug( "deref(%p): width get count is %d", this, _ref);
+ if (!_ref) {
+ tdehtml::SharedPtr<RenderArena> guard(m_arena); //Since delete on us gets called -first-,
+ //before the arena free
+ arenaDelete(m_arena.get());
+ }
+}
+
+FindSelectionResult RenderReplaced::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &)
+{
+#if 0
+ kdDebug(6040) << "RenderReplaced::checkSelectionPoint(_x="<<_x<<",_y="<<_y<<",_tx="<<_tx<<",_ty="<<_ty<<")" << endl
+ << "xPos: " << xPos() << " yPos: " << yPos() << " width: " << width() << " height: " << height() << endl
+ << "_ty + yPos: " << (_ty + yPos()) << " + height: " << (_ty + yPos() + height()) << "; _tx + xPos: " << (_tx + xPos()) << " + width: " << (_tx + xPos() + width()) << endl;
+#endif
+ node = element();
+ offset = 0;
+
+ if ( _y < _ty + yPos() )
+ return SelectionPointBefore; // above -> before
+
+ if ( _y > _ty + yPos() + height() ) {
+ // below -> after
+ // Set the offset to the max
+ offset = 1;
+ return SelectionPointAfter;
+ }
+ if ( _x > _tx + xPos() + width() ) {
+ // to the right
+ // ### how to regard bidi in replaced elements? (LS)
+ offset = 1;
+ return SelectionPointAfterInLine;
+ }
+
+ // The Y matches, check if we're on the left
+ if ( _x < _tx + xPos() ) {
+ // ### how to regard bidi in replaced elements? (LS)
+ return SelectionPointBeforeInLine;
+ }
+
+ offset = _x > _tx + xPos() + width()/2;
+ return SelectionPointInside;
+}
+
+#ifdef ENABLE_DUMP
+void RenderWidget::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderReplaced::dump(stream,ind);
+ if ( widget() )
+ stream << " color=" << widget()->foregroundColor().name()
+ << " bg=" << widget()->backgroundColor().name();
+ else
+ stream << " null widget";
+}
+#endif
+
+#include "render_replaced.moc"
+
diff --git a/tdehtml/rendering/render_replaced.h b/tdehtml/rendering/render_replaced.h
new file mode 100644
index 000000000..c1369bfc0
--- /dev/null
+++ b/tdehtml/rendering/render_replaced.h
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the HTML widget for KDE.
+ *
+ * Copyright (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 render_replaced_h
+#define render_replaced_h
+
+#include "rendering/render_block.h"
+#include <tqobject.h>
+#include <tqscrollview.h>
+
+class KHTMLView;
+class TQWidget;
+
+namespace DOM
+{
+ class MouseEventImpl;
+}
+
+namespace tdehtml {
+
+class RenderReplaced : public RenderBox
+{
+public:
+ RenderReplaced(DOM::NodeImpl* node);
+
+ virtual const char *renderName() const { return "RenderReplaced"; }
+ virtual bool isRenderReplaced() const { return true; }
+
+ virtual bool childAllowed() const { return false; }
+
+ virtual void calcMinMaxWidth();
+
+ virtual short intrinsicWidth() const { return m_intrinsicWidth; }
+ virtual int intrinsicHeight() const { return m_intrinsicHeight; }
+
+ void setIntrinsicWidth(int w) { m_intrinsicWidth = w; }
+ void setIntrinsicHeight(int h) { m_intrinsicHeight = h; }
+
+ virtual void position(InlineBox*, int, int, bool);
+
+ // Return before, after (offset set to max), or inside the replaced element,
+ // at @p offset
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*& node, int & offset,
+ SelPointState & );
+
+ /** returns the lowest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns 0.
+ */
+ virtual long minOffset() const { return 0; }
+ /** returns the highest possible value the caret offset may have to
+ * still point to a valid position.
+ *
+ * Returns 0.
+ */
+ virtual long maxOffset() const { return 0; }
+
+protected:
+ short m_intrinsicWidth;
+ short m_intrinsicHeight;
+};
+
+
+class RenderWidget : public TQObject, public RenderReplaced, public tdehtml::Shared<RenderWidget>
+{
+ Q_OBJECT
+public:
+ RenderWidget(DOM::NodeImpl* node);
+ virtual ~RenderWidget();
+
+ virtual void setStyle(RenderStyle *style);
+ virtual void paint( PaintInfo& i, int tx, int ty );
+ virtual bool isWidget() const { return true; };
+
+ virtual bool isFrame() const { return false; }
+
+ virtual void detach( );
+ virtual void layout( );
+
+ virtual void updateFromElement();
+
+ TQWidget *widget() const { return m_widget; }
+ KHTMLView* view() const { return m_view; }
+
+ void deref();
+
+ void cancelPendingResize();
+ bool needsMask() const { return m_needsMask; }
+
+ static void paintWidget(PaintInfo& pI, TQWidget *widget, int tx, int ty);
+ virtual bool handleEvent(const DOM::EventImpl& ev);
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+ // for ECMA to flush all pending resizes
+ KDE_EXPORT static void flushWidgetResizes();
+
+public slots:
+ void slotWidgetDestructed();
+ bool isKHTMLWidget() const { return m_isKHTMLWidget; }
+
+protected:
+ virtual bool canHaveBorder() const { return false; }
+
+ virtual bool acceptsSyntheticEvents() const { return true; }
+
+ virtual void handleFocusOut() {}
+ bool event( TQEvent *e );
+
+ bool eventFilter(TQObject* /*o*/, TQEvent* e);
+ void setQWidget(TQWidget *widget);
+ void resizeWidget( int w, int h );
+
+ TQWidget *m_widget;
+ KHTMLView* m_view;
+
+ //Because we mess with normal detach due to ref/deref,
+ //we need to keep track of the arena ourselves
+ //so it doesn't get yanked from us, etc.
+ SharedPtr<RenderArena> m_arena;
+
+ bool m_resizePending;
+ bool m_discardResizes;
+ bool m_isKHTMLWidget;
+ bool m_needsMask;
+
+public:
+ virtual int borderTop() const { return canHaveBorder() ? RenderReplaced::borderTop() : 0; }
+ virtual int borderBottom() const { return canHaveBorder() ? RenderReplaced::borderBottom() : 0; }
+ virtual int borderLeft() const { return canHaveBorder() ? RenderReplaced::borderLeft() : 0; }
+ virtual int borderRight() const { return canHaveBorder() ? RenderReplaced::borderRight() : 0; }
+
+ class EventPropagator : public TQWidget {
+ public:
+ void sendEvent(TQEvent *e);
+ };
+ class ScrollViewEventPropagator : public TQScrollView {
+ public:
+ void sendEvent(TQEvent *e);
+ };
+};
+
+extern bool allowWidgetPaintEvents;
+
+}
+
+#endif
diff --git a/tdehtml/rendering/render_style.cpp b/tdehtml/rendering/render_style.cpp
new file mode 100644
index 000000000..a2ae70948
--- /dev/null
+++ b/tdehtml/rendering/render_style.cpp
@@ -0,0 +1,1301 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002-2005 Apple Computer, Inc.
+ * Copyright (C) 2005 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.
+ *
+ */
+
+#include "xml/dom_stringimpl.h"
+#include "css/cssstyleselector.h"
+#include "css/css_valueimpl.h"
+#include "render_style.h"
+
+#include "kdebug.h"
+
+using namespace tdehtml;
+using namespace DOM;
+
+/* CSS says Fixed for the default padding value, but we treat variable as 0 padding anyways, and like
+ * this is works fine for table paddings aswell
+ */
+StyleSurroundData::StyleSurroundData()
+ : margin( Fixed ), padding( Variable )
+{
+}
+
+StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
+ : Shared<StyleSurroundData>(),
+ offset( o.offset ), margin( o.margin ), padding( o.padding ),
+ border( o.border )
+{
+}
+
+bool StyleSurroundData::operator==(const StyleSurroundData& o) const
+{
+ return offset==o.offset && margin==o.margin &&
+ padding==o.padding && border==o.border;
+}
+
+StyleBoxData::StyleBoxData()
+ : z_index( 0 ), z_auto( true )
+{
+ min_width = min_height = RenderStyle::initialMinSize();
+ max_width = max_height = RenderStyle::initialMaxSize();
+ box_sizing = RenderStyle::initialBoxSizing();
+}
+
+StyleBoxData::StyleBoxData(const StyleBoxData& o )
+ : Shared<StyleBoxData>(),
+ width( o.width ), height( o.height ),
+ min_width( o.min_width ), max_width( o.max_width ),
+ min_height ( o.min_height ), max_height( o.max_height ),
+ box_sizing( o.box_sizing),
+ z_index( o.z_index ), z_auto( o.z_auto )
+{
+}
+
+bool StyleBoxData::operator==(const StyleBoxData& o) const
+{
+ return
+ width == o.width &&
+ height == o.height &&
+ min_width == o.min_width &&
+ max_width == o.max_width &&
+ min_height == o.min_height &&
+ max_height == o.max_height &&
+ box_sizing == o.box_sizing &&
+ z_index == o.z_index &&
+ z_auto == o.z_auto;
+}
+
+StyleVisualData::StyleVisualData()
+ : textDecoration(RenderStyle::initialTextDecoration()),
+ palette( TQApplication::palette() )
+{
+}
+
+StyleVisualData::~StyleVisualData() {
+}
+
+StyleVisualData::StyleVisualData(const StyleVisualData& o )
+ : Shared<StyleVisualData>(),
+ clip( o.clip ), textDecoration(o.textDecoration),
+ palette( o.palette )
+{
+}
+
+BackgroundLayer::BackgroundLayer()
+:m_image(RenderStyle::initialBackgroundImage()),
+ m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
+ m_bgClip(RenderStyle::initialBackgroundClip()),
+ m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
+ m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
+ m_backgroundSize(RenderStyle::initialBackgroundSize()),
+ m_next(0)
+{
+ m_imageSet = m_attachmentSet = m_clipSet = m_originSet =
+ m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;
+}
+
+BackgroundLayer::BackgroundLayer(const BackgroundLayer& o)
+{
+ m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
+ m_image = o.m_image;
+ m_xPosition = o.m_xPosition;
+ m_yPosition = o.m_yPosition;
+ m_bgAttachment = o.m_bgAttachment;
+ m_bgClip = o.m_bgClip;
+ m_bgOrigin = o.m_bgOrigin;
+ m_bgRepeat = o.m_bgRepeat;
+ m_backgroundSize = o.m_backgroundSize;
+ m_imageSet = o.m_imageSet;
+ m_attachmentSet = o.m_attachmentSet;
+ m_clipSet = o.m_clipSet;
+ m_originSet = o.m_originSet;
+ m_repeatSet = o.m_repeatSet;
+ m_xPosSet = o.m_xPosSet;
+ m_yPosSet = o.m_yPosSet;
+ m_backgroundSizeSet = o.m_backgroundSizeSet;
+}
+
+BackgroundLayer::~BackgroundLayer()
+{
+ delete m_next;
+}
+
+BackgroundLayer& BackgroundLayer::operator=(const BackgroundLayer& o) {
+ if (m_next != o.m_next) {
+ delete m_next;
+ m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
+ }
+
+ m_image = o.m_image;
+ m_xPosition = o.m_xPosition;
+ m_yPosition = o.m_yPosition;
+ m_bgAttachment = o.m_bgAttachment;
+ m_bgClip = o.m_bgClip;
+ m_bgOrigin = o.m_bgOrigin;
+ m_bgRepeat = o.m_bgRepeat;
+ m_backgroundSize = o.m_backgroundSize;
+
+ m_imageSet = o.m_imageSet;
+ m_attachmentSet = o.m_attachmentSet;
+ m_originSet = o.m_originSet;
+ m_repeatSet = o.m_repeatSet;
+ m_xPosSet = o.m_xPosSet;
+ m_yPosSet = o.m_yPosSet;
+ m_backgroundSizeSet = o.m_backgroundSizeSet;
+
+ return *this;
+}
+
+bool BackgroundLayer::operator==(const BackgroundLayer& o) const {
+ return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
+ m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin && m_bgRepeat == o.m_bgRepeat &&
+ m_backgroundSize.width == o.m_backgroundSize.width && m_backgroundSize.height == o.m_backgroundSize.height &&
+ m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet &&
+ m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet &&
+ ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
+}
+
+void BackgroundLayer::fillUnsetProperties()
+{
+ BackgroundLayer* curr;
+ for (curr = this; curr && curr->isBackgroundImageSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_image = pattern->m_image;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_xPosition = pattern->m_xPosition;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_yPosition = pattern->m_yPosition;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_bgAttachment = pattern->m_bgAttachment;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_bgClip = pattern->m_bgClip;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_bgOrigin = pattern->m_bgOrigin;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_bgRepeat = pattern->m_bgRepeat;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+
+ for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next());
+ if (curr && curr != this) {
+ // We need to fill in the remaining values with the pattern specified.
+ for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
+ curr->m_backgroundSize = pattern->m_backgroundSize;
+ pattern = pattern->next();
+ if (pattern == curr || !pattern)
+ pattern = this;
+ }
+ }
+}
+
+void BackgroundLayer::cullEmptyLayers()
+{
+ BackgroundLayer *next;
+ for (BackgroundLayer *p = this; p; p = next) {
+ next = p->m_next;
+ if (next && !next->isBackgroundImageSet() &&
+ !next->isBackgroundXPositionSet() && !next->isBackgroundYPositionSet() &&
+ !next->isBackgroundAttachmentSet() && !next->isBackgroundClipSet() &&
+ !next->isBackgroundOriginSet() && !next->isBackgroundRepeatSet() &&
+ !next->isBackgroundSizeSet()) {
+ delete next;
+ p->m_next = 0;
+ break;
+ }
+ }
+}
+
+StyleBackgroundData::StyleBackgroundData()
+{}
+
+StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o)
+ : Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
+{}
+
+bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
+{
+ return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
+}
+
+StyleGeneratedData::StyleGeneratedData() : Shared<StyleGeneratedData>(), content(0), counter_reset(0), counter_increment(0) {}
+
+StyleGeneratedData::~StyleGeneratedData()
+{
+ if (counter_reset) counter_reset->deref();
+ if (counter_increment) counter_increment->deref();
+ delete content;
+}
+
+StyleGeneratedData::StyleGeneratedData(const StyleGeneratedData& o)
+ : Shared<StyleGeneratedData>(), content(0),
+ counter_reset(o.counter_reset), counter_increment(o.counter_increment)
+{
+ if (o.content) content = new ContentData(*o.content);
+ if (counter_reset) counter_reset->ref();
+ if (counter_increment) counter_increment->ref();
+}
+
+bool StyleGeneratedData::contentDataEquivalent(const StyleGeneratedData* otherStyle) const
+{
+ ContentData* c1 = content;
+ ContentData* c2 = otherStyle->content;
+
+ while (c1 && c2) {
+ if (c1->_contentType != c2->_contentType)
+ return false;
+ if (c1->_contentType == CONTENT_TEXT) {
+ DOM::DOMString c1Str(c1->_content.text);
+ DOM::DOMString c2Str(c2->_content.text);
+ if (c1Str != c2Str)
+ return false;
+ }
+ else if (c1->_contentType == CONTENT_OBJECT) {
+ if (c1->_content.object != c2->_content.object)
+ return false;
+ }
+ else if (c1->_contentType == CONTENT_COUNTER) {
+ if (c1->_content.counter != c2->_content.counter)
+ return false;
+ }
+ else if (c1->_contentType == CONTENT_QUOTE) {
+ if (c1->_content.quote != c2->_content.quote)
+ return false;
+ }
+
+ c1 = c1->_nextContent;
+ c2 = c2->_nextContent;
+ }
+
+ return !c1 && !c2;
+}
+
+static bool compareCounterActList(const CSSValueListImpl* ca, const CSSValueListImpl* cb) {
+ // weeee....
+ CSSValueListImpl* a = const_cast<CSSValueListImpl*>(ca);
+ CSSValueListImpl* b = const_cast<CSSValueListImpl*>(cb);
+
+ if (!a && !b) return true;
+ if (!a || !b) return false;
+ if (a->length() != b->length()) return false;
+ for(uint i=0; i< a->length(); i++) {
+ CSSValueImpl *ai = a->item(i);
+ CSSValueImpl *bi = b->item(i);
+ assert(ai && ai->cssValueType() == CSSValue::CSS_CUSTOM);
+ assert(bi && bi->cssValueType() == CSSValue::CSS_CUSTOM);
+ CounterActImpl* caa = static_cast<CounterActImpl*>(ai);
+ CounterActImpl* cab = static_cast<CounterActImpl*>(bi);
+ if (caa->value() != cab->value()) return false;
+ if (caa->counter() != cab->counter()) return false;
+ }
+ return true;
+}
+
+bool StyleGeneratedData::counterDataEquivalent(const StyleGeneratedData* otherStyle) const
+{
+ return compareCounterActList(counter_reset, otherStyle->counter_reset) &&
+ compareCounterActList(counter_increment, otherStyle->counter_increment);
+}
+
+bool StyleGeneratedData::operator==(const StyleGeneratedData& o) const
+{
+ return contentDataEquivalent(&o) && counterDataEquivalent(&o);
+}
+
+StyleMarqueeData::StyleMarqueeData()
+{
+ increment = RenderStyle::initialMarqueeIncrement();
+ speed = RenderStyle::initialMarqueeSpeed();
+ direction = RenderStyle::initialMarqueeDirection();
+ behavior = RenderStyle::initialMarqueeBehavior();
+ loops = RenderStyle::initialMarqueeLoopCount();
+}
+
+StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
+:Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
+ behavior(o.behavior), direction(o.direction)
+{}
+
+bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
+{
+ return (increment == o.increment && speed == o.speed && direction == o.direction &&
+ behavior == o.behavior && loops == o.loops);
+}
+
+StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
+:Shared<StyleCSS3NonInheritedData>()
+, opacity(RenderStyle::initialOpacity())
+{
+}
+
+StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
+:Shared<StyleCSS3NonInheritedData>(),
+ opacity(o.opacity),
+#ifdef APPLE_CHANGES
+ flexibleBox(o.flexibleBox),
+#endif
+ marquee(o.marquee)
+{
+}
+
+bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
+{
+ return
+ opacity == o.opacity &&
+#ifdef APPLE_CHANGES
+ flexibleBox == o.flexibleBox &&
+#endif
+ marquee == o.marquee;
+}
+
+StyleCSS3InheritedData::StyleCSS3InheritedData()
+:Shared<StyleCSS3InheritedData>(), textShadow(0), wordWrap(RenderStyle::initialWordWrap())
+#ifdef APPLE_CHANGES
+, userModify(READ_ONLY), textSizeAdjust(RenderStyle::initialTextSizeAdjust())
+#endif
+{
+
+}
+
+StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
+:Shared<StyleCSS3InheritedData>()
+{
+ textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
+ wordWrap = o.wordWrap;
+#ifdef APPLE_CHANGES
+ userModify = o.userModify;
+ textSizeAdjust = o.textSizeAdjust;
+#endif
+}
+
+StyleCSS3InheritedData::~StyleCSS3InheritedData()
+{
+ delete textShadow;
+}
+
+bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
+{
+ return shadowDataEquivalent(o) && (wordWrap == o.wordWrap)
+#ifdef APPLE_CHANGES
+ && (userModify == o.userModify) && (textSizeAdjust == o.textSizeAdjust)
+#endif
+ ;
+}
+
+bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
+{
+ if (!textShadow && o.textShadow || textShadow && !o.textShadow)
+ return false;
+ if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
+ return false;
+ return true;
+}
+
+StyleInheritedData::StyleInheritedData()
+ : indent( RenderStyle::initialTextIndent() ), line_height( RenderStyle::initialLineHeight() ),
+ style_image( RenderStyle::initialListStyleImage() ),
+ font(), color( RenderStyle::initialColor() ),
+ border_hspacing( RenderStyle::initialBorderHorizontalSpacing() ),
+ border_vspacing( RenderStyle::initialBorderVerticalSpacing() ),
+ widows( RenderStyle::initialWidows() ), orphans( RenderStyle::initialOrphans() ),
+ quotes(0)
+{
+}
+
+StyleInheritedData::~StyleInheritedData()
+{
+ if (quotes) quotes->deref();
+}
+
+StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
+ : Shared<StyleInheritedData>(),
+ indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
+ font( o.font ), color( o.color ),
+ border_hspacing( o.border_hspacing ),
+ border_vspacing( o.border_vspacing ),
+ widows(o.widows), orphans(o.orphans)
+{
+ quotes = o.quotes;
+ if (quotes) quotes->ref();
+}
+
+bool StyleInheritedData::operator==(const StyleInheritedData& o) const
+{
+ return
+ indent == o.indent &&
+ line_height == o.line_height &&
+ border_hspacing == o.border_hspacing &&
+ border_vspacing == o.border_vspacing &&
+ style_image == o.style_image &&
+ font == o.font &&
+ color == o.color &&
+ border_hspacing == o.border_hspacing &&
+ border_vspacing == o.border_vspacing &&
+ quotes == o.quotes &&
+ widows == o.widows &&
+ orphans == o.orphans ;
+
+ // doesn't work because structs are not packed
+ //return memcmp(this, &o, sizeof(*this))==0;
+}
+
+RenderStyle::RenderStyle()
+{
+// counter++;
+ if (!_default)
+ _default = new RenderStyle(true);
+
+ box = _default->box;
+ visual = _default->visual;
+ background = _default->background;
+ surround = _default->surround;
+ generated = _default->generated;
+ css3NonInheritedData = _default->css3NonInheritedData;
+ css3InheritedData = _default->css3InheritedData;
+
+ inherited = _default->inherited;
+
+ setBitDefaults();
+
+ pseudoStyle = 0;
+}
+
+RenderStyle::RenderStyle(bool)
+{
+ setBitDefaults();
+
+ box.init();
+ visual.init();
+ background.init();
+ surround.init();
+ generated.init();
+ css3NonInheritedData.init();
+#ifdef APPLE_CHANGES // ### yet to be merged
+ css3NonInheritedData.access()->flexibleBox.init();
+#endif
+ css3NonInheritedData.access()->marquee.init();
+ css3InheritedData.init();
+ inherited.init();
+
+ pseudoStyle = 0;
+}
+
+RenderStyle::RenderStyle(const RenderStyle& o)
+ : Shared<RenderStyle>(),
+ inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
+ box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ), generated(o.generated),
+ css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
+ inherited( o.inherited ), pseudoStyle( 0 )
+{}
+
+void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
+{
+ css3InheritedData = inheritParent->css3InheritedData;
+ inherited = inheritParent->inherited;
+ inherited_flags = inheritParent->inherited_flags;
+
+ // Simulate ":after,:before { white-space: pre-line }"
+ if (styleType() == AFTER || styleType() == BEFORE)
+ setWhiteSpace(PRE_LINE);
+}
+
+RenderStyle::~RenderStyle()
+{
+ RenderStyle *ps = pseudoStyle;
+ RenderStyle *prev = 0;
+
+ while (ps) {
+ prev = ps;
+ ps = ps->pseudoStyle;
+ // to prevent a double deletion.
+ // this works only because the styles below aren't really shared
+ // Dirk said we need another construct as soon as these are shared
+ prev->pseudoStyle = 0;
+ prev->deref();
+ }
+}
+
+bool RenderStyle::operator==(const RenderStyle& o) const
+{
+// compare everything except the pseudoStyle pointer
+ return (inherited_flags == o.inherited_flags &&
+ noninherited_flags == o.noninherited_flags &&
+ box == o.box &&
+ visual == o.visual &&
+ background == o.background &&
+ surround == o.surround &&
+ generated == o.generated &&
+ css3NonInheritedData == o.css3NonInheritedData &&
+ css3InheritedData == o.css3InheritedData &&
+ inherited == o.inherited);
+}
+
+enum EPseudoBit { NO_BIT = 0x0,
+ FIRST_LINE_BIT = 0x1, FIRST_LETTER_BIT = 0x2, SELECTION_BIT = 0x4,
+ BEFORE_BIT = 0x8, AFTER_BIT = 0x10, MARKER_BIT = 0x20,
+ REPLACED_BIT = 0x40
+ };
+
+static int pseudoBit(RenderStyle::PseudoId pseudo)
+{
+ switch (pseudo) {
+ case RenderStyle::BEFORE:
+ return BEFORE_BIT;
+ case RenderStyle::AFTER:
+ return AFTER_BIT;
+ case RenderStyle::MARKER:
+ return MARKER_BIT;
+ case RenderStyle::REPLACED:
+ return REPLACED_BIT;
+ case RenderStyle::FIRST_LINE:
+ return FIRST_LINE_BIT;
+ case RenderStyle::FIRST_LETTER:
+ return FIRST_LETTER_BIT;
+ case RenderStyle::SELECTION:
+ return SELECTION_BIT;
+ default:
+ return NO_BIT;
+ }
+}
+
+bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
+{
+ return (pseudoBit(pseudo) & noninherited_flags.f._pseudoBits) != 0;
+}
+
+void RenderStyle::setHasPseudoStyle(PseudoId pseudo, bool b)
+{
+ if (b)
+ noninherited_flags.f._pseudoBits |= pseudoBit(pseudo);
+ else
+ noninherited_flags.f._pseudoBits &= ~(pseudoBit(pseudo));
+}
+
+RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid) const
+{
+ if (!hasPseudoStyle(pid)) return 0;
+
+ RenderStyle *ps = 0;
+ if (noninherited_flags.f._styleType==NOPSEUDO)
+ for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
+ if (ps->noninherited_flags.f._styleType==pid)
+ break;
+ return ps;
+}
+
+RenderStyle* RenderStyle::addPseudoStyle(PseudoId pid)
+{
+ if (hasPseudoStyle(pid)) return getPseudoStyle(pid);
+
+ RenderStyle *ps = 0;
+
+ switch (pid) {
+ case FIRST_LETTER: // pseudo-elements (FIRST_LINE has a special handling)
+ case SELECTION:
+ case BEFORE:
+ case AFTER:
+ ps = new RenderStyle();
+ break;
+ default:
+ ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
+ }
+ ps->ref();
+ ps->noninherited_flags.f._styleType = pid;
+ ps->pseudoStyle = pseudoStyle;
+
+ pseudoStyle = ps;
+
+ setHasPseudoStyle(pid, true);
+
+ return ps;
+}
+
+void RenderStyle::removePseudoStyle(PseudoId pid)
+{
+ RenderStyle *ps = pseudoStyle;
+ RenderStyle *prev = this;
+
+ while (ps) {
+ if (ps->noninherited_flags.f._styleType==pid) {
+ prev->pseudoStyle = ps->pseudoStyle;
+ ps->deref();
+ return;
+ }
+ prev = ps;
+ ps = ps->pseudoStyle;
+ }
+
+ setHasPseudoStyle(pid, false);
+}
+
+
+bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
+{
+ return
+ (
+ inherited_flags != other->inherited_flags ||
+ inherited != other->inherited ||
+ css3InheritedData != other->css3InheritedData
+ );
+}
+
+/*
+ compares two styles. The result gives an idea of the action that
+ needs to be taken when replacing the old style with a new one.
+
+ CbLayout: The containing block of the object needs a relayout.
+ Layout: the RenderObject needs a relayout after the style change
+ Visible: The change is visible, but no relayout is needed
+ NonVisible: The object does need neither repaint nor relayout after
+ the change.
+
+ ### TODO:
+ A lot can be optimised here based on the display type, lots of
+ optimisations are unimplemented, and currently result in the
+ worst case result causing a relayout of the containing block.
+*/
+RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
+{
+ // we anyway assume they are the same
+// EDisplay _display : 5;
+
+ // NonVisible:
+// ECursor _cursor_style : 4;
+// EUserInput _user_input : 2; as long as :enabled is not impl'd
+
+// ### this needs work to know more exactly if we need a relayout
+// or just a repaint
+
+// non-inherited attributes
+// DataRef<StyleBoxData> box;
+// DataRef<StyleVisualData> visual;
+// DataRef<StyleSurroundData> surround;
+
+// inherited attributes
+// DataRef<StyleInheritedData> inherited;
+
+ if ( *box.get() != *other->box.get() ||
+ *visual.get() != *other->visual.get() ||
+ (*surround.get() != *other->surround.get()
+ && (other->position() == STATIC || other->position() != position())) ||
+ !(inherited->indent == other->inherited->indent) ||
+ !(inherited->line_height == other->inherited->line_height) ||
+ !(inherited->style_image == other->inherited->style_image) ||
+ !(inherited->font == other->inherited->font) ||
+ !(inherited->border_hspacing == other->inherited->border_hspacing) ||
+ !(inherited->border_vspacing == other->inherited->border_vspacing) ||
+ !(inherited_flags.f._visuallyOrdered == other->inherited_flags.f._visuallyOrdered) ||
+ !(inherited_flags.f._htmlHacks == other->inherited_flags.f._htmlHacks) ||
+ !(noninherited_flags.f._textOverflow == other->noninherited_flags.f._textOverflow) )
+ return CbLayout;
+
+ // changes causing Layout changes:
+
+// only for tables:
+// _border_collapse
+// EEmptyCell _empty_cells : 2 ;
+// ECaptionSide _caption_side : 2;
+// ETableLayout _table_layout : 1;
+// EPosition _position : 2;
+// EFloat _floating : 2;
+ if ( ((int)noninherited_flags.f._display) >= TABLE ) {
+ if ( !(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
+ !(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
+ !(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
+ !(noninherited_flags.f._table_layout == other->noninherited_flags.f._table_layout) ||
+ !(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
+ !(noninherited_flags.f._floating == other->noninherited_flags.f._floating) ||
+ !(noninherited_flags.f._flowAroundFloats == other->noninherited_flags.f._flowAroundFloats) ||
+ !(noninherited_flags.f._unicodeBidi == other->noninherited_flags.f._unicodeBidi) )
+ return CbLayout;
+ }
+
+// only for lists:
+// EListStyleType _list_style_type : 5 ;
+// EListStylePosition _list_style_position :1;
+ if (noninherited_flags.f._display == LIST_ITEM ) {
+ if ( !(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
+ !(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position) )
+ return Layout;
+ }
+
+// ### These could be better optimised
+// ETextAlign _text_align : 3;
+// ETextTransform _text_transform : 4;
+// EDirection _direction : 1;
+// EWhiteSpace _white_space : 2;
+// EClear _clear : 2;
+ if ( !(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
+ !(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
+ !(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
+ !(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
+ !(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
+ )
+ return Layout;
+
+ // Overflow returns a layout hint.
+ if (noninherited_flags.f._overflowX != other->noninherited_flags.f._overflowX ||
+ noninherited_flags.f._overflowY != other->noninherited_flags.f._overflowY)
+ return Layout;
+
+// only for inline:
+// EVerticalAlign _vertical_align : 4;
+
+ if ( !(noninherited_flags.f._display == INLINE) &&
+ !(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align) )
+ return Layout;
+
+ if (*surround.get() != *other->surround.get()) {
+ assert( other->position() != STATIC ); // this style is positioned or relatively positioned
+ if ( surround->hasSamePBMData(*other->surround.get()) && // padding/border/margin are identical
+ (other->position() == RELATIVE ||
+ !(other->left().isVariable() && other->right().isVariable()) && // X isn't static
+ !(other->top().isVariable() && other->bottom().isVariable()) )) // neither is Y
+ // therefore only the offset is different
+ return Position;
+ return Layout;
+ }
+
+ // Visible:
+// EVisibility _visibility : 2;
+// int _text_decorations : 4;
+// DataRef<StyleBackgroundData> background;
+ if (inherited->color != other->inherited->color ||
+ !(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
+ !(inherited_flags.f._text_decorations == other->inherited_flags.f._text_decorations) ||
+ !(noninherited_flags.f._hasClip == other->noninherited_flags.f._hasClip) ||
+ visual->textDecoration != other->visual->textDecoration ||
+ *background.get() != *other->background.get() ||
+ css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
+ !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
+ )
+ return Visible;
+
+ RenderStyle::Diff ch = Equal;
+ // Check for visible pseudo-changes:
+ if (hasPseudoStyle(FIRST_LINE) != other->hasPseudoStyle(FIRST_LINE))
+ ch = Visible;
+ else
+ if (hasPseudoStyle(FIRST_LINE) && other->hasPseudoStyle(FIRST_LINE))
+ ch = getPseudoStyle(FIRST_LINE)->diff(other->getPseudoStyle(FIRST_LINE));
+
+ if (ch != Equal) return ch;
+
+ // Check for visible pseudo-changes:
+ if (hasPseudoStyle(SELECTION) != other->hasPseudoStyle(SELECTION))
+ ch = Visible;
+ else
+ if (hasPseudoStyle(SELECTION) && other->hasPseudoStyle(SELECTION))
+ ch = getPseudoStyle(SELECTION)->diff(other->getPseudoStyle(SELECTION));
+
+ return ch;
+}
+
+
+RenderStyle* RenderStyle::_default = 0;
+
+void RenderStyle::cleanup()
+{
+ delete _default;
+ _default = 0;
+}
+
+void RenderStyle::setPaletteColor(TQPalette::ColorGroup g, TQColorGroup::ColorRole r, const TQColor& c)
+{
+ visual.access()->palette.setColor(g,r,c);
+}
+
+void RenderStyle::adjustBackgroundLayers()
+{
+ if (backgroundLayers()->next()) {
+ // First we cull out layers that have no properties set.
+ accessBackgroundLayers()->cullEmptyLayers();
+
+ // Next we repeat patterns into layers that don't have some properties set.
+ accessBackgroundLayers()->fillUnsetProperties();
+ }
+}
+
+void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
+{
+ StyleVisualData *data = visual.access();
+ data->clip.top = top;
+ data->clip.right = right;
+ data->clip.bottom = bottom;
+ data->clip.left = left;
+}
+
+void RenderStyle::setQuotes(DOM::QuotesValueImpl* q)
+{
+ DOM::QuotesValueImpl *t = inherited->quotes;
+ inherited.access()->quotes = q;
+ if (q) q->ref();
+ if (t) t->deref();
+}
+
+TQString RenderStyle::openQuote(int level) const
+{
+ if (inherited->quotes)
+ return inherited->quotes->openQuote(level);
+ else
+ return "\""; // 0 is default quotes
+}
+
+TQString RenderStyle::closeQuote(int level) const
+{
+ if (inherited->quotes)
+ return inherited->quotes->closeQuote(level);
+ else
+ return "\""; // 0 is default quotes
+}
+
+void RenderStyle::addContent(CachedObject* o)
+{
+ if (!o)
+ return; // The object is null. Nothing to do. Just bail.
+
+ StyleGeneratedData *t_generated = generated.access();
+
+ ContentData* lastContent = t_generated->content;
+ while (lastContent && lastContent->_nextContent)
+ lastContent = lastContent->_nextContent;
+
+ ContentData* newContentData = new ContentData;
+
+ if (lastContent)
+ lastContent->_nextContent = newContentData;
+ else
+ t_generated->content = newContentData;
+
+ // o->ref();
+ newContentData->_content.object = o;
+ newContentData->_contentType = CONTENT_OBJECT;
+}
+
+void RenderStyle::addContent(DOM::DOMStringImpl* s)
+{
+ if (!s)
+ return; // The string is null. Nothing to do. Just bail.
+
+ StyleGeneratedData *t_generated = generated.access();
+
+ ContentData* lastContent = t_generated->content;
+ while (lastContent && lastContent->_nextContent)
+ lastContent = lastContent->_nextContent;
+
+ if (lastContent) {
+ if (lastContent->_contentType == CONTENT_TEXT) {
+ // We can augment the existing string and share this ContentData node.
+ DOMStringImpl* oldStr = lastContent->_content.text;
+ DOMStringImpl* newStr = oldStr->copy();
+ newStr->ref();
+ oldStr->deref();
+ newStr->append(s);
+ lastContent->_content.text = newStr;
+ return;
+ }
+ }
+
+ ContentData* newContentData = new ContentData;
+
+ if (lastContent)
+ lastContent->_nextContent = newContentData;
+ else
+ t_generated->content = newContentData;
+
+ newContentData->_content.text = s;
+ newContentData->_content.text->ref();
+ newContentData->_contentType = CONTENT_TEXT;
+
+}
+
+void RenderStyle::addContent(DOM::CounterImpl* c)
+{
+ if (!c)
+ return;
+
+ StyleGeneratedData *t_generated = generated.access();
+
+ ContentData* lastContent = t_generated->content;
+ while (lastContent && lastContent->_nextContent)
+ lastContent = lastContent->_nextContent;
+
+ ContentData* newContentData = new ContentData;
+
+ if (lastContent)
+ lastContent->_nextContent = newContentData;
+ else
+ t_generated->content = newContentData;
+
+ c->ref();
+ newContentData->_content.counter = c;
+ newContentData->_contentType = CONTENT_COUNTER;
+}
+
+void RenderStyle::addContent(EQuoteContent q)
+{
+ if (q == NO_QUOTE)
+ return;
+
+ StyleGeneratedData *t_generated = generated.access();
+
+ ContentData* lastContent = t_generated->content;
+ while (lastContent && lastContent->_nextContent)
+ lastContent = lastContent->_nextContent;
+
+ ContentData* newContentData = new ContentData;
+
+ if (lastContent)
+ lastContent->_nextContent = newContentData;
+ else
+ t_generated->content = newContentData;
+
+ newContentData->_content.quote = q;
+ newContentData->_contentType = CONTENT_QUOTE;
+}
+
+// content: normal is the same as having no content at all
+void RenderStyle::setContentNormal() {
+ if (generated->content != 0) {
+ delete generated->content;
+ generated.access()->content = 0;
+ }
+}
+
+// content: none, add an empty content node
+void RenderStyle::setContentNone() {
+ setContentNormal();
+ generated.access()->content = new ContentData;
+}
+
+void RenderStyle::setContentData(ContentData *data) {
+ if (data != generated->content) {
+ if (data)
+ generated.access()->content = new ContentData(*data);
+ else
+ generated.access()->content = 0;
+ }
+}
+
+ContentData::ContentData(const ContentData& o) : _contentType(o._contentType)
+{
+ switch (_contentType) {
+ case CONTENT_OBJECT:
+ _content.object = o._content.object;
+ break;
+ case CONTENT_TEXT:
+ _content.text = o._content.text;
+ _content.text->ref();
+ break;
+ case CONTENT_COUNTER:
+ _content.counter = o._content.counter;
+ _content.counter->ref();
+ break;
+ case CONTENT_QUOTE:
+ _content.quote = o._content.quote;
+ break;
+ case CONTENT_NONE:
+ default:
+ break;
+ }
+
+ _nextContent = o._nextContent ? new ContentData(*o._nextContent) : 0;
+}
+
+ContentData::~ContentData()
+{
+ clearContent();
+}
+
+void ContentData::clearContent()
+{
+ delete _nextContent;
+ _nextContent = 0;
+
+ switch (_contentType)
+ {
+ case CONTENT_OBJECT:
+ _content.object = 0;
+ break;
+ case CONTENT_TEXT:
+ _content.text->deref();
+ _content.text = 0;
+ break;
+ case CONTENT_COUNTER:
+ _content.counter->deref();
+ _content.counter = 0;
+ break;
+ case CONTENT_QUOTE:
+ _content.quote = NO_QUOTE;
+ break;
+ default:
+ ;
+ }
+}
+
+void RenderStyle::setTextShadow(ShadowData* val, bool add)
+{
+ StyleCSS3InheritedData* css3Data = css3InheritedData.access();
+ if (!add) {
+ delete css3Data->textShadow;
+ css3Data->textShadow = val;
+ return;
+ }
+
+ ShadowData* last = css3Data->textShadow;
+ while (last->next) last = last->next;
+ last->next = val;
+}
+
+ShadowData::ShadowData(const ShadowData& o)
+:x(o.x), y(o.y), blur(o.blur), color(o.color)
+{
+ next = o.next ? new ShadowData(*o.next) : 0;
+}
+
+bool ShadowData::operator==(const ShadowData& o) const
+{
+ if ((next && !o.next) || (!next && o.next) ||
+ (next && o.next && *next != *o.next))
+ return false;
+
+ return x == o.x && y == o.y && blur == o.blur && color == o.color;
+}
+
+static bool hasCounter(const DOM::DOMString& c, CSSValueListImpl *l)
+{
+ int len = l->length();
+ for(int i=0; i<len; i++) {
+ CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
+ Q_ASSERT(ca != 0);
+ if (ca->m_counter == c) return true;
+ }
+ return false;
+}
+
+bool RenderStyle::hasCounterReset(const DOM::DOMString& c) const
+{
+ if (generated->counter_reset)
+ return hasCounter(c, generated->counter_reset);
+ else
+ return false;
+}
+
+bool RenderStyle::hasCounterIncrement(const DOM::DOMString& c) const
+{
+ if (generated->counter_increment)
+ return hasCounter(c, generated->counter_increment);
+ else
+ return false;
+}
+
+static short readCounter(const DOM::DOMString& c, CSSValueListImpl *l)
+{
+ int len = l->length();
+ for(int i=0; i<len; i++) {
+ CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
+ Q_ASSERT(ca != 0);
+ if (ca->m_counter == c) return ca->m_value;
+ }
+ return 0;
+}
+
+short RenderStyle::counterReset(const DOM::DOMString& c) const
+{
+ if (generated->counter_reset)
+ return readCounter(c, generated->counter_reset);
+ else
+ return 0;
+}
+
+short RenderStyle::counterIncrement(const DOM::DOMString& c) const
+{
+ if (generated->counter_increment)
+ return readCounter(c, generated->counter_increment);
+ else
+ return 0;
+}
+
+void RenderStyle::setCounterReset(CSSValueListImpl *l)
+{
+ CSSValueListImpl *t = generated->counter_reset;
+ generated.access()->counter_reset = l;
+ if (l) l->ref();
+ if (t) t->deref();
+}
+
+void RenderStyle::setCounterIncrement(CSSValueListImpl *l)
+{
+ CSSValueListImpl *t = generated->counter_increment;
+ generated.access()->counter_increment = l;
+ if (l) l->ref();
+ if (t) t->deref();
+}
+
+#ifdef ENABLE_DUMP
+
+static TQString describeFont( const TQFont &f)
+{
+ TQString res = "'" + f.family() + "' ";
+
+ if ( f.pointSize() > 0)
+ res += TQString::number( f.pointSize() ) + "pt";
+ else
+ res += TQString::number( f.pixelSize() ) + "px";
+
+ if ( f.bold() )
+ res += " bold";
+ if ( f.italic() )
+ res += " italic";
+ if ( f.underline() )
+ res += " underline";
+ if ( f.overline() )
+ res += " overline";
+ if ( f.strikeOut() )
+ res += " strikeout";
+ return res;
+}
+
+TQString RenderStyle::createDiff( const RenderStyle &parent ) const
+{
+ TQString res;
+ if ( color().isValid() && parent.color() != color() )
+ res += " [color=" + color().name() + "]";
+ if ( backgroundColor().isValid() && parent.backgroundColor() != backgroundColor() )
+ res += " [bgcolor=" + backgroundColor().name() + "]";
+ if ( parent.font() != font() )
+ res += " [font=" + describeFont( font() ) + "]";
+
+ return res;
+}
+#endif
+
+RenderPageStyle::RenderPageStyle() : next(0), m_pageType(ANY_PAGE)
+{
+}
+
+RenderPageStyle::~RenderPageStyle()
+{
+ delete next;
+}
+
+RenderPageStyle* RenderPageStyle::getPageStyle(PageType type)
+{
+ RenderPageStyle *ps = 0;
+ for (ps = this; ps; ps = ps->next)
+ if (ps->m_pageType==type)
+ break;
+ return ps;
+}
+
+RenderPageStyle* RenderPageStyle::addPageStyle(PageType type)
+{
+ RenderPageStyle *ps = getPageStyle(type);
+
+ if (!ps)
+ {
+ ps = new RenderPageStyle(*this); // use the real copy constructor to get an identical copy
+ ps->m_pageType = type;
+
+ ps->next = next;
+ next = ps;
+ }
+
+ return ps;
+}
+
+void RenderPageStyle::removePageStyle(PageType type)
+{
+ RenderPageStyle *ps = next;
+ RenderPageStyle *prev = this;
+
+ while (ps) {
+ if (ps->m_pageType==type) {
+ prev->next = ps->next;
+ delete ps;
+ return;
+ }
+ prev = ps;
+ ps = ps->next;
+ }
+}
diff --git a/tdehtml/rendering/render_style.h b/tdehtml/rendering/render_style.h
new file mode 100644
index 000000000..6e1b9cbc8
--- /dev/null
+++ b/tdehtml/rendering/render_style.h
@@ -0,0 +1,1524 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2003-2005 Apple Computer, Inc.
+ * (C) 2004-2006 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.
+ *
+ */
+#ifndef RENDERSTYLE_H
+#define RENDERSTYLE_H
+
+/*
+ * WARNING:
+ * --------
+ *
+ * The order of the values in the enums have to agree with the order specified
+ * in cssvalues.in, otherwise some optimizations in the parser will fail,
+ * and produce invaliud results.
+ */
+
+#include <tqcolor.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqptrlist.h>
+#include <tqpalette.h>
+#include <tqapplication.h>
+
+#include "dom/dom_misc.h"
+#include "dom/dom_string.h"
+#include "misc/tdehtmllayout.h"
+#include "misc/shared.h"
+#include "rendering/font.h"
+
+#include <assert.h>
+
+#define SET_VAR(group,variable,value) \
+ if (!(group->variable == value)) \
+ group.access()->variable = value;
+
+#ifndef ENABLE_DUMP
+#ifndef NDEBUG
+#define ENABLE_DUMP 1
+#endif
+#endif
+
+namespace DOM {
+ class DOMStringImpl;
+ class ShadowValueImpl;
+ class QuotesValueImpl;
+ class CounterImpl;
+ class CSSValueListImpl;
+ class CounterActImpl;
+}
+
+namespace tdehtml {
+
+ class CachedImage;
+ class CachedObject;
+
+template <class DATA>
+class DataRef
+{
+public:
+
+ DataRef()
+ {
+ data=0;
+ }
+ DataRef( const DataRef<DATA> &d )
+ {
+ data = d.data;
+ data->ref();
+ }
+
+ ~DataRef()
+ {
+ if(data) data->deref();
+ }
+
+ const DATA* operator->() const
+ {
+ return data;
+ }
+
+ const DATA* get() const
+ {
+ return data;
+ }
+
+
+ DATA* access()
+ {
+ if (!data->hasOneRef())
+ {
+ data->deref();
+ data = new DATA(*data);
+ data->ref();
+ }
+ return data;
+ }
+
+ void init()
+ {
+ data = new DATA;
+ data->ref();
+ }
+
+ DataRef<DATA>& operator=(const DataRef<DATA>& d)
+ {
+ if (data==d.data)
+ return *this;
+ if (data)
+ data->deref();
+ data = d.data;
+
+ data->ref();
+
+ return *this;
+ }
+
+ bool operator == ( const DataRef<DATA> &o ) const {
+ return (*data == *(o.data) );
+ }
+ bool operator != ( const DataRef<DATA> &o ) const {
+ return (*data != *(o.data) );
+ }
+
+private:
+ DATA* data;
+};
+
+
+//------------------------------------------------
+
+//------------------------------------------------
+// Box model attributes. Not inherited.
+
+struct LengthBox
+{
+ LengthBox()
+ {
+ }
+ LengthBox( LengthType t )
+ : left( t ), right ( t ), top( t ), bottom( t ) {}
+
+ Length left;
+ Length right;
+ Length top;
+ Length bottom;
+ Length& operator=(Length& len)
+ {
+ left=len;
+ right=len;
+ top=len;
+ bottom=len;
+ return len;
+ }
+
+ bool operator==(const LengthBox& o) const
+ {
+ return left==o.left && right==o.right && top==o.top && bottom==o.bottom;
+ }
+
+
+ bool nonZero() const { return left.value() || right.value() || top.value() || bottom.value(); }
+};
+
+
+
+enum EPosition {
+ STATIC, RELATIVE, ABSOLUTE, FIXED
+};
+
+enum EFloat {
+ FNONE = 0, FLEFT = 0x01, FRIGHT = 0x02, FLEFT_ALIGN = 0x05, FRIGHT_ALIGN = 0x06
+};
+
+enum EWordWrap {
+ WWNORMAL = 0, WWBREAKWORD = 0x01
+};
+
+//------------------------------------------------
+// Border attributes. Not inherited.
+
+
+// These have been defined in the order of their precedence for border-collapsing. Do
+// not change this order!
+enum EBorderStyle {
+ BNATIVE, BNONE, BHIDDEN, INSET, GROOVE, RIDGE, OUTSET, DOTTED, DASHED, SOLID, DOUBLE
+};
+
+class BorderValue
+{
+public:
+ BorderValue() : width( 3 ), style( BNONE ) {}
+
+ TQColor color;
+ unsigned short width : 12;
+ EBorderStyle style : 6;
+
+ bool nonZero(bool checkStyle = true) const {
+ return width != 0 && !(checkStyle && style == BNONE);
+ }
+
+ bool isTransparent() const {
+ return color.isValid() && tqAlpha(color.rgb()) == 0;
+ }
+
+ bool operator==(const BorderValue& o) const
+ {
+ return width==o.width && style==o.style && color==o.color;
+ }
+
+ bool operator!=(const BorderValue& o) const
+ {
+ return !(*this == o);
+ }
+};
+
+class OutlineValue : public BorderValue
+{
+ public:
+ OutlineValue()
+ {
+ _offset = 0;
+ _auto = false;
+ }
+
+ bool operator==(const OutlineValue& o) const
+ {
+ return width==o.width && style==o.style && color==o.color && _offset == o._offset && _auto == o._auto;
+ }
+
+ bool operator!=(const OutlineValue& o) const
+ {
+ return !(*this == o);
+ }
+
+ int _offset;
+ bool _auto;
+};
+
+enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL };
+
+struct CollapsedBorderValue
+{
+ CollapsedBorderValue() :border(0), precedence(BOFF) {}
+ CollapsedBorderValue(const BorderValue* b, EBorderPrecedence p) :border(b), precedence(p) {}
+
+ int width() const { return border && border->nonZero() ? border->width : 0; }
+ EBorderStyle style() const { return border ? border->style : BHIDDEN; }
+ bool exists() const { return border; }
+ TQColor color() const { return border ? border->color : TQColor(); }
+ bool isTransparent() const { return border ? border->isTransparent() : true; }
+
+ bool operator==(const CollapsedBorderValue& o) const
+ {
+ if (!border) return !o.border;
+ if (!o.border) return false;
+ return *border == *o.border && precedence == o.precedence;
+ }
+
+ const BorderValue* border;
+ EBorderPrecedence precedence;
+};
+
+class BorderData : public Shared<BorderData>
+{
+public:
+ BorderValue left;
+ BorderValue right;
+ BorderValue top;
+ BorderValue bottom;
+
+ bool hasBorder() const
+ {
+ return left.nonZero() || right.nonZero() || top.nonZero() || bottom.nonZero();
+ }
+
+ unsigned short borderLeftWidth() const {
+ if (left.style == BNONE || left.style == BHIDDEN || left.style == BNATIVE)
+ return 0;
+ return left.width;
+ }
+
+ unsigned short borderRightWidth() const {
+ if (right.style == BNONE || right.style == BHIDDEN || right.style == BNATIVE)
+ return 0;
+ return right.width;
+ }
+
+ unsigned short borderTopWidth() const {
+ if (top.style == BNONE || top.style == BHIDDEN || top.style == BNATIVE)
+ return 0;
+ return top.width;
+ }
+
+ unsigned short borderBottomWidth() const {
+ if (bottom.style == BNONE || bottom.style == BHIDDEN || bottom.style == BNATIVE)
+ return 0;
+ return bottom.width;
+ }
+
+ bool operator==(const BorderData& o) const
+ {
+ return left==o.left && right==o.right && top==o.top && bottom==o.bottom;
+ }
+
+};
+
+class StyleSurroundData : public Shared<StyleSurroundData>
+{
+public:
+ StyleSurroundData();
+
+ StyleSurroundData(const StyleSurroundData& o );
+ bool operator==(const StyleSurroundData& o) const;
+ bool operator!=(const StyleSurroundData& o) const {
+ return !(*this == o);
+ }
+ bool hasSamePBMData(const StyleSurroundData& o) const {
+ return (margin == o.margin) && (padding == o.padding) && (border == o.border);
+ }
+
+ LengthBox offset;
+ LengthBox margin;
+ LengthBox padding;
+ BorderData border;
+};
+
+
+//------------------------------------------------
+// Box attributes. Not inherited.
+
+enum EBoxSizing {
+ BORDER_BOX, CONTENT_BOX
+};
+
+class StyleBoxData : public Shared<StyleBoxData>
+{
+public:
+ StyleBoxData();
+
+ StyleBoxData(const StyleBoxData& o );
+
+
+ // copy and assignment
+// StyleBoxData(const StyleBoxData &other);
+// const StyleBoxData &operator = (const StyleBoxData &other);
+
+ bool operator==(const StyleBoxData& o) const;
+ bool operator!=(const StyleBoxData& o) const {
+ return !(*this == o);
+ }
+
+ Length width;
+ Length height;
+
+ Length min_width;
+ Length max_width;
+
+ Length min_height;
+ Length max_height;
+
+ Length vertical_align;
+
+ EBoxSizing box_sizing;
+
+ signed int z_index :31;
+ bool z_auto : 1;
+};
+
+//------------------------------------------------
+// Random visual rendering model attributes. Not inherited.
+
+enum EOverflow {
+ OVISIBLE, OHIDDEN, OSCROLL, OAUTO, OMARQUEE
+};
+
+enum EVerticalAlign {
+ BASELINE, MIDDLE, SUB, SUPER, TEXT_TOP,
+ TEXT_BOTTOM, TOP, BOTTOM, BASELINE_MIDDLE, LENGTH
+};
+
+enum EClear{
+ CNONE = 0, CLEFT = 1, CRIGHT = 2, CBOTH = 3
+};
+
+enum ETableLayout {
+ TAUTO, TFIXED
+};
+
+enum EUnicodeBidi {
+ UBNormal, Embed, Override
+};
+
+class StyleVisualData : public Shared<StyleVisualData>
+{
+public:
+ StyleVisualData();
+
+ ~StyleVisualData();
+
+ StyleVisualData(const StyleVisualData& o );
+
+ bool operator==( const StyleVisualData &o ) const {
+ return ( clip == o.clip &&
+ palette == o.palette );
+ }
+ bool operator!=( const StyleVisualData &o ) const {
+ return !(*this == o);
+ }
+
+ LengthBox clip;
+ unsigned textDecoration : 4; // Text decorations defined *only* by this element.
+
+ TQPalette palette; //widget styling with IE attributes
+
+};
+
+//------------------------------------------------
+enum EBackgroundBox {
+ BGBORDER, BGPADDING, BGCONTENT
+};
+
+enum EBackgroundRepeat {
+ REPEAT, REPEAT_X, REPEAT_Y, NO_REPEAT
+};
+
+struct LengthSize {
+ Length width;
+ Length height;
+};
+
+struct BackgroundLayer {
+public:
+ BackgroundLayer();
+ ~BackgroundLayer();
+
+ CachedImage* backgroundImage() const { return m_image; }
+ Length backgroundXPosition() const { return m_xPosition; }
+ Length backgroundYPosition() const { return m_yPosition; }
+ bool backgroundAttachment() const { return m_bgAttachment; }
+ EBackgroundBox backgroundClip() const { return m_bgClip; }
+ EBackgroundBox backgroundOrigin() const { return m_bgOrigin; }
+ EBackgroundRepeat backgroundRepeat() const { return m_bgRepeat; }
+ LengthSize backgroundSize() const { return m_backgroundSize; }
+
+ BackgroundLayer* next() const { return m_next; }
+ BackgroundLayer* next() { return m_next; }
+
+ bool isBackgroundImageSet() const { return m_imageSet; }
+ bool isBackgroundXPositionSet() const { return m_xPosSet; }
+ bool isBackgroundYPositionSet() const { return m_yPosSet; }
+ bool isBackgroundAttachmentSet() const { return m_attachmentSet; }
+ bool isBackgroundClipSet() const { return m_clipSet; }
+ bool isBackgroundOriginSet() const { return m_originSet; }
+ bool isBackgroundRepeatSet() const { return m_repeatSet; }
+ bool isBackgroundSizeSet() const { return m_backgroundSizeSet; }
+
+ void setBackgroundImage(CachedImage* i) { m_image = i; m_imageSet = true; }
+ void setBackgroundXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; }
+ void setBackgroundYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; }
+ void setBackgroundAttachment(bool b) { m_bgAttachment = b; m_attachmentSet = true; }
+ void setBackgroundClip(EBackgroundBox b) { m_bgClip = b; m_clipSet = true; }
+ void setBackgroundOrigin(EBackgroundBox b) { m_bgOrigin = b; m_originSet = true; }
+ void setBackgroundRepeat(EBackgroundRepeat r) { m_bgRepeat = r; m_repeatSet = true; }
+ void setBackgroundSize(const LengthSize& b) { m_backgroundSize = b; m_backgroundSizeSet = true; }
+
+ void clearBackgroundImage() { m_imageSet = false; }
+ void clearBackgroundXPosition() { m_xPosSet = false; }
+ void clearBackgroundYPosition() { m_yPosSet = false; }
+ void clearBackgroundAttachment() { m_attachmentSet = false; }
+ void clearBackgroundClip() { m_clipSet = false; }
+ void clearBackgroundOrigin() { m_originSet = false; }
+ void clearBackgroundRepeat() { m_repeatSet = false; }
+ void clearBackgroundSize() { m_backgroundSizeSet = false; }
+
+ void setNext(BackgroundLayer* n) { if (m_next != n) { delete m_next; m_next = n; } }
+
+ BackgroundLayer& operator=(const BackgroundLayer& o);
+ BackgroundLayer(const BackgroundLayer& o);
+
+ bool operator==(const BackgroundLayer& o) const;
+ bool operator!=(const BackgroundLayer& o) const {
+ return !(*this == o);
+ }
+
+ bool containsImage(CachedImage* c) const { if (c == m_image) return true; if (m_next) return m_next->containsImage(c); return false; }
+
+ bool hasImage() const {
+ if (m_image)
+ return true;
+ return m_next ? m_next->hasImage() : false;
+ }
+ bool hasFixedImage() const {
+ if (m_image && !m_bgAttachment)
+ return true;
+ return m_next ? m_next->hasFixedImage() : false;
+ }
+
+ void fillUnsetProperties();
+ void cullEmptyLayers();
+
+ CachedImage* m_image;
+
+ Length m_xPosition;
+ Length m_yPosition;
+
+ bool m_bgAttachment : 1;
+ EBackgroundBox m_bgClip : 2;
+ EBackgroundBox m_bgOrigin : 2;
+ EBackgroundRepeat m_bgRepeat : 2;
+
+ LengthSize m_backgroundSize;
+
+ bool m_imageSet : 1;
+ bool m_attachmentSet : 1;
+ bool m_clipSet : 1;
+ bool m_originSet : 1;
+ bool m_repeatSet : 1;
+ bool m_xPosSet : 1;
+ bool m_yPosSet : 1;
+ bool m_backgroundSizeSet : 1;
+
+ BackgroundLayer* m_next;
+};
+
+class StyleBackgroundData : public Shared<StyleBackgroundData>
+{
+public:
+ StyleBackgroundData();
+ ~StyleBackgroundData() {}
+ StyleBackgroundData(const StyleBackgroundData& o );
+
+ bool operator==(const StyleBackgroundData& o) const;
+ bool operator!=(const StyleBackgroundData &o) const {
+ return !(*this == o);
+ }
+
+ BackgroundLayer m_background;
+ TQColor m_color;
+ OutlineValue m_outline;
+};
+
+enum EQuoteContent {
+ NO_QUOTE = 0, OPEN_QUOTE, CLOSE_QUOTE, NO_OPEN_QUOTE, NO_CLOSE_QUOTE
+};
+
+enum ContentType {
+ CONTENT_NONE = 0, CONTENT_NORMAL, CONTENT_OBJECT,
+ CONTENT_TEXT, CONTENT_COUNTER, CONTENT_QUOTE
+};
+
+struct ContentData {
+ ContentData() : _contentType( CONTENT_NONE ), _nextContent(0) {}
+ ContentData(const ContentData& o);
+ ~ContentData();
+ void clearContent();
+
+ DOM::DOMStringImpl* contentText()
+ { if (_contentType == CONTENT_TEXT) return _content.text; return 0; }
+ CachedObject* contentObject()
+ { if (_contentType == CONTENT_OBJECT) return _content.object; return 0; }
+ DOM::CounterImpl* contentCounter()
+ { if (_contentType == CONTENT_COUNTER) return _content.counter; return 0; }
+ EQuoteContent contentQuote()
+ { if (_contentType == CONTENT_QUOTE) return _content.quote; return NO_QUOTE; }
+
+ ContentType _contentType;
+
+ union {
+ CachedObject* object;
+ DOM::DOMStringImpl* text;
+ DOM::CounterImpl* counter;
+ EQuoteContent quote;
+ } _content ;
+
+ ContentData* _nextContent;
+};
+
+class StyleGeneratedData : public Shared<StyleGeneratedData>
+{
+public:
+ StyleGeneratedData();
+ ~StyleGeneratedData();
+ StyleGeneratedData(const StyleGeneratedData& o );
+
+ bool operator==(const StyleGeneratedData& o) const;
+ bool operator!=(const StyleGeneratedData &o) const {
+ return !(*this == o);
+ }
+
+ bool contentDataEquivalent(const StyleGeneratedData* otherStyle) const;
+ bool counterDataEquivalent(const StyleGeneratedData* otherStyle) const;
+
+ ContentData *content;
+ DOM::CSSValueListImpl *counter_reset;
+ DOM::CSSValueListImpl *counter_increment;
+};
+
+//------------------------------------------------
+// CSS3 Marquee Properties
+
+enum EMarqueeBehavior { MNONE, MSCROLL, MSLIDE, MALTERNATE, MUNFURL };
+enum EMarqueeDirection { MAUTO = 0, MLEFT = 1, MRIGHT = -1, MUP = 2, MDOWN = -2, MFORWARD = 3, MBACKWARD = -3 };
+
+class StyleMarqueeData : public Shared<StyleMarqueeData>
+{
+public:
+ StyleMarqueeData();
+ StyleMarqueeData(const StyleMarqueeData& o);
+
+ bool operator==(const StyleMarqueeData& o) const;
+ bool operator!=(const StyleMarqueeData& o) const {
+ return !(*this == o);
+ }
+
+ Length increment;
+ int speed;
+
+ int loops; // -1 means infinite.
+
+ EMarqueeBehavior behavior : 3;
+ EMarqueeDirection direction : 3;
+};
+
+// This struct holds information about shadows for the text-shadow and box-shadow properties.
+struct ShadowData {
+ ShadowData(int _x, int _y, int _blur, const TQColor& _color)
+ :x(_x), y(_y), blur(_blur), color(_color), next(0) {}
+ ShadowData(const ShadowData& o);
+
+ ~ShadowData() { delete next; }
+
+ bool operator==(const ShadowData& o) const;
+ bool operator!=(const ShadowData &o) const {
+ return !(*this == o);
+ }
+
+ int x;
+ int y;
+ int blur;
+ TQColor color;
+ ShadowData* next;
+};
+
+// This struct is for rarely used non-inherited CSS3 properties. By grouping them together,
+// we save space, and only allocate this object when someone actually uses
+// a non-inherited CSS3 property.
+class StyleCSS3NonInheritedData : public Shared<StyleCSS3NonInheritedData>
+{
+public:
+ StyleCSS3NonInheritedData();
+ ~StyleCSS3NonInheritedData() {}
+ StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o);
+
+ bool operator==(const StyleCSS3NonInheritedData& o) const;
+ bool operator!=(const StyleCSS3NonInheritedData &o) const {
+ return !(*this == o);
+ }
+
+ float opacity; // Whether or not we're transparent.
+#ifdef APPLE_CHANGES // ### we don't have those (yet)
+ DataRef<StyleFlexibleBoxData> flexibleBox; // Flexible box properties
+#endif
+ DataRef<StyleMarqueeData> marquee; // Marquee properties
+};
+
+// This struct is for rarely used inherited CSS3 properties. By grouping them together,
+// we save space, and only allocate this object when someone actually uses
+// an inherited CSS3 property.
+class StyleCSS3InheritedData : public Shared<StyleCSS3InheritedData>
+{
+ public:
+ StyleCSS3InheritedData();
+ ~StyleCSS3InheritedData();
+ StyleCSS3InheritedData(const StyleCSS3InheritedData& o);
+
+ bool operator==(const StyleCSS3InheritedData& o) const;
+ bool operator!=(const StyleCSS3InheritedData &o) const {
+ return !(*this == o);
+ }
+ bool shadowDataEquivalent(const StyleCSS3InheritedData& o) const;
+
+ ShadowData* textShadow; // Our text shadow information for shadowed text drawing.
+#ifdef APPLE_CHANGES
+ EUserModify userModify : 2; // Flag used for editing state
+ bool textSizeAdjust : 1; // An Apple extension. Not really CSS3 but not worth making a new struct over.
+#endif
+ EWordWrap wordWrap : 1;
+ private:
+ StyleCSS3InheritedData &operator=(const StyleCSS3InheritedData &);
+};
+
+//------------------------------------------------
+// Inherited attributes.
+//
+// the inherited-decoration and inherited-shadow attributes
+// are inherited from the
+// first parent which is block level
+//
+
+enum EWhiteSpace {
+ NORMAL, PRE, NOWRAP, PRE_WRAP, PRE_LINE, KHTML_NOWRAP
+};
+
+enum ETextAlign {
+ TAAUTO, LEFT, RIGHT, CENTER, JUSTIFY, KHTML_LEFT, KHTML_RIGHT, KHTML_CENTER
+};
+
+enum ETextTransform {
+ CAPITALIZE, UPPERCASE, LOWERCASE, TTNONE
+};
+
+enum EDirection {
+ LTR, RTL
+};
+
+enum ETextDecoration {
+ TDNONE = 0x0 , UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4, BLINK = 0x8
+};
+
+enum EPageBreak {
+ PBAUTO, PBALWAYS, PBAVOID,
+ /* reserved for later use: */
+ PBLEFT, PBRIGHT
+};
+
+class StyleInheritedData : public Shared<StyleInheritedData>
+{
+ StyleInheritedData& operator=(const StyleInheritedData&);
+public:
+ StyleInheritedData();
+ ~StyleInheritedData();
+ StyleInheritedData(const StyleInheritedData& o );
+
+ bool operator==(const StyleInheritedData& o) const;
+ bool operator != ( const StyleInheritedData &o ) const {
+ return !(*this == o);
+ }
+
+ Length indent;
+ // could be packed in a short but doesn't
+ // make a difference currently because of padding
+ Length line_height;
+
+ CachedImage *style_image;
+
+ tdehtml::Font font;
+ TQColor color;
+
+ short border_hspacing;
+ short border_vspacing;
+
+ // Paged media properties.
+ short widows;
+ short orphans;
+
+ DOM::QuotesValueImpl* quotes;
+};
+
+
+enum EEmptyCell {
+ SHOW, HIDE
+};
+
+enum ECaptionSide {
+ CAPTOP, CAPBOTTOM, CAPLEFT, CAPRIGHT
+};
+
+
+enum EListStyleType {
+ // Symbols:
+ LDISC, LCIRCLE, LSQUARE, LBOX, LDIAMOND,
+ // Numeric:
+ LDECIMAL, DECIMAL_LEADING_ZERO, ARABIC_INDIC, LAO, PERSIAN, URDU, THAI, TIBETAN,
+ // Algorithmic:
+ LOWER_ROMAN, UPPER_ROMAN, HEBREW, ARMENIAN, GEORGIAN,
+ // Ideographic:
+ CJK_IDEOGRAPHIC, JAPANESE_FORMAL, JAPANESE_INFORMAL,
+ SIMP_CHINESE_FORMAL, SIMP_CHINESE_INFORMAL, TRAD_CHINESE_FORMAL, TRAD_CHINESE_INFORMAL,
+ // Alphabetic:
+ LOWER_GREEK, UPPER_GREEK, LOWER_ALPHA, LOWER_LATIN, UPPER_ALPHA, UPPER_LATIN,
+ HIRAGANA, KATAKANA, HIRAGANA_IROHA, KATAKANA_IROHA,
+ // Special:
+ LNONE
+};
+
+inline bool isListStyleCounted(EListStyleType type)
+{
+ switch(type) {
+ case LDISC: case LCIRCLE: case LSQUARE: case LBOX: case LDIAMOND:
+ case LNONE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+enum EListStylePosition { OUTSIDE, INSIDE };
+
+enum EVisibility { VISIBLE, HIDDEN, COLLAPSE };
+
+enum ECursor {
+ CURSOR_AUTO, CURSOR_CROSS, CURSOR_DEFAULT, CURSOR_POINTER, CURSOR_PROGRESS, CURSOR_MOVE,
+ CURSOR_E_RESIZE, CURSOR_NE_RESIZE, CURSOR_NW_RESIZE, CURSOR_N_RESIZE, CURSOR_SE_RESIZE, CURSOR_SW_RESIZE,
+ CURSOR_S_RESIZE, CURSOR_W_RESIZE, CURSOR_TEXT, CURSOR_WAIT, CURSOR_HELP
+};
+
+enum EUserInput {
+ UI_ENABLED, UI_DISABLED, UI_NONE
+};
+
+//------------------------------------------------
+
+enum EDisplay {
+ INLINE, BLOCK, LIST_ITEM, RUN_IN,
+ COMPACT, INLINE_BLOCK, TABLE, INLINE_TABLE,
+ TABLE_ROW_GROUP, TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
+ TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
+ TABLE_CAPTION, NONE
+};
+
+class RenderStyle : public Shared<RenderStyle>
+{
+ friend class CSSStyleSelector;
+public:
+ KDE_EXPORT static void cleanup();
+
+ // pseudo elements
+ enum PseudoId {
+ NOPSEUDO, FIRST_LINE, FIRST_LETTER, SELECTION,
+ BEFORE, AFTER, REPLACED, MARKER
+ };
+
+protected:
+
+// !START SYNC!: Keep this in sync with the copy constructor in render_style.cpp
+
+ // inherit
+ struct InheritedFlags {
+ // 64 bit inherited, update unused when adding to the struct, or the operator will break.
+ bool operator==( const InheritedFlags &other ) const
+ { return _iflags ==other._iflags; }
+ bool operator!=( const InheritedFlags &other ) const
+ { return _iflags != other._iflags; }
+
+ union {
+ struct {
+ EEmptyCell _empty_cells : 1 ;
+ ECaptionSide _caption_side : 2;
+ EListStyleType _list_style_type : 6;
+ EListStylePosition _list_style_position :1;
+
+ EVisibility _visibility : 2;
+ ETextAlign _text_align : 4;
+ ETextTransform _text_transform : 2;
+ unsigned _text_decorations : 4;
+ ECursor _cursor_style : 5;
+
+ EDirection _direction : 1;
+ bool _border_collapse : 1 ;
+ EWhiteSpace _white_space : 3;
+ // non CSS2 inherited
+ bool _visuallyOrdered : 1;
+ bool _htmlHacks :1;
+ EUserInput _user_input : 2;
+
+ bool _page_break_inside : 1; // AUTO/AVOID
+
+ unsigned int unused : 27;
+ } f;
+ TQ_UINT64 _iflags;
+ };
+ } inherited_flags;
+
+// don't inherit
+ struct NonInheritedFlags {
+ // 64 bit non-inherited, update unused when adding to the struct, or the operator will break.
+ bool operator==( const NonInheritedFlags &other ) const
+ { return _niflags == other._niflags; }
+ bool operator!=( const NonInheritedFlags &other ) const
+ { return _niflags != other._niflags; }
+
+ union {
+ struct {
+ EDisplay _display : 5;
+ EDisplay _originalDisplay: 5;
+ EOverflow _overflowX : 4 ;
+ EOverflow _overflowY : 4 ;
+ EVerticalAlign _vertical_align : 4;
+ EClear _clear : 2;
+ EPosition _position : 2;
+ EFloat _floating : 3;
+ ETableLayout _table_layout : 1;
+ bool _flowAroundFloats :1;
+
+ EPageBreak _page_break_before : 3;
+ EPageBreak _page_break_after : 3;
+
+ PseudoId _styleType : 4;
+ bool _hasClip : 1;
+ unsigned _pseudoBits : 8;
+ EUnicodeBidi _unicodeBidi : 2;
+
+ // non CSS2 non-inherited
+ bool _textOverflow : 1; // Whether or not lines that spill out should be truncated with "..."
+
+ unsigned int unused : 11;
+ } f;
+ TQ_UINT64 _niflags;
+ };
+ } noninherited_flags;
+
+// non-inherited attributes
+ DataRef<StyleBoxData> box;
+ DataRef<StyleVisualData> visual;
+ DataRef<StyleBackgroundData> background;
+ DataRef<StyleSurroundData> surround;
+ DataRef<StyleGeneratedData> generated;
+ DataRef<StyleCSS3NonInheritedData> css3NonInheritedData;
+
+// inherited attributes
+ DataRef<StyleCSS3InheritedData> css3InheritedData;
+ DataRef<StyleInheritedData> inherited;
+
+// list of associated pseudo styles
+ RenderStyle* pseudoStyle;
+
+// !END SYNC!
+
+// static default style
+ static RenderStyle* _default;
+
+private:
+ RenderStyle(const RenderStyle*) {}
+
+protected:
+ void setBitDefaults()
+ {
+ inherited_flags.f._empty_cells = initialEmptyCells();
+ inherited_flags.f._caption_side = initialCaptionSide();
+ inherited_flags.f._list_style_type = initialListStyleType();
+ inherited_flags.f._list_style_position = initialListStylePosition();
+ inherited_flags.f._visibility = initialVisibility();
+ inherited_flags.f._text_align = initialTextAlign();
+ inherited_flags.f._text_transform = initialTextTransform();
+ inherited_flags.f._text_decorations = initialTextDecoration();
+ inherited_flags.f._cursor_style = initialCursor();
+ inherited_flags.f._direction = initialDirection();
+ inherited_flags.f._border_collapse = initialBorderCollapse();
+ inherited_flags.f._white_space = initialWhiteSpace();
+ inherited_flags.f._visuallyOrdered = false;
+ inherited_flags.f._htmlHacks=false;
+ inherited_flags.f._user_input = UI_NONE;
+ inherited_flags.f._page_break_inside = true;
+ inherited_flags.f.unused = 0;
+
+ noninherited_flags._niflags = 0L; // for safety: without this, the equality method sometimes
+ // makes use of uninitialised bits according to valgrind
+
+ noninherited_flags.f._display = noninherited_flags.f._originalDisplay = initialDisplay();
+ noninherited_flags.f._overflowX = initialOverflowX();
+ noninherited_flags.f._overflowY = initialOverflowY();
+ noninherited_flags.f._vertical_align = initialVerticalAlign();
+ noninherited_flags.f._clear = initialClear();
+ noninherited_flags.f._position = initialPosition();
+ noninherited_flags.f._floating = initialFloating();
+ noninherited_flags.f._table_layout = initialTableLayout();
+ noninherited_flags.f._flowAroundFloats= initialFlowAroundFloats();
+ noninherited_flags.f._page_break_before = initialPageBreak();
+ noninherited_flags.f._page_break_after = initialPageBreak();
+ noninherited_flags.f._styleType = NOPSEUDO;
+ noninherited_flags.f._hasClip = false;
+ noninherited_flags.f._pseudoBits = 0;
+ noninherited_flags.f._unicodeBidi = initialUnicodeBidi();
+ noninherited_flags.f._textOverflow = initialTextOverflow();
+ noninherited_flags.f.unused = 0;
+ }
+
+public:
+
+ RenderStyle();
+ // used to create the default style.
+ RenderStyle(bool);
+ RenderStyle(const RenderStyle&);
+
+ ~RenderStyle();
+
+ void inheritFrom(const RenderStyle* inheritParent);
+
+ PseudoId styleType() const { return noninherited_flags.f._styleType; }
+ void setStyleType(PseudoId pi) { noninherited_flags.f._styleType = pi; }
+ bool isGenerated() const {
+ if (styleType() == AFTER || styleType() == BEFORE || styleType() == MARKER || styleType() == REPLACED)
+ return true;
+ else
+ return false;
+ }
+
+ bool hasPseudoStyle(PseudoId pi) const;
+ void setHasPseudoStyle(PseudoId pi, bool b=true);
+ RenderStyle* getPseudoStyle(PseudoId pi) const;
+ RenderStyle* addPseudoStyle(PseudoId pi);
+ void removePseudoStyle(PseudoId pi);
+
+ bool operator==(const RenderStyle& other) const;
+ bool isFloating() const { return !(noninherited_flags.f._floating == FNONE); }
+ bool hasMargin() const { return surround->margin.nonZero(); }
+ bool hasBorder() const { return surround->border.hasBorder(); }
+ bool hasOffset() const { return surround->offset.nonZero(); }
+
+ bool hasBackground() const {
+ if (backgroundColor().isValid() && tqAlpha(backgroundColor().rgb()) > 0)
+ return true;
+ else
+ return background->m_background.hasImage();
+ }
+ bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); }
+
+ bool visuallyOrdered() const { return inherited_flags.f._visuallyOrdered; }
+ void setVisuallyOrdered(bool b) { inherited_flags.f._visuallyOrdered = b; }
+
+// attribute getter methods
+
+ EDisplay display() const { return noninherited_flags.f._display; }
+ EDisplay originalDisplay() const { return noninherited_flags.f._originalDisplay; }
+
+ Length left() const { return surround->offset.left; }
+ Length right() const { return surround->offset.right; }
+ Length top() const { return surround->offset.top; }
+ Length bottom() const { return surround->offset.bottom; }
+
+ EPosition position() const { return noninherited_flags.f._position; }
+ EFloat floating() const { return noninherited_flags.f._floating; }
+
+ Length width() const { return box->width; }
+ Length height() const { return box->height; }
+ Length minWidth() const { return box->min_width; }
+ Length maxWidth() const { return box->max_width; }
+ Length minHeight() const { return box->min_height; }
+ Length maxHeight() const { return box->max_height; }
+
+ const BorderData& border() const { return surround->border; }
+ const BorderValue& borderLeft() const { return surround->border.left; }
+ const BorderValue& borderRight() const { return surround->border.right; }
+ const BorderValue& borderTop() const { return surround->border.top; }
+ const BorderValue& borderBottom() const { return surround->border.bottom; }
+
+ unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); }
+ EBorderStyle borderLeftStyle() const { return surround->border.left.style; }
+ const TQColor& borderLeftColor() const { return surround->border.left.color; }
+ bool borderLeftIsTransparent() const { return surround->border.left.isTransparent(); }
+ unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); }
+ EBorderStyle borderRightStyle() const { return surround->border.right.style; }
+ const TQColor& borderRightColor() const { return surround->border.right.color; }
+ bool borderRightIsTransparent() const { return surround->border.right.isTransparent(); }
+ unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); }
+ EBorderStyle borderTopStyle() const { return surround->border.top.style; }
+ const TQColor& borderTopColor() const { return surround->border.top.color; }
+ bool borderTopIsTransparent() const { return surround->border.top.isTransparent(); }
+ unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); }
+ EBorderStyle borderBottomStyle() const { return surround->border.bottom.style; }
+ const TQColor& borderBottomColor() const { return surround->border.bottom.color; }
+ bool borderBottomIsTransparent() const { return surround->border.bottom.isTransparent(); }
+
+ unsigned short outlineSize() const { return outlineWidth() + outlineOffset(); }
+ unsigned short outlineWidth() const
+ { if(background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0;
+ else return background->m_outline.width; }
+ EBorderStyle outlineStyle() const { return background->m_outline.style; }
+ bool outlineStyleIsAuto() const { return background->m_outline._auto; }
+ const TQColor & outlineColor() const { return background->m_outline.color; }
+
+ EOverflow overflowX() const { return noninherited_flags.f._overflowX; }
+ EOverflow overflowY() const { return noninherited_flags.f._overflowY; }
+ bool hidesOverflow() const {
+ // either both overflow are visible or none are
+ return overflowX() != OVISIBLE;
+ }
+
+ EVisibility visibility() const { return inherited_flags.f._visibility; }
+ EVerticalAlign verticalAlign() const { return noninherited_flags.f._vertical_align; }
+ Length verticalAlignLength() const { return box->vertical_align; }
+
+ Length clipLeft() const { return visual->clip.left; }
+ Length clipRight() const { return visual->clip.right; }
+ Length clipTop() const { return visual->clip.top; }
+ Length clipBottom() const { return visual->clip.bottom; }
+ LengthBox clip() const { return visual->clip; }
+ bool hasClip() const { return noninherited_flags.f._hasClip; }
+
+ EUnicodeBidi unicodeBidi() const { return noninherited_flags.f._unicodeBidi; }
+
+ EClear clear() const { return noninherited_flags.f._clear; }
+ ETableLayout tableLayout() const { return noninherited_flags.f._table_layout; }
+
+ const TQFont & font() const { return inherited->font.f; }
+ // use with care. call font->update() after modifications
+ const Font &htmlFont() { return inherited->font; }
+ const TQFontMetrics & fontMetrics() const { return inherited->font.fm; }
+
+ const TQColor & color() const { return inherited->color; }
+ Length textIndent() const { return inherited->indent; }
+ ETextAlign textAlign() const { return inherited_flags.f._text_align; }
+ ETextTransform textTransform() const { return inherited_flags.f._text_transform; }
+ int textDecorationsInEffect() const { return inherited_flags.f._text_decorations; }
+ int textDecoration() const { return visual->textDecoration; }
+ int wordSpacing() const { return inherited->font.wordSpacing; }
+ int letterSpacing() const { return inherited->font.letterSpacing; }
+
+ EDirection direction() const { return inherited_flags.f._direction; }
+ Length lineHeight() const { return inherited->line_height; }
+
+ EWhiteSpace whiteSpace() const { return inherited_flags.f._white_space; }
+ bool autoWrap() const {
+ if (whiteSpace() == NORMAL || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE)
+ return true;
+ // nowrap | pre
+ return false;
+ }
+ bool preserveLF() const {
+ if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE)
+ return true;
+ // normal | nowrap
+ return false;
+ }
+ bool preserveWS() const {
+ if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP)
+ return true;
+ // normal | nowrap | pre-line
+ return false;
+ }
+
+ const TQColor & backgroundColor() const { return background->m_color; }
+ CachedImage *backgroundImage() const { return background->m_background.m_image; }
+ EBackgroundRepeat backgroundRepeat() const { return background->m_background.m_bgRepeat; }
+ bool backgroundAttachment() const { return background->m_background.m_bgAttachment; }
+ Length backgroundXPosition() const { return background->m_background.m_xPosition; }
+ Length backgroundYPosition() const { return background->m_background.m_yPosition; }
+ BackgroundLayer* accessBackgroundLayers() { return &(background.access()->m_background); }
+ const BackgroundLayer* backgroundLayers() const { return &(background->m_background); }
+
+ // returns true for collapsing borders, false for separate borders
+ bool borderCollapse() const { return inherited_flags.f._border_collapse; }
+ short borderHorizontalSpacing() const { return inherited->border_hspacing; }
+ short borderVerticalSpacing() const { return inherited->border_vspacing; }
+ EEmptyCell emptyCells() const { return inherited_flags.f._empty_cells; }
+ ECaptionSide captionSide() const { return inherited_flags.f._caption_side; }
+
+ EListStyleType listStyleType() const { return inherited_flags.f._list_style_type; }
+ CachedImage *listStyleImage() const { return inherited->style_image; }
+ EListStylePosition listStylePosition() const { return inherited_flags.f._list_style_position; }
+
+ Length marginTop() const { return surround->margin.top; }
+ Length marginBottom() const { return surround->margin.bottom; }
+ Length marginLeft() const { return surround->margin.left; }
+ Length marginRight() const { return surround->margin.right; }
+
+ Length paddingTop() const { return surround->padding.top; }
+ Length paddingBottom() const { return surround->padding.bottom; }
+ Length paddingLeft() const { return surround->padding.left; }
+ Length paddingRight() const { return surround->padding.right; }
+
+ ECursor cursor() const { return inherited_flags.f._cursor_style; }
+
+ short widows() const { return inherited->widows; }
+ short orphans() const { return inherited->orphans; }
+ bool pageBreakInside() const { return inherited_flags.f._page_break_inside; }
+ EPageBreak pageBreakBefore() const { return noninherited_flags.f._page_break_before; }
+ EPageBreak pageBreakAfter() const { return noninherited_flags.f._page_break_after; }
+
+ DOM::QuotesValueImpl* quotes() const { return inherited->quotes; }
+ TQString openQuote(int level) const;
+ TQString closeQuote(int level) const;
+
+ // CSS3 Getter Methods
+ EBoxSizing boxSizing() const { return box->box_sizing; }
+ int outlineOffset() const {
+ if (background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0;
+ return background->m_outline._offset;
+ }
+ ShadowData* textShadow() const { return css3InheritedData->textShadow; }
+ EWordWrap wordWrap() const { return css3InheritedData->wordWrap; }
+ float opacity() { return css3NonInheritedData->opacity; }
+ EUserInput userInput() const { return inherited_flags.f._user_input; }
+
+ Length marqueeIncrement() { return css3NonInheritedData->marquee->increment; }
+ int marqueeSpeed() { return css3NonInheritedData->marquee->speed; }
+ int marqueeLoopCount() { return css3NonInheritedData->marquee->loops; }
+ EMarqueeBehavior marqueeBehavior() { return css3NonInheritedData->marquee->behavior; }
+ EMarqueeDirection marqueeDirection() { return css3NonInheritedData->marquee->direction; }
+ bool textOverflow() const { return noninherited_flags.f._textOverflow; }
+ // End CSS3 Getters
+
+// attribute setter methods
+
+ void setDisplay(EDisplay v) { noninherited_flags.f._display = v; }
+ void setOriginalDisplay(EDisplay v) { noninherited_flags.f._originalDisplay = v; }
+ void setPosition(EPosition v) { noninherited_flags.f._position = v; }
+ void setFloating(EFloat v) { noninherited_flags.f._floating = v; }
+
+ void setLeft(Length v) { SET_VAR(surround,offset.left,v) }
+ void setRight(Length v) { SET_VAR(surround,offset.right,v) }
+ void setTop(Length v) { SET_VAR(surround,offset.top,v) }
+ void setBottom(Length v){ SET_VAR(surround,offset.bottom,v) }
+
+ void setWidth(Length v) { SET_VAR(box,width,v) }
+ void setHeight(Length v) { SET_VAR(box,height,v) }
+
+ void setMinWidth(Length v) { SET_VAR(box,min_width,v) }
+ void setMaxWidth(Length v) { SET_VAR(box,max_width,v) }
+ void setMinHeight(Length v) { SET_VAR(box,min_height,v) }
+ void setMaxHeight(Length v) { SET_VAR(box,max_height,v) }
+
+ void resetBorderTop() { SET_VAR(surround, border.top, BorderValue()) }
+ void resetBorderRight() { SET_VAR(surround, border.right, BorderValue()) }
+ void resetBorderBottom() { SET_VAR(surround, border.bottom, BorderValue()) }
+ void resetBorderLeft() { SET_VAR(surround, border.left, BorderValue()) }
+ void resetOutline() { SET_VAR(background, m_outline, OutlineValue()) }
+
+ void setBackgroundColor(const TQColor& v) { SET_VAR(background, m_color, v) }
+
+ void setBorderLeftWidth(unsigned short v) { SET_VAR(surround,border.left.width,v) }
+ void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround,border.left.style,v) }
+ void setBorderLeftColor(const TQColor & v) { SET_VAR(surround,border.left.color,v) }
+ void setBorderRightWidth(unsigned short v) { SET_VAR(surround,border.right.width,v) }
+ void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround,border.right.style,v) }
+ void setBorderRightColor(const TQColor & v) { SET_VAR(surround,border.right.color,v) }
+ void setBorderTopWidth(unsigned short v) { SET_VAR(surround,border.top.width,v) }
+ void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround,border.top.style,v) }
+ void setBorderTopColor(const TQColor & v) { SET_VAR(surround,border.top.color,v) }
+ void setBorderBottomWidth(unsigned short v) { SET_VAR(surround,border.bottom.width,v) }
+ void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround,border.bottom.style,v) }
+ void setBorderBottomColor(const TQColor & v) { SET_VAR(surround,border.bottom.color,v) }
+ void setOutlineWidth(unsigned short v) { SET_VAR(background,m_outline.width,v) }
+ void setOutlineStyle(EBorderStyle v, bool isAuto = false)
+ {
+ SET_VAR(background,m_outline.style,v)
+ SET_VAR(background,m_outline._auto, isAuto)
+ }
+ void setOutlineColor(const TQColor & v) { SET_VAR(background,m_outline.color,v) }
+
+ void setOverflowX(EOverflow v) { noninherited_flags.f._overflowX = v; }
+ void setOverflowY(EOverflow v) { noninherited_flags.f._overflowY = v; }
+ void setVisibility(EVisibility v) { inherited_flags.f._visibility = v; }
+ void setVerticalAlign(EVerticalAlign v) { noninherited_flags.f._vertical_align = v; }
+ void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l ) }
+
+ void setClipLeft(Length v) { SET_VAR(visual,clip.left,v) }
+ void setClipRight(Length v) { SET_VAR(visual,clip.right,v) }
+ void setClipTop(Length v) { SET_VAR(visual,clip.top,v) }
+ void setClipBottom(Length v) { SET_VAR(visual,clip.bottom,v) }
+ void setClip( Length top, Length right, Length bottom, Length left );
+ void setHasClip( bool b ) { noninherited_flags.f._hasClip = b; }
+
+ void setUnicodeBidi( EUnicodeBidi b ) { noninherited_flags.f._unicodeBidi = b; }
+
+ void setClear(EClear v) { noninherited_flags.f._clear = v; }
+ void setTableLayout(ETableLayout v) { noninherited_flags.f._table_layout = v; }
+ bool setFontDef(const tdehtml::FontDef & v) {
+ // bah, this doesn't compare pointers. broken! (Dirk)
+ if (!(inherited->font.fontDef == v)) {
+ inherited.access()->font = Font( v );
+ return true;
+ }
+ return false;
+ }
+
+ void setColor(const TQColor & v) { SET_VAR(inherited,color,v) }
+ void setTextIndent(Length v) { SET_VAR(inherited,indent,v) }
+ void setTextAlign(ETextAlign v) { inherited_flags.f._text_align = v; }
+ void setTextTransform(ETextTransform v) { inherited_flags.f._text_transform = v; }
+ void addToTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations |= v; }
+ void setTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations = v; }
+ void setTextDecoration(unsigned v) { SET_VAR(visual, textDecoration, v); }
+ void setDirection(EDirection v) { inherited_flags.f._direction = v; }
+ void setLineHeight(Length v) { SET_VAR(inherited,line_height,v) }
+
+ void setWhiteSpace(EWhiteSpace v) { inherited_flags.f._white_space = v; }
+
+ void setWordSpacing(int v) { SET_VAR(inherited,font.wordSpacing,v) }
+ void setLetterSpacing(int v) { SET_VAR(inherited,font.letterSpacing,v) }
+
+ void clearBackgroundLayers() { background.access()->m_background = BackgroundLayer(); }
+ void inheritBackgroundLayers(const BackgroundLayer& parent) { background.access()->m_background = parent; }
+ void adjustBackgroundLayers();
+
+ void setBorderCollapse(bool collapse) { inherited_flags.f._border_collapse = collapse; }
+ void setBorderHorizontalSpacing(short v) { SET_VAR(inherited,border_hspacing,v) }
+ void setBorderVerticalSpacing(short v) { SET_VAR(inherited,border_vspacing,v) }
+
+ void setEmptyCells(EEmptyCell v) { inherited_flags.f._empty_cells = v; }
+ void setCaptionSide(ECaptionSide v) { inherited_flags.f._caption_side = v; }
+
+ void setListStyleType(EListStyleType v) { inherited_flags.f._list_style_type = v; }
+ void setListStyleImage(CachedImage *v) { SET_VAR(inherited,style_image,v)}
+ void setListStylePosition(EListStylePosition v) { inherited_flags.f._list_style_position = v; }
+
+ void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)) }
+ void setMarginTop(Length v) { SET_VAR(surround,margin.top,v) }
+ void setMarginBottom(Length v) { SET_VAR(surround,margin.bottom,v) }
+ void setMarginLeft(Length v) { SET_VAR(surround,margin.left,v) }
+ void setMarginRight(Length v) { SET_VAR(surround,margin.right,v) }
+
+ void resetPadding() { SET_VAR(surround, padding, LengthBox(Variable)) }
+ void setPaddingTop(Length v) { SET_VAR(surround,padding.top,v) }
+ void setPaddingBottom(Length v) { SET_VAR(surround,padding.bottom,v) }
+ void setPaddingLeft(Length v) { SET_VAR(surround,padding.left,v) }
+ void setPaddingRight(Length v) { SET_VAR(surround,padding.right,v) }
+
+ void setCursor( ECursor c ) { inherited_flags.f._cursor_style = c; }
+
+ bool htmlHacks() const { return inherited_flags.f._htmlHacks; }
+ void setHtmlHacks(bool b=true) { inherited_flags.f._htmlHacks = b; }
+
+ bool flowAroundFloats() const { return noninherited_flags.f._flowAroundFloats; }
+ void setFlowAroundFloats(bool b=true) { noninherited_flags.f._flowAroundFloats = b; }
+
+ int zIndex() const { return box->z_auto? 0 : box->z_index; }
+ void setZIndex(int v) { SET_VAR(box,z_auto,false ); SET_VAR(box, z_index, v); }
+ bool hasAutoZIndex() const { return box->z_auto; }
+ void setHasAutoZIndex() { SET_VAR(box, z_auto, true ); }
+
+ void setWidows(short w) { SET_VAR(inherited, widows, w); }
+ void setOrphans(short o) { SET_VAR(inherited, orphans, o); }
+ void setPageBreakInside(bool b) { inherited_flags.f._page_break_inside = b; }
+ void setPageBreakBefore(EPageBreak b) { noninherited_flags.f._page_break_before = b; }
+ void setPageBreakAfter(EPageBreak b) { noninherited_flags.f._page_break_after = b; }
+
+ void setQuotes(DOM::QuotesValueImpl* q);
+
+ // CSS3 Setters
+ void setBoxSizing( EBoxSizing b ) { SET_VAR(box,box_sizing,b); }
+ void setOutlineOffset(unsigned short v) { SET_VAR(background,m_outline._offset,v) }
+ void setWordWrap(EWordWrap w) { SET_VAR(css3InheritedData, wordWrap, w); }
+ void setTextShadow(ShadowData* val, bool add=false);
+ void setOpacity(float f) { SET_VAR(css3NonInheritedData, opacity, f); }
+ void setUserInput(EUserInput ui) { inherited_flags.f._user_input = ui; }
+
+ void setMarqueeIncrement(const Length& f) { SET_VAR(css3NonInheritedData.access()->marquee, increment, f); }
+ void setMarqueeSpeed(int f) { SET_VAR(css3NonInheritedData.access()->marquee, speed, f); }
+ void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(css3NonInheritedData.access()->marquee, direction, d); }
+ void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(css3NonInheritedData.access()->marquee, behavior, b); }
+ void setMarqueeLoopCount(int i) { SET_VAR(css3NonInheritedData.access()->marquee, loops, i); }
+ void setTextOverflow(bool b) { noninherited_flags.f._textOverflow = b; }
+ // End CSS3 Setters
+
+ TQPalette palette() const { return visual->palette; }
+ void setPaletteColor(TQPalette::ColorGroup g, TQColorGroup::ColorRole r, const TQColor& c);
+ void resetPalette() // Called when the desktop color scheme changes.
+ {
+ const_cast<StyleVisualData *>(visual.get())->palette = TQApplication::palette();
+ }
+
+ bool useNormalContent() const { return generated->content == 0; }
+ ContentData* contentData() const { return generated->content; }
+ bool contentDataEquivalent(const RenderStyle* otherStyle) const
+ {
+ return generated->contentDataEquivalent(otherStyle->generated.get());
+ }
+ void addContent(DOM::DOMStringImpl* s);
+ void addContent(CachedObject* o);
+ void addContent(DOM::CounterImpl* c);
+ void addContent(EQuoteContent q);
+ void setContentNone();
+ void setContentNormal();
+ void setContentData(ContentData* content);
+
+ DOM::CSSValueListImpl* counterReset() const { return generated->counter_reset; }
+ DOM::CSSValueListImpl* counterIncrement() const { return generated->counter_increment; }
+ void setCounterReset(DOM::CSSValueListImpl* v);
+ void setCounterIncrement(DOM::CSSValueListImpl* v);
+ bool hasCounterReset(const DOM::DOMString& c) const;
+ bool hasCounterIncrement(const DOM::DOMString& c) const;
+ short counterReset(const DOM::DOMString& c) const;
+ short counterIncrement(const DOM::DOMString& c) const;
+
+
+ bool inheritedNotEqual( RenderStyle *other ) const;
+
+ enum Diff { Equal, NonVisible = Equal, Visible, Position, Layout, CbLayout };
+ Diff diff( const RenderStyle *other ) const;
+
+ bool isDisplayReplacedType() {
+ return display() == INLINE_BLOCK ||/* display() == INLINE_BOX ||*/ display() == INLINE_TABLE;
+ }
+ bool isDisplayInlineType() {
+ return display() == INLINE || isDisplayReplacedType();
+ }
+ bool isOriginalDisplayInlineType() {
+ return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK ||
+ /*originalDisplay() == INLINE_BOX ||*/ originalDisplay() == INLINE_TABLE;
+ }
+
+
+#ifdef ENABLE_DUMP
+ TQString createDiff( const RenderStyle &parent ) const;
+#endif
+
+ // Initial values for all the properties
+ static bool initialBackgroundAttachment() { return true; }
+ static EBackgroundBox initialBackgroundClip() { return BGBORDER; }
+ static EBackgroundBox initialBackgroundOrigin() { return BGPADDING; }
+ static EBackgroundRepeat initialBackgroundRepeat() { return REPEAT; }
+ static LengthSize initialBackgroundSize() { return LengthSize(); }
+ static bool initialBorderCollapse() { return false; }
+ static EBorderStyle initialBorderStyle() { return BNONE; }
+ static ECaptionSide initialCaptionSide() { return CAPTOP; }
+ static EClear initialClear() { return CNONE; }
+ static EDirection initialDirection() { return LTR; }
+ static EDisplay initialDisplay() { return INLINE; }
+ static EEmptyCell initialEmptyCells() { return SHOW; }
+ static EFloat initialFloating() { return FNONE; }
+ static EWordWrap initialWordWrap() { return WWNORMAL; }
+ static EListStylePosition initialListStylePosition() { return OUTSIDE; }
+ static EListStyleType initialListStyleType() { return LDISC; }
+ static EOverflow initialOverflowX() { return OVISIBLE; }
+ static EOverflow initialOverflowY() { return OVISIBLE; }
+ static EPageBreak initialPageBreak() { return PBAUTO; }
+ static bool initialPageBreakInside() { return true; }
+ static EPosition initialPosition() { return STATIC; }
+ static ETableLayout initialTableLayout() { return TAUTO; }
+ static EUnicodeBidi initialUnicodeBidi() { return UBNormal; }
+ static DOM::QuotesValueImpl* initialQuotes() { return 0; }
+ static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
+ static ETextTransform initialTextTransform() { return TTNONE; }
+ static EVisibility initialVisibility() { return VISIBLE; }
+ static EWhiteSpace initialWhiteSpace() { return NORMAL; }
+ static Length initialBackgroundXPosition() { return Length(); }
+ static Length initialBackgroundYPosition() { return Length(); }
+ static short initialBorderHorizontalSpacing() { return 0; }
+ static short initialBorderVerticalSpacing() { return 0; }
+ static ECursor initialCursor() { return CURSOR_AUTO; }
+ static TQColor initialColor() { return Qt::black; }
+ static CachedImage* initialBackgroundImage() { return 0; }
+ static CachedImage* initialListStyleImage() { return 0; }
+ static unsigned short initialBorderWidth() { return 3; }
+ static int initialLetterWordSpacing() { return 0; }
+ static Length initialSize() { return Length(); }
+ static Length initialMinSize() { return Length(0, Fixed); }
+ static Length initialMaxSize() { return Length(UNDEFINED, Fixed); }
+ static Length initialOffset() { return Length(); }
+ static Length initialMargin() { return Length(Fixed); }
+ static Length initialPadding() { return Length(Variable); }
+ static Length initialTextIndent() { return Length(Fixed); }
+ static EVerticalAlign initialVerticalAlign() { return BASELINE; }
+ static int initialWidows() { return 2; }
+ static int initialOrphans() { return 2; }
+ static Length initialLineHeight() { return Length(-100, Percent); }
+ static ETextAlign initialTextAlign() { return TAAUTO; }
+ static ETextDecoration initialTextDecoration() { return TDNONE; }
+ static bool initialFlowAroundFloats() { return false; }
+ static int initialOutlineOffset() { return 0; }
+ static float initialOpacity() { return 1.0f; }
+ static int initialMarqueeLoopCount() { return -1; }
+ static int initialMarqueeSpeed() { return 85; }
+ static Length initialMarqueeIncrement() { return Length(6, Fixed); }
+ static EMarqueeBehavior initialMarqueeBehavior() { return MSCROLL; }
+ static EMarqueeDirection initialMarqueeDirection() { return MAUTO; }
+ static bool initialTextOverflow() { return false; }
+};
+
+class RenderPageStyle {
+ friend class CSSStyleSelector;
+public:
+ enum PageType { NO_PAGE = 0, ANY_PAGE, FIRST_PAGE, LEFT_PAGES, RIGHT_PAGES };
+
+ RenderPageStyle();
+ ~RenderPageStyle();
+
+ PageType pageType() { return m_pageType; }
+
+ RenderPageStyle* getPageStyle(PageType type);
+ RenderPageStyle* addPageStyle(PageType type);
+ void removePageStyle(PageType type);
+
+ Length marginTop() const { return margin.top; }
+ Length marginBottom() const { return margin.bottom; }
+ Length marginLeft() const { return margin.left; }
+ Length marginRight() const { return margin.right; }
+
+ Length pageWidth() const { return m_pageWidth; }
+ Length pageHeight() const { return m_pageHeight; }
+
+ void setMarginTop(Length v) { margin.top = v; }
+ void setMarginBottom(Length v) { margin.bottom = v; }
+ void setMarginLeft(Length v) { margin.left = v; }
+ void setMarginRight(Length v) { margin.right = v; }
+
+ void setPageWidth(Length v) { m_pageWidth = v; }
+ void setPageHeight(Length v) { m_pageHeight = v; }
+
+protected:
+ RenderPageStyle *next;
+ PageType m_pageType;
+
+ LengthBox margin;
+ Length m_pageWidth;
+ Length m_pageHeight;
+};
+
+} // namespace
+
+#endif
+
diff --git a/tdehtml/rendering/render_table.cpp b/tdehtml/rendering/render_table.cpp
new file mode 100644
index 000000000..ef7fe1031
--- /dev/null
+++ b/tdehtml/rendering/render_table.cpp
@@ -0,0 +1,3070 @@
+/**
+ * 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) 2005 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 TABLE_DEBUG
+//#define TABLE_PRINT
+//#define DEBUG_LAYOUT
+//#define BOX_DEBUG
+#include "rendering/render_table.h"
+#include "rendering/render_replaced.h"
+#include "rendering/render_canvas.h"
+#include "rendering/table_layout.h"
+#include "html/html_tableimpl.h"
+#include "html/html_formimpl.h"
+#include "misc/htmltags.h"
+#include "misc/htmlattrs.h"
+#include "rendering/render_line.h"
+#include "xml/dom_docimpl.h"
+
+#include <kglobal.h>
+
+#include <tqapplication.h>
+#include <tqstyle.h>
+
+#include <kdebug.h>
+#include <assert.h>
+
+using namespace tdehtml;
+using namespace DOM;
+
+RenderTable::RenderTable(DOM::NodeImpl* node)
+ : RenderBlock(node)
+{
+
+ tCaption = 0;
+ head = foot = firstBody = 0;
+ tableLayout = 0;
+ m_currentBorder = 0;
+
+ has_col_elems = false;
+ hspacing = vspacing = 0;
+ padding = 0;
+ needSectionRecalc = false;
+ padding = 0;
+
+ columnPos.resize( 2 );
+ columnPos.fill( 0 );
+ columns.resize( 1 );
+ columns.fill( ColumnStruct() );
+
+ columnPos[0] = 0;
+}
+
+RenderTable::~RenderTable()
+{
+ delete tableLayout;
+}
+
+void RenderTable::setStyle(RenderStyle *_style)
+{
+ ETableLayout oldTableLayout = style() ? style()->tableLayout() : TAUTO;
+ if ( _style->display() == INLINE ) _style->setDisplay( INLINE_TABLE );
+ if ( _style->display() != INLINE_TABLE ) _style->setDisplay(TABLE);
+ if ( !_style->flowAroundFloats() ) _style->setFlowAroundFloats(true);
+ RenderBlock::setStyle(_style);
+
+ // init RenderObject attributes
+ setInline(style()->display()==INLINE_TABLE && !isPositioned());
+ setReplaced(style()->display()==INLINE_TABLE);
+
+ // In the collapsed border model, there is no cell spacing.
+ hspacing = collapseBorders() ? 0 : style()->borderHorizontalSpacing();
+ vspacing = collapseBorders() ? 0 : style()->borderVerticalSpacing();
+ columnPos[0] = hspacing;
+
+ if ( !tableLayout || style()->tableLayout() != oldTableLayout ) {
+ delete tableLayout;
+
+ // According to the CSS2 spec, you only use fixed table layout if an
+ // explicit width is specified on the table. Auto width implies auto table layout.
+ if (style()->tableLayout() == TFIXED && !style()->width().isVariable()) {
+ tableLayout = new FixedTableLayout(this);
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "using fixed table layout" << endl;
+#endif
+ } else
+ tableLayout = new AutoTableLayout(this);
+ }
+}
+
+short RenderTable::lineHeight(bool b) const
+{
+ // Inline tables are replaced elements. Otherwise, just pass off to
+ // the base class.
+ if (isReplaced())
+ return height()+marginTop()+marginBottom();
+ return RenderBlock::lineHeight(b);
+}
+
+short RenderTable::baselinePosition(bool b) const
+{
+ // Inline tables are replaced elements. Otherwise, just pass off to
+ // the base class.
+ if (isReplaced())
+ return height()+marginTop()+marginBottom();
+ return RenderBlock::baselinePosition(b);
+}
+
+
+void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(Table)::addChild( " << child->renderName() << ", " <<
+ (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
+#endif
+ bool wrapInAnonymousSection = false;
+
+ switch(child->style()->display())
+ {
+ case TABLE_CAPTION:
+ if (child->isRenderBlock())
+ tCaption = static_cast<RenderBlock *>(child);
+ break;
+ case TABLE_COLUMN:
+ case TABLE_COLUMN_GROUP:
+ has_col_elems = true;
+ break;
+ case TABLE_HEADER_GROUP:
+ if ( !head ) {
+ if (child->isTableSection())
+ head = static_cast<RenderTableSection *>(child);
+ }
+ else if ( !firstBody )
+ if (child->isTableSection())
+ firstBody = static_cast<RenderTableSection *>(child);
+ break;
+ case TABLE_FOOTER_GROUP:
+ if ( !foot ) {
+ if (child->isTableSection())
+ foot = static_cast<RenderTableSection *>(child);
+ break;
+ }
+ // fall through
+ case TABLE_ROW_GROUP:
+ if(!firstBody)
+ if (child->isTableSection())
+ firstBody = static_cast<RenderTableSection *>(child);
+ break;
+ case TABLE_CELL:
+ case TABLE_ROW:
+ wrapInAnonymousSection = true;
+ break;
+ case BLOCK:
+// case BOX:
+ case COMPACT:
+ case INLINE:
+ case INLINE_BLOCK:
+// case INLINE_BOX:
+ case INLINE_TABLE:
+ case LIST_ITEM:
+ case NONE:
+ case RUN_IN:
+ case TABLE:
+ // The special TABLE > FORM quirk allows the form to sit directly under the table
+ if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM)
+ wrapInAnonymousSection = !static_cast<HTMLFormElementImpl*>(child->element())->isMalformed();
+ else
+ wrapInAnonymousSection = true;
+ break;
+ }
+
+ if (!wrapInAnonymousSection) {
+ RenderContainer::addChild(child, beforeChild);
+ return;
+ }
+
+ if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
+ lastChild()->addChild(child);
+ return;
+ }
+
+ RenderObject *lastBox = beforeChild;
+ RenderObject *nextToLastBox = beforeChild;
+ while (lastBox && lastBox->parent()->isAnonymous() &&
+ !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION) {
+ nextToLastBox = lastBox;
+ lastBox = lastBox->parent();
+ }
+ if (lastBox && lastBox->isAnonymous()) {
+ lastBox->addChild(child, nextToLastBox);
+ return;
+ }
+
+ if (beforeChild && !beforeChild->isTableSection())
+ beforeChild = 0;
+ RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(TABLE_ROW_GROUP);
+ section->setStyle(newStyle);
+ addChild(section, beforeChild);
+ section->addChild(child);
+}
+
+void RenderTable::calcWidth()
+{
+ if ( isPositioned() ) {
+ calcAbsoluteHorizontal();
+ }
+
+ RenderBlock *cb = containingBlock();
+ int availableWidth = cb->lineWidth( m_y );
+
+ LengthType widthType = style()->width().type();
+ if(widthType > Relative && style()->width().value() > 0) {
+ // Percent or fixed table
+ // Percent is calculated from contentWidth, not available width
+ m_width = calcBoxWidth(style()->width().minWidth( cb->contentWidth() ));
+ } else {
+ // Subtract out any fixed margins from our available width for auto width tables.
+ int marginTotal = 0;
+ if (!style()->marginLeft().isVariable())
+ marginTotal += style()->marginLeft().width(availableWidth);
+ if (!style()->marginRight().isVariable())
+ marginTotal += style()->marginRight().width(availableWidth);
+
+ // Subtract out our margins to get the available content width.
+ int availContentWidth = kMax(0, availableWidth - marginTotal);
+
+ // Ensure we aren't bigger than our max width or smaller than our min width.
+ m_width = kMin(availContentWidth, m_maxWidth);
+ }
+
+ m_width = kMax (m_width, m_minWidth);
+
+ // Finally, with our true width determined, compute our margins for real.
+ m_marginRight=0;
+ m_marginLeft=0;
+
+ calcHorizontalMargins(style()->marginLeft(),style()->marginRight(),availableWidth);
+}
+
+void RenderTable::layout()
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+ KHTMLAssert( !needSectionRecalc );
+
+ if (posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
+ // All we have to is lay out our positioned objects.
+ layoutPositionedObjects(true);
+ setNeedsLayout(false);
+ return;
+ }
+
+ if (markedForRepaint()) {
+ repaintDuringLayout();
+ setMarkedForRepaint(false);
+ }
+
+ m_height = 0;
+ initMaxMarginValues();
+
+ int oldWidth = m_width;
+ calcWidth();
+ m_overflowWidth = m_width;
+
+ if (tCaption && (oldWidth != m_width || tCaption->style()->height().isPercent()))
+ tCaption->setChildNeedsLayout(true);
+
+ // the optimization below doesn't work since the internal table
+ // layout could have changed. we need to add a flag to the table
+ // layout that tells us if something has changed in the min max
+ // calculations to do it correctly.
+// if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )
+ tableLayout->layout();
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(Table)::layout1() width=" << width() << ", marginLeft=" << marginLeft() << " marginRight=" << marginRight() << endl;
+#endif
+
+ setCellWidths();
+
+ // layout child objects
+ int calculatedHeight = 0;
+
+ RenderObject *child = firstChild();
+ while( child ) {
+ // FIXME: What about a form that has a display value that makes it a table section?
+ if ( child->needsLayout() && !(child->element() && child->element()->id() == ID_FORM) )
+ child->layout();
+ if ( child->isTableSection() ) {
+ static_cast<RenderTableSection *>(child)->calcRowHeight();
+ calculatedHeight += static_cast<RenderTableSection *>(child)->layoutRows( 0 );
+ }
+ child = child->nextSibling();
+ }
+
+ // ### collapse caption margin
+ if(tCaption && tCaption->style()->captionSide() != CAPBOTTOM) {
+ tCaption->setPos(tCaption->marginLeft(), tCaption->marginTop()+m_height);
+ m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
+ }
+
+ int bpTop = borderTop() + (collapseBorders() ? 0 : paddingTop());
+ int bpBottom = borderBottom() + (collapseBorders() ? 0 : paddingBottom());
+
+ m_height += bpTop;
+
+ int oldHeight = m_height;
+ if (isPositioned())
+ m_height += calculatedHeight + bpBottom;
+ calcHeight();
+ int newHeight = m_height;
+ m_height = oldHeight;
+
+ Length h = style()->height();
+ int th = -(bpTop + bpBottom); // Tables size as though CSS height includes border/padding.
+ if (isPositioned())
+ th += newHeight;
+ else if (h.isFixed())
+ th += h.value();
+ else if (h.isPercent())
+ th += calcPercentageHeight(h);
+
+ // layout rows
+ if ( th > calculatedHeight ) {
+ // we have to redistribute that height to get the constraint correctly
+ // just force the first body to the height needed
+ // ### FIXME This should take height constraints on all table sections into account and distribute
+ // accordingly. For now this should be good enough
+ if (firstBody) {
+ firstBody->calcRowHeight();
+ firstBody->layoutRows( th - calculatedHeight );
+ }
+ else if (!style()->htmlHacks()) {
+ // Completely empty tables (with no sections or anything) should at least honor specified height
+ // in strict mode.
+ m_height += th;
+ }
+ }
+
+ int bl = borderLeft();
+ if (!collapseBorders())
+ bl += paddingLeft();
+
+ // position the table sections
+ if ( head ) {
+ head->setPos(bl, m_height);
+ m_height += head->height();
+ }
+ RenderObject *body = firstBody;
+ while ( body ) {
+ if ( body != head && body != foot && body->isTableSection() ) {
+ body->setPos(bl, m_height);
+ m_height += body->height();
+ }
+ body = body->nextSibling();
+ }
+ if ( foot ) {
+ foot->setPos(bl, m_height);
+ m_height += foot->height();
+ }
+
+ m_height += bpBottom;
+
+ if(tCaption && tCaption->style()->captionSide()==CAPBOTTOM) {
+ tCaption->setPos(tCaption->marginLeft(), tCaption->marginTop()+m_height);
+ m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
+ }
+
+ if (canvas()->pagedMode()) {
+ RenderObject *child = firstChild();
+ // relayout taking real position into account
+ while( child ) {
+ if ( !(child->element() && child->element()->id() == ID_FORM) ) {
+ child->setNeedsLayout(true);
+ child->layout();
+ if (child->containsPageBreak()) setContainsPageBreak(true);
+ if (child->needsPageClear()) setNeedsPageClear(true);
+ }
+ child = child->nextSibling();
+ }
+ }
+
+ //kdDebug(0) << "table height: " << m_height << endl;
+
+ // table can be containing block of positioned elements.
+ // ### only pass true if width or height changed.
+ layoutPositionedObjects( true );
+
+ m_overflowHeight = m_height;
+
+ setNeedsLayout(false);
+}
+
+void RenderTable::setCellWidths()
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
+#endif
+
+ RenderObject *child = firstChild();
+ while( child ) {
+ if ( child->isTableSection() )
+ static_cast<RenderTableSection *>(child)->setCellWidths();
+ child = child->nextSibling();
+ }
+}
+
+void RenderTable::paint( PaintInfo& pI, int _tx, int _ty)
+{
+ if(needsLayout()) return;
+
+ _tx += xPos();
+ _ty += yPos();
+
+#ifdef TABLE_PRINT
+ kdDebug( 6040 ) << "RenderTable::paint() w/h = (" << width() << "/" << height() << ")" << endl;
+#endif
+ if (!overhangingContents() && !isRelPositioned() && !isPositioned())
+ {
+ int os = 2*maximalOutlineSize(pI.phase);
+ if((_ty > pI.r.y() + pI.r.height() + os) || (_ty + height() < pI.r.y() - os)) return;
+ if((_tx > pI.r.x() + pI.r.width() + os) || (_tx + width() < pI.r.x() - os)) return;
+ }
+
+#ifdef TABLE_PRINT
+ kdDebug( 6040 ) << "RenderTable::paint(2) " << _tx << "/" << _ty << " (" << _y << "/" << _h << ")" << endl;
+#endif
+
+ if (pI.phase == PaintActionOutline)
+ paintOutline(pI.p, _tx, _ty, width(), height(), style());
+
+ if(( pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground )
+ && shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE)
+ paintBoxDecorations(pI, _tx, _ty);
+
+ if ( pI.phase == PaintActionElementBackground )
+ return;
+
+ PaintAction oldphase = pI.phase;
+ if ( pI.phase == PaintActionChildBackgrounds )
+ pI.phase = PaintActionChildBackground;
+
+ for( RenderObject *child = firstChild(); child; child = child->nextSibling())
+ if ( child->isTableSection() || child == tCaption )
+ child->paint( pI, _tx, _ty );
+
+ if (collapseBorders() &&
+ (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground)
+ && style()->visibility() == VISIBLE) {
+ // Collect all the unique border styles that we want to paint in a sorted list. Once we
+ // have all the styles sorted, we then do individual passes, painting each style of border
+ // from lowest precedence to highest precedence.
+ pI.phase = PaintActionCollapsedTableBorders;
+ TQValueList<CollapsedBorderValue> borderStyles;
+ collectBorders(borderStyles);
+#if 0
+ TQString m;
+ for (uint i = 0; i < borderStyles.count(); i++)
+ m += TQString("%1 ").arg((*borderStyles.at(i)).width());
+ kdDebug(6040) << m << endl;
+#endif
+ TQValueListIterator<CollapsedBorderValue> it = borderStyles.begin();
+ TQValueListIterator<CollapsedBorderValue> end = borderStyles.end();
+ for (; it != end; ++it) {
+ m_currentBorder = &*it;
+ for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isTableSection())
+ child->paint(pI, _tx, _ty);
+ }
+ }
+ m_currentBorder = 0;
+ }
+
+ pI.phase = oldphase;
+#ifdef BOX_DEBUG
+ outlineBox(p, _tx, _ty, "blue");
+#endif
+}
+
+void RenderTable::paintBoxDecorations(PaintInfo &pI, int _tx, int _ty)
+{
+ int w = width();
+ int h = height();
+
+ // Account for the caption.
+ if (tCaption) {
+ int captionHeight = (tCaption->height() + tCaption->marginBottom() + tCaption->marginTop());
+ h -= captionHeight;
+ if (tCaption->style()->captionSide() != CAPBOTTOM)
+ _ty += captionHeight;
+ }
+
+ int my = kMax(_ty,pI.r.y());
+ int mh;
+ if (_ty<pI.r.y())
+ mh= kMax(0,h-(pI.r.y()-_ty));
+ else
+ mh = kMin(pI.r.height(),h);
+
+ paintBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
+
+ if (style()->hasBorder() && !collapseBorders())
+ paintBorder(pI.p, _tx, _ty, w, h, style());
+}
+
+void RenderTable::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ if ( needSectionRecalc )
+ recalcSections();
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(Table " << this << ")::calcMinMaxWidth()" << endl;
+#endif
+
+ tableLayout->calcMinMaxWidth();
+
+ if (tCaption) {
+ tCaption->calcWidth();
+ if (tCaption->marginLeft()+tCaption->marginRight()+tCaption->minWidth() > m_minWidth)
+ m_minWidth = tCaption->marginLeft()+tCaption->marginRight()+tCaption->minWidth();
+ }
+
+ setMinMaxKnown();
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << " END: (Table " << this << ")::calcMinMaxWidth() min = " << m_minWidth << " max = " << m_maxWidth << endl;
+#endif
+}
+
+void RenderTable::close()
+{
+// kdDebug( 6040 ) << "RenderTable::close()" << endl;
+ setNeedsLayoutAndMinMaxRecalc();
+}
+
+void RenderTable::splitColumn( int pos, int firstSpan )
+{
+ // we need to add a new columnStruct
+ int oldSize = columns.size();
+ columns.resize( oldSize + 1 );
+ int oldSpan = columns[pos].span;
+// tqDebug("splitColumn( %d,%d ), oldSize=%d, oldSpan=%d", pos, firstSpan, oldSize, oldSpan );
+ KHTMLAssert( oldSpan > firstSpan );
+ columns[pos].span = firstSpan;
+ memmove( columns.data()+pos+1, columns.data()+pos, (oldSize-pos)*sizeof(ColumnStruct) );
+ columns[pos+1].span = oldSpan - firstSpan;
+
+ // change width of all rows.
+ RenderObject *child = firstChild();
+ while ( child ) {
+ if ( child->isTableSection() ) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ int size = section->grid.size();
+ int row = 0;
+ if ( section->cCol > pos )
+ section->cCol++;
+ while ( row < size ) {
+ section->grid[row].row->resize( oldSize+1 );
+ RenderTableSection::Row &r = *section->grid[row].row;
+ memmove( r.data()+pos+1, r.data()+pos, (oldSize-pos)*sizeof( RenderTableCell * ) );
+// tqDebug("moving from %d to %d, num=%d", pos, pos+1, (oldSize-pos-1) );
+ r[pos+1] = r[pos] ? (RenderTableCell *)-1 : 0;
+ row++;
+ }
+ }
+ child = child->nextSibling();
+ }
+ columnPos.resize( numEffCols()+1 );
+ setNeedsLayoutAndMinMaxRecalc();
+}
+
+void RenderTable::appendColumn( int span )
+{
+ // easy case.
+ int pos = columns.size();
+// tqDebug("appendColumn( %d ), size=%d", span, pos );
+ int newSize = pos + 1;
+ columns.resize( newSize );
+ columns[pos].span = span;
+ //tqDebug("appending column at %d, span %d", pos, span );
+
+ // change width of all rows.
+ RenderObject *child = firstChild();
+ while ( child ) {
+ if ( child->isTableSection() ) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ int size = section->grid.size();
+ int row = 0;
+ while ( row < size ) {
+ section->grid[row].row->resize( newSize );
+ section->cellAt( row, pos ) = 0;
+ row++;
+ }
+
+ }
+ child = child->nextSibling();
+ }
+ columnPos.resize( numEffCols()+1 );
+ setNeedsLayoutAndMinMaxRecalc();
+}
+
+RenderTableCol *RenderTable::colElement( int col ) {
+ if ( !has_col_elems )
+ return 0;
+ RenderObject *child = firstChild();
+ int cCol = 0;
+ while ( child ) {
+ if ( child->isTableCol() ) {
+ RenderTableCol *colElem = static_cast<RenderTableCol *>(child);
+ int span = colElem->span();
+ if ( !colElem->firstChild() ) {
+ cCol += span;
+ if ( cCol > col )
+ return colElem;
+ }
+
+ RenderObject *next = child->firstChild();
+ if ( !next )
+ next = child->nextSibling();
+ if ( !next && child->parent()->isTableCol() )
+ next = child->parent()->nextSibling();
+ child = next;
+ } else if (child == tCaption) {
+ child = child->nextSibling();
+ } else
+ break;
+ }
+ return 0;
+}
+
+void RenderTable::recalcSections()
+{
+ tCaption = 0;
+ head = foot = firstBody = 0;
+ has_col_elems = false;
+
+ RenderObject *child = firstChild();
+ // We need to get valid pointers to caption, head, foot and firstbody again
+ while ( child ) {
+ switch(child->style()->display()) {
+ case TABLE_CAPTION:
+ if ( !tCaption && child->isRenderBlock() ) {
+ tCaption = static_cast<RenderBlock*>(child);
+ tCaption->setNeedsLayout(true);
+ }
+ break;
+ case TABLE_COLUMN:
+ case TABLE_COLUMN_GROUP:
+ has_col_elems = true;
+ break;
+ case TABLE_HEADER_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ if (!head)
+ head = section;
+ else if (!firstBody)
+ firstBody = section;
+ if (section->needCellRecalc)
+ section->recalcCells();
+ }
+ break;
+ case TABLE_FOOTER_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ if (!foot)
+ foot = section;
+ else if (!firstBody)
+ firstBody = section;
+ if (section->needCellRecalc)
+ section->recalcCells();
+ }
+ break;
+ case TABLE_ROW_GROUP:
+ if (child->isTableSection()) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ if (!firstBody)
+ firstBody = section;
+ if (section->needCellRecalc)
+ section->recalcCells();
+ }
+ break;
+ default:
+ break;
+ }
+ child = child->nextSibling();
+ }
+ needSectionRecalc = false;
+ setNeedsLayout(true);
+}
+
+RenderObject* RenderTable::removeChildNode(RenderObject* child)
+{
+ setNeedSectionRecalc();
+ return RenderContainer::removeChildNode( child );
+}
+
+int RenderTable::borderLeft() const
+{
+ if (collapseBorders()) {
+ // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
+ // but I'm working to get this changed. For now, follow the spec.
+ return 0;
+ }
+ return RenderBlock::borderLeft();
+}
+
+int RenderTable::borderRight() const
+{
+ if (collapseBorders()) {
+ // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
+ // but I'm working to get this changed. For now, follow the spec.
+ return 0;
+ }
+ return RenderBlock::borderRight();
+}
+
+int RenderTable::borderTop() const
+{
+ if (collapseBorders()) {
+ // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
+ // but I'm working to get this changed. For now, follow the spec.
+ return 0;
+ }
+ return RenderBlock::borderTop();
+}
+
+int RenderTable::borderBottom() const
+{
+ if (collapseBorders()) {
+ // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
+ // but I'm working to get this changed. For now, follow the spec.
+ return 0;
+ }
+ return RenderBlock::borderBottom();
+}
+
+RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
+{
+ if (section == head)
+ return 0;
+ RenderObject *prevSection = (section == foot ? lastChild() : const_cast<RenderTableSection *>(section))->previousSibling();
+ while (prevSection) {
+ if (prevSection->isTableSection() && prevSection != head && prevSection != foot && (!skipEmptySections || static_cast<RenderTableSection*>(prevSection)->numRows()))
+ break;
+ prevSection = prevSection->previousSibling();
+ }
+ if (!prevSection && head && (!skipEmptySections || head->numRows()))
+ prevSection = head;
+ return static_cast<RenderTableSection*>(prevSection);
+}
+
+RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
+{
+ if (section == foot)
+ return 0;
+ RenderObject *nextSection = (section == head ? firstChild() : const_cast<RenderTableSection *>(section))->nextSibling();
+ while (nextSection) {
+ if (nextSection->isTableSection() && nextSection != head && nextSection != foot && (!skipEmptySections || static_cast<RenderTableSection*>(nextSection)->numRows()))
+ break;
+ nextSection = nextSection->nextSibling();
+ }
+ if (!nextSection && foot && (!skipEmptySections || foot->numRows()))
+ nextSection = foot;
+ return static_cast<RenderTableSection*>(nextSection);
+}
+
+RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
+{
+ // Find the section and row to look in
+ int r = cell->row();
+ RenderTableSection* section = 0;
+ int rAbove = 0;
+ if (r > 0) {
+ // cell is not in the first row, so use the above row in its own section
+ section = cell->section();
+ rAbove = r-1;
+ } else {
+ section = sectionAbove(cell->section(), true);
+ if (section)
+ rAbove = section->numRows() - 1;
+ }
+
+ // Look up the cell in the section's grid, which requires effective col index
+ if (section) {
+ int effCol = colToEffCol(cell->col());
+ RenderTableCell* aboveCell;
+ // If we hit a span back up to a real cell.
+ do {
+ aboveCell = section->cellAt(rAbove, effCol);
+ effCol--;
+ } while (aboveCell == (RenderTableCell *)-1 && effCol >=0);
+ return (aboveCell == (RenderTableCell *)-1) ? 0 : aboveCell;
+ } else {
+ return 0;
+ }
+}
+
+RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
+{
+ // Find the section and row to look in
+ int r = cell->row() + cell->rowSpan() - 1;
+ RenderTableSection* section = 0;
+ int rBelow = 0;
+ if (r < cell->section()->numRows()-1) {
+ // The cell is not in the last row, so use the next row in the section.
+ section = cell->section();
+ rBelow= r+1;
+ } else {
+ section = sectionBelow(cell->section(), true);
+ if (section)
+ rBelow = 0;
+ }
+
+ // Look up the cell in the section's grid, which requires effective col index
+ if (section) {
+ int effCol = colToEffCol(cell->col());
+ RenderTableCell* belowCell;
+ // If we hit a colspan back up to a real cell.
+ do {
+ belowCell = section->cellAt(rBelow, effCol);
+ effCol--;
+ } while (belowCell == (RenderTableCell *)-1 && effCol >=0);
+ return (belowCell == (RenderTableCell *)-1) ? 0 : belowCell;
+ } else {
+ return 0;
+ }
+}
+
+RenderTableCell* RenderTable::cellLeft(const RenderTableCell* cell) const
+{
+ RenderTableSection* section = cell->section();
+ int effCol = colToEffCol(cell->col());
+ if (effCol == 0)
+ return 0;
+
+ // If we hit a colspan back up to a real cell.
+ RenderTableCell* prevCell;
+ do {
+ prevCell = section->cellAt(cell->row(), effCol-1);
+ effCol--;
+ } while (prevCell == (RenderTableCell *)-1 && effCol >=0);
+ return (prevCell == (RenderTableCell *)-1) ? 0 : prevCell;
+}
+
+RenderTableCell* RenderTable::cellRight(const RenderTableCell* cell) const
+{
+ int effCol = colToEffCol(cell->col()+cell->colSpan());
+ if (effCol >= numEffCols())
+ return 0;
+ RenderTableCell* result = cell->section()->cellAt(cell->row(), effCol);
+ return (result == (RenderTableCell*)-1) ? 0 : result;
+}
+
+#ifdef ENABLE_DUMP
+void RenderTable::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderBlock::dump(stream, ind);
+
+ if (tCaption)
+ stream << " tCaption";
+ if (head)
+ stream << " head";
+ if (foot)
+ stream << " foot";
+
+ stream << " [cspans:";
+ for ( unsigned int i = 0; i < columns.size(); i++ )
+ stream << " " << columns[i].span;
+ stream << "]";
+}
+
+#endif
+
+FindSelectionResult RenderTable::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
+{
+ int off = offset;
+ DOM::NodeImpl* nod = node;
+
+ FindSelectionResult pos;
+ TableSectionIterator it(this);
+ for (; *it; ++it) {
+ pos = (*it)->checkSelectionPoint(_x, _y, _tx + m_x, _ty + m_y, nod, off, state);
+ switch(pos) {
+ case SelectionPointBeforeInLine:
+ case SelectionPointInside:
+ //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " returning SelectionPointInside offset=" << offset << endl;
+ node = nod;
+ offset = off;
+ return SelectionPointInside;
+ case SelectionPointBefore:
+ //x,y is before this element -> stop here
+ if ( state.m_lastNode ) {
+ node = state.m_lastNode;
+ offset = state.m_lastOffset;
+ //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before this child "
+ // << node << "-> returning SelectionPointInside, offset=" << offset << endl;
+ return SelectionPointInside;
+ } else {
+ node = nod;
+ offset = off;
+ //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl;
+ return SelectionPointBefore;
+ }
+ break;
+ case SelectionPointAfter:
+ if (state.m_afterInLine) break;
+ // fall through
+ case SelectionPointAfterInLine:
+ if (pos == SelectionPointAfterInLine) state.m_afterInLine = true;
+ //kdDebug(6030) << "RenderTable::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl;
+ state.m_lastNode = nod;
+ state.m_lastOffset = off;
+ // No "return" here, obviously. We must keep looking into the children.
+ break;
+ }
+ }
+ // If we are after the last child, return lastNode/lastOffset
+ // But lastNode can be 0L if there is no child, for instance.
+ if ( state.m_lastNode )
+ {
+ node = state.m_lastNode;
+ offset = state.m_lastOffset;
+ }
+ // Fallback
+ return SelectionPointAfter;
+}
+
+// --------------------------------------------------------------------------
+
+RenderTableSection::RenderTableSection(DOM::NodeImpl* node)
+ : RenderBox(node)
+{
+ // init RenderObject attributes
+ setInline(false); // our object is not Inline
+ cCol = 0;
+ cRow = -1;
+ needCellRecalc = false;
+}
+
+RenderTableSection::~RenderTableSection()
+{
+ clearGrid();
+}
+
+void RenderTableSection::detach()
+{
+ // recalc cell info because RenderTable has unguarded pointers
+ // stored that point to this RenderTableSection.
+ if (table())
+ table()->setNeedSectionRecalc();
+
+ RenderBox::detach();
+}
+
+void RenderTableSection::setStyle(RenderStyle* _style)
+{
+ // we don't allow changing this one
+ if (style())
+ _style->setDisplay(style()->display());
+ else if (_style->display() != TABLE_FOOTER_GROUP && _style->display() != TABLE_HEADER_GROUP)
+ _style->setDisplay(TABLE_ROW_GROUP);
+
+ RenderBox::setStyle(_style);
+}
+
+void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(TableSection)::addChild( " << child->renderName() << ", beforeChild=" <<
+ (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
+#endif
+ if ( !child->isTableRow() ) {
+ // TBODY > FORM quirk (???)
+ if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM &&
+ static_cast<HTMLFormElementImpl*>(child->element())->isMalformed())
+ {
+ RenderContainer::addChild(child, beforeChild);
+ return;
+ }
+
+ RenderObject* last = beforeChild;
+ if (!last)
+ last = lastChild();
+ if (last && last->isAnonymous()) {
+ last->addChild(child);
+ return;
+ }
+
+ // If beforeChild is inside an anonymous cell/row, insert into the cell or into
+ // the anonymous row containing it, if there is one.
+ RenderObject* lastBox = last;
+ while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
+ lastBox = lastBox->parent();
+ if (lastBox && lastBox->isAnonymous()) {
+ lastBox->addChild(child, beforeChild);
+ return;
+ }
+
+ RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(TABLE_ROW);
+ row->setStyle(newStyle);
+ addChild(row, beforeChild);
+ row->addChild(child);
+ return;
+ }
+
+ if (beforeChild)
+ setNeedCellRecalc();
+
+ cRow++;
+ cCol = 0;
+
+ ensureRows( cRow+1 );
+ KHTMLAssert( child->isTableRow() );
+ grid[cRow].rowRenderer = static_cast<RenderTableRow*>(child);
+
+ if (!beforeChild) {
+ grid[cRow].height = child->style()->height();
+ if ( grid[cRow].height.isRelative() )
+ grid[cRow].height = Length();
+ }
+
+
+ RenderContainer::addChild(child,beforeChild);
+}
+
+void RenderTableSection::ensureRows( int numRows )
+{
+ int nRows = grid.size();
+ int nCols = table()->numEffCols();
+ if ( numRows > nRows ) {
+ grid.resize( numRows );
+ for ( int r = nRows; r < numRows; r++ ) {
+ grid[r].row = new Row( nCols );
+ grid[r].row->fill( 0 );
+ grid[r].rowRenderer = 0;
+ grid[r].baseLine = 0;
+ grid[r].height = Length();
+ }
+ }
+
+}
+
+void RenderTableSection::addCell( RenderTableCell *cell, RenderTableRow *row )
+{
+ int rSpan = cell->rowSpan();
+ int cSpan = cell->colSpan();
+ TQMemArray<RenderTable::ColumnStruct> &columns = table()->columns;
+ int nCols = columns.size();
+
+ // ### mozilla still seems to do the old HTML way, even for strict DTD
+ // (see the annotation on table cell layouting in the CSS specs and the testcase below:
+ // <TABLE border>
+ // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
+ // <TR><TD colspan="2">5
+ // </TABLE>
+ while ( cCol < nCols && cellAt( cRow, cCol ) )
+ cCol++;
+
+// tqDebug("adding cell at %d/%d span=(%d/%d)", cRow, cCol, rSpan, cSpan );
+
+ if ( rSpan == 1 ) {
+ // we ignore height settings on rowspan cells
+ Length height = cell->style()->height();
+ if ( height.value() > 0 || (height.isRelative() && height.value() >= 0) ) {
+ Length cRowHeight = grid[cRow].height;
+ switch( height.type() ) {
+ case Percent:
+ if ( !cRowHeight.isPercent() ||
+ (cRowHeight.isPercent() && cRowHeight.value() < height.value() ) )
+ grid[cRow].height = height;
+ break;
+ case Fixed:
+ if ( cRowHeight.type() < Percent ||
+ ( cRowHeight.isFixed() && cRowHeight.value() < height.value() ) )
+ grid[cRow].height = height;
+ break;
+ case Relative:
+#if 0
+ // we treat this as variable. This is correct according to HTML4, as it only specifies length for the height.
+ if ( cRowHeight.type == Variable ||
+ ( cRowHeight.type == Relative && cRowHeight.value < height.value ) )
+ grid[cRow].height = height;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+ }
+
+ // make sure we have enough rows
+ ensureRows( cRow + rSpan );
+
+ grid[cRow].rowRenderer = row;
+
+ int col = cCol;
+ // tell the cell where it is
+ RenderTableCell *set = cell;
+ while ( cSpan ) {
+ int currentSpan;
+ if ( cCol >= nCols ) {
+ table()->appendColumn( cSpan );
+ currentSpan = cSpan;
+ } else {
+ if ( cSpan < columns[cCol].span )
+ table()->splitColumn( cCol, cSpan );
+ currentSpan = columns[cCol].span;
+ }
+ int r = 0;
+ while ( r < rSpan ) {
+ if ( !cellAt( cRow + r, cCol ) ) {
+// tqDebug(" adding cell at %d, %d", cRow + r, cCol );
+ cellAt( cRow + r, cCol ) = set;
+ }
+ r++;
+ }
+ cCol++;
+ cSpan -= currentSpan;
+ set = (RenderTableCell *)-1;
+ }
+ if ( cell ) {
+ cell->setRow( cRow );
+ cell->setCol( table()->effColToCol( col ) );
+ }
+}
+
+
+
+void RenderTableSection::setCellWidths()
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
+#endif
+ TQMemArray<int> &columnPos = table()->columnPos;
+
+ int rows = grid.size();
+ for ( int i = 0; i < rows; i++ ) {
+ Row &row = *grid[i].row;
+ int cols = row.size();
+ for ( int j = 0; j < cols; j++ ) {
+ RenderTableCell *cell = row[j];
+// tqDebug("cell[%d,%d] = %p", i, j, cell );
+ if ( !cell || cell == (RenderTableCell *)-1 )
+ continue;
+ int endCol = j;
+ int cspan = cell->colSpan();
+ while ( cspan && endCol < cols ) {
+ cspan -= table()->columns[endCol].span;
+ endCol++;
+ }
+ int w = columnPos[endCol] - columnPos[j] - table()->borderHSpacing();
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "setting width of cell " << cell << " " << cell->row() << "/" << cell->col() << " to " << w << " colspan=" << cell->colSpan() << " start=" << j << " end=" << endCol << endl;
+#endif
+ int oldWidth = cell->width();
+ if ( w != oldWidth ) {
+ cell->setNeedsLayout(true);
+ cell->setWidth( w );
+ }
+ }
+ }
+}
+
+short RenderTableSection::width() const
+{
+ return table()->width();
+}
+
+
+void RenderTableSection::calcRowHeight()
+{
+ int indx;
+ RenderTableCell *cell;
+
+ int totalRows = grid.size();
+ int vspacing = table()->borderVSpacing();
+
+ rowPos.resize( totalRows + 1 );
+ rowPos[0] = vspacing + borderTop();
+
+ for ( int r = 0; r < totalRows; r++ ) {
+ rowPos[r+1] = 0;
+
+ int baseline=0;
+ int bdesc = 0;
+// tqDebug("height of row %d is %d/%d", r, grid[r].height.value, grid[r].height.type );
+ int ch = grid[r].height.minWidth( 0 );
+ int pos = rowPos[r] + ch + (grid[r].rowRenderer ? vspacing : 0);
+
+ if ( pos > rowPos[r+1] )
+ rowPos[r+1] = pos;
+
+ Row *row = grid[r].row;
+ int totalCols = row->size();
+ int totalRows = grid.size();
+ bool pagedMode = canvas()->pagedMode();
+
+ grid[r].needFlex = false;
+
+ for ( int c = 0; c < totalCols; c++ ) {
+ cell = cellAt(r, c);
+ if ( !cell || cell == (RenderTableCell *)-1 )
+ continue;
+ if ( r < totalRows - 1 && cellAt(r+1, c) == cell )
+ continue;
+
+ if ( ( indx = r - cell->rowSpan() + 1 ) < 0 )
+ indx = 0;
+
+ if (cell->cellPercentageHeight() != -1) {
+ cell->setCellPercentageHeight(-1);
+ cell->setChildNeedsLayout(true, false);
+ if (cell->hasFlexedAnonymous()) {
+ for (RenderObject* o = cell->firstChild(); o ; o = o->nextSibling())
+ if (o->isAnonymousBlock())
+ o->setChildNeedsLayout(true, false);
+ }
+ if (pagedMode) cell->setNeedsLayout(true);
+ cell->layoutIfNeeded();
+ }
+
+ ch = cell->style()->height().width(0);
+ if ( cell->height() > ch)
+ ch = cell->height();
+
+ if (!cell->style()->height().isVariable())
+ grid[r].needFlex = true;
+
+ pos = rowPos[indx] + ch + (grid[r].rowRenderer ? vspacing : 0);
+
+ if ( pos > rowPos[r+1] )
+ rowPos[r+1] = pos;
+
+ // find out the baseline
+ EVerticalAlign va = cell->style()->verticalAlign();
+ if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP
+ || va == SUPER || va == SUB)
+ {
+ int b=cell->baselinePosition();
+ if (b > cell->borderTop() + cell->paddingTop()) {
+ if (b>baseline)
+ baseline=b;
+
+ int td = rowPos[ indx ] + ch - b;
+ if (td>bdesc)
+ bdesc = td;
+ }
+ }
+ }
+
+ //do we have baseline aligned elements?
+ if (baseline) {
+ // increase rowheight if baseline requires
+ int bRowPos = baseline + bdesc + (grid[r].rowRenderer ? vspacing : 0);
+ if (rowPos[r+1]<bRowPos)
+ rowPos[r+1]=bRowPos;
+
+ grid[r].baseLine = baseline;
+ }
+
+ if ( rowPos[r+1] < rowPos[r] )
+ rowPos[r+1] = rowPos[r];
+// tqDebug("rowpos(%d)=%d", r, rowPos[r] );
+ }
+}
+
+int RenderTableSection::layoutRows( int toAdd )
+{
+ int rHeight;
+ int rindx;
+ int totalRows = grid.size();
+ int hspacing = table()->borderHSpacing();
+ int vspacing = table()->borderVSpacing();
+
+ // Set the width of our section now. The rows will also be this width.
+ m_width = table()->contentWidth();
+
+ if (markedForRepaint()) {
+ repaintDuringLayout();
+ setMarkedForRepaint(false);
+ }
+
+ if (toAdd && totalRows && (rowPos[totalRows] || !nextSibling())) {
+
+ int totalHeight = rowPos[totalRows] + toAdd;
+// tqDebug("layoutRows: totalHeight = %d", totalHeight );
+
+ int dh = toAdd;
+ int totalPercent = 0;
+ int numVariable = 0;
+ for ( int r = 0; r < totalRows; r++ ) {
+ if ( grid[r].height.isVariable() && !emptyRow(r))
+ numVariable++;
+ else if ( grid[r].height.isPercent() )
+ totalPercent += grid[r].height.value();
+ }
+ if ( totalPercent ) {
+// tqDebug("distributing %d over percent rows totalPercent=%d", dh, totalPercent );
+ // try to satisfy percent
+ int add = 0;
+ if ( totalPercent > 100 )
+ totalPercent = 100;
+ int rh = rowPos[1]-rowPos[0];
+ for ( int r = 0; r < totalRows; r++ ) {
+ if ( totalPercent > 0 && grid[r].height.isPercent() ) {
+ int toAdd = kMin( dh, (totalHeight * grid[r].height.value() / 100)-rh );
+ // If toAdd is negative, then we don't want to shrink the row (this bug
+ // affected Outlook Web Access).
+ toAdd = kMax(0, toAdd);
+ add += toAdd;
+ dh -= toAdd;
+ totalPercent -= grid[r].height.value();
+// tqDebug( "adding %d to row %d", toAdd, r );
+ }
+ if ( r < totalRows-1 )
+ rh = rowPos[r+2] - rowPos[r+1];
+ rowPos[r+1] += add;
+ }
+ }
+ if ( numVariable ) {
+ // distribute over non-empty variable rows
+// tqDebug("distributing %d over variable rows numVariable=%d", dh, numVariable );
+ int add = 0;
+ int toAdd = dh/numVariable;
+ for ( int r = 0; r < totalRows; r++ ) {
+ if ( grid[r].height.isVariable() && !emptyRow(r)) {
+ add += toAdd;
+ }
+ rowPos[r+1] += add;
+ }
+ dh -= add;
+ }
+ if (dh>0 && rowPos[totalRows]) {
+ // if some left overs, distribute weighted.
+ int tot=rowPos[totalRows];
+ int add=0;
+ int prev=rowPos[0];
+ for ( int r = 0; r < totalRows; r++ ) {
+ //weight with the original height
+ add+=dh*(rowPos[r+1]-prev)/tot;
+ prev=rowPos[r+1];
+ rowPos[r+1]+=add;
+ }
+ dh -= add;
+ }
+ if (dh > totalRows) {
+ // distribute to tables with all empty rows
+ int add=0;
+ int toAdd = dh/totalRows;
+ for ( int r = 0; r < totalRows; r++ ) {
+ add += toAdd;
+ rowPos[r+1] += add;
+ }
+ dh -= add;
+ }
+ // Finally distribute round-off values
+ if (dh > 0) {
+ // There is not enough for every row
+ int add=0;
+ for ( int r = 0; r < totalRows; r++ ) {
+ if (add < dh) add++;
+ rowPos[r+1] += add;
+ }
+ dh -= add;
+ }
+ assert (dh == 0);
+ }
+
+ int leftOffset = borderLeft() + hspacing;
+
+ int nEffCols = table()->numEffCols();
+ for ( int r = 0; r < totalRows; r++ )
+ {
+ Row *row = grid[r].row;
+ int totalCols = row->size();
+
+#ifdef APPLE_CHANGES
+ // in WC, rows and cells share the same coordinate space, so that rows can have
+ // dimensions in the layer system. This is of dubious value, and a heavy maintenance burden
+ // (RenderObject's coordinates can't be used deterministically anymore) so we'll consider other options.
+
+ // Set the row's x/y position and width/height.
+ if (grid[r].rowRenderer) {
+ grid[r].rowRenderer->setPos(0, rowPos[r]);
+ grid[r].rowRenderer->setWidth(m_width);
+ grid[r].rowRenderer->setHeight(rowPos[r+1] - rowPos[r] - vspacing);
+ }
+#endif
+
+ for ( int c = 0; c < nEffCols; c++ )
+ {
+ RenderTableCell *cell = cellAt(r, c);
+ if (!cell || cell == (RenderTableCell *)-1 )
+ continue;
+ if ( r < totalRows - 1 && cell == cellAt(r+1, c) )
+ continue;
+
+ if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
+ rindx = 0;
+
+ rHeight = rowPos[r+1] - rowPos[rindx] - vspacing;
+
+ // Force percent height children to lay themselves out again.
+ // This will cause, e.g., textareas to grow to
+ // fill the area. FIXME: <div>s and blocks still don't
+ // work right. We'll need to have an efficient way of
+ // invalidating all percent height objects in a render subtree.
+ // For now, we just handle immediate children. -dwh
+
+ bool flexAllChildren = grid[r].needFlex || (!table()->style()->height().isVariable() && rHeight != cell->height());
+ cell->setHasFlexedAnonymous(false);
+ if ( flexAllChildren && flexCellChildren(cell) ) {
+ cell->setCellPercentageHeight(kMax(0,
+ rHeight - cell->borderTop() - cell->paddingTop() -
+ cell->borderBottom() - cell->paddingBottom()));
+ cell->layoutIfNeeded();
+
+ }
+ {
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << "setting position " << r << "/" << c << ": "
+ << table()->columnPos[c] /*+ padding */ << "/" << rowPos[rindx] << " height=" << rHeight<< endl;
+#endif
+
+ EVerticalAlign va = cell->style()->verticalAlign();
+ int te=0;
+ switch (va)
+ {
+ case SUB:
+ case SUPER:
+ case TEXT_TOP:
+ case TEXT_BOTTOM:
+ case BASELINE:
+ te = getBaseline(r) - cell->baselinePosition() ;
+ break;
+ case TOP:
+ te = 0;
+ break;
+ case MIDDLE:
+ te = (rHeight - cell->height())/2;
+ break;
+ case BOTTOM:
+ te = rHeight - cell->height();
+ break;
+ default:
+ break;
+ }
+ te = kMax( 0, te );
+#ifdef DEBUG_LAYOUT
+ // kdDebug( 6040 ) << "CELL " << cell << " te=" << te << ", be=" << rHeight - cell->height() - te << ", rHeight=" << rHeight << ", valign=" << va << endl;
+#endif
+ cell->setCellTopExtra( te );
+ cell->setCellBottomExtra( rHeight - cell->height() - te);
+ }
+ if (style()->direction()==RTL) {
+ cell->setPos(
+ table()->columnPos[(int)totalCols] -
+ table()->columnPos[table()->colToEffCol(cell->col()+cell->colSpan())] +
+ leftOffset,
+ rowPos[rindx] );
+ } else {
+ cell->setPos( table()->columnPos[c] + leftOffset, rowPos[rindx] );
+ }
+ }
+ }
+
+ m_height = rowPos[totalRows];
+ return m_height;
+}
+
+bool RenderTableSection::flexCellChildren(RenderObject* p) const
+{
+ if (!p)
+ return false;
+ RenderObject* o = p->firstChild();
+ bool didFlex = false;
+ while (o) {
+ if (!o->isText() && o->style()->height().isPercent()) {
+ if (o->isWidget()) {
+ // cancel resizes from transitory relayouts
+ static_cast<RenderWidget *>(o)->cancelPendingResize();
+ }
+ o->setNeedsLayout(true, false);
+ p->setChildNeedsLayout(true, false);
+ didFlex = true;
+ } else if (o->isAnonymousBlock() && flexCellChildren( o )) {
+ p->setChildNeedsLayout(true, false);
+ if (p->isTableCell())
+ static_cast<RenderTableCell*>(p)->setHasFlexedAnonymous();
+ didFlex = true;
+ }
+ o = o->nextSibling();
+ }
+ return didFlex;
+}
+
+inline static RenderTableRow *firstTableRow(RenderObject *row)
+{
+ while (row && !row->isTableRow())
+ row = row->nextSibling();
+ return static_cast<RenderTableRow *>(row);
+}
+
+inline static RenderTableRow *nextTableRow(RenderObject *row)
+{
+ row = row ? row->nextSibling() : row;
+ while (row && !row->isTableRow())
+ row = row->nextSibling();
+ return static_cast<RenderTableRow *>(row);
+}
+
+int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return bottom;
+
+ for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
+ for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
+ if (cell->isTableCell()) {
+ int bp = cell->yPos() + cell->lowestPosition(false);
+ bottom = kMax(bottom, bp);
+ }
+ }
+
+ return bottom;
+}
+
+int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return right;
+
+ for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
+ for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
+ if (cell->isTableCell()) {
+ int rp = cell->xPos() + cell->rightmostPosition(false);
+ right = kMax(right, rp);
+ }
+ }
+
+ return right;
+}
+
+int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return left;
+
+ for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
+ for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
+ if (cell->isTableCell()) {
+ int lp = cell->xPos() + cell->leftmostPosition(false);
+ left = kMin(left, lp);
+ }
+ }
+
+ return left;
+}
+
+int RenderTableSection::highestPosition(bool includeOverflowInterior, bool includeSelf) const
+{
+ int top = RenderBox::highestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && hasOverflowClip())
+ return top;
+
+ for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
+ for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
+ if (cell->isTableCell()) {
+ int hp = cell->yPos() + cell->highestPosition(false);
+ top = kMin(top, hp);
+ }
+ }
+
+ return top;
+}
+
+// Search from first_row to last_row for the row containing y
+static unsigned int findRow(unsigned int first_row, unsigned int last_row,
+ const TQMemArray<int> &rowPos, int y)
+{
+ unsigned int under = first_row;
+ unsigned int over = last_row;
+ int offset = (over - under)/2;
+ while (over-under > 1) {
+ if (rowPos[under+offset] <= y)
+ under = under+offset;
+ else
+ over = under+offset;
+ offset = (over - under)/2;
+ }
+
+ assert(under == first_row || rowPos[under] <= y);
+ assert(over == last_row || rowPos[over] > y);
+
+ return under;
+}
+
+static void findRowCover(unsigned int &startrow, unsigned int &endrow,
+ const TQMemArray<int> &rowPos,
+ int min_y, int max_y)
+{
+ assert(max_y >= min_y);
+ unsigned int totalRows = endrow;
+
+ unsigned int index = 0;
+ // Initial binary search boost:
+ if (totalRows >= 8) {
+ int offset = (endrow - startrow)/2;
+ while (endrow - startrow > 1) {
+ index = startrow+offset;
+ if (rowPos[index] <= min_y )
+ // index is below both min_y and max_y
+ startrow = index;
+ else
+ if (rowPos[index] > max_y)
+ // index is above both min_y and max_y
+ endrow = index;
+ else
+ // index is within the selection
+ break;
+ offset = (endrow - startrow)/2;
+ }
+ }
+
+ // Binary search for startrow
+ startrow = findRow(startrow, endrow, rowPos, min_y);
+ // Binary search for endrow
+ endrow = findRow(startrow, endrow, rowPos, max_y) + 1;
+ if (endrow > totalRows) endrow = totalRows;
+}
+
+void RenderTableSection::paint( PaintInfo& pI, int tx, int ty )
+{
+ unsigned int totalRows = grid.size();
+ unsigned int totalCols = table()->columns.size();
+
+ tx += m_x;
+ ty += m_y;
+
+ if (pI.phase == PaintActionOutline)
+ paintOutline(pI.p, tx, ty, width(), height(), style());
+
+ CollapsedBorderValue *cbs = table()->currentBorderStyle();
+ int cbsw2 = cbs ? cbs->width()/2 : 0;
+ int cbsw21 = cbs ? (cbs->width()+1)/2 : 0;
+
+ int x = pI.r.x(), y = pI.r.y(), w = pI.r.width(), h = pI.r.height();
+ // check which rows and cols are visible and only paint these
+ int os = 2*maximalOutlineSize(pI.phase);
+ unsigned int startrow = 0;
+ unsigned int endrow = totalRows;
+ findRowCover(startrow, endrow, rowPos, y - os - ty - kMax(cbsw21, os), y + h + os - ty + kMax(cbsw2, os));
+
+ // A binary search is probably not worthwhile for coloumns
+ unsigned int startcol = 0;
+ unsigned int endcol = totalCols;
+ if ( style()->direction() == LTR ) {
+ for ( ; startcol < totalCols; startcol++ ) {
+ if ( tx + table()->columnPos[startcol+1] + kMax(cbsw21, os) > x - os )
+ break;
+ }
+ for ( ; endcol > 0; endcol-- ) {
+ if ( tx + table()->columnPos[endcol-1] - kMax(cbsw2, os) < x + w + os )
+ break;
+ }
+ }
+ if ( startcol < endcol ) {
+ // draw the cells
+ for ( unsigned int r = startrow; r < endrow; r++ ) {
+ // paint the row
+ if (grid[r].rowRenderer) {
+ int height = rowPos[r+1] - rowPos[r] - table()->borderVSpacing();
+ grid[r].rowRenderer->paintRow(pI, tx, ty + rowPos[r], width(), height);
+ }
+
+ unsigned int c = startcol;
+ Row *row = grid[r].row;
+ Row *nextrow = (r < endrow - 1) ? grid[r+1].row : 0;
+ // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
+ while ( c && (*row)[c] == (RenderTableCell *)-1 )
+ c--;
+ for ( ; c < endcol; c++ ) {
+ RenderTableCell *cell = (*row)[c];
+ if ( !cell || cell == (RenderTableCell *)-1 || nextrow && (*nextrow)[c] == cell )
+ continue;
+#ifdef TABLE_PRINT
+ kdDebug( 6040 ) << "painting cell " << r << "/" << c << endl;
+#endif
+ if (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground) {
+ // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
+ // the column group, column, row group, row, and then the cell.
+ RenderObject* col = table()->colElement(c);
+ RenderObject* colGroup = 0;
+ if (col) {
+ RenderStyle *style = col->parent()->style();
+ if (style->display() == TABLE_COLUMN_GROUP)
+ colGroup = col->parent();
+ }
+ RenderObject* row = cell->parent();
+
+ // ###
+ // Column groups and columns first.
+ // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
+ // the stack, since we have already opened a transparency layer (potentially) for the table row group.
+ // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
+ // cell.
+ cell->paintBackgroundsBehindCell(pI, tx, ty, colGroup);
+ cell->paintBackgroundsBehindCell(pI, tx, ty, col);
+
+ // Paint the row group next.
+ cell->paintBackgroundsBehindCell(pI, tx, ty, this);
+
+ // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
+ // painting the row background for the cell.
+ if (!row->layer())
+ cell->paintBackgroundsBehindCell(pI, tx, ty, row);
+ }
+
+ if ((!cell->layer() && !cell->parent()->layer()) || pI.phase == PaintActionCollapsedTableBorders)
+ cell->paint(pI, tx, ty);
+ }
+ }
+ }
+}
+
+void RenderTableSection::recalcCells()
+{
+ cCol = 0;
+ cRow = -1;
+ clearGrid();
+ grid.resize( 0 );
+
+ for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
+ if (row->isTableRow()) {
+ cRow++;
+ cCol = 0;
+ ensureRows( cRow+1 );
+ grid[cRow].rowRenderer = static_cast<RenderTableRow*>(row);
+
+ for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
+ if (cell->isTableCell())
+ addCell( static_cast<RenderTableCell *>(cell), static_cast<RenderTableRow *>(row) );
+ }
+ }
+ needCellRecalc = false;
+ setNeedsLayout(true);
+}
+
+void RenderTableSection::clearGrid()
+{
+ int rows = grid.size();
+ while ( rows-- ) {
+ delete grid[rows].row;
+ }
+}
+
+bool RenderTableSection::emptyRow(int rowNum) {
+ Row &r = *grid[rowNum].row;
+ const int s = r.size();
+ RenderTableCell *cell;
+ for(int i=0; i<s; i++) {
+ cell = r[i];
+ if (!cell || cell==(RenderTableCell*)-1)
+ continue;
+ return false;
+ }
+ return true;
+}
+
+RenderObject* RenderTableSection::removeChildNode(RenderObject* child)
+{
+ setNeedCellRecalc();
+ return RenderContainer::removeChildNode( child );
+}
+
+bool RenderTableSection::canClear(RenderObject */*child*/, PageBreakLevel level)
+{
+ // We cannot clear rows yet.
+ return parent()->canClear(this, level);
+}
+
+void RenderTableSection::addSpaceAt(int pos, int dy)
+{
+ const int nEffCols = table()->numEffCols();
+ const int totalRows = numRows();
+ for ( int r = 0; r < totalRows; r++ ) {
+ if (rowPos[r] >= pos) {
+ rowPos[r] += dy;
+ int rindx;
+ for ( int c = 0; c < nEffCols; c++ )
+ {
+ RenderTableCell *cell = cellAt(r, c);
+ if (!cell || cell == (RenderTableCell *)-1 )
+ continue;
+ if ( r > 0 && cell == cellAt(r-1, c) )
+ continue;
+
+ if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
+ rindx = 0;
+
+ cell->setPos(cell->xPos(), rowPos[r]);
+ }
+ }
+ }
+ if (rowPos[totalRows] >= pos)
+ rowPos[totalRows] += dy;
+ m_height = rowPos[totalRows];
+
+ setContainsPageBreak(true);
+}
+
+
+#ifdef ENABLE_DUMP
+void RenderTableSection::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderContainer::dump(stream,ind);
+
+ stream << " grid=(" << grid.size() << "," << table()->numEffCols() << ")";
+ for ( unsigned int r = 0; r < grid.size(); r++ ) {
+ for ( int c = 0; c < table()->numEffCols(); c++ ) {
+ if ( cellAt( r, c ) && cellAt( r, c ) != (RenderTableCell *)-1 )
+ stream << " (" << cellAt( r, c )->row() << "," << cellAt( r, c )->col() << ","
+ << cellAt(r, c)->rowSpan() << "," << cellAt(r, c)->colSpan() << ") ";
+ else
+ stream << " null cell";
+ }
+ }
+}
+#endif
+
+static RenderTableCell *seekCell(RenderTableSection *section, int row, int col)
+{
+ if (row < 0 || col < 0 || row >= section->numRows()) return 0;
+ // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
+ while ( col && section->cellAt( row, col ) == (RenderTableCell *)-1 )
+ col--;
+
+ return section->cellAt(row, col);
+}
+
+/** Looks for the first element suitable for text selection, beginning from
+ * the last.
+ * @param base search is restricted within this node. This node must have
+ * a renderer.
+ * @return the element or @p base if no suitable element found.
+ */
+static NodeImpl *findLastSelectableNode(NodeImpl *base)
+{
+ NodeImpl *last = base;
+ // Look for last text/cdata node that has a renderer,
+ // or last childless replaced element
+ while ( last && !(last->renderer()
+ && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
+ || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
+ {
+ NodeImpl *next = last->lastChild();
+ if ( !next ) next = last->previousSibling();
+ while ( last && last != base && !next )
+ {
+ last = last->parentNode();
+ if ( last && last != base )
+ next = last->previousSibling();
+ }
+ last = next;
+ }
+
+ return last ? last : base;
+}
+
+FindSelectionResult RenderTableSection::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
+{
+ // Table sections need extra treatment for selections. The rows are scanned
+ // from top to bottom, and within each row, only the cell that matches
+ // the given position best is descended into.
+
+ unsigned int totalRows = grid.size();
+ unsigned int totalCols = table()->columns.size();
+
+// absolutePosition(_tx, _ty, false);
+
+ _tx += m_x;
+ _ty += m_y;
+
+// bool save_last = false; // true to save last investigated cell
+
+ if (needsLayout() || _y < _ty) return SelectionPointBefore;
+// else if (_y >= _ty + height()) save_last = true;
+
+ // Find the row containing the pointer
+ int row_idx = findRow(0, totalRows, rowPos, _y - _ty);
+
+ int col_idx;
+ if ( style()->direction() == LTR ) {
+ for ( col_idx = (int)totalCols - 1; col_idx >= 0; col_idx-- ) {
+ if ( _tx + table()->columnPos[col_idx] < _x )
+ break;
+ }
+ if (col_idx < 0) col_idx = 0;
+ } else {
+ for ( col_idx = 0; col_idx < (int)totalCols; col_idx++ ) {
+ if ( _tx + table()->columnPos[col_idx] > _x )
+ break;
+ }
+ if (col_idx >= (int)totalCols) col_idx = (int)totalCols + 1;
+ }
+
+ FindSelectionResult pos = SelectionPointBefore;
+
+ RenderTableCell *cell = seekCell(this, row_idx, col_idx);
+ // ### dunno why cell can be 0, maybe due to weird spans? (LS)
+ if (cell) {
+ SelPointState localState;
+ pos = cell->checkSelectionPoint(_x, _y, _tx, _ty, node, offset, localState);
+ }
+
+ if (pos != SelectionPointBefore) return pos;
+
+ // store last column of last line
+ row_idx--;
+ col_idx = totalCols - 1;
+ cell = seekCell(this, row_idx, col_idx);
+
+ // end of section? take previous section
+ RenderTableSection *sec = this;
+ if (!cell) {
+ sec = *--TableSectionIterator(sec);
+ if (!sec) return pos;
+
+ cell = seekCell(sec, sec->grid.size() - 1, col_idx);
+ if (!cell) return pos;
+ }
+
+ // take last child of previous cell, and store this one as last node
+ NodeImpl *element = cell->element();
+ if (!element) return SelectionPointBefore;
+
+ element = findLastSelectableNode(element);
+
+ state.m_lastNode = element;
+ state.m_lastOffset = element->maxOffset();
+ return SelectionPointBefore;
+}
+
+// Hit Testing
+bool RenderTableSection::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside)
+{
+ // Table sections cannot ever be hit tested. Effectively they do not exist.
+ // Just forward to our children always.
+ tx += m_x;
+ ty += m_y;
+
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ // FIXME: We have to skip over inline flows, since they can show up inside table rows
+ // at the moment (a demoted inline <form> for example). If we ever implement a
+ // table-specific hit-test method (which we should do for performance reasons anyway),
+ // then we can remove this check.
+ if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(info, x, y, tx, ty, action, inside)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// -------------------------------------------------------------------------
+
+RenderTableRow::RenderTableRow(DOM::NodeImpl* node)
+ : RenderContainer(node)
+{
+ // init RenderObject attributes
+ setInline(false); // our object is not Inline
+}
+
+RenderObject* RenderTableRow::removeChildNode(RenderObject* child)
+{
+ RenderTableSection *s = section();
+ if (s)
+ s->setNeedCellRecalc();
+
+ return RenderContainer::removeChildNode( child );
+}
+
+void RenderTableRow::detach()
+{
+ RenderTableSection *s = section();
+ if (s)
+ s->setNeedCellRecalc();
+
+ RenderContainer::detach();
+}
+
+void RenderTableRow::setStyle(RenderStyle* newStyle)
+{
+ if (section() && style() && style()->height() != newStyle->height())
+ section()->setNeedCellRecalc();
+
+ newStyle->setDisplay(TABLE_ROW);
+ RenderContainer::setStyle(newStyle);
+}
+
+void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
+{
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(TableRow)::addChild( " << child->renderName() << " )" << ", " <<
+ (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
+#endif
+
+ if ( !child->isTableCell() ) {
+ // TR > FORM quirk (???)
+ if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM &&
+ static_cast<HTMLFormElementImpl*>(child->element())->isMalformed())
+ {
+ RenderContainer::addChild(child, beforeChild);
+ return;
+ }
+
+ RenderObject* last = beforeChild;
+ if (!last)
+ last = lastChild();
+ if (last && last->isAnonymous() && last->isTableCell()) {
+ last->addChild(child);
+ return;
+ }
+
+ // If beforeChild is inside an anonymous cell, insert into the cell.
+ if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
+ last->parent()->addChild(child, beforeChild);
+ return;
+ }
+
+ RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
+ RenderStyle* newStyle = new RenderStyle();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(TABLE_CELL);
+ cell->setStyle(newStyle);
+ addChild(cell, beforeChild);
+ cell->addChild(child);
+ return;
+ }
+
+ RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+
+ section()->addCell( cell, this );
+
+ RenderContainer::addChild(cell,beforeChild);
+
+ if ( beforeChild || nextSibling() )
+ section()->setNeedCellRecalc();
+}
+
+void RenderTableRow::layout()
+{
+ KHTMLAssert( needsLayout() );
+ KHTMLAssert( minMaxKnown() );
+
+ RenderObject *child = firstChild();
+ const bool pagedMode = canvas()->pagedMode();
+ while( child ) {
+ if ( child->isTableCell() ) {
+ RenderTableCell *cell = static_cast<RenderTableCell *>(child);
+ if (pagedMode) {
+ cell->setNeedsLayout(true);
+ int oldHeight = child->height();
+ cell->layout();
+ if (oldHeight > 0 && child->containsPageBreak() && child->height() != oldHeight)
+ section()->addSpaceAt(child->yPos()+1, child->height() - oldHeight);
+ } else
+ if ( child->needsLayout() ) {
+ if (markedForRepaint())
+ cell->setMarkedForRepaint( true );
+ cell->calcVerticalMargins();
+ cell->layout();
+ cell->setCellTopExtra(0);
+ cell->setCellBottomExtra(0);
+ if (child->containsPageBreak()) setContainsPageBreak(true);
+ }
+ }
+ child = child->nextSibling();
+ }
+ setMarkedForRepaint(false);
+ setNeedsLayout(false);
+}
+
+int RenderTableRow::offsetLeft() const
+{
+ RenderObject *child = firstChild();
+ while (child && !child->isTableCell())
+ child = child->nextSibling();
+
+ if (!child)
+ return 0;
+
+ return child->offsetLeft();
+}
+
+int RenderTableRow::offsetTop() const
+{
+ RenderObject *child = firstChild();
+ while (child && !child->isTableCell())
+ child = child->nextSibling();
+
+ if (!child)
+ return 0;
+
+ return child->offsetTop() -
+ static_cast<RenderTableCell*>(child)->cellTopExtra();
+}
+
+int RenderTableRow::offsetHeight() const
+{
+ RenderObject *child = firstChild();
+ while (child && !child->isTableCell())
+ child = child->nextSibling();
+
+ if (!child)
+ return 0;
+
+ return child->offsetHeight() +
+ static_cast<RenderTableCell*>(child)->cellTopExtra() +
+ static_cast<RenderTableCell*>(child)->cellBottomExtra();
+}
+
+short RenderTableRow::offsetWidth() const
+{
+ RenderObject *fc = firstChild();
+ RenderObject *lc = lastChild();
+ while (fc && !fc->isTableCell())
+ fc = fc->nextSibling();
+ while (lc && !lc->isTableCell())
+ lc = lc->previousSibling();
+ if (!lc || !fc)
+ return 0;
+
+ return lc->xPos()+lc->width()-fc->xPos();
+}
+
+void RenderTableRow::paintRow( PaintInfo& pI, int tx, int ty, int w, int h )
+{
+ if (pI.phase == PaintActionOutline)
+ paintOutline(pI.p, tx, ty, w, h, style());
+}
+
+void RenderTableRow::paint(PaintInfo& i, int tx, int ty)
+{
+ KHTMLAssert(layer());
+ if (!layer())
+ return;
+
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ if (child->isTableCell()) {
+ // Paint the row background behind the cell.
+ if (i.phase == PaintActionElementBackground || i.phase == PaintActionChildBackground) {
+ RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+ cell->paintBackgroundsBehindCell(i, tx, ty, this);
+ }
+ if (!child->layer())
+ child->paint(i, tx, ty);
+ }
+ }
+}
+
+// Hit Testing
+bool RenderTableRow::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside)
+{
+ // Table rows cannot ever be hit tested. Effectively they do not exist.
+ // Just forward to our children always.
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ // FIXME: We have to skip over inline flows, since they can show up inside table rows
+ // at the moment (a demoted inline <form> for example). If we ever implement a
+ // table-specific hit-test method (which we should do for performance reasons anyway),
+ // then we can remove this check.
+ if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(info, x, y, tx, ty, action, inside)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// -------------------------------------------------------------------------
+
+RenderTableCell::RenderTableCell(DOM::NodeImpl* _node)
+ : RenderBlock(_node)
+{
+ _col = -1;
+ _row = -1;
+ updateFromElement();
+ setShouldPaintBackgroundOrBorder(true);
+ _topExtra = 0;
+ _bottomExtra = 0;
+ m_percentageHeight = -1;
+ m_hasFlexedAnonymous = false;
+ m_widthChanged = false;
+}
+
+void RenderTableCell::detach()
+{
+ if (parent() && section())
+ section()->setNeedCellRecalc();
+
+ RenderBlock::detach();
+}
+
+void RenderTableCell::updateFromElement()
+{
+ DOM::NodeImpl *node = element();
+ if ( node && (node->id() == ID_TD || node->id() == ID_TH) ) {
+ DOM::HTMLTableCellElementImpl *tc = static_cast<DOM::HTMLTableCellElementImpl *>(node);
+ cSpan = tc->colSpan();
+ rSpan = tc->rowSpan();
+ } else {
+ cSpan = rSpan = 1;
+ }
+}
+
+Length RenderTableCell::styleOrColWidth()
+{
+ Length w = style()->width();
+ if (colSpan() > 1 || !w.isVariable())
+ return w;
+ RenderTableCol* col = table()->colElement(_col);
+ if (col)
+ w = col->style()->width();
+ return w;
+}
+
+void RenderTableCell::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(TableCell)::calcMinMaxWidth() known=" << minMaxKnown() << endl;
+#endif
+
+ if (section()->needCellRecalc)
+ section()->recalcCells();
+
+ RenderBlock::calcMinMaxWidth();
+ if (element() && style()->whiteSpace() == NORMAL) {
+ // See if nowrap was set.
+ Length w = styleOrColWidth();
+ DOMString nowrap = static_cast<ElementImpl*>(element())->getAttribute(ATTR_NOWRAP);
+ if (!nowrap.isNull() && w.isFixed() &&
+ m_minWidth < w.value() )
+ // Nowrap is set, but we didn't actually use it because of the
+ // fixed width set on the cell. Even so, it is a WinIE/Moz trait
+ // to make the minwidth of the cell into the fixed width. They do this
+ // even in strict mode, so do not make this a quirk. Affected the top
+ // of hiptop.com.
+ m_minWidth = w.value();
+ }
+
+ setMinMaxKnown();
+}
+
+void RenderTableCell::calcWidth()
+{
+}
+
+void RenderTableCell::setWidth( int width )
+{
+ if ( width != m_width ) {
+ m_width = width;
+ m_widthChanged = true;
+ }
+}
+
+void RenderTableCell::layout()
+{
+ layoutBlock( m_widthChanged );
+ m_widthChanged = false;
+}
+
+void RenderTableCell::close()
+{
+ RenderBlock::close();
+
+#ifdef DEBUG_LAYOUT
+ kdDebug( 6040 ) << renderName() << "(RenderTableCell)::close() total height =" << m_height << endl;
+#endif
+}
+
+bool RenderTableCell::requiresLayer() const {
+ // table-cell display is never positioned (css 2.1-9.7), so the only time a layer is needed
+ // is when overflow != visible (or when there is opacity when we support it)
+ return /* style()->opacity() < 1.0f || */ hasOverflowClip() || isRelPositioned();
+}
+
+void RenderTableCell::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
+{
+ RenderBlock::repaintRectangle(x, y, w, h + _topExtra + _bottomExtra, p, f);
+}
+
+bool RenderTableCell::absolutePosition(int &xPos, int &yPos, bool f) const
+{
+ bool result = RenderBlock::absolutePosition(xPos, yPos, f);
+ xPos -= parent()->xPos(); // Rows are in the same coordinate space, so don't add their offset in.
+ yPos -= parent()->yPos();
+ return result;
+}
+
+int RenderTableCell::pageTopAfter(int y) const
+{
+ return section()->pageTopAfter(y+m_y + _topExtra) - (m_y + _topExtra);
+}
+
+short RenderTableCell::baselinePosition( bool ) const
+{
+ RenderObject* o = firstChild();
+ int offset = paddingTop() + borderTop();
+ if (!o) return offset + contentHeight();
+ while (o->firstChild()) {
+ if (!o->isInline())
+ offset += o->paddingTop() + o->borderTop();
+ o = o->firstChild();
+ }
+
+ if (!o->isInline())
+ return paddingTop() + borderTop() + contentHeight();
+
+ offset += o->baselinePosition( true );
+ return offset;
+}
+
+
+void RenderTableCell::setStyle( RenderStyle *newStyle )
+{
+ if (parent() && section() && style() && style()->height() != newStyle->height())
+ section()->setNeedCellRecalc();
+
+ newStyle->setDisplay(TABLE_CELL);
+ RenderBlock::setStyle( newStyle );
+ setShouldPaintBackgroundOrBorder(true);
+
+ if (newStyle->whiteSpace() == KHTML_NOWRAP) {
+ // Figure out if we are really nowrapping or if we should just
+ // use normal instead. If the width of the cell is fixed, then
+ // we don't actually use NOWRAP.
+ if (newStyle->width().isFixed())
+ newStyle->setWhiteSpace(NORMAL);
+ else
+ newStyle->setWhiteSpace(NOWRAP);
+ }
+}
+
+bool RenderTableCell::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
+{
+ int tx = _tx + m_x;
+ int ty = _ty + m_y;
+
+ // also include the top and bottom extra space
+ inside |= style()->visibility() != HIDDEN
+ && (_y >= ty) && (_y < ty + height() + _topExtra + _bottomExtra)
+ && (_x >= tx) && (_x < tx + width());
+
+ return RenderBlock::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
+}
+
+// The following rules apply for resolving conflicts and figuring out which border
+// to use.
+// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting
+// borders. Any border with this value suppresses all borders at this location.
+// (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all
+// the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is
+// the default value for the border style.)
+// (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders
+// are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred
+// in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
+// (4) If border styles differ only in color, then a style set on a cell wins over one on a row,
+// which wins over a row group, column, column group and, lastly, table. It is undefined which color
+// is used when two elements of the same type disagree.
+static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1,
+ const CollapsedBorderValue& border2)
+{
+ // Sanity check the values passed in. If either is null, return the other.
+ if (!border2.exists()) return border1;
+ if (!border1.exists()) return border2;
+
+ // Rule #1 above.
+ if (border1.style() == BHIDDEN || border2.style() == BHIDDEN)
+ return CollapsedBorderValue(); // No border should exist at this location.
+
+ // Rule #2 above. A style of 'none' has lowest priority and always loses to any other border.
+ if (border2.style() == BNONE) return border1;
+ if (border1.style() == BNONE) return border2;
+
+ // The first part of rule #3 above. Wider borders win.
+ if (border1.width() != border2.width())
+ return border1.width() > border2.width() ? border1 : border2;
+
+ // The borders have equal width. Sort by border style.
+ if (border1.style() != border2.style())
+ return border1.style() > border2.style() ? border1 : border2;
+
+ // The border have the same width and style. Rely on precedence (cell over row over row group, etc.)
+ return border1.precedence >= border2.precedence ? border1 : border2;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedLeftBorder() const
+{
+ // For border left, we need to check, in order of precedence:
+ // (1) Our left border.
+ CollapsedBorderValue result(&style()->borderLeft(), BCELL);
+
+ // (2) The previous cell's right border.
+ RenderTableCell* prevCell = table()->cellLeft(this);
+ if (prevCell) {
+ result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL));
+ if (!result.exists()) return result;
+ }
+ else if (col() == 0) {
+ // (3) Our row's left border.
+ result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW));
+ if (!result.exists()) return result;
+
+ // (4) Our row group's left border.
+ result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderLeft(), BROWGROUP));
+ if (!result.exists()) return result;
+ }
+
+ // (5) Our column's left border.
+ RenderTableCol* colElt = table()->colElement(col());
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+ if (!result.exists()) return result;
+ }
+
+ // (6) The previous column's right border.
+ if (col() > 0) {
+ colElt = table()->colElement(col()-1);
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
+ if (!result.exists()) return result;
+ }
+ }
+
+ if (col() == 0) {
+ // (7) The table's left border.
+ result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderLeft(), BTABLE));
+ if (!result.exists()) return result;
+ }
+
+ return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedRightBorder() const
+{
+ RenderTable* tableElt = table();
+ bool inLastColumn = false;
+ int effCol = tableElt->colToEffCol(col()+colSpan()-1);
+ if (effCol == tableElt->numEffCols()-1)
+ inLastColumn = true;
+
+ // For border right, we need to check, in order of precedence:
+ // (1) Our right border.
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL);
+
+ // (2) The next cell's left border.
+ if (!inLastColumn) {
+ RenderTableCell* nextCell = tableElt->cellRight(this);
+ if (nextCell) {
+ result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL));
+ if (!result.exists()) return result;
+ }
+ }
+ else {
+ // (3) Our row's right border.
+ result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW));
+ if (!result.exists()) return result;
+
+ // (4) Our row group's right border.
+ result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderRight(), BROWGROUP));
+ if (!result.exists()) return result;
+ }
+
+ // (5) Our column's right border.
+ RenderTableCol* colElt = table()->colElement(col()+colSpan()-1);
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
+ if (!result.exists()) return result;
+ }
+
+ // (6) The next column's left border.
+ if (!inLastColumn) {
+ colElt = tableElt->colElement(col()+colSpan());
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
+ if (!result.exists()) return result;
+ }
+ }
+ else {
+ // (7) The table's right border.
+ result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE));
+ if (!result.exists()) return result;
+ }
+
+ return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
+{
+ // For border top, we need to check, in order of precedence:
+ // (1) Our top border.
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL);
+
+ RenderTableCell* prevCell = table()->cellAbove(this);
+ if (prevCell) {
+ // (2) A previous cell's bottom border.
+ result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL));
+ if (!result.exists()) return result;
+ }
+
+ // (3) Our row's top border.
+ result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW));
+ if (!result.exists()) return result;
+
+ // (4) The previous row's bottom border.
+ if (prevCell) {
+ RenderObject* prevRow = 0;
+ if (prevCell->section() == section())
+ prevRow = parent()->previousSibling();
+ else
+ prevRow = prevCell->section()->lastChild();
+
+ if (prevRow) {
+ result = compareBorders(result, CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW));
+ if (!result.exists()) return result;
+ }
+ }
+
+ // Now check row groups.
+ RenderTableSection* currSection = section();
+ if (row() == 0) {
+ // (5) Our row group's top border.
+ result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+ if (!result.exists()) return result;
+
+ // (6) Previous row group's bottom border.
+ currSection = table()->sectionAbove(currSection);
+ if (currSection) {
+ result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
+ if (!result.exists())
+ return result;
+ }
+ }
+
+ if (!currSection) {
+ // (8) Our column's top border.
+ RenderTableCol* colElt = table()->colElement(col());
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), BCOL));
+ if (!result.exists()) return result;
+ }
+
+ // (9) The table's top border.
+ result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderTop(), BTABLE));
+ if (!result.exists()) return result;
+ }
+
+ return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
+{
+ // For border top, we need to check, in order of precedence:
+ // (1) Our bottom border.
+ CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), BCELL);
+
+ RenderTableCell* nextCell = table()->cellBelow(this);
+ if (nextCell) {
+ // (2) A following cell's top border.
+ result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), BCELL));
+ if (!result.exists()) return result;
+ }
+
+ // (3) Our row's bottom border. (FIXME: Deal with rowspan!)
+ result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), BROW));
+ if (!result.exists()) return result;
+
+ // (4) The next row's top border.
+ if (nextCell) {
+ result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), BROW));
+ if (!result.exists()) return result;
+ }
+
+ // Now check row groups.
+ RenderTableSection* currSection = section();
+ if (row()+rowSpan() >= static_cast<RenderTableSection*>(currSection)->numRows()) {
+ // (5) Our row group's bottom border.
+ result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
+ if (!result.exists()) return result;
+
+ // (6) Following row group's top border.
+ currSection = table()->sectionBelow(currSection);
+ if (currSection) {
+ result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
+ if (!result.exists())
+ return result;
+ }
+ }
+
+ if (!currSection) {
+ // (8) Our column's bottom border.
+ RenderTableCol* colElt = table()->colElement(col());
+ if (colElt) {
+ result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), BCOL));
+ if (!result.exists()) return result;
+ }
+
+ // (9) The table's bottom border.
+ result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderBottom(), BTABLE));
+ if (!result.exists()) return result;
+ }
+
+ return result;
+}
+
+int RenderTableCell::borderLeft() const
+{
+ if (table()->collapseBorders()) {
+ CollapsedBorderValue border = collapsedLeftBorder();
+ if (border.exists())
+ return (border.width()+1)/2; // Give the extra pixel to top and left.
+ return 0;
+ }
+ return RenderBlock::borderLeft();
+}
+
+int RenderTableCell::borderRight() const
+{
+ if (table()->collapseBorders()) {
+ CollapsedBorderValue border = collapsedRightBorder();
+ if (border.exists())
+ return border.width()/2;
+ return 0;
+ }
+ return RenderBlock::borderRight();
+}
+
+int RenderTableCell::borderTop() const
+{
+ if (table()->collapseBorders()) {
+ CollapsedBorderValue border = collapsedTopBorder();
+ if (border.exists())
+ return (border.width()+1)/2; // Give the extra pixel to top and left.
+ return 0;
+ }
+ return RenderBlock::borderTop();
+}
+
+int RenderTableCell::borderBottom() const
+{
+ if (table()->collapseBorders()) {
+ CollapsedBorderValue border = collapsedBottomBorder();
+ if (border.exists())
+ return border.width()/2;
+ return 0;
+ }
+ return RenderBlock::borderBottom();
+}
+
+#ifdef BOX_DEBUG
+#include <tqpainter.h>
+
+static void outlineBox(TQPainter *p, int _tx, int _ty, int w, int h)
+{
+ p->setPen(TQPen(TQColor("yellow"), 3, Qt::DotLine));
+ p->setBrush( Qt::NoBrush );
+ p->drawRect(_tx, _ty, w, h );
+}
+#endif
+
+void RenderTableCell::paint(PaintInfo& pI, int _tx, int _ty)
+{
+
+#ifdef TABLE_PRINT
+ kdDebug( 6040 ) << renderName() << "(RenderTableCell)::paint() w/h = (" << width() << "/" << height() << ")" << " _y/_h=" << pI.r.y() << "/" << pI.r.height() << endl;
+#endif
+
+ if (needsLayout()) return;
+
+ _tx += m_x;
+ _ty += m_y/* + _topExtra*/;
+
+ RenderTable *tbl = table();
+
+ // check if we need to do anything at all...
+ int os = kMax(tbl->currentBorderStyle() ? (tbl->currentBorderStyle()->border->width+1)/2 : 0, 2*maximalOutlineSize(pI.phase));
+ if (!overhangingContents() && ((_ty >= pI.r.y() + pI.r.height() + os)
+ || (_ty + _topExtra + m_height + _bottomExtra <= pI.r.y() - os))) return;
+
+ if (pI.phase == PaintActionOutline) {
+ paintOutline( pI.p, _tx, _ty, width(), height() + borderTopExtra() + borderBottomExtra(), style());
+ }
+
+ if (pI.phase == PaintActionCollapsedTableBorders && style()->visibility() == VISIBLE) {
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ paintCollapsedBorder(pI.p, _tx, _ty, w, h);
+ }
+ else
+ RenderBlock::paintObject(pI, _tx, _ty + _topExtra, false);
+
+#ifdef BOX_DEBUG
+ ::outlineBox( p, _tx, _ty - _topExtra, width(), height() + borderTopExtra() + borderBottomExtra());
+#endif
+}
+
+static EBorderStyle collapsedBorderStyle(EBorderStyle style)
+{
+ if (style == OUTSET)
+ style = GROOVE;
+ else if (style == INSET)
+ style = RIDGE;
+ return style;
+}
+
+struct CollapsedBorder {
+ CollapsedBorder(){}
+
+ CollapsedBorderValue border;
+ RenderObject::BorderSide side;
+ bool shouldPaint;
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ EBorderStyle style;
+};
+
+class CollapsedBorders
+{
+public:
+ CollapsedBorders() :count(0) {}
+
+ void addBorder(const CollapsedBorderValue& b, RenderObject::BorderSide s, bool paint,
+ int _x1, int _y1, int _x2, int _y2,
+ EBorderStyle _style)
+ {
+ if (b.exists() && paint) {
+ borders[count].border = b;
+ borders[count].side = s;
+ borders[count].shouldPaint = paint;
+ borders[count].x1 = _x1;
+ borders[count].x2 = _x2;
+ borders[count].y1 = _y1;
+ borders[count].y2 = _y2;
+ borders[count].style = _style;
+ count++;
+ }
+ }
+
+ CollapsedBorder* nextBorder() {
+ for (int i = 0; i < count; i++) {
+ if (borders[i].border.exists() && borders[i].shouldPaint) {
+ borders[i].shouldPaint = false;
+ return &borders[i];
+ }
+ }
+
+ return 0;
+ }
+
+ CollapsedBorder borders[4];
+ int count;
+};
+
+static void addBorderStyle(TQValueList<CollapsedBorderValue>& borderStyles, CollapsedBorderValue borderValue)
+{
+ if (!borderValue.exists() || borderStyles.contains(borderValue))
+ return;
+
+ TQValueListIterator<CollapsedBorderValue> it = borderStyles.begin();
+ TQValueListIterator<CollapsedBorderValue> end = borderStyles.end();
+ for (; it != end; ++it) {
+ CollapsedBorderValue result = compareBorders(*it, borderValue);
+ if (result == *it) {
+ borderStyles.insert(it, borderValue);
+ return;
+ }
+ }
+
+ borderStyles.append(borderValue);
+}
+
+void RenderTableCell::collectBorders(TQValueList<CollapsedBorderValue>& borderStyles)
+{
+ addBorderStyle(borderStyles, collapsedLeftBorder());
+ addBorderStyle(borderStyles, collapsedRightBorder());
+ addBorderStyle(borderStyles, collapsedTopBorder());
+ addBorderStyle(borderStyles, collapsedBottomBorder());
+}
+
+void RenderTableCell::paintCollapsedBorder(TQPainter* p, int _tx, int _ty, int w, int h)
+{
+ if (!table()->currentBorderStyle())
+ return;
+
+ CollapsedBorderValue leftVal = collapsedLeftBorder();
+ CollapsedBorderValue rightVal = collapsedRightBorder();
+ CollapsedBorderValue topVal = collapsedTopBorder();
+ CollapsedBorderValue bottomVal = collapsedBottomBorder();
+
+ // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
+ int topWidth = topVal.width();
+ int bottomWidth = bottomVal.width();
+ int leftWidth = leftVal.width();
+ int rightWidth = rightVal.width();
+
+ _tx -= leftWidth/2;
+ _ty -= topWidth/2;
+ w += leftWidth/2 + (rightWidth+1)/2;
+ h += topWidth/2 + (bottomWidth+1)/2;
+
+ bool tt = topVal.isTransparent();
+ bool bt = bottomVal.isTransparent();
+ bool rt = rightVal.isTransparent();
+ bool lt = leftVal.isTransparent();
+
+ EBorderStyle ts = collapsedBorderStyle(topVal.style());
+ EBorderStyle bs = collapsedBorderStyle(bottomVal.style());
+ EBorderStyle ls = collapsedBorderStyle(leftVal.style());
+ EBorderStyle rs = collapsedBorderStyle(rightVal.style());
+
+ bool render_t = ts > BHIDDEN && !tt && (topVal.precedence != BCELL || *topVal.border == style()->borderTop());
+ bool render_l = ls > BHIDDEN && !lt && (leftVal.precedence != BCELL || *leftVal.border == style()->borderLeft());
+ bool render_r = rs > BHIDDEN && !rt && (rightVal.precedence != BCELL || *rightVal.border == style()->borderRight());
+ bool render_b = bs > BHIDDEN && !bt && (bottomVal.precedence != BCELL || *bottomVal.border == style()->borderBottom());
+
+ // We never paint diagonals at the joins. We simply let the border with the highest
+ // precedence paint on top of borders with lower precedence.
+ CollapsedBorders borders;
+ borders.addBorder(topVal, BSTop, render_t, _tx, _ty, _tx + w, _ty + topWidth, ts);
+ borders.addBorder(bottomVal, BSBottom, render_b, _tx, _ty + h - bottomWidth, _tx + w, _ty + h, bs);
+ borders.addBorder(leftVal, BSLeft, render_l, _tx, _ty, _tx + leftWidth, _ty + h, ls);
+ borders.addBorder(rightVal, BSRight, render_r, _tx + w - rightWidth, _ty, _tx + w, _ty + h, rs);
+
+ for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
+ if (border->border == *table()->currentBorderStyle())
+ drawBorder(p, border->x1, border->y1, border->x2, border->y2, border->side,
+ border->border.color(), style()->color(), border->style, 0, 0);
+ }
+}
+
+void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& pI, int _tx, int _ty, RenderObject* backgroundObject)
+{
+ if (!backgroundObject)
+ return;
+
+ RenderTable* tableElt = table();
+ if (backgroundObject != this) {
+ _tx += m_x;
+ _ty += m_y + _topExtra;
+ }
+
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ _ty -= borderTopExtra();
+
+ int my = kMax(_ty,pI.r.y());
+ int end = kMin( pI.r.y() + pI.r.height(), _ty + h );
+ int mh = end - my;
+
+ TQColor c = backgroundObject->style()->backgroundColor();
+ const BackgroundLayer* bgLayer = backgroundObject->style()->backgroundLayers();
+
+ if (bgLayer->hasImage() || c.isValid()) {
+ // We have to clip here because the background would paint
+ // on top of the borders otherwise. This only matters for cells and rows.
+ bool hasLayer = backgroundObject->layer() && (backgroundObject == this || backgroundObject == parent());
+ if (hasLayer && tableElt->collapseBorders()) {
+ pI.p->save();
+ TQRect clipRect(_tx + borderLeft(), _ty + borderTop(), w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
+ clipRect = pI.p->xForm(clipRect);
+ TQRegion creg(clipRect);
+ TQRegion old = pI.p->clipRegion();
+ if (!old.isNull())
+ creg = old.intersect(creg);
+ pI.p->setClipRegion(creg);
+ }
+ paintBackground(pI.p, c, bgLayer, my, mh, _tx, _ty, w, h);
+ if (hasLayer && tableElt->collapseBorders())
+ pI.p->restore();
+ }
+}
+
+void RenderTableCell::paintBoxDecorations(PaintInfo& pI, int _tx, int _ty)
+{
+ RenderTable* tableElt = table();
+ bool drawBorders = true;
+ // Moz paints bgcolor/bgimage on <td>s in quirks mode even if
+ // empty-cells are on. Fixes regression on #43426, attachment #354
+ if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+ drawBorders = false;
+ if (!style()->htmlHacks() && !drawBorders) return;
+
+ // Paint our cell background.
+ paintBackgroundsBehindCell(pI, _tx, _ty, this);
+
+ int w = width();
+ int h = height() + borderTopExtra() + borderBottomExtra();
+ _ty -= borderTopExtra();
+
+ if (drawBorders && style()->hasBorder() && !tableElt->collapseBorders())
+ paintBorder(pI.p, _tx, _ty, w, h, style());
+}
+
+
+#ifdef ENABLE_DUMP
+void RenderTableCell::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderFlow::dump(stream,ind);
+ stream << " row=" << _row;
+ stream << " col=" << _col;
+ stream << " rSpan=" << rSpan;
+ stream << " cSpan=" << cSpan;
+// *stream << " nWrap=" << nWrap;
+}
+#endif
+
+// -------------------------------------------------------------------------
+
+RenderTableCol::RenderTableCol(DOM::NodeImpl* node)
+ : RenderContainer(node), m_span(1)
+{
+ // init RenderObject attributes
+ setInline(true); // our object is not Inline
+ updateFromElement();
+}
+
+void RenderTableCol::updateFromElement()
+{
+ DOM::NodeImpl *node = element();
+ if ( node && (node->id() == ID_COL || node->id() == ID_COLGROUP) ) {
+ DOM::HTMLTableColElementImpl *tc = static_cast<DOM::HTMLTableColElementImpl *>(node);
+ m_span = tc->span();
+ } else
+ m_span = ! ( style() && style()->display() == TABLE_COLUMN_GROUP );
+}
+
+#ifdef ENABLE_DUMP
+void RenderTableCol::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderContainer::dump(stream,ind);
+ stream << " _span=" << m_span;
+}
+#endif
+
+// -------------------------------------------------------------------------
+
+TableSectionIterator::TableSectionIterator(RenderTable *table, bool fromEnd)
+{
+ if (fromEnd) {
+ sec = table->foot;
+ if (sec) return;
+
+ sec = static_cast<RenderTableSection *>(table->lastChild());
+ while (sec && (!sec->isTableSection()
+ || sec == table->head || sec == table->foot))
+ sec = static_cast<RenderTableSection *>(sec->previousSibling());
+ if (sec) return;
+
+ sec = table->head;
+ } else {
+ sec = table->head;
+ if (sec) return;
+
+ sec = static_cast<RenderTableSection *>(table->firstChild());
+ while (sec && (!sec->isTableSection()
+ || sec == table->head || sec == table->foot))
+ sec = static_cast<RenderTableSection *>(sec->nextSibling());
+ if (sec) return;
+
+ sec = table->foot;
+ }/*end if*/
+
+}
+
+TableSectionIterator &TableSectionIterator::operator ++()
+{
+ RenderTable *table = sec->table();
+ if (sec == table->head) {
+
+ sec = static_cast<RenderTableSection *>(table->firstChild());
+ while (sec && (!sec->isTableSection()
+ || sec == table->head || sec == table->foot))
+ sec = static_cast<RenderTableSection *>(sec->nextSibling());
+ if (sec) return *this;
+
+ } else if (sec == table->foot) {
+ sec = 0;
+ return *this;
+
+ } else {
+
+ do {
+ sec = static_cast<RenderTableSection *>(sec->nextSibling());
+ } while (sec && (!sec->isTableSection() || sec == table->head || sec == table->foot));
+ if (sec) return *this;
+
+ }/*end if*/
+
+ sec = table->foot;
+ return *this;
+}
+
+TableSectionIterator &TableSectionIterator::operator --()
+{
+ RenderTable *table = sec->table();
+ if (sec == table->foot) {
+
+ sec = static_cast<RenderTableSection *>(table->lastChild());
+ while (sec && (!sec->isTableSection()
+ || sec == table->head || sec == table->foot))
+ sec = static_cast<RenderTableSection *>(sec->previousSibling());
+ if (sec) return *this;
+
+ } else if (sec == table->head) {
+ sec = 0;
+ return *this;
+
+ } else {
+
+ do {
+ sec = static_cast<RenderTableSection *>(sec->previousSibling());
+ } while (sec && (!sec->isTableSection() || sec == table->head || sec == table->foot));
+ if (sec) return *this;
+
+ }/*end if*/
+
+ sec = table->foot;
+ return *this;
+}
+
+#undef TABLE_DEBUG
+#undef DEBUG_LAYOUT
+#undef BOX_DEBUG
diff --git a/tdehtml/rendering/render_table.h b/tdehtml/rendering/render_table.h
new file mode 100644
index 000000000..09695e3d8
--- /dev/null
+++ b/tdehtml/rendering/render_table.h
@@ -0,0 +1,524 @@
+/*
+ * 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.
+ *
+ * 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 RENDER_TABLE_H
+#define RENDER_TABLE_H
+
+#include <tqcolor.h>
+#include <tqptrvector.h>
+
+#include "rendering/render_box.h"
+#include "rendering/render_block.h"
+#include "rendering/render_style.h"
+
+#include "misc/tdehtmllayout.h"
+
+namespace DOM {
+ class DOMString;
+}
+
+namespace tdehtml {
+
+class RenderTable;
+class RenderTableSection;
+class RenderTableRow;
+class RenderTableCell;
+class RenderTableCol;
+class TableLayout;
+
+class RenderTable : public RenderBlock
+{
+public:
+
+ RenderTable(DOM::NodeImpl* node);
+ ~RenderTable();
+
+ virtual const char *renderName() const { return "RenderTable"; }
+
+ virtual void setStyle(RenderStyle *style);
+
+ virtual bool isTable() const { return true; }
+
+ int getColumnPos(int col) const
+ { return columnPos[col]; }
+
+ int borderHSpacing() const { return hspacing; }
+ int borderVSpacing() const { return vspacing; }
+
+ bool collapseBorders() const { return style()->borderCollapse(); }
+ int borderLeft() const;
+ int borderRight() const;
+ int borderTop() const;
+ int borderBottom() const;
+ int paddingLeft() const { return collapseBorders() ? 0 : RenderBlock::paddingLeft(); }
+ int paddingRight() const { return collapseBorders() ? 0 : RenderBlock::paddingRight(); }
+ int paddingTop() const { return collapseBorders() ? 0 : RenderBlock::paddingTop(); }
+ int paddingBottom() const { return collapseBorders() ? 0 : RenderBlock::paddingBottom(); }
+
+ const TQColor &bgColor() const { return style()->backgroundColor(); }
+
+ uint cellPadding() const { return padding; }
+ void setCellPadding( uint p ) { padding = p; }
+
+ // overrides
+ virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
+ virtual void paint( PaintInfo&, int tx, int ty);
+ virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
+ virtual void layout();
+ virtual void calcMinMaxWidth();
+ virtual void close();
+
+ virtual short lineHeight(bool b) const;
+ virtual short baselinePosition(bool b) const;
+
+ virtual void setCellWidths( );
+
+ virtual void calcWidth();
+
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*& node, int & offset,
+ SelPointState & );
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+ struct ColumnStruct {
+ enum {
+ WidthUndefined = 0xffff
+ };
+ ColumnStruct() {
+ span = 1;
+ width = WidthUndefined;
+ }
+ ushort span;
+ ushort width; // the calculated position of the column
+ };
+
+ TQMemArray<int> columnPos;
+ TQMemArray<ColumnStruct> columns;
+
+ void splitColumn( int pos, int firstSpan );
+ void appendColumn( int span );
+ int numEffCols() const { return columns.size(); }
+ int spanOfEffCol( int effCol ) const { return columns[effCol].span; }
+ int colToEffCol( int col ) const {
+ int c = 0;
+ int i = 0;
+ while ( c < col && i < (int)columns.size() ) {
+ c += columns[i].span;
+ i++;
+ }
+ return i;
+ }
+ int effColToCol( int effCol ) const {
+ int c = 0;
+ for ( int i = 0; i < effCol; i++ )
+ c += columns[i].span;
+ return c;
+ }
+
+ int bordersPaddingAndSpacing() const {
+ return borderLeft() + borderRight() +
+ (collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols()+1) * borderHSpacing()));
+ }
+
+ RenderTableCol *colElement( int col );
+
+ void setNeedSectionRecalc() { needSectionRecalc = true; }
+
+ virtual RenderObject* removeChildNode(RenderObject* child);
+
+ RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
+ RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
+
+ RenderTableCell* cellAbove(const RenderTableCell* cell) const;
+ RenderTableCell* cellBelow(const RenderTableCell* cell) const;
+ RenderTableCell* cellLeft(const RenderTableCell* cell) const;
+ RenderTableCell* cellRight(const RenderTableCell* cell) const;
+
+ CollapsedBorderValue* currentBorderStyle() { return m_currentBorder; }
+
+ RenderTableSection *firstBodySection() const { return firstBody; }
+ RenderFlow* caption() const { return tCaption; }
+
+protected:
+
+ void recalcSections();
+
+ friend class AutoTableLayout;
+ friend class FixedTableLayout;
+
+ RenderFlow *tCaption;
+ RenderTableSection *head;
+ RenderTableSection *foot;
+ RenderTableSection *firstBody;
+
+ TableLayout *tableLayout;
+
+ CollapsedBorderValue* m_currentBorder;
+
+ bool has_col_elems : 1;
+ uint needSectionRecalc : 1;
+ uint padding : 22;
+
+ ushort hspacing;
+ ushort vspacing;
+
+ friend class TableSectionIterator;
+};
+
+// -------------------------------------------------------------------------
+
+class RenderTableSection : public RenderBox
+{
+public:
+ RenderTableSection(DOM::NodeImpl* node);
+ ~RenderTableSection();
+ virtual void detach();
+
+ virtual void setStyle(RenderStyle *style);
+
+ virtual const char *renderName() const { return "RenderTableSection"; }
+
+ // overrides
+ virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
+ virtual bool isTableSection() const { return true; }
+
+ virtual short lineHeight(bool) const { return 0; }
+ virtual void position(InlineBox*, int, int, bool) {}
+
+ virtual short width() const;
+
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*& node, int & offset,
+ SelPointState & );
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+ void addCell( RenderTableCell *cell, RenderTableRow *row );
+
+ void setCellWidths();
+ void calcRowHeight();
+ int layoutRows( int height );
+
+ RenderTable *table() const { return static_cast<RenderTable *>(parent()); }
+
+ typedef TQMemArray<RenderTableCell *> Row;
+ struct RowStruct {
+ Row *row;
+ RenderTableRow* rowRenderer;
+ int baseLine;
+ Length height;
+ bool needFlex;
+ };
+
+ RenderTableCell *&cellAt( int row, int col ) {
+ return (*(grid[row].row))[col];
+ }
+ RenderTableCell *cellAt( int row, int col ) const {
+ return (*(grid[row].row))[col];
+ }
+
+ virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
+ virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
+ virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
+ virtual int highestPosition(bool includeOverflowInterior, bool includeSelf) const;
+
+ int borderLeft() const { return table()->collapseBorders() ? 0 : RenderBox::borderLeft(); }
+ int borderRight() const { return table()->collapseBorders() ? 0 : RenderBox::borderRight(); }
+ int borderTop() const { return table()->collapseBorders() ? 0 : RenderBox::borderTop(); }
+ int borderBottom() const { return table()->collapseBorders() ? 0 : RenderBox::borderBottom(); }
+
+ virtual void paint( PaintInfo& i, int tx, int ty);
+
+ int numRows() const { return grid.size(); }
+ int getBaseline(int row) {return grid[row].baseLine;}
+
+ void setNeedCellRecalc() {
+ needCellRecalc = true;
+ table()->setNeedSectionRecalc();
+ }
+
+ virtual RenderObject* removeChildNode(RenderObject* child);
+
+ virtual bool canClear(RenderObject *child, PageBreakLevel level);
+ void addSpaceAt(int pos, int dy);
+
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
+
+ // this gets a cell grid data structure. changing the number of
+ // columns is done by the table
+ TQMemArray<RowStruct> grid;
+ TQMemArray<int> rowPos;
+
+ signed short cRow;
+ ushort cCol;
+ bool needCellRecalc;
+
+ void recalcCells();
+protected:
+ void ensureRows( int numRows );
+ void clearGrid();
+ bool emptyRow(int rowNum);
+ bool flexCellChildren(RenderObject* p) const;
+
+
+ friend class TableSectionIterator;
+};
+
+// -------------------------------------------------------------------------
+
+class RenderTableRow : public RenderContainer
+{
+public:
+ RenderTableRow(DOM::NodeImpl* node);
+
+ virtual void detach();
+
+ virtual void setStyle( RenderStyle* );
+ virtual const char *renderName() const { return "RenderTableRow"; }
+ virtual bool isTableRow() const { return true; }
+ virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
+
+ virtual short offsetWidth() const;
+ virtual int offsetHeight() const;
+ virtual int offsetLeft() const;
+ virtual int offsetTop() const;
+
+ virtual short lineHeight( bool ) const { return 0; }
+ virtual void position(InlineBox*, int, int, bool) {}
+
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
+
+ virtual void layout();
+
+ virtual RenderObject* removeChildNode(RenderObject* child);
+
+ // The only time rows get a layer is when they have transparency.
+ virtual bool requiresLayer() const { return /* style()->opacity() < 1.0f; */ false ; }
+ virtual void paint(PaintInfo& i, int tx, int ty);
+
+ void paintRow( PaintInfo& i, int tx, int ty, int w, int h);
+
+ RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()); }
+ RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()); }
+};
+
+// -------------------------------------------------------------------------
+
+class RenderTableCell : public RenderBlock
+{
+public:
+ RenderTableCell(DOM::NodeImpl* node);
+
+ virtual void layout();
+ virtual void detach();
+
+ virtual const char *renderName() const { return "RenderTableCell"; }
+ virtual bool isTableCell() const { return true; }
+
+ // ### FIX these two...
+ long cellIndex() const { return 0; }
+ void setCellIndex( long ) { }
+
+ unsigned short colSpan() const { return cSpan; }
+ void setColSpan( unsigned short c ) { cSpan = c; }
+
+ unsigned short rowSpan() const { return rSpan; }
+ void setRowSpan( unsigned short r ) { rSpan = r; }
+
+ int col() const { return _col; }
+ void setCol(int col) { _col = col; }
+ int row() const { return _row; }
+ void setRow(int r) { _row = r; }
+
+ Length styleOrColWidth();
+
+ // overrides
+ virtual void calcMinMaxWidth();
+ virtual void calcWidth();
+ virtual void setWidth( int width );
+ virtual void setStyle( RenderStyle *style );
+ virtual bool requiresLayer() const;
+
+ int borderLeft() const;
+ int borderRight() const;
+ int borderTop() const;
+ int borderBottom() const;
+
+ CollapsedBorderValue collapsedLeftBorder() const;
+ CollapsedBorderValue collapsedRightBorder() const;
+ CollapsedBorderValue collapsedTopBorder() const;
+ CollapsedBorderValue collapsedBottomBorder() const;
+ virtual void collectBorders(TQValueList<CollapsedBorderValue>& borderStyles);
+
+ virtual void updateFromElement();
+
+ void setCellTopExtra(int p) { _topExtra = p; }
+ void setCellBottomExtra(int p) { _bottomExtra = p; }
+ int cellTopExtra() const { return _topExtra; }
+ int cellBottomExtra() const { return _bottomExtra; }
+
+ int pageTopAfter(int x) const;
+
+ virtual void paint( PaintInfo& i, int tx, int ty);
+
+ void paintCollapsedBorder(TQPainter* p, int x, int y, int w, int h);
+ void paintBackgroundsBehindCell(PaintInfo& i, int _tx, int _ty, RenderObject* backgroundObject);
+
+ virtual void close();
+
+ // lie position to outside observers
+ virtual int yPos() const { return m_y + _topExtra; }
+
+ virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
+ virtual bool absolutePosition(int &xPos, int &yPos, bool f = false) const;
+
+ virtual short baselinePosition( bool = false ) const;
+
+ virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside);
+
+ RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()->parent()); }
+ RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()->parent()); }
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+ bool widthChanged() {
+ bool retval = m_widthChanged;
+ m_widthChanged = false;
+ return retval;
+ }
+
+ int cellPercentageHeight() const
+ { return m_percentageHeight; }
+ void setCellPercentageHeight(int h)
+ { m_percentageHeight = h; }
+ bool hasFlexedAnonymous() const
+ { return m_hasFlexedAnonymous; }
+ void setHasFlexedAnonymous(bool b=true)
+ { m_hasFlexedAnonymous = b; }
+
+protected:
+ virtual void paintBoxDecorations(PaintInfo& p, int _tx, int _ty);
+ virtual int borderTopExtra() const { return _topExtra; }
+ virtual int borderBottomExtra() const { return _bottomExtra; }
+
+ short _row;
+ short _col;
+ ushort rSpan;
+ ushort cSpan;
+ int _topExtra;
+ signed int _bottomExtra : 30;
+ bool m_widthChanged : 1;
+ bool m_hasFlexedAnonymous : 1;
+ int m_percentageHeight;
+};
+
+
+// -------------------------------------------------------------------------
+
+class RenderTableCol : public RenderContainer
+{
+public:
+ RenderTableCol(DOM::NodeImpl* node);
+
+ virtual const char *renderName() const { return "RenderTableCol"; }
+
+ virtual bool isTableCol() const { return true; }
+
+ virtual short lineHeight( bool ) const { return 0; }
+ virtual void position(InlineBox*, int, int, bool) {}
+ virtual void layout() {}
+ virtual bool requiresLayer() const { return false; }
+
+ virtual void updateFromElement();
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString& ind) const;
+#endif
+
+ int span() const { return m_span; }
+ void setSpan( int s ) { m_span = s; }
+
+private:
+ int m_span;
+};
+
+// -------------------------------------------------------------------------
+
+/** This class provides an iterator to iterate through the sections of a
+ * render table in their visual order.
+ *
+ * In HTML, sections are specified in the order of THEAD, TFOOT, and TBODY.
+ * Visually, TBODY sections appear between THEAD and TFOOT, which this iterator
+ * takes into regard.
+ * @author Leo Savernik
+ * @internal
+ * @since 3.2
+ */
+class TableSectionIterator {
+public:
+
+ /**
+ * Initializes a new iterator
+ * @param table table whose sections to iterate
+ * @param fromEnd @p true, begin with last section, @p false, begin with
+ * first section.
+ */
+ TableSectionIterator(RenderTable *table, bool fromEnd = false);
+
+ /**
+ * Initializes a new iterator
+ * @param start table section to start with.
+ */
+ TableSectionIterator(RenderTableSection *start) : sec(start) {}
+
+ /**
+ * Uninitialized iterator.
+ */
+ TableSectionIterator() {}
+
+ /** Returns the current section, or @p 0 if the end has been reached.
+ */
+ RenderTableSection *operator *() const { return sec; }
+
+ /** Moves to the next section in visual order. */
+ TableSectionIterator &operator ++();
+
+ /** Moves to the previous section in visual order. */
+ TableSectionIterator &operator --();
+
+private:
+ RenderTableSection *sec;
+};
+
+}
+#endif
+
diff --git a/tdehtml/rendering/render_text.cpp b/tdehtml/rendering/render_text.cpp
new file mode 100644
index 000000000..9090e1631
--- /dev/null
+++ b/tdehtml/rendering/render_text.cpp
@@ -0,0 +1,1546 @@
+/**
+ * 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) 2003 Apple Computer, Inc.
+ * (C) 2004-2005 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_LAYOUT
+//#define BIDI_DEBUG
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "rendering/render_text.h"
+#include "rendering/render_canvas.h"
+#include "rendering/break_lines.h"
+#include "rendering/render_arena.h"
+#include "xml/dom_nodeimpl.h"
+
+#include "misc/loader.h"
+#include "misc/helper.h"
+
+#include <tqbitmap.h>
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+
+#ifdef HAVE_ALLOCA_H
+// explicitly included for systems that don't provide it in stdlib.h
+#include <alloca.h>
+#else
+#include <stdlib.h>
+#endif
+
+using namespace tdehtml;
+using namespace DOM;
+
+#ifndef NDEBUG
+static bool inInlineTextBoxDetach;
+#endif
+
+void InlineTextBox::detach(RenderArena* renderArena)
+{
+ if (m_parent)
+ m_parent->removeFromLine(this);
+
+#ifndef NDEBUG
+ inInlineTextBoxDetach = true;
+#endif
+ delete this;
+#ifndef NDEBUG
+ inInlineTextBoxDetach = false;
+#endif
+
+ // Recover the size left there for us by operator delete and free the memory.
+ renderArena->free(*(size_t *)this, this);
+}
+
+void* InlineTextBox::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+ return renderArena->allocate(sz);
+}
+
+void InlineTextBox::operator delete(void* ptr, size_t sz)
+{
+ assert(inInlineTextBoxDetach);
+
+ // Stash size where detach can find it.
+ *(size_t *)ptr = sz;
+}
+
+void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
+{
+ int startPos, endPos;
+ if (object()->selectionState() == RenderObject::SelectionInside) {
+ startPos = 0;
+ endPos = renderText()->string()->l;
+ } else {
+ renderText()->selectionStartEnd(startPos, endPos);
+ if (object()->selectionState() == RenderObject::SelectionStart)
+ endPos = renderText()->string()->l;
+ else if (object()->selectionState() == RenderObject::SelectionEnd)
+ startPos = 0;
+ }
+
+ sPos = kMax(startPos - m_start, 0);
+ ePos = kMin(endPos - m_start, (int)m_len);
+}
+
+RenderObject::SelectionState InlineTextBox::selectionState()
+{
+ RenderObject::SelectionState state = object()->selectionState();
+ if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd ||
+ state == RenderObject::SelectionBoth) {
+ int startPos, endPos;
+ renderText()->selectionStartEnd(startPos, endPos);
+
+ bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos < m_start + m_len);
+ bool end = (state != RenderObject::SelectionStart && endPos > m_start && endPos <= m_start + m_len);
+ if (start && end)
+ state = RenderObject::SelectionBoth;
+ else if (start)
+ state = RenderObject::SelectionStart;
+ else if (end)
+ state = RenderObject::SelectionEnd;
+ else if ((state == RenderObject::SelectionEnd || startPos < m_start) &&
+ (state == RenderObject::SelectionStart || endPos > m_start + m_len))
+ state = RenderObject::SelectionInside;
+ }
+ return state;
+}
+
+void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
+{
+ if (object()->isBR() || object()->style()->visibility() != VISIBLE ||
+ m_truncation == cFullTruncation || i.phase == PaintActionOutline)
+ return;
+
+ if (i.phase == PaintActionSelection && object()->selectionState() == RenderObject::SelectionNone)
+ // When only painting the selection, don't bother to paint if there is none.
+ return;
+
+ int xPos = tx + m_x;
+ int w = width();
+ if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
+ return;
+
+ // Set our font.
+ RenderStyle* styleToUse = object()->style(m_firstLine);
+ int d = styleToUse->textDecorationsInEffect();
+ if (styleToUse->font() != i.p->font())
+ i.p->setFont(styleToUse->font());
+ const Font *font = &styleToUse->htmlFont();
+ bool haveSelection = selectionState() != RenderObject::SelectionNone;
+
+ // Now calculate startPos and endPos, for painting selection.
+ // We paint selection while endPos > 0
+ int ePos = 0, sPos = 0;
+ if (haveSelection && !object()->canvas()->staticMode()) {
+ selectionStartEnd(sPos, ePos);
+ }
+ if (styleToUse->color() != i.p->pen().color())
+ i.p->setPen(styleToUse->color());
+
+ if (m_len > 0 && i.phase != PaintActionSelection) {
+ int endPoint = m_len;
+ if (m_truncation != cNoTruncation)
+ endPoint = m_truncation - m_start;
+ if (styleToUse->textShadow())
+ paintShadow(i.p, font, tx, ty, styleToUse->textShadow());
+ if (!haveSelection || sPos != 0 || ePos != m_len) {
+ font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, renderText()->string()->s, renderText()->string()->l, m_start, endPoint,
+ m_toAdd, m_reversed ? TQPainter::RTL : TQPainter::LTR);
+ }
+ }
+
+ if (d != TDNONE && i.phase != PaintActionSelection && styleToUse->htmlHacks()) {
+ i.p->setPen(styleToUse->color());
+ paintDecoration(i.p, font, tx, ty, d);
+ }
+
+ if (haveSelection && i.phase == PaintActionSelection) {
+ //kdDebug(6040) << this << " paintSelection with startPos=" << sPos << " endPos=" << ePos << endl;
+ if ( sPos < ePos )
+ paintSelection(font, renderText(), i.p, styleToUse, tx, ty, sPos, ePos, d);
+ }
+}
+
+/** returns the proper ::selection pseudo style for the given element
+ * @return the style or 0 if no ::selection pseudo applies.
+ */
+inline const RenderStyle *retrieveSelectionPseudoStyle(const RenderObject *obj)
+{
+ // http://www.w3.org/Style/CSS/Test/CSS3/Selectors/20021129/html/tests/css3-modsel-162.html
+ // is of the opinion that ::selection of parent elements is also to be applied
+ // to children, so let's do it.
+ while (obj) {
+ const RenderStyle *style = obj->style()->getPseudoStyle(RenderStyle::SELECTION);
+ if (style) return style;
+
+ obj = obj->parent();
+ }/*wend*/
+ return 0;
+}
+
+void InlineTextBox::paintSelection(const Font *f, RenderText *text, TQPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos, int deco)
+{
+ if(startPos > m_len) return;
+ if(startPos < 0) startPos = 0;
+
+ TQColor hc;
+ TQColor hbg;
+ const RenderStyle* pseudoStyle = retrieveSelectionPseudoStyle(text);
+ if (pseudoStyle) {
+ // ### support outline (mandated by CSS3)
+ // ### support background-image? (optional by CSS3)
+ if (pseudoStyle->backgroundColor().isValid())
+ hbg = pseudoStyle->backgroundColor();
+ hc = pseudoStyle->color();
+ } else {
+ const TQColorGroup &grp = style->palette().active();
+ hc = grp.highlightedText();
+ hbg = grp.highlight();
+ // ### should be at most retrieved once per render text
+ TQColor bg = tdehtml::retrieveBackgroundColor(text);
+ // It may happen that the contrast is -- well -- virtually non existent.
+ // In this case, simply swap the colors, thus in compliance with
+ // NN4 (win32 only), IE, and Mozilla.
+ if (!tdehtml::hasSufficientContrast(hbg, bg))
+ tqSwap(hc, hbg);
+ }
+
+ p->setPen(hc);
+
+ //kdDebug( 6040 ) << "textRun::painting(" << TQConstString(text->str->s + m_start, m_len).string().left(30) << ") at(" << m_x+tx << "/" << m_y+ty << ")" << endl;
+
+ const bool needClipping = startPos != 0 || endPos != m_len;
+
+ if (needClipping) {
+ p->save();
+
+ int visualSelectionStart = f->width(text->str->s, text->str->l, m_start, startPos, m_start, m_start + m_len, m_toAdd);
+ int visualSelectionEnd = f->width(text->str->s, text->str->l, m_start, endPos, m_start, m_start + m_len, m_toAdd);
+ int visualSelectionWidth = visualSelectionEnd - visualSelectionStart;
+ if (m_reversed) {
+ visualSelectionStart = f->width(text->str->s, text->str->l, m_start, m_len) - visualSelectionEnd;
+ }
+
+ TQRect selectionRect(m_x + tx + visualSelectionStart, m_y + ty, visualSelectionWidth, height());
+ TQRegion r(selectionRect);
+ if (p->hasClipping())
+ r &= p->clipRegion(TQPainter::CoordPainter);
+ p->setClipRegion(r, TQPainter::CoordPainter);
+ }
+
+ f->drawText(p, m_x + tx, m_y + ty + m_baseline, text->str->s, text->str->l,
+ m_start, m_len, m_toAdd,
+ m_reversed ? TQPainter::RTL : TQPainter::LTR,
+ needClipping ? 0 : startPos, needClipping ? m_len : endPos,
+ hbg, m_y + ty, height(), deco);
+
+ if (needClipping) p->restore();
+}
+
+void InlineTextBox::paintDecoration( TQPainter *pt, const Font *f, int _tx, int _ty, int deco)
+{
+ _tx += m_x;
+ _ty += m_y;
+
+ if (m_truncation == cFullTruncation)
+ return;
+
+ int width = m_width - 1;
+ if (m_truncation != cNoTruncation) {
+ width = static_cast<RenderText*>(m_object)->width(m_start, m_truncation - m_start, m_firstLine);
+ }
+
+ RenderObject *p = object();
+
+ TQColor underline, overline, linethrough;
+ p->getTextDecorationColors(deco, underline, overline, linethrough, p->style()->htmlHacks());
+
+ if(deco & UNDERLINE){
+ pt->setPen(underline);
+ f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::UNDERLINE);
+ }
+ if (deco & OVERLINE) {
+ pt->setPen(overline);
+ f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::OVERLINE);
+ }
+ if(deco & LINE_THROUGH) {
+ pt->setPen(linethrough);
+ f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::LINE_THROUGH);
+ }
+ // NO! Do NOT add BLINK! It is the most annouing feature of Netscape, and IE has a reason not to
+ // support it. Lars
+}
+
+void InlineTextBox::paintShadow(TQPainter *pt, const Font *f, int _tx, int _ty, const ShadowData *shadow )
+{
+ int x = m_x + _tx + shadow->x;
+ int y = m_y + _ty + shadow->y;
+ const RenderText* text = renderText();
+
+ if (shadow->blur <= 0) {
+ TQColor c = pt->pen().color();
+ pt->setPen(shadow->color);
+ f->drawText(pt, x, y+m_baseline, text->str->s, text->str->l,
+ m_start, m_len, m_toAdd,
+ m_reversed ? TQPainter::RTL : TQPainter::LTR);
+ pt->setPen(c);
+
+ }
+ else {
+ const int thickness = shadow->blur;
+ const int w = m_width+2*thickness;
+ const int h = m_height+2*thickness;
+ const TQRgb color = shadow->color.rgb();
+ const int gray = tqGray(color);
+ const bool inverse = (gray < 100);
+ const TQRgb bgColor = (inverse) ? tqRgb(255,255,255) : tqRgb(0,0,0);
+ TQPixmap pixmap(w, h);
+ pixmap.fill(bgColor);
+ TQPainter p;
+
+ p.begin(&pixmap);
+ p.setPen(shadow->color);
+ p.setFont(pt->font());
+ f->drawText(&p, thickness, thickness+m_baseline, text->str->s, text->str->l,
+ m_start, m_len, m_toAdd,
+ m_reversed ? TQPainter::RTL : TQPainter::LTR);
+
+ p.end();
+ TQImage img = TQT_TQIMAGE_OBJECT(pixmap.convertToImage()).convertDepth(32);
+
+ int md = thickness*thickness; // max-dist^2
+
+ // blur map (division cache)
+ float *bmap = (float*)alloca(sizeof(float)*(md+1));
+ for(int n=0; n<=md; n++) {
+ float f;
+ f = n/(float)(md+1);
+ f = 1.0 - f*f;
+ bmap[n] = f;
+ }
+
+ float factor = 0.0; // maximal potential opacity-sum
+ for(int n=-thickness; n<=thickness; n++)
+ for(int m=-thickness; m<=thickness; m++) {
+ int d = n*n+m*m;
+ if (d<=md)
+ factor += bmap[d];
+ }
+
+ // arbitratry factor adjustment to make shadows solid.
+ factor = factor/1.333;
+
+ // alpha map
+ float* amap = (float*)alloca(sizeof(float)*(h*w));
+ memset(amap, 0, h*w*(sizeof(float)));
+ for(int j=thickness; j<h-thickness; j++) {
+ for(int i=thickness; i<w-thickness; i++) {
+ TQRgb col= img.pixel(i,j);
+ if (col == bgColor) continue;
+ float g = tqGray(col);
+ if (inverse)
+ g = (255-g)/(255-gray);
+ else
+ g = g/gray;
+ for(int n=-thickness; n<=thickness; n++) {
+ for(int m=-thickness; m<=thickness; m++) {
+ int d = n*n+m*m;
+ if (d>md) continue;
+ float f = bmap[d];
+ amap[(i+m)+(j+n)*w] += (g*f);
+ }
+ }
+ }
+ }
+
+ TQImage res(w,h,32);
+ res.setAlphaBuffer(true);
+ int r = tqRed(color);
+ int g = tqGreen(color);
+ int b = tqBlue(color);
+
+ // divide by factor
+ factor = 1.0/factor;
+
+ for(int j=0; j<h; j++) {
+ for(int i=0; i<w; i++) {
+ int a = (int)(amap[i+j*w] * factor * 255.0);
+ if (a > 255) a = 255;
+ res.setPixel(i,j, tqRgba(r,g,b,a));
+ }
+ }
+
+ pt->drawImage(x-thickness, y-thickness, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither);
+ }
+ // Paint next shadow effect
+ if (shadow->next) paintShadow(pt, f, _tx, _ty, shadow->next);
+}
+
+/**
+ * Distributes pixels to justify text.
+ * @param numSpaces spaces left, will be decremented by one
+ * @param toAdd number of pixels left to be distributed, will have the
+ * amount of pixels distributed during this call subtracted.
+ * @return number of pixels to distribute
+ */
+static inline int justifyWidth(int &numSpaces, int &toAdd) {
+ int a = 0;
+ if ( numSpaces ) {
+ a = toAdd/numSpaces;
+ toAdd -= a;
+ numSpaces--;
+ }/*end if*/
+ return a;
+}
+
+FindSelectionResult InlineTextBox::checkSelectionPoint(int _x, int _y, int _tx, int _ty, const Font *f, RenderText *text, int & offset, short lineHeight)
+{
+// kdDebug(6040) << "InlineTextBox::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y
+// << " _tx+m_x=" << _tx+m_x << " _ty+m_y=" << _ty+m_y << endl;
+ offset = 0;
+
+ if ( _y < _ty + m_y )
+ return SelectionPointBefore; // above -> before
+
+ if ( _y > _ty + m_y + lineHeight ) {
+ // below -> after
+ // Set the offset to the max
+ offset = m_len;
+ return SelectionPointAfter;
+ }
+ if ( _x > _tx + m_x + m_width ) {
+ // to the right
+ return SelectionPointAfterInLine;
+ }
+
+ // The Y matches, check if we're on the left
+ if ( _x < _tx + m_x ) {
+ return SelectionPointBeforeInLine;
+ }
+
+ // consider spacing for justified text
+ int toAdd = m_toAdd;
+ bool justified = text->style()->textAlign() == JUSTIFY && toAdd > 0;
+ int numSpaces = 0;
+ if (justified) {
+
+ for( int i = 0; i < m_len; i++ )
+ if ( text->str->s[m_start+i].category() == TQChar::Separator_Space )
+ numSpaces++;
+
+ }/*end if*/
+
+ int delta = _x - (_tx + m_x);
+ //kdDebug(6040) << "InlineTextBox::checkSelectionPoint delta=" << delta << endl;
+ int pos = 0;
+ if ( m_reversed ) {
+ delta -= m_width;
+ while(pos < m_len) {
+ int w = f->width( text->str->s, text->str->l, m_start + pos);
+ if (justified && text->str->s[m_start + pos].category() == TQChar::Separator_Space)
+ w += justifyWidth(numSpaces, toAdd);
+ int w2 = w/2;
+ w -= w2;
+ delta += w2;
+ if(delta >= 0) break;
+ pos++;
+ delta += w;
+ }
+ } else {
+ while(pos < m_len) {
+ int w = f->width( text->str->s, text->str->l, m_start + pos);
+ if (justified && text->str->s[m_start + pos].category() == TQChar::Separator_Space)
+ w += justifyWidth(numSpaces, toAdd);
+ int w2 = w/2;
+ w -= w2;
+ delta -= w2;
+ if(delta <= 0) break;
+ pos++;
+ delta -= w;
+ }
+ }
+// kdDebug( 6040 ) << " Text --> inside at position " << pos << endl;
+ offset = pos;
+ return SelectionPointInside;
+}
+
+int InlineTextBox::offsetForPoint(int _x, int &ax) const
+{
+ // Do binary search for finding out offset, saves some time for long
+ // runs.
+ int start = 0;
+ int end = m_len;
+ ax = m_x;
+ int offset = (start + end) / 2;
+ while (end - start > 0) {
+ // always snap to the right column. This makes up for "jumpy" vertical
+ // navigation.
+ if (end - start == 1) start = end;
+
+ offset = (start + end) / 2;
+ ax = m_x + widthFromStart(offset);
+ if (ax > _x) end = offset;
+ else if (ax < _x) start = offset;
+ else break;
+ }
+ return m_start + offset;
+}
+
+int InlineTextBox::widthFromStart(int pos) const
+{
+ // gasp! sometimes pos is i < 0 which crashes Font::width
+ pos = kMax(pos, 0);
+
+ const RenderText *t = renderText();
+ Q_ASSERT(t->isText());
+ const Font *f = t->htmlFont(m_firstLine);
+ const TQFontMetrics &fm = t->fontMetrics(m_firstLine);
+
+ int numSpaces = 0;
+ // consider spacing for justified text
+ bool justified = t->style()->textAlign() == JUSTIFY;
+ //kdDebug(6000) << "InlineTextBox::width(int)" << endl;
+ if (justified && m_toAdd > 0) do {
+ //kdDebug(6000) << "justify" << endl;
+
+// TQConstString cstr = TQConstString(t->str->s + m_start, m_len);
+ for( int i = 0; i < m_len; i++ )
+ if ( t->str->s[m_start+i].category() == TQChar::Separator_Space )
+ numSpaces++;
+ if (numSpaces == 0) break;
+
+ int toAdd = m_toAdd;
+ int w = 0; // accumulated width
+ int start = 0; // start of non-space sequence
+ int current = 0; // current position
+ while (current < pos) {
+ // add spacing
+ while (current < pos && t->str->s[m_start + current].category() == TQChar::Separator_Space) {
+ w += f->getWordSpacing();
+ w += f->getLetterSpacing();
+ w += justifyWidth(numSpaces, toAdd);
+ w += fm.width(' '); // ### valid assumption? (LS)
+ current++; start++;
+ }/*wend*/
+ if (current >= pos) break;
+
+ // seek next space
+ while (current < pos && t->str->s[m_start + current].category() != TQChar::Separator_Space)
+ current++;
+
+ // check run without spaces
+ if ( current > start ) {
+ w += f->width(t->str->s + m_start, m_len, start, current - start);
+ start = current;
+ }
+ }
+
+ return w;
+
+ } while(false);/*end if*/
+
+ //kdDebug(6000) << "default" << endl;
+ // else use existing width function
+ return f->width(t->str->s + m_start, m_len, 0, pos);
+
+}
+
+long InlineTextBox::minOffset() const
+{
+ return m_start;
+}
+
+long InlineTextBox::maxOffset() const
+{
+ return m_start + m_len;
+}
+
+int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+{
+ if (foundBox) {
+ m_truncation = cFullTruncation;
+ return -1;
+ }
+
+ int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth;
+
+ // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated.
+ if (ltr) {
+ if (ellipsisX <= m_x) {
+ // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.
+ m_truncation = cFullTruncation;
+ foundBox = true;
+ return -1;
+ }
+
+ if (ellipsisX < m_x + m_width) {
+ if (m_reversed)
+ return -1; // FIXME: Support LTR truncation when the last run is RTL someday.
+
+ foundBox = true;
+
+ int ax;
+ int offset = offsetForPoint(ellipsisX, ax) - 1;
+ if (offset <= m_start) {
+ // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
+ // and the ellipsis edge.
+ m_truncation = cFullTruncation;
+ return kMin(ellipsisX, (int)m_x);
+ }
+
+ // Set the truncation index on the text run. The ellipsis needs to be placed just after the last visible character.
+ m_truncation = offset;
+ return widthFromStart(offset - m_start);
+ }
+ }
+ else {
+ // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR)
+ }
+ return -1;
+}
+
+// -----------------------------------------------------------------------------
+
+InlineTextBoxArray::InlineTextBoxArray()
+{
+ setAutoDelete(false);
+}
+
+int InlineTextBoxArray::compareItems( Item d1, Item d2 )
+{
+ assert(d1);
+ assert(d2);
+
+ return static_cast<InlineTextBox*>(d1)->m_y - static_cast<InlineTextBox*>(d2)->m_y;
+}
+
+// remove this once TQVector::bsearch is fixed
+int InlineTextBoxArray::findFirstMatching(Item d) const
+{
+ int len = count();
+
+ if ( !len )
+ return -1;
+ if ( !d )
+ return -1;
+ int n1 = 0;
+ int n2 = len - 1;
+ int mid = 0;
+ bool found = false;
+ while ( n1 <= n2 ) {
+ int res;
+ mid = (n1 + n2)/2;
+ if ( (*this)[mid] == 0 ) // null item greater
+ res = -1;
+ else
+ res = ((TQGVector*)this)->compareItems( d, (*this)[mid] );
+ if ( res < 0 )
+ n2 = mid - 1;
+ else if ( res > 0 )
+ n1 = mid + 1;
+ else { // found it
+ found = true;
+ break;
+ }
+ }
+ /* if ( !found )
+ return -1; */
+ // search to first one equal or bigger
+ while ( found && (mid > 0) && !((TQGVector*)this)->compareItems(d, (*this)[mid-1]) )
+ mid--;
+ return mid;
+}
+
+// -------------------------------------------------------------------------------------
+
+RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
+ : RenderObject(node)
+{
+ // init RenderObject attributes
+ setRenderText(); // our object inherits from RenderText
+
+ m_minWidth = -1;
+ m_maxWidth = -1;
+ str = _str;
+ if(str) str->ref();
+ KHTMLAssert(!str || !str->l || str->s);
+
+ m_selectionState = SelectionNone;
+ m_hasReturn = true;
+
+#ifdef DEBUG_LAYOUT
+ TQConstString cstr(str->s, str->l);
+ kdDebug( 6040 ) << "RenderText ctr( "<< cstr.string().length() << " ) '" << cstr.string() << "'" << endl;
+#endif
+}
+
+void RenderText::setStyle(RenderStyle *_style)
+{
+ if ( style() != _style ) {
+ bool changedText = ((!style() && ( _style->textTransform() != TTNONE ||
+ !_style->preserveLF() || !_style->preserveWS() )) ||
+ (style() && (style()->textTransform() != _style->textTransform() ||
+ style()->whiteSpace() != _style->whiteSpace())));
+
+ RenderObject::setStyle( _style );
+ m_lineHeight = RenderObject::lineHeight(false);
+
+ if (!isBR() && changedText) {
+ DOM::DOMStringImpl* textToTransform = originalString();
+ if (textToTransform)
+ setText(textToTransform, true);
+ }
+ }
+}
+
+RenderText::~RenderText()
+{
+ KHTMLAssert(m_lines.count() == 0);
+ if(str) str->deref();
+}
+
+void RenderText::deleteInlineBoxes(RenderArena* arena)
+{
+ // this is a slight variant of TQArray::clear().
+ // We don't delete the array itself here because its
+ // likely to be used in the same size later again, saves
+ // us resize() calls
+ unsigned int len = m_lines.size();
+ if (len) {
+ if (!arena)
+ arena = renderArena();
+ for(unsigned int i=0; i < len; i++) {
+ InlineTextBox* s = m_lines.at(i);
+ if (s)
+ s->detach(arena);
+ m_lines.remove(i);
+ }
+ }
+
+ KHTMLAssert(m_lines.count() == 0);
+}
+
+bool RenderText::isTextFragment() const
+{
+ return false;
+}
+
+DOM::DOMStringImpl* RenderText::originalString() const
+{
+ return element() ? element()->string() : 0;
+}
+
+InlineTextBox * RenderText::findInlineTextBox( int offset, int &pos, bool checkFirstLetter )
+{
+ // The text boxes point to parts of the rendertext's str string
+ // (they don't include '\n')
+ // Find the text box that includes the character at @p offset
+ // and return pos, which is the position of the char in the run.
+
+ // FIXME: make this use binary search? Dirk says it won't work :-( (LS)
+ (void)checkFirstLetter;
+#if 0
+ if (checkFirstLetter && forcedMinOffset()) {
+// kdDebug(6040) << "checkFirstLetter: forcedMinOffset: " << forcedMinOffset() << endl;
+ RenderFlow *firstLetter = static_cast<RenderFlow *>(previousSibling());
+ if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) {
+ RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild());
+ //kdDebug(6040) << "lettertext: " << letterText << " minOfs: " << letterText->minOffset() << " maxOfs: " << letterText->maxOffset() << endl;
+ if (offset >= letterText->minOffset() && offset <= letterText->maxOffset()) {
+ InlineTextBox *result = letterText->findInlineTextBox(offset, pos, false);
+ //kdDebug(6040) << "result: " << result << endl;
+ if (result) return result;
+ }
+ }
+ }
+#endif
+
+ if ( m_lines.isEmpty() )
+ return 0L;
+
+ // The text boxes don't resemble a contiguous coverage of the text, there
+ // may be holes. Therefore, we snap to the nearest previous text box if
+ // the given offset happens to point to such a hole.
+
+ InlineTextBox* s = m_lines[0];
+ uint count = m_lines.count();
+ uint si = 0;
+ uint nearest_idx = 0; // index of nearest text box
+ int nearest = INT_MAX; // nearest distance
+//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
+ while(!(offset >= s->m_start && offset <= s->m_start + s->m_len)
+ && ++si < count)
+ {
+ int dist = offset - (s->m_start + s->m_len);
+//kdDebug(6040) << "dist " << dist << " nearest " << nearest << endl;
+ if (dist >= 0 && dist <= nearest) {
+ nearest = dist;
+ nearest_idx = si - 1;
+ }/*end if*/
+ s = m_lines[si];
+//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
+ }
+//kdDebug(6040) << "nearest_idx " << nearest_idx << " count " << count << endl;
+ if (si >= count) s = m_lines[nearest_idx];
+ // we are now in the correct text box
+ pos = kMin(offset - s->m_start, int( s->m_len ));
+ //kdDebug(6040) << "offset=" << offset << " s->m_start=" << s->m_start << endl;
+ return s;
+}
+
+bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction /*hitTestAction*/, bool /*inBox*/)
+{
+ assert(parent());
+
+ bool inside = false;
+ if (style()->visibility() != HIDDEN) {
+ InlineTextBox *s = m_lines.count() ? m_lines[0] : 0;
+ int si = 0;
+ while(s) {
+ if((_y >=_ty + s->m_y) && (_y < _ty + s->m_y + s->m_height) &&
+ (_x >= _tx + s->m_x) && (_x <_tx + s->m_x + s->m_width) ) {
+ inside = true;
+ break;
+ }
+
+ s = si < (int) m_lines.count()-1 ? m_lines[++si] : 0;
+ }
+ }
+
+ // #### ported over from Safari. Can this happen at all? (lars)
+
+ if (inside && element()) {
+ if (info.innerNode() && info.innerNode()->renderer() &&
+ !info.innerNode()->renderer()->isInline()) {
+ // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node.
+ info.setInnerNode(element());
+
+ // Clear everything else.
+ info.setInnerNonSharedNode(0);
+ info.setURLElement(0);
+ }
+
+ if (!info.innerNode())
+ info.setInnerNode(element());
+
+ if(!info.innerNonSharedNode())
+ info.setInnerNonSharedNode(element());
+ }
+
+ return inside;
+}
+
+FindSelectionResult RenderText::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &)
+{
+// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y
+// << " _tx=" << _tx << " _ty=" << _ty << endl;
+//kdDebug(6040) << renderName() << "::checkSelectionPoint x=" << xPos() << " y=" << yPos() << " w=" << width() << " h=" << height() << " m_lines.count=" << m_lines.count() << endl;
+
+ NodeImpl *lastNode = 0;
+ int lastOffset = 0;
+ FindSelectionResult lastResult = SelectionPointAfter;
+
+ for(unsigned int si = 0; si < m_lines.count(); si++)
+ {
+ InlineTextBox* s = m_lines[si];
+ FindSelectionResult result;
+ const Font *f = htmlFont( si==0 );
+ result = s->checkSelectionPoint(_x, _y, _tx, _ty, f, this, offset, m_lineHeight);
+
+// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " line " << si << " result=" << result << " offset=" << offset << endl;
+ if ( result == SelectionPointInside ) // x,y is inside the textrun
+ {
+ offset += s->m_start; // add the offset from the previous lines
+// kdDebug(6040) << "RenderText::checkSelectionPoint inside -> " << offset << endl;
+ node = element();
+ return SelectionPointInside;
+ } else if ( result == SelectionPointBefore ) {
+ if (!lastNode) {
+ // x,y is before the textrun -> stop here
+ offset = 0;
+// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << "before us -> returning Before" << endl;
+ node = element();
+ return SelectionPointBefore;
+ }
+ } else if ( result == SelectionPointBeforeInLine ) {
+ offset = s->m_start;
+ node = element();
+ return SelectionPointInside;
+ } else if ( result == SelectionPointAfterInLine ) {
+ lastOffset = s->m_start + s->m_len;
+ lastNode = element();
+ lastResult = result;
+ // no return here
+ }
+
+ }
+
+ if (lastNode) {
+ offset = lastOffset;
+ node = lastNode;
+// kdDebug(6040) << "RenderText::checkSelectionPoint: lastNode " << lastNode << " lastOffset " << lastOffset << endl;
+ return lastResult;
+ }
+
+ // set offset to max
+ offset = str->l;
+ //tqDebug("setting node to %p", element());
+ node = element();
+// kdDebug(6040) << "RenderText::checkSelectionPoint: node " << node << " offset " << offset << endl;
+ return SelectionPointAfter;
+}
+
+void RenderText::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
+{
+ if (!m_lines.count()) {
+ _x = _y = height = -1;
+ width = 1;
+ return;
+ }
+
+ int pos;
+ InlineTextBox * s = findInlineTextBox( offset, pos, true );
+ RenderText *t = s->renderText();
+// kdDebug(6040) << "offset="<<offset << " pos="<<pos << endl;
+
+ const TQFontMetrics &fm = t->metrics( s->m_firstLine );
+ height = fm.height(); // s->m_height;
+
+ _x = s->m_x + s->widthFromStart(pos);
+ _y = s->m_y + s->baseline() - fm.ascent();
+ width = 1;
+ if (flags & CFOverride) {
+ width = offset < maxOffset() ? fm.width(str->s[offset]) : 1;
+ }/*end if*/
+#if 0
+ kdDebug(6040) << "_x="<<_x << " s->m_x="<<s->m_x
+ << " s->m_start"<<s->m_start
+ << " s->m_len" << s->m_len << " _y=" << _y << endl;
+#endif
+
+ int absx, absy;
+
+ if (absolutePosition(absx,absy))
+ {
+ //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
+ _x += absx;
+ _y += absy;
+ } else {
+ // we don't know our absolute position, and there is no point returning
+ // just a relative one
+ _x = _y = -1;
+ }
+}
+
+long RenderText::minOffset() const
+{
+ if (!m_lines.count()) return 0;
+ // FIXME: it is *not* guaranteed that the first run contains the lowest offset
+ // Either make this a linear search (slow),
+ // or maintain an index (needs much mem),
+ // or calculate and store it in bidi.cpp (needs calculation even if not needed)
+ // (LS)
+ return m_lines[0]->m_start;
+}
+
+long RenderText::maxOffset() const
+{
+ int count = m_lines.count();
+ if (!count) return str->l;
+ // FIXME: it is *not* guaranteed that the last run contains the highest offset
+ // Either make this a linear search (slow),
+ // or maintain an index (needs much mem),
+ // or calculate and store it in bidi.cpp (needs calculation even if not needed)
+ // (LS)
+ return m_lines[count - 1]->m_start + m_lines[count - 1]->m_len;
+}
+
+bool RenderText::absolutePosition(int &xPos, int &yPos, bool) const
+{
+ return RenderObject::absolutePosition(xPos, yPos, false);
+}
+
+bool RenderText::posOfChar(int chr, int &x, int &y)
+{
+ if (!parent())
+ return false;
+ parent()->absolutePosition( x, y, false );
+
+ int pos;
+ InlineTextBox * s = findInlineTextBox( chr, pos );
+
+ if ( s ) {
+ // s is the line containing the character
+ x += s->m_x; // this is the x of the beginning of the line, but it's good enough for now
+ y += s->m_y;
+ return true;
+ }
+
+ return false;
+}
+
+void RenderText::paint( PaintInfo& /*pI*/, int /*tx*/, int /*ty*/)
+{
+ KHTMLAssert( false );
+}
+
+void RenderText::calcMinMaxWidth()
+{
+ KHTMLAssert( !minMaxKnown() );
+
+ // ### calc Min and Max width...
+ m_minWidth = m_beginMinWidth = m_endMinWidth = 0;
+ m_maxWidth = 0;
+
+ if (isBR())
+ return;
+
+ int currMinWidth = 0;
+ int currMaxWidth = 0;
+ m_hasBreakableChar = m_hasBreak = m_hasBeginWS = m_hasEndWS = false;
+
+ // ### not 100% correct for first-line
+ const Font *f = htmlFont( false );
+ int wordSpacing = style()->wordSpacing();
+ int len = str->l;
+ bool isSpace = false;
+ bool firstWord = true;
+ bool firstLine = true;
+ for(int i = 0; i < len; i++)
+ {
+ unsigned short c = str->s[i].unicode();
+ bool isNewline = false;
+
+ // If line-breaks survive to here they are preserved
+ if ( c == '\n' ) {
+ m_hasBreak = true;
+ isNewline = true;
+ isSpace = false;
+ } else
+ isSpace = c == ' ';
+
+ if ((isSpace || isNewline) && i == 0)
+ m_hasBeginWS = true;
+ if ((isSpace || isNewline) && i == len-1)
+ m_hasEndWS = true;
+
+ if (i && c == SOFT_HYPHEN)
+ continue;
+
+ int wordlen = 0;
+ while( i+wordlen < len && (i+wordlen == 0 || str->s[i+wordlen].unicode() != SOFT_HYPHEN) &&
+ !(isBreakable( str->s, i+wordlen, str->l )) )
+ wordlen++;
+
+ if (wordlen)
+ {
+#ifndef APPLE_CHANGES
+ int w = f->width(str->s, str->l, i, wordlen);
+#else
+ int w = widthFromCache(f, i, wordlen);
+#endif
+ currMinWidth += w;
+ currMaxWidth += w;
+
+ // Add in wordspacing to our maxwidth, but not if this is the last word.
+ if (wordSpacing && !containsOnlyWhitespace(i+wordlen, len-(i+wordlen)))
+ currMaxWidth += wordSpacing;
+
+ if (firstWord) {
+ firstWord = false;
+ m_beginMinWidth = w;
+ }
+ m_endMinWidth = w;
+
+ if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+ currMinWidth = 0;
+
+ i += wordlen-1;
+ }
+ else {
+ // Nowrap can never be broken, so don't bother setting the
+ // breakable character boolean. Pre can only be broken if we encounter a newline.
+ if (style()->autoWrap() || isNewline)
+ m_hasBreakableChar = true;
+
+ if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+ currMinWidth = 0;
+
+ if (isNewline) // Only set if isPre was true and we saw a newline.
+ {
+ if ( firstLine ) {
+ firstLine = false;
+ m_beginMinWidth = currMaxWidth;
+ }
+
+ if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
+ currMaxWidth = 0;
+ }
+ else
+ {
+ currMaxWidth += f->width( str->s, str->l, i + wordlen );
+ }
+ }
+ }
+
+ if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+ if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
+
+ if (!style()->autoWrap()) {
+ m_minWidth = m_maxWidth;
+ if (style()->preserveLF()) {
+ if (firstLine)
+ m_beginMinWidth = m_maxWidth;
+ m_endMinWidth = currMaxWidth;
+ }
+ }
+
+ setMinMaxKnown();
+ //kdDebug( 6040 ) << "Text::calcMinMaxWidth(): min = " << m_minWidth << " max = " << m_maxWidth << endl;
+
+}
+
+int RenderText::minXPos() const
+{
+ if (!m_lines.count())
+ return 0;
+ int retval=6666666;
+ for (unsigned i=0;i < m_lines.count(); i++)
+ {
+ retval = kMin ( retval, int( m_lines[i]->m_x ));
+ }
+ return retval;
+}
+
+int RenderText::inlineXPos() const
+{
+ return minXPos();
+}
+
+int RenderText::inlineYPos() const
+{
+ return m_lines.isEmpty() ? 0 : m_lines[0]->yPos();
+}
+
+const TQFont &RenderText::font()
+{
+ return style()->font();
+}
+
+void RenderText::setText(DOMStringImpl *text, bool force)
+{
+ if( !force && str == text ) return;
+
+ DOMStringImpl *oldstr = str;
+ if(text && style())
+ str = text->collapseWhiteSpace(style()->preserveLF(), style()->preserveWS());
+ else
+ str = text;
+ if(str) str->ref();
+ if(oldstr) oldstr->deref();
+
+ if ( str && style() ) {
+ oldstr = str;
+ switch(style()->textTransform()) {
+ case CAPITALIZE:
+ {
+ RenderObject *o;
+ bool runOnString = false;
+
+ // find previous non-empty text renderer if one exists
+ for (o = previousRenderer(); o; o = o->previousRenderer()) {
+ if (!o->isInlineFlow()) {
+ if (!o->isText())
+ break;
+
+ DOMStringImpl *prevStr = static_cast<RenderText*>(o)->string();
+ // !prevStr can happen with css like "content:open-quote;"
+ if (!prevStr)
+ break;
+
+ if (prevStr->length() == 0)
+ continue;
+ TQChar c = (*prevStr)[prevStr->length() - 1];
+ if (!c.isSpace())
+ runOnString = true;
+
+ break;
+ }
+ }
+
+ str = str->capitalize(runOnString);
+ }
+ break;
+
+
+
+ case UPPERCASE: str = str->upper(); break;
+ case LOWERCASE: str = str->lower(); break;
+ case NONE:
+ default:;
+ }
+ str->ref();
+ oldstr->deref();
+ }
+
+ // ### what should happen if we change the text of a
+ // RenderBR object ?
+ KHTMLAssert(!isBR() || (str->l == 1 && (*str->s) == '\n'));
+ KHTMLAssert(!str->l || str->s);
+
+ setNeedsLayoutAndMinMaxRecalc();
+#ifdef BIDI_DEBUG
+ TQConstString cstr(str->s, str->l);
+ kdDebug( 6040 ) << "RenderText::setText( " << cstr.string().length() << " ) '" << cstr.string() << "'" << endl;
+#endif
+}
+
+int RenderText::height() const
+{
+ int retval;
+ if ( m_lines.count() )
+ retval = m_lines[m_lines.count()-1]->m_y + m_lineHeight - m_lines[0]->m_y;
+ else
+ retval = metrics( false ).height();
+
+ return retval;
+}
+
+short RenderText::lineHeight( bool firstLine ) const
+{
+ if ( firstLine )
+ return RenderObject::lineHeight( firstLine );
+
+ return m_lineHeight;
+}
+
+short RenderText::baselinePosition( bool firstLine ) const
+{
+ const TQFontMetrics &fm = metrics( firstLine );
+ return fm.ascent() +
+ ( lineHeight( firstLine ) - fm.height() ) / 2;
+}
+
+InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox)
+{
+ KHTMLAssert( !isRootLineBox );
+ return new (renderArena()) InlineTextBox(this);
+}
+
+void RenderText::position(InlineBox* box, int from, int len, bool reverse)
+{
+//kdDebug(6040) << "position: from="<<from<<" len="<<len<<endl;
+ // ### should not be needed!!!
+ // asserts sometimes with pre (that unibw-hamburg testcase). ### find out why
+ //KHTMLAssert(!(len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ));
+ // It is now needed. BRs need text boxes too otherwise caret navigation
+ // gets stuck (LS)
+ // if (len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ) return;
+
+ reverse = reverse && !style()->visuallyOrdered();
+
+#ifdef DEBUG_LAYOUT
+ TQChar *ch = str->s+from;
+ TQConstString cstr(ch, len);
+#endif
+
+ KHTMLAssert(box->isInlineTextBox());
+ InlineTextBox *s = static_cast<InlineTextBox *>(box);
+ s->m_start = from;
+ s->m_len = len;
+ s->m_reversed = reverse;
+ //kdDebug(6040) << "m_start: " << s->m_start << " m_len: " << s->m_len << endl;
+
+ if(m_lines.count() == m_lines.size())
+ m_lines.resize(m_lines.size()*2+1);
+
+ m_lines.insert(m_lines.count(), s);
+ //kdDebug(6040) << this << " " << renderName() << "::position inserted" << endl;
+}
+
+unsigned int RenderText::width(unsigned int from, unsigned int len, bool firstLine) const
+{
+ if(!str->s || from > str->l ) return 0;
+ if ( from + len > str->l ) len = str->l - from;
+
+ const Font *f = htmlFont( firstLine );
+ return width( from, len, f );
+}
+
+unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *f) const
+{
+ if(!str->s || from > str->l ) return 0;
+ if ( from + len > str->l ) len = str->l - from;
+
+ if ( f == &style()->htmlFont() && from == 0 && len == str->l )
+ return m_maxWidth;
+
+ int w = f->width(str->s, str->l, from, len );
+
+ //kdDebug( 6040 ) << "RenderText::width(" << from << ", " << len << ") = " << w << endl;
+ return w;
+}
+
+short RenderText::width() const
+{
+ int w;
+ int minx = 100000000;
+ int maxx = 0;
+ // slooow
+ for(unsigned int si = 0; si < m_lines.count(); si++) {
+ InlineTextBox* s = m_lines[si];
+ if(s->m_x < minx)
+ minx = s->m_x;
+ if(s->m_x + s->m_width > maxx)
+ maxx = s->m_x + s->m_width;
+ }
+
+ w = kMax(0, maxx-minx);
+
+ return w;
+}
+
+void RenderText::repaint(Priority p)
+{
+ RenderObject *cb = containingBlock();
+ if(cb)
+ cb->repaint(p);
+}
+
+bool RenderText::isFixedWidthFont() const
+{
+ return TQFontInfo(style()->font()).fixedPitch();
+}
+
+short RenderText::verticalPositionHint( bool firstLine ) const
+{
+ return parent()->verticalPositionHint( firstLine );
+}
+
+const TQFontMetrics &RenderText::metrics(bool firstLine) const
+{
+ if( firstLine && hasFirstLine() ) {
+ RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+ if ( pseudoStyle )
+ return pseudoStyle->fontMetrics();
+ }
+ return style()->fontMetrics();
+}
+
+const Font *RenderText::htmlFont(bool firstLine) const
+{
+ const Font *f = 0;
+ if( firstLine && hasFirstLine() ) {
+ RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+ if ( pseudoStyle )
+ f = &pseudoStyle->htmlFont();
+ } else {
+ f = &style()->htmlFont();
+ }
+ return f;
+}
+
+bool RenderText::containsOnlyWhitespace(unsigned int from, unsigned int len) const
+{
+ unsigned int currPos;
+ for (currPos = from;
+ currPos < from+len && (str->s[currPos] == '\n' || str->s[currPos].direction() == TQChar::DirWS);
+ currPos++);
+ return currPos >= (from+len);
+}
+
+void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
+ short& endMinW, bool& endWS,
+ bool& hasBreakableChar, bool& hasBreak,
+ short& beginMaxW, short& endMaxW,
+ short& minW, short& maxW, bool& stripFrontSpaces)
+{
+ bool preserveWS = style()->preserveWS();
+ bool preserveLF = style()->preserveLF();
+ bool autoWrap = style()->autoWrap();
+ if (preserveWS)
+ stripFrontSpaces = false;
+
+ int len = str->l;
+ if (len == 0 || (stripFrontSpaces && str->containsOnlyWhitespace())) {
+ maxW = 0;
+ hasBreak = false;
+ return;
+ }
+
+ minW = m_minWidth;
+ maxW = m_maxWidth;
+ beginWS = stripFrontSpaces ? false : m_hasBeginWS;
+ endWS = m_hasEndWS;
+
+ beginMinW = m_beginMinWidth;
+ endMinW = m_endMinWidth;
+
+ hasBreakableChar = m_hasBreakableChar;
+ hasBreak = m_hasBreak;
+
+ if (stripFrontSpaces && (str->s[0].direction() == TQChar::DirWS || (!preserveLF && str->s[0] == '\n'))) {
+ const Font *f = htmlFont( false );
+ TQChar space[1]; space[0] = ' ';
+ int spaceWidth = f->width(space, 1, 0);
+ maxW -= spaceWidth;
+ }
+
+ stripFrontSpaces = !preserveWS && m_hasEndWS;
+
+ if (!autoWrap)
+ minW = maxW;
+ else if (minW > maxW)
+ minW = maxW;
+
+ // Compute our max widths by scanning the string for newlines.
+ if (hasBreak) {
+ const Font *f = htmlFont( false );
+ bool firstLine = true;
+ beginMaxW = endMaxW = maxW;
+ for(int i = 0; i < len; i++)
+ {
+ int linelen = 0;
+ while( i+linelen < len && str->s[i+linelen] != '\n')
+ linelen++;
+
+ if (linelen)
+ {
+#ifndef APPLE_CHANGES
+ endMaxW = f->width(str->s, str->l, i, linelen);
+#else
+ endMaxW = widthFromCache(f, i, linelen);
+#endif
+ if (firstLine) {
+ firstLine = false;
+ beginMaxW = endMaxW;
+ }
+ i += linelen;
+ }
+ else if (firstLine) {
+ beginMaxW = 0;
+ firstLine = false;
+ }
+ if (i == len-1)
+ // A <pre> run that ends with a newline, as in, e.g.,
+ // <pre>Some text\n\n<span>More text</pre>
+ endMaxW = 0;
+ }
+ }
+}
+
+#ifdef ENABLE_DUMP
+
+static TQString quoteAndEscapeNonPrintables(const TQString &s)
+{
+ TQString result;
+ result += '"';
+ for (uint i = 0; i != s.length(); ++i) {
+ TQChar c = s.at(i);
+ if (c == '\\') {
+ result += "\\\\";
+ } else if (c == '"') {
+ result += "\\\"";
+ } else {
+ ushort u = c.unicode();
+ if (u >= 0x20 && u < 0x7F) {
+ result += c;
+ } else {
+ TQString hex;
+ hex.sprintf("\\x{%X}", u);
+ result += hex;
+ }
+ }
+ }
+ result += '"';
+ return result;
+}
+
+static void writeTextRun(TQTextStream &ts, const RenderText &o, const InlineTextBox &run)
+{
+ ts << "text run at (" << run.m_x << "," << run.m_y << ") width " << run.m_width << ": "
+ << quoteAndEscapeNonPrintables(o.data().string().mid(run.m_start, run.m_len));
+}
+
+void RenderText::dump(TQTextStream &stream, const TQString &ind) const
+{
+ RenderObject::dump( stream, ind );
+
+ for (unsigned int i = 0; i < m_lines.count(); i++) {
+ stream << endl << ind << " ";
+ writeTextRun(stream, *this, *m_lines[i]);
+ }
+}
+#endif
+
+RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
+ int startOffset, int endOffset)
+:RenderText(_node, _str->substring(startOffset, endOffset)),
+m_start(startOffset), m_end(endOffset), m_generatedContentStr(0)
+{}
+
+RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str)
+:RenderText(_node, _str), m_start(0)
+{
+ m_generatedContentStr = _str;
+ if (_str) {
+ _str->ref();
+ m_end = _str->l;
+ }
+ else
+ m_end = 0;
+}
+
+RenderTextFragment::~RenderTextFragment()
+{
+ if (m_generatedContentStr)
+ m_generatedContentStr->deref();
+}
+
+bool RenderTextFragment::isTextFragment() const
+{
+ return true;
+}
+
+DOM::DOMStringImpl* RenderTextFragment::originalString() const
+{
+ DOM::DOMStringImpl* result = 0;
+ if (element())
+ result = element()->string();
+ else
+ result = contentString();
+ if (result && (start() > 0 || start() < result->l))
+ result = result->substring(start(), end());
+ return result;
+}
+
+#undef BIDI_DEBUG
+#undef DEBUG_LAYOUT
diff --git a/tdehtml/rendering/render_text.h b/tdehtml/rendering/render_text.h
new file mode 100644
index 000000000..acce98350
--- /dev/null
+++ b/tdehtml/rendering/render_text.h
@@ -0,0 +1,345 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2000-2003 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.
+ *
+ */
+#ifndef RENDERTEXT_H
+#define RENDERTEXT_H
+
+#include "dom/dom_string.h"
+#include "xml/dom_stringimpl.h"
+#include "xml/dom_textimpl.h"
+#include "rendering/render_object.h"
+#include "rendering/render_line.h"
+
+#include <tqptrvector.h>
+#include <assert.h>
+
+class TQPainter;
+class TQFontMetrics;
+
+// Define a constant for soft hyphen's unicode value.
+#define SOFT_HYPHEN 173
+
+const int cNoTruncation = -1;
+const int cFullTruncation = -2;
+
+namespace tdehtml
+{
+ class RenderText;
+ class RenderStyle;
+
+class InlineTextBox : public InlineBox
+{
+public:
+ InlineTextBox(RenderObject *obj)
+ :InlineBox(obj),
+ // ### necessary as some codepaths (<br>) do *not* initialize these (LS)
+ m_start(0), m_len(0), m_truncation(cNoTruncation), m_reversed(false), m_toAdd(0)
+ {
+ }
+
+ void detach(RenderArena* renderArena);
+
+ virtual void clearTruncation() { m_truncation = cNoTruncation; }
+ virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
+
+ // Overloaded new operator. Derived classes must override operator new
+ // in order to allocate out of the RenderArena.
+ void* operator new(size_t sz, RenderArena* renderArena) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void* ptr, size_t sz);
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t sz) throw();
+
+public:
+ void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
+ int spaceAdd() { return m_toAdd; }
+
+ virtual bool isInlineTextBox() const { return true; }
+
+ void paint(RenderObject::PaintInfo& i, int tx, int ty);
+ void paintDecoration(TQPainter *pt, const Font *f, int _tx, int _ty, int decoration);
+ void paintShadow(TQPainter *pt, const Font* f, int _tx, int _ty, const ShadowData *shadow );
+ void paintSelection(const Font *f, RenderText *text, TQPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos, int deco);
+
+ void selectionStartEnd(int& sPos, int& ePos);
+ RenderObject::SelectionState selectionState();
+
+ // Return before, after (offset set to max), or inside the text, at @p offset
+ FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, const Font *f, RenderText *text, int & offset, short lineheight);
+
+ bool checkVerticalPoint(int _y, int _ty, int _h, int height)
+ { if((_ty + m_y > _y + _h) || (_ty + m_y + m_baseline + height < _y)) return false; return true; }
+
+ /**
+ * determines the offset into the DOMString of the character the given
+ * coordinate points to.
+ * The returned offset is never out of range.
+ * @param _x given coordinate (relative to containing block)
+ * @param ax returns exact coordinate the offset corresponds to
+ * (relative to containing block)
+ * @return the offset (relative to the RenderText object, not to this run)
+ */
+ int offsetForPoint(int _x, int &ax) const;
+
+ /**
+ * calculates the with of the specified chunk in this text box.
+ * @param pos zero-based position within the text box up to which
+ * the width is to be determined
+ * @return the width in pixels
+ */
+ int widthFromStart(int pos) const;
+
+ /** returns the lowest possible value the caret offset may have to
+ * still point to a valid position.
+ */
+ virtual long minOffset() const;
+ /** returns the highest possible value the caret offset may have to
+ * still point to a valid position.
+ */
+ virtual long maxOffset() const;
+
+ /** returns the associated render text
+ */
+ const RenderText *renderText() const;
+ RenderText *renderText();
+
+ int m_start;
+ unsigned short m_len;
+
+ int m_truncation; // Where to truncate when text overflow is applied.
+ // We use special constants to denote no truncation (the whole run paints)
+ // and full truncation (nothing paints at all).
+
+ bool m_reversed : 1;
+ unsigned m_toAdd : 14; // for justified text
+private:
+ // this is just for TQVector::bsearch. Don't use it otherwise
+ InlineTextBox(int _x, int _y)
+ :InlineBox(0)
+ {
+ m_x = _x;
+ m_y = _y;
+ m_reversed = false;
+ };
+ friend class RenderText;
+};
+
+class InlineTextBoxArray : public TQPtrVector<InlineTextBox>
+{
+public:
+ InlineTextBoxArray();
+
+ InlineTextBox* first();
+
+ int findFirstMatching( Item ) const;
+ virtual int compareItems( Item, Item );
+};
+
+class RenderText : public RenderObject
+{
+ friend class InlineTextBox;
+
+public:
+ RenderText(DOM::NodeImpl* node, DOM::DOMStringImpl *_str);
+ virtual ~RenderText();
+
+ virtual bool isTextFragment() const;
+ virtual DOM::DOMStringImpl* originalString() const;
+
+ virtual const char *renderName() const { return "RenderText"; }
+
+ virtual void setStyle(RenderStyle *style);
+
+
+ virtual void paint( PaintInfo& i, int tx, int ty );
+
+ virtual void deleteInlineBoxes(RenderArena* arena=0);
+
+ DOM::DOMString data() const { return str; }
+ DOM::DOMStringImpl *string() const { return str; }
+
+ virtual InlineBox* createInlineBox(bool, bool);
+
+ virtual void layout() {assert(false);}
+
+ virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inBox);
+
+ // Return before, after (offset set to max), or inside the text, at @p offset
+ virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
+ DOM::NodeImpl*& node, int & offset,
+ SelPointState & );
+
+ unsigned int length() const { if (str) return str->l; else return 0; }
+ TQChar *text() const { if (str) return str->s; else return 0; }
+ unsigned int stringLength() const { return str->l; } // non virtual implementation of length()
+ virtual void position(InlineBox* box, int from, int len, bool reverse);
+
+ virtual unsigned int width(unsigned int from, unsigned int len, const Font *f) const;
+ virtual unsigned int width(unsigned int from, unsigned int len, bool firstLine = false) const;
+ virtual short width() const;
+ virtual int height() const;
+
+ // height of the contents (without paddings, margins and borders)
+ virtual short lineHeight( bool firstLine ) const;
+ virtual short baselinePosition( bool firstLine ) const;
+
+ // overrides
+ virtual void calcMinMaxWidth();
+ virtual short minWidth() const { return m_minWidth; }
+ virtual int maxWidth() const { return m_maxWidth; }
+
+ void trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
+ short& endMinW, bool& endWS,
+ bool& hasBreakableChar, bool& hasBreak,
+ short& beginMaxW, short& endMaxW,
+ short& minW, short& maxW, bool& stripFrontSpaces);
+
+ bool containsOnlyWhitespace(unsigned int from, unsigned int len) const;
+
+ ushort startMin() const { return m_startMin; }
+ ushort endMin() const { return m_endMin; }
+
+ // returns the minimum x position of all runs relative to the parent.
+ // defaults to 0.
+ int minXPos() const;
+
+ virtual int inlineXPos() const;
+ virtual int inlineYPos() const;
+
+ bool hasReturn() const { return m_hasReturn; }
+
+ virtual const TQFont &font();
+ virtual short verticalPositionHint( bool firstLine ) const;
+
+ bool isFixedWidthFont() const;
+
+ void setText(DOM::DOMStringImpl *text, bool force=false);
+
+ virtual SelectionState selectionState() const {return m_selectionState;}
+ virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
+ virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
+ virtual bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool f = false) const;
+ bool posOfChar(int ch, int &x, int &y);
+
+ virtual short marginLeft() const { return style()->marginLeft().minWidth(0); }
+ virtual short marginRight() const { return style()->marginRight().minWidth(0); }
+
+ virtual void repaint(Priority p=NormalPriority);
+
+ bool hasBreakableChar() const { return m_hasBreakableChar; }
+ const TQFontMetrics &metrics(bool firstLine) const;
+ const Font *htmlFont(bool firstLine) const;
+
+ DOM::TextImpl *element() const
+ { return static_cast<DOM::TextImpl*>(RenderObject::element()); }
+
+ /** returns the lowest possible value the caret offset may have to
+ * still point to a valid position.
+ */
+ virtual long minOffset() const;
+
+ /** returns the highest possible value the caret offset may have to
+ * still point to a valid position.
+ */
+ virtual long maxOffset() const;
+
+ /** returns the number of inline text boxes
+ */
+ unsigned inlineTextBoxCount() const { return m_lines.count(); }
+ /** returns the array of inline text boxes for this render text.
+ */
+ const InlineTextBoxArray &inlineTextBoxes() const { return m_lines; }
+
+#ifdef ENABLE_DUMP
+ virtual void dump(TQTextStream &stream, const TQString &ind) const;
+#endif
+
+ /** Find the text box that includes the character at @p offset
+ * and return pos, which is the position of the char in the run.
+ * @param offset zero-based offset into DOM string
+ * @param pos returns relative position within text box
+ * @param checkFirstLetter passing @p true will also regard :first-letter
+ * boxes, if available.
+ * @return the text box, or 0 if no match has been found
+ */
+ InlineTextBox * findInlineTextBox( int offset, int &pos,
+ bool checkFirstLetter = false );
+
+protected: // members
+ InlineTextBoxArray m_lines;
+ DOM::DOMStringImpl *str; //
+
+ short m_lineHeight;
+ short m_minWidth;
+ int m_maxWidth;
+ short m_beginMinWidth;
+ short m_endMinWidth;
+
+ SelectionState m_selectionState : 3 ;
+ bool m_hasReturn : 1;
+ bool m_hasBreakableChar : 1;
+ bool m_hasBreak : 1;
+ bool m_hasBeginWS : 1;
+ bool m_hasEndWS : 1;
+
+ ushort m_startMin : 8;
+ ushort m_endMin : 8;
+};
+
+inline const RenderText* InlineTextBox::renderText() const
+{ return static_cast<RenderText*>( object() ); }
+
+inline RenderText* InlineTextBox::renderText()
+{ return static_cast<RenderText*>( object() ); }
+
+// Used to represent a text substring of an element, e.g., for text runs that are split because of
+// first letter and that must therefore have different styles (and positions in the render tree).
+// We cache offsets so that text transformations can be applied in such a way that we can recover
+// the original unaltered string from our corresponding DOM node.
+class RenderTextFragment : public RenderText
+{
+public:
+ RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
+ int startOffset, int endOffset);
+ RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str);
+ ~RenderTextFragment();
+
+ virtual bool isTextFragment() const;
+ virtual const char *renderName() const { return "RenderTextFragment"; }
+
+ uint start() const { return m_start; }
+ uint end() const { return m_end; }
+
+ DOM::DOMStringImpl* contentString() const { return m_generatedContentStr; }
+ virtual DOM::DOMStringImpl* originalString() const;
+
+private:
+ uint m_start;
+ uint m_end;
+ DOM::DOMStringImpl* m_generatedContentStr;
+};
+} // end namespace
+#endif
diff --git a/tdehtml/rendering/table_layout.cpp b/tdehtml/rendering/table_layout.cpp
new file mode 100644
index 000000000..eb8153331
--- /dev/null
+++ b/tdehtml/rendering/table_layout.cpp
@@ -0,0 +1,1193 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ * (C) 2002 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.
+ *
+ * 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 "table_layout.h"
+#include "render_table.h"
+
+#include <kglobal.h>
+
+using namespace tdehtml;
+
+// #define DEBUG_LAYOUT
+
+/*
+ The text below is from the CSS 2.1 specs.
+
+ Fixed table layout
+ ------------------
+
+ With this (fast) algorithm, the horizontal layout of the table does
+ not depend on the contents of the cells; it only depends on the
+ table's width, the width of the columns, and borders or cell
+ spacing.
+
+ The table's width may be specified explicitly with the 'width'
+ property. A value of 'auto' (for both 'display: table' and 'display:
+ inline-table') means use the automatic table layout algorithm.
+
+ In the fixed table layout algorithm, the width of each column is
+ determined as follows:
+
+ 1. A column element with a value other than 'auto' for the 'width'
+ property sets the width for that column.
+
+ 2. Otherwise, a cell in the first row with a value other than
+ 'auto' for the 'width' property sets the width for that column. If
+ the cell spans more than one column, the width is divided over the
+ columns.
+
+ 3. Any remaining columns equally divide the remaining horizontal
+ table space (minus borders or cell spacing).
+
+ The width of the table is then the greater of the value of the
+ 'width' property for the table element and the sum of the column
+ widths (plus cell spacing or borders). If the table is wider than
+ the columns, the extra space should be distributed over the columns.
+
+
+ In this manner, the user agent can begin to lay out the table once
+ the entire first row has been received. Cells in subsequent rows do
+ not affect column widths. Any cell that has content that overflows
+ uses the 'overflow' property to determine whether to clip the
+ overflow content.
+
+_____________________________________________________
+
+ This is not quite true when comparing to IE. IE always honors
+ table-layout:fixed and treats a variable table width as 100%. Makes
+ a lot of sense, and is implemented here the same way.
+
+*/
+
+FixedTableLayout::FixedTableLayout( RenderTable *table )
+ : TableLayout ( table )
+{
+}
+
+FixedTableLayout::~FixedTableLayout()
+{
+}
+
+int FixedTableLayout::calcWidthArray()
+{
+ int usedWidth = 0;
+
+ // iterate over all <col> elements
+ RenderObject *child = table->firstChild();
+ int cCol = 0;
+ int nEffCols = table->numEffCols();
+ width.resize( nEffCols );
+ width.fill( Length( Variable ) );
+
+#ifdef DEBUG_LAYOUT
+ tqDebug("FixedTableLayout::calcWidthArray()" );
+ tqDebug(" col elements:");
+#endif
+
+ Length grpWidth;
+ while ( child ) {
+ if ( child->isTableCol() ) {
+ RenderTableCol *col = static_cast<RenderTableCol *>(child);
+ int span = col->span();
+ if ( col->firstChild() ) {
+ grpWidth = col->style()->width();
+ } else {
+ Length w = col->style()->width();
+ if ( w.isVariable() )
+ w = grpWidth;
+ int effWidth = 0;
+ if ( w.isFixed() && w.value() > 0 ) {
+ effWidth = w.value();
+ effWidth = KMIN( effWidth, 32760 );
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col element: effCol=%d, span=%d: %d w=%d type=%d",
+ cCol, span, effWidth, w.value(), w.type());
+#endif
+ int usedSpan = 0;
+ int i = 0;
+ while ( usedSpan < span ) {
+ if( cCol + i >= nEffCols ) {
+ table->appendColumn( span - usedSpan );
+ nEffCols++;
+ width.resize( nEffCols );
+ width[nEffCols-1] = Length();
+ }
+ int eSpan = table->spanOfEffCol( cCol+i );
+ if ( (w.isFixed() || w.isPercent()) && w.value() > 0 ) {
+ width[cCol+i] = Length( w.value() * eSpan, w.type() );
+ usedWidth += effWidth * eSpan;
+#ifdef DEBUG_LAYOUT
+ tqDebug(" setting effCol %d (span=%d) to width %d(type=%d)",
+ cCol+i, eSpan, width[cCol+i].value(), width[cCol+i].type() );
+#endif
+ }
+ usedSpan += eSpan;
+ i++;
+ }
+ cCol += i;
+ }
+ } else {
+ break;
+ }
+
+ RenderObject *next = child->firstChild();
+ if ( !next )
+ next = child->nextSibling();
+ if ( !next && child->parent()->isTableCol() ) {
+ next = child->parent()->nextSibling();
+ grpWidth = Length();
+ }
+ child = next;
+ }
+
+#ifdef DEBUG_LAYOUT
+ tqDebug(" first row:");
+#endif
+ // iterate over the first row in case some are unspecified.
+ RenderTableSection *section = table->head;
+ if ( !section )
+ section = table->firstBody;
+ if ( !section )
+ section = table->foot;
+ if ( section && section->firstChild() ) {
+ cCol = 0;
+ // get the first cell in the first row
+ child = section->firstChild()->firstChild();
+ while ( child ) {
+ if ( child->isTableCell() ) {
+ RenderTableCell *cell = static_cast<RenderTableCell *>(child);
+ Length w = cell->styleOrColWidth();
+ int span = cell->colSpan();
+ int effWidth = 0;
+ if ( (w.isFixed() || w.isPercent()) && w.value() > 0 ) {
+ effWidth = w.value();
+ effWidth = kMin( effWidth, 32760 );
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug(" table cell: effCol=%d, span=%d: %d", cCol, span, effWidth);
+#endif
+ int usedSpan = 0;
+ int i = 0;
+ while ( usedSpan < span ) {
+ Q_ASSERT( cCol + i < nEffCols );
+ int eSpan = table->spanOfEffCol( cCol+i );
+ // only set if no col element has already set it.
+ if ( width[cCol+i].isVariable() && !w.isVariable() ) {
+ width[cCol+i] = Length( w.value()*eSpan, w.type() );
+ usedWidth += effWidth*eSpan;
+#ifdef DEBUG_LAYOUT
+ tqDebug(" setting effCol %d (span=%d) to width %d(type=%d)",
+ cCol+i, eSpan, width[cCol+i].value(), width[cCol+i].type() );
+#endif
+ }
+#ifdef DEBUG_LAYOUT
+ else {
+ tqDebug(" width of col %d already defined (span=%d)", cCol, table->spanOfEffCol( cCol ) );
+ }
+#endif
+ usedSpan += eSpan;
+ i++;
+ }
+ cCol += i;
+ } else {
+ Q_ASSERT( false );
+ }
+ child = child->nextSibling();
+ }
+ }
+
+ return usedWidth;
+
+}
+
+void FixedTableLayout::calcMinMaxWidth()
+{
+ // we might want to wait until we have all of the first row before
+ // layouting for the first time.
+
+ // only need to calculate the minimum width as the sum of the
+ // cols/cells with a fixed width.
+ //
+ // The maximum width is kMax( minWidth, tableWidth ) if table
+ // width is fixed. If table width is percent, we set maxWidth to
+ // unlimited.
+
+ int bs = table->bordersPaddingAndSpacing();
+ int tableWidth = 0;
+ if (table->style()->width().isFixed()) {
+ tableWidth = table->calcBoxWidth(table->style()->width().value());
+ }
+
+ int mw = calcWidthArray() + bs;
+ table->m_minWidth = kMin( kMax( mw, tableWidth ), 0x7fff );
+ table->m_maxWidth = table->m_minWidth;
+
+ if ( !tableWidth ) {
+ bool haveNonFixed = false;
+ for ( unsigned int i = 0; i < width.size(); i++ ) {
+ if ( !width[i].isFixed() ) {
+ haveNonFixed = true;
+ break;
+ }
+ }
+ if ( haveNonFixed )
+ table->m_maxWidth = 0x7fff;
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug("FixedTableLayout::calcMinMaxWidth: minWidth=%d, maxWidth=%d", table->m_minWidth, table->m_maxWidth );
+#endif
+}
+
+void FixedTableLayout::layout()
+{
+ int tableWidth = table->width() - table->bordersPaddingAndSpacing();
+ int available = tableWidth;
+ int nEffCols = table->numEffCols();
+#ifdef DEBUG_LAYOUT
+ tqDebug("FixedTableLayout::layout: tableWidth=%d, numEffCols=%d", tableWidth, nEffCols);
+#endif
+
+
+ TQMemArray<int> calcWidth;
+ calcWidth.resize( nEffCols );
+ calcWidth.fill( -1 );
+
+ // first assign fixed width
+ for ( int i = 0; i < nEffCols; i++ ) {
+ if ( width[i].isFixed() ) {
+ calcWidth[i] = width[i].value();
+ available -= width[i].value();
+ }
+ }
+
+ // assign percent width
+ if ( available > 0 ) {
+ int totalPercent = 0;
+ for ( int i = 0; i < nEffCols; i++ )
+ if ( width[i].isPercent() )
+ totalPercent += width[i].value();
+
+ // calculate how much to distribute to percent cells.
+ int base = tableWidth * totalPercent / 100;
+ if ( base > available )
+ base = available;
+
+#ifdef DEBUG_LAYOUT
+ tqDebug("FixedTableLayout::layout: assigning percent width, base=%d, totalPercent=%d", base, totalPercent);
+#endif
+ for ( int i = 0; available > 0 && i < nEffCols; i++ ) {
+ if ( width[i].isPercent() ) {
+ // totalPercent may be 0 below if all %-width specifed are 0%. (#172557)
+ int w = totalPercent ? base * width[i].value() / totalPercent : 0;
+ available -= w;
+ calcWidth[i] = w;
+ }
+ }
+ }
+
+ // assign variable width
+ if ( available > 0 ) {
+ int totalVariable = 0;
+ for ( int i = 0; i < nEffCols; i++ )
+ if ( width[i].isVariable() )
+ totalVariable++;
+
+ for ( int i = 0; available > 0 && i < nEffCols; i++ ) {
+ if ( width[i].isVariable() ) {
+ // totalVariable may be 0 below if all the variable widths specified are 0.
+ int w = totalVariable ? available / totalVariable : 0;
+ available -= w;
+ calcWidth[i] = w;
+ totalVariable--;
+ }
+ }
+ }
+
+ for ( int i = 0; i < nEffCols; i++ )
+ if ( calcWidth[i] < 0 )
+ calcWidth[i] = 0; // IE gives min 1 px...
+
+ // spread extra space over columns
+ if ( available > 0 ) {
+ int total = nEffCols;
+ // still have some width to spread
+ int i = nEffCols;
+ while ( i-- ) {
+ int w = available / total;
+ available -= w;
+ total--;
+ calcWidth[i] += w;
+ }
+ }
+
+ int pos = 0;
+ int hspacing = table->borderHSpacing();
+ for ( int i = 0; i < nEffCols; i++ ) {
+#ifdef DEBUG_LAYOUT
+ tqDebug("col %d: %d (width %d)", i, pos, calcWidth[i] );
+#endif
+ table->columnPos[i] = pos;
+ pos += calcWidth[i] + hspacing;
+ }
+ table->columnPos[table->columnPos.size()-1] = pos;
+}
+
+// -------------------------------------------------------------------------
+// -------------------------------------------------------------------------
+
+
+AutoTableLayout::AutoTableLayout( RenderTable* table )
+ : TableLayout( table )
+{
+ percentagesDirty = true;
+ effWidthDirty = true;
+ total_percent = 0;
+ hasPercent = false;
+}
+
+AutoTableLayout::~AutoTableLayout()
+{
+}
+
+/* recalculates the full structure needed to do layouting and minmax calculations.
+ This is usually calculated on the fly, but needs to be done fully when table cells change
+ dynamically
+*/
+void AutoTableLayout::recalcColumn( int effCol )
+{
+ Layout &l = layoutStruct[effCol];
+
+ RenderObject *child = table->firstChild();
+ // first we iterate over all rows.
+
+ RenderTableCell *fixedContributor = 0;
+ RenderTableCell *maxContributor = 0;
+
+ while ( child ) {
+ if ( child->isTableSection() ) {
+ RenderTableSection *section = static_cast<RenderTableSection *>(child);
+ int numRows = section->numRows();
+ RenderTableCell *last = 0;
+ for ( int i = 0; i < numRows; i++ ) {
+ RenderTableCell *cell = section->cellAt( i, effCol );
+ if ( cell == (RenderTableCell *)-1 )
+ continue;
+ if ( cell && cell->colSpan() == 1 ) {
+ // A cell originates in this column. Ensure we have
+ // a min/max width of at least 1px for this column now.
+ l.minWidth = kMax(int( l.minWidth ), 1);
+ l.maxWidth = kMax(int( l.maxWidth ), 1);
+
+ if ( !cell->minMaxKnown() )
+ cell->calcMinMaxWidth();
+ if ( cell->minWidth() > l.minWidth )
+ l.minWidth = cell->minWidth();
+ if ( cell->maxWidth() > l.maxWidth ) {
+ l.maxWidth = cell->maxWidth();
+ maxContributor = cell;
+ }
+
+ Length w = cell->styleOrColWidth();
+ w.l.value = kMin( 32767, kMax( 0, w.value() ) );
+ switch( w.type() ) {
+ case Fixed:
+ // ignore width=0
+ if ( w.value() > 0 && !l.width.isPercent() ) {
+ int wval = cell->calcBoxWidth(w.value());
+ if ( l.width.isFixed() ) {
+ // Nav/IE weirdness
+ if ((wval > l.width.value()) ||
+ ((l.width.value() == wval) && (maxContributor == cell))) {
+ l.width.l.value = wval;
+ fixedContributor = cell;
+ }
+ } else {
+ l.width = Length( wval, Fixed );
+ fixedContributor = cell;
+ }
+ }
+ break;
+ case Percent:
+ hasPercent = true;
+ if ( w.value() > 0 && (!l.width.isPercent() || w.value() > l.width.value() ) )
+ l.width = w;
+ break;
+ case Relative:
+ if ( w.isVariable() || (w.isRelative() && w.value() > l.width.value() ) )
+ l.width = w;
+ default:
+ break;
+ }
+ } else {
+ if ( cell && (!effCol || section->cellAt( i, effCol-1 ) != cell) ) {
+ // This spanning cell originates in this column. Ensure we have
+ // a min/max width of at least 1px for this column now.
+ l.minWidth = kMax(int( l.minWidth ), 1);
+ l.maxWidth = kMax(int( l.maxWidth ), 1);
+ insertSpanCell( cell );
+ }
+ last = cell;
+ }
+ }
+ }
+ child = child->nextSibling();
+ }
+
+ // Nav/IE weirdness
+ if ( l.width.isFixed() ) {
+ if ( table->style()->htmlHacks()
+ && (l.maxWidth > l.width.value()) && (fixedContributor != maxContributor)) {
+ l.width = Length();
+ fixedContributor = 0;
+ }
+ }
+
+ l.maxWidth = kMax(l.maxWidth, int(l.minWidth));
+#ifdef DEBUG_LAYOUT
+ tqDebug("col %d, final min=%d, max=%d, width=%d(%d)", effCol, l.minWidth, l.maxWidth, l.width.value(), l.width.type() );
+#endif
+
+ // ### we need to add col elements aswell
+}
+
+
+void AutoTableLayout::fullRecalc()
+{
+ percentagesDirty = true;
+ hasPercent = false;
+ effWidthDirty = true;
+
+ int nEffCols = table->numEffCols();
+ layoutStruct.resize( nEffCols );
+ layoutStruct.fill( Layout() );
+ spanCells.fill( 0 );
+
+ RenderObject *child = table->firstChild();
+ Length grpWidth;
+ int cCol = 0;
+ while ( child ) {
+ if ( child->isTableCol() ) {
+ RenderTableCol *col = static_cast<RenderTableCol *>(child);
+ int span = col->span();
+ if ( col->firstChild() ) {
+ grpWidth = col->style()->width();
+ } else {
+ Length w = col->style()->width();
+ if ( w.isVariable() )
+ w = grpWidth;
+ if ( (w.isFixed() && w.value() == 0) ||
+ (w.isPercent() && w.value() == 0) )
+ w = Length();
+ int cEffCol = table->colToEffCol( cCol );
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col element %d (eff=%d): Length=%d(%d), span=%d, effColSpan=%d", cCol, cEffCol, w.value(), w.type(), span, table->spanOfEffCol(cEffCol ) );
+#endif
+ if ( !w.isVariable() && span == 1 && cEffCol < nEffCols ) {
+ if ( table->spanOfEffCol( cEffCol ) == 1 ) {
+ layoutStruct[cEffCol].width = w;
+ if (w.isFixed() && layoutStruct[cEffCol].maxWidth < w.value())
+ layoutStruct[cEffCol].maxWidth = w.value();
+ }
+ }
+ cCol += span;
+ }
+ } else {
+ break;
+ }
+
+ RenderObject *next = child->firstChild();
+ if ( !next )
+ next = child->nextSibling();
+ if ( !next && child->parent()->isTableCol() ) {
+ next = child->parent()->nextSibling();
+ grpWidth = Length();
+ }
+ child = next;
+ }
+
+
+ for ( int i = 0; i < nEffCols; i++ )
+ recalcColumn( i );
+}
+
+static bool shouldScaleColumns(RenderTable* table)
+{
+ // A special case. If this table is not fixed width and contained inside
+ // a cell, then don't bloat the maxwidth by examining percentage growth.
+ bool scale = true;
+ while (table) {
+ Length tw = table->style()->width();
+ if ((tw.isVariable() || tw.isPercent()) && !table->isPositioned()) {
+ RenderBlock* cb = table->containingBlock();
+ while (cb && !cb->isCanvas() && !cb->isTableCell() &&
+ cb->style()->width().isVariable() && !cb->isPositioned())
+ cb = cb->containingBlock();
+
+ table = 0;
+ if (cb && cb->isTableCell() &&
+ (cb->style()->width().isVariable() || cb->style()->width().isPercent())) {
+ if (tw.isPercent())
+ scale = false;
+ else {
+ RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
+ if (cell->colSpan() > 1 || cell->table()->style()->width().isVariable())
+ scale = false;
+ else
+ table = cell->table();
+ }
+ }
+ }
+ else
+ table = 0;
+ }
+ return scale;
+}
+
+void AutoTableLayout::calcMinMaxWidth()
+{
+#ifdef DEBUG_LAYOUT
+ tqDebug("AutoTableLayout::calcMinMaxWidth");
+#endif
+ fullRecalc();
+
+ int spanMaxWidth = calcEffectiveWidth();
+ int minWidth = 0;
+ int maxWidth = 0;
+ int maxPercent = 0;
+ int maxNonPercent = 0;
+
+ int remainingPercent = 100;
+ for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
+ minWidth += layoutStruct[i].effMinWidth;
+ maxWidth += layoutStruct[i].effMaxWidth;
+ if ( layoutStruct[i].effWidth.isPercent() ) {
+ int percent = kMin(layoutStruct[i].effWidth.value(), remainingPercent);
+ int pw = ( layoutStruct[i].effMaxWidth * 100) / kMax(percent, 1);
+ remainingPercent -= percent;
+ maxPercent = kMax( pw, maxPercent );
+ } else {
+ maxNonPercent += layoutStruct[i].effMaxWidth;
+ }
+ }
+
+ if (shouldScaleColumns(table)) {
+ maxNonPercent = (maxNonPercent * 100 + 50) / kMax(remainingPercent, 1);
+ maxWidth = kMax( maxNonPercent, maxWidth );
+ maxWidth = kMax( maxWidth, maxPercent );
+ }
+
+ maxWidth = kMax( maxWidth, spanMaxWidth );
+
+ int bs = table->bordersPaddingAndSpacing();
+ minWidth += bs;
+ maxWidth += bs;
+
+ Length tw = table->style()->width();
+ if ( tw.isFixed() && tw.value() > 0 ) {
+ int width = table->calcBoxWidth(tw.value());
+ minWidth = kMax( minWidth, width );
+ maxWidth = minWidth;
+ }
+
+ table->m_maxWidth = kMin(maxWidth, 0x7fff);
+ table->m_minWidth = kMin(minWidth, 0x7fff);
+#ifdef DEBUG_LAYOUT
+ tqDebug(" minWidth=%d, maxWidth=%d", table->m_minWidth, table->m_maxWidth );
+#endif
+}
+
+/*
+ This method takes care of colspans.
+ effWidth is the same as width for cells without colspans. If we have colspans, they get modified.
+ */
+int AutoTableLayout::calcEffectiveWidth()
+{
+ int tMaxWidth = 0;
+
+ unsigned int nEffCols = layoutStruct.size();
+ int hspacing = table->borderHSpacing();
+#ifdef DEBUG_LAYOUT
+ tqDebug("AutoTableLayout::calcEffectiveWidth for %d cols", nEffCols );
+#endif
+ for ( unsigned int i = 0; i < nEffCols; i++ ) {
+ layoutStruct[i].effWidth = layoutStruct[i].width;
+ layoutStruct[i].effMinWidth = layoutStruct[i].minWidth;
+ layoutStruct[i].effMaxWidth = layoutStruct[i].maxWidth;
+ }
+
+ for ( unsigned int i = 0; i < spanCells.size(); i++ ) {
+ RenderTableCell *cell = spanCells[i];
+ if ( !cell || cell == (RenderTableCell *)-1 )
+ break;
+ int span = cell->colSpan();
+
+ Length w = cell->styleOrColWidth();
+ if ( !w.isRelative() && w.value() == 0 )
+ w = Length(); // make it Variable
+
+ int col = table->colToEffCol( cell->col() );
+ unsigned int lastCol = col;
+ int cMinWidth = cell->minWidth() + hspacing;
+ int cMaxWidth = cell->maxWidth() + hspacing;
+ int totalPercent = 0;
+ int minWidth = 0;
+ int maxWidth = 0;
+ bool allColsArePercent = true;
+ bool allColsAreFixed = true;
+ bool haveVariable = false;
+ int fixedWidth = 0;
+#ifdef DEBUG_LAYOUT
+ int cSpan = span;
+#endif
+ while ( lastCol < nEffCols && span > 0 ) {
+ switch( layoutStruct[lastCol].width.type() ) {
+ case Percent:
+ totalPercent += layoutStruct[lastCol].width.value();
+ allColsAreFixed = false;
+ break;
+ case Fixed:
+ if (layoutStruct[lastCol].width.value() > 0) {
+ fixedWidth += layoutStruct[lastCol].width.value();
+ allColsArePercent = false;
+ // IE resets effWidth to Variable here, but this breaks the konqueror about page and seems to be some bad
+ // legacy behavior anyway. mozilla doesn't do this so I decided we don't either.
+ break;
+ }
+ // fall through
+ case Variable:
+ haveVariable = true;
+ // fall through
+ default:
+ // If the column is a percentage width, do not let the spanning cell overwrite the
+ // width value. This caused a mis-rendering on amazon.com.
+ // Sample snippet:
+ // <table border=2 width=100%><
+ // <tr><td>1</td><td colspan=2>2-3</tr>
+ // <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
+ // </table>
+ if (!layoutStruct[lastCol].effWidth.isPercent()) {
+ layoutStruct[lastCol].effWidth = Length();
+ allColsArePercent = false;
+ }
+ else
+ totalPercent += layoutStruct[lastCol].effWidth.value();
+ allColsAreFixed = false;
+ }
+ span -= table->spanOfEffCol( lastCol );
+ minWidth += layoutStruct[lastCol].effMinWidth;
+ maxWidth += layoutStruct[lastCol].effMaxWidth;
+ lastCol++;
+ cMinWidth -= hspacing;
+ cMaxWidth -= hspacing;
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug(" colspan cell %p at effCol %d, span %d, type %d, value %d cmin=%d min=%d fixedwidth=%d", cell, col, cSpan, w.type(), w.value(), cMinWidth, minWidth, fixedWidth );
+#endif
+
+ // adjust table max width if needed
+ if ( w.isPercent() ) {
+ if ( totalPercent > w.value() || allColsArePercent ) {
+ // can't satify this condition, treat as variable
+ w = Length();
+ } else {
+ int spanMax = kMax( maxWidth, cMaxWidth );
+#ifdef DEBUG_LAYOUT
+ tqDebug(" adjusting tMaxWidth (%d): spanMax=%d, value=%d, totalPercent=%d", tMaxWidth, spanMax, w.value(), totalPercent );
+#endif
+ tMaxWidth = kMax( tMaxWidth, spanMax * 100 / w.value() );
+
+ // all non percent columns in the span get percent values to sum up correctly.
+ int percentMissing = w.value() - totalPercent;
+ int totalWidth = 0;
+ for ( unsigned int pos = col; pos < lastCol; pos++ ) {
+ if ( !(layoutStruct[pos].width.isPercent() ) )
+ totalWidth += layoutStruct[pos].effMaxWidth;
+ }
+
+ for ( unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++ ) {
+ if ( !(layoutStruct[pos].width.isPercent() ) ) {
+ int percent = percentMissing * layoutStruct[pos].effMaxWidth / totalWidth;
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: setting percent value %d effMaxWidth=%d totalWidth=%d", pos, percent, layoutStruct[pos].effMaxWidth, totalWidth );
+#endif
+ totalWidth -= layoutStruct[pos].effMaxWidth;
+ percentMissing -= percent;
+ if ( percent > 0 )
+ layoutStruct[pos].effWidth = Length( percent, Percent );
+ else
+ layoutStruct[pos].effWidth = Length();
+ }
+ }
+
+ }
+ }
+
+ // make sure minWidth and maxWidth of the spanning cell are honoured
+ if ( cMinWidth > minWidth ) {
+ if ( allColsAreFixed ) {
+#ifdef DEBUG_LAYOUT
+ tqDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d accroding to fixed sum %d", col, lastCol-1, cMinWidth, minWidth, fixedWidth );
+#endif
+ for ( unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++ ) {
+ int w = kMax( int( layoutStruct[pos].effMinWidth ), cMinWidth * layoutStruct[pos].width.value() / fixedWidth );
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
+#endif
+ fixedWidth -= layoutStruct[pos].width.value();
+ cMinWidth -= w;
+ layoutStruct[pos].effMinWidth = w;
+ }
+
+ } else if ( allColsArePercent ) {
+ int maxw = maxWidth;
+ int minw = minWidth;
+ int cminw = cMinWidth;
+
+ for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) {
+ if ( layoutStruct[pos].effWidth.isPercent() && layoutStruct[pos].effWidth.value()>0 && fixedWidth <= cMinWidth) {
+ int w = layoutStruct[pos].effMinWidth;
+ w = kMax( w, cminw*layoutStruct[pos].effWidth.value()/totalPercent );
+ w = kMin(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
+#endif
+ maxw -= layoutStruct[pos].effMaxWidth;
+ minw -= layoutStruct[pos].effMinWidth;
+ cMinWidth -= w;
+ layoutStruct[pos].effMinWidth = w;
+ }
+ }
+ } else {
+#ifdef DEBUG_LAYOUT
+ tqDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d", col, lastCol-1, cMinWidth, minWidth );
+#endif
+ int maxw = maxWidth;
+ int minw = minWidth;
+
+ // Give min to variable first, to fixed second, and to others third.
+ for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) {
+ if ( layoutStruct[pos].width.isFixed() && haveVariable && fixedWidth <= cMinWidth ) {
+ int w = kMax( int( layoutStruct[pos].effMinWidth ), layoutStruct[pos].width.value() );
+ fixedWidth -= layoutStruct[pos].width.value();
+ minw -= layoutStruct[pos].effMinWidth;
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
+#endif
+ maxw -= layoutStruct[pos].effMaxWidth;
+ cMinWidth -= w;
+ layoutStruct[pos].effMinWidth = w;
+ }
+ }
+
+ for ( unsigned int pos = col; maxw > 0 && pos < lastCol && minw < cMinWidth; pos++ ) {
+ if ( !(layoutStruct[pos].width.isFixed() && haveVariable && fixedWidth <= cMinWidth) ) {
+ int w = kMax( int( layoutStruct[pos].effMinWidth ), cMinWidth * layoutStruct[pos].effMaxWidth / maxw );
+ w = kMin(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
+
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
+#endif
+ maxw -= layoutStruct[pos].effMaxWidth;
+ minw -= layoutStruct[pos].effMinWidth;
+ cMinWidth -= w;
+ layoutStruct[pos].effMinWidth = w;
+ }
+ }
+ }
+ }
+ if ( !w.isPercent() ) {
+ if ( cMaxWidth > maxWidth ) {
+#ifdef DEBUG_LAYOUT
+ tqDebug("extending maxWidth of cols %d-%d to %dpx", col, lastCol-1, cMaxWidth );
+#endif
+ for ( unsigned int pos = col; maxWidth > 0 && pos < lastCol; pos++ ) {
+ int w = kMax( int( layoutStruct[pos].effMaxWidth ), cMaxWidth * layoutStruct[pos].effMaxWidth / maxWidth );
+#ifdef DEBUG_LAYOUT
+ tqDebug(" col %d: max=%d, effMax=%d, new=%d", pos, layoutStruct[pos].effMaxWidth, layoutStruct[pos].effMaxWidth, w );
+#endif
+ maxWidth -= layoutStruct[pos].effMaxWidth;
+ cMaxWidth -= w;
+ layoutStruct[pos].effMaxWidth = w;
+ }
+ }
+ } else {
+ for ( unsigned int pos = col; pos < lastCol; pos++ )
+ layoutStruct[pos].maxWidth = kMax(layoutStruct[pos].maxWidth, int(layoutStruct[pos].minWidth) );
+ }
+ }
+ effWidthDirty = false;
+
+// tqDebug("calcEffectiveWidth: tMaxWidth=%d", tMaxWidth );
+ return tMaxWidth;
+}
+
+/* gets all cells that originate in a column and have a cellspan > 1
+ Sorts them by increasing cellspan
+*/
+void AutoTableLayout::insertSpanCell( RenderTableCell *cell )
+{
+ if ( !cell || cell == (RenderTableCell *)-1 || cell->colSpan() == 1 )
+ return;
+
+// tqDebug("inserting span cell %p with span %d", cell, cell->colSpan() );
+ int size = spanCells.size();
+ if ( !size || spanCells[size-1] != 0 ) {
+ spanCells.resize( size + 10 );
+ for ( int i = 0; i < 10; i++ )
+ spanCells[size+i] = 0;
+ size += 10;
+ }
+
+ // add them in sort. This is a slow algorithm, and a binary search or a fast sorting after collection would be better
+ unsigned int pos = 0;
+ int span = cell->colSpan();
+ while ( pos < spanCells.size() && spanCells[pos] && span > spanCells[pos]->colSpan() )
+ pos++;
+ memmove( spanCells.data()+pos+1, spanCells.data()+pos, (size-pos-1)*sizeof( RenderTableCell * ) );
+ spanCells[pos] = cell;
+}
+
+
+void AutoTableLayout::layout()
+{
+ // table layout based on the values collected in the layout structure.
+ int tableWidth = table->width() - table->bordersPaddingAndSpacing();
+ int available = tableWidth;
+ int nEffCols = table->numEffCols();
+
+ if ( nEffCols != (int)layoutStruct.size() ) {
+ tqWarning("WARNING: nEffCols is not equal to layoutstruct!" );
+ fullRecalc();
+ nEffCols = table->numEffCols();
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug("AutoTableLayout::layout()");
+#endif
+
+ if ( effWidthDirty )
+ calcEffectiveWidth();
+
+#ifdef DEBUG_LAYOUT
+ tqDebug(" tableWidth=%d, nEffCols=%d", tableWidth, nEffCols );
+ for ( int i = 0; i < nEffCols; i++ ) {
+ tqDebug(" effcol %d is of type %d value %d, minWidth=%d, maxWidth=%d",
+ i, layoutStruct[i].width.type(), layoutStruct[i].width.value(),
+ layoutStruct[i].minWidth, layoutStruct[i].maxWidth );
+ tqDebug(" effective: type %d value %d, minWidth=%d, maxWidth=%d",
+ layoutStruct[i].effWidth.type(), layoutStruct[i].effWidth.value(),
+ layoutStruct[i].effMinWidth, layoutStruct[i].effMaxWidth );
+ }
+#endif
+
+ bool havePercent = false;
+ bool haveRelative = false;
+ int totalRelative = 0;
+ int numVariable = 0;
+ int numFixed = 0;
+ int totalVariable = 0;
+ int totalFixed = 0;
+ int totalPercent = 0;
+ int allocVariable = 0;
+
+ // fill up every cell with it's minWidth
+ for ( int i = 0; i < nEffCols; i++ ) {
+ int w = layoutStruct[i].effMinWidth;
+ layoutStruct[i].calcWidth = w;
+ available -= w;
+ Length& width = layoutStruct[i].effWidth;
+ switch( width.type()) {
+ case Percent:
+ havePercent = true;
+ totalPercent += width.value();
+ break;
+ case Relative:
+ haveRelative = true;
+ totalRelative += width.value();
+ break;
+ case Fixed:
+ numFixed++;
+ totalFixed += layoutStruct[i].effMaxWidth;
+ // fall through
+ break;
+ case Variable:
+ case Static:
+ numVariable++;
+ totalVariable += layoutStruct[i].effMaxWidth;
+ allocVariable += w;
+ }
+ }
+
+ // allocate width to percent cols
+ if ( available > 0 && havePercent ) {
+ for ( int i = 0; i < nEffCols; i++ ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isPercent() ) {
+ int w = kMax ( int( layoutStruct[i].effMinWidth ), width.minWidth( tableWidth ) );
+ available += layoutStruct[i].calcWidth - w;
+ layoutStruct[i].calcWidth = w;
+ }
+ }
+ if ( totalPercent > 100 ) {
+ // remove overallocated space from the last columns
+ int excess = tableWidth*(totalPercent-100)/100;
+ for ( int i = nEffCols-1; i >= 0; i-- ) {
+ if ( layoutStruct[i].effWidth.isPercent() ) {
+ int w = layoutStruct[i].calcWidth;
+ int reduction = kMin( w, excess );
+ // the lines below might look inconsistent, but that's the way it's handled in mozilla
+ excess -= reduction;
+ int newWidth = kMax( int (layoutStruct[i].effMinWidth), w - reduction );
+ available += w - newWidth;
+ layoutStruct[i].calcWidth = newWidth;
+ //tqDebug("col %d: reducing to %d px (reduction=%d)", i, newWidth, reduction );
+ }
+ }
+ }
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug("percent satisfied: available is %d", available);
+#endif
+
+ // then allocate width to fixed cols
+ if ( available > 0 ) {
+ for ( int i = 0; i < nEffCols; ++i ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isFixed() && width.value() > layoutStruct[i].calcWidth ) {
+ available += layoutStruct[i].calcWidth - width.value();
+ layoutStruct[i].calcWidth = width.value();
+ }
+ }
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug("fixed satisfied: available is %d", available);
+#endif
+
+ // now satisfy relative
+ if ( available > 0 ) {
+ for ( int i = 0; i < nEffCols; i++ ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isRelative() && width.value() ) {
+ // width=0* gets effMinWidth.
+ int w = width.value()*tableWidth/totalRelative;
+ available += layoutStruct[i].calcWidth - w;
+ layoutStruct[i].calcWidth = w;
+ }
+ }
+ }
+
+ // now satisfy variable
+ if ( available > 0 && numVariable ) {
+ available += allocVariable; // this gets redistributed
+ //tqDebug("redistributing %dpx to %d variable columns. totalVariable=%d", available, numVariable, totalVariable );
+ for ( int i = 0; i < nEffCols; i++ ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isVariable() && totalVariable != 0 ) {
+ int w = kMax( int ( layoutStruct[i].calcWidth ),
+ available * layoutStruct[i].effMaxWidth / totalVariable );
+ available -= w;
+ totalVariable -= layoutStruct[i].effMaxWidth;
+ layoutStruct[i].calcWidth = w;
+ }
+ }
+ }
+#ifdef DEBUG_LAYOUT
+ tqDebug("variable satisfied: available is %d", available );
+#endif
+
+ // spread over fixed colums
+ if ( available > 0 && numFixed) {
+ // still have some width to spread, distribute to fixed columns
+ for ( int i = 0; i < nEffCols; i++ ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isFixed() ) {
+ int w = available * layoutStruct[i].effMaxWidth / totalFixed;
+ available -= w;
+ totalFixed -= layoutStruct[i].effMaxWidth;
+ layoutStruct[i].calcWidth += w;
+ }
+ }
+ }
+
+#ifdef DEBUG_LAYOUT
+ tqDebug("after fixed distribution: available=%d", available );
+#endif
+
+ // spread over percent colums
+ if ( available > 0 && hasPercent && totalPercent < 100) {
+ // still have some width to spread, distribute weighted to percent columns
+ for ( int i = 0; i < nEffCols; i++ ) {
+ const Length &width = layoutStruct[i].effWidth;
+ if ( width.isPercent() ) {
+ int w = available * width.value() / totalPercent;
+ available -= w;
+ totalPercent -= width.value();
+ layoutStruct[i].calcWidth += w;
+ if (!available || !totalPercent) break;
+ }
+ }
+ }
+
+#ifdef DEBUG_LAYOUT
+ tqDebug("after percent distribution: available=%d", available );
+#endif
+
+ // spread over the rest
+ if ( available > 0 ) {
+ int total = nEffCols;
+ // still have some width to spread
+ int i = nEffCols;
+ while ( i-- ) {
+ int w = available / total;
+ available -= w;
+ total--;
+ layoutStruct[i].calcWidth += w;
+ }
+ }
+
+#ifdef DEBUG_LAYOUT
+ tqDebug("after equal distribution: available=%d", available );
+#endif
+ // if we have overallocated, reduce every cell according to the difference between desired width and minwidth
+ // this seems to produce to the pixel exaxt results with IE. Wonder is some of this also holds for width distributing.
+ if ( available < 0 ) {
+ // Need to reduce cells with the following prioritization:
+ // (1) Variable
+ // (2) Relative
+ // (3) Fixed
+ // (4) Percent
+ // This is basically the reverse of how we grew the cells.
+ if (available < 0) {
+ int mw = 0;
+ for ( int i = nEffCols-1; i >= 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isVariable())
+ mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
+ }
+
+ for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isVariable()) {
+ int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
+ int reduce = available * minMaxDiff / mw;
+ layoutStruct[i].calcWidth += reduce;
+ available -= reduce;
+ mw -= minMaxDiff;
+ if ( available >= 0 )
+ break;
+ }
+ }
+ }
+
+ if (available < 0) {
+ int mw = 0;
+ for ( int i = nEffCols-1; i >= 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isRelative())
+ mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
+ }
+
+ for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isRelative()) {
+ int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
+ int reduce = available * minMaxDiff / mw;
+ layoutStruct[i].calcWidth += reduce;
+ available -= reduce;
+ mw -= minMaxDiff;
+ if ( available >= 0 )
+ break;
+ }
+ }
+ }
+
+ if (available < 0) {
+ int mw = 0;
+ for ( int i = nEffCols-1; i >= 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isFixed())
+ mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
+ }
+
+ for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isFixed()) {
+ int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
+ int reduce = available * minMaxDiff / mw;
+ layoutStruct[i].calcWidth += reduce;
+ available -= reduce;
+ mw -= minMaxDiff;
+ if ( available >= 0 )
+ break;
+ }
+ }
+ }
+
+ if (available < 0) {
+ int mw = 0;
+ for ( int i = nEffCols-1; i >= 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isPercent())
+ mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
+ }
+
+ for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
+ Length &width = layoutStruct[i].effWidth;
+ if (width.isPercent()) {
+ int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
+ int reduce = available * minMaxDiff / mw;
+ layoutStruct[i].calcWidth += reduce;
+ available -= reduce;
+ mw -= minMaxDiff;
+ if ( available >= 0 )
+ break;
+ }
+ }
+ }
+ }
+
+ //tqDebug( " final available=%d", available );
+
+ int pos = 0;
+ for ( int i = 0; i < nEffCols; i++ ) {
+#ifdef DEBUG_LAYOUT
+ tqDebug("col %d: %d (width %d)", i, pos, layoutStruct[i].calcWidth );
+#endif
+ table->columnPos[i] = pos;
+ pos += layoutStruct[i].calcWidth + table->borderHSpacing();
+ }
+ table->columnPos[table->columnPos.size()-1] = pos;
+
+}
+
+
+void AutoTableLayout::calcPercentages() const
+{
+ total_percent = 0;
+ for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
+ if ( layoutStruct[i].width.isPercent() )
+ total_percent += layoutStruct[i].width.value();
+ }
+ percentagesDirty = false;
+}
+
+#undef DEBUG_LAYOUT
diff --git a/tdehtml/rendering/table_layout.h b/tdehtml/rendering/table_layout.h
new file mode 100644
index 000000000..04b34a832
--- /dev/null
+++ b/tdehtml/rendering/table_layout.h
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the HTML rendering engine for KDE.
+ *
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ * (C) 2002 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.
+ *
+ * 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 TABLE_LAYOUT_H
+#define TABLE_LAYOUT_H
+
+#include <tqmemarray.h>
+#include <misc/tdehtmllayout.h>
+
+namespace tdehtml {
+
+class RenderTable;
+class RenderTableCell;
+
+// -------------------------------------------------------------------------
+
+class TableLayout
+{
+public:
+ TableLayout( RenderTable *t ) : table( t ) {}
+ virtual ~TableLayout() {}
+
+ virtual void calcMinMaxWidth() = 0;
+ virtual void layout() = 0;
+
+protected:
+ RenderTable *table;
+};
+
+// -------------------------------------------------------------------------
+
+class FixedTableLayout : public TableLayout
+{
+public:
+ FixedTableLayout( RenderTable *table );
+ ~FixedTableLayout();
+
+ void calcMinMaxWidth();
+ void layout();
+
+protected:
+ int calcWidthArray();
+
+ TQMemArray<Length> width;
+};
+
+// -------------------------------------------------------------------------
+
+class AutoTableLayout : public TableLayout
+{
+public:
+ AutoTableLayout( RenderTable *table );
+ ~AutoTableLayout();
+
+ void calcMinMaxWidth();
+ void layout();
+
+
+protected:
+ void fullRecalc();
+ void recalcColumn( int effCol );
+ int totalPercent() const {
+ if ( percentagesDirty )
+ calcPercentages();
+ return total_percent;
+ }
+ void calcPercentages() const;
+ int calcEffectiveWidth();
+ void insertSpanCell( RenderTableCell *cell );
+
+ struct Layout {
+ Layout() : minWidth( 1 ), maxWidth( 1 ),
+ effMinWidth( 0 ), effMaxWidth( 0 ),
+ calcWidth( 0 ) {}
+ Length width;
+ Length effWidth;
+ short minWidth;
+ int maxWidth;
+ short effMinWidth;
+ int effMaxWidth;
+ short calcWidth;
+ };
+
+ TQMemArray<Layout> layoutStruct;
+ TQMemArray<RenderTableCell *>spanCells;
+ bool hasPercent : 1;
+ mutable bool percentagesDirty : 1;
+ mutable bool effWidthDirty : 1;
+ mutable unsigned short total_percent;
+};
+
+}
+#endif
diff --git a/tdehtml/rendering/table_layout.txt b/tdehtml/rendering/table_layout.txt
new file mode 100644
index 000000000..6dee6c1c2
--- /dev/null
+++ b/tdehtml/rendering/table_layout.txt
@@ -0,0 +1,74 @@
+CSS describes two ways of layouting tables. Auto layout (the NS4
+compliant HTML table layout) and fixed layout. The fixed layout
+strategy is described in detail in the CSS specs and will not be
+repeated here.
+
+Due to the fact that two layout strategies exist, it is rather natural
+to encapsulate the layouting process in a TableLayout class. Two types
+(FixedTableLayout and AutoTableLayout) exist. AutoTableLayout is the
+default and also need a quirks flags for NS compatibility
+mode. FixedTableLayout will be used if a style rule sets the
+table-layout property to fixed.
+
+The grid of table cells is stored in each table section, as spans
+can't pass section borders. Changing the number of cols in the grid
+has to be done by the table to keep all grids (for all sections) in
+sync. The grid only stores effective columns. The table below would
+only result in one column being allocated in the grid:
+
+<table><tr><td colspan=1000>foo</td></tr></table>
+
+Once a colspan get's used, the column is split into its subparts. To
+do this, the table has to store the colspans of effective columns in a
+structure.
+
+
+
+
+NS & Mozilla compliant table layouting algorithm (AutoTableLayout)
+------------------------------------------------------------------
+
+The table layout algorithm computes a set of layout hints from the
+informations in the table cells, <col> elements and style
+sheets. Hints from different sources are treated a bit differently in
+the collection stage.
+
+In addition certain operations are only done in quirks (NS4 compat)
+mode.
+
+Resizing the table doesn't require you to build up this information
+again. All that is needed is a list of layout hints for each column.
+
+The algorithm below describes to the best of our knowledge the way
+table alyouting is handled in a NS compatible way.
+
+There are two stages, the collection stage (assocaited with
+calcMinMaxWidth() in tdehtml) and the stage assigning width to cells
+(associated with layout()).
+
+A set of hinted widths are used to determine the final table layout in
+the layouting stage.
+
+enum hintType {
+ MinWidth,
+ DesiredWidth,
+ FixedWidth,
+ MinWidthAdjusted,
+ DesiredWidthAdjusted,
+ FixedWidthAdjusted,
+ PercentWidth,
+ PercentWidthAdjusted,
+ ProportionalWidth
+};
+
+One width (in pixels) for each hintType describes how the column
+wishes to be layouted. The layouting stage operates only on an array
+of hints for each column.
+
+An additional totalCellSpacing variable is used to know about the
+remaining width to distribute.
+
+Collection stage:
+-----------------
+
+
diff --git a/tdehtml/tdehtml-devel-gdb b/tdehtml/tdehtml-devel-gdb
new file mode 100644
index 000000000..02030b2d6
--- /dev/null
+++ b/tdehtml/tdehtml-devel-gdb
@@ -0,0 +1,22 @@
+# This file defines handy gdb macros for KHTML
+# To use it, add this line to your ~/.gdbinit :
+# source /path/to/kde/sources/tdelibs/tdehtml/tdehtml-devel-gdb
+
+define printdomstring
+ printdomstringimpl $arg0.impl
+end
+document printdomstring
+ Prints the contents of a KHTML DOMString.
+end
+define printdomstringimpl
+ set $i=0
+ set $d = $arg0
+ while $i < $d->l
+ printf "%c", (char)($d->s[$i++].ucs & 0xff)
+ end
+ printf "\n"
+end
+document printdomstringimpl
+ Prints the contents of a KHTML DOMStringImpl.
+end
+
diff --git a/tdehtml/tdehtml.desktop b/tdehtml/tdehtml.desktop
new file mode 100644
index 000000000..959691671
--- /dev/null
+++ b/tdehtml/tdehtml.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Type=Service
+Comment=Embeddable HTML viewing component
+Comment[af]=Inlegbare Html aansig komponent
+Comment[ar]=مكون عرض HTML قابل للدمج
+Comment[az]=Hopdurula Bilən HTML nümayiş vasitəsi
+Comment[be]=Унутраны праглÑдальнік HTML
+Comment[bg]=Вграден компонент за преглед на HTML файлове
+Comment[bn]=অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ à¦à¦‡à¦š-টি-à¦à¦®-à¦à¦² পà§à¦°à¦¦à¦°à§à¦¶à¦• উপাদান
+Comment[br]=Parzh HTML gweler enframmus
+Comment[bs]=Umetljiva HTML komponenta
+Comment[ca]=Component encastable per a visualitzar HTML
+Comment[cs]=Komponenta pro zobrazování HTML
+Comment[csb]=Kòmpònent do przezeraniô lopków HTML
+Comment[cy]=Cydran gweld HTML mewnadeiladadwy
+Comment[da]=HTML-visningskomponent som kan indlejres
+Comment[de]=Einbettungsfähige HTML-Betrachtungskomponente
+Comment[el]=Ενσωματώσιμο στοιχείο Ï€Ïοβολής HTML
+Comment[eo]=HTML-rigardo-komponento
+Comment[es]=Componente incrustable para visualizar HTML
+Comment[et]=Põimitav HTML-i näitamise komponent
+Comment[eu]=Kapsulatutako HTML ikustailea
+Comment[fa]=مولÙÛ€ مشاهدۀ زنگام نهÙته
+Comment[fi]=Upotettava HTML-katselukomponentti
+Comment[fr]=Composant d'affichage HTML intégrable
+Comment[fy]=Yn te sluten HTML-werjeftekomponint
+Comment[ga]=Comhpháirt inleabaithe amharctha HTML
+Comment[gl]=Compoñente incrustábel de visualización de HTML
+Comment[he]=רכיב בר־הטבעה לתצוגת HTML
+Comment[hi]=अंतरà¥à¤¨à¤¿à¤¹à¤¿à¤¤ योगà¥à¤¯ HTML दरà¥à¤¶à¤• घटक
+Comment[hr]=Ugrađeni komponenta za pregledavanje HTML
+Comment[hu]=Beágyazható HTML-néző komponens
+Comment[id]=Komponen untuk melihat HTML yang embeddable
+Comment[is]=Ãvafin HTML-skoðunar eining
+Comment[it]=Componente integrabile per la visualizzazione di HTML
+Comment[ja]=埋ã‚è¾¼ã¿å¯èƒ½ãª HTML ビューアコンãƒãƒ¼ãƒãƒ³ãƒˆ
+Comment[ka]=ჩáƒáƒ“გმáƒáƒ“ი კáƒáƒ›áƒžáƒáƒœáƒ”ნტი HTML-ის სáƒáƒ©áƒ•áƒ”ნებლáƒáƒ“
+Comment[kk]=Ендірілетін HTML қарау компоненті
+Comment[km]=សមាសភាគ​មើល HTML ដែល​អាច​បង្កប់
+Comment[ko]=ë¼ì›Œë„£ëŠ” HTML 보기 구성 요소
+Comment[lb]=Abettbar HTML-Uweisungskomponent
+Comment[lt]=Įdedamas HTML peržiūros komponentas
+Comment[lv]=IegultÄ HTML skatÄ«Å¡anas komponente
+Comment[mk]=Вгнездлива компонента за гледање HTML
+Comment[mn]=Суулгаж болох HTML харах бүрÑлдхүүн Ñ…ÑÑÑг
+Comment[ms]=Komponen pelihat HTML boleh-serta
+Comment[mt]=Komponent integrat għall-wiri tal-HTML
+Comment[nb]=Inkluderbar komponent for HTML-visning
+Comment[nds]=Inbettbor Kieker-Komponent för HTML
+Comment[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ गरà¥à¤¨ सकिने HTML दृशà¥à¤¯ अवयव
+Comment[nl]=Ingebed HTML-weergavecomponent
+Comment[nn]=Inkluderbart komponent for HTML-vising
+Comment[nso]=Seripa seo se robatsegago sa pono ya HTML
+Comment[oc]=Component visualizador d'HTML encastable
+Comment[pa]=ਸ਼ਾਮਿਲ HTML ਵੇਖਣਯੋਗ ਹਿੱਸਾ
+Comment[pl]=Składnik do przeglądania plików HTML
+Comment[pt]=Componente incorporada para visualizar HTML
+Comment[pt_BR]=Componente integrado de visualização HTML
+Comment[ro]=Componentă înglobată de vizualizare HTML
+Comment[ru]=Ð’Ñтраиваемый компонент проÑмотра HTML
+Comment[rw]=Inyangingo yo kugaragaza HTML ishyirwamo
+Comment[se]=Vuojuhanláhkái HTML-Äájehanoassi
+Comment[sk]=Vložiteľný komponent HTML prehliadaÄ
+Comment[sl]=Integrirani pregled besedila HTML
+Comment[sq]=Komponentë për Shikimin e skedave HTML që mund të ngulitet
+Comment[sr]=Уградива компонента за преглед HTML-а
+Comment[sr@Latn]=Ugradiva komponenta za pregled HTML-a
+Comment[ss]=Incenye yekubuka ye HTML lelalisekako
+Comment[sv]=Inbäddningsbar HTML-visande komponent
+Comment[ta]=உடà¯à®ªà¯Šà®¤à®¿à®•à¯à®•à®µà®²à¯à®² HTML காடà¯à®šà®¿à®•à¯ கூறà¯
+Comment[te]=పొదగదగà±à°— HTML వికà±à°·à°£à°¾à°‚శం
+Comment[tg]=HTML қиÑмати биниш дар дарун Ñохтан
+Comment[th]=ส่วนประà¸à¸­à¸šà¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸ªà¸”งผล HTML ที่à¸à¸±à¸‡à¹„ด้
+Comment[tr]=Gömülebilir HTML görüntüleme aracı
+Comment[tt]=HTML qaraw öçen quşılma komponent
+Comment[uk]=Вбудований компонент "переглÑдач HTML"
+Comment[uz]=Ichiga oʻrnatib boʻladigan HTML koʻruvchi komponent
+Comment[uz@cyrillic]=Ичига ўрнатиб бўладиган HTML кўрувчи компонент
+Comment[ven]=Khomphonente ya HTML yau vhona
+Comment[vi]=Thành phần xem HTML có khả năng nhúng.
+Comment[xh]=Inxenye yemboniselo elungisiweyo ye HTML
+Comment[zh_CN]=å¯åµŒå…¥çš„ HTML 查看部件
+Comment[zh_HK]=å¯åµŒå…¥çš„ HTML 檢視元件
+Comment[zh_TW]=å¯åµŒå…¥çš„ HTML 檢視元件
+Comment[zu]= Ilunga lokubuka le-HTML Eshuthekiwe
+MimeType=text/html;text/xml;application/xhtml+xml;
+Icon=konqueror
+Name=KHTML
+Name[hi]=केà¤à¤šà¤Ÿà¥€à¤à¤®à¤à¤² (KHTML)
+Name[te]=కెహెచౠటి ఎమౠఎలà±
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+X-TDE-Library=libtdehtmlpart
+InitialPreference=10
diff --git a/tdehtml/tdehtml.rc b/tdehtml/tdehtml.rc
new file mode 100644
index 000000000..af41c8246
--- /dev/null
+++ b/tdehtml/tdehtml.rc
@@ -0,0 +1,16 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="tdehtmlpart" version="5">
+<MenuBar>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="selectAll" />
+ <Separator />
+ <Action name="find" />
+ <Action name="findNext" />
+ <Action name="findPrevious" />
+ <Action name="findAheadText" />
+ <Action name="findAheadLink" />
+ </Menu>
+</MenuBar>
+<ActionProperties>
+</ActionProperties>
+</kpartgui>
diff --git a/tdehtml/tdehtml_browser.rc b/tdehtml/tdehtml_browser.rc
new file mode 100644
index 000000000..02220dc51
--- /dev/null
+++ b/tdehtml/tdehtml_browser.rc
@@ -0,0 +1,49 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="tdehtmlpart" version="19">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="saveBackground" />
+ <Action name="saveDocument" />
+ <Action name="saveFrame" />
+ <Separator />
+ <Action name="printFrame" group="print" />
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="selectAll" />
+ <Separator />
+ <Action name="find" />
+ <Action name="findNext" />
+ <Action name="findPrevious" />
+ <Action name="findAheadText" />
+ <Action name="findAheadLink" />
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="incFontSizes" />
+ <Action name="decFontSizes" />
+ <Action name="viewDocumentSource" />
+ <Action name="viewPageInfo" />
+ <Action name="security" />
+ <Action name="setEncoding" />
+ <Action name="useStylesheet" />
+ <ActionList name="debugScriptList" />
+
+<!--
+ <Separator />
+ <Action name="debugRenderTree" />
+ <Action name="debugDOMTree" />
+-->
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="find" />
+ <Separator />
+ <Action name="incFontSizes" />
+ <Action name="decFontSizes" />
+ <ActionList name="loadImages" />
+ <Separator />
+ <Action name="security" />
+</ToolBar>
+<ActionProperties>
+ <Action shortcut="F7" name="caretMode" />
+</ActionProperties>
+</kpartgui>
diff --git a/tdehtml/tdehtml_caret.cpp b/tdehtml/tdehtml_caret.cpp
new file mode 100644
index 000000000..b5d5185f0
--- /dev/null
+++ b/tdehtml/tdehtml_caret.cpp
@@ -0,0 +1,2664 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003-2004 Leo Savernik <l.savernik@aon.at>
+ *
+ * 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 "tdehtml_caret_p.h"
+
+#include "html/html_documentimpl.h"
+
+namespace tdehtml {
+
+/** Flags representing the type of advance that has been made.
+ * @param LeftObject a render object was left and an ascent to its parent has
+ * taken place
+ * @param AdvancedToSibling an actual advance to a sibling has taken place
+ * @param EnteredObject a render object was entered by descending into it from
+ * its parent object.
+ */
+enum ObjectAdvanceState {
+ LeftObject = 0x01, AdvancedToSibling = 0x02, EnteredObject = 0x04
+};
+
+/** All possible states that may occur during render object traversal.
+ * @param OutsideDescending outside of the current object, ready to descend
+ * into children
+ * @param InsideDescending inside the current object, descending into
+ * children
+ * @param InsideAscending inside the current object, ascending to parents
+ * @param OutsideAscending outsie the current object, ascending to parents
+ */
+enum ObjectTraversalState {
+ OutsideDescending, InsideDescending, InsideAscending, OutsideAscending
+};
+
+/** Traverses the render object tree in a fine granularity.
+ * @param obj render object
+ * @param trav object traversal state
+ * @param toBegin traverse towards beginning
+ * @param base base render object which this method must not advance beyond
+ * (0 means document)
+ * @param state object advance state (enum ObjectAdvanceState)
+ * @return the render object according to the state. May be the same as \c obj
+ */
+static RenderObject* traverseRenderObjects(RenderObject *obj,
+ ObjectTraversalState &trav, bool toBegin, RenderObject *base,
+ int &state)
+{
+ RenderObject *r;
+ switch (trav) {
+ case OutsideDescending:
+ trav = InsideDescending;
+ break;
+ case InsideDescending:
+ r = toBegin ? obj->lastChild() : obj->firstChild();
+ if (r) {
+ trav = OutsideDescending;
+ obj = r;
+ state |= EnteredObject;
+ } else {
+ trav = InsideAscending;
+ }
+ break;
+ case InsideAscending:
+ trav = OutsideAscending;
+ break;
+ case OutsideAscending:
+ r = toBegin ? obj->previousSibling() : obj->nextSibling();
+ if (r) {
+ trav = OutsideDescending;
+ state |= AdvancedToSibling;
+ } else {
+ r = obj->parent();
+ if (r == base) r = 0;
+ trav = InsideAscending;
+ state |= LeftObject;
+ }
+ obj = r;
+ break;
+ }/*end switch*/
+
+ return obj;
+}
+
+/** Like RenderObject::objectBelow, but confined to stay within \c base.
+ * @param obj render object to begin with
+ * @param trav object traversal state, will be reset within this function
+ * @param base base render object (0: no base)
+ */
+static inline RenderObject *renderObjectBelow(RenderObject *obj, ObjectTraversalState &trav, RenderObject *base)
+{
+ trav = InsideDescending;
+ int state; // we don't need the state, so we don't initialize it
+ RenderObject *r = obj;
+ while (r && trav != OutsideDescending) {
+ r = traverseRenderObjects(r, trav, false, base, state);
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "renderObjectBelow: r " << r << " trav " << trav << endl;
+#endif
+ }
+ trav = InsideDescending;
+ return r;
+}
+
+/** Like RenderObject::objectAbove, but confined to stay within \c base.
+ * @param obj render object to begin with
+ * @param trav object traversal state, will be reset within this function
+ * @param base base render object (0: no base)
+ */
+static inline RenderObject *renderObjectAbove(RenderObject *obj, ObjectTraversalState &trav, RenderObject *base)
+{
+ trav = OutsideAscending;
+ int state; // we don't need the state, so we don't initialize it
+ RenderObject *r = obj;
+ while (r && trav != InsideAscending) {
+ r = traverseRenderObjects(r, trav, true, base, state);
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "renderObjectAbove: r " << r << " trav " << trav << endl;
+#endif
+ }
+ trav = InsideAscending;
+ return r;
+}
+
+/** Checks whether the given inline box matches the IndicatedFlows policy
+ * @param box inline box to test
+ * @return true on match
+ */
+static inline bool isIndicatedInlineBox(InlineBox *box)
+{
+ // text boxes are never indicated.
+ if (box->isInlineTextBox()) return false;
+ RenderStyle *s = box->object()->style();
+ return s->borderLeftWidth() || s->borderRightWidth()
+ || s->borderTopWidth() || s->borderBottomWidth()
+ || s->paddingLeft().value() || s->paddingRight().value()
+ || s->paddingTop().value() || s->paddingBottom().value()
+ // ### Can inline elements have top/bottom margins? Couldn't find
+ // it in the CSS 2 spec, but Mozilla ignores them, so we do, too.
+ || s->marginLeft().value() || s->marginRight().value();
+}
+
+/** Checks whether the given render object matches the IndicatedFlows policy
+ * @param r render object to test
+ * @return true on match
+ */
+static inline bool isIndicatedFlow(RenderObject *r)
+{
+ RenderStyle *s = r->style();
+ return s->borderLeftStyle() != BNONE || s->borderRightStyle() != BNONE
+ || s->borderTopStyle() != BNONE || s->borderBottomStyle() != BNONE
+// || s->paddingLeft().value() || s->paddingRight().value()
+// || s->paddingTop().value() || s->paddingBottom().value()
+// || s->marginLeft().value() || s->marginRight().value()
+ || s->hasClip() || s->hidesOverflow()
+ || s->backgroundColor().isValid() || s->backgroundImage();
+}
+
+/** Advances to the next render object, taking into account the current
+ * traversal state.
+ *
+ * @param r render object
+ * @param trav object traversal state
+ * @param toBegin @p true, advance towards beginning, @p false, advance toward end
+ * @param base base render object which this method must not advance beyond
+ * (0 means document)
+ * @param state object advance state (enum ObjectAdvanceState) (unchanged
+ * on LeafsOnly)
+ * @return a pointer to the render object which we advanced to,
+ * or 0 if the last possible object has been reached.
+ */
+static RenderObject *advanceObject(RenderObject *r,
+ ObjectTraversalState &trav, bool toBegin,
+ RenderObject *base, int &state)
+{
+
+ ObjectTraversalState origtrav = trav;
+ RenderObject *a = traverseRenderObjects(r, trav, toBegin, base, state);
+
+ bool ignoreOutsideDesc = toBegin && origtrav == OutsideAscending;
+
+ // render object and traversal state at which look ahead has been started
+ RenderObject *la = 0;
+ ObjectTraversalState latrav = trav;
+ ObjectTraversalState lasttrav = origtrav;
+
+ while (a) {
+#if DEBUG_CARETMODE > 5
+kdDebug(6200) << "a " << a << " trav " << trav << endl;
+#endif
+ if (a->element()) {
+#if DEBUG_CARETMODE > 4
+kdDebug(6200) << "a " << a << " trav " << trav << " origtrav " << origtrav << " ignoreOD " << ignoreOutsideDesc << endl;
+#endif
+ if (toBegin) {
+
+ switch (origtrav) {
+ case OutsideDescending:
+ if (trav == InsideAscending) return a;
+ if (trav == OutsideDescending) return a;
+ break;
+ case InsideDescending:
+ if (trav == OutsideDescending) return a;
+ // fall through
+ case InsideAscending:
+ if (trav == OutsideAscending) return a;
+ break;
+ case OutsideAscending:
+ if (trav == OutsideAscending) return a;
+ if (trav == InsideAscending && lasttrav == InsideDescending) return a;
+ if (trav == OutsideDescending && !ignoreOutsideDesc) return a;
+ // ignore this outside descending position, as it effectively
+ // demarkates the same position, but remember it in case we fall off
+ // the document.
+ la = a; latrav = trav;
+ ignoreOutsideDesc = false;
+ break;
+ }/*end switch*/
+
+ } else {
+
+ switch (origtrav) {
+ case OutsideDescending:
+ if (trav == InsideAscending) return a;
+ if (trav == OutsideDescending) return a;
+ break;
+ case InsideDescending:
+// if (trav == OutsideDescending) return a;
+ // fall through
+ case InsideAscending:
+// if (trav == OutsideAscending) return a;
+// break;
+ case OutsideAscending:
+ // ### what if origtrav == OA, and immediately afterwards trav
+ // becomes OD? In this case the effective position hasn't changed ->
+ // the caret gets stuck. Otherwise, it apparently cannot happen in
+ // real usage patterns.
+ if (trav == OutsideDescending) return a;
+ if (trav == OutsideAscending) {
+ if (la) return la;
+ // starting lookahead here. Remember old object in case we fall off
+ // the document.
+ la = a; latrav = trav;
+ }
+ break;
+ }/*end switch*/
+
+ }/*end if*/
+ }/*end if*/
+
+ lasttrav = trav;
+ a = traverseRenderObjects(a, trav, toBegin, base, state);
+ }/*wend*/
+
+ if (la) trav = latrav, a = la;
+ return a;
+
+}
+
+/** Check whether the current render object is unsuitable in caret mode handling.
+ *
+ * Some render objects cannot be handled correctly in caret mode. These objects
+ * are therefore considered to be unsuitable. The null object is suitable, as
+ * it denotes reaching the end.
+ * @param r current render object
+ * @param trav current traversal state
+ */
+static inline bool isUnsuitable(RenderObject *r, ObjectTraversalState trav)
+{
+ if (!r) return false;
+ return r->isTableCol() || r->isTableSection() || r->isTableRow()
+ || (r->isText() && static_cast<RenderText *>(r)->inlineTextBoxCount() == 0);
+ ;
+ Q_UNUSED(trav);
+}
+
+/** Advances to the next render object, taking into account the current
+ * traversal state, but skipping render objects which are not suitable for
+ * having placed the caret into them.
+ * @param r render object
+ * @param trav object traversal state (unchanged on LeafsOnly)
+ * @param toBegin @p true, advance towards beginning, @p false, advance toward end
+ * @param base base render object which this method must not advance beyond
+ * (0 means document)
+ * @param state object advance state (enum ObjectAdvanceState) (unchanged
+ * on LeafsOnly)
+ * @return a pointer to the advanced render object or 0 if the last possible
+ * object has been reached.
+ */
+static inline RenderObject *advanceSuitableObject(RenderObject *r,
+ ObjectTraversalState &trav, bool toBegin,
+ RenderObject *base, int &state)
+{
+ do {
+ r = advanceObject(r, trav, toBegin, base, state);
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "after advanceSWP: r " << r << " trav " << trav << " toBegin " << toBegin << endl;
+#endif
+ } while (isUnsuitable(r, trav));
+ return r;
+}
+
+/**
+ * Returns the next leaf node.
+ *
+ * Using this function delivers leaf nodes as if the whole DOM tree
+ * were a linear chain of its leaf nodes.
+ * @param r dom node
+ * @param baseElem base element not to search beyond
+ * @return next leaf node or 0 if there are no more.
+ */
+static NodeImpl *nextLeafNode(NodeImpl *r, NodeImpl *baseElem)
+{
+ NodeImpl *n = r->firstChild();
+ if (n) {
+ while (n) { r = n; n = n->firstChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+ n = r->nextSibling();
+ if (n) {
+ r = n;
+ while (n) { r = n; n = n->firstChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+
+ n = r->parentNode();
+ if (n == baseElem) n = 0;
+ while (n) {
+ r = n;
+ n = r->nextSibling();
+ if (n) {
+ r = n;
+ n = r->firstChild();
+ while (n) { r = n; n = n->firstChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+ n = r->parentNode();
+ if (n == baseElem) n = 0;
+ }/*wend*/
+ return 0;
+}
+
+#if 0 // currently not used
+/** (Not part of the official DOM)
+ * Returns the previous leaf node.
+ *
+ * Using this function delivers leaf nodes as if the whole DOM tree
+ * were a linear chain of its leaf nodes.
+ * @param r dom node
+ * @param baseElem base element not to search beyond
+ * @return previous leaf node or 0 if there are no more.
+ */
+static NodeImpl *prevLeafNode(NodeImpl *r, NodeImpl *baseElem)
+{
+ NodeImpl *n = r->firstChild();
+ if (n) {
+ while (n) { r = n; n = n->firstChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+ n = r->previousSibling();
+ if (n) {
+ r = n;
+ while (n) { r = n; n = n->firstChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+
+ n = r->parentNode();
+ if (n == baseElem) n = 0;
+ while (n) {
+ r = n;
+ n = r->previousSibling();
+ if (n) {
+ r = n;
+ n = r->lastChild();
+ while (n) { r = n; n = n->lastChild(); }
+ return const_cast<NodeImpl *>(r);
+ }/*end if*/
+ n = r->parentNode();
+ if (n == baseElem) n = 0;
+ }/*wend*/
+ return 0;
+}
+#endif
+
+/** Maps a DOM Range position to the corresponding caret position.
+ *
+ * The offset boundary is not checked for validity.
+ * @param node DOM node
+ * @param offset zero-based offset within node
+ * @param r returns render object (may be 0 if DOM node has no render object)
+ * @param r_ofs returns the appropriate offset for the found render object r
+ * @param outside returns true when offset is applied to the outside of
+ * \c r, or false for the inside.
+ * @param outsideEnd return true when the caret position is at the outside end.
+ */
+void /*KDE_NO_EXPORT*/ mapDOMPosToRenderPos(NodeImpl *node, long offset,
+ RenderObject *&r, long &r_ofs, bool &outside, bool &outsideEnd)
+{
+ if (node->nodeType() == Node::TEXT_NODE) {
+ outside = false;
+ outsideEnd = false;
+ r = node->renderer();
+ r_ofs = offset;
+ } else if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::DOCUMENT_NODE) {
+
+ // Though offset points between two children, attach it to the visually
+ // most suitable one (and only there, because the mapping must stay bijective)
+ if (node->firstChild()) {
+ outside = true;
+ NodeImpl *child = offset <= 0 ? node->firstChild()
+ // childNode is expensive
+ : node->childNode((unsigned long)offset);
+ // index was child count or out of bounds
+ bool atEnd = !child;
+#if DEBUG_CARETMODE > 5
+ kdDebug(6200) << "mapDTR: child " << child << "@" << (child ? child->nodeName().string() : TQString::null) << " atEnd " << atEnd << endl;
+#endif
+ if (atEnd) child = node->lastChild();
+
+ r = child->renderer();
+ r_ofs = 0;
+ outsideEnd = atEnd;
+
+ // Outside text nodes most likely stem from a continuation. Seek
+ // the enclosing continued render object and use this one instead.
+ if (r && child->nodeType() == Node::TEXT_NODE) {
+ r = r->parent();
+ RenderObject *o = node->renderer();
+ while (o->continuation() && o->continuation() != r)
+ o = o->continuation();
+ if (!r || o->continuation() != r) {
+ r = child->renderer();
+ }
+ }/*end if*/
+
+ // BRs cause troubles. Returns the previous render object instead,
+ // giving it the attributes outside, outside end.
+ if (r && r->isBR()) {
+ r = r->objectAbove();
+ outsideEnd = true;
+ }/*end if*/
+
+ } else {
+ // Element has no children, treat offset to be inside the node.
+ outside = false;
+ outsideEnd = false;
+ r = node->renderer();
+ r_ofs = 0; // only offset 0 possible
+ }
+
+ } else {
+ r = 0;
+ kdWarning() << k_funcinfo << "Mapping from nodes of type " << node->nodeType()
+ << " not supported!" << endl;
+ }
+}
+
+/** Maps a caret position to the corresponding DOM Range position.
+ *
+ * @param r render object
+ * @param r_ofs offset within render object
+ * @param outside true when offset is interpreted to be on the outside of
+ * \c r, or false if on the inside.
+ * @param outsideEnd true when the caret position is at the outside end.
+ * @param node returns DOM node
+ * @param offset returns zero-based offset within node
+ */
+void /*KDE_NO_EXPORT*/ mapRenderPosToDOMPos(RenderObject *r, long r_ofs,
+ bool outside, bool outsideEnd, NodeImpl *&node, long &offset)
+{
+ node = r->element();
+ Q_ASSERT(node);
+#if DEBUG_CARETMODE > 5
+ kdDebug(6200) << "mapRTD: r " << r << "@" << (r ? r->renderName() : TQString::null) << (r && r->element() ? TQString(".node ") + TQString::number((unsigned)r->element(),16) + "@" + r->element()->nodeName().string() : TQString::null) << " outside " << outside << " outsideEnd " << outsideEnd << endl;
+#endif
+ if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::TEXT_NODE) {
+
+ if (outside) {
+ NodeImpl *parent = node->parent();
+
+ // If this is part of a continuation, use the actual node as the parent,
+ // and the first render child as the node.
+ if (r != node->renderer()) {
+ RenderObject *o = node->renderer();
+ while (o->continuation() && o->continuation() != r)
+ o = o->continuation();
+ if (o->continuation() == r) {
+ parent = node;
+ // ### What if the first render child does not map to a child of
+ // the continued node?
+ node = r->firstChild() ? r->firstChild()->element() : node;
+ }
+ }/*end if*/
+
+ if (!parent) goto inside;
+
+ offset = (long)node->nodeIndex() + outsideEnd;
+ node = parent;
+#if DEBUG_CARETMODE > 5
+ kdDebug(6200) << node << "@" << (node ? node->nodeName().string() : TQString::null) << " offset " << offset << endl;
+#endif
+ } else { // !outside
+inside:
+ offset = r_ofs;
+ }
+
+ } else {
+ offset = 0;
+ kdWarning() << k_funcinfo << "Mapping to nodes of type " << node->nodeType()
+ << " not supported!" << endl;
+ }
+}
+
+/** Make sure the given node is a leaf node. */
+static inline void ensureLeafNode(NodeImpl *&node, NodeImpl *base)
+{
+ if (node && node->hasChildNodes()) node = nextLeafNode(node, base);
+}
+
+/** Converts a caret position to its respective object traversal state.
+ * @param outside whether the caret is outside the object
+ * @param atEnd whether the caret position is at the end
+ * @param toBegin \c true when advancing towards the beginning
+ * @param trav returns the corresponding traversal state
+ */
+static inline void mapRenderPosToTraversalState(bool outside, bool atEnd,
+ bool toBegin, ObjectTraversalState &trav)
+{
+ if (!outside) atEnd = !toBegin;
+ if (!atEnd ^ toBegin)
+ trav = outside ? OutsideDescending : InsideDescending;
+ else
+ trav = outside ? OutsideAscending : InsideAscending;
+}
+
+/** Converts a traversal state to its respective caret position
+ * @param trav object traversal state
+ * @param toBegin \c true when advancing towards the beginning
+ * @param outside whether the caret is outside the object
+ * @param atEnd whether the caret position is at the end
+ */
+static inline void mapTraversalStateToRenderPos(ObjectTraversalState trav,
+ bool toBegin, bool &outside, bool &atEnd)
+{
+ outside = false;
+ switch (trav) {
+ case OutsideDescending: outside = true; // fall through
+ case InsideDescending: atEnd = toBegin; break;
+ case OutsideAscending: outside = true; // fall through
+ case InsideAscending: atEnd = !toBegin; break;
+ }
+}
+
+/** Finds the next node that has a renderer.
+ *
+ * Note that if the initial @p node has a renderer, this will be returned,
+ * regardless of the caret advance policy.
+ * Otherwise, for the next nodes, only leaf nodes are considered.
+ * @param node node to start with, will be updated accordingly
+ * @param offset offset of caret within \c node
+ * @param base base render object which this method must not advance beyond
+ * (0 means document)
+ * @param r_ofs return the caret offset within the returned renderer
+ * @param outside returns whether offset is to be interpreted to the outside
+ * (true) or the inside (false) of the render object.
+ * @param outsideEnd returns whether the end of the outside position is meant
+ * @return renderer or 0 if no following node has a renderer.
+ */
+static RenderObject* findRenderer(NodeImpl *&node, long offset,
+ RenderObject *base, long &r_ofs,
+ bool &outside, bool &outsideEnd)
+{
+ if (!node) return 0;
+ RenderObject *r;
+ mapDOMPosToRenderPos(node, offset, r, r_ofs, outside, outsideEnd);
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "findRenderer: node " << node << " " << (node ? node->nodeName().string() : TQString::null) << " offset " << offset << " r " << r << "[" << (r ? r->renderName() : TQString::null) << "] r_ofs " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd << endl;
+#endif
+ if (r) return r;
+ NodeImpl *baseElem = base ? base->element() : 0;
+ while (!r) {
+ node = nextLeafNode(node, baseElem);
+ if (!node) break;
+ r = node->renderer();
+ if (r) r_ofs = offset;
+ }
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "1r " << r << endl;
+#endif
+ ObjectTraversalState trav;
+ int state; // not used
+ mapRenderPosToTraversalState(outside, outsideEnd, false, trav);
+ if (r && isUnsuitable(r, trav)) {
+ r = advanceSuitableObject(r, trav, false, base, state);
+ mapTraversalStateToRenderPos(trav, false, outside, outsideEnd);
+ if (r) r_ofs = r->minOffset();
+ }
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "2r " << r << endl;
+#endif
+ return r;
+}
+
+/** returns a suitable base element
+ * @param caretNode current node containing caret.
+ */
+static ElementImpl *determineBaseElement(NodeImpl *caretNode)
+{
+ // ### for now, only body is delivered for html documents,
+ // and 0 for xml documents.
+
+ DocumentImpl *doc = caretNode->getDocument();
+ if (!doc) return 0; // should not happen, but who knows.
+
+ if (doc->isHTMLDocument())
+ return static_cast<HTMLDocumentImpl *>(doc)->body();
+
+ return 0;
+}
+
+// == class CaretBox implementation
+
+#if DEBUG_CARETMODE > 0
+void CaretBox::dump(TQTextStream &ts, const TQString &ind) const
+{
+ ts << ind << "b@" << _box;
+
+ if (_box) {
+ ts << "<" << _box->object() << ":" << _box->object()->renderName() << ">";
+ }/*end if*/
+
+ ts << " " << _x << "+" << _y << "+" << _w << "*" << _h;
+
+ ts << " cb@" << cb;
+ if (cb) ts << ":" << cb->renderName();
+
+ ts << " " << (_outside ? (outside_end ? "oe" : "o-") : "i-");
+// ts << endl;
+}
+#endif
+
+// == class CaretBoxLine implementation
+
+#if DEBUG_CARETMODE > 0
+# define DEBUG_ACIB 1
+#else
+# define DEBUG_ACIB DEBUG_CARETMODE
+#endif
+void CaretBoxLine::addConvertedInlineBox(InlineBox *box, SeekBoxParams &sbp) /*KDE_NO_EXPORT*/
+{
+ // Generate only one outside caret box between two elements. If
+ // coalesceOutsideBoxes is true, generating left outside boxes is inhibited.
+ bool coalesceOutsideBoxes = false;
+ CaretBoxIterator lastCoalescedBox;
+ for (; box; box = box->nextOnLine()) {
+#if DEBUG_ACIB
+kdDebug(6200) << "box " << box << endl;
+kdDebug(6200) << "box->object " << box->object() << endl;
+kdDebug(6200) << "x " << box->m_x << " y " << box->m_y << " w " << box->m_width << " h " << box->m_height << " baseline " << box->m_baseline << " ifb " << box->isInlineFlowBox() << " itb " << box->isInlineTextBox() << " rlb " << box->isRootInlineBox() << endl;
+#endif
+ // ### Why the hell can object() ever be 0?!
+ if (!box->object()) continue;
+
+ RenderStyle *s = box->object()->style(box->m_firstLine);
+ // parent style for outside caret boxes
+ RenderStyle *ps = box->parent() && box->parent()->object()
+ ? box->parent()->object()->style(box->parent()->m_firstLine)
+ : s;
+
+ if (box->isInlineFlowBox()) {
+#if DEBUG_ACIB
+kdDebug(6200) << "isinlineflowbox " << box << endl;
+#endif
+ InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(box);
+ bool rtl = ps->direction() == RTL;
+ const TQFontMetrics &pfm = ps->fontMetrics();
+
+ if (flowBox->includeLeftEdge()) {
+ // If this box is to be coalesced with the outside end box of its
+ // predecessor, then check if it is the searched box. If it is, we
+ // substitute the outside end box.
+ if (coalesceOutsideBoxes) {
+ if (sbp.equalsBox(flowBox, true, false)) {
+ sbp.it = lastCoalescedBox;
+ Q_ASSERT(!sbp.found);
+ sbp.found = true;
+ }
+ } else {
+ addCreatedFlowBoxEdge(flowBox, pfm, true, rtl);
+ sbp.check(preEnd());
+ }
+ }/*end if*/
+
+ if (flowBox->firstChild()) {
+#if DEBUG_ACIB
+kdDebug(6200) << "this " << this << " flowBox " << flowBox << " firstChild " << flowBox->firstChild() << endl;
+kdDebug(6200) << "== recursive invocation" << endl;
+#endif
+ addConvertedInlineBox(flowBox->firstChild(), sbp);
+#if DEBUG_ACIB
+kdDebug(6200) << "== recursive invocation end" << endl;
+#endif
+}
+ else {
+ addCreatedFlowBoxInside(flowBox, s->fontMetrics());
+ sbp.check(preEnd());
+ }
+
+ if (flowBox->includeRightEdge()) {
+ addCreatedFlowBoxEdge(flowBox, pfm, false, rtl);
+ lastCoalescedBox = preEnd();
+ sbp.check(lastCoalescedBox);
+ coalesceOutsideBoxes = true;
+ }
+
+ } else if (box->isInlineTextBox()) {
+#if DEBUG_ACIB
+kdDebug(6200) << "isinlinetextbox " << box << (box->object() ? TQString(" contains \"%1\"").arg(TQConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), kMin(box->maxOffset() - box->minOffset(), 15L)).string()) : TQString::null) << endl;
+#endif
+ caret_boxes.append(new CaretBox(box, false, false));
+ sbp.check(preEnd());
+ // coalescing has been interrupted
+ coalesceOutsideBoxes = false;
+
+ } else {
+#if DEBUG_ACIB
+kdDebug(6200) << "some replaced or what " << box << endl;
+#endif
+ // must be an inline-block, inline-table, or any RenderReplaced
+ bool rtl = ps->direction() == RTL;
+ const TQFontMetrics &pfm = ps->fontMetrics();
+
+ if (coalesceOutsideBoxes) {
+ if (sbp.equalsBox(box, true, false)) {
+ sbp.it = lastCoalescedBox;
+ Q_ASSERT(!sbp.found);
+ sbp.found = true;
+ }
+ } else {
+ addCreatedInlineBoxEdge(box, pfm, true, rtl);
+ sbp.check(preEnd());
+ }
+
+ caret_boxes.append(new CaretBox(box, false, false));
+ sbp.check(preEnd());
+
+ addCreatedInlineBoxEdge(box, pfm, false, rtl);
+ lastCoalescedBox = preEnd();
+ sbp.check(lastCoalescedBox);
+ coalesceOutsideBoxes = true;
+ }/*end if*/
+ }/*next box*/
+}
+#undef DEBUG_ACIB
+
+void CaretBoxLine::addCreatedFlowBoxInside(InlineFlowBox *flowBox, const TQFontMetrics &fm) /*KDE_NO_EXPORT*/
+{
+
+ CaretBox *caretBox = new CaretBox(flowBox, false, false);
+ caret_boxes.append(caretBox);
+
+ // afaik an inner flow box can only have the width 0, therefore we don't
+ // have to care for rtl or alignment
+ // ### can empty inline elements have a width? css 2 spec isn't verbose about it
+
+ caretBox->_y += flowBox->baseline() - fm.ascent();
+ caretBox->_h = fm.height();
+}
+
+void CaretBoxLine::addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const TQFontMetrics &fm, bool left, bool rtl) /*KDE_NO_EXPORT*/
+{
+ CaretBox *caretBox = new CaretBox(flowBox, true, !left);
+ caret_boxes.append(caretBox);
+
+ if (left ^ rtl) caretBox->_x -= flowBox->paddingLeft() + flowBox->borderLeft() + 1;
+ else caretBox->_x += caretBox->_w + flowBox->paddingRight() + flowBox->borderRight();
+
+ caretBox->_y += flowBox->baseline() - fm.ascent();
+ caretBox->_h = fm.height();
+ caretBox->_w = 1;
+}
+
+void CaretBoxLine::addCreatedInlineBoxEdge(InlineBox *box, const TQFontMetrics &fm, bool left, bool rtl) /*KDE_NO_EXPORT*/
+{
+ CaretBox *caretBox = new CaretBox(box, true, !left);
+ caret_boxes.append(caretBox);
+
+ if (left ^ rtl) caretBox->_x--;
+ else caretBox->_x += caretBox->_w;
+
+ caretBox->_y += box->baseline() - fm.ascent();
+ caretBox->_h = fm.height();
+ caretBox->_w = 1;
+}
+
+CaretBoxLine *CaretBoxLine::constructCaretBoxLine(CaretBoxLineDeleter *deleter,
+ InlineFlowBox *basicFlowBox, InlineBox *seekBox, bool seekOutside,
+ bool seekOutsideEnd, CaretBoxIterator &iter, RenderObject *seekObject)
+// KDE_NO_EXPORT
+{
+ // Iterate all inline boxes within this inline flow box.
+ // Caret boxes will be created for each
+ // - outside begin of an inline flow box (except for the basic inline flow box)
+ // - outside end of an inline flow box (except for the basic inline flow box)
+ // - inside of an empty inline flow box
+ // - outside begin of an inline box resembling a replaced element
+ // - outside end of an inline box resembling a replaced element
+ // - inline text box
+ // - inline replaced box
+
+ CaretBoxLine *result = new CaretBoxLine(basicFlowBox);
+ deleter->append(result);
+
+ SeekBoxParams sbp(seekBox, seekOutside, seekOutsideEnd, seekObject, iter);
+
+ // iterate recursively, I'm too lazy to do it iteratively
+ result->addConvertedInlineBox(basicFlowBox, sbp);
+
+ if (!sbp.found) sbp.it = result->end();
+
+ return result;
+}
+
+CaretBoxLine *CaretBoxLine::constructCaretBoxLine(CaretBoxLineDeleter *deleter,
+ RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/
+{
+ int _x = cb->xPos();
+ int _y = cb->yPos();
+ int height;
+ int width = 1; // no override is indicated in boxes
+
+ if (outside) {
+
+ RenderStyle *s = cb->element() && cb->element()->parent()
+ && cb->element()->parent()->renderer()
+ ? cb->element()->parent()->renderer()->style()
+ : cb->style();
+ bool rtl = s->direction() == RTL;
+
+ const TQFontMetrics &fm = s->fontMetrics();
+ height = fm.height();
+
+ if (!outsideEnd) {
+ _x--;
+ } else {
+ _x += cb->width();
+ }
+
+ int hl = fm.leading() / 2;
+ int baseline = cb->baselinePosition(false);
+ if (!cb->isReplaced() || cb->style()->display() == BLOCK) {
+ if (!outsideEnd ^ rtl)
+ _y -= fm.leading() / 2;
+ else
+ _y += kMax(cb->height() - fm.ascent() - hl, 0);
+ } else {
+ _y += baseline - fm.ascent() - hl;
+ }
+
+ } else { // !outside
+
+ RenderStyle *s = cb->style();
+ const TQFontMetrics &fm = s->fontMetrics();
+ height = fm.height();
+
+ _x += cb->borderLeft() + cb->paddingLeft();
+ _y += cb->borderTop() + cb->paddingTop();
+
+ // ### regard direction
+ switch (s->textAlign()) {
+ case LEFT:
+ case KHTML_LEFT:
+ case TAAUTO: // ### find out what this does
+ case JUSTIFY:
+ break;
+ case CENTER:
+ case KHTML_CENTER:
+ _x += cb->contentWidth() / 2;
+ break;
+ case KHTML_RIGHT:
+ case RIGHT:
+ _x += cb->contentWidth();
+ break;
+ }/*end switch*/
+ }/*end if*/
+
+ CaretBoxLine *result = new CaretBoxLine;
+ deleter->append(result);
+ result->caret_boxes.append(new CaretBox(_x, _y, width, height, cb,
+ outside, outsideEnd));
+ iter = result->begin();
+ return result;
+}
+
+#if DEBUG_CARETMODE > 0
+void CaretBoxLine::dump(TQTextStream &ts, const TQString &ind) const
+{
+ ts << ind << "cbl: baseFlowBox@" << basefb << endl;
+ TQString ind2 = ind + " ";
+ for (size_t i = 0; i < caret_boxes.size(); i++) {
+ if (i > 0) ts << endl;
+ caret_boxes[i]->dump(ts, ind2);
+ }
+}
+#endif
+
+// == caret mode related helper functions
+
+/** seeks the root line box that is the parent of the given inline box.
+ * @param b given inline box
+ * @param base base render object which not to step over. If \c base's
+ * inline flow box is hit before the root line box, the flow box
+ * is returned instead.
+ * @return the root line box or the base flow box.
+ */
+inline InlineFlowBox *seekBaseFlowBox(InlineBox *b, RenderObject *base = 0)
+{
+ // Seek root line box or base inline flow box, if \c base is interfering.
+ while (b->parent() && b->object() != base) {
+ b = b->parent();
+ }/*wend*/
+ Q_ASSERT(b->isInlineFlowBox());
+ return static_cast<InlineFlowBox *>(b);
+}
+
+/** determines whether the given element is a block level replaced element.
+ */
+inline bool isBlockRenderReplaced(RenderObject *r)
+{
+ return r->isRenderReplaced() && r->style()->display() == BLOCK;
+}
+
+/** determines the caret line box that contains the given position.
+ *
+ * If the node does not map to a render object, the function will snap to
+ * the next suitable render object following it.
+ *
+ * @param node node to begin with
+ * @param offset zero-based offset within node.
+ * @param cblDeleter deleter for caret box lines
+ * @param base base render object which the caret must not be placed beyond.
+ * @param r_ofs adjusted offset within render object
+ * @param caretBoxIt returns an iterator to the caret box that contains the
+ * given position.
+ * @return the determined caret box lineor 0 if either the node is 0 or
+ * there is no inline flow box containing this node. The containing block
+ * will still be set. If it is 0 too, @p node was invalid.
+ */
+static CaretBoxLine* findCaretBoxLine(DOM::NodeImpl *node, long offset,
+ CaretBoxLineDeleter *cblDeleter, RenderObject *base,
+ long &r_ofs, CaretBoxIterator &caretBoxIt)
+{
+ bool outside, outsideEnd;
+ RenderObject *r = findRenderer(node, offset, base, r_ofs, outside, outsideEnd);
+ if (!r) { return 0; }
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== findCaretBoxLine" << endl;
+ kdDebug(6200) << "node " << node << " offset: " << offset << " r " << r->renderName() << "[" << r << "].node " << r->element()->nodeName().string() << "[" << r->element() << "]" << " r_ofs " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd << endl;
+#endif
+
+ // There are two strategies to find the correct line box. (The third is failsafe)
+ // (A) First, if node's renderer is a RenderText, we only traverse its text
+ // runs and return the root line box (saves much time for long blocks).
+ // This should be the case 99% of the time.
+ // (B) Second, we derive the inline flow box directly when the renderer is
+ // a RenderBlock, RenderInline, or blocked RenderReplaced.
+ // (C) Otherwise, we iterate linearly through all line boxes in order to find
+ // the renderer.
+
+ // (A)
+ if (r->isText()) do {
+ RenderText *t = static_cast<RenderText *>(r);
+ int dummy;
+ InlineBox *b = t->findInlineTextBox(offset, dummy, true);
+ // Actually b should never be 0, but some render texts don't have text
+ // boxes, so we insert the last run as an error correction.
+ // If there is no last run, we resort to (B)
+ if (!b) {
+ if (t->m_lines.count() > 0)
+ b = t->m_lines[t->m_lines.count() - 1];
+ else
+ break;
+ }/*end if*/
+ Q_ASSERT(b);
+ outside = false; // text boxes cannot have outside positions
+ InlineFlowBox *baseFlowBox = seekBaseFlowBox(b, base);
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "text-box b: " << b << " baseFlowBox: " << baseFlowBox << (b && b->object() ? TQString(" contains \"%1\"").arg(TQConstString(static_cast<RenderText *>(b->object())->str->s+b->minOffset(), kMin(b->maxOffset() - b->minOffset(), 15L)).string()) : TQString::null) << endl;
+#endif
+#if 0
+ if (t->containingBlock()->isListItem()) dumpLineBoxes(static_cast<RenderFlow *>(t->containingBlock()));
+#endif
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== end findCaretBoxLine (renderText)" << endl;
+#endif
+ return CaretBoxLine::constructCaretBoxLine(cblDeleter, baseFlowBox,
+ b, outside, outsideEnd, caretBoxIt);
+ } while(false);/*end if*/
+
+ // (B)
+ bool isrepl = isBlockRenderReplaced(r);
+ if (r->isRenderBlock() || r->isRenderInline() || isrepl) {
+ RenderFlow *flow = static_cast<RenderFlow *>(r);
+ InlineFlowBox *firstLineBox = isrepl ? 0 : flow->firstLineBox();
+
+ // On render blocks, if we are outside, or have a totally empty render
+ // block, we simply construct a special caret box line.
+ // The latter case happens only when the render block is a leaf object itself.
+ if (isrepl || r->isRenderBlock() && (outside || !firstLineBox)
+ || r->isRenderInline() && !firstLineBox) {
+ #if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== end findCaretBoxLine (box " << (outside ? (outsideEnd ? "outside end" : "outside begin") : "inside") << ")" << endl;
+ #endif
+ Q_ASSERT(r->isBox());
+ return CaretBoxLine::constructCaretBoxLine(cblDeleter,
+ static_cast<RenderBox *>(r), outside, outsideEnd, caretBoxIt);
+ }/*end if*/
+
+ kdDebug(6200) << "firstlinebox " << firstLineBox << endl;
+ InlineFlowBox *baseFlowBox = seekBaseFlowBox(firstLineBox, base);
+ return CaretBoxLine::constructCaretBoxLine(cblDeleter, baseFlowBox,
+ firstLineBox, outside, outsideEnd, caretBoxIt);
+ }/*end if*/
+
+ RenderBlock *cb = r->containingBlock();
+ //if ( !cb ) return 0L;
+ Q_ASSERT(cb);
+
+ // ### which element doesn't have a block as its containing block?
+ // Is it still possible after the RenderBlock/RenderInline merge?
+ if (!cb->isRenderBlock()) {
+ kdWarning() << "containing block is no render block!!! crash imminent" << endl;
+ }/*end if*/
+
+ InlineFlowBox *flowBox = cb->firstLineBox();
+ // (C)
+ // This case strikes when the element is replaced, but neither a
+ // RenderBlock nor a RenderInline
+ if (!flowBox) { // ### utter emergency (why is this possible at all?)
+// flowBox = generateDummyFlowBox(arena, cb, r);
+// if (ibox) *ibox = flowBox->firstChild();
+// outside = outside_end = true;
+
+// kdWarning() << "containing block contains no inline flow boxes!!! crash imminent" << endl;
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== end findCaretBoxLine (2)" << endl;
+#endif
+ return CaretBoxLine::constructCaretBoxLine(cblDeleter, cb,
+ outside, outsideEnd, caretBoxIt);
+ }/*end if*/
+
+ // We iterate the inline flow boxes of the containing block until
+ // we find the given node. This has one major flaw: it is linear, and therefore
+ // painfully slow for really large blocks.
+ for (; flowBox; flowBox = static_cast<InlineFlowBox *>(flowBox->nextLineBox())) {
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "[scan line]" << endl;
+#endif
+
+ // construct a caret line box and stop when the element is contained within
+ InlineFlowBox *baseFlowBox = seekBaseFlowBox(flowBox, base);
+ CaretBoxLine *cbl = CaretBoxLine::constructCaretBoxLine(cblDeleter,
+ baseFlowBox, 0, outside, outsideEnd, caretBoxIt, r);
+#if DEBUG_CARETMODE > 5
+ kdDebug(6200) << cbl->information() << endl;
+#endif
+ if (caretBoxIt != cbl->end()) {
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== end findCaretBoxLine (3)" << endl;
+#endif
+ return cbl;
+ }
+ }/*next flowBox*/
+
+ // no inline flow box found, approximate to nearest following node.
+ // Danger: this is O(n^2). It's only called to recover from
+ // errors, that means, theoretically, never. (Practically, far too often :-( )
+ Q_ASSERT(!flowBox);
+ CaretBoxLine *cbl = findCaretBoxLine(nextLeafNode(node, base ? base->element() : 0), 0, cblDeleter, base, r_ofs, caretBoxIt);
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "=================== end findCaretBoxLine" << endl;
+#endif
+ return cbl;
+}
+
+/** finds the innermost table object @p r is contained within, but no
+ * farther than @p cb.
+ * @param r leaf element to begin with
+ * @param cb bottom element where to stop search at least.
+ * @return the table object or 0 if none found.
+ */
+static inline RenderTable *findTableUpTo(RenderObject *r, RenderFlow *cb)
+{
+ while (r && r != cb && !r->isTable()) r = r->parent();
+ return r && r->isTable() ? static_cast<RenderTable *>(r) : 0;
+}
+
+/** checks whether @p r is a descendant of @p cb, or r == cb
+ */
+static inline bool isDescendant(RenderObject *r, RenderObject *cb)
+{
+ while (r && r != cb) r = r->parent();
+ return r;
+}
+
+/** checks whether the given block contains at least one editable element.
+ *
+ * Warning: This function has linear complexity, and therefore is expensive.
+ * Use it sparingly, and cache the result.
+ * @param part part
+ * @param cb block to be searched
+ * @param table returns the nested table if there is one directly at the beginning
+ * or at the end.
+ * @param fromEnd begin search from end (default: begin from beginning)
+ */
+static bool containsEditableElement(KHTMLPart *part, RenderBlock *cb,
+ RenderTable *&table, bool fromEnd = false)
+{
+ RenderObject *r = cb;
+ if (fromEnd)
+ while (r->lastChild()) r = r->lastChild();
+ else
+ while (r->firstChild()) r = r->firstChild();
+
+ RenderTable *tempTable = 0;
+ table = 0;
+ bool withinCb;
+// int state; // not used
+ ObjectTraversalState trav = InsideDescending;
+ do {
+ bool modWithinCb = withinCb = isDescendant(r, cb);
+
+ // treat cb extra, it would not be considered otherwise
+ if (!modWithinCb) {
+ modWithinCb = true;
+ r = cb;
+ } else
+ tempTable = findTableUpTo(r, cb);
+
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "cee: r " << (r ? r->renderName() : TQString::null) << "@" << r << " cb " << cb << " withinCb " << withinCb << " modWithinCb " << modWithinCb << " tempTable " << tempTable << endl;
+#endif
+ if (r && modWithinCb && r->element() && !isUnsuitable(r, trav)
+ && (part->isCaretMode() || part->isEditable()
+ || r->style()->userInput() == UI_ENABLED)) {
+ table = tempTable;
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "cee: editable" << endl;
+#endif
+ return true;
+ }/*end if*/
+
+// RenderObject *oldr = r;
+// while (r && r == oldr)
+// r = advanceSuitableObject(r, trav, fromEnd, cb->parent(), state);
+ r = fromEnd ? r->objectAbove() : r->objectBelow();
+ } while (r && withinCb);
+ return false;
+}
+
+/** checks whether the given block contains at least one editable child
+ * element, beginning with but excluding @p start.
+ *
+ * Warning: This function has linear complexity, and therefore is expensive.
+ * Use it sparingly, and cache the result.
+ * @param part part
+ * @param cb block to be searched
+ * @param table returns the nested table if there is one directly before/after
+ * the start object.
+ * @param fromEnd begin search from end (default: begin from beginning)
+ * @param start object after which to begin search.
+ */
+static bool containsEditableChildElement(KHTMLPart *part, RenderBlock *cb,
+ RenderTable *&table, bool fromEnd, RenderObject *start)
+{
+ int state = 0;
+ ObjectTraversalState trav = OutsideAscending;
+// kdDebug(6201) << "start: " << start << endl;
+ RenderObject *r = start;
+ do {
+ r = traverseRenderObjects(r, trav, fromEnd, cb->parent(), state);
+ } while(r && !(state & AdvancedToSibling));
+// kdDebug(6201) << "r: " << r << endl;
+ //advanceObject(start, trav, fromEnd, cb->parent(), state);
+// RenderObject *oldr = r;
+// while (r && r == oldr)
+ if (!r) return false;
+
+ if (fromEnd)
+ while (r->firstChild()) r = r->firstChild();
+ else
+ while (r->lastChild()) r = r->lastChild();
+// kdDebug(6201) << "child r: " << r << endl;
+ if (!r) return false;
+
+ RenderTable *tempTable = 0;
+ table = 0;
+ bool withinCb = false;
+ do {
+
+ bool modWithinCb = withinCb = isDescendant(r, cb);
+
+ // treat cb extra, it would not be considered otherwise
+ if (!modWithinCb) {
+ modWithinCb = true;
+ r = cb;
+ } else
+ tempTable = findTableUpTo(r, cb);
+
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "cece: r " << (r ? r->renderName() : TQString::null) << "@" << r << " cb " << cb << " withinCb " << withinCb << " modWithinCb " << modWithinCb << " tempTable " << tempTable << endl;
+#endif
+ if (r && withinCb && r->element() && !isUnsuitable(r, trav)
+ && (part->isCaretMode() || part->isEditable()
+ || r->style()->userInput() == UI_ENABLED)) {
+ table = tempTable;
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "cece: editable" << endl;
+#endif
+ return true;
+ }/*end if*/
+
+ r = fromEnd ? r->objectAbove() : r->objectBelow();
+ } while (withinCb);
+ return false;
+}
+
+// == class LinearDocument implementation
+
+LinearDocument::LinearDocument(KHTMLPart *part, NodeImpl *node, long offset,
+ CaretAdvancePolicy advancePolicy, ElementImpl *baseElem)
+ : node(node), offset(offset), m_part(part),
+ advPol(advancePolicy), base(0)
+{
+ if (node == 0) return;
+
+ if (baseElem) {
+ RenderObject *b = baseElem->renderer();
+ if (b && (b->isRenderBlock() || b->isRenderInline()))
+ base = b;
+ }
+
+ initPreBeginIterator();
+ initEndIterator();
+}
+
+LinearDocument::~LinearDocument()
+{
+}
+
+int LinearDocument::count() const
+{
+ // FIXME: not implemented
+ return 1;
+}
+
+LinearDocument::Iterator LinearDocument::current()
+{
+ return LineIterator(this, node, offset);
+}
+
+LinearDocument::Iterator LinearDocument::begin()
+{
+ NodeImpl *n = base ? base->element() : 0;
+ if (!base) n = node ? node->getDocument() : 0;
+ if (!n) return end();
+
+ n = n->firstChild();
+ if (advPol == LeafsOnly)
+ while (n->firstChild()) n = n->firstChild();
+
+ if (!n) return end(); // must be empty document or empty base element
+ return LineIterator(this, n, n->minOffset());
+}
+
+LinearDocument::Iterator LinearDocument::preEnd()
+{
+ NodeImpl *n = base ? base->element() : 0;
+ if (!base) n = node ? node->getDocument() : 0;
+ if (!n) return preBegin();
+
+ n = n->lastChild();
+ if (advPol == LeafsOnly)
+ while (n->lastChild()) n = n->lastChild();
+
+ if (!n) return preBegin(); // must be empty document or empty base element
+ return LineIterator(this, n, n->maxOffset());
+}
+
+void LinearDocument::initPreBeginIterator()
+{
+ _preBegin = LineIterator(this, 0, 0);
+}
+
+void LinearDocument::initEndIterator()
+{
+ _end = LineIterator(this, 0, 1);
+}
+
+// == class LineIterator implementation
+
+CaretBoxIterator LineIterator::currentBox /*KDE_NO_EXPORT*/;
+long LineIterator::currentOffset /*KDE_NO_EXPORT*/;
+
+LineIterator::LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset)
+ : lines(l)
+{
+// kdDebug(6200) << "LineIterator: node " << node << " offset " << offset << endl;
+ if (!node) { cbl = 0; return; }
+ cbl = findCaretBoxLine(node, offset, &lines->cblDeleter,
+ l->baseObject(), currentOffset, currentBox);
+ // can happen on partially loaded documents
+#if DEBUG_CARETMODE > 0
+ if (!cbl) kdDebug(6200) << "no render object found!" << endl;
+#endif
+ if (!cbl) return;
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "LineIterator: offset " << offset << " outside " << cbl->isOutside() << endl;
+#endif
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << cbl->information() << endl;
+#endif
+ if (currentBox == cbl->end()) {
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "LineIterator: findCaretBoxLine failed" << endl;
+#endif
+ cbl = 0;
+ }/*end if*/
+}
+
+void LineIterator::nextBlock()
+{
+ RenderObject *base = lines->baseObject();
+
+ bool cb_outside = cbl->isOutside();
+ bool cb_outside_end = cbl->isOutsideEnd();
+
+ {
+ RenderObject *r = cbl->enclosingObject();
+
+ ObjectTraversalState trav;
+ int state; // not used
+ mapRenderPosToTraversalState(cb_outside, cb_outside_end, false, trav);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "nextBlock: before adv r" << r << " " << (r ? r->renderName() : TQString::null) << (r && r->isText() ? " contains \"" + TQString(((RenderText *)r)->str->s, QMIN(((RenderText *)r)->str->l,15)) + "\"" : TQString::null) << " trav " << trav << " cb_outside " << cb_outside << " cb_outside_end " << cb_outside_end << endl;
+#endif
+ r = advanceSuitableObject(r, trav, false, base, state);
+ if (!r) {
+ cbl = 0;
+ return;
+ }/*end if*/
+
+ mapTraversalStateToRenderPos(trav, false, cb_outside, cb_outside_end);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "nextBlock: after r" << r << " trav " << trav << " cb_outside " << cb_outside << " cb_outside_end " << cb_outside_end << endl;
+#endif
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "++: r " << r << "[" << (r?r->renderName():TQString::null) << "]" << endl;
+#endif
+
+ RenderBlock *cb;
+
+ // If we hit a block or replaced object, use this as its enclosing object
+ bool isrepl = isBlockRenderReplaced(r);
+ if (r->isRenderBlock() || isrepl) {
+ RenderBox *cb = static_cast<RenderBox *>(r);
+
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter, cb,
+ cb_outside, cb_outside_end, currentBox);
+
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "r->isFlow is cb. continuation @" << cb->continuation() << endl;
+#endif
+ return;
+ } else {
+ cb = r->containingBlock();
+ Q_ASSERT(cb->isRenderBlock());
+ }/*end if*/
+ InlineFlowBox *flowBox = cb->firstLineBox();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "++: flowBox " << flowBox << " cb " << cb << "[" << (cb?cb->renderName()+TQString(".node ")+TQString::number((unsigned)cb->element(),16)+(cb->element()?"@"+cb->element()->nodeName().string():TQString::null):TQString::null) << "]" << endl;
+#endif
+ Q_ASSERT(flowBox);
+ if (!flowBox) { // ### utter emergency (why is this possible at all?)
+ cb_outside = cb_outside_end = true;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter, cb,
+ cb_outside, cb_outside_end, currentBox);
+ return;
+ }
+
+ bool seekOutside = false, seekOutsideEnd = false; // silence gcc uninit warning
+ CaretBoxIterator it;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter,
+ flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
+ }
+}
+
+void LineIterator::prevBlock()
+{
+ RenderObject *base = lines->baseObject();
+
+ bool cb_outside = cbl->isOutside();
+ bool cb_outside_end = cbl->isOutsideEnd();
+
+ {
+ RenderObject *r = cbl->enclosingObject();
+ if (r->isAnonymous() && !cb_outside)
+ cb_outside = true, cb_outside_end = false;
+
+ ObjectTraversalState trav;
+ int state; // not used
+ mapRenderPosToTraversalState(cb_outside, cb_outside_end, true, trav);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "prevBlock: before adv r" << r << " " << (r ? r->renderName() : TQString::null) << (r && r->isText() ? " contains \"" + TQString(((RenderText *)r)->str->s, QMIN(((RenderText *)r)->str->l,15)) + "\"" : TQString::null) << " trav " << trav << " cb_outside " << cb_outside << " cb_outside_end " << cb_outside_end << endl;
+#endif
+ r = advanceSuitableObject(r, trav, true, base, state);
+ if (!r) {
+ cbl = 0;
+ return;
+ }/*end if*/
+
+ mapTraversalStateToRenderPos(trav, true, cb_outside, cb_outside_end);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "prevBlock: after r" << r << " trav " << trav << " cb_outside " << cb_outside << " cb_outside_end " << cb_outside_end << endl;
+#endif
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "--: r " << r << "[" << (r?r->renderName():TQString::null) << "]" << endl;
+#endif
+
+ RenderBlock *cb;
+
+ // If we hit a block, use this as its enclosing object
+ bool isrepl = isBlockRenderReplaced(r);
+// kdDebug(6200) << "isrepl " << isrepl << " isblock " << r->isRenderBlock() << endl;
+ if (r->isRenderBlock() || isrepl) {
+ RenderBox *cb = static_cast<RenderBox *>(r);
+
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter, cb,
+ cb_outside, cb_outside_end, currentBox);
+
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "r->isFlow is cb. continuation @" << cb->continuation() << endl;
+#endif
+ return;
+ } else {
+ cb = r->containingBlock();
+ Q_ASSERT(cb->isRenderBlock());
+ }/*end if*/
+ InlineFlowBox *flowBox = cb->lastLineBox();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "--: flowBox " << flowBox << " cb " << cb << "[" << (cb?cb->renderName()+TQString(".node ")+TQString::number((unsigned)cb->element(),16)+(cb->element()?"@"+cb->element()->nodeName().string():TQString::null):TQString::null) << "]" << endl;
+#endif
+ Q_ASSERT(flowBox);
+ if (!flowBox) { // ### utter emergency (why is this possible at all?)
+ cb_outside = true; cb_outside_end = false;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter, cb,
+ cb_outside, cb_outside_end, currentBox);
+ return;
+ }
+
+ bool seekOutside = false, seekOutsideEnd = false; // silence gcc uninit warning
+ CaretBoxIterator it;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter,
+ flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
+ }
+}
+
+void LineIterator::advance(bool toBegin)
+{
+ InlineFlowBox *flowBox = cbl->baseFlowBox();
+ if (flowBox) {
+ flowBox = static_cast<InlineFlowBox *>(toBegin ? flowBox->prevLineBox() : flowBox->nextLineBox());
+ if (flowBox) {
+ bool seekOutside = false, seekOutsideEnd = false; // silence gcc uninit warning
+ CaretBoxIterator it;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter,
+ flowBox, flowBox->firstChild(), seekOutside, seekOutsideEnd, it);
+ }/*end if*/
+ }/*end if*/
+
+ // if there are no more lines in this block, move towards block to come
+ if (!flowBox) { if (toBegin) prevBlock(); else nextBlock(); }
+
+#if DEBUG_CARETMODE > 3
+ if (cbl) kdDebug(6200) << cbl->information() << endl;
+#endif
+}
+
+// == class EditableCaretBoxIterator implementation
+
+void EditableCaretBoxIterator::advance(bool toBegin)
+{
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "---------------" << k_funcinfo << "toBegin " << toBegin << endl;
+#endif
+ const CaretBoxIterator preBegin = cbl->preBegin();
+ const CaretBoxIterator end = cbl->end();
+
+ CaretBoxIterator lastbox = *this, curbox;
+ bool islastuseable = true; // silence gcc
+ bool iscuruseable;
+ // Assume adjacency of caret boxes. Will be falsified later if applicable.
+ adjacent = true;
+
+#if DEBUG_CARETMODE > 4
+// kdDebug(6200) << "ebit::advance: before: " << (**this)->object() << "@" << (**this)->object()->renderName() << ".node " << (**this)->object()->element() << "[" << ((**this)->object()->element() ? (**this)->object()->element()->nodeName().string() : TQString::null) << "] inline " << (**this)->isInline() << " outside " << (**this)->isOutside() << " outsideEnd " << (**this)->isOutsideEnd() << endl;
+#endif
+
+ if (toBegin) CaretBoxIterator::operator --(); else CaretBoxIterator::operator ++();
+ bool curAtEnd = *this == preBegin || *this == end;
+ curbox = *this;
+ bool atEnd = true;
+ if (!curAtEnd) {
+ iscuruseable = isEditable(curbox, toBegin);
+ if (toBegin) CaretBoxIterator::operator --(); else CaretBoxIterator::operator ++();
+ atEnd = *this == preBegin || *this == end;
+ }
+ while (!curAtEnd) {
+ bool haslast = lastbox != end && lastbox != preBegin;
+ bool hascoming = !atEnd;
+ bool iscominguseable = true; // silence gcc
+
+ if (!atEnd) iscominguseable = isEditable(*this, toBegin);
+ if (iscuruseable) {
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "ebit::advance: " << (*curbox)->object() << "@" << (*curbox)->object()->renderName() << ".node " << (*curbox)->object()->element() << "[" << ((*curbox)->object()->element() ? (*curbox)->object()->element()->nodeName().string() : TQString::null) << "] inline " << (*curbox)->isInline() << " outside " << (*curbox)->isOutside() << " outsideEnd " << (*curbox)->isOutsideEnd() << endl;
+#endif
+
+ CaretBox *box = *curbox;
+ if (box->isOutside()) {
+ // if this caret box represents no inline box, it is an outside box
+ // which has to be considered unconditionally
+ if (!box->isInline()) break;
+
+ if (advpol == VisibleFlows) break;
+
+ // IndicatedFlows and LeafsOnly are treated equally in caret box lines
+
+ InlineBox *ibox = box->inlineBox();
+ // get previous inline box
+ InlineBox *prev = box->isOutsideEnd() ? ibox : ibox->prevOnLine();
+ // get next inline box
+ InlineBox *next = box->isOutsideEnd() ? ibox->nextOnLine() : ibox;
+
+ const bool isprevindicated = !prev || isIndicatedInlineBox(prev);
+ const bool isnextindicated = !next || isIndicatedInlineBox(next);
+ const bool last = haslast && !islastuseable;
+ const bool coming = hascoming && !iscominguseable;
+ const bool left = !prev || prev->isInlineFlowBox() && isprevindicated
+ || (toBegin && coming || !toBegin && last);
+ const bool right = !next || next->isInlineFlowBox() && isnextindicated
+ || (!toBegin && coming || toBegin && last);
+ const bool text2indicated = toBegin && next && next->isInlineTextBox()
+ && isprevindicated
+ || !toBegin && prev && prev->isInlineTextBox() && isnextindicated;
+ const bool indicated2text = !toBegin && next && next->isInlineTextBox()
+ && prev && isprevindicated
+ // ### this code is so broken.
+ /*|| toBegin && prev && prev->isInlineTextBox() && isnextindicated*/;
+#if DEBUG_CARETMODE > 5
+ kdDebug(6200) << "prev " << prev << " haslast " << haslast << " islastuseable " << islastuseable << " left " << left << " next " << next << " hascoming " << hascoming << " iscominguseable " << iscominguseable << " right " << right << " text2indicated " << text2indicated << " indicated2text " << indicated2text << endl;
+#endif
+
+ if (left && right && !text2indicated || indicated2text) {
+ adjacent = false;
+#if DEBUG_CARETMODE > 4
+ kdDebug(6200) << "left && right && !text2indicated || indicated2text" << endl;
+#endif
+ break;
+ }
+
+ } else {
+ // inside boxes are *always* valid
+#if DEBUG_CARETMODE > 4
+if (box->isInline()) {
+ InlineBox *ibox = box->inlineBox();
+ kdDebug(6200) << "inside " << (!ibox->isInlineFlowBox() || static_cast<InlineFlowBox *>(ibox)->firstChild() ? "non-empty" : "empty") << (isIndicatedInlineBox(ibox) ? " indicated" : "") << " adjacent=" << adjacent << endl;
+ }
+#if 0
+ RenderStyle *s = ibox->object()->style();
+ kdDebug(6200) << "bordls " << s->borderLeftStyle()
+ << " bordl " << (s->borderLeftStyle() != BNONE)
+ << " bordr " << (s->borderRightStyle() != BNONE)
+ << " bordt " << (s->borderTopStyle() != BNONE)
+ << " bordb " << (s->borderBottomStyle() != BNONE)
+ << " padl " << s->paddingLeft().value()
+ << " padr " << s->paddingRight().value()
+ << " padt " << s->paddingTop().value()
+ << " padb " << s->paddingBottom().value()
+ // ### Can inline elements have top/bottom margins? Couldn't find
+ // it in the CSS 2 spec, but Mozilla ignores them, so we do, too.
+ << " marl " << s->marginLeft().value()
+ << " marr " << s->marginRight().value()
+ << endl;
+#endif
+#endif
+ break;
+ }/*end if*/
+
+ } else {
+
+ if (!(*curbox)->isOutside()) {
+ // cannot be adjacent anymore
+ adjacent = false;
+ }
+
+ }/*end if*/
+ lastbox = curbox;
+ islastuseable = iscuruseable;
+ curbox = *this;
+ iscuruseable = iscominguseable;
+ curAtEnd = atEnd;
+ if (!atEnd) {
+ if (toBegin) CaretBoxIterator::operator --(); else CaretBoxIterator::operator ++();
+ atEnd = *this == preBegin || *this == end;
+ }/*end if*/
+ }/*wend*/
+
+ *static_cast<CaretBoxIterator *>(this) = curbox;
+#if DEBUG_CARETMODE > 4
+// kdDebug(6200) << "still valid? " << (*this != preBegin && *this != end) << endl;
+#endif
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "---------------" << k_funcinfo << "end " << endl;
+#endif
+}
+
+bool EditableCaretBoxIterator::isEditable(const CaretBoxIterator &boxit, bool fromEnd)
+{
+ Q_ASSERT(boxit != cbl->end() && boxit != cbl->preBegin());
+ CaretBox *b = *boxit;
+ RenderObject *r = b->object();
+#if DEBUG_CARETMODE > 0
+// if (b->isInlineFlowBox()) kdDebug(6200) << "b is inline flow box" << (outside ? " (outside)" : "") << endl;
+ kdDebug(6200) << "isEditable r" << r << ": " << (r ? r->renderName() : TQString::null) << (r && r->isText() ? " contains \"" + TQString(((RenderText *)r)->str->s, QMIN(((RenderText *)r)->str->l,15)) + "\"" : TQString::null) << endl;
+#endif
+ // Must check caret mode or design mode *after* r->element(), otherwise
+ // lines without a backing DOM node get regarded, leading to a crash.
+ // ### check should actually be in InlineBoxIterator
+ NodeImpl *node = r->element();
+ ObjectTraversalState trav;
+ mapRenderPosToTraversalState(b->isOutside(), b->isOutsideEnd(), fromEnd, trav);
+ if (isUnsuitable(r, trav) || !node) {
+ return false;
+ }
+
+ // generally exclude replaced elements with no children from navigation
+ if (!b->isOutside() && r->isRenderReplaced() && !r->firstChild())
+ return false;
+
+ RenderObject *eff_r = r;
+ bool globallyNavigable = m_part->isCaretMode() || m_part->isEditable();
+
+ // calculate the parent element's editability if this inline box is outside.
+ if (b->isOutside() && !globallyNavigable) {
+ NodeImpl *par = node->parent();
+ // I wonder whether par can be 0. It shouldn't be possible if the
+ // algorithm contained no bugs.
+ Q_ASSERT(par);
+ if (par) node = par;
+ eff_r = node->renderer();
+ Q_ASSERT(eff_r); // this is a hard requirement
+ }
+
+ bool result = globallyNavigable || eff_r->style()->userInput() == UI_ENABLED;
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << result << endl;
+#endif
+ return result;
+}
+
+// == class EditableLineIterator implementation
+
+void EditableLineIterator::advance(bool toBegin)
+{
+ CaretAdvancePolicy advpol = lines->advancePolicy();
+ LineIterator lasteditable, lastindicated;
+ bool haslasteditable = false;
+ bool haslastindicated = false;
+ bool uselasteditable = false;
+
+ LineIterator::advance(toBegin);
+ while (cbl) {
+ if (isEditable(*this)) {
+#if DEBUG_CARETMODE > 3
+ kdDebug(6200) << "advance: " << cbl->enclosingObject() << "@" << cbl->enclosingObject()->renderName() << ".node " << cbl->enclosingObject()->element() << "[" << (cbl->enclosingObject()->element() ? cbl->enclosingObject()->element()->nodeName().string() : TQString::null) << "]" << endl;
+#endif
+
+ bool hasindicated = isIndicatedFlow(cbl->enclosingObject());
+ if (hasindicated) {
+ haslastindicated = true;
+ lastindicated = *this;
+ }
+
+ switch (advpol) {
+ case IndicatedFlows:
+ if (hasindicated) goto wend;
+ // fall through
+ case LeafsOnly:
+ if (cbl->isOutside()) break;
+ // fall through
+ case VisibleFlows: goto wend;
+ }/*end switch*/
+
+ // remember rejected editable element
+ lasteditable = *this;
+ haslasteditable = true;
+#if DEBUG_CARETMODE > 4
+ kdDebug(6200) << "remembered lasteditable " << *lasteditable << endl;
+#endif
+ } else {
+
+ // If this element isn't editable, but the last one was, and it was only
+ // rejected because it didn't match the caret advance policy, force it.
+ // Otherwise certain combinations of editable and uneditable elements
+ // could never be reached with some policies.
+ if (haslasteditable) { uselasteditable = true; break; }
+
+ }
+ LineIterator::advance(toBegin);
+ }/*wend*/
+wend:
+
+ if (uselasteditable) *this = haslastindicated ? lastindicated : lasteditable;
+ if (!cbl && haslastindicated) *this = lastindicated;
+}
+
+// == class EditableCharacterIterator implementation
+
+void EditableCharacterIterator::initFirstChar()
+{
+ CaretBox *box = *ebit;
+ InlineBox *b = box->inlineBox();
+ if (_offset == box->maxOffset())
+ peekNext();
+ else if (b && !box->isOutside() && b->isInlineTextBox())
+ _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
+ else
+ _char = -1;
+}
+
+/** returns true when the given caret box is empty, i. e. should not
+ * take place in caret movement.
+ */
+static inline bool isCaretBoxEmpty(CaretBox *box) {
+ if (!box->isInline()) return false;
+ InlineBox *ibox = box->inlineBox();
+ return ibox->isInlineFlowBox()
+ && !static_cast<InlineFlowBox *>(ibox)->firstChild()
+ && !isIndicatedInlineBox(ibox);
+}
+
+EditableCharacterIterator &EditableCharacterIterator::operator ++()
+{
+ _offset++;
+
+ CaretBox *box = *ebit;
+ InlineBox *b = box->inlineBox();
+ long maxofs = box->maxOffset();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "box->maxOffset() " << box->maxOffset() << " box->minOffset() " << box->minOffset() << endl;
+#endif
+ if (_offset == maxofs) {
+#if DEBUG_CARETMODE > 2
+kdDebug(6200) << "_offset == maxofs: " << _offset << " == " << maxofs << endl;
+#endif
+ peekNext();
+ } else if (_offset > maxofs) {
+#if DEBUG_CARETMODE > 2
+kdDebug(6200) << "_offset > maxofs: " << _offset << " > " << maxofs /*<< " _peekNext: " << _peekNext*/ << endl;
+#endif
+ if (/*!_peekNext*/true) {
+ ++ebit;
+ if (ebit == (*_it)->end()) { // end of line reached, go to next line
+ ++_it;
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "++_it" << endl;
+#endif
+ if (_it != _it.lines->end()) {
+ ebit = _it;
+ box = *ebit;
+ b = box->inlineBox();
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "box " << box << " b " << b << " isText " << box->isInlineTextBox() << endl;
+#endif
+
+#if DEBUG_CARETMODE > 3
+ RenderObject *_r = box->object();
+kdDebug(6200) << "_r " << _r << ":" << _r->element()->nodeName().string() << endl;
+#endif
+ _offset = box->minOffset();
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "_offset " << _offset << endl;
+#endif
+ } else {
+ b = 0;
+ _end = true;
+ }/*end if*/
+ goto readchar;
+ }/*end if*/
+ }/*end if*/
+
+ bool adjacent = ebit.isAdjacent();
+#if 0
+ // Jump over element if this one is not a text node.
+ if (adjacent && !(*ebit)->isInlineTextBox()) {
+ EditableCaretBoxIterator copy = ebit;
+ ++ebit;
+ if (ebit != (*_it)->end() && (*ebit)->isInlineTextBox()
+ /*&& (!(*ebit)->isInlineFlowBox()
+ || static_cast<InlineFlowBox *>(*ebit)->)*/)
+ adjacent = false;
+ else ebit = copy;
+ }/*end if*/
+#endif
+ // Jump over empty elements.
+ if (adjacent && !(*ebit)->isInlineTextBox()) {
+ bool noemptybox = true;
+ while (isCaretBoxEmpty(*ebit)) {
+ noemptybox = false;
+ EditableCaretBoxIterator copy = ebit;
+ ++ebit;
+ if (ebit == (*_it)->end()) { ebit = copy; break; }
+ }
+ if (noemptybox) adjacent = false;
+ }/*end if*/
+// _r = (*ebit)->object();
+ /*if (!_it.outside) */_offset = (*ebit)->minOffset() + adjacent;
+ //_peekNext = 0;
+ box = *ebit;
+ b = box->inlineBox();
+ goto readchar;
+ } else {
+readchar:
+ // get character
+ if (b && !box->isOutside() && b->isInlineTextBox() && _offset < b->maxOffset())
+ _char = static_cast<RenderText *>(b->object())->str->s[_offset].unicode();
+ else
+ _char = -1;
+ }/*end if*/
+#if DEBUG_CARETMODE > 2
+kdDebug(6200) << "_offset: " << _offset /*<< " _peekNext: " << _peekNext*/ << " char '" << (char)_char << "'" << endl;
+#endif
+
+#if DEBUG_CARETMODE > 0
+ if (!_end && ebit != (*_it)->end()) {
+ CaretBox *box = *ebit;
+ RenderObject *_r = box->object();
+ kdDebug(6200) << "echit++(1): box " << box << (box && box->isInlineTextBox() ? TQString(" contains \"%1\"").arg(TQConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : TQString::null) << " _r " << (_r ? _r->element()->nodeName().string() : TQString("<nil>")) << endl;
+ }
+#endif
+ return *this;
+}
+
+EditableCharacterIterator &EditableCharacterIterator::operator --()
+{
+ _offset--;
+ //kdDebug(6200) << "--: _offset=" << _offset << endl;
+
+ CaretBox *box = *ebit;
+ CaretBox *_peekPrev = 0;
+ CaretBox *_peekNext = 0;
+ InlineBox *b = box->inlineBox();
+ long minofs = box->minOffset();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "box->maxOffset() " << box->maxOffset() << " box->minOffset() " << box->minOffset() << endl;
+#endif
+ if (_offset == minofs) {
+#if DEBUG_CARETMODE > 2
+kdDebug(6200) << "_offset == minofs: " << _offset << " == " << minofs << endl;
+#endif
+// _peekNext = b;
+ // get character
+ if (b && !box->isOutside() && b->isInlineTextBox())
+ _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
+ else
+ _char = -1;
+
+ //peekPrev();
+ bool do_prev = false;
+ {
+ EditableCaretBoxIterator copy;
+ _peekPrev = 0;
+ do {
+ copy = ebit;
+ --ebit;
+ if (ebit == (*_it)->preBegin()) { ebit = copy; break; }
+ } while (isCaretBoxEmpty(*ebit));
+ // Jump to end of previous element if it's adjacent, and a text box
+ if (ebit.isAdjacent() && ebit != (*_it)->preBegin() && (*ebit)->isInlineTextBox()) {
+ _peekPrev = *ebit;
+ do_prev = true;
+ } else
+ ebit = copy;
+ }
+ if (do_prev) goto prev;
+ } else if (_offset < minofs) {
+prev:
+#if DEBUG_CARETMODE > 2
+kdDebug(6200) << "_offset < minofs: " << _offset << " < " << minofs /*<< " _peekNext: " << _peekNext*/ << endl;
+#endif
+ if (!_peekPrev) {
+ _peekNext = *ebit;
+ --ebit;
+ if (ebit == (*_it)->preBegin()) { // end of line reached, go to previous line
+ --_it;
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "--_it" << endl;
+#endif
+ if (_it != _it.lines->preBegin()) {
+// kdDebug(6200) << "begin from end!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
+ ebit = EditableCaretBoxIterator(_it, true);
+ box = *ebit;
+// RenderObject *r = box->object();
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "box " << box << " b " << box->inlineBox() << " isText " << box->isInlineTextBox() << endl;
+#endif
+ _offset = box->maxOffset();
+// if (!_it.outside) _offset = r->isBR() ? (*ebit)->minOffset() : (*ebit)->maxOffset();
+ _char = -1;
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "echit--(2): box " << box << " b " << box->inlineBox() << (box->isInlineTextBox() ? TQString(" contains \"%1\"").arg(TQConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : TQString::null) << endl;
+#endif
+ } else
+ _end = true;
+ return *this;
+ }/*end if*/
+ }/*end if*/
+
+#if DEBUG_CARETMODE > 0
+ bool adjacent = ebit.isAdjacent();
+ kdDebug(6200) << "adjacent " << adjacent << " _peekNext " << _peekNext << " _peekNext->isInlineTextBox: " << (_peekNext ? _peekNext->isInlineTextBox() : false) << " !((*ebit)->isInlineTextBox): " << (*ebit ? !(*ebit)->isInlineTextBox() : true) << endl;
+#endif
+#if 0
+ // Ignore this box if it isn't a text box, but the previous box was
+ if (adjacent && _peekNext && _peekNext->isInlineTextBox()
+ && !(*ebit)->isInlineTextBox()) {
+ EditableCaretBoxIterator copy = ebit;
+ --ebit;
+ if (ebit == (*_it)->preBegin()) /*adjacent = false;
+ else */ebit = copy;
+ }/*end if*/
+#endif
+#if 0
+ // Jump over empty elements.
+ if (adjacent //&& _peekNext && _peekNext->isInlineTextBox()
+ && !(*ebit)->isInlineTextBox()) {
+ bool noemptybox = true;
+ while (isCaretBoxEmpty(*ebit)) {
+ noemptybox = false;
+ EditableCaretBoxIterator copy = ebit;
+ --ebit;
+ if (ebit == (*_it)->preBegin()) { ebit = copy; break; }
+ else _peekNext = *copy;
+ }
+ if (noemptybox) adjacent = false;
+ }/*end if*/
+#endif
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "(*ebit)->obj " << (*ebit)->object()->renderName() << "[" << (*ebit)->object() << "]" << " minOffset: " << (*ebit)->minOffset() << " maxOffset: " << (*ebit)->maxOffset() << endl;
+#endif
+#if DEBUG_CARETMODE > 3
+ RenderObject *_r = (*ebit)->object();
+kdDebug(6200) << "_r " << _r << ":" << _r->element()->nodeName().string() << endl;
+#endif
+ _offset = (*ebit)->maxOffset();
+// if (!_it.outside) _offset = (*ebit)->maxOffset()/* - adjacent*/;
+#if DEBUG_CARETMODE > 3
+kdDebug(6200) << "_offset " << _offset << endl;
+#endif
+ _peekPrev = 0;
+ } else {
+#if DEBUG_CARETMODE > 0
+kdDebug(6200) << "_offset: " << _offset << " _peekNext: " << _peekNext << endl;
+#endif
+ // get character
+ if (_peekNext && _offset >= box->maxOffset() && _peekNext->isInlineTextBox())
+ _char = static_cast<RenderText *>(_peekNext->object())->text()[_peekNext->minOffset()].unicode();
+ else if (b && _offset < b->maxOffset() && b->isInlineTextBox())
+ _char = static_cast<RenderText *>(b->object())->text()[_offset].unicode();
+ else
+ _char = -1;
+ }/*end if*/
+
+#if DEBUG_CARETMODE > 0
+ if (!_end && ebit != (*_it)->preBegin()) {
+ CaretBox *box = *ebit;
+ kdDebug(6200) << "echit--(1): box " << box << " b " << box->inlineBox() << (box->isInlineTextBox() ? TQString(" contains \"%1\"").arg(TQConstString(static_cast<RenderText *>(box->object())->str->s+box->minOffset(), box->maxOffset() - box->minOffset()).string()) : TQString::null) << endl;
+ }
+#endif
+ return *this;
+}
+
+// == class TableRowIterator implementation
+
+TableRowIterator::TableRowIterator(RenderTable *table, bool fromEnd,
+ RenderTableSection::RowStruct *row)
+ : sec(table, fromEnd)
+{
+ // set index
+ if (*sec) {
+ if (fromEnd) index = (*sec)->grid.size() - 1;
+ else index = 0;
+ }/*end if*/
+
+ // initialize with given row
+ if (row && *sec) {
+ while (operator *() != row)
+ if (fromEnd) operator --(); else operator ++();
+ }/*end if*/
+}
+
+TableRowIterator &TableRowIterator::operator ++()
+{
+ index++;
+
+ if (index >= (int)(*sec)->grid.size()) {
+ ++sec;
+
+ if (*sec) index = 0;
+ }/*end if*/
+ return *this;
+}
+
+TableRowIterator &TableRowIterator::operator --()
+{
+ index--;
+
+ if (index < 0) {
+ --sec;
+
+ if (*sec) index = (*sec)->grid.size() - 1;
+ }/*end if*/
+ return *this;
+}
+
+// == class ErgonomicEditableLineIterator implementation
+
+// some decls
+static RenderTableCell *findNearestTableCellInRow(KHTMLPart *part, int x,
+ RenderTableSection::RowStruct *row, bool fromEnd);
+
+/** finds the cell corresponding to absolute x-coordinate @p x in the given
+ * table.
+ *
+ * If there is no direct cell, or the cell is not accessible, the function
+ * will return the nearest suitable cell.
+ * @param part part containing the document
+ * @param x absolute x-coordinate
+ * @param it table row iterator, will be adapted accordingly as more rows are
+ * investigated.
+ * @param fromEnd @p true to begin search from end and work towards the
+ * beginning
+ * @return the cell, or 0 if no editable cell was found.
+ */
+static inline RenderTableCell *findNearestTableCell(KHTMLPart *part, int x,
+ TableRowIterator &it, bool fromEnd)
+{
+ RenderTableCell *result = 0;
+
+ while (*it) {
+ result = findNearestTableCellInRow(part, x, *it, fromEnd);
+ if (result) break;
+
+ if (fromEnd) --it; else ++it;
+ }/*wend*/
+
+ return result;
+}
+
+/** finds the nearest editable cell around the given absolute x-coordinate
+ *
+ * It will dive into nested tables as necessary to provide seamless navigation.
+ *
+ * If the cell at @p x is not editable, its left neighbor is tried, then its
+ * right neighbor, then the left neighbor's left neighbor etc. If no
+ * editable cell can be found, 0 is returned.
+ * @param part tdehtml part
+ * @param x absolute x-coordinate
+ * @param row table row to be searched
+ * @param fromEnd @p true, begin from end (applies only to nested tables)
+ * @return the found cell or 0 if no editable cell was found
+ */
+static RenderTableCell *findNearestTableCellInRow(KHTMLPart *part, int x,
+ RenderTableSection::RowStruct *row, bool fromEnd)
+{
+ // First pass. Find spatially nearest cell.
+ int n = (int)row->row->size();
+ int i;
+ for (i = 0; i < n; i++) {
+ RenderTableCell *cell = row->row->at(i);
+ if (!cell || (long)cell == -1) continue;
+
+ int absx, absy;
+ cell->absolutePosition(absx, absy, false); // ### position: fixed?
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "i/n " << i << "/" << n << " absx " << absx << " absy " << absy << endl;
+#endif
+
+ // I rely on the assumption that all cells are in ascending visual order
+ // ### maybe this assumption is wrong for bidi?
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "x " << x << " < " << (absx + cell->width()) << "?" << endl;
+#endif
+ if (x < absx + cell->width()) break;
+ }/*next i*/
+ if (i >= n) i = n - 1;
+
+ // Second pass. Find editable cell, beginning with the currently found,
+ // extending to the left, and to the right, alternating.
+ for (int cnt = 0; cnt < 2*n; cnt++) {
+ int index = i - ((cnt >> 1) + 1)*(cnt & 1) + (cnt >> 1)*!(cnt & 1);
+ if (index < 0 || index >= n) continue;
+
+ RenderTableCell *cell = row->row->at(index);
+ if (!cell || (long)cell == -1) continue;
+
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "index " << index << " cell " << cell << endl;
+#endif
+ RenderTable *nestedTable;
+ if (containsEditableElement(part, cell, nestedTable, fromEnd)) {
+
+ if (nestedTable) {
+ TableRowIterator it(nestedTable, fromEnd);
+ while (*it) {
+// kdDebug(6201) << "=== recursive invocation" << endl;
+ cell = findNearestTableCell(part, x, it, fromEnd);
+ if (cell) break;
+ if (fromEnd) --it; else ++it;
+ }/*wend*/
+ }/*end if*/
+
+ return cell;
+ }/*end if*/
+ }/*next i*/
+ return 0;
+}
+
+/** returns the nearest common ancestor of two objects that is a table cell,
+ * a table section, or 0 if not inside a common table.
+ *
+ * If @p r1 and @p r2 belong to the same table, but different sections, @p r1's
+ * section is returned.
+ */
+static RenderObject *commonAncestorTableSectionOrCell(RenderObject *r1,
+ RenderObject *r2)
+{
+ if (!r1 || !r2) return 0;
+ RenderTableSection *sec = 0;
+ int start_depth=0, end_depth=0;
+ // First we find the depths of the two objects in the tree (start_depth, end_depth)
+ RenderObject *n = r1;
+ while (n->parent()) {
+ n = n->parent();
+ start_depth++;
+ }/*wend*/
+ n = r2;
+ while( n->parent()) {
+ n = n->parent();
+ end_depth++;
+ }/*wend*/
+ // here we climb up the tree with the deeper object, until both objects have equal depth
+ while (end_depth > start_depth) {
+ r2 = r2->parent();
+ end_depth--;
+ }/*wend*/
+ while (start_depth > end_depth) {
+ r1 = r1->parent();
+// if (r1->isTableSection()) sec = static_cast<RenderTableSection *>(r1);
+ start_depth--;
+ }/*wend*/
+ // Climb the tree with both r1 and r2 until they are the same
+ while (r1 != r2){
+ r1 = r1->parent();
+ if (r1->isTableSection()) sec = static_cast<RenderTableSection *>(r1);
+ r2 = r2->parent();
+ }/*wend*/
+
+ // At this point, we found the most approximate common ancestor. Now climb
+ // up until the condition of the function return value is satisfied.
+ while (r1 && !r1->isTableCell() && !r1->isTableSection() && !r1->isTable())
+ r1 = r1->parent();
+
+ return r1 && r1->isTable() ? sec : r1;
+}
+
+/** Finds the row that contains the given cell, directly, or indirectly
+ * @param section section to be searched
+ * @param cell table cell
+ * @param row returns the row
+ * @param directCell returns the direct cell that contains @p cell
+ * @return the index of the row.
+ */
+static int findRowInSection(RenderTableSection *section, RenderTableCell *cell,
+ RenderTableSection::RowStruct *&row, RenderTableCell *&directCell)
+{
+ // Seek direct cell
+ RenderObject *r = cell;
+ while (r != section) {
+ if (r->isTableCell()) directCell = static_cast<RenderTableCell *>(r);
+ r = r->parent();
+ }/*wend*/
+
+ // So, and this is really nasty: As we have no indices, we have to do a
+ // linear comparison. Oh, that sucks so much for long tables, you can't
+ // imagine.
+ int n = section->numRows();
+ for (int i = 0; i < n; i++) {
+ row = &section->grid[i];
+
+ // check for cell
+ int m = row->row->size();
+ for (int j = 0; j < m; j++) {
+ RenderTableCell *c = row->row->at(j);
+ if (c == directCell) return i;
+ }/*next j*/
+
+ }/*next i*/
+ Q_ASSERT(false);
+ return -1;
+}
+
+/** finds the table that is the first direct or indirect descendant of @p block.
+ * @param leaf object to begin search from.
+ * @param block object to search to, or 0 to search up to top.
+ * @return the table or 0 if there were none.
+ */
+static inline RenderTable *findFirstDescendantTable(RenderObject *leaf, RenderBlock *block)
+{
+ RenderTable *result = 0;
+ while (leaf && leaf != block) {
+ if (leaf->isTable()) result = static_cast<RenderTable *>(leaf);
+ leaf = leaf->parent();
+ }/*wend*/
+ return result;
+}
+
+/** looks for the table cell the given object @p r is contained within.
+ * @return the table cell or 0 if not contained in any table.
+ */
+static inline RenderTableCell *containingTableCell(RenderObject *r)
+{
+ while (r && !r->isTableCell()) r = r->parent();
+ return static_cast<RenderTableCell *>(r);
+}
+
+inline void ErgonomicEditableLineIterator::calcAndStoreNewLine(
+ RenderBlock *newBlock, bool toBegin)
+{
+ // take the first/last editable element in the found cell as the new
+ // value for the iterator
+ CaretBoxIterator it;
+ cbl = CaretBoxLine::constructCaretBoxLine(&lines->cblDeleter,
+ newBlock, true, toBegin, it);
+#if DEBUG_CARETMODE > 3
+ kdDebug(6201) << cbl->information() << endl;
+#endif
+// if (toBegin) prevBlock(); else nextBlock();
+
+ if (!cbl) {
+ return;
+ }/*end if*/
+
+ EditableLineIterator::advance(toBegin);
+}
+
+void ErgonomicEditableLineIterator::determineTopologicalElement(
+ RenderTableCell *oldCell, RenderObject *newObject, bool toBegin)
+{
+ // When we arrive here, a transition between cells has happened.
+ // Now determine the type of the transition. This can be
+ // (1) a transition from this cell into a table inside this cell.
+ // (2) a transition from this cell into another cell of this table
+
+ TableRowIterator it;
+
+ RenderObject *commonAncestor = commonAncestorTableSectionOrCell(oldCell, newObject);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << " ancestor " << commonAncestor << endl;
+#endif
+
+ // The whole document is treated as a table cell.
+ if (!commonAncestor || commonAncestor->isTableCell()) { // (1)
+
+ RenderTableCell *cell = static_cast<RenderTableCell *>(commonAncestor);
+ RenderTable *table = findFirstDescendantTable(newObject, cell);
+
+#if DEBUG_CARETMODE > 0
+ kdDebug(6201) << "table cell: " << cell << endl;
+#endif
+
+ // if there is no table, we fell out of the previous table, and are now
+ // in some table-less block. Therefore, done.
+ if (!table) return;
+
+ it = TableRowIterator(table, toBegin);
+
+ } else if (commonAncestor->isTableSection()) { // (2)
+
+ RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
+ RenderTableSection::RowStruct *row;
+ int idx = findRowInSection(section, oldCell, row, oldCell);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "table section: row idx " << idx << endl;
+#endif
+
+ it = TableRowIterator(section, idx);
+
+ // advance rowspan rows
+ int rowspan = oldCell->rowSpan();
+ while (*it && rowspan--) {
+ if (toBegin) --it; else ++it;
+ }/*wend*/
+
+ } else {
+ kdError(6201) << "Neither common cell nor section! " << commonAncestor->renderName() << endl;
+ // will crash on uninitialized table row iterator
+ }/*end if*/
+
+ RenderTableCell *cell = findNearestTableCell(lines->m_part, xCoor, it, toBegin);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "findNearestTableCell result: " << cell << endl;
+#endif
+
+ RenderBlock *newBlock = cell;
+ if (!cell) {
+ Q_ASSERT(commonAncestor->isTableSection());
+ RenderTableSection *section = static_cast<RenderTableSection *>(commonAncestor);
+ cell = containingTableCell(section);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "containing cell: " << cell << endl;
+#endif
+
+ RenderTable *nestedTable;
+ bool editableChild = cell && containsEditableChildElement(lines->m_part,
+ cell, nestedTable, toBegin, section->table());
+
+ if (cell && !editableChild) {
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "========= recursive invocation outer =========" << endl;
+#endif
+ determineTopologicalElement(cell, cell->section(), toBegin);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "========= end recursive invocation outer =========" << endl;
+#endif
+ return;
+
+ } else if (cell && nestedTable) {
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "========= recursive invocation inner =========" << endl;
+#endif
+ determineTopologicalElement(cell, nestedTable, toBegin);
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "========= end recursive invocation inner =========" << endl;
+#endif
+ return;
+
+ } else {
+#if DEBUG_CARETMODE > 1
+ kdDebug(6201) << "newBlock is table: " << section->table() << endl;
+#endif
+ RenderObject *r = section->table();
+ int state; // not used
+ ObjectTraversalState trav = OutsideAscending;
+ r = advanceSuitableObject(r, trav, toBegin, lines->baseObject(), state);
+ if (!r) { cbl = 0; return; }
+// if (toBegin) prevBlock(); else nextBlock();
+ newBlock = static_cast<RenderBlock *>(!r || r->isRenderBlock() ? r : r->containingBlock());
+ }/*end if*/
+#if 0
+ } else {
+ // adapt cell so that prevBlock/nextBlock works as expected
+ newBlock = cell;
+ // on forward advancing, we must start from the outside end of the
+ // previous object
+ if (!toBegin) {
+ RenderObject *r = newBlock;
+ int state; // not used
+ ObjectTraversalState trav = OutsideAscending;
+ r = advanceSuitableObject(r, trav, true, lines->advancePolicy(), lines->baseObject(), state);
+ newBlock = static_cast<RenderBlock *>(!r || r->isRenderBlock() ? r : r->containingBlock());
+ }/*end if*/
+#endif
+ }/*end if*/
+
+ calcAndStoreNewLine(newBlock, toBegin);
+}
+
+ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator ++()
+{
+ RenderTableCell *oldCell = containingTableCell(cbl->enclosingObject());
+
+ EditableLineIterator::operator ++();
+ if (*this == lines->end() || *this == lines->preBegin()) return *this;
+
+ RenderTableCell *newCell = containingTableCell(cbl->enclosingObject());
+
+ if (!newCell || newCell == oldCell) return *this;
+
+ determineTopologicalElement(oldCell, newCell, false);
+
+ return *this;
+}
+
+ErgonomicEditableLineIterator &ErgonomicEditableLineIterator::operator --()
+{
+ RenderTableCell *oldCell = containingTableCell(cbl->enclosingObject());
+
+ EditableLineIterator::operator --();
+ if (*this == lines->end() || *this == lines->preBegin()) return *this;
+
+ RenderTableCell *newCell = containingTableCell(cbl->enclosingObject());
+
+ if (!newCell || newCell == oldCell) return *this;
+
+ determineTopologicalElement(oldCell, newCell, true);
+
+ return *this;
+}
+
+// == Navigational helper functions ==
+
+/** seeks the caret box which contains or is the nearest to @p x
+ * @param it line iterator pointing to line to be searched
+ * @param cv caret view context
+ * @param x returns the cv->origX approximation, relatively positioned to the
+ * containing block.
+ * @param absx returns absolute x-coordinate of containing block
+ * @param absy returns absolute y-coordinate of containing block
+ * @return the most suitable caret box
+ */
+static CaretBox *nearestCaretBox(LineIterator &it, CaretViewContext *cv,
+ int &x, int &absx, int &absy)
+{
+ // Find containing block
+ RenderObject *cb = (*it)->containingBlock();
+#if DEBUG_CARETMODE > 4
+ kdDebug(6200) << "nearestCB: cb " << cb << "@" << (cb ? cb->renderName() : "") << endl;
+#endif
+
+ if (cb) cb->absolutePosition(absx, absy);
+ else absx = absy = 0;
+
+ // Otherwise find out in which inline box the caret is to be placed.
+
+ // this horizontal position is to be approximated
+ x = cv->origX - absx;
+ CaretBox *caretBox = 0; // Inline box containing the caret
+// NodeImpl *lastnode = 0; // node of previously checked render object.
+ int xPos; // x-coordinate of current inline box
+ int oldXPos = -1; // x-coordinate of last inline box
+ EditableCaretBoxIterator fbit = it;
+#if DEBUG_CARETMODE > 0
+/* if (it.linearDocument()->advancePolicy() != LeafsOnly)
+ kdWarning() << "nearestInlineBox is only prepared to handle the LeafsOnly advance policy" << endl;*/
+// kdDebug(6200) << "*fbit = " << *fbit << endl;
+#endif
+ // Iterate through all children
+ for (CaretBox *b; fbit != (*it)->end(); ++fbit) {
+ b = *fbit;
+
+#if DEBUG_CARETMODE > 0
+// RenderObject *r = b->object();
+// if (b->isInlineFlowBox()) kdDebug(6200) << "b is inline flow box" << endl;
+// kdDebug(6200) << "approximate r" << r << ": " << (r ? r->renderName() : TQString::null) << (r && r->isText() ? " contains \"" + TQString(((RenderText *)r)->str->s, ((RenderText *)r)->str->l) + "\"" : TQString::null) << endl;
+#endif
+ xPos = b->xPos();
+
+ // the caret is before this box
+ if (x < xPos) {
+ // snap to nearest box
+ if (oldXPos < 0 || x - (oldXPos + caretBox->width()) > xPos - x) {
+ caretBox = b; // current box is nearer
+ }/*end if*/
+ break; // Otherwise, preceding box is implicitly used
+ }
+
+ caretBox = b;
+
+ // the caret is within this box
+ if (x >= xPos && x < xPos + caretBox->width())
+ break;
+ oldXPos = xPos;
+
+ // the caret can only be after the last box which is automatically
+ // contained in caretBox when we fall out of the loop.
+ }/*next fbit*/
+
+ return caretBox;
+}
+
+/** moves the given iterator to the beginning of the next word.
+ *
+ * If the end is reached, the iterator will be positioned there.
+ * @param it character iterator to be moved
+ */
+static void moveItToNextWord(EditableCharacterIterator &it)
+{
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "%%%%%%%%%%%%%%%%%%%%% moveItToNextWord" << endl;
+#endif
+ EditableCharacterIterator copy;
+ while (!it.isEnd() && !(*it).isSpace() && !(*it).isPunct()) {
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "reading1 '" << (*it).latin1() << "'" << endl;
+#endif
+ copy = it;
+ ++it;
+ }
+
+ if (it.isEnd()) {
+ it = copy;
+ return;
+ }/*end if*/
+
+ while (!it.isEnd() && ((*it).isSpace() || (*it).isPunct())) {
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "reading2 '" << (*it).latin1() << "'" << endl;
+#endif
+ copy = it;
+ ++it;
+ }
+
+ if (it.isEnd()) it = copy;
+}
+
+/** moves the given iterator to the beginning of the previous word.
+ *
+ * If the beginning is reached, the iterator will be positioned there.
+ * @param it character iterator to be moved
+ */
+static void moveItToPrevWord(EditableCharacterIterator &it)
+{
+ if (it.isEnd()) return;
+
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "%%%%%%%%%%%%%%%%%%%%% moveItToPrevWord" << endl;
+#endif
+ EditableCharacterIterator copy;
+
+ // Jump over all space and punctuation characters first
+ do {
+ copy = it;
+ --it;
+#if DEBUG_CARETMODE > 2
+ if (!it.isEnd()) kdDebug(6200) << "reading1 '" << (*it).latin1() << "'" << endl;
+#endif
+ } while (!it.isEnd() && ((*it).isSpace() || (*it).isPunct()));
+
+ if (it.isEnd()) {
+ it = copy;
+ return;
+ }/*end if*/
+
+ do {
+ copy = it;
+ --it;
+#if DEBUG_CARETMODE > 0
+ if (!it.isEnd()) kdDebug(6200) << "reading2 '" << (*it).latin1() << "' (" << (int)(*it).latin1() << ") box " << it.caretBox() << endl;
+#endif
+ } while (!it.isEnd() && !(*it).isSpace() && !(*it).isPunct());
+
+ it = copy;
+#if DEBUG_CARETMODE > 1
+ if (!it.isEnd()) kdDebug(6200) << "effective '" << (*it).latin1() << "' (" << (int)(*it).latin1() << ") box " << it.caretBox() << endl;
+#endif
+}
+
+/** moves the iterator by one page.
+ * @param ld linear document
+ * @param it line iterator, will be updated accordingly
+ * @param mindist minimum distance in pixel the iterator should be moved
+ * (if possible)
+ * @param next @p true, move downward, @p false move upward
+ */
+static void moveIteratorByPage(LinearDocument &ld,
+ ErgonomicEditableLineIterator &it, int mindist, bool next)
+{
+ // ### This whole routine plainly sucks. Use an inverse strategie for pgup/pgdn.
+
+ if (it == ld.end() || it == ld.preBegin()) return;
+
+ ErgonomicEditableLineIterator copy = it;
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << " mindist: " << mindist << endl;
+#endif
+
+ CaretBoxLine *cbl = *copy;
+ int absx = 0, absy = 0;
+
+ RenderBlock *lastcb = cbl->containingBlock();
+ Q_ASSERT(lastcb->isRenderBlock());
+ lastcb->absolutePosition(absx, absy, false); // ### what about fixed?
+
+ int lastfby = cbl->begin().data()->yPos();
+ int lastheight = 0;
+ int rescue = 1000; // ### this is a hack to keep stuck carets from hanging the ua
+ do {
+ if (next) ++copy; else --copy;
+ if (copy == ld.end() || copy == ld.preBegin()) break;
+
+ cbl = *copy;
+ RenderBlock *cb = cbl->containingBlock();
+
+ int diff = 0;
+ // ### actually flowBox->yPos() should suffice, but this is not ported
+ // over yet from WebCore
+ int fby = cbl->begin().data()->yPos();
+ if (cb != lastcb) {
+ if (next) {
+ diff = absy + lastfby + lastheight;
+ cb->absolutePosition(absx, absy, false); // ### what about fixed?
+ diff = absy - diff + fby;
+ lastfby = 0;
+ } else {
+ diff = absy;
+ cb->absolutePosition(absx, absy, false); // ### what about fixed?
+ diff -= absy + fby + lastheight;
+ lastfby = fby - lastheight;
+ }/*end if*/
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "absdiff " << diff << endl;
+#endif
+ } else {
+ diff = kAbs(fby - lastfby);
+ }/*end if*/
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "cbl->begin().data()->yPos(): " << fby << " diff " << diff << endl;
+#endif
+
+ mindist -= diff;
+
+ lastheight = kAbs(fby - lastfby);
+ lastfby = fby;
+ lastcb = cb;
+ it = copy;
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << " mindist: " << mindist << endl;
+#endif
+ // trick: actually the distance is always one line short, but we cannot
+ // calculate the height of the first line (### WebCore will make it better)
+ // Therefore, we simply approximate that excess line by using the last
+ // caluculated line height.
+ } while (mindist - lastheight > 0 && --rescue);
+}
+
+
+}/*end namespace*/
diff --git a/tdehtml/tdehtml_caret_p.h b/tdehtml/tdehtml_caret_p.h
new file mode 100644
index 000000000..729f4d8ba
--- /dev/null
+++ b/tdehtml/tdehtml_caret_p.h
@@ -0,0 +1,1109 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2003-2004 Leo Savernik <l.savernik@aon.at>
+ *
+ * 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 KHTML_CARET_P_H
+#define KHTML_CARET_P_H
+
+#include "rendering/render_table.h"
+
+#include <tqvaluevector.h>
+
+#define DEBUG_CARETMODE 0
+
+class TQFontMetrics;
+
+namespace DOM {
+ class NodeImpl;
+ class ElementImpl;
+}
+
+namespace tdehtml {
+
+/** caret advance policy.
+ *
+ * Used to determine which elements are taken into account when the caret is
+ * advanced. Later policies pose refinements of all former
+ * policies.
+ * @param LeafsOnly advance from leave render object to leaf render object
+ * (It will allow outside flow positions if a flow wouldn't be reachable
+ * otherwise).
+ * @param IndicatedFlows place caret also at the beginning/end of flows
+ * that have at least one visible border at any side.
+ * (It will allow not indicated flow positions if a flow wouldn't
+ * be reachable otherwise).
+ * @param VisibleFlows place caret also at the beginning/end of any flow
+ * that has a renderer.
+ */
+enum CaretAdvancePolicy {
+ LeafsOnly, IndicatedFlows, VisibleFlows
+};
+
+/** contextual information about the caret which is related to the view.
+ * An object of this class is only instantiated when it is needed.
+ */
+struct CaretViewContext {
+ int freqTimerId; // caret blink frequency timer id
+ int x, y; // caret position in viewport coordinates
+ // (y specifies the top, not the baseline)
+ int width; // width of caret in pixels
+ int height; // height of caret in pixels
+ bool visible; // true if currently visible.
+ bool displayed; // true if caret is to be displayed at all.
+ bool caretMoved; // set to true once caret has been moved in page
+ // how to display the caret when view is not focused
+ KHTMLPart::CaretDisplayPolicy displayNonFocused;
+
+ /** For natural traversal of lines, the original x position is saved, and
+ * the actual x is set to the first character whose x position is
+ * greater than origX.
+ *
+ * origX is reset to x whenever the caret is moved horizontally or placed
+ * by the mouse.
+ */
+ int origX;
+
+ bool keyReleasePending; // true if keypress under caret mode awaits
+ // corresponding release event
+ CaretViewContext() : freqTimerId(-1), x(0), y(0), width(1), height(16),
+ visible(true), displayed(false), caretMoved(false),
+ displayNonFocused(KHTMLPart::CaretInvisible), origX(0),
+ keyReleasePending(false)
+ {}
+};
+
+/** contextual information about the editing state.
+ * An object of this class is only instantiated when it is needed.
+ */
+struct EditorContext {
+ bool override; // true if typed characters should override
+ // the existing ones.
+
+ EditorContext() : override(false)
+ {}
+};
+
+class LinearDocument;
+
+/**
+ * Stores objects of a certain type, and calls delete on each of them
+ * when this data structure is destroyed.
+ *
+ * As this structure merely consists of a vector of pointers, all objects
+ * allocated can be traversed as seen fit.
+ *
+ * @author Leo Savernik
+ * @since 3.3
+ * @internal
+ */
+template<class T> class MassDeleter : public TQValueVector<T *> {
+public:
+ MassDeleter(size_t reserved = 1) { this->reserve(reserved); }
+ ~MassDeleter()
+ {
+ typename TQValueVector<T *>::Iterator nd = this->end();
+ for (typename TQValueVector<T *>::Iterator it = this->begin(); it != nd; ++it)
+ delete *it;
+ }
+};
+
+class CaretBoxLine;
+
+/**
+ * Represents a rectangular box within which the caret is located.
+ *
+ * The caret box serves as a wrapper for inline boxes of all kind. It either
+ * wraps an InlineBox, InlineTextBox, or InlineFlowBox, or if no such boxes
+ * exist for a certain context, it contains the relevant information directly.
+ *
+ * This class will be constructed whenever a caret position has to be described.
+ * @since 3.3
+ * @author Leo Savernik
+ * @internal
+ */
+class CaretBox {
+protected:
+ InlineBox *_box; // associated inline box if available.
+ short _w; // width of box in pixels
+ int _h; // height of box in pixels
+ int _x; // x coordinate relative to containing block
+ int _y; // y coordinate relative to containing block
+ RenderBox *cb; // containing block
+ bool _outside:1; // true when representing the outside of the element
+ bool outside_end:1; // at ending outside of element rather than at beginning
+ // 29 bits unused
+
+public:
+ /** empty constructor for later assignment */
+ CaretBox() {}
+ /** initializes the caret box from the given inline box */
+ CaretBox(InlineBox *ibox, bool outside, bool outsideEnd) : _box(ibox),
+ _w((short)ibox->width()), _h(ibox->height()), _x(ibox->xPos()),
+ _y(ibox->yPos()), cb(0), _outside(outside), outside_end(outsideEnd)
+ {
+ RenderObject *r = ibox->object();
+ if (r) cb = r->containingBlock();
+ }
+ /** initializes the caret box from scratch */
+ CaretBox(int x, int y, int w, int h, RenderBox *cb, bool outside, bool outsideEnd) :
+ _box(0), _w((short)w), _h(h), _x(x), _y(y), cb(cb), _outside(outside),
+ outside_end(outsideEnd)
+ {}
+
+ int width() const { return _w; }
+ int height() const { return _h; }
+ int xPos() const { return _x; }
+ int yPos() const { return _y; }
+ RenderBox *enclosingObject() const { return cb; }
+ InlineBox *inlineBox() const { return _box; }
+
+ /** returns the containing block of this caret box. If the caret box
+ * resembles a block itself, its containing block is returned.
+ */
+ RenderBlock *containingBlock() const { return _box ? static_cast<RenderBlock *>(cb) : cb->containingBlock(); }
+
+ /** returns the replaced render object if this caret box represents one,
+ * 0 otherwise.
+ */
+
+
+ /** returns true if this caret box represents an inline element, or text box,
+ * otherwise false.
+ */
+ bool isInline() const { return _box; }
+ /** returns true if this caret box represents an inline text box.
+ */
+ bool isInlineTextBox() const { return _box && _box->isInlineTextBox(); }
+ /** returns true if this caret box represents a line break
+ */
+ bool isLineBreak() const
+ {
+ return _box && _box->object() && _box->object()->isBR();
+ }
+ /** returns true when this caret box represents an ouside position of an
+ * element.
+ */
+ bool isOutside() const { return _outside; }
+ /** returns the position at which the outside is targeted at.
+ *
+ * This method's return value is meaningless if isOutside() is not true.
+ * @return true if the outside end is meant, false if the outside beginning
+ * is meant.
+ */
+ bool isOutsideEnd() const { return outside_end; }
+ /** returns the associated render object. */
+ RenderObject *object() const { return _box ? _box->object() : cb; }
+
+ /** returns the minimum offset for this caret box.
+ */
+ long minOffset() const { return _box && !isLineBreak() ? _box->minOffset() : 0; }
+ /** returns the maximum offset for this caret box.
+ */
+ long maxOffset() const { return _box && !isLineBreak() ? _box->maxOffset() : 0; }
+
+#if DEBUG_CARETMODE > 0
+ void dump(TQTextStream &ts, const TQString &ind) const;
+#endif
+
+ friend class CaretBoxLine;
+};
+
+typedef MassDeleter<CaretBox> CaretBoxDeleter;
+
+/**
+ * Iterates over the elements of a caret box line.
+ *
+ * @author Leo Savernik
+ * @internal
+ * @since 3.3
+ */
+class CaretBoxIterator {
+protected:
+ CaretBoxLine *cbl; // associated caret box line
+ int index; // current index
+
+public:
+ // Let standard constructor/copy constructor/destructor/assignment operator
+ // be defined by the compiler. They do exactly what we want.
+
+ bool operator ==(const CaretBoxIterator &it) const
+ {
+ return cbl == it.cbl && index == it.index;
+ }
+
+ bool operator !=(const CaretBoxIterator &it) const
+ {
+ return !operator ==(it);
+ }
+
+ /** returns the current caret box.
+ * @return current caret box
+ */
+ CaretBox *data() const;
+ /** shortcut for \c data
+ * @return current caret box
+ */
+ CaretBox *operator *() const { return data(); }
+
+ /** increments the iterator to point to the next caret box.
+ */
+ CaretBoxIterator &operator ++() { index++; return *this; }
+ /** decrements the iterator to point to the previous caret box.
+ */
+ CaretBoxIterator &operator --() { index--; return *this; }
+
+ friend class CaretBoxLine;
+ friend class EditableCaretBoxIterator;
+};
+
+/**
+ * Resembles a line consisting of caret boxes.
+ *
+ * To the contrary of InlineFlowBoxes which are nested as needed to map the
+ * DOM to the rendered representation, it is sufficient for caret navigation
+ * to provide a linear list of unnested caret boxes.
+ *
+ * \code
+ * Example: The document fragment <p>a <i><b>c</b> f</i> g</p> will be
+ * represented by three caret box lines which each one consists of caret boxes
+ * as follows:
+ * CaretBoxLine 1:
+ * CaretBox(cb=<p>, _box=0, _outside=true, outside_end=false)
+ * CaretBoxLine 2:
+ * CaretBox(cb=<p>, _box=InlineTextBox("a "), _outside=false)
+ * CaretBox(cb=<p>, _box=InlineFlowBox(<i>), _outside=true, outside_end=false)
+ * CaretBox(cb=<p>, _box=InlineFlowBox(<b>), _outside=true, outside_end=false)
+ * CaretBox(cb=<p>, _box=InlineTextBox("c"), _outside=false)
+ * CaretBox(cb=<p>, _box=InlineFlowBox(<b>), _outside=true, outside_end=true)
+ * CaretBox(cb=<p>, _box=InlineTextBox(" f"), _outside=false)
+ * CaretBox(cb=<p>, _box=InlineFlowBox(<i>), _outside=true, outside_end=true)
+ * CaretBox(cb=<p>, _box=InlineTextBox(" g"), _outside=true, outside_end=true)
+ * CaretBoxLine 3:
+ * CaretBox(cb=<p>, _box=0, _outside=true, outside_end=true)
+ * \endcode
+ */
+class CaretBoxLine {
+protected:
+ CaretBoxDeleter caret_boxes;
+ // base flow box which caret boxes have been constructed for
+ InlineFlowBox *basefb;
+
+ CaretBoxLine() : caret_boxes(8), basefb(0) {}
+ CaretBoxLine(InlineFlowBox *basefb) : caret_boxes(8), basefb(basefb) {}
+public:
+#if DEBUG_CARETMODE > 3
+ ~CaretBoxLine() { kdDebug(6200) << k_funcinfo << "called" << endl; }
+#endif
+
+ CaretBoxIterator begin()
+ {
+ CaretBoxIterator it;
+ it.cbl = this;
+ it.index = 0;
+ return it;
+ }
+ CaretBoxIterator end()
+ {
+ CaretBoxIterator it;
+ it.cbl = this;
+ it.index = caret_boxes.size();
+ return it;
+ }
+ CaretBoxIterator preBegin()
+ {
+ CaretBoxIterator it;
+ it.cbl = this;
+ it.index = -1;
+ return it;
+ }
+ CaretBoxIterator preEnd()
+ {
+ CaretBoxIterator it;
+ it.cbl = this;
+ it.index = caret_boxes.size() - 1;
+ return it;
+ }
+
+ /** returns the base inline flow box which the caret boxes of this
+ * caret box line have been constructed from.
+ *
+ * This is generally a root line box, but may be an inline flow box when the
+ * base is restricted to an inline element.
+ */
+ InlineFlowBox *baseFlowBox() const { return basefb; }
+
+ /** returns the containing block */
+ RenderBlock *containingBlock() const { return caret_boxes[0]->containingBlock(); }
+ /** returns the enclosing object */
+ RenderBox *enclosingObject() const { return caret_boxes[0]->enclosingObject(); }
+
+ /** returns whether this caret box line is outside.
+ * @return true if this caret box represents an outside position of this
+ * line box' containing block, false otherwise.
+ */
+ bool isOutside() const
+ {
+ const CaretBox *cbox = caret_boxes[0];
+ return !cbox->isInline() && cbox->isOutside();
+ }
+
+ /** returns whether this caret box line is at the outside end.
+ *
+ * The result cannot be relied upon unless isOutside() returns true.
+ */
+ bool isOutsideEnd() const { return caret_boxes[0]->isOutsideEnd(); }
+
+ /** constructs a new caret box line out of the given inline flow box
+ * @param deleter deleter which handles alloc+dealloc of the object
+ * @param baseFlowBox basic flow box which to create a caret line box from
+ * @param seekBox seek this box within the constructed line
+ * @param seekOutside denoting whether position is outside of seekBox
+ * @param seekOutsideEnd whether at the outside end of seekBox
+ * @param iter returns an iterator that corresponds to seekBox. If no suitable
+ * caret box exists, it will return end()
+ * @param seekObject seek this render object within the constructed line.
+ * It will only be regarded if \c seekBox is 0. \c iter will then point
+ * to the first caret box whose render object matches.
+ */
+ static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
+ InlineFlowBox *baseFlowBox, InlineBox *seekBox, bool seekOutside,
+ bool seekOutsideEnd, CaretBoxIterator &iter,
+ RenderObject *seekObject = 0) /*KDE_NO_EXPORT*/;
+
+ /** constructs a new caret box line for the given render block.
+ * @param deleter deleter which handles alloc+dealloc of the object
+ * @param cb render block or render replaced
+ * @param outside true when line is to be constructed outside
+ * @param outsideEnd true when the ending outside is meant
+ * @param iter returns the iterator to the caret box representing the given
+ * position for \c cb
+ */
+ static CaretBoxLine *constructCaretBoxLine(MassDeleter<CaretBoxLine> *deleter,
+ RenderBox *cb, bool outside, bool outsideEnd, CaretBoxIterator &iter) /*KDE_NO_EXPORT*/;
+
+#if DEBUG_CARETMODE > 0
+ void dump(TQTextStream &ts, const TQString &ind) const;
+ TQString information() const
+ {
+ TQString result;
+ TQTextStream ts(&result, IO_WriteOnly);
+ dump(ts, TQString::null);
+ return result;
+ }
+#endif
+
+protected:
+ /** contains the seek parameters */
+ struct SeekBoxParams {
+ InlineBox *box;
+ bool outside;
+ bool outsideEnd;
+ bool found;
+ RenderObject *r; // if box is 0, seek for equal render objects instead
+ CaretBoxIterator &it;
+
+ SeekBoxParams(InlineBox *box, bool outside, bool outsideEnd, RenderObject *obj, CaretBoxIterator &it)
+ : box(box), outside(outside), outsideEnd(outsideEnd), found(false), r(obj), it(it)
+ {}
+
+ /** compares whether this seek box matches the given specification */
+ bool equalsBox(const InlineBox *box, bool outside, bool outsideEnd) const
+ {
+ return (this->box && this->box == box
+ || this->r == box->object())
+ && this->outside == outside
+ && (!this->outside || this->outsideEnd == outsideEnd);
+ }
+ /** compares whether this seek box matches the given caret box */
+ bool operator ==(const CaretBox *cbox) const
+ {
+ return equalsBox(cbox->inlineBox(), cbox->isOutside(), cbox->isOutsideEnd());
+ }
+ /** checks whether this box matches the given iterator.
+ *
+ * On success, it sets \c found, and assigns the iterator to \c it.
+ * @return true on match
+ */
+ bool check(const CaretBoxIterator &chit)
+ {
+ if (*this == *chit) {
+ Q_ASSERT(!found);
+ found = true;
+ it = chit;
+ }
+ return found;
+ }
+ };
+
+ /** recursively converts the given inline box into caret boxes and adds them
+ * to this caret box line.
+ *
+ * It will additionally look for the caret box specified in SeekBoxParams.
+ */
+ void addConvertedInlineBox(InlineBox *, SeekBoxParams &) /*KDE_NO_EXPORT*/;
+
+ /** creates and adds the edge of a generic inline box
+ * @param box inline box
+ * @param fm font metrics of inline box
+ * @param left true to add left edge, false to add right edge
+ * @param rtl true if direction is rtl
+ */
+ void addCreatedInlineBoxEdge(InlineBox *box, const TQFontMetrics &fm,
+ bool left, bool rtl) /*KDE_NO_EXPORT*/;
+ /** creates and adds the edge of an inline flow box
+ * @param flowBox inline flow box
+ * @param fm font metrics of inline flow box
+ * @param left true to add left edge, false to add right edge
+ * @param rtl true if direction is rtl
+ */
+ void addCreatedFlowBoxEdge(InlineFlowBox *flowBox, const TQFontMetrics &fm,
+ bool left, bool rtl) /*KDE_NO_EXPORT*/;
+ /** creates and adds the inside of an inline flow box
+ * @param flowBox inline flow box
+ * @param fm font metrics of inline flow box
+ */
+ void addCreatedFlowBoxInside(InlineFlowBox *flowBox, const TQFontMetrics &fm) /*KDE_NO_EXPORT*/;
+
+ friend class CaretBoxIterator;
+};
+
+typedef MassDeleter<CaretBoxLine> CaretBoxLineDeleter;
+
+inline CaretBox *CaretBoxIterator::data() const { return cbl->caret_boxes[index]; }
+
+/**
+ * Iterates through the lines of a document.
+ *
+ * The line iterator becomes invalid when the associated LinearDocument object
+ * is destroyed.
+ * @since 3.2
+ * @internal
+ * @author Leo Savernik
+ */
+class LineIterator
+{
+protected:
+ LinearDocument *lines; // associated document
+ CaretBoxLine *cbl; // current caret box line
+
+ static CaretBoxIterator currentBox; // current inline box
+ static long currentOffset;
+
+ // Note: cbl == 0 indicates a position beyond the beginning or the
+ // end of a document.
+
+ /** Default constructor, only for internal use
+ */
+ LineIterator() {}
+
+ /** Initializes a new iterator.
+ *
+ * Note: This constructor neither cares about the correctness of @p node
+ * nor about @p offset. It is the responsibility of the caller to ensure
+ * that both point to valid places.
+ */
+ LineIterator(LinearDocument *l, DOM::NodeImpl *node, long offset);
+
+public:
+ /** dereferences current caret box line.
+ *
+ * @returns the caret line box or 0 if end of document
+ */
+ CaretBoxLine *operator *() const { return cbl; }
+
+ /** returns the associated linear document
+ */
+ LinearDocument *linearDocument() const { return lines; }
+
+ /** seek next line
+ *
+ * Guaranteed to crash if beyond beginning/end of document.
+ */
+ LineIterator &operator ++() { advance(false); return *this; }
+
+ /** seek previous line.
+ *
+ * Guaranteed to crash if beyond beginning/end of document.
+ */
+ LineIterator &operator --() { advance(true); return *this; }
+
+ /** compares two iterators. The comparator actually works only for
+ * comparing arbitrary iterators to begin() and end().
+ */
+ bool operator ==(const LineIterator &it) const
+ {
+ return lines == it.lines && cbl == it.cbl;
+ }
+
+ /** compares two iterators
+ */
+ bool operator !=(const LineIterator &it) const
+ {
+ return !operator ==(it);
+ }
+
+ /** Returns whether this line represents the outside end of the containing
+ * block.
+ *
+ * This result can only be relied on when isOutside is true.
+ */
+ bool isOutsideEnd() { return cbl->isOutsideEnd(); }
+
+ /** Tells whether the offset is meant to be outside or inside the
+ * containing block.
+ */
+ bool isOutside() const { return cbl->isOutside(); }
+
+ /** advances to the line to come.
+ * @param toBegin true, move to previous line, false, move to next line.
+ */
+ void advance(bool toBegin);
+
+ /** Whenever a new line iterator is created, it gets a caret box created.
+ * For memory reasons, it's saved in a static instance,
+ * thus making this function not thread-safe.
+ *
+ * This value can only be trusted immediately after having instantiated
+ * a line iterator or one of its derivatives.
+ * @return an iterator onto the corresponing caret box within the
+ * line represented by the last instantiation of a line iterator,
+ * or 0 if there was none.
+ */
+ static CaretBoxIterator &currentCaretBox() { return currentBox; }
+
+ /** Whenever a new line iterator is created, it calculates a modified offset
+ * that is to be used with respect to the current render object.
+ * This offset can be queried with this function.
+ *
+ * This value can only be trusted immediately after having instantiated
+ * a line iterator or one of its derivatives.
+ * @return the modified offset.
+ */
+ static long currentModifiedOffset() { return currentOffset; }
+
+protected:
+ /** seeks next block.
+ */
+ void nextBlock();
+ /** seeks previous block.
+ */
+ void prevBlock();
+
+ friend class CaretBoxIterator;
+ friend class EditableLineIterator;
+ friend class EditableCaretBoxIterator;
+ friend class EditableCharacterIterator;
+ friend class LinearDocument;
+};
+
+/**
+ * Represents the whole document in terms of lines.
+ *
+ * SGML documents are trees. But for navigation, this representation is
+ * not practical. Therefore this class serves as a helper to represent the
+ * document as a linear list of lines. Its usage somewhat resembles STL
+ * semantics like begin and end as well as iterators.
+ *
+ * The lines itself are represented as caret line boxes.
+ *
+ * LinearDocument instances are not meant to be kept over the lifetime of their
+ * associated document, but constructed from (node, offset) pairs whenever line
+ * traversal is needed. This is because the underlying InlineFlowBox objects
+ * may be destroyed and recreated (e. g. by resizing the window, adding/removing
+ * elements).
+ *
+ * @author Leo Savernik
+ * @since 3.2
+ * @internal
+ */
+class LinearDocument {
+public:
+ typedef LineIterator Iterator;
+
+ /**
+ * Creates a new instance, and initializes it to the line specified by
+ * the parameters below.
+ *
+ * Creation will fail if @p node is invisible or defect.
+ * @param part part within which everything is taking place.
+ * @param node document node with which to start
+ * @param offset zero-based offset within this node.
+ * @param advancePolicy caret advance policy
+ * @param baseElem base element which the caret must not advance beyond
+ * (0 means whole document). The base element will be ignored if it
+ * cannot serve as a base (to see if this is the case, check whether
+ * LinearDocument::baseFlow()->element() != base)
+ */
+ LinearDocument(KHTMLPart *part, DOM::NodeImpl *node, long offset,
+ CaretAdvancePolicy advancePolicy, DOM::ElementImpl *baseElem);
+
+ virtual ~LinearDocument();
+
+ /**
+ * Tells whether this list contains any lines.
+ *
+ * @returns @p true if this document contains lines, @p false otherwise. Note
+ * that an empty document contains at least one line, so this method
+ * only returns @p false if the document could not be initialised for
+ * some reason.
+ */
+ bool isValid() const // FIXME: not yet impl'd
+ {
+ return true;
+ }
+
+ /**
+ * Returns the count of lines.
+ *
+ * Warning: This function is expensive. Call it once and cache the value.
+ *
+ * FIXME: It's not implemented yet (and maybe never will)
+ */
+ int count() const;
+
+ /**
+ * Returns a line iterator containing the current position as its starting
+ * value.
+ */
+ Iterator current();
+
+ /**
+ * Returns a line iterator pointing right after the end of the document.
+ */
+ const Iterator &end() const { return _end; }
+
+ /**
+ * Returns a line iterator pointing to the very last line of the document.
+ */
+ Iterator preEnd();
+
+ /**
+ * Returns a line iterator pointing to the very first line of the document.
+ */
+ Iterator begin();
+
+ /**
+ * Returns a line iterator pointing just before the very first line of the
+ * document (this is somewhat an emulation of reverse iterators).
+ */
+ const Iterator &preBegin() const { return _preBegin; }
+
+ /**
+ * Returns the current caret advance policy
+ */
+ CaretAdvancePolicy advancePolicy() const { return advPol; }
+
+ /**
+ * Returns the base render object which the caret must not advance beyond.
+ *
+ * Note that HTML documents are usually restricted to the body element.
+ *
+ * @return the base render object or 0 if the whole document is valid.
+ */
+ RenderObject *baseObject() const { return base; }
+
+protected:
+ void initPreBeginIterator();
+ void initEndIterator();
+
+protected:
+ CaretBoxLineDeleter cblDeleter; // mass deleter for caret box lines
+ DOM::NodeImpl *node;
+ long offset;
+
+ Iterator _preBegin;
+ Iterator _end;
+
+ KHTMLPart *m_part;
+ CaretAdvancePolicy advPol;
+ RenderObject *base;
+
+ friend class LineIterator;
+ friend class EditableLineIterator;
+ friend class ErgonomicEditableLineIterator;
+ friend class CaretBoxIterator;
+ friend class EditableCaretBoxIterator;
+ friend class EditableCharacterIterator;
+};
+
+/**
+ * Iterates over the editable inner elements of a caret line box.
+ *
+ * The incrementor will traverse all caret boxes according to the associated
+ * linear document's caret advance policy. In contrast to \c CaretBoxIterator
+ * this iterator only regards caret boxes which are editable.
+ *
+ * @author Leo Savernik
+ * @internal
+ * @since 3.3
+ */
+class EditableCaretBoxIterator : public CaretBoxIterator {
+ KHTMLPart *m_part;
+ bool adjacent;
+ CaretAdvancePolicy advpol; // caret advance policy
+
+public:
+ /** initializes a new iterator from the given line iterator,
+ * beginning with the given caret box iterator, if specified
+ */
+ EditableCaretBoxIterator(LineIterator &lit, bool fromEnd = false,
+ CaretBoxIterator *it = 0)
+ : CaretBoxIterator(it ? *it : (fromEnd ? (*lit)->end() : (*lit)->preBegin())),
+ m_part(lit.lines->m_part), adjacent(false),
+ advpol(lit.lines->advancePolicy())
+ {
+ if (!it) {
+ if (fromEnd) --*this; else ++*this;
+ }
+ }
+
+ /** empty constructor. Use only to copy another iterator into this one.
+ */
+ EditableCaretBoxIterator() {}
+
+ /** returns @p true when the current caret box is adjacent to the
+ * previously iterated caret box, i. e. no intervening caret boxes.
+ */
+ bool isAdjacent() const { return adjacent; }
+
+ /** increments the iterator to point to the next editable caret box.
+ */
+ EditableCaretBoxIterator &operator ++() { advance(false); return *this; }
+
+ /** decrements the iterator to point to the previous editable caret box.
+ */
+ EditableCaretBoxIterator &operator --() { advance(true); return *this; }
+
+ /** advances to the editable caret box to come
+ * @param toBegin true, move towards beginning, false, move towards end.
+ */
+ void advance(bool toBegin);
+
+protected:
+ /** finds out if the given box is editable.
+ * @param boxit iterator to given caret box
+ * @param fromEnd true when advancing towards the beginning
+ * @return @p true if box is editable
+ */
+ bool isEditable(const CaretBoxIterator &boxit, bool fromEnd);
+};
+
+/**
+ * Iterates through the editable lines of a document.
+ *
+ * This iterator, opposing to @p LineIterator, only regards editable lines.
+ * Additionally, this iterator enforces the caret advance policy.
+ *
+ * The iterator can be compared to normal LineIterators, especially to
+ * @ref LinearDocument::preBegin and @ref LinearDocument::end
+ *
+ * The line iterator becomes invalid when the associated LinearDocument object
+ * is destroyed.
+ * @since 3.2
+ * @internal
+ * @author Leo Savernik
+ */
+class EditableLineIterator : public LineIterator {
+public:
+ /** Initializes a new iterator.
+ *
+ * The iterator is set to the first following editable line or to the
+ * end if no editable line follows.
+ * @param it a line iterator to initialize this from
+ * @param fromEnd @p true, traverse towards the beginning in search of an
+ * editable line
+ */
+ EditableLineIterator(const LineIterator &it, bool fromEnd = false)
+ : LineIterator(it)
+ {
+ if (!cbl) return;
+ if (!isEditable(*this)) advance(fromEnd);
+ }
+
+ /** empty constructor.
+ *
+ * Only use if you want to copy another iterator onto it later.
+ */
+ EditableLineIterator() {}
+
+ /** seek next line
+ *
+ * Guaranteed to crash if beyond beginning/end of document.
+ */
+ EditableLineIterator &operator ++() { advance(false); return *this; }
+
+ /** seek previous line.
+ *
+ * Guaranteed to crash if beyond beginning/end of document.
+ */
+ EditableLineIterator &operator --() { advance(true); return *this; }
+
+ /** advances to the line to come.
+ * @param toBegin true, move to previous line, false, move to next line.
+ */
+ void advance(bool toBegin);
+
+protected:
+ /** finds out if the current line is editable.
+ *
+ * @param it check caret box line iterator points to
+ * @return @p true if line is editable
+ */
+ bool isEditable(LineIterator &it)
+ {
+ EditableCaretBoxIterator fbit = it;
+ return fbit != (*it)->end();
+ }
+
+};
+
+/** Represents a render table as a linear list of rows.
+ *
+ * This iterator abstracts from table sections and treats tables as a linear
+ * representation of all rows they contain.
+ * @author Leo Savernik
+ * @internal
+ * @since 3.2
+ */
+class TableRowIterator {
+protected:
+ TableSectionIterator sec; // current section
+ int index; // index of row within section
+public:
+ /** Constructs a new iterator.
+ * @param table table to iterate through.
+ * @param fromEnd @p true to iterate towards the beginning
+ * @param row pointer to row to start with, 0 starts at the first/last
+ * row.
+ */
+ TableRowIterator(RenderTable *table, bool fromEnd = false,
+ RenderTableSection::RowStruct *row = 0);
+
+ /** Constructs a new iterator.
+ * @param section table section to begin with
+ * @param index index within table section
+ */
+ TableRowIterator(RenderTableSection *section, int index)
+ : sec(section), index(index)
+ {}
+
+ /** empty constructor. This must be assigned another iterator before it is
+ * useable.
+ */
+ TableRowIterator() {}
+
+ /** returns the current table row.
+ * @return the row or 0 if the end of the table has been reached.
+ */
+ RenderTableSection::RowStruct *operator *()
+ {
+ if (!*sec) return 0;
+ return &(*sec)->grid[index];
+ }
+
+ /** advances to the next row
+ */
+ TableRowIterator &operator ++();
+
+ /** advances to the previous row
+ */
+ TableRowIterator &operator --();
+
+protected:
+};
+
+/** Iterates through the editable lines of a document, in a topological order.
+ *
+ * The differences between this and the EditableLineIterator lies in the way
+ * lines are inquired. While the latter steps through the lines in document
+ * order, the former takes into consideration ergonomics.
+ *
+ * This is especially useful for tables. EditableLineIterator traverses all
+ * table cells from left to right, top to bottom, while this one will
+ * actually snap to the cell in the right position, and traverse only
+ * upwards/downwards, thus providing a more intuitive navigation.
+ *
+ * @author Leo Savernik
+ * @internal
+ * @since 3.2
+ */
+class ErgonomicEditableLineIterator : public EditableLineIterator {
+protected:
+ int xCoor; // x-coordinate to determine cell position
+public:
+ /** Initializes a new ergonomic editable line iterator from the given one.
+ * @param it line iterator
+ * @param x absolute x-coordinate for cell determination
+ */
+ ErgonomicEditableLineIterator(const LineIterator &it, int x)
+ : EditableLineIterator(it), xCoor(x) {}
+
+ /** Constructs an uninitialized iterator which must be assigned a line iterator before
+ * it can be used.
+ */
+ ErgonomicEditableLineIterator() {}
+
+ /** seek next line.
+ *
+ * The next line will be one that is visually situated below this line.
+ */
+ ErgonomicEditableLineIterator &operator ++();
+
+ /** seek previous line.
+ *
+ * The previous line will be one that is visually situated above this line.
+ */
+ ErgonomicEditableLineIterator &operator --();
+
+protected:
+ /** determines the topologically next render object.
+ * @param oldCell table cell the original object was under.
+ * @param newObject object to determine whether and which transition
+ * between cells is to be handled. It does not have to be an object in the correct
+ * topological cell, a simple delivery from an editable line iterator suffices.
+ * @param toBegin if @p true, iterate towards the beginning
+ */
+ void determineTopologicalElement(RenderTableCell *oldCell,
+ RenderObject *newObject, bool toBegin);
+
+ /** initializes the iterator to point to the first previous/following editable
+ * line.
+ * @param newBlock take this as base block.
+ * @param toBegin @p true, iterate towards beginning.
+ */
+ void calcAndStoreNewLine(RenderBlock *newBlock, bool toBegin);
+
+};
+
+/**
+ * Provides iterating through the document in terms of characters. Only the
+ * editable characters are regarded.
+ *
+ * This iterator represents the document, which is structured as a tree itself,
+ * as a linear stream of characters.
+ */
+class EditableCharacterIterator {
+protected:
+ EditableLineIterator _it;
+ EditableCaretBoxIterator ebit;
+ long _offset; // offset within current caret box.
+ int _char;
+ bool _end:1; // true when end of document has been reached
+
+public:
+
+ /** empty constructor.
+ *
+ * Only use if you want to assign another iterator as no fields will
+ * be initialized.
+ */
+ EditableCharacterIterator() {}
+
+ /** constructs a new iterator from the given linear document.
+ *
+ * @param ld linear representation of document.
+ */
+ EditableCharacterIterator(LinearDocument *ld)
+ : _it(ld->current()),
+ ebit(_it, false, &_it.currentCaretBox()),
+ _offset(_it.currentModifiedOffset()), _char(-1), _end(false)
+ {
+ // ### temporary fix for illegal nodes
+ if (_it == ld->end()) { _end = true; return; }
+ initFirstChar();
+ }
+
+ /** returns the current character, or -1 if not on a text node, or beyond
+ * the end.
+ */
+ int chr() const { return _char; }
+
+ /** returns the current character as a unicode symbol, substituting
+ * a blank for a non-text node.
+ */
+ TQChar operator *() const { return TQChar(_char >= 0 ? _char : ' '); }
+
+ /** returns true when the end of the document has been reached.
+ */
+ bool isEnd() const { return _end; }
+ /** returns the current offset
+ */
+ long offset() const { return _offset; }
+ /** returns the current render object.
+ */
+ RenderObject *renderer() const { return (*ebit)->object(); }
+ /** returns the current caret box.
+ *
+ * Will crash if beyond end.
+ */
+ CaretBox *caretBox() const { return *ebit; }
+ /** returns the current inline box.
+ *
+ * May be 0 if the current element has none, or if the end has been reached.
+ * Therefore, do *not* use this to test for the end condition, use node()
+ * instead.
+ */
+ InlineBox *inlineBox() const { return (*ebit)->inlineBox(); }
+ /** returns whether the current line box represents the outside of its
+ * render object.
+ */
+// bool boxIsOutside() const { return _it.isOutside(); }
+
+ /** moves to the next editable character.
+ */
+ EditableCharacterIterator &operator ++();
+
+ /** moves to the previous editable character.
+ */
+ EditableCharacterIterator &operator --();
+
+protected:
+ /** initializes the _char member by reading the character at the current
+ * offset, peeking ahead as necessary.
+ */
+ void initFirstChar();
+ /** reads ahead the next node and updates the data structures accordingly
+ */
+ void peekNext()
+ {
+ EditableCaretBoxIterator copy = ebit;
+ ++copy;
+ if (copy == (*_it)->end()) { _char = -1; return; }
+
+ CaretBox *box = *copy;
+ InlineBox *b = box->inlineBox();
+ if (b && !box->isOutside() && b->isInlineTextBox())
+ _char = static_cast<RenderText *>(b->object())->str->s[b->minOffset()].unicode();
+ else
+ _char = -1;
+ }
+ /** reads ahead the previous node and updates the data structures accordingly
+ */
+ void peekPrev()
+ {
+ --ebit;
+ }
+
+};
+
+
+}/*namespace tdehtml*/
+
+
+#endif
diff --git a/tdehtml/tdehtml_events.cpp b/tdehtml/tdehtml_events.cpp
new file mode 100644
index 000000000..0bb9c6fc3
--- /dev/null
+++ b/tdehtml/tdehtml_events.cpp
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ Copyright (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.
+*/
+
+#include "tdehtml_events.h"
+#include "rendering/render_object.h"
+#include "xml/dom_nodeimpl.h"
+
+using namespace tdehtml;
+
+class tdehtml::MouseEvent::MouseEventPrivate
+{
+};
+
+tdehtml::MouseEvent::MouseEvent( const char *name, TQMouseEvent *qmouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode )
+: KParts::Event( name ), m_qmouseEvent( qmouseEvent ), m_x( x ), m_y( y ),
+ m_url( url ), m_target(target), m_innerNode( innerNode )
+{
+ d = 0;
+ if (innerNode.handle() && innerNode.handle()->renderer())
+ innerNode.handle()->renderer()->absolutePosition(m_nodeAbsX, m_nodeAbsY);
+}
+
+tdehtml::MouseEvent::~MouseEvent()
+{
+ delete d;
+}
+
+long tdehtml::MouseEvent::offset() const
+{
+ int offset = 0;
+ DOM::NodeImpl* tempNode = 0;
+ int absX, absY;
+ absX = absY = 0;
+ if (innerNode().handle()->renderer()) {
+ innerNode().handle()->renderer()->absolutePosition(absX, absY);
+ tdehtml::RenderObject::SelPointState state;
+ innerNode().handle()->renderer()->checkSelectionPoint( x(), y(), absX, absY, tempNode, offset, state );
+ }
+ return offset;
+}
+
+const char *tdehtml::MousePressEvent::s_strMousePressEvent = "tdehtml/Events/MousePressEvent";
+
+const char *tdehtml::MouseDoubleClickEvent::s_strMouseDoubleClickEvent = "tdehtml/Events/MouseDoubleClickEvent";
+
+const char *tdehtml::MouseMoveEvent::s_strMouseMoveEvent = "tdehtml/Events/MouseMoveEvent";
+
+const char *tdehtml::MouseReleaseEvent::s_strMouseReleaseEvent = "tdehtml/Events/MouseReleaseEvent";
+
+const char *tdehtml::DrawContentsEvent::s_strDrawContentsEvent = "tdehtml/Events/DrawContentsEvent";
+
+class tdehtml::DrawContentsEvent::DrawContentsEventPrivate
+{
+public:
+ DrawContentsEventPrivate()
+ {
+ }
+ ~DrawContentsEventPrivate()
+ {
+ }
+};
+
+tdehtml::DrawContentsEvent::DrawContentsEvent( TQPainter *painter, int clipx, int clipy, int clipw, int cliph )
+ : KParts::Event( s_strDrawContentsEvent ), m_painter( painter ), m_clipx( clipx ), m_clipy( clipy ),
+ m_clipw( clipw ), m_cliph( cliph )
+{
+ d = new DrawContentsEventPrivate;
+}
+
+tdehtml::DrawContentsEvent::~DrawContentsEvent()
+{
+ delete d;
+}
+
diff --git a/tdehtml/tdehtml_events.h b/tdehtml/tdehtml_events.h
new file mode 100644
index 000000000..f71298262
--- /dev/null
+++ b/tdehtml/tdehtml_events.h
@@ -0,0 +1,157 @@
+/* This file is part of the KDE project
+ Copyright (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 __tdehtml_events_h__
+#define __tdehtml_events_h__
+
+#include <tdeparts/event.h>
+
+#include "dom/dom_node.h"
+#include "dom/dom_string.h"
+
+namespace tdehtml
+{
+
+class MouseEvent : public KParts::Event
+{
+public:
+ MouseEvent( const char *name, TQMouseEvent *qmouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode);
+ virtual ~MouseEvent();
+
+ TQMouseEvent *qmouseEvent() const { return m_qmouseEvent; }
+ int x() const { return m_x; }
+ int y() const { return m_y; }
+ int absX() const { return m_nodeAbsX; }
+ int absY() const { return m_nodeAbsY; }
+
+ DOM::DOMString url() const { return m_url; }
+ DOM::DOMString target() const { return m_target; }
+ DOM::Node innerNode() const { return m_innerNode; }
+
+ // return the offset of innerNode
+ long offset() const;
+
+private:
+ TQMouseEvent *m_qmouseEvent;
+ int m_x;
+ int m_y;
+ int m_nodeAbsX, m_nodeAbsY;
+ DOM::DOMString m_url;
+ DOM::DOMString m_target;
+ DOM::Node m_innerNode;
+ class MouseEventPrivate;
+ MouseEventPrivate *d;
+};
+
+class MousePressEvent : public MouseEvent
+{
+public:
+ MousePressEvent( TQMouseEvent *mouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode)
+ : MouseEvent( s_strMousePressEvent, mouseEvent, x, y, url, target, innerNode )
+ {}
+
+ static bool test( const TQEvent *event ) { return KParts::Event::test( event, s_strMousePressEvent ); }
+
+
+private:
+ static const char *s_strMousePressEvent;
+};
+
+class MouseDoubleClickEvent : public MouseEvent
+{
+public:
+ // clickCount is 3 for a triple-click event
+ MouseDoubleClickEvent( TQMouseEvent *mouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode, int clickCount = 2 )
+ : MouseEvent( s_strMouseDoubleClickEvent, mouseEvent, x, y, url, target, innerNode ),
+ m_clickCount( clickCount )
+ {}
+
+ static bool test( const TQEvent *event )
+ { return KParts::Event::test( event, s_strMouseDoubleClickEvent ); }
+
+ int clickCount() const { return m_clickCount; }
+
+private:
+ int m_clickCount;
+ static const char *s_strMouseDoubleClickEvent;
+};
+
+class MouseMoveEvent : public MouseEvent
+{
+public:
+ MouseMoveEvent( TQMouseEvent *mouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode)
+ : MouseEvent( s_strMouseMoveEvent, mouseEvent, x, y, url, target, innerNode )
+ {}
+
+ static bool test( const TQEvent *event ) { return KParts::Event::test( event, s_strMouseMoveEvent ); }
+
+private:
+ static const char *s_strMouseMoveEvent;
+};
+
+class MouseReleaseEvent : public MouseEvent
+{
+public:
+ MouseReleaseEvent( TQMouseEvent *mouseEvent, int x, int y,
+ const DOM::DOMString &url, const DOM::DOMString& target,
+ const DOM::Node &innerNode, long = 0 )
+ : MouseEvent( s_strMouseReleaseEvent, mouseEvent, x, y, url, target, innerNode )
+ {}
+
+ static bool test( const TQEvent *event ) { return KParts::Event::test( event, s_strMouseReleaseEvent ); }
+
+private:
+ static const char *s_strMouseReleaseEvent;
+};
+
+class DrawContentsEvent : public KParts::Event
+{
+public:
+ DrawContentsEvent( TQPainter *painter, int clipx, int clipy, int clipw, int cliph );
+ virtual ~DrawContentsEvent();
+
+ TQPainter *painter() const { return m_painter; }
+ int clipx() const { return m_clipx; }
+ int clipy() const { return m_clipy; }
+ int clipw() const { return m_clipw; }
+ int cliph() const { return m_cliph; }
+
+ static bool test( const TQEvent *event ) { return KParts::Event::test( event, s_strDrawContentsEvent ); }
+
+private:
+ TQPainter *m_painter;
+ int m_clipx;
+ int m_clipy;
+ int m_clipw;
+ int m_cliph;
+ class DrawContentsEventPrivate;
+ DrawContentsEventPrivate *d;
+ static const char *s_strDrawContentsEvent;
+};
+
+}
+
+#endif
diff --git a/tdehtml/tdehtml_ext.cpp b/tdehtml/tdehtml_ext.cpp
new file mode 100644
index 000000000..62a5293c1
--- /dev/null
+++ b/tdehtml/tdehtml_ext.cpp
@@ -0,0 +1,1032 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000-2003 Simon Hausmann <hausmann@kde.org>
+ * 2001-2003 George Staikos <staikos@kde.org>
+ * 2001-2003 Laurent Montel <montel@kde.org>
+ * 2001-2003 Dirk Mueller <mueller@kde.org>
+ * 2001-2003 Waldo Bastian <bastian@kde.org>
+ * 2001-2003 David Faure <faure@kde.org>
+ * 2001-2003 Daniel Naber <dnaber@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 <assert.h>
+#include "tdehtml_ext.h"
+#include "tdehtmlview.h"
+#include "tdehtml_pagecache.h"
+#include "rendering/render_form.h"
+#include "rendering/render_image.h"
+#include "html/html_imageimpl.h"
+#include "misc/loader.h"
+#include "dom/html_form.h"
+#include "dom/html_image.h"
+#include <tqclipboard.h>
+#include <tqfileinfo.h>
+#include <tqpopupmenu.h>
+#include <tqurl.h>
+#include <tqmetaobject.h>
+#include <tqucomextra_p.h>
+#include <tqdragobject.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kio/job.h>
+#include <kprocess.h>
+#include <ktoolbarbutton.h>
+#include <ktoolbar.h>
+#include <ksavefile.h>
+#include <kurldrag.h>
+#include <kstringhandler.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <krun.h>
+#include <kurifilter.h>
+#include <kiconloader.h>
+#include <kdesktopfile.h>
+#include <tdemultipledrag.h>
+#include <kinputdialog.h>
+
+#include "tdehtml_factory.h"
+
+#include "dom/dom_element.h"
+#include "misc/htmltags.h"
+
+#include "tdehtmlpart_p.h"
+
+KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart *parent, const char *name )
+: KParts::BrowserExtension( parent, name )
+{
+ m_part = parent;
+ setURLDropHandlingEnabled( true );
+
+ enableAction( "cut", false );
+ enableAction( "copy", false );
+ enableAction( "paste", false );
+
+ m_connectedToClipboard = false;
+}
+
+int KHTMLPartBrowserExtension::xOffset()
+{
+ return m_part->view()->contentsX();
+}
+
+int KHTMLPartBrowserExtension::yOffset()
+{
+ return m_part->view()->contentsY();
+}
+
+void KHTMLPartBrowserExtension::saveState( TQDataStream &stream )
+{
+ //kdDebug( 6050 ) << "saveState!" << endl;
+ m_part->saveState( stream );
+}
+
+void KHTMLPartBrowserExtension::restoreState( TQDataStream &stream )
+{
+ //kdDebug( 6050 ) << "restoreState!" << endl;
+ m_part->restoreState( stream );
+}
+
+void KHTMLPartBrowserExtension::editableWidgetFocused( TQWidget *widget )
+{
+ m_editableFormWidget = widget;
+ updateEditActions();
+
+ if ( !m_connectedToClipboard && m_editableFormWidget )
+ {
+ connect( TQApplication::clipboard(), TQT_SIGNAL( dataChanged() ),
+ this, TQT_SLOT( updateEditActions() ) );
+
+ if ( m_editableFormWidget->inherits( TQLINEEDIT_OBJECT_NAME_STRING ) || m_editableFormWidget->inherits( TQTEXTEDIT_OBJECT_NAME_STRING ) )
+ connect( m_editableFormWidget, TQT_SIGNAL( selectionChanged() ),
+ this, TQT_SLOT( updateEditActions() ) );
+
+ m_connectedToClipboard = true;
+ }
+ editableWidgetFocused();
+}
+
+void KHTMLPartBrowserExtension::editableWidgetBlurred( TQWidget * /*widget*/ )
+{
+ TQWidget *oldWidget = m_editableFormWidget;
+
+ m_editableFormWidget = 0;
+ enableAction( "cut", false );
+ enableAction( "paste", false );
+ m_part->emitSelectionChanged();
+
+ if ( m_connectedToClipboard )
+ {
+ disconnect( TQApplication::clipboard(), TQT_SIGNAL( dataChanged() ),
+ this, TQT_SLOT( updateEditActions() ) );
+
+ if ( oldWidget )
+ {
+ if ( oldWidget->inherits( TQLINEEDIT_OBJECT_NAME_STRING ) || oldWidget->inherits( TQTEXTEDIT_OBJECT_NAME_STRING ) )
+ disconnect( oldWidget, TQT_SIGNAL( selectionChanged() ),
+ this, TQT_SLOT( updateEditActions() ) );
+ }
+
+ m_connectedToClipboard = false;
+ }
+ editableWidgetBlurred();
+}
+
+void KHTMLPartBrowserExtension::setExtensionProxy( KParts::BrowserExtension *proxy )
+{
+ if ( m_extensionProxy )
+ {
+ disconnect( m_extensionProxy, TQT_SIGNAL( enableAction( const char *, bool ) ),
+ this, TQT_SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
+ if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
+ {
+ disconnect( m_extensionProxy, TQT_SIGNAL( editableWidgetFocused() ),
+ this, TQT_SLOT( extensionProxyEditableWidgetFocused() ) );
+ disconnect( m_extensionProxy, TQT_SIGNAL( editableWidgetBlurred() ),
+ this, TQT_SLOT( extensionProxyEditableWidgetBlurred() ) );
+ }
+ }
+
+ m_extensionProxy = proxy;
+
+ if ( m_extensionProxy )
+ {
+ connect( m_extensionProxy, TQT_SIGNAL( enableAction( const char *, bool ) ),
+ this, TQT_SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
+ if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
+ {
+ connect( m_extensionProxy, TQT_SIGNAL( editableWidgetFocused() ),
+ this, TQT_SLOT( extensionProxyEditableWidgetFocused() ) );
+ connect( m_extensionProxy, TQT_SIGNAL( editableWidgetBlurred() ),
+ this, TQT_SLOT( extensionProxyEditableWidgetBlurred() ) );
+ }
+
+ enableAction( "cut", m_extensionProxy->isActionEnabled( "cut" ) );
+ enableAction( "copy", m_extensionProxy->isActionEnabled( "copy" ) );
+ enableAction( "paste", m_extensionProxy->isActionEnabled( "paste" ) );
+ }
+ else
+ {
+ updateEditActions();
+ enableAction( "copy", false ); // ### re-check this
+ }
+}
+
+void KHTMLPartBrowserExtension::cut()
+{
+ if ( m_extensionProxy )
+ {
+ callExtensionProxyMethod( "cut()" );
+ return;
+ }
+
+ if ( !m_editableFormWidget )
+ return;
+
+ if ( m_editableFormWidget->inherits( TQLINEEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQLineEdit *>( &(*m_editableFormWidget) )->cut();
+ else if ( m_editableFormWidget->inherits( TQTEXTEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQTextEdit *>( &(*m_editableFormWidget) )->cut();
+}
+
+void KHTMLPartBrowserExtension::copy()
+{
+ if ( m_extensionProxy )
+ {
+ callExtensionProxyMethod( "copy()" );
+ return;
+ }
+
+ kdDebug( 6050 ) << "************! KHTMLPartBrowserExtension::copy()" << endl;
+ if ( !m_editableFormWidget )
+ {
+ // get selected text and paste to the clipboard
+ TQString text= m_part->selectedText();
+ text.replace( TQChar( 0xa0 ), ' ' );
+
+
+ TQClipboard *cb = TQApplication::clipboard();
+ disconnect( cb, TQT_SIGNAL( selectionChanged() ), m_part, TQT_SLOT( slotClearSelection() ) );
+#ifndef QT_NO_MIMECLIPBOARD
+ TQString htmltext;
+ /*
+ * When selectionModeEnabled, that means the user has just selected
+ * the text, not ctrl+c to copy it. The selection clipboard
+ * doesn't seem to support mime type, so to save time, don't calculate
+ * the selected text as html.
+ * optomisation disabled for now until everything else works.
+ */
+ //if(!cb->selectionModeEnabled())
+ htmltext = m_part->selectedTextAsHTML();
+ TQTextDrag *textdrag = new TQTextDrag(text, 0L);
+ KMultipleDrag *drag = new KMultipleDrag( m_editableFormWidget );
+ drag->addDragObject( textdrag );
+ if(!htmltext.isEmpty()) {
+ htmltext.replace( TQChar( 0xa0 ), ' ' );
+ TQTextDrag *htmltextdrag = new TQTextDrag(htmltext, 0L);
+ htmltextdrag->setSubtype("html");
+ drag->addDragObject( htmltextdrag );
+ }
+ cb->setData(drag);
+#else
+ cb->setText(text);
+#endif
+
+ connect( cb, TQT_SIGNAL( selectionChanged() ), m_part, TQT_SLOT( slotClearSelection() ) );
+ }
+ else
+ {
+ if ( m_editableFormWidget->inherits( TQLINEEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQLineEdit *>( &(*m_editableFormWidget) )->copy();
+ else if ( m_editableFormWidget->inherits( TQTEXTEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQTextEdit *>( &(*m_editableFormWidget) )->copy();
+ }
+}
+
+void KHTMLPartBrowserExtension::searchProvider()
+{
+ // action name is of form "previewProvider[<searchproviderprefix>:]"
+ const TQString searchProviderPrefix = TQString( TQT_TQOBJECT_CONST(sender())->name() ).mid( 14 );
+
+ KURIFilterData data;
+ TQStringList list;
+ data.setData( searchProviderPrefix + m_part->selectedText() );
+ list << "kurisearchfilter" << "kuriikwsfilter";
+
+ if( !KURIFilter::self()->filterURI(data, list) )
+ {
+ KDesktopFile file("searchproviders/google.desktop", true, "services");
+ TQString encodedSearchTerm = m_part->selectedText();
+ TQUrl::encode(encodedSearchTerm);
+ data.setData(file.readEntry("Query").replace("\\{@}", encodedSearchTerm));
+ }
+
+ KParts::URLArgs args;
+ args.frameName = "_blank";
+
+ emit m_part->browserExtension()->openURLRequest( data.uri(), args );
+}
+
+void KHTMLPartBrowserExtension::openSelection()
+{
+ KParts::URLArgs args;
+ args.frameName = "_blank";
+
+ emit m_part->browserExtension()->openURLRequest( m_part->selectedText(), args );
+}
+
+void KHTMLPartBrowserExtension::paste()
+{
+ if ( m_extensionProxy )
+ {
+ callExtensionProxyMethod( "paste()" );
+ return;
+ }
+
+ if ( !m_editableFormWidget )
+ return;
+
+ if ( m_editableFormWidget->inherits( TQLINEEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQLineEdit *>( &(*m_editableFormWidget) )->paste();
+ else if ( m_editableFormWidget->inherits( TQTEXTEDIT_OBJECT_NAME_STRING ) )
+ static_cast<TQTextEdit *>( &(*m_editableFormWidget) )->paste();
+}
+
+void KHTMLPartBrowserExtension::callExtensionProxyMethod( const char *method )
+{
+ if ( !m_extensionProxy )
+ return;
+
+ int slot = m_extensionProxy->metaObject()->findSlot( method );
+ if ( slot == -1 )
+ return;
+
+ TQUObject o[ 1 ];
+ m_extensionProxy->tqt_invoke( slot, o );
+}
+
+void KHTMLPartBrowserExtension::updateEditActions()
+{
+ if ( !m_editableFormWidget )
+ {
+ enableAction( "cut", false );
+ enableAction( "copy", false );
+ enableAction( "paste", false );
+ return;
+ }
+
+ // ### duplicated from KonqMainWindow::slotClipboardDataChanged
+#ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
+ TQMimeSource *data = TQApplication::clipboard()->data();
+ enableAction( "paste", data->provides( "text/plain" ) );
+#else
+ TQString data=TQApplication::clipboard()->text();
+ enableAction( "paste", data.contains("://"));
+#endif
+ bool hasSelection = false;
+
+ if( m_editableFormWidget) {
+ if ( ::tqqt_cast<TQLineEdit*>(m_editableFormWidget))
+ hasSelection = static_cast<TQLineEdit *>( &(*m_editableFormWidget) )->hasSelectedText();
+ else if(::tqqt_cast<TQTextEdit*>(m_editableFormWidget))
+ hasSelection = static_cast<TQTextEdit *>( &(*m_editableFormWidget) )->hasSelectedText();
+ }
+
+ enableAction( "copy", hasSelection );
+ enableAction( "cut", hasSelection );
+}
+
+void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused() {
+ editableWidgetFocused();
+}
+
+void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred() {
+ editableWidgetBlurred();
+}
+
+void KHTMLPartBrowserExtension::extensionProxyActionEnabled( const char *action, bool enable )
+{
+ // only forward enableAction calls for actions we actually do forward
+ if ( strcmp( action, "cut" ) == 0 ||
+ strcmp( action, "copy" ) == 0 ||
+ strcmp( action, "paste" ) == 0 ) {
+ enableAction( action, enable );
+ }
+}
+
+void KHTMLPartBrowserExtension::reparseConfiguration()
+{
+ m_part->reparseConfiguration();
+}
+
+void KHTMLPartBrowserExtension::print()
+{
+ m_part->view()->print();
+}
+
+void KHTMLPartBrowserExtension::disableScrolling()
+{
+ TQScrollView *scrollView = m_part->view();
+ if (scrollView) {
+ scrollView->setVScrollBarMode(TQScrollView::AlwaysOff);
+ scrollView->setHScrollBarMode(TQScrollView::AlwaysOff);
+ }
+}
+
+class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
+{
+public:
+ KHTMLPart *m_tdehtml;
+ KURL m_url;
+ KURL m_imageURL;
+ TQPixmap m_pixmap;
+ TQString m_suggestedFilename;
+};
+
+
+KHTMLPopupGUIClient::KHTMLPopupGUIClient( KHTMLPart *tdehtml, const TQString &doc, const KURL &url )
+ : TQObject( tdehtml )
+{
+ d = new KHTMLPopupGUIClientPrivate;
+ d->m_tdehtml = tdehtml;
+ d->m_url = url;
+ bool isImage = false;
+ bool hasSelection = tdehtml->hasSelection();
+ setInstance( tdehtml->instance() );
+
+ DOM::Element e;
+ e = tdehtml->nodeUnderMouse();
+
+ if ( !e.isNull() && (e.elementId() == ID_IMG ||
+ (e.elementId() == ID_INPUT && !static_cast<DOM::HTMLInputElement>(e).src().isEmpty())))
+ {
+ if (e.elementId() == ID_IMG) {
+ DOM::HTMLImageElementImpl *ie = static_cast<DOM::HTMLImageElementImpl*>(e.handle());
+ tdehtml::RenderImage *ri = dynamic_cast<tdehtml::RenderImage*>(ie->renderer());
+ if (ri && ri->contentObject()) {
+ d->m_suggestedFilename = static_cast<tdehtml::CachedImage*>(ri->contentObject())->suggestedFilename();
+ }
+ }
+ isImage=true;
+ }
+
+ if (hasSelection)
+ {
+ KAction* copyAction = KStdAction::copy( d->m_tdehtml->browserExtension(), TQT_SLOT( copy() ), actionCollection(), "copy" );
+ copyAction->setText(i18n("&Copy Text"));
+ copyAction->setEnabled(d->m_tdehtml->browserExtension()->isActionEnabled( "copy" ));
+ actionCollection()->insert( tdehtml->actionCollection()->action( "selectAll" ) );
+
+
+ // Fill search provider entries
+ TDEConfig config("kuriikwsfilterrc");
+ config.setGroup("General");
+ const TQString defaultEngine = config.readEntry("DefaultSearchEngine", "google");
+ const char keywordDelimiter = config.readNumEntry("KeywordDelimiter", ':');
+
+ // search text
+ TQString selectedText = tdehtml->selectedText();
+ selectedText.replace("&", "&&");
+ if ( selectedText.length()>18 ) {
+ selectedText.truncate(15);
+ selectedText+="...";
+ }
+
+ // default search provider
+ KService::Ptr service = KService::serviceByDesktopPath(TQString("searchproviders/%1.desktop").arg(defaultEngine));
+
+ // search provider icon
+ TQPixmap icon;
+ KURIFilterData data;
+ TQStringList list;
+ data.setData( TQString("some keyword") );
+ list << "kurisearchfilter" << "kuriikwsfilter";
+
+ TQString name;
+ if ( KURIFilter::self()->filterURI(data, list) )
+ {
+ TQString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png");
+ if ( iconPath.isEmpty() )
+ icon = SmallIcon("find");
+ else
+ icon = TQPixmap( iconPath );
+ name = service->name();
+ }
+ else
+ {
+ icon = SmallIcon("google");
+ name = "Google";
+ }
+
+ // using .arg(foo, bar) instead of .arg(foo).arg(bar), as foo can contain %x
+ new KAction( i18n( "Search for '%1' with %2" ).arg( selectedText, name ), icon, 0, d->m_tdehtml->browserExtension(),
+ TQT_SLOT( searchProvider() ), actionCollection(), "searchProvider" );
+
+ // favorite search providers
+ TQStringList favoriteEngines;
+ favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
+ favoriteEngines = config.readListEntry("FavoriteSearchEngines", favoriteEngines);
+
+ if ( !favoriteEngines.isEmpty()) {
+ KActionMenu* providerList = new KActionMenu( i18n( "Search for '%1' with" ).arg( selectedText ), actionCollection(), "searchProviderList" );
+
+ TQStringList::ConstIterator it = favoriteEngines.begin();
+ for ( ; it != favoriteEngines.end(); ++it ) {
+ if (*it==defaultEngine)
+ continue;
+ service = KService::serviceByDesktopPath(TQString("searchproviders/%1.desktop").arg(*it));
+ if (!service)
+ continue;
+ const TQString searchProviderPrefix = *(service->property("Keys").toStringList().begin()) + keywordDelimiter;
+ data.setData( searchProviderPrefix + "some keyword" );
+
+ if ( KURIFilter::self()->filterURI(data, list) )
+ {
+ TQString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png");
+ if ( iconPath.isEmpty() )
+ icon = SmallIcon("find");
+ else
+ icon = TQPixmap( iconPath );
+ name = service->name();
+
+ providerList->insert( new KAction( name, icon, 0, d->m_tdehtml->browserExtension(),
+ TQT_SLOT( searchProvider() ), actionCollection(), TQString( "searchProvider" + searchProviderPrefix ).latin1() ) );
+ }
+ }
+ }
+
+
+ if ( selectedText.contains("://") && KURL(selectedText).isValid() )
+ new KAction( i18n( "Open '%1'" ).arg( selectedText ), "window_new", 0,
+ d->m_tdehtml->browserExtension(), TQT_SLOT( openSelection() ), actionCollection(), "openSelection" );
+ }
+ else if ( url.isEmpty() && !isImage )
+ {
+ actionCollection()->insert( tdehtml->actionCollection()->action( "security" ) );
+ actionCollection()->insert( tdehtml->actionCollection()->action( "setEncoding" ) );
+ new KAction( i18n( "Stop Animations" ), 0, this, TQT_SLOT( slotStopAnimations() ),
+ actionCollection(), "stopanimations" );
+ }
+
+ if ( !url.isEmpty() )
+ {
+ if (url.protocol() == "mailto")
+ {
+ new KAction( i18n( "Copy Email Address" ), 0, this, TQT_SLOT( slotCopyLinkLocation() ),
+ actionCollection(), "copylinklocation" );
+ }
+ else
+ {
+ new KAction( i18n( "&Save Link As..." ), 0, this, TQT_SLOT( slotSaveLinkAs() ),
+ actionCollection(), "savelinkas" );
+ new KAction( i18n( "Copy &Link Address" ), 0, this, TQT_SLOT( slotCopyLinkLocation() ),
+ actionCollection(), "copylinklocation" );
+ }
+ }
+
+ // frameset? -> add "Reload Frame" etc.
+ if (!hasSelection)
+ {
+ if ( tdehtml->parentPart() )
+ {
+ new KAction( i18n( "Open in New &Window" ), "window_new", 0, this, TQT_SLOT( slotFrameInWindow() ),
+ actionCollection(), "frameinwindow" );
+ new KAction( i18n( "Open in &This Window" ), 0, this, TQT_SLOT( slotFrameInTop() ),
+ actionCollection(), "frameintop" );
+ new KAction( i18n( "Open in &New Tab" ), "tab_new", 0, this, TQT_SLOT( slotFrameInTab() ),
+ actionCollection(), "frameintab" );
+ new KAction( i18n( "Reload Frame" ), 0, this, TQT_SLOT( slotReloadFrame() ),
+ actionCollection(), "reloadframe" );
+
+ if ( KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled() ) {
+ if ( tdehtml->d->m_frame->m_type == tdehtml::ChildFrame::IFrame )
+ new KAction( i18n( "Block IFrame..." ), 0, this, TQT_SLOT( slotBlockIFrame() ), actionCollection(), "blockiframe" );
+ }
+
+ new KAction( i18n( "View Frame Source" ), 0, d->m_tdehtml, TQT_SLOT( slotViewDocumentSource() ),
+ actionCollection(), "viewFrameSource" );
+ new KAction( i18n( "View Frame Information" ), 0, d->m_tdehtml, TQT_SLOT( slotViewPageInfo() ), actionCollection(), "viewFrameInfo" );
+ // This one isn't in tdehtml_popupmenu.rc anymore, because Print isn't either,
+ // and because print frame is already in the toolbar and the menu.
+ // But leave this here, so that it's easy to read it.
+ new KAction( i18n( "Print Frame..." ), "frameprint", 0, d->m_tdehtml->browserExtension(), TQT_SLOT( print() ), actionCollection(), "printFrame" );
+ new KAction( i18n( "Save &Frame As..." ), 0, d->m_tdehtml, TQT_SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
+
+ actionCollection()->insert( tdehtml->parentPart()->actionCollection()->action( "viewDocumentSource" ) );
+ actionCollection()->insert( tdehtml->parentPart()->actionCollection()->action( "viewPageInfo" ) );
+ } else {
+ actionCollection()->insert( tdehtml->actionCollection()->action( "viewDocumentSource" ) );
+ actionCollection()->insert( tdehtml->actionCollection()->action( "viewPageInfo" ) );
+ }
+ } else if (isImage || !url.isEmpty()) {
+ actionCollection()->insert( tdehtml->actionCollection()->action( "viewDocumentSource" ) );
+ actionCollection()->insert( tdehtml->actionCollection()->action( "viewPageInfo" ) );
+ new KAction( i18n( "Stop Animations" ), 0, this, TQT_SLOT( slotStopAnimations() ),
+ actionCollection(), "stopanimations" );
+ }
+
+ if (isImage)
+ {
+ if ( e.elementId() == ID_IMG ) {
+ d->m_imageURL = KURL( static_cast<DOM::HTMLImageElement>( e ).src().string() );
+ DOM::HTMLImageElementImpl *imageimpl = static_cast<DOM::HTMLImageElementImpl *>( e.handle() );
+ Q_ASSERT(imageimpl);
+ if(imageimpl) // should be true always. right?
+ {
+ if(imageimpl->complete()) {
+ d->m_pixmap = imageimpl->currentPixmap();
+ }
+ }
+ }
+ else
+ d->m_imageURL = KURL( static_cast<DOM::HTMLInputElement>( e ).src().string() );
+ new KAction( i18n( "Save Image As..." ), 0, this, TQT_SLOT( slotSaveImageAs() ),
+ actionCollection(), "saveimageas" );
+ new KAction( i18n( "Send Image..." ), 0, this, TQT_SLOT( slotSendImage() ),
+ actionCollection(), "sendimage" );
+
+
+#ifndef QT_NO_MIMECLIPBOARD
+ (new KAction( i18n( "Copy Image" ), 0, this, TQT_SLOT( slotCopyImage() ),
+ actionCollection(), "copyimage" ))->setEnabled(!d->m_pixmap.isNull());
+#endif
+
+ if(d->m_pixmap.isNull()) { //fallback to image location if still loading the image. this will always be true if ifdef QT_NO_MIMECLIPBOARD
+ new KAction( i18n( "Copy Image Location" ), 0, this, TQT_SLOT( slotCopyImageLocation() ),
+ actionCollection(), "copyimagelocation" );
+ }
+
+ TQString name = KStringHandler::csqueeze(d->m_imageURL.fileName()+d->m_imageURL.query(), 25);
+ new KAction( i18n( "View Image (%1)" ).arg(d->m_suggestedFilename.isEmpty() ? name.replace("&", "&&") : d->m_suggestedFilename.replace("&", "&&")), 0, this, TQT_SLOT( slotViewImage() ),
+ actionCollection(), "viewimage" );
+
+ if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
+ {
+ new KAction( i18n( "Block Image..." ), 0, this, TQT_SLOT( slotBlockImage() ),
+ actionCollection(), "blockimage" );
+
+ if (!d->m_imageURL.host().isEmpty() &&
+ !d->m_imageURL.protocol().isEmpty())
+ {
+ new KAction( i18n( "Block Images From %1" ).arg(d->m_imageURL.host()), 0, this, TQT_SLOT( slotBlockHost() ),
+ actionCollection(), "blockhost" );
+ }
+ }
+ }
+
+ setXML( doc );
+ setDOMDocument( TQDomDocument(), true ); // ### HACK
+
+ TQDomElement menu = domDocument().documentElement().namedItem( "Menu" ).toElement();
+
+ if ( actionCollection()->count() > 0 )
+ menu.insertBefore( domDocument().createElement( "separator" ), menu.firstChild() );
+}
+
+KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
+{
+ delete d;
+}
+
+void KHTMLPopupGUIClient::slotSaveLinkAs()
+{
+ TDEIO::MetaData metaData;
+ metaData["referrer"] = d->m_tdehtml->referrer();
+ saveURL( d->m_tdehtml->widget(), i18n( "Save Link As" ), d->m_url, metaData );
+}
+
+void KHTMLPopupGUIClient::slotSendImage()
+{
+ TQStringList urls;
+ urls.append( d->m_imageURL.url());
+ TQString subject = d->m_imageURL.url();
+ kapp->invokeMailer(TQString::null, TQString::null, TQString::null, subject,
+ TQString::null, //body
+ TQString::null,
+ urls); // attachments
+
+
+}
+
+void KHTMLPopupGUIClient::slotSaveImageAs()
+{
+ TDEIO::MetaData metaData;
+ metaData["referrer"] = d->m_tdehtml->referrer();
+ saveURL( d->m_tdehtml->widget(), i18n( "Save Image As" ), d->m_imageURL, metaData, TQString::null, 0, d->m_suggestedFilename );
+}
+
+void KHTMLPopupGUIClient::slotBlockHost()
+{
+ TQString name=d->m_imageURL.protocol()+"://"+d->m_imageURL.host()+"/*";
+ KHTMLFactory::defaultHTMLSettings()->addAdFilter( name );
+ d->m_tdehtml->reparseConfiguration();
+}
+
+void KHTMLPopupGUIClient::slotBlockImage()
+{
+ bool ok = false;
+
+ TQString url = KInputDialog::getText( i18n("Add URL to Filter"),
+ i18n("Enter the URL:"),
+ d->m_imageURL.url(),
+ &ok);
+ if ( ok ) {
+ KHTMLFactory::defaultHTMLSettings()->addAdFilter( url );
+ d->m_tdehtml->reparseConfiguration();
+ }
+}
+
+void KHTMLPopupGUIClient::slotBlockIFrame()
+{
+ bool ok = false;
+ TQString url = KInputDialog::getText( i18n( "Add URL to Filter"),
+ i18n("Enter the URL:"),
+ d->m_tdehtml->url().url(),
+ &ok );
+ if ( ok ) {
+ KHTMLFactory::defaultHTMLSettings()->addAdFilter( url );
+ d->m_tdehtml->reparseConfiguration();
+ }
+}
+
+void KHTMLPopupGUIClient::slotCopyLinkLocation()
+{
+ KURL safeURL(d->m_url);
+ safeURL.setPass(TQString::null);
+#ifndef QT_NO_MIMECLIPBOARD
+ // Set it in both the mouse selection and in the clipboard
+ KURL::List lst;
+ lst.append( safeURL );
+ TQApplication::clipboard()->setData( new KURLDrag( lst ), TQClipboard::Clipboard );
+ TQApplication::clipboard()->setData( new KURLDrag( lst ), TQClipboard::Selection );
+#else
+ TQApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
+#endif
+}
+
+void KHTMLPopupGUIClient::slotStopAnimations()
+{
+ d->m_tdehtml->stopAnimations();
+}
+
+void KHTMLPopupGUIClient::slotCopyImage()
+{
+#ifndef QT_NO_MIMECLIPBOARD
+ KURL safeURL(d->m_imageURL);
+ safeURL.setPass(TQString::null);
+
+ KURL::List lst;
+ lst.append( safeURL );
+ KMultipleDrag *drag = new KMultipleDrag(d->m_tdehtml->view(), "Image");
+
+ drag->addDragObject( new TQImageDrag(d->m_pixmap.convertToImage()) );
+ drag->addDragObject( new KURLDrag(lst, d->m_tdehtml->view(), "Image URL") );
+
+ // Set it in both the mouse selection and in the clipboard
+ TQApplication::clipboard()->setData( drag, TQClipboard::Clipboard );
+ TQApplication::clipboard()->setData( new KURLDrag(lst), TQClipboard::Selection );
+#else
+ kdDebug() << "slotCopyImage called when the clipboard does not support this. This should not be possible." << endl;
+#endif
+}
+
+void KHTMLPopupGUIClient::slotCopyImageLocation()
+{
+ KURL safeURL(d->m_imageURL);
+ safeURL.setPass(TQString::null);
+#ifndef QT_NO_MIMECLIPBOARD
+ // Set it in both the mouse selection and in the clipboard
+ KURL::List lst;
+ lst.append( safeURL );
+ TQApplication::clipboard()->setData( new KURLDrag( lst ), TQClipboard::Clipboard );
+ TQApplication::clipboard()->setData( new KURLDrag( lst ), TQClipboard::Selection );
+#else
+ TQApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
+#endif
+}
+
+void KHTMLPopupGUIClient::slotViewImage()
+{
+ d->m_tdehtml->browserExtension()->createNewWindow(d->m_imageURL);
+}
+
+void KHTMLPopupGUIClient::slotReloadFrame()
+{
+ KParts::URLArgs args( d->m_tdehtml->browserExtension()->urlArgs() );
+ args.reload = true;
+ args.metaData()["referrer"] = d->m_tdehtml->pageReferrer();
+ // reload document
+ d->m_tdehtml->closeURL();
+ d->m_tdehtml->browserExtension()->setURLArgs( args );
+ d->m_tdehtml->openURL( d->m_tdehtml->url() );
+}
+
+void KHTMLPopupGUIClient::slotFrameInWindow()
+{
+ KParts::URLArgs args( d->m_tdehtml->browserExtension()->urlArgs() );
+ args.metaData()["referrer"] = d->m_tdehtml->pageReferrer();
+ args.metaData()["forcenewwindow"] = "true";
+ emit d->m_tdehtml->browserExtension()->createNewWindow( d->m_tdehtml->url(), args );
+}
+
+void KHTMLPopupGUIClient::slotFrameInTop()
+{
+ KParts::URLArgs args( d->m_tdehtml->browserExtension()->urlArgs() );
+ args.metaData()["referrer"] = d->m_tdehtml->pageReferrer();
+ args.frameName = "_top";
+ emit d->m_tdehtml->browserExtension()->openURLRequest( d->m_tdehtml->url(), args );
+}
+
+void KHTMLPopupGUIClient::slotFrameInTab()
+{
+ KParts::URLArgs args( d->m_tdehtml->browserExtension()->urlArgs() );
+ args.metaData()["referrer"] = d->m_tdehtml->pageReferrer();
+ args.setNewTab(true);
+ emit d->m_tdehtml->browserExtension()->createNewWindow( d->m_tdehtml->url(), args );
+}
+
+void KHTMLPopupGUIClient::saveURL( TQWidget *parent, const TQString &caption,
+ const KURL &url,
+ const TQMap<TQString, TQString> &metadata,
+ const TQString &filter, long cacheId,
+ const TQString & suggestedFilename )
+{
+ TQString name = TQString::fromLatin1( "index.html" );
+ if ( !suggestedFilename.isEmpty() )
+ name = suggestedFilename;
+ else if ( !url.fileName().isEmpty() )
+ name = url.fileName();
+
+ KURL destURL;
+ int query;
+ do {
+ query = KMessageBox::Yes;
+ destURL = KFileDialog::getSaveURL( name, filter, parent, caption );
+ if( destURL.isLocalFile() )
+ {
+ TQFileInfo info( destURL.path() );
+ if( info.exists() ) {
+ // TODO: use TDEIO::RenameDlg (shows more information)
+ query = KMessageBox::warningContinueCancel( parent, i18n( "A file named \"%1\" already exists. " "Are you sure you want to overwrite it?" ).arg( info.fileName() ), i18n( "Overwrite File?" ), i18n( "Overwrite" ) );
+ }
+ }
+ } while ( query == KMessageBox::Cancel );
+
+ if ( destURL.isValid() )
+ saveURL(url, destURL, metadata, cacheId);
+}
+
+void KHTMLPopupGUIClient::saveURL( const KURL &url, const KURL &destURL,
+ const TQMap<TQString, TQString> &metadata,
+ long cacheId )
+{
+ if ( destURL.isValid() )
+ {
+ bool saved = false;
+ if (KHTMLPageCache::self()->isComplete(cacheId))
+ {
+ if (destURL.isLocalFile())
+ {
+ KSaveFile destFile(destURL.path());
+ if (destFile.status() == 0)
+ {
+ KHTMLPageCache::self()->saveData(cacheId, destFile.dataStream());
+ saved = true;
+ }
+ }
+ else
+ {
+ // save to temp file, then move to final destination.
+ KTempFile destFile;
+ if (destFile.status() == 0)
+ {
+ KHTMLPageCache::self()->saveData(cacheId, destFile.dataStream());
+ destFile.close();
+ KURL url2 = KURL();
+ url2.setPath(destFile.name());
+ TDEIO::file_move(url2, destURL, -1, true /*overwrite*/);
+ saved = true;
+ }
+ }
+ }
+ if(!saved)
+ {
+ // DownloadManager <-> konqueror integration
+ // find if the integration is enabled
+ // the empty key means no integration
+ // only use download manager for non-local urls!
+ bool downloadViaKIO = true;
+ if ( !url.isLocalFile() )
+ {
+ TDEConfig cfg("konquerorrc", false, false);
+ cfg.setGroup("HTML Settings");
+ TQString downloadManger = cfg.readPathEntry("DownloadManager");
+ if (!downloadManger.isEmpty())
+ {
+ // then find the download manager location
+ kdDebug(1000) << "Using: "<<downloadManger <<" as Download Manager" <<endl;
+ TQString cmd = KStandardDirs::findExe(downloadManger);
+ if (cmd.isEmpty())
+ {
+ TQString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ").arg(downloadManger);
+ TQString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled!");
+ KMessageBox::detailedSorry(0,errMsg,errMsgEx);
+ cfg.writePathEntry("DownloadManager",TQString::null);
+ cfg.sync ();
+ }
+ else
+ {
+ downloadViaKIO = false;
+ KURL cleanDest = destURL;
+ cleanDest.setPass( TQString::null ); // don't put password into commandline
+ cmd += " " + TDEProcess::quote(url.url()) + " " +
+ TDEProcess::quote(cleanDest.url());
+ kdDebug(1000) << "Calling command "<<cmd<<endl;
+ KRun::runCommand(cmd);
+ }
+ }
+ }
+
+ if ( downloadViaKIO )
+ {
+ TDEIO::Job *job = TDEIO::file_copy( url, destURL, -1, true /*overwrite*/ );
+ job->setMetaData(metadata);
+ job->addMetaData("MaxCacheSize", "0"); // Don't store in http cache.
+ job->addMetaData("cache", "cache"); // Use entry from cache if available.
+ job->setAutoErrorHandlingEnabled( true );
+ }
+ } //end if(!saved)
+ }
+}
+
+KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension( KHTMLPart *part )
+: KParts::BrowserHostExtension( part )
+{
+ m_part = part;
+}
+
+KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
+{
+}
+
+TQStringList KHTMLPartBrowserHostExtension::frameNames() const
+{
+ return m_part->frameNames();
+}
+
+const TQPtrList<KParts::ReadOnlyPart> KHTMLPartBrowserHostExtension::frames() const
+{
+ return m_part->frames();
+}
+
+bool KHTMLPartBrowserHostExtension::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
+{
+ return m_part->openURLInFrame( url, urlArgs );
+}
+
+void KHTMLPartBrowserHostExtension::virtual_hook( int id, void *data )
+{
+ if (id == VIRTUAL_FIND_FRAME_PARENT)
+ {
+ FindFrameParentParams *param = static_cast<FindFrameParentParams*>(data);
+ KHTMLPart *parentPart = m_part->findFrameParent(param->callingPart, param->frame);
+ if (parentPart)
+ param->parent = parentPart->browserHostExtension();
+ return;
+ }
+ BrowserHostExtension::virtual_hook( id, data );
+}
+
+
+// defined in tdehtml_part.cpp
+extern const int KDE_NO_EXPORT fastZoomSizes[];
+extern const int KDE_NO_EXPORT fastZoomSizeCount;
+
+// BCI: remove in KDE 4
+KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const TQString &text, const TQString &icon, const TQObject *receiver, const char *slot, TQObject *parent, const char *name )
+ : KAction( text, icon, 0, receiver, slot, parent, name )
+{
+ init(part, direction);
+}
+
+KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const TQString &text, const TQString &icon, const KShortcut &cut, const TQObject *receiver, const char *slot, TQObject *parent, const char *name )
+ : KAction( text, icon, cut, receiver, slot, parent, name )
+{
+ init(part, direction);
+}
+
+void KHTMLZoomFactorAction::init(KHTMLPart *part, bool direction)
+{
+ m_direction = direction;
+ m_part = part;
+
+ m_popup = new TQPopupMenu;
+ // xgettext: no-c-format
+ m_popup->insertItem( i18n( "Default Font Size (100%)" ) );
+
+ int m = m_direction ? 1 : -1;
+ int ofs = fastZoomSizeCount / 2; // take index of 100%
+
+ // this only works if there is an odd number of elements in fastZoomSizes[]
+ for ( int i = m; i != m*(ofs+1); i += m )
+ {
+ int num = i * m;
+ TQString numStr = TQString::number( num );
+ if ( num > 0 ) numStr.prepend( '+' );
+
+ // xgettext: no-c-format
+ m_popup->insertItem( i18n( "%1%" ).arg( fastZoomSizes[ofs + i] ) );
+ }
+
+ connect( m_popup, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotActivated( int ) ) );
+}
+
+KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
+{
+ delete m_popup;
+}
+
+int KHTMLZoomFactorAction::plug( TQWidget *w, int index )
+{
+ int containerId = KAction::plug( w, index );
+ if ( containerId == -1 || !w->inherits( "KToolBar" ) )
+ return containerId;
+
+ KToolBarButton *button = static_cast<KToolBar *>( w )->getButton( itemId( containerId ) );
+ if ( !button )
+ return containerId;
+
+ button->setDelayedPopup( m_popup );
+ return containerId;
+}
+
+void KHTMLZoomFactorAction::slotActivated( int id )
+{
+ int idx = m_popup->indexOf( id );
+
+ if (idx == 0)
+ m_part->setZoomFactor(100);
+ else
+ m_part->setZoomFactor(fastZoomSizes[fastZoomSizeCount/2 + (m_direction ? 1 : -1)*idx]);
+}
+
+#include "tdehtml_ext.moc"
+
diff --git a/tdehtml/tdehtml_ext.h b/tdehtml/tdehtml_ext.h
new file mode 100644
index 000000000..5e2eafa9e
--- /dev/null
+++ b/tdehtml/tdehtml_ext.h
@@ -0,0 +1,177 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000-2003 Simon Hausmann <hausmann@kde.org>
+ * 2001-2003 George Staikos <staikos@kde.org>
+ * 2001-2003 Laurent Montel <montel@kde.org>
+ * 2001-2003 Dirk Mueller <mueller@kde.org>
+ * 2001-2003 Waldo Bastian <bastian@kde.org>
+ * 2001-2003 David Faure <faure@kde.org>
+ * 2001-2003 Daniel Naber <dnaber@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 __tdehtml_ext_h__
+#define __tdehtml_ext_h__
+
+#include "tdehtml_part.h"
+
+#include <tqguardedptr.h>
+
+#include <kaction.h>
+#include <kio/global.h>
+
+/**
+ * This is the BrowserExtension for a KHTMLPart document. Please see the KParts documentation for
+ * more information about the BrowserExtension.
+ */
+class KHTMLPartBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+ friend class KHTMLPart;
+ friend class KHTMLView;
+public:
+ KHTMLPartBrowserExtension( KHTMLPart *parent, const char *name = 0L );
+
+ virtual int xOffset();
+ virtual int yOffset();
+
+ virtual void saveState( TQDataStream &stream );
+ virtual void restoreState( TQDataStream &stream );
+
+ // internal
+ void editableWidgetFocused( TQWidget *widget );
+ void editableWidgetBlurred( TQWidget *widget );
+
+ void setExtensionProxy( KParts::BrowserExtension *proxyExtension );
+
+public slots:
+ void cut();
+ void copy();
+ void paste();
+ void searchProvider();
+ void openSelection();
+ void reparseConfiguration();
+ void print();
+ void disableScrolling();
+
+ // internal . updates the state of the cut/copt/paste action based
+ // on whether data is available in the clipboard
+ void updateEditActions();
+
+private slots:
+ // connected to a frame's browserextensions enableAction signal
+ void extensionProxyActionEnabled( const char *action, bool enable );
+ void extensionProxyEditableWidgetFocused();
+ void extensionProxyEditableWidgetBlurred();
+
+signals:
+ void editableWidgetFocused();
+ void editableWidgetBlurred();
+private:
+ void callExtensionProxyMethod( const char *method );
+
+ KHTMLPart *m_part;
+ TQGuardedPtr<TQWidget> m_editableFormWidget;
+ TQGuardedPtr<KParts::BrowserExtension> m_extensionProxy;
+ bool m_connectedToClipboard;
+};
+
+class KHTMLPartBrowserHostExtension : public KParts::BrowserHostExtension
+{
+public:
+ KHTMLPartBrowserHostExtension( KHTMLPart *part );
+ virtual ~KHTMLPartBrowserHostExtension();
+
+ virtual TQStringList frameNames() const;
+
+ virtual const TQPtrList<KParts::ReadOnlyPart> frames() const;
+
+ virtual bool openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KHTMLPart *m_part;
+};
+
+/**
+ * @internal
+ * INTERNAL class. *NOT* part of the public API.
+ */
+class KHTMLPopupGUIClient : public TQObject, public KXMLGUIClient
+{
+ Q_OBJECT
+public:
+ KHTMLPopupGUIClient( KHTMLPart *tdehtml, const TQString &doc, const KURL &url );
+ virtual ~KHTMLPopupGUIClient();
+
+ static void saveURL( TQWidget *parent, const TQString &caption, const KURL &url,
+ const TQMap<TQString, TQString> &metaData = TDEIO::MetaData(),
+ const TQString &filter = TQString::null, long cacheId = 0,
+ const TQString &suggestedFilename = TQString::null );
+
+ static void saveURL( const KURL &url, const KURL &destination,
+ const TQMap<TQString, TQString> &metaData = TDEIO::MetaData(),
+ long cacheId = 0 );
+private slots:
+ void slotSaveLinkAs();
+ void slotSaveImageAs();
+ void slotCopyLinkLocation();
+ void slotSendImage();
+ void slotStopAnimations();
+ void slotCopyImageLocation();
+ void slotCopyImage();
+ void slotViewImage();
+ void slotReloadFrame();
+ void slotFrameInWindow();
+ void slotFrameInTop();
+ void slotFrameInTab();
+ void slotBlockImage();
+ void slotBlockHost();
+ void slotBlockIFrame();
+
+private:
+ class KHTMLPopupGUIClientPrivate;
+ KHTMLPopupGUIClientPrivate *d;
+};
+
+class KHTMLZoomFactorAction : public KAction
+{
+ Q_OBJECT
+public:
+ //BCI: remove in KDE 4
+ KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const TQString &text, const TQString &icon, const TQObject *receiver, const char *slot, TQObject *parent, const char *name );
+ KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const TQString &text,
+ const TQString &icon, const KShortcut& cut, const TQObject *receiver,
+ const char *slot, TQObject *parent, const char *name );
+ virtual ~KHTMLZoomFactorAction();
+
+ virtual int plug( TQWidget *widget, int index );
+
+private slots:
+ void slotActivated( int );
+protected slots:
+ void slotActivated() { KAction::slotActivated(); }
+private:
+ void init(KHTMLPart *part, bool direction);
+private:
+ TQPopupMenu *m_popup;
+ bool m_direction;
+ KHTMLPart *m_part;
+};
+
+#endif
diff --git a/tdehtml/tdehtml_factory.cpp b/tdehtml/tdehtml_factory.cpp
new file mode 100644
index 000000000..9d0ec6d36
--- /dev/null
+++ b/tdehtml/tdehtml_factory.cpp
@@ -0,0 +1,207 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (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.
+ */
+
+#include "tdehtml_factory.h"
+#include "tdehtml_part.h"
+#include "tdehtml_settings.h"
+
+#include "css/cssstyleselector.h"
+#include "html/html_imageimpl.h"
+#include "rendering/render_style.h"
+#include "rendering/break_lines.h"
+#include "misc/loader.h"
+#include "misc/arena.h"
+
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+
+#include <assert.h>
+
+#include <kdebug.h>
+
+template class TQPtrList<KHTMLPart>;
+
+extern "C" KDE_EXPORT void *init_libtdehtml()
+{
+ // We can't use a plain self() here, because that would
+ // return the global factory, which might already exist
+ // at the time init_libtdehtml is called! As soon as someone
+ // does new KHTMLPart() in his application and loads up
+ // an html document into that part which either embeds
+ // embeds another KHTMLPart instance via <object> or
+ // as html frame, then we cannot return self(), as
+ // what we return here is what the KLibLoader deletes
+ // in the end, and we don't want the libloader to
+ // delete our global instance. Anyway, the new
+ // KHTMLFactory we create here is very cheap :)
+ // (Simon)
+ return new KHTMLFactory( true );
+}
+
+KHTMLFactory *KHTMLFactory::s_self = 0;
+unsigned long int KHTMLFactory::s_refcnt = 0;
+TDEInstance *KHTMLFactory::s_instance = 0;
+TDEAboutData *KHTMLFactory::s_about = 0;
+KHTMLSettings *KHTMLFactory::s_settings = 0;
+TQPtrList<KHTMLPart> *KHTMLFactory::s_parts = 0;
+TQString *KHTMLSettings::avFamilies = 0;
+
+KHTMLFactory::KHTMLFactory( bool clone )
+{
+ if ( clone )
+ ref();
+}
+
+KHTMLFactory::~KHTMLFactory()
+{
+ if ( s_self == this )
+ {
+ assert( !s_refcnt );
+
+ delete s_instance;
+ delete s_about;
+ delete s_settings;
+ delete KHTMLSettings::avFamilies;
+ if ( s_parts )
+ {
+ assert( s_parts->isEmpty() );
+ delete s_parts;
+ }
+
+ s_instance = 0;
+ s_about = 0;
+ s_settings = 0;
+ s_parts = 0;
+ KHTMLSettings::avFamilies = 0;
+
+ // clean up static data
+ tdehtml::CSSStyleSelector::clear();
+ tdehtml::RenderStyle::cleanup();
+ tdehtml::Cache::clear();
+ tdehtml::cleanup_thaibreaks();
+ tdehtml::ArenaFinish();
+ }
+ else
+ deref();
+}
+
+KParts::Part *KHTMLFactory::createPartObject( TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const char *className, const TQStringList & )
+{
+ KHTMLPart::GUIProfile prof = KHTMLPart::DefaultGUI;
+ if ( strcmp( className, "Browser/View" ) == 0 )
+ prof = KHTMLPart::BrowserViewGUI;
+
+ return new KHTMLPart( parentWidget, widgetName, parent, name, prof );
+}
+
+void KHTMLFactory::ref()
+{
+ if ( !s_refcnt && !s_self )
+ {
+ // we can't use a staticdeleter here, because that would mean
+ // that the factory gets deleted from within a qPostRoutine, called
+ // from the TQApplication destructor. That however is too late, because
+ // we want to destruct a TDEInstance object, which involves destructing
+ // a TDEConfig object, which might call TDEGlobal::dirs() (in sync()) which
+ // probably is not going to work ;-)
+ // well, perhaps I'm wrong here, but as I'm unsure I try to stay on the
+ // safe side ;-) -> let's use a simple reference counting scheme
+ // (Simon)
+ s_self = new KHTMLFactory;
+ tdehtml::Cache::init();
+ }
+
+ s_refcnt++;
+}
+
+void KHTMLFactory::deref()
+{
+ if ( !--s_refcnt && s_self )
+ {
+ delete s_self;
+ s_self = 0;
+ }
+}
+
+void KHTMLFactory::registerPart( KHTMLPart *part )
+{
+ if ( !s_parts )
+ s_parts = new TQPtrList<KHTMLPart>;
+
+ if ( !s_parts->containsRef( part ) )
+ {
+ s_parts->append( part );
+ ref();
+ }
+}
+
+void KHTMLFactory::deregisterPart( KHTMLPart *part )
+{
+ assert( s_parts );
+
+ if ( s_parts->removeRef( part ) )
+ {
+ if ( s_parts->isEmpty() )
+ {
+ delete s_parts;
+ s_parts = 0;
+ }
+ deref();
+ }
+}
+
+TDEInstance *KHTMLFactory::instance()
+{
+ assert( s_self );
+
+ if ( !s_instance )
+ {
+ s_about = new TDEAboutData( "tdehtml", I18N_NOOP( "KHTML" ), "4.0",
+ I18N_NOOP( "Embeddable HTML component" ),
+ TDEAboutData::License_LGPL );
+ s_about->addAuthor( "Lars Knoll", 0, "knoll@kde.org" );
+ s_about->addAuthor( "Antti Koivisto", 0, "koivisto@kde.org" );
+ s_about->addAuthor( "Waldo Bastian", 0, "bastian@kde.org" );
+ s_about->addAuthor( "Dirk Mueller", 0, "mueller@kde.org" );
+ s_about->addAuthor( "Peter Kelly", 0, "pmk@kde.org" );
+ s_about->addAuthor( "Torben Weis", 0, "weis@kde.org" );
+ s_about->addAuthor( "Martin Jones", 0, "mjones@kde.org" );
+ s_about->addAuthor( "Simon Hausmann", 0, "hausmann@kde.org" );
+ s_about->addAuthor( "Tobias Anton", 0, "anton@stud.fbi.fh-darmstadt.de" );
+
+ s_instance = new TDEInstance( s_about );
+ }
+
+ return s_instance;
+}
+
+KHTMLSettings *KHTMLFactory::defaultHTMLSettings()
+{
+ assert( s_self );
+ if ( !s_settings )
+ s_settings = new KHTMLSettings();
+
+ return s_settings;
+}
+
+using namespace KParts;
+#include "tdehtml_factory.moc"
+
diff --git a/tdehtml/tdehtml_factory.h b/tdehtml/tdehtml_factory.h
new file mode 100644
index 000000000..2177a2602
--- /dev/null
+++ b/tdehtml/tdehtml_factory.h
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (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 __tdehtml_factory_h__
+#define __tdehtml_factory_h__
+
+#include <tdeparts/factory.h>
+#include <tdeparts/historyprovider.h>
+#include <tqptrlist.h>
+#include <kurl.h>
+
+class TDEInstance;
+class TDEAboutData;
+class HistoryProvider;
+class KHTMLSettings;
+class KHTMLPart;
+
+namespace DOM
+{
+ class DocumentImpl;
+}
+
+class KDE_EXPORT KHTMLFactory : public KParts::Factory
+{
+ Q_OBJECT
+ friend class DOM::DocumentImpl;
+ friend class KHTMLViewPrivate;
+public:
+ KHTMLFactory( bool clone = false );
+ virtual ~KHTMLFactory();
+
+ virtual KParts::Part *createPartObject( TQWidget *parentWidget, const char *widgetName, TQObject *parent, const char *name, const char *className, const TQStringList &args );
+
+ static void registerPart( KHTMLPart *part );
+ static void deregisterPart( KHTMLPart *part );
+
+ static TQPtrList<KHTMLPart> *partList() { return s_parts; }
+
+ static TDEInstance *instance();
+
+ static KHTMLSettings *defaultHTMLSettings();
+
+ // list of visited URLs
+ static KParts::HistoryProvider *vLinks() {
+ return KParts::HistoryProvider::self();
+ }
+
+protected:
+ static void ref();
+ static void deref();
+private:
+ static unsigned long s_refcnt;
+ static KHTMLFactory *s_self;
+ static TDEInstance *s_instance;
+ static TDEAboutData *s_about;
+ static KHTMLSettings *s_settings;
+ static TQPtrList<KHTMLPart> *s_parts;
+};
+
+#endif
diff --git a/tdehtml/tdehtml_iface.cc b/tdehtml/tdehtml_iface.cc
new file mode 100644
index 000000000..e42562c51
--- /dev/null
+++ b/tdehtml/tdehtml_iface.cc
@@ -0,0 +1,233 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2002 Stephan Kulow <coolo@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 "tdehtml_iface.h"
+#include "tdehtml_part.h"
+#include "tdehtmlview.h"
+#include "tdehtml_ext.h"
+#include <kio/global.h>
+#include <tqapplication.h>
+#include <tqvariant.h>
+
+KHTMLPartIface::KHTMLPartIface( KHTMLPart *_part )
+ : DCOPObject( _part->dcopObjectId() ), part(_part)
+{
+}
+
+KHTMLPartIface::~KHTMLPartIface()
+{
+}
+
+KURL KHTMLPartIface::url() const
+{
+ return part->url();
+}
+
+void KHTMLPartIface::setJScriptEnabled( bool enable )
+{
+ part->setJScriptEnabled(enable);
+}
+
+bool KHTMLPartIface::jScriptEnabled() const
+{
+ return part->jScriptEnabled();
+}
+
+bool KHTMLPartIface::closeURL()
+{
+ return part->closeURL();
+}
+
+bool KHTMLPartIface::metaRefreshEnabled() const
+{
+ return part->metaRefreshEnabled();
+}
+
+void KHTMLPartIface::setDNDEnabled( bool b )
+{
+ part->setDNDEnabled(b);
+}
+
+bool KHTMLPartIface::dndEnabled() const
+{
+ return part->dndEnabled();
+}
+
+void KHTMLPartIface::setJavaEnabled( bool enable )
+{
+ part->setJavaEnabled( enable );
+}
+
+bool KHTMLPartIface::javaEnabled() const
+{
+ return part->javaEnabled();
+}
+
+void KHTMLPartIface::setPluginsEnabled( bool enable )
+{
+ part->setPluginsEnabled( enable );
+}
+
+bool KHTMLPartIface::pluginsEnabled() const
+{
+ return part->pluginsEnabled();
+}
+
+void KHTMLPartIface::setAutoloadImages( bool enable )
+{
+ part->setAutoloadImages( enable );
+}
+
+bool KHTMLPartIface::autoloadImages() const
+{
+ return part->autoloadImages();
+}
+
+void KHTMLPartIface::setOnlyLocalReferences(bool enable)
+{
+ part->setOnlyLocalReferences(enable);
+}
+
+void KHTMLPartIface::setMetaRefreshEnabled( bool enable )
+{
+ part->setMetaRefreshEnabled(enable);
+}
+
+bool KHTMLPartIface::onlyLocalReferences() const
+{
+ return part->onlyLocalReferences();
+}
+
+bool KHTMLPartIface::setEncoding( const TQString &name )
+{
+ return part->setEncoding(name);
+}
+
+TQString KHTMLPartIface::encoding() const
+{
+ return part->encoding();
+}
+
+void KHTMLPartIface::setFixedFont( const TQString &name )
+{
+ part->setFixedFont(name);
+
+}
+
+bool KHTMLPartIface::gotoAnchor( const TQString &name )
+{
+ return part->gotoAnchor(name);
+}
+
+bool KHTMLPartIface::nextAnchor()
+{
+ return part->nextAnchor();
+}
+
+bool KHTMLPartIface::prevAnchor()
+{
+ return part->prevAnchor();
+}
+
+void KHTMLPartIface::activateNode()
+{
+ KParts::ReadOnlyPart* p = part->currentFrame();
+ if ( p && p->widget() ) {
+ TQKeyEvent ev( TQKeyEvent::KeyPress, Qt::Key_Return, '\n', 0, "\n" );
+ TQApplication::sendEvent( p->widget(), &ev );
+ }
+}
+
+void KHTMLPartIface::selectAll()
+{
+ part->selectAll();
+}
+
+TQString KHTMLPartIface::lastModified() const
+{
+ return part->lastModified();
+}
+
+void KHTMLPartIface::debugRenderTree()
+{
+ part->slotDebugRenderTree();
+}
+
+void KHTMLPartIface::debugDOMTree()
+{
+ part->slotDebugDOMTree();
+}
+
+void KHTMLPartIface::stopAnimations()
+{
+ part->slotStopAnimations();
+}
+
+void KHTMLPartIface::viewDocumentSource()
+{
+ part->slotViewDocumentSource();
+}
+
+void KHTMLPartIface::saveBackground(const TQString &destination)
+{
+ KURL back = part->backgroundURL();
+ if (back.isEmpty())
+ return;
+
+ TDEIO::MetaData metaData;
+ metaData["referrer"] = part->referrer();
+ KHTMLPopupGUIClient::saveURL( back, KURL( destination ), metaData );
+}
+
+void KHTMLPartIface::saveDocument(const TQString &destination)
+{
+ KURL srcURL( part->url() );
+
+ if ( srcURL.fileName(false).isEmpty() )
+ srcURL.setFileName( "index.html" );
+
+ TDEIO::MetaData metaData;
+ // Referrer unknown?
+ KHTMLPopupGUIClient::saveURL( srcURL, KURL( destination ), metaData, part->cacheId() );
+}
+
+void KHTMLPartIface::setUserStyleSheet(const TQString &styleSheet)
+{
+ part->setUserStyleSheet(styleSheet);
+}
+
+TQString KHTMLPartIface::selectedText() const
+{
+ return part->selectedText();
+}
+
+void KHTMLPartIface::viewFrameSource()
+{
+ part->slotViewFrameSource();
+}
+
+TQString KHTMLPartIface::evalJS(const TQString &script)
+{
+ return part->executeScript(DOM::Node(), script).toString();
+}
+
+void KHTMLPartIface::print( bool quick ) {
+ part->view()->print( quick );
+}
diff --git a/tdehtml/tdehtml_iface.h b/tdehtml/tdehtml_iface.h
new file mode 100644
index 000000000..d4c34940b
--- /dev/null
+++ b/tdehtml/tdehtml_iface.h
@@ -0,0 +1,242 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2002 Stephan Kulow <coolo@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 __tdehtml_Iface_h__
+#define __tdehtml_Iface_h__
+
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <kurl.h>
+
+class KHTMLPart;
+
+/**
+ * DCOP interface for KHTML
+ */
+class KHTMLPartIface : public DCOPObject
+{
+ K_DCOP
+
+public:
+
+ KHTMLPartIface( KHTMLPart * );
+ virtual ~KHTMLPartIface();
+
+k_dcop:
+ /**
+ * @return the current URL
+ */
+ KURL url() const;
+
+ bool closeURL();
+
+ /**
+ * Enable/disable Javascript support. Note that this will
+ * in either case permanently override the default usersetting.
+ * If you want to have the default UserSettings, don't call this
+ * method.
+ */
+ void setJScriptEnabled( bool enable );
+
+ /**
+ * Returns @p true if Javascript support is enabled or @p false
+ * otherwise.
+ */
+ bool jScriptEnabled() const;
+
+ /**
+ * Enable/disable the automatic forwarding by <meta http-equiv="refresh" ....>
+ */
+ void setMetaRefreshEnabled( bool enable );
+
+ /**
+ * Returns @p true if automtaic forwarding is enabled.
+ */
+ bool metaRefreshEnabled() const;
+
+ /**
+ * Enables or disables Drag'n'Drop support. A drag operation is started if
+ * the users drags a link.
+ */
+ void setDNDEnabled( bool b );
+
+ /**
+ * Returns whether Dragn'n'Drop support is enabled or not.
+ */
+ bool dndEnabled() const;
+
+ /**
+ * Enables/disables Java applet support. Note that calling this function
+ * will permanently override the User settings about Java applet support.
+ * Not calling this function is the only way to let the default settings
+ * apply.
+ */
+ void setJavaEnabled( bool enable );
+
+ /**
+ * Return if Java applet support is enabled/disabled.
+ */
+ bool javaEnabled() const;
+
+
+ /**
+ * Enables or disables plugins via, default is enabled
+ */
+ void setPluginsEnabled( bool enable );
+
+ /**
+ * Returns trie if plugins are enabled/disabled.
+ */
+ bool pluginsEnabled() const;
+
+ /**
+ * Specifies whether images contained in the document should be loaded
+ * automatically or not.
+ *
+ * @note Request will be ignored if called before begin().
+ */
+ void setAutoloadImages( bool enable );
+
+ /**
+ * Returns whether images contained in the document are loaded automatically
+ * or not.
+ * @note that the returned information is unrelieable as long as no begin()
+ * was called.
+ */
+ bool autoloadImages() const;
+
+ /**
+ * Security option.
+ *
+ * Specify whether only local references ( stylesheets, images, scripts, subdocuments )
+ * should be loaded. ( default false - everything is loaded, if the more specific
+ * options allow )
+ */
+ void setOnlyLocalReferences(bool enable);
+
+ /**
+ * Returns whether references should be loaded ( default false )
+ **/
+ bool onlyLocalReferences() const;
+
+ /**
+ * Sets the encoding the page uses.
+ *
+ * This can be different from the charset. The widget will try to reload
+ * the current page in the new encoding, if url() is not empty.
+ */
+ bool setEncoding( const TQString &name );
+
+ /**
+ * Returns the encoding the page currently uses.
+ *
+ * Note that the encoding might be different from the charset.
+ */
+ TQString encoding() const;
+
+ /**
+ * Sets a user defined style sheet to be used on top of the HTML 4
+ * default style sheet.
+ *
+ * This gives a wide range of possibilities to
+ * change the layout of the page.
+ */
+ void setUserStyleSheet(const TQString &styleSheet);
+
+ /**
+ * Sets the fixed font style.
+ *
+ * @param name The font name to use for fixed text, e.g.
+ * the <tt>&lt;pre&gt;</tt> tag.
+ */
+ void setFixedFont( const TQString &name );
+
+ /**
+ * Finds the anchor named @p name.
+ *
+ * If the anchor is found, the widget
+ * scrolls to the closest position. Returns @p true if the anchor has
+ * been found.
+ */
+ bool gotoAnchor( const TQString &name );
+
+ /**
+ * Go to next Anchor.
+ *
+ * This is useful to navigate from outside of the navigator.
+ * @since 3.2
+ */
+ bool nextAnchor();
+
+ /**
+ * Go to previous Anchor.
+ * @since 3.2
+ */
+ bool prevAnchor();
+
+ /**
+ * Activate the node that currently has the focus
+ * (emulates pressing Return)
+ */
+ void activateNode();
+
+ /**
+ * Returns the text the user has marked.
+ */
+ TQString selectedText() const;
+
+ /**
+ * Marks all text in the document as selected.
+ */
+ void selectAll();
+
+ /**
+ * Last-modified date (in raw string format), if received in the [HTTP] headers.
+ */
+ TQString lastModified() const;
+
+ /**
+ * Print the contents of the current html view.
+ * @param quick if true, fully automated printing, without the print dialog.
+ */
+ ASYNC print( bool quick );
+
+ void debugRenderTree();
+ void debugDOMTree();
+ void viewDocumentSource();
+ void viewFrameSource();
+ void saveBackground(const TQString &url);
+ void saveDocument(const TQString &url);
+
+ /**
+ * Evaluate a given piece of Javascript code
+ */
+ TQString evalJS(const TQString &script);
+
+ /**
+ * Stops display of animated images
+ */
+ void stopAnimations();
+
+private:
+ KHTMLPart *part;
+};
+
+#endif
+
diff --git a/tdehtml/tdehtml_pagecache.cpp b/tdehtml/tdehtml_pagecache.cpp
new file mode 100644
index 000000000..bde26c9de
--- /dev/null
+++ b/tdehtml/tdehtml_pagecache.cpp
@@ -0,0 +1,313 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Waldo Bastian <bastian@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 "tdehtml_pagecache.h"
+
+#include <kstaticdeleter.h>
+#include <ktempfile.h>
+#include <kstandarddirs.h>
+
+#include <tqintdict.h>
+#include <tqtimer.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+
+// We keep 12 pages in memory.
+#ifndef KHTML_PAGE_CACHE_SIZE
+#define KHTML_PAGE_CACHE_SIZE 12
+#endif
+
+template class TQPtrList<KHTMLPageCacheDelivery>;
+class KHTMLPageCacheEntry
+{
+ friend class KHTMLPageCache;
+public:
+ KHTMLPageCacheEntry(long id);
+
+ ~KHTMLPageCacheEntry();
+
+ void addData(const TQByteArray &data);
+
+ void endData();
+
+ bool isComplete()
+ { return m_complete; }
+
+ KHTMLPageCacheDelivery *fetchData(TQObject *recvObj, const char *recvSlot);
+private:
+ long m_id;
+ bool m_complete;
+ TQValueList<TQByteArray> m_data;
+ KTempFile *m_file;
+};
+
+class KHTMLPageCachePrivate
+{
+public:
+ long newId;
+ TQIntDict<KHTMLPageCacheEntry> dict;
+ TQPtrList<KHTMLPageCacheDelivery> delivery;
+ TQPtrList<KHTMLPageCacheEntry> expireQueue;
+ bool deliveryActive;
+};
+
+KHTMLPageCacheEntry::KHTMLPageCacheEntry(long id) : m_id(id), m_complete(false)
+{
+ TQString path = locateLocal("tmp", "tdehtmlcache");
+ m_file = new KTempFile(path);
+ m_file->unlink();
+}
+
+KHTMLPageCacheEntry::~KHTMLPageCacheEntry()
+{
+ delete m_file;
+}
+
+
+void
+KHTMLPageCacheEntry::addData(const TQByteArray &data)
+{
+ if (m_file->status() == 0)
+ m_file->dataStream()->writeRawBytes(data.data(), data.size());
+}
+
+void
+KHTMLPageCacheEntry::endData()
+{
+ m_complete = true;
+ if ( m_file->status() == 0) {
+ m_file->dataStream()->device()->flush();
+ m_file->dataStream()->device()->at(0);
+ }
+}
+
+
+KHTMLPageCacheDelivery *
+KHTMLPageCacheEntry::fetchData(TQObject *recvObj, const char *recvSlot)
+{
+ // Duplicate fd so that entry can be safely deleted while delivering the data.
+ int fd = dup(m_file->handle());
+ lseek(fd, 0, SEEK_SET);
+ KHTMLPageCacheDelivery *delivery = new KHTMLPageCacheDelivery(fd);
+ recvObj->connect(delivery, TQT_SIGNAL(emitData(const TQByteArray&)), recvSlot);
+ delivery->recvObj = recvObj;
+ return delivery;
+}
+
+static KStaticDeleter<KHTMLPageCache> pageCacheDeleter;
+
+KHTMLPageCache *KHTMLPageCache::_self = 0;
+
+KHTMLPageCache *
+KHTMLPageCache::self()
+{
+ if (!_self)
+ _self = pageCacheDeleter.setObject(_self, new KHTMLPageCache);
+ return _self;
+}
+
+KHTMLPageCache::KHTMLPageCache()
+{
+ d = new KHTMLPageCachePrivate;
+ d->newId = 1;
+ d->deliveryActive = false;
+}
+
+KHTMLPageCache::~KHTMLPageCache()
+{
+ d->delivery.setAutoDelete(true);
+ d->dict.setAutoDelete(true);
+ delete d;
+}
+
+long
+KHTMLPageCache::createCacheEntry()
+{
+ KHTMLPageCacheEntry *entry = new KHTMLPageCacheEntry(d->newId);
+ d->dict.insert(d->newId, entry);
+ d->expireQueue.append(entry);
+ if (d->expireQueue.count() > KHTML_PAGE_CACHE_SIZE)
+ {
+ KHTMLPageCacheEntry *entry = d->expireQueue.take(0);
+ d->dict.remove(entry->m_id);
+ delete entry;
+ }
+ return (d->newId++);
+}
+
+void
+KHTMLPageCache::addData(long id, const TQByteArray &data)
+{
+ KHTMLPageCacheEntry *entry = d->dict.find(id);
+ if (entry)
+ entry->addData(data);
+}
+
+void
+KHTMLPageCache::endData(long id)
+{
+ KHTMLPageCacheEntry *entry = d->dict.find(id);
+ if (entry)
+ entry->endData();
+}
+
+void
+KHTMLPageCache::cancelEntry(long id)
+{
+ KHTMLPageCacheEntry *entry = d->dict.take(id);
+ if (entry)
+ {
+ d->expireQueue.removeRef(entry);
+ delete entry;
+ }
+}
+
+bool
+KHTMLPageCache::isValid(long id)
+{
+ return (d->dict.find(id) != 0);
+}
+
+bool
+KHTMLPageCache::isComplete(long id)
+{
+ KHTMLPageCacheEntry *entry = d->dict.find(id);
+ if (entry)
+ return entry->isComplete();
+ return false;
+}
+
+void
+KHTMLPageCache::fetchData(long id, TQObject *recvObj, const char *recvSlot)
+{
+ KHTMLPageCacheEntry *entry = d->dict.find(id);
+ if (!entry || !entry->isComplete()) return;
+
+ // Make this entry the most recent entry.
+ d->expireQueue.removeRef(entry);
+ d->expireQueue.append(entry);
+
+ d->delivery.append( entry->fetchData(recvObj, recvSlot) );
+ if (!d->deliveryActive)
+ {
+ d->deliveryActive = true;
+ TQTimer::singleShot(20, this, TQT_SLOT(sendData()));
+ }
+}
+
+void
+KHTMLPageCache::cancelFetch(TQObject *recvObj)
+{
+ KHTMLPageCacheDelivery *next;
+ for(KHTMLPageCacheDelivery* delivery = d->delivery.first();
+ delivery;
+ delivery = next)
+ {
+ next = d->delivery.next();
+ if (delivery->recvObj == recvObj)
+ {
+ d->delivery.removeRef(delivery);
+ delete delivery;
+ }
+ }
+}
+
+void
+KHTMLPageCache::sendData()
+{
+ if (d->delivery.isEmpty())
+ {
+ d->deliveryActive = false;
+ return;
+ }
+ KHTMLPageCacheDelivery *delivery = d->delivery.take(0);
+ assert(delivery);
+
+ char buf[8192];
+ TQByteArray byteArray;
+
+ int n = read(delivery->fd, buf, 8192);
+
+ if ((n < 0) && (errno == EINTR))
+ {
+ // try again later
+ d->delivery.append( delivery );
+ }
+ else if (n <= 0)
+ {
+ // done.
+ delivery->emitData(byteArray); // Empty array
+ delete delivery;
+ }
+ else
+ {
+ byteArray.setRawData(buf, n);
+ delivery->emitData(byteArray);
+ byteArray.resetRawData(buf, n);
+ d->delivery.append( delivery );
+ }
+ TQTimer::singleShot(0, this, TQT_SLOT(sendData()));
+}
+
+void
+KHTMLPageCache::saveData(long id, TQDataStream *str)
+{
+ KHTMLPageCacheEntry *entry = d->dict.find(id);
+ assert(entry);
+
+ int fd = entry->m_file->handle();
+ if ( fd < 0 ) return;
+
+ off_t pos = lseek(fd, 0, SEEK_CUR);
+ lseek(fd, 0, SEEK_SET);
+
+ char buf[8192];
+
+ while(true)
+ {
+ int n = read(fd, buf, 8192);
+ if ((n < 0) && (errno == EINTR))
+ {
+ // try again
+ continue;
+ }
+ else if (n <= 0)
+ {
+ // done.
+ break;
+ }
+ else
+ {
+ str->writeRawBytes(buf, n);
+ }
+ }
+
+ if (pos != (off_t)-1)
+ lseek(fd, pos, SEEK_SET);
+}
+
+KHTMLPageCacheDelivery::~KHTMLPageCacheDelivery()
+{
+ close(fd);
+}
+
+#include "tdehtml_pagecache.moc"
diff --git a/tdehtml/tdehtml_pagecache.h b/tdehtml/tdehtml_pagecache.h
new file mode 100644
index 000000000..e2992faa4
--- /dev/null
+++ b/tdehtml/tdehtml_pagecache.h
@@ -0,0 +1,134 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 2000 Waldo Bastian <bastian@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 __tdehtml_pagecache_h__
+#define __tdehtml_pagecache_h__
+
+#include <tqobject.h>
+#include <tqcstring.h>
+#include <tqvaluelist.h>
+#include <tqptrlist.h>
+
+class KHTMLPageCachePrivate;
+
+/**
+ * Singleton Object that handles a binary cache on top of
+ * the http cache management of kio.
+ *
+ * A limited number of HTML pages are stored in this cache. This
+ * cache is used for the history and operations like "view source".
+ * These operations always want to use the original document and
+ * don't want to fetch the data from the network again.
+ *
+ * It operates completely independent from the kio_http cache.
+ */
+class KHTMLPageCache : public TQObject
+{
+ Q_OBJECT
+public:
+ /**
+ * static "constructor".
+ * @return returns a pointer to the cache, if it exists.
+ * creates a new cache otherwise.
+ */
+ static KHTMLPageCache *self();
+ ~KHTMLPageCache();
+
+ /**
+ * Create a new cache entry.
+ *
+ * @return a cache entry ID is returned.
+ */
+ long createCacheEntry();
+
+ /**
+ * Add @p data to the cache entry with id @p id.
+ */
+ void addData(long id, const TQByteArray &data);
+
+ /**
+ * Signal end of data for the cache entry with id @p id.
+ * After calling this the entry is marked complete
+ */
+ void endData(long id);
+
+ /**
+ * Cancel the entry.
+ */
+ void cancelEntry(long id);
+
+ /**
+ * @return true when the cache entry with id @p is still valid,
+ * and at least some of the data is available for reading (the
+ * complete data may not yet be loaded)
+ */
+ bool isValid(long id);
+
+ /**
+ * @return true when the cache entry with id @p is still valid,
+ * and the complete data is available for reading
+ */
+ bool isComplete(long id);
+
+ /**
+ * Fetch data for cache entry @p id and send it to slot @p recvSlot
+ * in the object @p recvObj
+ */
+ void fetchData(long id, TQObject *recvObj, const char *recvSlot);
+
+ /**
+ * Cancel sending data to @p recvObj
+ */
+ void cancelFetch(TQObject *recvObj);
+
+ /**
+ * Save the data of cache entry @p id to the datastream @p str
+ */
+ void saveData(long id, TQDataStream *str);
+
+private slots:
+ void sendData();
+
+private:
+ KHTMLPageCache();
+
+ static KHTMLPageCache *_self;
+
+ KHTMLPageCachePrivate *d;
+};
+
+class KHTMLPageCacheDelivery : public TQObject
+{
+ friend class KHTMLPageCache;
+Q_OBJECT
+public:
+ KHTMLPageCacheDelivery(int _fd)
+ : fd(_fd) { }
+ ~KHTMLPageCacheDelivery();
+
+signals:
+ void emitData(const TQByteArray &data);
+
+public:
+ TQObject *recvObj;
+ int fd;
+};
+
+
+#endif
diff --git a/tdehtml/tdehtml_part.cpp b/tdehtml/tdehtml_part.cpp
new file mode 100644
index 000000000..185ded02d
--- /dev/null
+++ b/tdehtml/tdehtml_part.cpp
@@ -0,0 +1,7471 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999 Lars Knoll <knoll@kde.org>
+ * 1999 Antti Koivisto <koivisto@kde.org>
+ * 2000 Simon Hausmann <hausmann@kde.org>
+ * 2000 Stefan Schimanski <1Stein@gmx.de>
+ * 2001-2003 George Staikos <staikos@kde.org>
+ * 2001-2003 Dirk Mueller <mueller@kde.org>
+ * 2000-2005 David Faure <faure@kde.org>
+ * 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 SPEED_DEBUG
+#include "tdehtml_part.h"
+
+#include "tdehtml_pagecache.h"
+
+#include "dom/dom_string.h"
+#include "dom/dom_element.h"
+#include "dom/dom_exception.h"
+#include "html/html_documentimpl.h"
+#include "html/html_baseimpl.h"
+#include "html/html_objectimpl.h"
+#include "html/html_miscimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_objectimpl.h"
+#include "rendering/render_text.h"
+#include "rendering/render_frames.h"
+#include "rendering/render_layer.h"
+#include "misc/htmlhashes.h"
+#include "misc/loader.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom2_rangeimpl.h"
+#include "xml/xml_tokenizer.h"
+#include "css/cssstyleselector.h"
+#include "css/csshelper.h"
+using namespace DOM;
+
+#include "tdehtmlview.h"
+#include <tdeparts/partmanager.h>
+#include "ecma/kjs_proxy.h"
+#include "ecma/kjs_window.h"
+#include "tdehtml_settings.h"
+#include "kjserrordlg.h"
+
+#include <kjs/function.h>
+#include <kjs/interpreter.h>
+
+#include "htmlpageinfo.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <config.h>
+
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+#include <kio/job.h>
+#include <kio/global.h>
+#include <kio/netaccess.h>
+#include <kprotocolmanager.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kcharsets.h>
+#include <kmessagebox.h>
+#include <kstdaction.h>
+#include <kfiledialog.h>
+#include <ktrader.h>
+#include <kdatastream.h>
+#include <ktempfile.h>
+#include <kglobalsettings.h>
+#include <kurldrag.h>
+#include <kapplication.h>
+#include <tdeparts/browserinterface.h>
+#if !defined(QT_NO_DRAGANDDROP)
+#include <tdemultipledrag.h>
+#endif
+#include "../tdeutils/kfinddialog.h"
+#include "../tdeutils/kfind.h"
+
+#include <ksslcertchain.h>
+#include <ksslinfodlg.h>
+
+#include <kfileitem.h>
+#include <kurifilter.h>
+#include <kstatusbar.h>
+#include <kurllabel.h>
+
+#include <tqclipboard.h>
+#include <tqfile.h>
+#include <tqtooltip.h>
+#include <tqmetaobject.h>
+#include <tqucomextra_p.h>
+
+#include "tdehtmlpart_p.h"
+#include "kpassivepopup.h"
+#include "kpopupmenu.h"
+#include "rendering/render_form.h"
+#include <twin.h>
+
+#define HINT_UTF8 106
+
+namespace tdehtml {
+ class PartStyleSheetLoader : public CachedObjectClient
+ {
+ public:
+ PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
+ {
+ m_part = part;
+ m_cachedSheet = dl->requestStyleSheet(url, TQString(), "text/css",
+ true /* "user sheet" */);
+ if (m_cachedSheet)
+ m_cachedSheet->ref( this );
+ }
+ virtual ~PartStyleSheetLoader()
+ {
+ if ( m_cachedSheet ) m_cachedSheet->deref(this);
+ }
+ virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet, const DOM::DOMString &)
+ {
+ if ( m_part )
+ m_part->setUserStyleSheet( sheet.string() );
+
+ delete this;
+ }
+ virtual void error( int, const TQString& ) {
+ delete this;
+ }
+ TQGuardedPtr<KHTMLPart> m_part;
+ tdehtml::CachedCSSStyleSheet *m_cachedSheet;
+ };
+}
+
+void tdehtml::ChildFrame::liveConnectEvent(const unsigned long, const TQString & event, const KParts::LiveConnectExtension::ArgList & args)
+{
+ if (!m_part || !m_frame || !m_liveconnect)
+ // hmmm
+ return;
+
+ TQString script;
+ script.sprintf("%s(", event.latin1());
+
+ KParts::LiveConnectExtension::ArgList::const_iterator i = args.begin();
+ const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin = i;
+ const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd = args.end();
+
+ for ( ; i != argsEnd; ++i) {
+ if (i != argsBegin)
+ script += ",";
+ if ((*i).first == KParts::LiveConnectExtension::TypeString) {
+ script += "\"";
+ script += TQString((*i).second).replace('\\', "\\\\").replace('"', "\\\"");
+ script += "\"";
+ } else
+ script += (*i).second;
+ }
+ script += ")";
+ kdDebug(6050) << "tdehtml::ChildFrame::liveConnectEvent " << script << endl;
+
+ KHTMLPart * part = ::tqqt_cast<KHTMLPart *>(m_part->parent());
+ if (!part)
+ return;
+ if (!m_jscript)
+ part->framejScript(m_part);
+ if (m_jscript) {
+ // we have a jscript => a part in an iframe
+ KJS::Completion cmp;
+ m_jscript->evaluate(TQString(), 1, script, 0L, &cmp);
+ } else
+ part->executeScript(m_frame->element(), script);
+}
+
+KHTMLFrameList::Iterator KHTMLFrameList::find( const TQString &name )
+{
+ Iterator it = begin();
+ const Iterator e = end();
+
+ for (; it!=e; ++it )
+ if ( (*it)->m_name==name )
+ break;
+
+ return it;
+}
+
+KHTMLPart::KHTMLPart( TQWidget *parentWidget, const char *widgetname, TQObject *parent, const char *name, GUIProfile prof )
+: KParts::ReadOnlyPart( parent, name )
+{
+ d = 0;
+ KHTMLFactory::registerPart( this );
+ setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
+ // TODO KDE4 - don't load plugins yet
+ //setInstance( KHTMLFactory::instance(), false );
+ init( new KHTMLView( this, parentWidget, widgetname ), prof );
+}
+
+KHTMLPart::KHTMLPart( KHTMLView *view, TQObject *parent, const char *name, GUIProfile prof )
+: KParts::ReadOnlyPart( parent, name )
+{
+ d = 0;
+ KHTMLFactory::registerPart( this );
+ setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
+ // TODO KDE4 - don't load plugins yet
+ //setInstance( KHTMLFactory::instance(), false );
+ assert( view );
+ init( view, prof );
+}
+
+void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
+{
+ if ( prof == DefaultGUI )
+ setXMLFile( "tdehtml.rc" );
+ else if ( prof == BrowserViewGUI )
+ setXMLFile( "tdehtml_browser.rc" );
+
+ d = new KHTMLPartPrivate(parent());
+
+ d->m_view = view;
+ setWidget( d->m_view );
+
+ d->m_guiProfile = prof;
+ d->m_extension = new KHTMLPartBrowserExtension( this, "KHTMLBrowserExtension" );
+ d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
+ d->m_statusBarExtension = new KParts::StatusBarExtension( this );
+ d->m_statusBarIconLabel = 0L;
+ d->m_statusBarPopupLabel = 0L;
+ d->m_openableSuppressedPopups = 0;
+
+ d->m_bSecurityInQuestion = false;
+ d->m_paLoadImages = 0;
+ d->m_paDebugScript = 0;
+ d->m_bMousePressed = false;
+ d->m_bRightMousePressed = false;
+ d->m_bCleared = false;
+ d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, TQT_SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
+ d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, TQT_SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
+ d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, TQT_SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
+ d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, TQT_SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
+ d->m_paSaveDocument = KStdAction::saveAs( this, TQT_SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
+ if ( parentPart() )
+ d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
+ d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, TQT_SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
+ d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, TQT_SLOT( slotSecurity() ), actionCollection(), "security" );
+ d->m_paSecurity->setWhatsThis( i18n( "Security Settings<p>"
+ "Shows the certificate of the displayed page. Only "
+ "pages that have been transmitted using a secure, encrypted connection have a "
+ "certificate.<p> "
+ "Hint: If the image shows a closed lock, the page has been transmitted over a "
+ "secure connection.") );
+ d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_A, this, TQT_SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
+ d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), ALT + CTRL + SHIFT + Key_D, this, TQT_SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
+ d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, TQT_SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" );
+
+ d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" );
+ d->m_paSetEncoding->setDelayed( false );
+
+ d->m_automaticDetection = new KPopupMenu( 0L );
+
+ d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 );
+ d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 );
+ d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 );
+ d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 );
+ //d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 );
+ d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 );
+ d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 );
+ d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 );
+ //d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 );
+ d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 );
+ //d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 );
+ d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 );
+ d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 );
+ //d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 );
+ d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 );
+
+ connect( d->m_automaticDetection, TQT_SIGNAL( activated( int ) ), this, TQT_SLOT( slotAutomaticDetectionLanguage( int ) ) );
+
+ d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 );
+
+ d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) );
+
+
+ d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, TQT_SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
+ TQStringList encodings = TDEGlobal::charsets()->descriptiveEncodingNames();
+ d->m_manualDetection->setItems( encodings );
+ d->m_manualDetection->setCurrentItem( -1 );
+ d->m_paSetEncoding->insert( d->m_manualDetection );
+
+
+ TDEConfig *config = TDEGlobal::config();
+ if ( config->hasGroup( "HTML Settings" ) ) {
+ config->setGroup( "HTML Settings" );
+ tdehtml::Decoder::AutoDetectLanguage language;
+ TQCString name = TQTextCodec::codecForLocale()->name();
+ name = name.lower();
+
+ if ( name == "cp1256" || name == "iso-8859-6" ) {
+ language = tdehtml::Decoder::Arabic;
+ }
+ else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) {
+ language = tdehtml::Decoder::Baltic;
+ }
+ else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) {
+ language = tdehtml::Decoder::CentralEuropean;
+ }
+ else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) {
+ language = tdehtml::Decoder::Russian;
+ }
+ else if ( name == "koi8-u" ) {
+ language = tdehtml::Decoder::Ukrainian;
+ }
+ else if ( name == "cp1253" || name == "iso-8859-7" ) {
+ language = tdehtml::Decoder::Greek;
+ }
+ else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) {
+ language = tdehtml::Decoder::Hebrew;
+ }
+ else if ( name == "jis7" || name == "eucjp" || name == "sjis" ) {
+ language = tdehtml::Decoder::Japanese;
+ }
+ else if ( name == "cp1254" || name == "iso-8859-9" ) {
+ language = tdehtml::Decoder::Turkish;
+ }
+ else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) {
+ language = tdehtml::Decoder::WesternEuropean;
+ }
+ else
+ language = tdehtml::Decoder::SemiautomaticDetection;
+
+ int _id = config->readNumEntry( "AutomaticDetectionLanguage", language );
+ d->m_automaticDetection->setItemChecked( _id, true );
+ d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
+
+ d->m_autoDetectLanguage = static_cast< tdehtml::Decoder::AutoDetectLanguage >( _id );
+ }
+
+
+ d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, TQT_SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
+
+ if ( prof == BrowserViewGUI ) {
+ d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
+ "Enlarge Font" ), "viewmag+", "CTRL++;CTRL+=", this,
+ TQT_SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" );
+ d->m_paIncZoomFactor->setWhatsThis( i18n( "Enlarge Font<p>"
+ "Make the font in this window bigger. "
+ "Click and hold down the mouse button for a menu with all available font sizes." ) );
+ d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n(
+ "Shrink Font" ), "viewmag-", CTRL + Key_Minus, this,
+ TQT_SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" );
+ d->m_paDecZoomFactor->setWhatsThis( i18n( "Shrink Font<p>"
+ "Make the font in this window smaller. "
+ "Click and hold down the mouse button for a menu with all available font sizes." ) );
+ }
+
+ d->m_paFind = KStdAction::find( this, TQT_SLOT( slotFind() ), actionCollection(), "find" );
+ d->m_paFind->setWhatsThis( i18n( "Find text<p>"
+ "Shows a dialog that allows you to find text on the displayed page." ) );
+
+ d->m_paFindNext = KStdAction::findNext( this, TQT_SLOT( slotFindNext() ), actionCollection(), "findNext" );
+ d->m_paFindNext->setWhatsThis( i18n( "Find next<p>"
+ "Find the next occurrence of the text that you "
+ "have found using the <b>Find Text</b> function" ) );
+
+ d->m_paFindPrev = KStdAction::findPrev( this, TQT_SLOT( slotFindPrev() ), actionCollection(), "findPrevious" );
+ d->m_paFindPrev->setWhatsThis( i18n( "Find previous<p>"
+ "Find the previous occurrence of the text that you "
+ "have found using the <b>Find Text</b> function" ) );
+
+ d->m_paFindAheadText = new KAction( i18n("Find Text as You Type"), KShortcut( '/' ), this, TQT_SLOT( slotFindAheadText()),
+ actionCollection(), "findAheadText");
+ d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), KShortcut( '\'' ), this, TQT_SLOT( slotFindAheadLink()),
+ actionCollection(), "findAheadLink");
+ d->m_paFindAheadText->setEnabled( false );
+ d->m_paFindAheadLinks->setEnabled( false );
+
+ if ( parentPart() )
+ {
+ d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
+ d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
+ d->m_paFindPrev->setShortcut( KShortcut() ); // avoid clashes
+ d->m_paFindAheadText->setShortcut( KShortcut());
+ d->m_paFindAheadLinks->setShortcut( KShortcut());
+ }
+
+ d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, TQT_SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
+ d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame<p>"
+ "Some pages have several frames. To print only a single frame, click "
+ "on it and then use this function." ) );
+
+ d->m_paSelectAll = KStdAction::selectAll( this, TQT_SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
+ if ( parentPart() )
+ d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
+
+ d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"),
+ Key_F7, this, TQT_SLOT(slotToggleCaretMode()),
+ actionCollection(), "caretMode");
+ d->m_paToggleCaretMode->setChecked(isCaretMode());
+ if (parentPart())
+ d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
+
+ // set the default java(script) flags according to the current host.
+ d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
+ d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
+ d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
+ setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
+ d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
+ d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
+
+ // Set the meta-refresh flag...
+ d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
+
+ connect( view, TQT_SIGNAL( zoomView( int ) ), TQT_SLOT( slotZoomView( int ) ) );
+
+ connect( this, TQT_SIGNAL( completed() ),
+ this, TQT_SLOT( updateActions() ) );
+ connect( this, TQT_SIGNAL( completed( bool ) ),
+ this, TQT_SLOT( updateActions() ) );
+ connect( this, TQT_SIGNAL( started( TDEIO::Job * ) ),
+ this, TQT_SLOT( updateActions() ) );
+
+ d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "tdehtml/tdehtml_popupmenu.rc", KHTMLFactory::instance() ) );
+
+ connect( tdehtml::Cache::loader(), TQT_SIGNAL( requestStarted( tdehtml::DocLoader*, tdehtml::CachedObject* ) ),
+ this, TQT_SLOT( slotLoaderRequestStarted( tdehtml::DocLoader*, tdehtml::CachedObject* ) ) );
+ connect( tdehtml::Cache::loader(), TQT_SIGNAL( requestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ),
+ this, TQT_SLOT( slotLoaderRequestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ) );
+ connect( tdehtml::Cache::loader(), TQT_SIGNAL( requestFailed( tdehtml::DocLoader*, tdehtml::CachedObject *) ),
+ this, TQT_SLOT( slotLoaderRequestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ) );
+
+ connect ( &d->m_progressUpdateTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressUpdate() ) );
+
+ findTextBegin(); //reset find variables
+
+ connect( &d->m_redirectionTimer, TQT_SIGNAL( timeout() ),
+ this, TQT_SLOT( slotRedirect() ) );
+
+ d->m_dcopobject = new KHTMLPartIface(this);
+
+ // TODO KDE4 - load plugins now (see also the constructors)
+ //if ( prof == BrowserViewGUI && !parentPart() )
+ // loadPlugins( partObject(), this, instance() );
+
+ // "tdehtml" catalog does not exist, our translations are in tdelibs.
+ // removing this catalog from TDEGlobal::locale() prevents problems
+ // with changing the language in applications at runtime -Thomas Reitelbach
+ TDEGlobal::locale()->removeCatalogue("tdehtml");
+}
+
+KHTMLPart::~KHTMLPart()
+{
+ //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
+
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup( "HTML Settings" );
+ config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage );
+
+ delete d->m_automaticDetection;
+ delete d->m_manualDetection;
+
+ slotWalletClosed();
+ if (!parentPart()) { // only delete it if the top tdehtml_part closes
+ removeJSErrorExtension();
+ delete d->m_statusBarPopupLabel;
+ }
+
+ d->m_find = 0; // deleted by its parent, the view.
+
+ if ( d->m_manager )
+ {
+ d->m_manager->setActivePart( 0 );
+ // We specify "this" as parent qobject for d->manager, so no need to delete it.
+ }
+
+ stopAutoScroll();
+ d->m_redirectionTimer.stop();
+
+ if (!d->m_bComplete)
+ closeURL();
+
+ disconnect( tdehtml::Cache::loader(), TQT_SIGNAL( requestStarted( tdehtml::DocLoader*, tdehtml::CachedObject* ) ),
+ this, TQT_SLOT( slotLoaderRequestStarted( tdehtml::DocLoader*, tdehtml::CachedObject* ) ) );
+ disconnect( tdehtml::Cache::loader(), TQT_SIGNAL( requestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ),
+ this, TQT_SLOT( slotLoaderRequestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ) );
+ disconnect( tdehtml::Cache::loader(), TQT_SIGNAL( requestFailed( tdehtml::DocLoader*, tdehtml::CachedObject *) ),
+ this, TQT_SLOT( slotLoaderRequestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ) );
+
+ clear();
+
+ if ( d->m_view )
+ {
+ d->m_view->hide();
+ d->m_view->viewport()->hide();
+ d->m_view->m_part = 0;
+ }
+
+ // Have to delete this here since we forward declare it in tdehtmlpart_p and
+ // at least some compilers won't call the destructor in this case.
+ delete d->m_jsedlg;
+ d->m_jsedlg = 0;
+
+ if (!parentPart()) // only delete d->m_frame if the top tdehtml_part closes
+ delete d->m_frame;
+ delete d; d = 0;
+ KHTMLFactory::deregisterPart( this );
+}
+
+bool KHTMLPart::restoreURL( const KURL &url )
+{
+ kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
+
+ d->m_redirectionTimer.stop();
+
+ /*
+ * That's not a good idea as it will call closeURL() on all
+ * child frames, preventing them from further loading. This
+ * method gets called from restoreState() in case of a full frameset
+ * restoral, and restoreState() calls closeURL() before restoring
+ * anyway.
+ kdDebug( 6050 ) << "closing old URL" << endl;
+ closeURL();
+ */
+
+ d->m_bComplete = false;
+ d->m_bLoadEventEmitted = false;
+ d->m_workingURL = url;
+
+ // set the java(script) flags according to the current host.
+ d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
+ setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
+ d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
+ d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
+
+ m_url = url;
+
+ d->m_restoreScrollPosition = true;
+ disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+ connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+
+ KHTMLPageCache::self()->fetchData( d->m_cacheId, this, TQT_SLOT(slotRestoreData(const TQByteArray &)));
+
+ emit started( 0L );
+
+ return true;
+}
+
+
+bool KHTMLPart::openURL( const KURL &url )
+{
+ kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
+
+ d->m_redirectionTimer.stop();
+
+ // check to see if this is an "error://" URL. This is caused when an error
+ // occurs before this part was loaded (e.g. KonqRun), and is passed to
+ // tdehtmlpart so that it can display the error.
+ if ( url.protocol() == "error" && url.hasSubURL() ) {
+ closeURL();
+
+ if( d->m_bJScriptEnabled )
+ d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = TQString();
+
+ /**
+ * The format of the error url is that two variables are passed in the query:
+ * error = int kio error code, errText = TQString error text from kio
+ * and the URL where the error happened is passed as a sub URL.
+ */
+ KURL::List urls = KURL::split( url );
+ //kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
+
+ if ( urls.count() > 1 ) {
+ KURL mainURL = urls.first();
+ int error = mainURL.queryItem( "error" ).toInt();
+ // error=0 isn't a valid error code, so 0 means it's missing from the URL
+ if ( error == 0 ) error = TDEIO::ERR_UNKNOWN;
+ TQString errorText = mainURL.queryItem( "errText", HINT_UTF8 );
+ urls.pop_front();
+ d->m_workingURL = KURL::join( urls );
+ //kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
+ emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
+ htmlError( error, errorText, d->m_workingURL );
+ return true;
+ }
+ }
+
+ if (!parentPart()) { // only do it for toplevel part
+ TQString host = url.isLocalFile() ? "localhost" : url.host();
+ TQString userAgent = KProtocolManager::userAgentForHost(host);
+ if (userAgent != KProtocolManager::userAgentForHost(TQString())) {
+ if (!d->m_statusBarUALabel) {
+ d->m_statusBarUALabel = new KURLLabel(d->m_statusBarExtension->statusBar());
+ d->m_statusBarUALabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
+ d->m_statusBarUALabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ d->m_statusBarUALabel->setUseCursor(false);
+ d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
+ d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance()));
+ } else {
+ TQToolTip::remove(d->m_statusBarUALabel);
+ }
+ TQToolTip::add(d->m_statusBarUALabel, i18n("The fake user-agent '%1' is in use.").arg(userAgent));
+ } else if (d->m_statusBarUALabel) {
+ d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel);
+ delete d->m_statusBarUALabel;
+ d->m_statusBarUALabel = 0L;
+ }
+ }
+
+ KParts::URLArgs args( d->m_extension->urlArgs() );
+
+ // in case
+ // a) we have no frameset (don't test m_frames.count(), iframes get in there)
+ // b) the url is identical with the currently displayed one (except for the htmlref!)
+ // c) the url request is not a POST operation and
+ // d) the caller did not request to reload the page
+ // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
+ // => we don't reload the whole document and
+ // we just jump to the requested html anchor
+ bool isFrameSet = false;
+ if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
+ HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
+ isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
+ }
+
+ if ( url.hasRef() && !isFrameSet )
+ {
+ bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost();
+ if (noReloadForced && urlcmp( url.url(), m_url.url(), true, true ))
+ {
+ kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
+ m_url = url;
+ emit started( 0L );
+
+ if ( !gotoAnchor( url.encodedHtmlRef()) )
+ gotoAnchor( url.htmlRef() );
+
+ d->m_bComplete = true;
+ if (d->m_doc)
+ d->m_doc->setParsing(false);
+
+ kdDebug( 6050 ) << "completed..." << endl;
+ emit completed();
+ return true;
+ }
+ }
+
+ // Save offset of viewport when page is reloaded to be compliant
+ // to every other capable browser out there.
+ if (args.reload) {
+ args.xOffset = d->m_view->contentsX();
+ args.yOffset = d->m_view->contentsY();
+ d->m_extension->setURLArgs(args);
+ }
+
+ if (!d->m_restored)
+ closeURL();
+
+ d->m_restoreScrollPosition = d->m_restored;
+ disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+ connect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+
+ // initializing m_url to the new url breaks relative links when opening such a link after this call and _before_ begin() is called (when the first
+ // data arrives) (Simon)
+ m_url = url;
+ if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
+ m_url.path().isEmpty()) {
+ m_url.setPath("/");
+ emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
+ }
+ // copy to m_workingURL after fixing m_url above
+ d->m_workingURL = m_url;
+
+ args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
+ args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
+ args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
+ args.metaData().insert("PropagateHttpHeader", "true");
+ args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
+ args.metaData().insert("ssl_activate_warnings", "TRUE" );
+ args.metaData().insert("cross-domain", toplevelURL().url());
+
+ if (d->m_restored)
+ {
+ args.metaData().insert("referrer", d->m_pageReferrer);
+ d->m_cachePolicy = TDEIO::CC_Cache;
+ }
+ else if (args.reload)
+ d->m_cachePolicy = TDEIO::CC_Reload;
+ else
+ d->m_cachePolicy = KProtocolManager::cacheControl();
+
+ if ( args.doPost() && (m_url.protocol().startsWith("http")) )
+ {
+ d->m_job = TDEIO::http_post( m_url, args.postData, false );
+ d->m_job->addMetaData("content-type", args.contentType() );
+ }
+ else
+ {
+ d->m_job = TDEIO::get( m_url, false, false );
+ d->m_job->addMetaData("cache", TDEIO::getCacheControlString(d->m_cachePolicy));
+ }
+
+ if (widget())
+ d->m_job->setWindow(widget()->topLevelWidget());
+ d->m_job->addMetaData(args.metaData());
+
+ connect( d->m_job, TQT_SIGNAL( result( TDEIO::Job* ) ),
+ TQT_SLOT( slotFinished( TDEIO::Job* ) ) );
+ connect( d->m_job, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
+ TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray& ) ) );
+ connect ( d->m_job, TQT_SIGNAL( infoMessage( TDEIO::Job*, const TQString& ) ),
+ TQT_SLOT( slotInfoMessage(TDEIO::Job*, const TQString& ) ) );
+ connect( d->m_job, TQT_SIGNAL(redirection(TDEIO::Job*, const KURL& ) ),
+ TQT_SLOT( slotRedirection(TDEIO::Job*, const KURL&) ) );
+
+ d->m_bComplete = false;
+ d->m_bLoadEventEmitted = false;
+
+ // delete old status bar msg's from kjs (if it _was_ activated on last URL)
+ if( d->m_bJScriptEnabled )
+ d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = TQString();
+
+ // set the javascript flags according to the current url
+ d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
+ setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
+ d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
+ d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
+
+
+ connect( d->m_job, TQT_SIGNAL( speed( TDEIO::Job*, unsigned long ) ),
+ this, TQT_SLOT( slotJobSpeed( TDEIO::Job*, unsigned long ) ) );
+
+ connect( d->m_job, TQT_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
+ this, TQT_SLOT( slotJobPercent( TDEIO::Job*, unsigned long ) ) );
+
+ connect( d->m_job, TQT_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQT_SLOT( slotJobDone( TDEIO::Job* ) ) );
+
+ d->m_jobspeed = 0;
+
+ // If this was an explicit reload and the user style sheet should be used,
+ // do a stat to see whether the stylesheet was changed in the meanwhile.
+ if ( args.reload && !settings()->userStyleSheet().isEmpty() ) {
+ KURL url( settings()->userStyleSheet() );
+ TDEIO::StatJob *job = TDEIO::stat( url, false /* don't show progress */ );
+ connect( job, TQT_SIGNAL( result( TDEIO::Job * ) ),
+ this, TQT_SLOT( slotUserSheetStatDone( TDEIO::Job * ) ) );
+ }
+ emit started( 0L );
+
+ return true;
+}
+
+bool KHTMLPart::closeURL()
+{
+ if ( d->m_job )
+ {
+ KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
+ d->m_job->kill();
+ d->m_job = 0;
+ }
+
+ if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
+ HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
+
+ if ( hdoc->body() && d->m_bLoadEventEmitted ) {
+ hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
+ if ( d->m_doc )
+ d->m_doc->updateRendering();
+ d->m_bLoadEventEmitted = false;
+ }
+ }
+
+ d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
+ d->m_bLoadEventEmitted = true; // don't want that one either
+ d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
+
+ disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+
+ KHTMLPageCache::self()->cancelFetch(this);
+ if ( d->m_doc && d->m_doc->parsing() )
+ {
+ kdDebug( 6050 ) << " was still parsing... calling end " << endl;
+ slotFinishedParsing();
+ d->m_doc->setParsing(false);
+ }
+
+ if ( !d->m_workingURL.isEmpty() )
+ {
+ // Aborted before starting to render
+ kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
+ emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
+ }
+
+ d->m_workingURL = KURL();
+
+ if ( d->m_doc && d->m_doc->docLoader() )
+ tdehtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
+
+ // tell all subframes to stop as well
+ {
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ {
+ if ( (*it)->m_run )
+ (*it)->m_run->abort();
+ if ( !( *it )->m_part.isNull() )
+ ( *it )->m_part->closeURL();
+ }
+ }
+ // tell all objects to stop as well
+ {
+ ConstFrameIt it = d->m_objects.begin();
+ const ConstFrameIt end = d->m_objects.end();
+ for (; it != end; ++it)
+ {
+ if ( !( *it )->m_part.isNull() )
+ ( *it )->m_part->closeURL();
+ }
+ }
+ // Stop any started redirections as well!! (DA)
+ if ( d && d->m_redirectionTimer.isActive() )
+ d->m_redirectionTimer.stop();
+
+ // null node activated.
+ emit nodeActivated(Node());
+
+ // make sure before clear() runs, we pop out of a dialog's message loop
+ if ( d->m_view )
+ d->m_view->closeChildDialogs();
+
+ return true;
+}
+
+DOM::HTMLDocument KHTMLPart::htmlDocument() const
+{
+ if (d->m_doc && d->m_doc->isHTMLDocument())
+ return static_cast<HTMLDocumentImpl*>(d->m_doc);
+ else
+ return static_cast<HTMLDocumentImpl*>(0);
+}
+
+DOM::Document KHTMLPart::document() const
+{
+ return d->m_doc;
+}
+
+TQString KHTMLPart::documentSource() const
+{
+ TQString sourceStr;
+ if ( !( m_url.isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) )
+ {
+ TQByteArray sourceArray;
+ TQDataStream dataStream( sourceArray, IO_WriteOnly );
+ KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream );
+ TQTextStream stream( sourceArray, IO_ReadOnly );
+ stream.setCodec( TQTextCodec::codecForName( encoding().latin1() ) );
+ sourceStr = stream.read();
+ } else
+ {
+ TQString tmpFile;
+ if( TDEIO::NetAccess::download( m_url, tmpFile, NULL ) )
+ {
+ TQFile f( tmpFile );
+ if ( f.open( IO_ReadOnly ) )
+ {
+ TQTextStream stream( &f );
+ stream.setCodec( TQTextCodec::codecForName( encoding().latin1() ) );
+ sourceStr = stream.read();
+ f.close();
+ }
+ TDEIO::NetAccess::removeTempFile( tmpFile );
+ }
+ }
+
+ return sourceStr;
+}
+
+
+KParts::BrowserExtension *KHTMLPart::browserExtension() const
+{
+ return d->m_extension;
+}
+
+KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
+{
+ return d->m_hostExtension;
+}
+
+KHTMLView *KHTMLPart::view() const
+{
+ return d->m_view;
+}
+
+void KHTMLPart::setStatusMessagesEnabled( bool enable )
+{
+ d->m_statusMessagesEnabled = enable;
+}
+
+KJS::Interpreter *KHTMLPart::jScriptInterpreter()
+{
+ KJSProxy *proxy = jScript();
+ if (!proxy || proxy->paused())
+ return 0;
+
+ return proxy->interpreter();
+}
+
+bool KHTMLPart::statusMessagesEnabled() const
+{
+ return d->m_statusMessagesEnabled;
+}
+
+void KHTMLPart::setJScriptEnabled( bool enable )
+{
+ if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) {
+ d->m_frame->m_jscript->clear();
+ }
+ d->m_bJScriptForce = enable;
+ d->m_bJScriptOverride = true;
+}
+
+bool KHTMLPart::jScriptEnabled() const
+{
+ if(onlyLocalReferences()) return false;
+
+ if ( d->m_bJScriptOverride )
+ return d->m_bJScriptForce;
+ return d->m_bJScriptEnabled;
+}
+
+void KHTMLPart::setMetaRefreshEnabled( bool enable )
+{
+ d->m_metaRefreshEnabled = enable;
+}
+
+bool KHTMLPart::metaRefreshEnabled() const
+{
+ return d->m_metaRefreshEnabled;
+}
+
+// Define this to disable dlopening kjs_html, when directly linking to it.
+// You need to edit tdehtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
+// and to edit tdehtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libtdehtml from LIBADD,
+// remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
+// Also, change the order of "ecma" and "." in tdehtml's SUBDIRS line.
+// OK - that's the default now, use the opposite of the above instructions to go back
+// to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
+#define DIRECT_LINKAGE_TO_ECMA
+
+#ifdef DIRECT_LINKAGE_TO_ECMA
+extern "C" { KJSProxy *kjs_html_init(tdehtml::ChildFrame * childframe); }
+#endif
+
+static bool createJScript(tdehtml::ChildFrame *frame)
+{
+#ifndef DIRECT_LINKAGE_TO_ECMA
+ KLibrary *lib = KLibLoader::self()->library("kjs_html");
+ if ( !lib ) {
+ setJScriptEnabled( false );
+ return false;
+ }
+ // look for plain C init function
+ void *sym = lib->symbol("kjs_html_init");
+ if ( !sym ) {
+ lib->unload();
+ setJScriptEnabled( false );
+ return false;
+ }
+ typedef KJSProxy* (*initFunction)(tdehtml::ChildFrame *);
+ initFunction initSym = (initFunction) sym;
+ frame->m_jscript = (*initSym)(d->m_frame);
+ frame->m_kjs_lib = lib;
+#else
+ frame->m_jscript = kjs_html_init(frame);
+ // frame->m_kjs_lib remains 0L.
+#endif
+ return true;
+}
+
+KJSProxy *KHTMLPart::jScript()
+{
+ if (!jScriptEnabled()) return 0;
+
+ if ( !d->m_frame ) {
+ KHTMLPart * p = parentPart();
+ if (!p) {
+ d->m_frame = new tdehtml::ChildFrame;
+ d->m_frame->m_part = this;
+ } else {
+ ConstFrameIt it = p->d->m_frames.begin();
+ const ConstFrameIt end = p->d->m_frames.end();
+ for (; it != end; ++it)
+ if ((*it)->m_part.operator->() == this) {
+ d->m_frame = *it;
+ break;
+ }
+ }
+ if ( !d->m_frame )
+ return 0;
+ }
+ if ( !d->m_frame->m_jscript )
+ if (!createJScript(d->m_frame))
+ return 0;
+ if (d->m_bJScriptDebugEnabled)
+ d->m_frame->m_jscript->setDebugEnabled(true);
+
+ return d->m_frame->m_jscript;
+}
+
+TQVariant KHTMLPart::crossFrameExecuteScript(const TQString& target, const TQString& script)
+{
+ KHTMLPart* destpart = this;
+
+ TQString trg = target.lower();
+
+ if (target == "_top") {
+ while (destpart->parentPart())
+ destpart = destpart->parentPart();
+ }
+ else if (target == "_parent") {
+ if (parentPart())
+ destpart = parentPart();
+ }
+ else if (target == "_self" || target == "_blank") {
+ // we always allow these
+ }
+ else {
+ destpart = findFrame(target);
+ if (!destpart)
+ destpart = this;
+ }
+
+ // easy way out?
+ if (destpart == this)
+ return executeScript(DOM::Node(), script);
+
+ // now compare the domains
+ if (destpart->checkFrameAccess(this))
+ return destpart->executeScript(DOM::Node(), script);
+
+ // eww, something went wrong. better execute it in our frame
+ return executeScript(DOM::Node(), script);
+}
+
+//Enable this to see all JS scripts being executed
+//#define KJS_VERBOSE
+
+KJSErrorDlg *KHTMLPart::jsErrorExtension() {
+ if (!d->m_settings->jsErrorsEnabled()) {
+ return 0L;
+ }
+
+ if (parentPart()) {
+ return parentPart()->jsErrorExtension();
+ }
+
+ if (!d->m_statusBarJSErrorLabel) {
+ d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
+ d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
+ d->m_statusBarJSErrorLabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ d->m_statusBarJSErrorLabel->setUseCursor(false);
+ d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
+ TQToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
+ d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
+ connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchJSErrorDialog()));
+ connect(d->m_statusBarJSErrorLabel, TQT_SIGNAL(rightClickedURL()), TQT_SLOT(jsErrorDialogContextMenu()));
+ }
+ if (!d->m_jsedlg) {
+ d->m_jsedlg = new KJSErrorDlg;
+ d->m_jsedlg->setURL(m_url.prettyURL());
+ if (TDEGlobalSettings::showIconsOnPushButtons()) {
+ d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase"));
+ d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose"));
+ }
+ }
+ return d->m_jsedlg;
+}
+
+void KHTMLPart::removeJSErrorExtension() {
+ if (parentPart()) {
+ parentPart()->removeJSErrorExtension();
+ return;
+ }
+ if (d->m_statusBarJSErrorLabel != 0) {
+ d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
+ delete d->m_statusBarJSErrorLabel;
+ d->m_statusBarJSErrorLabel = 0;
+ }
+ delete d->m_jsedlg;
+ d->m_jsedlg = 0;
+}
+
+void KHTMLPart::disableJSErrorExtension() {
+ removeJSErrorExtension();
+ // These two lines are really kind of hacky, and it sucks to do this inside
+ // KHTML but I don't know of anything that's reasonably easy as an alternative
+ // right now. It makes me wonder if there should be a more clean way to
+ // contact all running "KHTML" instance as opposed to Konqueror instances too.
+ d->m_settings->setJSErrorsEnabled(false);
+ DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQByteArray());
+}
+
+void KHTMLPart::jsErrorDialogContextMenu() {
+ KPopupMenu *m = new KPopupMenu(0L);
+ m->insertItem(i18n("&Hide Errors"), this, TQT_SLOT(removeJSErrorExtension()));
+ m->insertItem(i18n("&Disable Error Reporting"), this, TQT_SLOT(disableJSErrorExtension()));
+ m->popup(TQCursor::pos());
+}
+
+void KHTMLPart::launchJSErrorDialog() {
+ KJSErrorDlg *dlg = jsErrorExtension();
+ if (dlg) {
+ dlg->show();
+ dlg->raise();
+ }
+}
+
+void KHTMLPart::launchJSConfigDialog() {
+ TQStringList args;
+ args << "tdehtml_java_js";
+ TDEApplication::tdeinitExec( "kcmshell", args );
+}
+
+TQVariant KHTMLPart::executeScript(const TQString& filename, int baseLine, const DOM::Node& n, const TQString& script)
+{
+#ifdef KJS_VERBOSE
+ // The script is now printed by KJS's Parser::parse
+ kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl;
+#endif
+ KJSProxy *proxy = jScript();
+
+ if (!proxy || proxy->paused())
+ return TQVariant();
+
+ KJS::Completion comp;
+
+ TQVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
+
+ /*
+ * Error handling
+ */
+ if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
+ KJSErrorDlg *dlg = jsErrorExtension();
+ if (dlg) {
+ KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
+ dlg->addError(i18n("<b>Error</b>: %1: %2").arg(filename, msg.qstring()));
+ }
+ }
+
+ // Handle immediate redirects now (e.g. location='foo')
+ if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 )
+ {
+ kdDebug(6070) << "executeScript done, handling immediate redirection NOW" << endl;
+ // Must abort tokenizer, no further script must execute.
+ tdehtml::Tokenizer* t = d->m_doc->tokenizer();
+ if(t)
+ t->abort();
+ d->m_redirectionTimer.start( 0, true );
+ }
+
+ return ret;
+}
+
+TQVariant KHTMLPart::executeScript( const TQString &script )
+{
+ return executeScript( DOM::Node(), script );
+}
+
+TQVariant KHTMLPart::executeScript( const DOM::Node &n, const TQString &script )
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl;
+#endif
+ KJSProxy *proxy = jScript();
+
+ if (!proxy || proxy->paused())
+ return TQVariant();
+ ++(d->m_runningScripts);
+ KJS::Completion comp;
+ const TQVariant ret = proxy->evaluate( TQString(), 1, script, n, &comp );
+ --(d->m_runningScripts);
+
+ /*
+ * Error handling
+ */
+ if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
+ KJSErrorDlg *dlg = jsErrorExtension();
+ if (dlg) {
+ KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
+ dlg->addError(i18n("<b>Error</b>: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
+ }
+ }
+
+ if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
+ submitFormAgain();
+
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
+#endif
+ return ret;
+}
+
+bool KHTMLPart::scheduleScript(const DOM::Node &n, const TQString& script)
+{
+ //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
+
+ d->scheduledScript = script;
+ d->scheduledScriptNode = n;
+
+ return true;
+}
+
+TQVariant KHTMLPart::executeScheduledScript()
+{
+ if( d->scheduledScript.isEmpty() )
+ return TQVariant();
+
+ //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
+
+ TQVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
+ d->scheduledScript = TQString();
+ d->scheduledScriptNode = DOM::Node();
+
+ return ret;
+}
+
+void KHTMLPart::setJavaEnabled( bool enable )
+{
+ d->m_bJavaForce = enable;
+ d->m_bJavaOverride = true;
+}
+
+bool KHTMLPart::javaEnabled() const
+{
+ if (onlyLocalReferences()) return false;
+
+#ifndef Q_WS_QWS
+ if( d->m_bJavaOverride )
+ return d->m_bJavaForce;
+ return d->m_bJavaEnabled;
+#else
+ return false;
+#endif
+}
+
+KJavaAppletContext *KHTMLPart::javaContext()
+{
+ return 0;
+}
+
+KJavaAppletContext *KHTMLPart::createJavaContext()
+{
+ return 0;
+}
+
+void KHTMLPart::setPluginsEnabled( bool enable )
+{
+ d->m_bPluginsForce = enable;
+ d->m_bPluginsOverride = true;
+}
+
+bool KHTMLPart::pluginsEnabled() const
+{
+ if (onlyLocalReferences()) return false;
+
+ if ( d->m_bPluginsOverride )
+ return d->m_bPluginsForce;
+ return d->m_bPluginsEnabled;
+}
+
+static int s_DOMTreeIndentLevel = 0;
+
+void KHTMLPart::slotDebugDOMTree()
+{
+ if ( d->m_doc && d->m_doc->firstChild() )
+ tqDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
+
+ // Now print the contents of the frames that contain HTML
+
+ const int indentLevel = s_DOMTreeIndentLevel++;
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
+ KParts::ReadOnlyPart* const p = ( *it )->m_part;
+ kdDebug(6050) << TQString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl;
+ static_cast<KHTMLPart*>( p )->slotDebugDOMTree();
+ }
+ s_DOMTreeIndentLevel = indentLevel;
+}
+
+void KHTMLPart::slotDebugScript()
+{
+ if (jScript())
+ jScript()->showDebugWindow();
+}
+
+void KHTMLPart::slotDebugRenderTree()
+{
+#ifndef NDEBUG
+ if ( d->m_doc ) {
+ d->m_doc->renderer()->printTree();
+ // dump out the contents of the rendering & DOM trees
+// TQString dumps;
+// TQTextStream outputStream(dumps,IO_WriteOnly);
+// d->m_doc->renderer()->layer()->dump( outputStream );
+// kdDebug() << "dump output:" << "\n" + dumps;
+ }
+#endif
+}
+
+void KHTMLPart::slotStopAnimations()
+{
+ stopAnimations();
+}
+
+void KHTMLPart::setAutoloadImages( bool enable )
+{
+ if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
+ return;
+
+ if ( d->m_doc )
+ d->m_doc->docLoader()->setAutoloadImages( enable );
+
+ unplugActionList( "loadImages" );
+
+ if ( enable ) {
+ delete d->m_paLoadImages;
+ d->m_paLoadImages = 0;
+ }
+ else if ( !d->m_paLoadImages )
+ d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, TQT_SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
+
+ if ( d->m_paLoadImages ) {
+ TQPtrList<KAction> lst;
+ lst.append( d->m_paLoadImages );
+ plugActionList( "loadImages", lst );
+ }
+}
+
+bool KHTMLPart::autoloadImages() const
+{
+ if ( d->m_doc )
+ return d->m_doc->docLoader()->autoloadImages();
+
+ return true;
+}
+
+void KHTMLPart::clear()
+{
+ if ( d->m_bCleared )
+ return;
+
+ d->m_bCleared = true;
+
+ d->m_bClearing = true;
+
+ {
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for(; it != end; ++it )
+ {
+ // Stop HTMLRun jobs for frames
+ if ( (*it)->m_run )
+ (*it)->m_run->abort();
+ }
+ }
+
+ {
+ ConstFrameIt it = d->m_objects.begin();
+ const ConstFrameIt end = d->m_objects.end();
+ for(; it != end; ++it )
+ {
+ // Stop HTMLRun jobs for objects
+ if ( (*it)->m_run )
+ (*it)->m_run->abort();
+ }
+ }
+
+
+ findTextBegin(); // resets d->m_findNode and d->m_findPos
+ d->m_mousePressNode = DOM::Node();
+
+
+ if ( d->m_doc )
+ {
+ if (d->m_doc->attached()) //the view may have detached it already
+ d->m_doc->detach();
+ }
+
+ // Moving past doc so that onUnload works.
+ if ( d->m_frame && d->m_frame->m_jscript )
+ d->m_frame->m_jscript->clear();
+
+ // stopping marquees
+ if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
+ d->m_doc->renderer()->layer()->suspendMarquees();
+
+ if ( d->m_view )
+ d->m_view->clear();
+
+ // do not dereference the document before the jscript and view are cleared, as some destructors
+ // might still try to access the document.
+ if ( d->m_doc ) {
+ d->m_doc->deref();
+ }
+ d->m_doc = 0;
+
+ delete d->m_decoder;
+ d->m_decoder = 0;
+
+ // We don't want to change between parts if we are going to delete all of them anyway
+ disconnect( partManager(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
+ this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
+
+ if (d->m_frames.count())
+ {
+ KHTMLFrameList frames = d->m_frames;
+ d->m_frames.clear();
+ ConstFrameIt it = frames.begin();
+ const ConstFrameIt end = frames.end();
+ for(; it != end; ++it )
+ {
+ if ( (*it)->m_part )
+ {
+ partManager()->removePart( (*it)->m_part );
+ delete (KParts::ReadOnlyPart *)(*it)->m_part;
+ }
+ delete *it;
+ }
+ }
+ d->m_suppressedPopupOriginParts.clear();
+
+ if (d->m_objects.count())
+ {
+ KHTMLFrameList objects = d->m_objects;
+ d->m_objects.clear();
+ ConstFrameIt oi = objects.begin();
+ const ConstFrameIt oiEnd = objects.end();
+
+ for (; oi != oiEnd; ++oi )
+ delete *oi;
+ }
+
+ // Listen to part changes again
+ connect( partManager(), TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
+ this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
+
+ d->m_delayRedirect = 0;
+ d->m_redirectURL = TQString();
+ d->m_redirectionTimer.stop();
+ d->m_redirectLockHistory = true;
+ d->m_bClearing = false;
+ d->m_frameNameId = 1;
+ d->m_bFirstData = true;
+
+ d->m_bMousePressed = false;
+
+ d->m_selectionStart = DOM::Node();
+ d->m_selectionEnd = DOM::Node();
+ d->m_startOffset = 0;
+ d->m_endOffset = 0;
+#ifndef QT_NO_CLIPBOARD
+ connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), TQT_SLOT( slotClearSelection()));
+#endif
+
+ d->m_jobPercent = 0;
+
+ if ( !d->m_haveEncoding )
+ d->m_encoding = TQString();
+#ifdef SPEED_DEBUG
+ d->m_parsetime.restart();
+#endif
+}
+
+bool KHTMLPart::openFile()
+{
+ return true;
+}
+
+DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
+{
+ if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
+ return static_cast<HTMLDocumentImpl*>(d->m_doc);
+ return 0;
+}
+
+DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
+{
+ if ( d )
+ return d->m_doc;
+ return 0;
+}
+
+void KHTMLPart::slotInfoMessage(TDEIO::Job* kio_job, const TQString& msg)
+{
+ assert(d->m_job == kio_job);
+
+ if (!parentPart())
+ setStatusBarText(msg, BarDefaultText);
+}
+
+void KHTMLPart::setPageSecurity( PageSecurity sec )
+{
+ emit d->m_extension->setPageSecurity( sec );
+ if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
+ d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
+ d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
+ d->m_statusBarIconLabel->setSizePolicy(TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
+ d->m_statusBarIconLabel->setUseCursor( false );
+ d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
+ connect( d->m_statusBarIconLabel, TQT_SIGNAL( leftClickedURL() ), TQT_SLOT( slotSecurity() ) );
+ } else if (d->m_statusBarIconLabel) {
+ TQToolTip::remove(d->m_statusBarIconLabel);
+ }
+
+ if (d->m_statusBarIconLabel) {
+ if (d->m_ssl_in_use)
+ TQToolTip::add(d->m_statusBarIconLabel,
+ i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
+ else TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
+ }
+
+ TQString iconName;
+ switch (sec) {
+ case NotCrypted:
+ iconName = "decrypted";
+ if ( d->m_statusBarIconLabel ) {
+ d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
+ delete d->m_statusBarIconLabel;
+ d->m_statusBarIconLabel = 0L;
+ }
+ break;
+ case Encrypted:
+ iconName = "encrypted";
+ break;
+ case Mixed:
+ iconName = "halfencrypted";
+ break;
+ }
+ d->m_paSecurity->setIcon( iconName );
+ if ( d->m_statusBarIconLabel )
+ d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
+}
+
+void KHTMLPart::slotData( TDEIO::Job* kio_job, const TQByteArray &data )
+{
+ assert ( d->m_job == kio_job );
+
+ //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
+ // The first data ?
+ if ( !d->m_workingURL.isEmpty() )
+ {
+ //kdDebug( 6050 ) << "begin!" << endl;
+
+ // We must suspend KIO while we're inside begin() because it can cause
+ // crashes if a window (such as kjsdebugger) goes back into the event loop,
+ // more data arrives, and begin() gets called again (re-entered).
+ d->m_job->suspend();
+ begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
+ d->m_job->resume();
+
+ if (d->m_cachePolicy == TDEIO::CC_Refresh)
+ d->m_doc->docLoader()->setCachePolicy(TDEIO::CC_Verify);
+ else
+ d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
+
+ d->m_workingURL = KURL();
+
+ d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
+
+ // When the first data arrives, the metadata has just been made available
+ d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
+ time_t cacheCreationDate = d->m_job->queryMetaData("cache-creation-date").toLong();
+ d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
+
+ d->m_pageServices = d->m_job->queryMetaData("PageServices");
+ d->m_pageReferrer = d->m_job->queryMetaData("referrer");
+ d->m_bSecurityInQuestion = false;
+ d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
+
+ {
+ KHTMLPart *p = parentPart();
+ if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
+ while (p->parentPart()) p = p->parentPart();
+
+ p->setPageSecurity( Mixed );
+ p->d->m_bSecurityInQuestion = true;
+ }
+ }
+
+ setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
+
+ // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
+ d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
+ d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
+ d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
+ d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
+ d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
+ d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
+ d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
+ d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
+ d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
+ d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
+ d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
+
+ if (d->m_statusBarIconLabel) {
+ TQToolTip::remove(d->m_statusBarIconLabel);
+ if (d->m_ssl_in_use) {
+ TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
+ } else {
+ TQToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
+ }
+ }
+
+ // Check for charset meta-data
+ TQString qData = d->m_job->queryMetaData("charset");
+ if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
+ d->m_encoding = qData;
+
+
+ // Support for http-refresh
+ qData = d->m_job->queryMetaData("http-refresh");
+ if( !qData.isEmpty())
+ d->m_doc->processHttpEquiv("refresh", qData);
+
+ // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
+ // See BR# 51185,BR# 82747
+ /*
+ TQString baseURL = d->m_job->queryMetaData ("content-location");
+ if (!baseURL.isEmpty())
+ d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
+ */
+
+ // Support for Content-Language
+ TQString language = d->m_job->queryMetaData("content-language");
+ if (!language.isEmpty())
+ d->m_doc->setContentLanguage(language);
+
+ if ( !m_url.isLocalFile() ) {
+ // Support for http last-modified
+ d->m_lastModified = d->m_job->queryMetaData("modified");
+ } else
+ d->m_lastModified = TQString(); // done on-demand by lastModified()
+ }
+
+ KHTMLPageCache::self()->addData(d->m_cacheId, data);
+ write( data.data(), data.size() );
+ if (d->m_frame && d->m_frame->m_jscript)
+ d->m_frame->m_jscript->dataReceived();
+}
+
+void KHTMLPart::slotRestoreData(const TQByteArray &data )
+{
+ // The first data ?
+ if ( !d->m_workingURL.isEmpty() )
+ {
+ long saveCacheId = d->m_cacheId;
+ TQString savePageReferrer = d->m_pageReferrer;
+ TQString saveEncoding = d->m_encoding;
+ begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
+ d->m_encoding = saveEncoding;
+ d->m_pageReferrer = savePageReferrer;
+ d->m_cacheId = saveCacheId;
+ d->m_workingURL = KURL();
+ }
+
+ //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
+ write( data.data(), data.size() );
+
+ if (data.size() == 0)
+ {
+ //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
+ // End of data.
+ if (d->m_doc && d->m_doc->parsing())
+ end(); //will emit completed()
+ }
+}
+
+void KHTMLPart::showError( TDEIO::Job* job )
+{
+ kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
+ << " d->m_bCleared=" << d->m_bCleared << endl;
+
+ if (job->error() == TDEIO::ERR_NO_CONTENT)
+ return;
+
+ if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
+ job->showErrorDialog( /*d->m_view*/ );
+ else
+ {
+ htmlError( job->error(), job->errorText(), d->m_workingURL );
+ }
+}
+
+// This is a protected method, placed here because of it's relevance to showError
+void KHTMLPart::htmlError( int errorCode, const TQString& text, const KURL& reqUrl )
+{
+ kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
+ // make sure we're not executing any embedded JS
+ bool bJSFO = d->m_bJScriptForce;
+ bool bJSOO = d->m_bJScriptOverride;
+ d->m_bJScriptForce = false;
+ d->m_bJScriptOverride = true;
+ begin();
+ TQString errText = TQString::fromLatin1( "<HTML dir=%1><HEAD><TITLE>" )
+ .arg(TQApplication::reverseLayout() ? "rtl" : "ltr");
+ errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
+ errText += TQString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
+ errText += i18n( "An error occurred while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
+ errText += TQString::fromLatin1( "</P>" );
+ errText += TQStyleSheet::convertFromPlainText( TDEIO::buildErrorString( errorCode, text ) );
+ errText += TQString::fromLatin1( "</BODY></HTML>" );
+ write(errText);
+ end();
+
+ d->m_bJScriptForce = bJSFO;
+ d->m_bJScriptOverride = bJSOO;
+
+ // make the working url the current url, so that reload works and
+ // emit the progress signals to advance one step in the history
+ // (so that 'back' works)
+ m_url = reqUrl; // same as d->m_workingURL
+ d->m_workingURL = KURL();
+ emit started( 0 );
+ emit completed();
+ return;
+ // following disabled until 3.1
+
+ TQString errorName, techName, description;
+ TQStringList causes, solutions;
+
+ TQByteArray raw = TDEIO::rawErrorDetail( errorCode, text, &reqUrl );
+ TQDataStream stream(raw, IO_ReadOnly);
+
+ stream >> errorName >> techName >> description >> causes >> solutions;
+
+ TQString url, protocol, datetime;
+ url = reqUrl.prettyURL();
+ protocol = reqUrl.protocol();
+ datetime = TDEGlobal::locale()->formatDateTime( TQDateTime::currentDateTime(),
+ false );
+
+ TQString doc = TQString::fromLatin1( "<html><head><title>" );
+ doc += i18n( "Error: " );
+ doc += errorName;
+ doc += TQString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
+ doc += i18n( "The requested operation could not be completed" );
+ doc += TQString::fromLatin1( "</h1><h2>" );
+ doc += errorName;
+ doc += TQString::fromLatin1( "</h2>" );
+ if ( !techName.isNull() ) {
+ doc += TQString::fromLatin1( "<h2>" );
+ doc += i18n( "Technical Reason: " );
+ doc += techName;
+ doc += TQString::fromLatin1( "</h2>" );
+ }
+ doc += TQString::fromLatin1( "<h3>" );
+ doc += i18n( "Details of the Request:" );
+ doc += TQString::fromLatin1( "</h3><ul><li>" );
+ doc += i18n( "URL: %1" ).arg( url );
+ doc += TQString::fromLatin1( "</li><li>" );
+ if ( !protocol.isNull() ) {
+ // uncomment for 3.1... i18n change
+ // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
+ doc += TQString::fromLatin1( "</li><li>" );
+ }
+ doc += i18n( "Date and Time: %1" ).arg( datetime );
+ doc += TQString::fromLatin1( "</li><li>" );
+ doc += i18n( "Additional Information: %1" ).arg( text );
+ doc += TQString::fromLatin1( "</li></ul><h3>" );
+ doc += i18n( "Description:" );
+ doc += TQString::fromLatin1( "</h3><p>" );
+ doc += description;
+ doc += TQString::fromLatin1( "</p>" );
+ if ( causes.count() ) {
+ doc += TQString::fromLatin1( "<h3>" );
+ doc += i18n( "Possible Causes:" );
+ doc += TQString::fromLatin1( "</h3><ul><li>" );
+ doc += causes.join( "</li><li>" );
+ doc += TQString::fromLatin1( "</li></ul>" );
+ }
+ if ( solutions.count() ) {
+ doc += TQString::fromLatin1( "<h3>" );
+ doc += i18n( "Possible Solutions:" );
+ doc += TQString::fromLatin1( "</h3><ul><li>" );
+ doc += solutions.join( "</li><li>" );
+ doc += TQString::fromLatin1( "</li></ul>" );
+ }
+ doc += TQString::fromLatin1( "</body></html>" );
+
+ write( doc );
+ end();
+}
+
+void KHTMLPart::slotFinished( TDEIO::Job * job )
+{
+ d->m_job = 0L;
+ d->m_jobspeed = 0L;
+
+ if (job->error())
+ {
+ KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
+
+ // The following catches errors that occur as a result of HTTP
+ // to FTP redirections where the FTP URL is a directory. Since
+ // KIO cannot change a redirection request from GET to LISTDIR,
+ // we have to take care of it here once we know for sure it is
+ // a directory...
+ if (job->error() == TDEIO::ERR_IS_DIRECTORY)
+ {
+ KParts::URLArgs args;
+ emit d->m_extension->openURLRequest( d->m_workingURL, args );
+ }
+ else
+ {
+ emit canceled( job->errorString() );
+ // TODO: what else ?
+ checkCompleted();
+ showError( job );
+ }
+
+ return;
+ }
+ TDEIO::TransferJob *tjob = ::tqqt_cast<TDEIO::TransferJob*>(job);
+ if (tjob && tjob->isErrorPage()) {
+ tdehtml::RenderPart *renderPart = d->m_frame ? static_cast<tdehtml::RenderPart *>(d->m_frame->m_frame) : 0;
+ if (renderPart) {
+ HTMLObjectElementImpl* elt = static_cast<HTMLObjectElementImpl *>(renderPart->element());
+ if (!elt)
+ return;
+ elt->renderAlternative();
+ checkCompleted();
+ }
+ if (d->m_bComplete) return;
+ }
+
+ //kdDebug( 6050 ) << "slotFinished" << endl;
+
+ KHTMLPageCache::self()->endData(d->m_cacheId);
+ if (d->m_frame && d->m_frame->m_jscript)
+ d->m_frame->m_jscript->dataReceived();
+
+ if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
+ TDEIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
+
+ d->m_workingURL = KURL();
+
+ if ( d->m_doc && d->m_doc->parsing())
+ end(); //will emit completed()
+}
+
+void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
+{
+ // No need to show this for a new page until an error is triggered
+ if (!parentPart()) {
+ removeJSErrorExtension();
+ setSuppressedPopupIndicator( false );
+ d->m_openableSuppressedPopups = 0;
+ for ( TQValueListIterator<TQGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
+ i != d->m_suppressedPopupOriginParts.end(); ++i ) {
+
+ if (KHTMLPart* part = *i) {
+ KJS::Window *w = KJS::Window::retrieveWindow( part );
+ if (w)
+ w->forgetSuppressedWindows();
+ }
+ }
+ }
+
+ clear();
+ d->m_bCleared = false;
+ d->m_cacheId = 0;
+ d->m_bComplete = false;
+ d->m_bLoadEventEmitted = false;
+
+ if(url.isValid()) {
+ TQString urlString = url.url();
+ KHTMLFactory::vLinks()->insert( urlString );
+ TQString urlString2 = url.prettyURL();
+ if ( urlString != urlString2 ) {
+ KHTMLFactory::vLinks()->insert( urlString2 );
+ }
+ }
+
+
+ // ###
+ //stopParser();
+
+ KParts::URLArgs args( d->m_extension->urlArgs() );
+ args.xOffset = xOffset;
+ args.yOffset = yOffset;
+ d->m_extension->setURLArgs( args );
+
+ d->m_pageReferrer = TQString();
+
+ KURL ref(url);
+ d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
+
+ m_url = url;
+
+ bool servedAsXHTML = args.serviceType == "application/xhtml+xml";
+ bool servedAsXML = KMimeType::mimeType(args.serviceType)->is( "text/xml" );
+ // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
+ if ( servedAsXML && !servedAsXHTML ) { // any XML derivative, except XHTML
+ d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
+ } else {
+ d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
+ // HTML or XHTML? (#86446)
+ static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( !servedAsXHTML );
+ }
+#ifndef KHTML_NO_CARET
+// d->m_view->initCaret();
+#endif
+
+ d->m_doc->ref();
+ d->m_doc->setURL( m_url.url() );
+ if (!d->m_doc->attached())
+ d->m_doc->attach( );
+ d->m_doc->setBaseURL( KURL() );
+ d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
+ emit docCreated();
+
+ d->m_paUseStylesheet->setItems(TQStringList());
+ d->m_paUseStylesheet->setEnabled( false );
+
+ setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
+ TQString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
+ if ( !userStyleSheet.isEmpty() )
+ setUserStyleSheet( KURL( userStyleSheet ) );
+
+ d->m_doc->setRestoreState(args.docState);
+ d->m_doc->open();
+ connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
+
+ emit d->m_extension->enableAction( "print", true );
+
+ d->m_doc->setParsing(true);
+}
+
+void KHTMLPart::write( const char *str, int len )
+{
+ if ( !d->m_decoder )
+ d->m_decoder = createDecoder();
+
+ if ( len == -1 )
+ len = strlen( str );
+
+ if ( len == 0 )
+ return;
+
+ TQString decoded = d->m_decoder->decode( str, len );
+
+ if(decoded.isEmpty()) return;
+
+ if(d->m_bFirstData) {
+ // determine the parse mode
+ d->m_doc->determineParseMode( decoded );
+ d->m_bFirstData = false;
+
+ //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
+ // ### this is still quite hacky, but should work a lot better than the old solution
+ if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
+ d->m_doc->setDecoderCodec(d->m_decoder->codec());
+ d->m_doc->recalcStyle( NodeImpl::Force );
+ }
+
+ tdehtml::Tokenizer* t = d->m_doc->tokenizer();
+ if(t)
+ t->write( decoded, true );
+}
+
+void KHTMLPart::write( const TQString &str )
+{
+ if ( str.isNull() )
+ return;
+
+ if(d->m_bFirstData) {
+ // determine the parse mode
+ d->m_doc->setParseMode( DocumentImpl::Strict );
+ d->m_bFirstData = false;
+ }
+ tdehtml::Tokenizer* t = d->m_doc->tokenizer();
+ if(t)
+ t->write( str, true );
+}
+
+void KHTMLPart::end()
+{
+ if (d->m_doc) {
+ if (d->m_decoder) {
+ TQString decoded = d->m_decoder->flush();
+ if (d->m_bFirstData) {
+ d->m_bFirstData = false;
+ d->m_doc->determineParseMode(decoded);
+ }
+ write(decoded);
+ }
+ d->m_doc->finishParsing();
+ }
+}
+
+bool KHTMLPart::doOpenStream( const TQString& mimeType )
+{
+ KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
+ if ( mime->is( "text/html" ) || mime->is( "text/xml" ) )
+ {
+ begin( url() );
+ return true;
+ }
+ return false;
+}
+
+bool KHTMLPart::doWriteStream( const TQByteArray& data )
+{
+ write( data.data(), data.size() );
+ return true;
+}
+
+bool KHTMLPart::doCloseStream()
+{
+ end();
+ return true;
+}
+
+
+void KHTMLPart::paint(TQPainter *p, const TQRect &rc, int yOff, bool *more)
+{
+ if (!d->m_view) return;
+ d->m_view->paint(p, rc, yOff, more);
+}
+
+void KHTMLPart::stopAnimations()
+{
+ if ( d->m_doc )
+ d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( !(*it)->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
+ KParts::ReadOnlyPart* const p = ( *it )->m_part;
+ static_cast<KHTMLPart*>( p )->stopAnimations();
+ }
+}
+
+void KHTMLPart::resetFromScript()
+{
+ closeURL();
+ d->m_bComplete = false;
+ d->m_bLoadEventEmitted = false;
+ disconnect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
+ connect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
+ d->m_doc->setParsing(true);
+
+ emit started( 0L );
+}
+
+void KHTMLPart::slotFinishedParsing()
+{
+ d->m_doc->setParsing(false);
+ checkEmitLoadEvent();
+ disconnect(d->m_doc,TQT_SIGNAL(finishedParsing()),this,TQT_SLOT(slotFinishedParsing()));
+
+ if (!d->m_view)
+ return; // We are probably being destructed.
+
+ checkCompleted();
+}
+
+void KHTMLPart::slotLoaderRequestStarted( tdehtml::DocLoader* dl, tdehtml::CachedObject *obj )
+{
+ if ( obj && obj->type() == tdehtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
+ KHTMLPart* p = this;
+ while ( p ) {
+ KHTMLPart* const op = p;
+ ++(p->d->m_totalObjectCount);
+ p = p->parentPart();
+ if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
+ && !op->d->m_progressUpdateTimer.isActive())
+ op->d->m_progressUpdateTimer.start( 200, true );
+ }
+ }
+}
+
+void KHTMLPart::slotLoaderRequestDone( tdehtml::DocLoader* dl, tdehtml::CachedObject *obj )
+{
+ if ( obj && obj->type() == tdehtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
+ KHTMLPart* p = this;
+ while ( p ) {
+ KHTMLPart* const op = p;
+ ++(p->d->m_loadedObjects);
+ p = p->parentPart();
+ if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
+ && !op->d->m_progressUpdateTimer.isActive())
+ op->d->m_progressUpdateTimer.start( 200, true );
+ }
+ }
+
+ checkCompleted();
+}
+
+void KHTMLPart::slotProgressUpdate()
+{
+ int percent;
+ if ( d->m_loadedObjects < d->m_totalObjectCount )
+ percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
+ else
+ percent = d->m_jobPercent;
+
+ if( d->m_bComplete )
+ percent = 100;
+
+ if (d->m_statusMessagesEnabled) {
+ if( d->m_bComplete )
+ emit d->m_extension->infoMessage( i18n( "Page loaded." ));
+ else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
+ emit d->m_extension->infoMessage( i18n( "%n Image of %1 loaded.", "%n Images of %1 loaded.", d->m_loadedObjects).arg(d->m_totalObjectCount) );
+ }
+
+ emit d->m_extension->loadingProgress( percent );
+}
+
+void KHTMLPart::slotJobSpeed( TDEIO::Job* /*job*/, unsigned long speed )
+{
+ d->m_jobspeed = speed;
+ if (!parentPart())
+ setStatusBarText(jsStatusBarText(), BarOverrideText);
+}
+
+void KHTMLPart::slotJobPercent( TDEIO::Job* /*job*/, unsigned long percent )
+{
+ d->m_jobPercent = percent;
+
+ if ( !parentPart() )
+ d->m_progressUpdateTimer.start( 0, true );
+}
+
+void KHTMLPart::slotJobDone( TDEIO::Job* /*job*/ )
+{
+ d->m_jobPercent = 100;
+
+ if ( !parentPart() )
+ d->m_progressUpdateTimer.start( 0, true );
+}
+
+void KHTMLPart::slotUserSheetStatDone( TDEIO::Job *_job )
+{
+ using namespace TDEIO;
+
+ if ( _job->error() ) {
+ showError( _job );
+ return;
+ }
+
+ const UDSEntry entry = dynamic_cast<TDEIO::StatJob *>( _job )->statResult();
+ UDSEntry::ConstIterator it = entry.begin();
+ const UDSEntry::ConstIterator end = entry.end();
+ for ( ; it != end; ++it ) {
+ if ( ( *it ).m_uds == UDS_MODIFICATION_TIME ) {
+ break;
+ }
+ }
+
+ // If the filesystem supports modification times, only reload the
+ // user-defined stylesheet if necessary - otherwise always reload.
+ if ( it != end ) {
+ const time_t lastModified = static_cast<time_t>( ( *it ).m_long );
+ if ( d->m_userStyleSheetLastModified >= lastModified ) {
+ return;
+ }
+ d->m_userStyleSheetLastModified = lastModified;
+ }
+
+ setUserStyleSheet( KURL( settings()->userStyleSheet() ) );
+}
+
+void KHTMLPart::checkCompleted()
+{
+// kdDebug( 6050 ) << "KHTMLPart::checkCompleted() " << this << " " << name() << endl;
+// kdDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing()) << endl;
+// kdDebug( 6050 ) << " complete: " << d->m_bComplete << endl;
+
+ // restore the cursor position
+ if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
+ {
+ if (d->m_focusNodeNumber >= 0)
+ d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
+
+ d->m_focusNodeRestored = true;
+ }
+
+ bool bPendingChildRedirection = false;
+ // Any frame that hasn't completed yet ?
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it ) {
+ if ( !(*it)->m_bCompleted )
+ {
+ //kdDebug( 6050 ) << this << " is waiting for " << (*it)->m_part << endl;
+ return;
+ }
+ // Check for frames with pending redirections
+ if ( (*it)->m_bPendingRedirection )
+ bPendingChildRedirection = true;
+ }
+
+ // Any object that hasn't completed yet ?
+ {
+ ConstFrameIt oi = d->m_objects.begin();
+ const ConstFrameIt oiEnd = d->m_objects.end();
+
+ for (; oi != oiEnd; ++oi )
+ if ( !(*oi)->m_bCompleted )
+ return;
+ }
+ // Are we still parsing - or have we done the completed stuff already ?
+ if ( d->m_bComplete || (d->m_doc && d->m_doc->parsing()) )
+ return;
+
+ // Still waiting for images/scripts from the loader ?
+ int requests = 0;
+ if ( d->m_doc && d->m_doc->docLoader() )
+ requests = tdehtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
+
+ if ( requests > 0 )
+ {
+ //kdDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests << endl;
+ return;
+ }
+
+ // OK, completed.
+ // Now do what should be done when we are really completed.
+ d->m_bComplete = true;
+ d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
+ d->m_totalObjectCount = 0;
+ d->m_loadedObjects = 0;
+
+ KHTMLPart* p = this;
+ while ( p ) {
+ KHTMLPart* op = p;
+ p = p->parentPart();
+ if ( !p && !op->d->m_progressUpdateTimer.isActive())
+ op->d->m_progressUpdateTimer.start( 0, true );
+ }
+
+ checkEmitLoadEvent(); // if we didn't do it before
+
+ bool pendingAction = false;
+
+ if ( !d->m_redirectURL.isEmpty() )
+ {
+ // DA: Do not start redirection for frames here! That action is
+ // deferred until the parent emits a completed signal.
+ if ( parentPart() == 0 ) {
+ //kdDebug(6050) << this << " starting redirection timer" << endl;
+ d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
+ } else {
+ //kdDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted." << endl;
+ }
+
+ pendingAction = true;
+ }
+ else if ( bPendingChildRedirection )
+ {
+ pendingAction = true;
+ }
+
+ // the view will emit completed on our behalf,
+ // either now or at next repaint if one is pending
+
+ //kdDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction << endl;
+ d->m_view->complete( pendingAction );
+
+ // find the alternate stylesheets
+ TQStringList sheets;
+ if (d->m_doc)
+ sheets = d->m_doc->availableStyleSheets();
+ sheets.prepend( i18n( "Automatic Detection" ) );
+ d->m_paUseStylesheet->setItems( sheets );
+
+ d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
+ if (sheets.count() > 2)
+ {
+ d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
+ slotUseStylesheet();
+ }
+
+ setJSDefaultStatusBarText(TQString());
+
+#ifdef SPEED_DEBUG
+ kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
+#endif
+}
+
+void KHTMLPart::checkEmitLoadEvent()
+{
+ if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( !(*it)->m_bCompleted ) // still got a frame running -> too early
+ return;
+
+ ConstFrameIt oi = d->m_objects.begin();
+ const ConstFrameIt oiEnd = d->m_objects.end();
+
+ for (; oi != oiEnd; ++oi )
+ if ( !(*oi)->m_bCompleted ) // still got a object running -> too early
+ return;
+
+ // Still waiting for images/scripts from the loader ?
+ // (onload must happen afterwards, #45607)
+ // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
+ int requests = 0;
+ if ( d->m_doc && d->m_doc->docLoader() )
+ requests = tdehtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
+
+ if ( requests > 0 )
+ return;
+
+ d->m_bLoadEventEmitted = true;
+ if (d->m_doc)
+ d->m_doc->close();
+}
+
+const KHTMLSettings *KHTMLPart::settings() const
+{
+ return d->m_settings;
+}
+
+#ifndef KDE_NO_COMPAT
+KURL KHTMLPart::baseURL() const
+{
+ if ( !d->m_doc ) return KURL();
+
+ return d->m_doc->baseURL();
+}
+
+TQString KHTMLPart::baseTarget() const
+{
+ if ( !d->m_doc ) return TQString();
+
+ return d->m_doc->baseTarget();
+}
+#endif
+
+KURL KHTMLPart::completeURL( const TQString &url )
+{
+ if ( !d->m_doc ) return KURL( url );
+
+ if (d->m_decoder)
+ return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
+
+ return KURL( d->m_doc->completeURL( url ) );
+}
+
+// Called by ecma/kjs_window in case of redirections from Javascript,
+// and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
+void KHTMLPart::scheduleRedirection( int delay, const TQString &url, bool doLockHistory )
+{
+ kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
+ kdDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect << endl;
+ if( delay < 24*60*60 &&
+ ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
+ d->m_delayRedirect = delay;
+ d->m_redirectURL = url;
+ d->m_redirectLockHistory = doLockHistory;
+ kdDebug(6050) << " d->m_bComplete=" << d->m_bComplete << endl;
+ if ( d->m_bComplete ) {
+ d->m_redirectionTimer.stop();
+ d->m_redirectionTimer.start( kMax(0, 1000 * d->m_delayRedirect), true );
+ }
+ }
+}
+
+void KHTMLPart::slotRedirect()
+{
+ kdDebug(6050) << this << " slotRedirect()" << endl;
+ TQString u = d->m_redirectURL;
+ d->m_delayRedirect = 0;
+ d->m_redirectURL = TQString();
+
+ // SYNC check with ecma/kjs_window.cpp::goURL !
+ if ( u.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
+ {
+ TQString script = KURL::decode_string( u.right( u.length() - 11 ) );
+ kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
+ TQVariant res = executeScript( DOM::Node(), script );
+ if ( res.type() == TQVariant::String ) {
+ begin( url() );
+ write( res.asString() );
+ end();
+ }
+ emit completed();
+ return;
+ }
+ KParts::URLArgs args;
+ KURL cUrl( m_url );
+ KURL url( u );
+
+ // handle windows opened by JS
+ if ( openedByJS() && d->m_opener )
+ cUrl = d->m_opener->url();
+
+ if (!kapp || !kapp->authorizeURLAction("redirect", cUrl, url))
+ {
+ kdWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!" << endl;
+ emit completed();
+ return;
+ }
+
+ if ( urlcmp( u, m_url.url(), true, true ) )
+ {
+ args.metaData().insert("referrer", d->m_pageReferrer);
+ }
+
+ // For javascript and META-tag based redirections:
+ // - We don't take cross-domain-ness in consideration if we are the
+ // toplevel frame because the new URL may be in a different domain as the current URL
+ // but that's ok.
+ // - If we are not the toplevel frame then we check against the toplevelURL()
+ if (parentPart())
+ args.metaData().insert("cross-domain", toplevelURL().url());
+
+ args.setLockHistory( d->m_redirectLockHistory );
+ // _self: make sure we don't use any <base target=>'s
+
+ d->m_urlSelectedOpenedURL = true; // In case overriden, default to success
+ urlSelected( u, 0, 0, "_self", args );
+
+ if ( !d->m_urlSelectedOpenedURL ) // urlSelected didn't open a url, so emit completed ourselves
+ emit completed();
+}
+
+void KHTMLPart::slotRedirection(TDEIO::Job*, const KURL& url)
+{
+ // the slave told us that we got redirected
+ //kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
+ emit d->m_extension->setLocationBarURL( url.prettyURL() );
+ d->m_workingURL = url;
+}
+
+bool KHTMLPart::setEncoding( const TQString &name, bool override )
+{
+ d->m_encoding = name;
+ d->m_haveEncoding = override;
+
+ if( !m_url.isEmpty() ) {
+ // reload document
+ closeURL();
+ KURL url = m_url;
+ m_url = 0;
+ d->m_restored = true;
+ openURL(url);
+ d->m_restored = false;
+ }
+
+ return true;
+}
+
+TQString KHTMLPart::encoding() const
+{
+ if(d->m_haveEncoding && !d->m_encoding.isEmpty())
+ return d->m_encoding;
+
+ if(d->m_decoder && d->m_decoder->encoding())
+ return TQString(d->m_decoder->encoding());
+
+ return defaultEncoding();
+}
+
+TQString KHTMLPart::defaultEncoding() const
+{
+ TQString encoding = settings()->encoding();
+ if ( !encoding.isEmpty() )
+ return encoding;
+ // HTTP requires the default encoding to be latin1, when neither
+ // the user nor the page requested a particular encoding.
+ if ( url().protocol().startsWith( "http" ) )
+ return "iso-8859-1";
+ else
+ return TDEGlobal::locale()->encoding();
+}
+
+void KHTMLPart::setUserStyleSheet(const KURL &url)
+{
+ if ( d->m_doc && d->m_doc->docLoader() )
+ (void) new tdehtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
+}
+
+void KHTMLPart::setUserStyleSheet(const TQString &styleSheet)
+{
+ if ( d->m_doc )
+ d->m_doc->setUserStyleSheet( styleSheet );
+}
+
+bool KHTMLPart::gotoAnchor( const TQString &name )
+{
+ if (!d->m_doc)
+ return false;
+
+ HTMLCollectionImpl *anchors =
+ new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
+ anchors->ref();
+ NodeImpl *n = anchors->namedItem(name);
+ anchors->deref();
+
+ if(!n) {
+ n = d->m_doc->getElementById( name );
+ }
+
+ d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
+
+ // Implement the rule that "" and "top" both mean top of page as in other browsers.
+ bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.lower() == "top");
+
+ if (quirkyName) {
+ d->m_view->setContentsPos(0, 0);
+ return true;
+ } else if (!n) {
+ kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
+ return false;
+ }
+
+ int x = 0, y = 0;
+ int gox, dummy;
+ HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
+
+ a->getUpperLeftCorner(x, y);
+ if (x <= d->m_view->contentsX())
+ gox = x - 10;
+ else {
+ gox = d->m_view->contentsX();
+ if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
+ a->getLowerRightCorner(x, dummy);
+ gox = x - d->m_view->visibleWidth() + 10;
+ }
+ }
+
+ d->m_view->setContentsPos(gox, y);
+
+ return true;
+}
+
+bool KHTMLPart::nextAnchor()
+{
+ if (!d->m_doc)
+ return false;
+ d->m_view->focusNextPrevNode ( true );
+
+ return true;
+}
+
+bool KHTMLPart::prevAnchor()
+{
+ if (!d->m_doc)
+ return false;
+ d->m_view->focusNextPrevNode ( false );
+
+ return true;
+}
+
+void KHTMLPart::setStandardFont( const TQString &name )
+{
+ d->m_settings->setStdFontName(name);
+}
+
+void KHTMLPart::setFixedFont( const TQString &name )
+{
+ d->m_settings->setFixedFontName(name);
+}
+
+void KHTMLPart::setURLCursor( const TQCursor &c )
+{
+ d->m_linkCursor = c;
+}
+
+TQCursor KHTMLPart::urlCursor() const
+{
+ return d->m_linkCursor;
+}
+
+bool KHTMLPart::onlyLocalReferences() const
+{
+ return d->m_onlyLocalReferences;
+}
+
+void KHTMLPart::setOnlyLocalReferences(bool enable)
+{
+ d->m_onlyLocalReferences = enable;
+}
+
+void KHTMLPartPrivate::setFlagRecursively(
+ bool KHTMLPartPrivate::*flag, bool value)
+{
+ // first set it on the current one
+ this->*flag = value;
+
+ // descend into child frames recursively
+ {
+ TQValueList<tdehtml::ChildFrame*>::Iterator it = m_frames.begin();
+ const TQValueList<tdehtml::ChildFrame*>::Iterator itEnd = m_frames.end();
+ for (; it != itEnd; ++it) {
+ KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
+ if (part->inherits("KHTMLPart"))
+ part->d->setFlagRecursively(flag, value);
+ }/*next it*/
+ }
+ // do the same again for objects
+ {
+ TQValueList<tdehtml::ChildFrame*>::Iterator it = m_objects.begin();
+ const TQValueList<tdehtml::ChildFrame*>::Iterator itEnd = m_objects.end();
+ for (; it != itEnd; ++it) {
+ KHTMLPart* const part = static_cast<KHTMLPart *>((KParts::ReadOnlyPart *)(*it)->m_part);
+ if (part->inherits("KHTMLPart"))
+ part->d->setFlagRecursively(flag, value);
+ }/*next it*/
+ }
+}
+
+void KHTMLPart::setCaretMode(bool enable)
+{
+#ifndef KHTML_NO_CARET
+ kdDebug(6200) << "setCaretMode(" << enable << ")" << endl;
+ if (isCaretMode() == enable) return;
+ d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
+ // FIXME: this won't work on frames as expected
+ if (!isEditable()) {
+ if (enable) {
+ view()->initCaret(true);
+ view()->ensureCaretVisible();
+ } else
+ view()->caretOff();
+ }/*end if*/
+#endif // KHTML_NO_CARET
+}
+
+bool KHTMLPart::isCaretMode() const
+{
+ return d->m_caretMode;
+}
+
+void KHTMLPart::setEditable(bool enable)
+{
+#ifndef KHTML_NO_CARET
+ if (isEditable() == enable) return;
+ d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
+ // FIXME: this won't work on frames as expected
+ if (!isCaretMode()) {
+ if (enable) {
+ view()->initCaret(true);
+ view()->ensureCaretVisible();
+ } else
+ view()->caretOff();
+ }/*end if*/
+#endif // KHTML_NO_CARET
+}
+
+bool KHTMLPart::isEditable() const
+{
+ return d->m_designMode;
+}
+
+void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
+{
+#ifndef KHTML_NO_CARET
+#if 0
+ kdDebug(6200) << k_funcinfo << "node: " << node.handle() << " nodeName: "
+ << node.nodeName().string() << " offset: " << offset
+ << " extendSelection " << extendSelection << endl;
+#endif
+ if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
+ emitSelectionChanged();
+ view()->ensureCaretVisible();
+#endif // KHTML_NO_CARET
+}
+
+KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
+{
+#ifndef KHTML_NO_CARET
+ return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
+#else // KHTML_NO_CARET
+ return CaretInvisible;
+#endif // KHTML_NO_CARET
+}
+
+void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
+{
+#ifndef KHTML_NO_CARET
+ view()->setCaretDisplayPolicyNonFocused(policy);
+#endif // KHTML_NO_CARET
+}
+
+void KHTMLPart::setCaretVisible(bool show)
+{
+#ifndef KHTML_NO_CARET
+ if (show) {
+
+ NodeImpl *caretNode = xmlDocImpl()->focusNode();
+ if (isCaretMode() || isEditable()
+ || (caretNode && caretNode->contentEditable())) {
+ view()->caretOn();
+ }/*end if*/
+
+ } else {
+
+ view()->caretOff();
+
+ }/*end if*/
+#endif // KHTML_NO_CARET
+}
+
+void KHTMLPart::findTextBegin()
+{
+ d->m_findPos = -1;
+ d->m_findNode = 0;
+ d->m_findPosEnd = -1;
+ d->m_findNodeEnd= 0;
+ d->m_findPosStart = -1;
+ d->m_findNodeStart = 0;
+ d->m_findNodePrevious = 0;
+ delete d->m_find;
+ d->m_find = 0L;
+}
+
+bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
+{
+ if ( !d->m_doc )
+ return false;
+
+ DOM::NodeImpl* firstNode = 0L;
+ if (d->m_doc->isHTMLDocument())
+ firstNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
+ else
+ firstNode = d->m_doc;
+
+ if ( !firstNode )
+ {
+ //kdDebug(6050) << k_funcinfo << "no first node (body or doc) -> return false" << endl;
+ return false;
+ }
+ if ( firstNode->id() == ID_FRAMESET )
+ {
+ //kdDebug(6050) << k_funcinfo << "FRAMESET -> return false" << endl;
+ return false;
+ }
+
+ if ( selection && hasSelection() )
+ {
+ //kdDebug(6050) << k_funcinfo << "using selection" << endl;
+ if ( !fromCursor )
+ {
+ d->m_findNode = reverse ? d->m_selectionEnd.handle() : d->m_selectionStart.handle();
+ d->m_findPos = reverse ? d->m_endOffset : d->m_startOffset;
+ }
+ d->m_findNodeEnd = reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
+ d->m_findPosEnd = reverse ? d->m_startOffset : d->m_endOffset;
+ d->m_findNodeStart = !reverse ? d->m_selectionStart.handle() : d->m_selectionEnd.handle();
+ d->m_findPosStart = !reverse ? d->m_startOffset : d->m_endOffset;
+ d->m_findNodePrevious = d->m_findNodeStart;
+ }
+ else // whole document
+ {
+ //kdDebug(6050) << k_funcinfo << "whole doc" << endl;
+ if ( !fromCursor )
+ {
+ d->m_findNode = firstNode;
+ d->m_findPos = reverse ? -1 : 0;
+ }
+ d->m_findNodeEnd = reverse ? firstNode : 0;
+ d->m_findPosEnd = reverse ? 0 : -1;
+ d->m_findNodeStart = !reverse ? firstNode : 0;
+ d->m_findPosStart = !reverse ? 0 : -1;
+ d->m_findNodePrevious = d->m_findNodeStart;
+ if ( reverse )
+ {
+ // Need to find out the really last object, to start from it
+ tdehtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
+ if ( obj )
+ {
+ // find the last object in the render tree
+ while ( obj->lastChild() )
+ {
+ obj = obj->lastChild();
+ }
+ // now get the last object with a NodeImpl associated
+ while ( !obj->element() && obj->objectAbove() )
+ {
+ obj = obj->objectAbove();
+ }
+ d->m_findNode = obj->element();
+ }
+ }
+ }
+ return true;
+}
+
+// Old method (its API limits the available features - remove in KDE-4)
+bool KHTMLPart::findTextNext( const TQString &str, bool forward, bool caseSensitive, bool isRegExp )
+{
+ if ( !initFindNode( false, !forward, d->m_findNode ) )
+ return false;
+ while(1)
+ {
+ if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
+ {
+ DOMString nodeText = d->m_findNode->nodeValue();
+ DOMStringImpl *t = nodeText.implementation();
+ TQConstString s(t->s, t->l);
+
+ int matchLen = 0;
+ if ( isRegExp ) {
+ TQRegExp matcher( str );
+ matcher.setCaseSensitive( caseSensitive );
+ d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
+ if ( d->m_findPos != -1 )
+ matchLen = matcher.matchedLength();
+ }
+ else {
+ d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
+ matchLen = str.length();
+ }
+
+ if(d->m_findPos != -1)
+ {
+ int x = 0, y = 0;
+ if(static_cast<tdehtml::RenderText *>(d->m_findNode->renderer())
+ ->posOfChar(d->m_findPos, x, y))
+ d->m_view->setContentsPos(x-50, y-50);
+
+ d->m_selectionStart = d->m_findNode;
+ d->m_startOffset = d->m_findPos;
+ d->m_selectionEnd = d->m_findNode;
+ d->m_endOffset = d->m_findPos + matchLen;
+ d->m_startBeforeEnd = true;
+
+ d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset );
+ emitSelectionChanged();
+ return true;
+ }
+ }
+ d->m_findPos = -1;
+
+ NodeImpl *next;
+
+ if ( forward )
+ {
+ next = d->m_findNode->firstChild();
+
+ if(!next) next = d->m_findNode->nextSibling();
+ while(d->m_findNode && !next) {
+ d->m_findNode = d->m_findNode->parentNode();
+ if( d->m_findNode ) {
+ next = d->m_findNode->nextSibling();
+ }
+ }
+ }
+ else
+ {
+ next = d->m_findNode->lastChild();
+
+ if (!next ) next = d->m_findNode->previousSibling();
+ while ( d->m_findNode && !next )
+ {
+ d->m_findNode = d->m_findNode->parentNode();
+ if( d->m_findNode )
+ {
+ next = d->m_findNode->previousSibling();
+ }
+ }
+ }
+
+ d->m_findNode = next;
+ if(!d->m_findNode) return false;
+ }
+}
+
+
+void KHTMLPart::slotFind()
+{
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (!part)
+ return;
+ if (!part->inherits("KHTMLPart") )
+ {
+ kdError(6000) << "slotFind: part is a " << part->className() << ", can't do a search into it" << endl;
+ return;
+ }
+ static_cast<KHTMLPart *>( part )->findText();
+}
+
+void KHTMLPart::slotFindNext()
+{
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (!part)
+ return;
+ if (!part->inherits("KHTMLPart") )
+ {
+ kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
+ return;
+ }
+ static_cast<KHTMLPart *>( part )->findTextNext();
+}
+
+void KHTMLPart::slotFindPrev()
+{
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (!part)
+ return;
+ if (!part->inherits("KHTMLPart") )
+ {
+ kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
+ return;
+ }
+ static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
+}
+
+void KHTMLPart::slotFindDone()
+{
+ // ### remove me
+}
+
+void KHTMLPart::slotFindAheadText()
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (!part)
+ return;
+ if (!part->inherits("KHTMLPart") )
+ {
+ kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
+ return;
+ }
+ static_cast<KHTMLPart *>( part )->view()->startFindAhead( false );
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+}
+
+void KHTMLPart::slotFindAheadLink()
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (!part)
+ return;
+ if (!part->inherits("KHTMLPart") )
+ {
+ kdError(6000) << "slotFindNext: part is a " << part->className() << ", can't do a search into it" << endl;
+ return;
+ }
+ static_cast<KHTMLPart *>( part )->view()->startFindAhead( true );
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+}
+
+void KHTMLPart::enableFindAheadActions( bool enable )
+{
+ // only the topmost one has shortcuts
+ KHTMLPart* p = this;
+ while( p->parentPart())
+ p = p->parentPart();
+ p->d->m_paFindAheadText->setEnabled( enable );
+ p->d->m_paFindAheadLinks->setEnabled( enable );
+}
+
+void KHTMLPart::slotFindDialogDestroyed()
+{
+ d->m_lastFindState.options = d->m_findDialog->options();
+ d->m_lastFindState.history = d->m_findDialog->findHistory();
+ d->m_findDialog->deleteLater();
+ d->m_findDialog = 0L;
+}
+
+void KHTMLPart::findText()
+{
+ // First do some init to make sure we can search in this frame
+ if ( !d->m_doc )
+ return;
+
+ // Raise if already opened
+ if ( d->m_findDialog )
+ {
+ KWin::activateWindow( d->m_findDialog->winId() );
+ return;
+ }
+
+ // The lineedit of the dialog would make tdehtml lose its selection, otherwise
+#ifndef QT_NO_CLIPBOARD
+ disconnect( kapp->clipboard(), TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotClearSelection()) );
+#endif
+
+ // Now show the dialog in which the user can choose options.
+ d->m_findDialog = new KFindDialog( false /*non-modal*/, widget(), "tdehtmlfind" );
+ d->m_findDialog->setHasSelection( hasSelection() );
+ d->m_findDialog->setHasCursor( d->m_findNode != 0 );
+ if ( d->m_findNode ) // has a cursor -> default to 'FromCursor'
+ d->m_lastFindState.options |= KFindDialog::FromCursor;
+
+ // TODO? optionsDialog.setPattern( d->m_lastFindState.text );
+ d->m_findDialog->setFindHistory( d->m_lastFindState.history );
+ d->m_findDialog->setOptions( d->m_lastFindState.options );
+
+ d->m_lastFindState.options = -1; // force update in findTextNext
+ d->m_lastFindState.last_dir = -1;
+
+ d->m_findDialog->show();
+ connect( d->m_findDialog, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotFindNext()) );
+ connect( d->m_findDialog, TQT_SIGNAL(finished()), this, TQT_SLOT(slotFindDialogDestroyed()) );
+
+ findText( d->m_findDialog->pattern(), 0 /*options*/, widget(), d->m_findDialog );
+}
+
+void KHTMLPart::findText( const TQString &str, long options, TQWidget *parent, KFindDialog *findDialog )
+{
+ // First do some init to make sure we can search in this frame
+ if ( !d->m_doc )
+ return;
+
+#ifndef QT_NO_CLIPBOARD
+ connect( kapp->clipboard(), TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotClearSelection()) );
+#endif
+
+ // Create the KFind object
+ delete d->m_find;
+ d->m_find = new KFind( str, options, parent, findDialog );
+ d->m_find->closeFindNextDialog(); // we use KFindDialog non-modal, so we don't want other dlg popping up
+ connect( d->m_find, TQT_SIGNAL( highlight( const TQString &, int, int ) ),
+ this, TQT_SLOT( slotHighlight( const TQString &, int, int ) ) );
+ //connect(d->m_find, TQT_SIGNAL( findNext() ),
+ // this, TQT_SLOT( slotFindNext() ) );
+
+ if ( !findDialog )
+ {
+ d->m_lastFindState.options = options;
+ initFindNode( options & KFindDialog::SelectedText,
+ options & KFindDialog::FindBackwards,
+ options & KFindDialog::FromCursor );
+ }
+}
+
+bool KHTMLPart::findTextNext()
+{
+ return findTextNext( false );
+}
+
+// New method
+bool KHTMLPart::findTextNext( bool reverse )
+{
+ if (!d->m_find)
+ {
+ // We didn't show the find dialog yet, let's do it then (#49442)
+ findText();
+ return false;
+ }
+
+ view()->updateFindAheadTimeout();
+ long options = 0;
+ if ( d->m_findDialog ) // 0 when we close the dialog
+ {
+ if ( d->m_find->pattern() != d->m_findDialog->pattern() ) {
+ d->m_find->setPattern( d->m_findDialog->pattern() );
+ d->m_find->resetCounts();
+ }
+ options = d->m_findDialog->options();
+ if ( d->m_lastFindState.options != options )
+ {
+ d->m_find->setOptions( options );
+
+ if ( options & KFindDialog::SelectedText )
+ Q_ASSERT( hasSelection() );
+
+ long difference = d->m_lastFindState.options ^ options;
+ if ( difference & (KFindDialog::SelectedText | KFindDialog::FromCursor ) )
+ {
+ // Important options changed -> reset search range
+ (void) initFindNode( options & KFindDialog::SelectedText,
+ options & KFindDialog::FindBackwards,
+ options & KFindDialog::FromCursor );
+ }
+ d->m_lastFindState.options = options;
+ }
+ } else
+ options = d->m_lastFindState.options;
+ if( reverse )
+ options = options ^ KFindDialog::FindBackwards;
+ if( d->m_find->options() != options )
+ d->m_find->setOptions( options );
+
+ // Changing find direction. Start and end nodes must be switched.
+ // Additionally since d->m_findNode points after the last node
+ // that was searched, it needs to be "after" it in the opposite direction.
+ if( d->m_lastFindState.last_dir != -1
+ && bool( d->m_lastFindState.last_dir ) != bool( options & KFindDialog::FindBackwards ))
+ {
+ tqSwap( d->m_findNodeEnd, d->m_findNodeStart );
+ tqSwap( d->m_findPosEnd, d->m_findPosStart );
+ tqSwap( d->m_findNode, d->m_findNodePrevious );
+ // d->m_findNode now point at the end of the last searched line - advance one node
+ tdehtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
+ tdehtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
+ if ( obj == end )
+ obj = 0L;
+ else if ( obj )
+ {
+ do {
+ obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
+ } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
+ }
+ if ( obj )
+ d->m_findNode = obj->element();
+ else
+ d->m_findNode = 0;
+ }
+ d->m_lastFindState.last_dir = ( options & KFindDialog::FindBackwards ) ? 1 : 0;
+
+ KFind::Result res = KFind::NoMatch;
+ tdehtml::RenderObject* obj = d->m_findNode ? d->m_findNode->renderer() : 0;
+ tdehtml::RenderObject* end = d->m_findNodeEnd ? d->m_findNodeEnd->renderer() : 0;
+ tdehtml::RenderTextArea *tmpTextArea=0L;
+ //kdDebug(6050) << k_funcinfo << "obj=" << obj << " end=" << end << endl;
+ while( res == KFind::NoMatch )
+ {
+ if ( d->m_find->needData() )
+ {
+ if ( !obj ) {
+ //kdDebug(6050) << k_funcinfo << "obj=0 -> done" << endl;
+ break; // we're done
+ }
+ //kdDebug(6050) << k_funcinfo << " gathering data" << endl;
+ // First make up the TQString for the current 'line' (i.e. up to \n)
+ // We also want to remember the DOMNode for every portion of the string.
+ // We store this in an index->node list.
+
+ d->m_stringPortions.clear();
+ bool newLine = false;
+ TQString str;
+ DOM::NodeImpl* lastNode = d->m_findNode;
+ while ( obj && !newLine )
+ {
+ // Grab text from render object
+ TQString s;
+ bool renderAreaText = obj->parent() && (TQCString(obj->parent()->renderName())== "RenderTextArea");
+ bool renderLineText = (TQCString(obj->renderName())== "RenderLineEdit");
+ if ( renderAreaText )
+ {
+ tdehtml::RenderTextArea *parent= static_cast<tdehtml::RenderTextArea *>(obj->parent());
+ s = parent->text();
+ s = s.replace(0xa0, ' ');
+ tmpTextArea = parent;
+ }
+ else if ( renderLineText )
+ {
+ tdehtml::RenderLineEdit *parentLine= static_cast<tdehtml::RenderLineEdit *>(obj);
+ if (parentLine->widget()->echoMode() == TQLineEdit::Normal)
+ s = parentLine->widget()->text();
+ s = s.replace(0xa0, ' ');
+ }
+ else if ( obj->isText() )
+ {
+ bool isLink = false;
+
+ // checks whether the node has a <A> parent
+ if ( options & FindLinksOnly )
+ {
+ DOM::NodeImpl *parent = obj->element();
+ while ( parent )
+ {
+ if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
+ {
+ isLink = true;
+ break;
+ }
+ parent = parent->parentNode();
+ }
+ }
+ else
+ {
+ isLink = true;
+ }
+
+ if ( isLink && obj->parent()!=tmpTextArea )
+ {
+ s = static_cast<tdehtml::RenderText *>(obj)->data().string();
+ s = s.replace(0xa0, ' ');
+ }
+ }
+ else if ( obj->isBR() )
+ s = '\n';
+ else if ( !obj->isInline() && !str.isEmpty() )
+ s = '\n';
+
+ if ( lastNode == d->m_findNodeEnd )
+ s.truncate( d->m_findPosEnd );
+ if ( !s.isEmpty() )
+ {
+ newLine = s.find( '\n' ) != -1; // did we just get a newline?
+ if( !( options & KFindDialog::FindBackwards ))
+ {
+ //kdDebug(6050) << "StringPortion: " << index << "-" << index+s.length()-1 << " -> " << lastNode << endl;
+ d->m_stringPortions.append( KHTMLPartPrivate::StringPortion( str.length(), lastNode ) );
+ str += s;
+ }
+ else // KFind itself can search backwards, so str must not be built backwards
+ {
+ for( TQValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
+ it != d->m_stringPortions.end();
+ ++it )
+ (*it).index += s.length();
+ d->m_stringPortions.prepend( KHTMLPartPrivate::StringPortion( 0, lastNode ) );
+ str.prepend( s );
+ }
+ }
+ // Compare obj and end _after_ we processed the 'end' node itself
+ if ( obj == end )
+ obj = 0L;
+ else
+ {
+ // Move on to next object (note: if we found a \n already, then obj (and lastNode)
+ // will point to the _next_ object, i.e. they are in advance.
+ do {
+ // We advance until the next RenderObject that has a NodeImpl as its element().
+ // Otherwise (if we keep the 'last node', and it has a '\n') we might be stuck
+ // on that object forever...
+ obj = (options & KFindDialog::FindBackwards) ? obj->objectAbove() : obj->objectBelow();
+ } while ( obj && ( !obj->element() || obj->isInlineContinuation() ) );
+ }
+ if ( obj )
+ lastNode = obj->element();
+ else
+ lastNode = 0;
+ } // end while
+ //kdDebug()<<" str : "<<str<<endl;
+ if ( !str.isEmpty() )
+ {
+ d->m_find->setData( str, d->m_findPos );
+ }
+
+ d->m_findPos = -1; // not used during the findnext loops. Only during init.
+ d->m_findNodePrevious = d->m_findNode;
+ d->m_findNode = lastNode;
+ }
+ if ( !d->m_find->needData() ) // happens if str was empty
+ {
+ // Let KFind inspect the text fragment, and emit highlighted if a match is found
+ res = d->m_find->find();
+ }
+ } // end while
+
+ if ( res == KFind::NoMatch ) // i.e. we're done
+ {
+ kdDebug() << "No more matches." << endl;
+ if ( !(options & FindNoPopups) && d->m_find->shouldRestart() )
+ {
+ //kdDebug(6050) << "Restarting" << endl;
+ initFindNode( false, options & KFindDialog::FindBackwards, false );
+ d->m_find->resetCounts();
+ findTextNext( reverse );
+ }
+ else // really done
+ {
+ //kdDebug(6050) << "Finishing" << endl;
+ //delete d->m_find;
+ //d->m_find = 0L;
+ initFindNode( false, options & KFindDialog::FindBackwards, false );
+ d->m_find->resetCounts();
+ slotClearSelection();
+ }
+ kdDebug() << "Dialog closed." << endl;
+ }
+
+ return res == KFind::Match;
+}
+
+void KHTMLPart::slotHighlight( const TQString& /*text*/, int index, int length )
+{
+ //kdDebug(6050) << "slotHighlight index=" << index << " length=" << length << endl;
+ TQValueList<KHTMLPartPrivate::StringPortion>::Iterator it = d->m_stringPortions.begin();
+ const TQValueList<KHTMLPartPrivate::StringPortion>::Iterator itEnd = d->m_stringPortions.end();
+ TQValueList<KHTMLPartPrivate::StringPortion>::Iterator prev = it;
+ // We stop at the first portion whose index is 'greater than', and then use the previous one
+ while ( it != itEnd && (*it).index <= index )
+ {
+ prev = it;
+ ++it;
+ }
+ Q_ASSERT ( prev != itEnd );
+ DOM::NodeImpl* node = (*prev).node;
+ Q_ASSERT( node );
+
+ d->m_selectionStart = node;
+ d->m_startOffset = index - (*prev).index;
+
+ tdehtml::RenderObject* obj = node->renderer();
+ tdehtml::RenderTextArea *parent = 0L;
+ tdehtml::RenderLineEdit *parentLine = 0L;
+ bool renderLineText =false;
+
+ TQRect highlightedRect;
+ bool renderAreaText =false;
+ Q_ASSERT( obj );
+ if ( obj )
+ {
+ int x = 0, y = 0;
+ renderAreaText = (TQCString(obj->parent()->renderName())== "RenderTextArea");
+ renderLineText = (TQCString(obj->renderName())== "RenderLineEdit");
+
+
+ if( renderAreaText )
+ parent= static_cast<tdehtml::RenderTextArea *>(obj->parent());
+ if ( renderLineText )
+ parentLine= static_cast<tdehtml::RenderLineEdit *>(obj);
+ if ( !renderLineText )
+ //if (static_cast<tdehtml::RenderText *>(node->renderer())
+ // ->posOfChar(d->m_startOffset, x, y))
+ {
+ int dummy;
+ static_cast<tdehtml::RenderText *>(node->renderer())
+ ->caretPos( d->m_startOffset, false, x, y, dummy, dummy ); // more precise than posOfChar
+ //kdDebug(6050) << "topleft: " << x << "," << y << endl;
+ if ( x != -1 || y != -1 )
+ {
+ int gox = d->m_view->contentsX();
+ if (x+50 > d->m_view->contentsX() + d->m_view->visibleWidth())
+ gox = x - d->m_view->visibleWidth() + 50;
+ if (x-10 < d->m_view->contentsX())
+ gox = x - d->m_view->visibleWidth() - 10;
+ if (gox < 0) gox = 0;
+ d->m_view->setContentsPos(gox, y-50);
+ highlightedRect.setTopLeft( d->m_view->mapToGlobal(TQPoint(x, y)) );
+ }
+ }
+ }
+ // Now look for end node
+ it = prev; // no need to start from beginning again
+ while ( it != itEnd && (*it).index < index + length )
+ {
+ prev = it;
+ ++it;
+ }
+ Q_ASSERT ( prev != itEnd );
+
+ d->m_selectionEnd = (*prev).node;
+ d->m_endOffset = index + length - (*prev).index;
+ d->m_startBeforeEnd = true;
+
+ // if the selection is limited to a single link, that link gets focus
+ if(d->m_selectionStart == d->m_selectionEnd)
+ {
+ bool isLink = false;
+
+ // checks whether the node has a <A> parent
+ DOM::NodeImpl *parent = d->m_selectionStart.handle();
+ while ( parent )
+ {
+ if ( parent->nodeType() == Node::ELEMENT_NODE && parent->id() == ID_A )
+ {
+ isLink = true;
+ break;
+ }
+ parent = parent->parentNode();
+ }
+
+ if(isLink == true)
+ {
+ d->m_doc->setFocusNode( parent );
+ }
+ }
+
+#if 0
+ kdDebug(6050) << "slotHighlight: " << d->m_selectionStart.handle() << "," << d->m_startOffset << " - " <<
+ d->m_selectionEnd.handle() << "," << d->m_endOffset << endl;
+ it = d->m_stringPortions.begin();
+ for ( ; it != d->m_stringPortions.end() ; ++it )
+ kdDebug(6050) << " StringPortion: from index=" << (*it).index << " -> node=" << (*it).node << endl;
+#endif
+ if( renderAreaText )
+ {
+ if( parent )
+ parent->highLightWord( length, d->m_endOffset-length );
+ }
+ else if ( renderLineText )
+ {
+ if( parentLine )
+ parentLine->highLightWord( length, d->m_endOffset-length );
+ }
+ else
+ {
+ d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset );
+ if (d->m_selectionEnd.handle()->renderer() )
+ {
+ int x, y, height, dummy;
+ static_cast<tdehtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
+ ->caretPos( d->m_endOffset, false, x, y, dummy, height ); // more precise than posOfChar
+ //kdDebug(6050) << "bottomright: " << x << "," << y+height << endl;
+ if ( x != -1 || y != -1 )
+ {
+ // if ( static_cast<tdehtml::RenderText *>(d->m_selectionEnd.handle()->renderer())
+ // ->posOfChar(d->m_endOffset-1, x, y))
+ highlightedRect.setBottomRight( d->m_view->mapToGlobal( TQPoint(x, y+height) ) );
+ }
+ }
+ }
+ emitSelectionChanged();
+
+ // make the finddialog move away from the selected area
+ if ( d->m_findDialog && !highlightedRect.isNull() )
+ {
+ highlightedRect.moveBy( -d->m_view->contentsX(), -d->m_view->contentsY() );
+ //kdDebug(6050) << "avoiding " << highlightedRect << endl;
+ KDialog::avoidArea( d->m_findDialog, highlightedRect );
+ }
+}
+
+TQString KHTMLPart::selectedTextAsHTML() const
+{
+ if(!hasSelection()) {
+ kdDebug() << "selectedTextAsHTML(): selection is not valid. Returning empty selection" << endl;
+ return TQString();
+ }
+ if(d->m_startOffset < 0 || d->m_endOffset <0) {
+ kdDebug() << "invalid values for end/startOffset " << d->m_startOffset << " " << d->m_endOffset << endl;
+ return TQString();
+ }
+ DOM::Range r = selection();
+ if(r.isNull() || r.isDetached())
+ return TQString();
+ int exceptioncode = 0; //ignore the result
+ return r.handle()->toHTML(exceptioncode).string();
+}
+
+TQString KHTMLPart::selectedText() const
+{
+ bool hasNewLine = true;
+ bool seenTDTag = false;
+ TQString text;
+ DOM::Node n = d->m_selectionStart;
+ while(!n.isNull()) {
+ if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
+ DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
+ TQString str(dstr->s, dstr->l);
+ if(!str.isEmpty()) {
+ if(seenTDTag) {
+ text += " ";
+ seenTDTag = false;
+ }
+ hasNewLine = false;
+ if(n == d->m_selectionStart && n == d->m_selectionEnd)
+ text = str.mid(d->m_startOffset, d->m_endOffset - d->m_startOffset);
+ else if(n == d->m_selectionStart)
+ text = str.mid(d->m_startOffset);
+ else if(n == d->m_selectionEnd)
+ text += str.left(d->m_endOffset);
+ else
+ text += str;
+ }
+ }
+ else {
+ // This is our simple HTML -> ASCII transformation:
+ unsigned short id = n.elementId();
+ switch(id) {
+ case ID_TEXTAREA:
+ text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
+ break;
+ case ID_INPUT:
+ if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
+ text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
+ break;
+ case ID_SELECT:
+ text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
+ break;
+ case ID_BR:
+ text += "\n";
+ hasNewLine = true;
+ break;
+ case ID_IMG:
+ text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
+ break;
+ case ID_TD:
+ break;
+ case ID_TH:
+ case ID_HR:
+ case ID_OL:
+ case ID_UL:
+ case ID_LI:
+ case ID_DD:
+ case ID_DL:
+ case ID_DT:
+ case ID_PRE:
+ case ID_BLOCKQUOTE:
+ case ID_DIV:
+ if (!hasNewLine)
+ text += "\n";
+ hasNewLine = true;
+ break;
+ case ID_P:
+ case ID_TR:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ if (!hasNewLine)
+ text += "\n";
+// text += "\n";
+ hasNewLine = true;
+ break;
+ }
+ }
+ if(n == d->m_selectionEnd) break;
+ DOM::Node next = n.firstChild();
+ if(next.isNull()) next = n.nextSibling();
+ while( next.isNull() && !n.parentNode().isNull() ) {
+ n = n.parentNode();
+ next = n.nextSibling();
+ unsigned short id = n.elementId();
+ switch(id) {
+ case ID_TD:
+ seenTDTag = true; //Add two spaces after a td if then followed by text.
+ break;
+ case ID_TH:
+ case ID_HR:
+ case ID_OL:
+ case ID_UL:
+ case ID_LI:
+ case ID_DD:
+ case ID_DL:
+ case ID_DT:
+ case ID_PRE:
+ case ID_BLOCKQUOTE:
+ case ID_DIV:
+ seenTDTag = false;
+ if (!hasNewLine)
+ text += "\n";
+ hasNewLine = true;
+ break;
+ case ID_P:
+ case ID_TR:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ if (!hasNewLine)
+ text += "\n";
+// text += "\n";
+ hasNewLine = true;
+ break;
+ }
+ }
+
+ n = next;
+ }
+
+ if(text.isEmpty())
+ return TQString();
+
+ int start = 0;
+ int end = text.length();
+
+ // Strip leading LFs
+ while ((start < end) && (text[start] == '\n'))
+ ++start;
+
+ // Strip excessive trailing LFs
+ while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
+ --end;
+
+ return text.mid(start, end-start);
+}
+
+bool KHTMLPart::hasSelection() const
+{
+ if ( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
+ return false;
+ if ( d->m_selectionStart == d->m_selectionEnd &&
+ d->m_startOffset == d->m_endOffset )
+ return false; // empty
+ return true;
+}
+
+DOM::Range KHTMLPart::selection() const
+{
+ if( d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() )
+ return DOM::Range();
+ DOM::Range r = document().createRange();
+ RangeImpl *rng = r.handle();
+ int exception = 0;
+ NodeImpl *n = d->m_selectionStart.handle();
+ if(!n->parentNode() ||
+ !n->renderer() ||
+ (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
+ rng->setStart( n, d->m_startOffset, exception );
+ if(exception) {
+ kdDebug(6000) << "1 -selection() threw the exception " << exception << ". Returning empty range." << endl;
+ return DOM::Range();
+ }
+ } else {
+ int o_start = 0;
+ while ((n = n->previousSibling()))
+ o_start++;
+ rng->setStart( d->m_selectionStart.parentNode().handle(), o_start + d->m_startOffset, exception );
+ if(exception) {
+ kdDebug(6000) << "2 - selection() threw the exception " << exception << ". Returning empty range." << endl;
+ return DOM::Range();
+ }
+
+ }
+
+ n = d->m_selectionEnd.handle();
+ if(!n->parentNode() ||
+ !n->renderer() ||
+ (!n->renderer()->isReplaced() && !n->renderer()->isBR())) {
+
+ rng->setEnd( n, d->m_endOffset, exception );
+ if(exception) {
+ kdDebug(6000) << "3 - selection() threw the exception " << exception << ". Returning empty range." << endl;
+ return DOM::Range();
+ }
+
+ } else {
+ int o_end = 0;
+ while ((n = n->previousSibling()))
+ o_end++;
+ rng->setEnd( d->m_selectionEnd.parentNode().handle(), o_end + d->m_endOffset, exception);
+ if(exception) {
+ kdDebug(6000) << "4 - selection() threw the exception " << exception << ". Returning empty range." << endl;
+ return DOM::Range();
+ }
+
+ }
+
+ return r;
+}
+
+void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
+{
+ s = d->m_selectionStart;
+ so = d->m_startOffset;
+ e = d->m_selectionEnd;
+ eo = d->m_endOffset;
+}
+
+void KHTMLPart::setSelection( const DOM::Range &r )
+{
+ // Quick-fix: a collapsed range shouldn't select the whole node.
+ // The real problem is in RenderCanvas::setSelection though (when index==0 the whole node is selected).
+ if ( r.collapsed() )
+ slotClearSelection();
+ else {
+ d->m_selectionStart = r.startContainer();
+ d->m_startOffset = r.startOffset();
+ d->m_selectionEnd = r.endContainer();
+ d->m_endOffset = r.endOffset();
+ d->m_doc->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+ d->m_selectionEnd.handle(),d->m_endOffset);
+#ifndef KHTML_NO_CARET
+ bool v = d->m_view->placeCaret();
+ emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
+#endif
+ }
+}
+
+void KHTMLPart::slotClearSelection()
+{
+ bool hadSelection = hasSelection();
+#ifndef KHTML_NO_CARET
+ //kdDebug(6000) << "d->m_selectionStart " << d->m_selectionStart.handle()
+ // << " d->m_selectionEnd " << d->m_selectionEnd.handle() << endl;
+ // nothing, leave selection parameters as is
+#else
+ d->m_selectionStart = 0;
+ d->m_startOffset = 0;
+ d->m_selectionEnd = 0;
+ d->m_endOffset = 0;
+#endif
+ if ( d->m_doc ) d->m_doc->clearSelection();
+ if ( hadSelection )
+ emitSelectionChanged();
+#ifndef KHTML_NO_CARET
+ bool v = d->m_view->placeCaret();
+ emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
+#endif
+}
+
+void KHTMLPart::resetHoverText()
+{
+ if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
+ {
+ d->m_overURL = d->m_overURLTarget = TQString();
+ emit onURL( TQString() );
+ // revert to default statusbar text
+ setStatusBarText(TQString(), BarHoverText);
+ emit d->m_extension->mouseOverInfo(0);
+ }
+}
+
+void KHTMLPart::overURL( const TQString &url, const TQString &target, bool /*shiftPressed*/ )
+{
+ KURL u = completeURL(url);
+
+ // special case for <a href="">
+ if ( url.isEmpty() )
+ u.setFileName( url );
+
+ emit onURL( url );
+
+ if ( url.isEmpty() ) {
+ setStatusBarText(u.htmlURL(), BarHoverText);
+ return;
+ }
+
+ if (url.find( TQString::fromLatin1( "javascript:" ),0, false ) == 0 ) {
+ TQString jscode = KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) );
+ jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
+ if (url.startsWith("javascript:window.open"))
+ jscode += i18n(" (In new window)");
+ setStatusBarText( TQStyleSheet::escape( jscode ), BarHoverText );
+ return;
+ }
+
+ KFileItem item(u, TQString(), KFileItem::Unknown);
+ emit d->m_extension->mouseOverInfo(&item);
+
+ TQString com;
+
+ KMimeType::Ptr typ = KMimeType::findByURL( u );
+
+ if ( typ )
+ com = typ->comment( u, false );
+
+ if ( !u.isValid() ) {
+ setStatusBarText(u.htmlURL(), BarHoverText);
+ return;
+ }
+
+ if ( u.isLocalFile() )
+ {
+ // TODO : use TDEIO::stat() and create a KFileItem out of its result,
+ // to use KFileItem::statusBarText()
+ TQCString path = TQFile::encodeName( u.path() );
+
+ struct stat buff;
+ bool ok = !stat( path.data(), &buff );
+
+ struct stat lbuff;
+ if (ok) ok = !lstat( path.data(), &lbuff );
+
+ TQString text = u.htmlURL();
+ TQString text2 = text;
+
+ if (ok && S_ISLNK( lbuff.st_mode ) )
+ {
+ TQString tmp;
+ if ( com.isNull() )
+ tmp = i18n( "Symbolic Link");
+ else
+ tmp = i18n("%1 (Link)").arg(com);
+ char buff_two[1024];
+ text += " -> ";
+ int n = readlink ( path.data(), buff_two, 1022);
+ if (n == -1)
+ {
+ text2 += " ";
+ text2 += tmp;
+ setStatusBarText(text2, BarHoverText);
+ return;
+ }
+ buff_two[n] = 0;
+
+ text += buff_two;
+ text += " ";
+ text += tmp;
+ }
+ else if ( ok && S_ISREG( buff.st_mode ) )
+ {
+ if (buff.st_size < 1024)
+ text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
+ else
+ {
+ float d = (float) buff.st_size/1024.0;
+ text = i18n("%2 (%1 K)").arg(TDEGlobal::locale()->formatNumber(d, 2)).arg(text2); // was %.2f
+ }
+ text += " ";
+ text += com;
+ }
+ else if ( ok && S_ISDIR( buff.st_mode ) )
+ {
+ text += " ";
+ text += com;
+ }
+ else
+ {
+ text += " ";
+ text += com;
+ }
+ setStatusBarText(text, BarHoverText);
+ }
+ else
+ {
+ TQString extra;
+ if (target.lower() == "_blank")
+ {
+ extra = i18n(" (In new window)");
+ }
+ else if (!target.isEmpty() &&
+ (target.lower() != "_top") &&
+ (target.lower() != "_self") &&
+ (target.lower() != "_parent"))
+ {
+ KHTMLPart *p = this;
+ while (p->parentPart())
+ p = p->parentPart();
+ if (!p->frameExists(target))
+ extra = i18n(" (In new window)");
+ else
+ extra = i18n(" (In other frame)");
+ }
+
+ if (u.protocol() == TQString::fromLatin1("mailto")) {
+ TQString mailtoMsg /* = TQString::fromLatin1("<img src=%1>").arg(locate("icon", TQString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
+ mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
+ TQStringList queries = TQStringList::split('&', u.query().mid(1));
+ TQStringList::Iterator it = queries.begin();
+ const TQStringList::Iterator itEnd = queries.end();
+ for (; it != itEnd; ++it)
+ if ((*it).startsWith(TQString::fromLatin1("subject=")))
+ mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
+ else if ((*it).startsWith(TQString::fromLatin1("cc=")))
+ mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
+ else if ((*it).startsWith(TQString::fromLatin1("bcc=")))
+ mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
+ mailtoMsg = TQStyleSheet::escape(mailtoMsg);
+ mailtoMsg.replace(TQRegExp("([\n\r\t]|[ ]{10})"), TQString());
+ setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
+ return;
+ }
+ // Is this check necessary at all? (Frerich)
+#if 0
+ else if (u.protocol() == TQString::fromLatin1("http")) {
+ DOM::Node hrefNode = nodeUnderMouse().parentNode();
+ while (hrefNode.nodeName().string() != TQString::fromLatin1("A") && !hrefNode.isNull())
+ hrefNode = hrefNode.parentNode();
+
+ if (!hrefNode.isNull()) {
+ DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
+ if (!hreflangNode.isNull()) {
+ TQString countryCode = hreflangNode.nodeValue().string().lower();
+ // Map the language code to an appropriate country code.
+ if (countryCode == TQString::fromLatin1("en"))
+ countryCode = TQString::fromLatin1("gb");
+ TQString flagImg = TQString::fromLatin1("<img src=%1>").arg(
+ locate("locale", TQString::fromLatin1("l10n/")
+ + countryCode
+ + TQString::fromLatin1("/flag.png")));
+ emit setStatusBarText(flagImg + u.prettyURL() + extra);
+ }
+ }
+ }
+#endif
+ setStatusBarText(u.htmlURL() + extra, BarHoverText);
+ }
+}
+
+//
+// This executes in the active part on a click or other url selection action in
+// that active part.
+//
+void KHTMLPart::urlSelected( const TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args )
+{
+ // The member var is so that slotRedirection still calls the virtual urlSelected
+ // but is able to know if is opened a url. KDE4: just make urlSelected return a bool
+ // and move the urlSelectedIntern code back here.
+ d->m_urlSelectedOpenedURL = urlSelectedIntern( url, button, state, _target, args );
+}
+
+// Return value: true if an url was opened, false if not (e.g. error, or jumping to anchor)
+bool KHTMLPart::urlSelectedIntern( const TQString &url, int button, int state, const TQString &_target, KParts::URLArgs args )
+{
+ bool hasTarget = false;
+
+ TQString target = _target;
+ if ( target.isEmpty() && d->m_doc )
+ target = d->m_doc->baseTarget();
+ if ( !target.isEmpty() )
+ hasTarget = true;
+
+ if ( url.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
+ {
+ crossFrameExecuteScript( target, KURL::decode_string( url.mid( 11 ) ) );
+ return false;
+ }
+
+ KURL cURL = completeURL(url);
+ // special case for <a href=""> (IE removes filename, mozilla doesn't)
+ if ( url.isEmpty() )
+ cURL.setFileName( url ); // removes filename
+
+ if ( !cURL.isValid() )
+ // ### ERROR HANDLING
+ return false;
+
+ kdDebug(6050) << this << " urlSelected: complete URL:" << cURL.url() << " target=" << target << endl;
+
+ if ( state & ControlButton )
+ {
+ args.setNewTab(true);
+ emit d->m_extension->createNewWindow( cURL, args );
+ return true;
+ }
+
+ if ( button == Qt::LeftButton && ( state & ShiftButton ) )
+ {
+ TDEIO::MetaData metaData;
+ metaData["referrer"] = d->m_referrer;
+ KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
+ return false;
+ }
+
+ if (!checkLinkSecurity(cURL,
+ i18n( "<qt>This untrusted page links to<BR><B>%1</B>.<BR>Do you want to follow the link?" ),
+ i18n( "Follow" )))
+ return false;
+
+ args.frameName = target;
+
+ args.metaData().insert("main_frame_request",
+ parentPart() == 0 ? "TRUE":"FALSE");
+ args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
+ args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
+ args.metaData().insert("PropagateHttpHeader", "true");
+ args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
+ args.metaData().insert("ssl_activate_warnings", "TRUE");
+
+ if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
+ {
+ // unknown frame names should open in a new window.
+ tdehtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, false );
+ if ( frame )
+ {
+ args.metaData()["referrer"] = d->m_referrer;
+ requestObject( frame, cURL, args );
+ return true;
+ }
+ }
+
+ if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
+ args.metaData()["referrer"] = d->m_referrer;
+
+
+ if ( button == Qt::NoButton && (state & ShiftButton) && (state & ControlButton) )
+ {
+ emit d->m_extension->createNewWindow( cURL, args );
+ return true;
+ }
+
+ if ( state & ShiftButton)
+ {
+ KParts::WindowArgs winArgs;
+ winArgs.lowerWindow = true;
+ KParts::ReadOnlyPart *newPart = 0;
+ emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
+ return true;
+ }
+
+ //If we're asked to open up an anchor in the current URL, in current window,
+ //merely gotoanchor, and do not reload the new page. Note that this does
+ //not apply if the URL is the same page, but without a ref
+ if (cURL.hasRef() && (!hasTarget || target == "_self"))
+ {
+ KURL curUrl = this->url();
+ if (urlcmp(cURL.url(), curUrl.url(),
+ false, // ignore trailing / diff, IE does, even if FFox doesn't
+ true)) // don't care if the ref changes!
+ {
+ m_url = cURL;
+ emit d->m_extension->openURLNotify();
+ if ( !gotoAnchor( m_url.encodedHtmlRef()) )
+ gotoAnchor( m_url.htmlRef() );
+ emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
+ return false; // we jumped, but we didn't open a URL
+ }
+ }
+
+ if ( !d->m_bComplete && !hasTarget )
+ closeURL();
+
+ view()->viewport()->unsetCursor();
+ emit d->m_extension->openURLRequest( cURL, args );
+ return true;
+}
+
+void KHTMLPart::slotViewDocumentSource()
+{
+ KURL url(m_url);
+ bool isTempFile = false;
+ if (!(url.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
+ {
+ KTempFile sourceFile(TQString(), defaultExtension());
+ if (sourceFile.status() == 0)
+ {
+ KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
+ url = KURL();
+ url.setPath(sourceFile.name());
+ isTempFile = true;
+ }
+ }
+
+ (void) KRun::runURL( url, TQString::fromLatin1("text/plain"), isTempFile );
+}
+
+void KHTMLPart::slotViewPageInfo()
+{
+ KHTMLInfoDlg *dlg = new KHTMLInfoDlg(NULL, "KHTML Page Info Dialog", false, (WFlags)WDestructiveClose);
+ dlg->_close->setGuiItem(KStdGuiItem::close());
+
+ if (d->m_doc)
+ dlg->_title->setText(d->m_doc->title().string());
+
+ // If it's a frame, set the caption to "Frame Information"
+ if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
+ dlg->setCaption(i18n("Frame Information"));
+ }
+
+ TQString editStr = TQString();
+
+ if (!d->m_pageServices.isEmpty())
+ editStr = i18n(" <a href=\"%1\">[Properties]</a>").arg(d->m_pageServices);
+
+ TQString squeezedURL = KStringHandler::csqueeze( url().prettyURL(), 80 );
+ dlg->_url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
+ if (lastModified().isEmpty())
+ {
+ dlg->_lastModified->hide();
+ dlg->_lmLabel->hide();
+ }
+ else
+ dlg->_lastModified->setText(lastModified());
+
+ const TQString& enc = encoding();
+ if (enc.isEmpty()) {
+ dlg->_eLabel->hide();
+ dlg->_encoding->hide();
+ } else {
+ dlg->_encoding->setText(enc);
+ }
+ /* populate the list view now */
+ const TQStringList headers = TQStringList::split("\n", d->m_httpHeaders);
+
+ TQStringList::ConstIterator it = headers.begin();
+ const TQStringList::ConstIterator itEnd = headers.end();
+
+ for (; it != itEnd; ++it) {
+ const TQStringList header = TQStringList::split(TQRegExp(":[ ]+"), *it);
+ if (header.count() != 2)
+ continue;
+ new TQListViewItem(dlg->_headers, header[0], header[1]);
+ }
+
+ dlg->show();
+ /* put no code here */
+}
+
+
+void KHTMLPart::slotViewFrameSource()
+{
+ KParts::ReadOnlyPart *frame = currentFrame();
+ if ( !frame )
+ return;
+
+ KURL url = frame->url();
+ bool isTempFile = false;
+ if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
+ {
+ long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
+
+ if (KHTMLPageCache::self()->isComplete(cacheId))
+ {
+ KTempFile sourceFile(TQString(), defaultExtension());
+ if (sourceFile.status() == 0)
+ {
+ KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
+ url = KURL();
+ url.setPath(sourceFile.name());
+ isTempFile = true;
+ }
+ }
+ }
+
+ (void) KRun::runURL( url, TQString::fromLatin1("text/plain"), isTempFile );
+}
+
+KURL KHTMLPart::backgroundURL() const
+{
+ // ### what about XML documents? get from CSS?
+ if (!d->m_doc || !d->m_doc->isHTMLDocument())
+ return KURL();
+
+ TQString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
+
+ return KURL( m_url, relURL );
+}
+
+void KHTMLPart::slotSaveBackground()
+{
+ TDEIO::MetaData metaData;
+ metaData["referrer"] = d->m_referrer;
+ KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
+}
+
+void KHTMLPart::slotSaveDocument()
+{
+ KURL srcURL( m_url );
+
+ if ( srcURL.fileName(false).isEmpty() )
+ srcURL.setFileName( "index" + defaultExtension() );
+
+ TDEIO::MetaData metaData;
+ // Referre unknown?
+ KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
+}
+
+void KHTMLPart::slotSecurity()
+{
+// kdDebug( 6050 ) << "Meta Data:" << endl
+// << d->m_ssl_peer_cert_subject
+// << endl
+// << d->m_ssl_peer_cert_issuer
+// << endl
+// << d->m_ssl_cipher
+// << endl
+// << d->m_ssl_cipher_desc
+// << endl
+// << d->m_ssl_cipher_version
+// << endl
+// << d->m_ssl_good_from
+// << endl
+// << d->m_ssl_good_until
+// << endl
+// << d->m_ssl_cert_state
+// << endl;
+
+ KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
+
+ if (d->m_bSecurityInQuestion)
+ kid->setSecurityInQuestion(true);
+
+ if (d->m_ssl_in_use) {
+ KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
+ if (x) {
+ // Set the chain back onto the certificate
+ const TQStringList cl = TQStringList::split(TQString("\n"), d->m_ssl_peer_chain);
+ TQPtrList<KSSLCertificate> ncl;
+
+ ncl.setAutoDelete(true);
+ TQStringList::ConstIterator it = cl.begin();
+ const TQStringList::ConstIterator itEnd = cl.end();
+ for (; it != itEnd; ++it) {
+ KSSLCertificate* const y = KSSLCertificate::fromString((*it).local8Bit());
+ if (y) ncl.append(y);
+ }
+
+ if (ncl.count() > 0)
+ x->chain().setChain(ncl);
+
+ kid->setup(x,
+ d->m_ssl_peer_ip,
+ m_url.url(),
+ d->m_ssl_cipher,
+ d->m_ssl_cipher_desc,
+ d->m_ssl_cipher_version,
+ d->m_ssl_cipher_used_bits.toInt(),
+ d->m_ssl_cipher_bits.toInt(),
+ (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
+ );
+ kid->exec();
+ delete x;
+ } else kid->exec();
+ } else kid->exec();
+}
+
+void KHTMLPart::slotSaveFrame()
+{
+ KParts::ReadOnlyPart *frame = currentFrame();
+ if ( !frame )
+ return;
+
+ KURL srcURL( frame->url() );
+
+ if ( srcURL.fileName(false).isEmpty() )
+ srcURL.setFileName( "index" + defaultExtension() );
+
+ TDEIO::MetaData metaData;
+ // Referrer unknown?
+ KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
+}
+
+void KHTMLPart::slotSetEncoding()
+{
+ d->m_automaticDetection->setItemChecked( int( d->m_autoDetectLanguage ), false );
+ d->m_paSetEncoding->popupMenu()->setItemChecked( 0, false );
+ d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), true );
+
+ TQString enc = TDEGlobal::charsets()->encodingForName( d->m_manualDetection->currentText() );
+ setEncoding( enc, true );
+}
+
+void KHTMLPart::slotUseStylesheet()
+{
+ if (d->m_doc)
+ {
+ bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
+ d->m_sheetUsed = autoselect ? TQString() : d->m_paUseStylesheet->currentText();
+ d->m_doc->updateStyleSelector();
+ }
+}
+
+void KHTMLPart::updateActions()
+{
+ bool frames = false;
+
+ TQValueList<tdehtml::ChildFrame*>::ConstIterator it = d->m_frames.begin();
+ const TQValueList<tdehtml::ChildFrame*>::ConstIterator end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( (*it)->m_type == tdehtml::ChildFrame::Frame )
+ {
+ frames = true;
+ break;
+ }
+
+ d->m_paViewFrame->setEnabled( frames );
+ d->m_paSaveFrame->setEnabled( frames );
+
+ if ( frames )
+ d->m_paFind->setText( i18n( "&Find in Frame..." ) );
+ else
+ d->m_paFind->setText( i18n( "&Find..." ) );
+
+ KParts::Part *frame = 0;
+
+ if ( frames )
+ frame = currentFrame();
+
+ bool enableFindAndSelectAll = true;
+
+ if ( frame )
+ enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
+
+ d->m_paFind->setEnabled( enableFindAndSelectAll );
+ d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
+
+ bool enablePrintFrame = false;
+
+ if ( frame )
+ {
+ TQObject *ext = KParts::BrowserExtension::childObject( frame );
+ if ( ext )
+ enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
+ }
+
+ d->m_paPrintFrame->setEnabled( enablePrintFrame );
+
+ TQString bgURL;
+
+ // ### frames
+ if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
+ bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
+
+ d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
+
+ if ( d->m_paDebugScript )
+ d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
+}
+
+KParts::LiveConnectExtension *KHTMLPart::liveConnectExtension( const tdehtml::RenderPart *frame) const {
+ const ConstFrameIt end = d->m_objects.end();
+ for(ConstFrameIt it = d->m_objects.begin(); it != end; ++it )
+ if ((*it)->m_frame == frame)
+ return (*it)->m_liveconnect;
+ return 0L;
+}
+
+bool KHTMLPart::requestFrame( tdehtml::RenderPart *frame, const TQString &url, const TQString &frameName,
+ const TQStringList &params, bool isIFrame )
+{
+ //kdDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )" << endl;
+ FrameIt it = d->m_frames.find( frameName );
+ if ( it == d->m_frames.end() )
+ {
+ tdehtml::ChildFrame * child = new tdehtml::ChildFrame;
+ //kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
+ child->m_name = frameName;
+ it = d->m_frames.append( child );
+ }
+
+ (*it)->m_type = isIFrame ? tdehtml::ChildFrame::IFrame : tdehtml::ChildFrame::Frame;
+ (*it)->m_frame = frame;
+ (*it)->m_params = params;
+
+ // Support for <frame src="javascript:string">
+ if ( url.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 )
+ {
+ if ( processObjectRequest(*it, KURL("about:blank"), TQString("text/html") ) ) {
+ KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>((*it)->m_part));
+
+ // See if we want to replace content with javascript: output..
+ TQVariant res = p->executeScript( DOM::Node(), KURL::decode_string( url.right( url.length() - 11) ) );
+ if ( res.type() == TQVariant::String ) {
+ p->begin();
+ p->write( res.asString() );
+ p->end();
+ }
+ return true;
+ }
+ return false;
+ }
+ KURL u = url.isEmpty() ? KURL() : completeURL( url );
+ return requestObject( *it, u );
+}
+
+TQString KHTMLPart::requestFrameName()
+{
+ return TQString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
+}
+
+bool KHTMLPart::requestObject( tdehtml::RenderPart *frame, const TQString &url, const TQString &serviceType,
+ const TQStringList &params )
+{
+ //kdDebug( 6005 ) << "KHTMLPart::requestObject " << this << " frame=" << frame << endl;
+ tdehtml::ChildFrame *child = new tdehtml::ChildFrame;
+ FrameIt it = d->m_objects.append( child );
+ (*it)->m_frame = frame;
+ (*it)->m_type = tdehtml::ChildFrame::Object;
+ (*it)->m_params = params;
+
+ KParts::URLArgs args;
+ args.serviceType = serviceType;
+ if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
+ (*it)->m_bCompleted = true;
+ return false;
+ }
+ return true;
+}
+
+bool KHTMLPart::requestObject( tdehtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
+{
+ if (!checkLinkSecurity(url))
+ {
+ kdDebug(6005) << this << " KHTMLPart::requestObject checkLinkSecurity refused" << endl;
+ return false;
+ }
+ if ( child->m_bPreloaded )
+ {
+ kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
+ if ( child->m_frame && child->m_part )
+ child->m_frame->setWidget( child->m_part->widget() );
+
+ child->m_bPreloaded = false;
+ return true;
+ }
+
+ //kdDebug(6005) << "KHTMLPart::requestObject child=" << child << " child->m_part=" << child->m_part << endl;
+
+ KParts::URLArgs args( _args );
+
+ if ( child->m_run )
+ child->m_run->abort();
+
+ if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
+ args.serviceType = child->m_serviceType;
+
+ child->m_args = args;
+ child->m_args.reload = (d->m_cachePolicy == TDEIO::CC_Reload);
+ child->m_serviceName = TQString();
+ if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
+ child->m_args.metaData()["referrer"] = d->m_referrer;
+
+ child->m_args.metaData().insert("PropagateHttpHeader", "true");
+ child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
+ child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
+ child->m_args.metaData().insert("main_frame_request",
+ parentPart() == 0 ? "TRUE":"FALSE");
+ child->m_args.metaData().insert("ssl_was_in_use",
+ d->m_ssl_in_use ? "TRUE":"FALSE");
+ child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
+ child->m_args.metaData().insert("cross-domain", toplevelURL().url());
+
+ // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
+ if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
+ args.serviceType = TQString::fromLatin1( "text/html" );
+
+ if ( args.serviceType.isEmpty() ) {
+ kdDebug(6050) << "Running new KHTMLRun for " << this << " and child=" << child << endl;
+ child->m_run = new KHTMLRun( this, child, url, child->m_args, true );
+ d->m_bComplete = false; // ensures we stop it in checkCompleted...
+ return false;
+ } else {
+ return processObjectRequest( child, url, args.serviceType );
+ }
+}
+
+bool KHTMLPart::processObjectRequest( tdehtml::ChildFrame *child, const KURL &_url, const TQString &mimetype )
+{
+ //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
+
+ // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
+ // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
+ // though -> the reference becomes invalid -> crash is likely
+ KURL url( _url );
+
+ // tdehtmlrun called us this way to indicate a loading error
+ if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
+ {
+ child->m_bCompleted = true;
+ checkCompleted();
+ return true;
+ }
+
+ if (child->m_bNotify)
+ {
+ child->m_bNotify = false;
+ if ( !child->m_args.lockHistory() )
+ emit d->m_extension->openURLNotify();
+ }
+
+ if ( child->m_serviceType != mimetype || !child->m_part )
+ {
+ // Before attempting to load a part, check if the user wants that.
+ // Many don't like getting ZIP files embedded.
+ // However we don't want to ask for flash and other plugin things..
+ if ( child->m_type != tdehtml::ChildFrame::Object )
+ {
+ TQString suggestedFilename;
+ if ( child->m_run )
+ suggestedFilename = child->m_run->suggestedFilename();
+
+ KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave(
+ url, mimetype, suggestedFilename );
+ switch( res ) {
+ case KParts::BrowserRun::Save:
+ KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), TQString(), 0, suggestedFilename);
+ // fall-through
+ case KParts::BrowserRun::Cancel:
+ child->m_bCompleted = true;
+ checkCompleted();
+ return true; // done
+ default: // Open
+ break;
+ }
+ }
+
+ TQStringList dummy; // the list of servicetypes handled by the part is now unused.
+ KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, dummy, child->m_params );
+
+ if ( !part )
+ {
+ if ( child->m_frame )
+ if (child->m_frame->partLoadingErrorNotify( child, url, mimetype ))
+ return true; // we succeeded after all (a fallback was used)
+
+ checkEmitLoadEvent();
+ return false;
+ }
+
+ //CRITICAL STUFF
+ if ( child->m_part )
+ {
+ if (!::tqqt_cast<KHTMLPart*>(child->m_part) && child->m_jscript)
+ child->m_jscript->clear();
+ partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
+ delete (KParts::ReadOnlyPart *)child->m_part;
+ if (child->m_liveconnect) {
+ disconnect(child->m_liveconnect, TQT_SIGNAL(partEvent(const unsigned long, const TQString &, const KParts::LiveConnectExtension::ArgList &)), child, TQT_SLOT(liveConnectEvent(const unsigned long, const TQString&, const KParts::LiveConnectExtension::ArgList &)));
+ child->m_liveconnect = 0L;
+ }
+ }
+
+ child->m_serviceType = mimetype;
+ if ( child->m_frame && part->widget() )
+ child->m_frame->setWidget( part->widget() );
+
+ if ( child->m_type != tdehtml::ChildFrame::Object )
+ partManager()->addPart( part, false );
+// else
+// kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
+
+ child->m_part = part;
+
+ if (::tqqt_cast<KHTMLPart*>(part)) {
+ static_cast<KHTMLPart*>(part)->d->m_frame = child;
+ } else if (child->m_frame) {
+ child->m_liveconnect = KParts::LiveConnectExtension::childObject(part);
+ if (child->m_liveconnect)
+ connect(child->m_liveconnect, TQT_SIGNAL(partEvent(const unsigned long, const TQString &, const KParts::LiveConnectExtension::ArgList &)), child, TQT_SLOT(liveConnectEvent(const unsigned long, const TQString&, const KParts::LiveConnectExtension::ArgList &)));
+ }
+ KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
+ if (sb)
+ sb->setStatusBar( d->m_statusBarExtension->statusBar() );
+
+ connect( part, TQT_SIGNAL( started( TDEIO::Job *) ),
+ this, TQT_SLOT( slotChildStarted( TDEIO::Job *) ) );
+ connect( part, TQT_SIGNAL( completed() ),
+ this, TQT_SLOT( slotChildCompleted() ) );
+ connect( part, TQT_SIGNAL( completed(bool) ),
+ this, TQT_SLOT( slotChildCompleted(bool) ) );
+ connect( part, TQT_SIGNAL( setStatusBarText( const TQString & ) ),
+ this, TQT_SIGNAL( setStatusBarText( const TQString & ) ) );
+ if ( part->inherits( "KHTMLPart" ) )
+ {
+ connect( this, TQT_SIGNAL( completed() ),
+ part, TQT_SLOT( slotParentCompleted() ) );
+ connect( this, TQT_SIGNAL( completed(bool) ),
+ part, TQT_SLOT( slotParentCompleted() ) );
+ // As soon as the child's document is created, we need to set its domain
+ // (but we do so only once, so it can't be simply done in the child)
+ connect( part, TQT_SIGNAL( docCreated() ),
+ this, TQT_SLOT( slotChildDocCreated() ) );
+ }
+
+ child->m_extension = KParts::BrowserExtension::childObject( part );
+
+ if ( child->m_extension )
+ {
+ connect( child->m_extension, TQT_SIGNAL( openURLNotify() ),
+ d->m_extension, TQT_SIGNAL( openURLNotify() ) );
+
+ connect( child->m_extension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
+ this, TQT_SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
+
+ connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
+ d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
+ connect( child->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
+ d->m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
+
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) );
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) );
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
+ connect( child->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
+ d->m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
+
+ connect( child->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ),
+ d->m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) );
+
+ connect( child->m_extension, TQT_SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
+ this, TQT_SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
+
+ child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
+ }
+ }
+ else if ( child->m_frame && child->m_part &&
+ child->m_frame->widget() != child->m_part->widget() )
+ child->m_frame->setWidget( child->m_part->widget() );
+
+ checkEmitLoadEvent();
+ // Some JS code in the load event may have destroyed the part
+ // In that case, abort
+ if ( !child->m_part )
+ return false;
+
+ if ( child->m_bPreloaded )
+ {
+ if ( child->m_frame && child->m_part )
+ child->m_frame->setWidget( child->m_part->widget() );
+
+ child->m_bPreloaded = false;
+ return true;
+ }
+
+ child->m_args.reload = (d->m_cachePolicy == TDEIO::CC_Reload);
+
+ // make sure the part has a way to find out about the mimetype.
+ // we actually set it in child->m_args in requestObject already,
+ // but it's useless if we had to use a KHTMLRun instance, as the
+ // point the run object is to find out exactly the mimetype.
+ child->m_args.serviceType = mimetype;
+
+ // if not a frame set child as completed
+ child->m_bCompleted = child->m_type == tdehtml::ChildFrame::Object;
+
+ if ( child->m_extension )
+ child->m_extension->setURLArgs( child->m_args );
+
+ if(url.protocol() == "javascript" || url.url() == "about:blank") {
+ if (!child->m_part->inherits("KHTMLPart"))
+ return false;
+
+ KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
+
+ p->begin();
+ if (d->m_doc && p->d->m_doc)
+ p->d->m_doc->setBaseURL(d->m_doc->baseURL());
+ if (!url.url().startsWith("about:")) {
+ p->write(url.path());
+ } else {
+ p->m_url = url;
+ // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
+ p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
+ }
+ p->end();
+ return true;
+ }
+ else if ( !url.isEmpty() )
+ {
+ //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
+ bool b = child->m_part->openURL( url );
+ if (child->m_bCompleted)
+ checkCompleted();
+ return b;
+ }
+ else
+ {
+ child->m_bCompleted = true;
+ checkCompleted();
+ return true;
+ }
+}
+
+KParts::ReadOnlyPart *KHTMLPart::createPart( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name, const TQString &mimetype,
+ TQString &serviceName, TQStringList &serviceTypes,
+ const TQStringList &params )
+{
+ TQString constr;
+ if ( !serviceName.isEmpty() )
+ constr.append( TQString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
+
+ KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, TQString() );
+
+ if ( offers.isEmpty() ) {
+ int pos = mimetype.find( "-plugin" );
+ if (pos < 0)
+ return 0L;
+ TQString stripped_mime = mimetype.left( pos );
+ offers = KTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr, TQString() );
+ if ( offers.isEmpty() )
+ return 0L;
+ }
+
+ KTrader::OfferList::ConstIterator it = offers.begin();
+ const KTrader::OfferList::ConstIterator itEnd = offers.end();
+ for ( ; it != itEnd; ++it )
+ {
+ KService::Ptr service = (*it);
+
+ KLibFactory* const factory = KLibLoader::self()->factory( TQFile::encodeName(service->library()) );
+ if ( factory ) {
+ KParts::ReadOnlyPart *res = 0L;
+
+ const char *className = "KParts::ReadOnlyPart";
+ if ( service->serviceTypes().contains( "Browser/View" ) )
+ className = "Browser/View";
+
+ if ( factory->inherits( "KParts::Factory" ) )
+ res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
+ else
+ res = static_cast<KParts::ReadOnlyPart *>(factory->create( TQT_TQOBJECT(parentWidget), widgetName, className ));
+
+ if ( res ) {
+ serviceTypes = service->serviceTypes();
+ serviceName = service->name();
+ return res;
+ }
+ } else {
+ // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
+ kdWarning() << TQString(TQString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
+ .arg(service->name()).arg(KLibLoader::self()->lastErrorMessage())) << endl;
+ }
+ }
+ return 0;
+}
+
+KParts::PartManager *KHTMLPart::partManager()
+{
+ if ( !d->m_manager && d->m_view )
+ {
+ d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "tdehtml part manager" );
+ d->m_manager->setAllowNestedParts( true );
+ connect( d->m_manager, TQT_SIGNAL( activePartChanged( KParts::Part * ) ),
+ this, TQT_SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
+ connect( d->m_manager, TQT_SIGNAL( partRemoved( KParts::Part * ) ),
+ this, TQT_SLOT( slotPartRemoved( KParts::Part * ) ) );
+ }
+
+ return d->m_manager;
+}
+
+void KHTMLPart::submitFormAgain()
+{
+ disconnect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(submitFormAgain()));
+ if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
+ KHTMLPart::submitForm( d->m_submitForm->submitAction, d->m_submitForm->submitUrl, d->m_submitForm->submitFormData, d->m_submitForm->target, d->m_submitForm->submitContentType, d->m_submitForm->submitBoundary );
+
+ delete d->m_submitForm;
+ d->m_submitForm = 0;
+}
+
+void KHTMLPart::submitFormProxy( const char *action, const TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& boundary )
+{
+ submitForm(action, url, formData, _target, contentType, boundary);
+}
+
+void KHTMLPart::submitForm( const char *action, const TQString &url, const TQByteArray &formData, const TQString &_target, const TQString& contentType, const TQString& boundary )
+{
+ kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
+ if (d->m_formNotification == KHTMLPart::Only) {
+ emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
+ return;
+ } else if (d->m_formNotification == KHTMLPart::Before) {
+ emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
+ }
+
+ KURL u = completeURL( url );
+
+ if ( !u.isValid() )
+ {
+ // ### ERROR HANDLING!
+ return;
+ }
+
+ // Form security checks
+ //
+ /*
+ * If these form security checks are still in this place in a month or two
+ * I'm going to simply delete them.
+ */
+
+ /* This is separate for a reason. It has to be _before_ all script, etc,
+ * AND I don't want to break anything that uses checkLinkSecurity() in
+ * other places.
+ */
+
+ if (!d->m_submitForm) {
+ if (u.protocol() != "https" && u.protocol() != "mailto") {
+ if (d->m_ssl_in_use) { // Going from SSL -> nonSSL
+ int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
+ "\nA third party may be able to intercept and view this information."
+ "\nAre you sure you wish to continue?"),
+ i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
+ if (rc == KMessageBox::Cancel)
+ return;
+ } else { // Going from nonSSL -> nonSSL
+ KSSLSettings kss(true);
+ if (kss.warnOnUnencrypted()) {
+ int rc = KMessageBox::warningContinueCancel(NULL,
+ i18n("Warning: Your data is about to be transmitted across the network unencrypted."
+ "\nAre you sure you wish to continue?"),
+ i18n("Network Transmission"),
+ KGuiItem(i18n("&Send Unencrypted")),
+ "WarnOnUnencryptedForm");
+ // Move this setting into KSSL instead
+ TDEConfig *config = kapp->config();
+ TQString grpNotifMsgs = TQString::fromLatin1("Notification Messages");
+ TDEConfigGroupSaver saver( config, grpNotifMsgs );
+
+ if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
+ config->deleteEntry("WarnOnUnencryptedForm");
+ config->sync();
+ kss.setWarnOnUnencrypted(false);
+ kss.save();
+ }
+ if (rc == KMessageBox::Cancel)
+ return;
+ }
+ }
+ }
+
+ if (u.protocol() == "mailto") {
+ int rc = KMessageBox::warningContinueCancel(NULL,
+ i18n("This site is attempting to submit form data via email.\n"
+ "Do you want to continue?"),
+ i18n("Network Transmission"),
+ KGuiItem(i18n("&Send Email")),
+ "WarnTriedEmailSubmit");
+
+ if (rc == KMessageBox::Cancel) {
+ return;
+ }
+ }
+ }
+
+ // End form security checks
+ //
+
+ TQString urlstring = u.url();
+
+ if ( urlstring.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
+ urlstring = KURL::decode_string(urlstring);
+ crossFrameExecuteScript( _target, urlstring.right( urlstring.length() - 11) );
+ return;
+ }
+
+ if (!checkLinkSecurity(u,
+ i18n( "<qt>The form will be submitted to <BR><B>%1</B><BR>on your local filesystem.<BR>Do you want to submit the form?" ),
+ i18n( "Submit" )))
+ return;
+
+ KParts::URLArgs args;
+
+ if (!d->m_referrer.isEmpty())
+ args.metaData()["referrer"] = d->m_referrer;
+
+ args.metaData().insert("PropagateHttpHeader", "true");
+ args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
+ args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
+ args.metaData().insert("main_frame_request",
+ parentPart() == 0 ? "TRUE":"FALSE");
+ args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
+ args.metaData().insert("ssl_activate_warnings", "TRUE");
+//WABA: When we post a form we should treat it as the main url
+//the request should never be considered cross-domain
+//args.metaData().insert("cross-domain", toplevelURL().url());
+ args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
+
+ // Handle mailto: forms
+ if (u.protocol() == "mailto") {
+ // 1) Check for attach= and strip it
+ TQString q = u.query().mid(1);
+ TQStringList nvps = TQStringList::split("&", q);
+ bool triedToAttach = false;
+
+ TQStringList::Iterator nvp = nvps.begin();
+ const TQStringList::Iterator nvpEnd = nvps.end();
+
+// cannot be a for loop as if something is removed we don't want to do ++nvp, as
+// remove returns an iterator pointing to the next item
+
+ while (nvp != nvpEnd) {
+ const TQStringList pair = TQStringList::split("=", *nvp);
+ if (pair.count() >= 2) {
+ if (pair.first().lower() == "attach") {
+ nvp = nvps.remove(nvp);
+ triedToAttach = true;
+ } else {
+ ++nvp;
+ }
+ } else {
+ ++nvp;
+ }
+ }
+
+ if (triedToAttach)
+ KMessageBox::information(NULL, i18n("This site attempted to attach a file from your computer in the form submission. The attachment was removed for your protection."), i18n("TDE"), "WarnTriedAttach");
+
+ // 2) Append body=
+ TQString bodyEnc;
+ if (contentType.lower() == "multipart/form-data") {
+ // FIXME: is this correct? I suspect not
+ bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
+ formData.size()));
+ } else if (contentType.lower() == "text/plain") {
+ // Convention seems to be to decode, and s/&/\n/
+ TQString tmpbody = TQString::fromLatin1(formData.data(),
+ formData.size());
+ tmpbody.replace(TQRegExp("[&]"), "\n");
+ tmpbody.replace(TQRegExp("[+]"), " ");
+ tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it
+ bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL
+ } else {
+ bodyEnc = KURL::encode_string(TQString::fromLatin1(formData.data(),
+ formData.size()));
+ }
+
+ nvps.append(TQString("body=%1").arg(bodyEnc));
+ q = nvps.join("&");
+ u.setQuery(q);
+ }
+
+ if ( strcmp( action, "get" ) == 0 ) {
+ if (u.protocol() != "mailto")
+ u.setQuery( TQString::fromLatin1( formData.data(), formData.size() ) );
+ args.setDoPost( false );
+ }
+ else {
+ args.postData = formData;
+ args.setDoPost( true );
+
+ // construct some user headers if necessary
+ if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
+ args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
+ else // contentType must be "multipart/form-data"
+ args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
+ }
+
+ if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
+ if( d->m_submitForm ) {
+ kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
+ return;
+ }
+ d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
+ d->m_submitForm->submitAction = action;
+ d->m_submitForm->submitUrl = url;
+ d->m_submitForm->submitFormData = formData;
+ d->m_submitForm->target = _target;
+ d->m_submitForm->submitContentType = contentType;
+ d->m_submitForm->submitBoundary = boundary;
+ connect(this, TQT_SIGNAL(completed()), this, TQT_SLOT(submitFormAgain()));
+ }
+ else
+ {
+ emit d->m_extension->openURLRequest( u, args );
+ }
+}
+
+void KHTMLPart::popupMenu( const TQString &linkUrl )
+{
+ KURL popupURL;
+ KURL linkKURL;
+ KParts::URLArgs args;
+ TQString referrer;
+ KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
+
+ if ( linkUrl.isEmpty() ) { // click on background
+ KHTMLPart* tdehtmlPart = this;
+ while ( tdehtmlPart->parentPart() )
+ {
+ tdehtmlPart=tdehtmlPart->parentPart();
+ }
+ popupURL = tdehtmlPart->url();
+ referrer = tdehtmlPart->pageReferrer();
+ if (hasSelection())
+ itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
+ else
+ itemflags |= KParts::BrowserExtension::ShowNavigationItems;
+ } else { // click on link
+ popupURL = completeURL( linkUrl );
+ linkKURL = popupURL;
+ referrer = this->referrer();
+
+ if (!(d->m_strSelectedURLTarget).isEmpty() &&
+ (d->m_strSelectedURLTarget.lower() != "_top") &&
+ (d->m_strSelectedURLTarget.lower() != "_self") &&
+ (d->m_strSelectedURLTarget.lower() != "_parent")) {
+ if (d->m_strSelectedURLTarget.lower() == "_blank")
+ args.setForcesNewWindow(true);
+ else {
+ KHTMLPart *p = this;
+ while (p->parentPart())
+ p = p->parentPart();
+ if (!p->frameExists(d->m_strSelectedURLTarget))
+ args.setForcesNewWindow(true);
+ }
+ }
+ }
+
+ // Danger, Will Robinson. The Popup might stay around for a much
+ // longer time than KHTMLPart. Deal with it.
+ KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
+ TQGuardedPtr<TQObject> guard( client );
+
+ TQString mimetype = TQString::fromLatin1( "text/html" );
+ args.metaData()["referrer"] = referrer;
+
+ if (!linkUrl.isEmpty()) // over a link
+ {
+ if (popupURL.isLocalFile()) // safe to do this
+ {
+ mimetype = KMimeType::findByURL(popupURL,0,true,false)->name();
+ }
+ else // look at "extension" of link
+ {
+ const TQString fname(popupURL.fileName(false));
+ if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
+ {
+ KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
+
+ // Further check for mime types guessed from the extension which,
+ // on a web page, are more likely to be a script delivering content
+ // of undecidable type. If the mime type from the extension is one
+ // of these, don't use it. Retain the original type 'text/html'.
+ if (pmt->name() != KMimeType::defaultMimeType() &&
+ !pmt->is("application/x-perl") &&
+ !pmt->is("application/x-perl-module") &&
+ !pmt->is("application/x-php") &&
+ !pmt->is("application/x-python-bytecode") &&
+ !pmt->is("application/x-python") &&
+ !pmt->is("application/x-shellscript"))
+ mimetype = pmt->name();
+ }
+ }
+ }
+
+ args.serviceType = mimetype;
+
+ emit d->m_extension->popupMenu( client, TQCursor::pos(), popupURL, args, itemflags, S_IFREG /*always a file*/);
+
+ if ( !guard.isNull() ) {
+ delete client;
+ emit popupMenu(linkUrl, TQCursor::pos());
+ d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
+ }
+}
+
+void KHTMLPart::slotParentCompleted()
+{
+ //kdDebug(6050) << this << " slotParentCompleted()" << endl;
+ if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
+ {
+ //kdDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL << endl;
+ d->m_redirectionTimer.start( 1000 * d->m_delayRedirect, true );
+ }
+}
+
+void KHTMLPart::slotChildStarted( TDEIO::Job *job )
+{
+ tdehtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender()) );
+
+ assert( child );
+
+ child->m_bCompleted = false;
+
+ if ( d->m_bComplete )
+ {
+#if 0
+ // WABA: Looks like this belongs somewhere else
+ if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
+ {
+ emit d->m_extension->openURLNotify();
+ }
+#endif
+ d->m_bComplete = false;
+ emit started( job );
+ }
+}
+
+void KHTMLPart::slotChildCompleted()
+{
+ slotChildCompleted( false );
+}
+
+void KHTMLPart::slotChildCompleted( bool pendingAction )
+{
+ tdehtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender()) );
+
+ if ( child ) {
+ kdDebug(6050) << this << " slotChildCompleted child=" << child << " m_frame=" << child->m_frame << endl;
+ child->m_bCompleted = true;
+ child->m_bPendingRedirection = pendingAction;
+ child->m_args = KParts::URLArgs();
+ }
+ checkCompleted();
+}
+
+void KHTMLPart::slotChildDocCreated()
+{
+ const KHTMLPart* htmlFrame = static_cast<const KHTMLPart *>(sender());
+ // Set domain to the frameset's domain
+ // This must only be done when loading the frameset initially (#22039),
+ // not when following a link in a frame (#44162).
+ if ( d->m_doc && d->m_doc->isHTMLDocument() )
+ {
+ if ( sender()->inherits("KHTMLPart") )
+ {
+ DOMString domain = static_cast<HTMLDocumentImpl*>(d->m_doc)->domain();
+ if (htmlFrame->d->m_doc && htmlFrame->d->m_doc->isHTMLDocument() )
+ //kdDebug(6050) << "KHTMLPart::slotChildDocCreated: url: " << htmlFrame->m_url.url() << endl;
+ static_cast<HTMLDocumentImpl*>(htmlFrame->d->m_doc)->setDomain( domain );
+ }
+ }
+ // So it only happens once
+ disconnect( htmlFrame, TQT_SIGNAL( docCreated() ), this, TQT_SLOT( slotChildDocCreated() ) );
+}
+
+void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
+{
+ tdehtml::ChildFrame *child = frame( TQT_TQOBJECT_CONST(sender())->parent() );
+ KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
+
+ // TODO: handle child target correctly! currently the script are always executed fur the parent
+ TQString urlStr = url.url();
+ if ( urlStr.find( TQString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
+ TQString script = KURL::decode_string( urlStr.right( urlStr.length() - 11 ) );
+ executeScript( DOM::Node(), script );
+ return;
+ }
+
+ TQString frameName = args.frameName.lower();
+ if ( !frameName.isEmpty() ) {
+ if ( frameName == TQString::fromLatin1( "_top" ) )
+ {
+ emit d->m_extension->openURLRequest( url, args );
+ return;
+ }
+ else if ( frameName == TQString::fromLatin1( "_blank" ) )
+ {
+ emit d->m_extension->createNewWindow( url, args );
+ return;
+ }
+ else if ( frameName == TQString::fromLatin1( "_parent" ) )
+ {
+ KParts::URLArgs newArgs( args );
+ newArgs.frameName = TQString();
+
+ emit d->m_extension->openURLRequest( url, newArgs );
+ return;
+ }
+ else if ( frameName != TQString::fromLatin1( "_self" ) )
+ {
+ tdehtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args );
+
+ if ( !_frame )
+ {
+ emit d->m_extension->openURLRequest( url, args );
+ return;
+ }
+
+ child = _frame;
+ }
+ }
+
+ if ( child && child->m_type != tdehtml::ChildFrame::Object ) {
+ // Inform someone that we are about to show something else.
+ child->m_bNotify = true;
+ requestObject( child, url, args );
+ } else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
+ {
+ KParts::URLArgs newArgs( args );
+ newArgs.frameName = TQString();
+ emit d->m_extension->openURLRequest( url, newArgs );
+ }
+}
+
+void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
+{
+ emit d->m_extension->requestFocus(this);
+}
+
+tdehtml::ChildFrame *KHTMLPart::frame( const TQObject *obj )
+{
+ assert( obj->inherits( "KParts::ReadOnlyPart" ) );
+ const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
+
+ FrameIt it = d->m_frames.begin();
+ const FrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( (KParts::ReadOnlyPart *)(*it)->m_part == part )
+ return *it;
+
+ FrameIt oi = d->m_objects.begin();
+ const FrameIt oiEnd = d->m_objects.end();
+ for (; oi != oiEnd; ++oi )
+ if ( (KParts::ReadOnlyPart *)(*oi)->m_part == part )
+ return *oi;
+
+ return 0L;
+}
+
+//#define DEBUG_FINDFRAME
+
+bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
+{
+ if (callingHtmlPart == this)
+ return true; // trivial
+
+ if (htmlDocument().isNull()) {
+#ifdef DEBUG_FINDFRAME
+ kdDebug(6050) << "KHTMLPart::checkFrameAccess: Empty part " << this << " URL = " << m_url << endl;
+#endif
+ return false; // we are empty?
+ }
+
+ // now compare the domains
+ if (callingHtmlPart && !callingHtmlPart->htmlDocument().isNull() &&
+ !htmlDocument().isNull()) {
+ DOM::DOMString actDomain = callingHtmlPart->htmlDocument().domain();
+ DOM::DOMString destDomain = htmlDocument().domain();
+
+#ifdef DEBUG_FINDFRAME
+ kdDebug(6050) << "KHTMLPart::checkFrameAccess: actDomain = '" << actDomain.string() << "' destDomain = '" << destDomain.string() << "'" << endl;
+#endif
+
+ if (actDomain == destDomain)
+ return true;
+ }
+#ifdef DEBUG_FINDFRAME
+ else
+ {
+ kdDebug(6050) << "KHTMLPart::checkFrameAccess: Unknown part/domain " << callingHtmlPart << " tries to access part " << this << endl;
+ }
+#endif
+ return false;
+}
+
+KHTMLPart *
+KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const TQString &f, tdehtml::ChildFrame **childFrame )
+{
+#ifdef DEBUG_FINDFRAME
+ kdDebug(6050) << "KHTMLPart::findFrameParent: this = " << this << " URL = " << m_url << " name = " << name() << " findFrameParent( " << f << " )" << endl;
+#endif
+ // Check access
+ KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
+
+ if (!checkFrameAccess(callingHtmlPart))
+ return 0;
+
+ // match encoding used in KonqView::setViewName()
+ if (!childFrame && !parentPart() && (TQString::fromLocal8Bit(name()) == f))
+ return this;
+
+ FrameIt it = d->m_frames.find( f );
+ const FrameIt end = d->m_frames.end();
+ if ( it != end )
+ {
+#ifdef DEBUG_FINDFRAME
+ kdDebug(6050) << "KHTMLPart::findFrameParent: FOUND!" << endl;
+#endif
+ if (childFrame)
+ *childFrame = *it;
+ return this;
+ }
+
+ it = d->m_frames.begin();
+ for (; it != end; ++it )
+ {
+ KParts::ReadOnlyPart* const p = (*it)->m_part;
+ if ( p && p->inherits( "KHTMLPart" ))
+ {
+ KHTMLPart* const frameParent = static_cast<KHTMLPart*>(p)->findFrameParent(callingPart, f, childFrame);
+ if (frameParent)
+ return frameParent;
+ }
+ }
+ return 0;
+}
+
+
+KHTMLPart *KHTMLPart::findFrame( const TQString &f )
+{
+ tdehtml::ChildFrame *childFrame;
+ KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
+ if (parentFrame)
+ {
+ KParts::ReadOnlyPart *p = childFrame->m_part;
+ if ( p && p->inherits( "KHTMLPart" ))
+ return static_cast<KHTMLPart *>(p);
+ }
+ return 0;
+}
+
+KParts::ReadOnlyPart *KHTMLPart::findFramePart(const TQString &f)
+{
+ tdehtml::ChildFrame *childFrame;
+ return findFrameParent(this, f, &childFrame) ? static_cast<KParts::ReadOnlyPart *>(childFrame->m_part) : 0L;
+}
+
+KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
+{
+ KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
+ // Find active part in our frame manager, in case we are a frameset
+ // and keep doing that (in case of nested framesets).
+ // Just realized we could also do this recursively, calling part->currentFrame()...
+ while ( part && part->inherits("KHTMLPart") &&
+ static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
+ KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
+ part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
+ if ( !part ) return frameset;
+ }
+ return part;
+}
+
+bool KHTMLPart::frameExists( const TQString &frameName )
+{
+ ConstFrameIt it = d->m_frames.find( frameName );
+ if ( it == d->m_frames.end() )
+ return false;
+
+ // WABA: We only return true if the child actually has a frame
+ // set. Otherwise we might find our preloaded-selve.
+ // This happens when we restore the frameset.
+ return (!(*it)->m_frame.isNull());
+}
+
+KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
+{
+ KHTMLPart* const kp = ::tqqt_cast<KHTMLPart*>(framePart);
+ if (kp)
+ return kp->jScript();
+
+ FrameIt it = d->m_frames.begin();
+ const FrameIt itEnd = d->m_frames.end();
+
+ for (; it != itEnd; ++it)
+ if (framePart == (*it)->m_part) {
+ if (!(*it)->m_jscript)
+ createJScript(*it);
+ return (*it)->m_jscript;
+ }
+ return 0L;
+}
+
+KHTMLPart *KHTMLPart::parentPart()
+{
+ return ::tqqt_cast<KHTMLPart *>( parent() );
+}
+
+tdehtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url,
+ const KParts::URLArgs &args, bool callParent )
+{
+#ifdef DEBUG_FINDFRAME
+ kdDebug( 6050 ) << "KHTMLPart::recursiveFrameRequest this = " << this << ", frame = " << args.frameName << ", url = " << url << endl;
+#endif
+ tdehtml::ChildFrame *childFrame;
+ KHTMLPart *childPart = findFrameParent(callingHtmlPart, args.frameName, &childFrame);
+ if (childPart)
+ {
+ if (childPart == this)
+ return childFrame;
+
+ childPart->requestObject( childFrame, url, args );
+ return 0;
+ }
+
+ if ( parentPart() && callParent )
+ {
+ tdehtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, callParent );
+
+ if ( res )
+ parentPart()->requestObject( res, url, args );
+ }
+
+ return 0L;
+}
+
+#ifndef NDEBUG
+static int s_saveStateIndentLevel = 0;
+#endif
+
+void KHTMLPart::saveState( TQDataStream &stream )
+{
+#ifndef NDEBUG
+ TQString indent = TQString().leftJustify( s_saveStateIndentLevel * 4, ' ' );
+ const int indentLevel = s_saveStateIndentLevel++;
+ kdDebug( 6050 ) << indent << "saveState this=" << this << " '" << name() << "' saving URL " << m_url.url() << endl;
+#endif
+
+ stream << m_url << (TQ_INT32)d->m_view->contentsX() << (TQ_INT32)d->m_view->contentsY()
+ << (TQ_INT32) d->m_view->contentsWidth() << (TQ_INT32) d->m_view->contentsHeight() << (TQ_INT32) d->m_view->marginWidth() << (TQ_INT32) d->m_view->marginHeight();
+
+ // save link cursor position
+ int focusNodeNumber;
+ if (!d->m_focusNodeRestored)
+ focusNodeNumber = d->m_focusNodeNumber;
+ else if (d->m_doc && d->m_doc->focusNode())
+ focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
+ else
+ focusNodeNumber = -1;
+ stream << focusNodeNumber;
+
+ // Save the doc's cache id.
+ stream << d->m_cacheId;
+
+ // Save the state of the document (Most notably the state of any forms)
+ TQStringList docState;
+ if (d->m_doc)
+ {
+ docState = d->m_doc->docState();
+ }
+ stream << d->m_encoding << d->m_sheetUsed << docState;
+
+ stream << d->m_zoomFactor;
+
+ stream << d->m_httpHeaders;
+ stream << d->m_pageServices;
+ stream << d->m_pageReferrer;
+
+ // Save ssl data
+ stream << d->m_ssl_in_use
+ << d->m_ssl_peer_certificate
+ << d->m_ssl_peer_chain
+ << d->m_ssl_peer_ip
+ << d->m_ssl_cipher
+ << d->m_ssl_cipher_desc
+ << d->m_ssl_cipher_version
+ << d->m_ssl_cipher_used_bits
+ << d->m_ssl_cipher_bits
+ << d->m_ssl_cert_state
+ << d->m_ssl_parent_ip
+ << d->m_ssl_parent_cert;
+
+
+ TQStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
+ KURL::List frameURLLst;
+ TQValueList<TQByteArray> frameStateBufferLst;
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ {
+ if ( !(*it)->m_part )
+ continue;
+
+ frameNameLst << (*it)->m_name;
+ frameServiceTypeLst << (*it)->m_serviceType;
+ frameServiceNameLst << (*it)->m_serviceName;
+ frameURLLst << (*it)->m_part->url();
+
+ TQByteArray state;
+ TQDataStream frameStream( state, IO_WriteOnly );
+
+ if ( (*it)->m_extension )
+ (*it)->m_extension->saveState( frameStream );
+
+ frameStateBufferLst << state;
+ }
+
+ // Save frame data
+ stream << (TQ_UINT32) frameNameLst.count();
+ stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
+#ifndef NDEBUG
+ s_saveStateIndentLevel = indentLevel;
+#endif
+}
+
+void KHTMLPart::restoreState( TQDataStream &stream )
+{
+ KURL u;
+ TQ_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
+ TQ_UINT32 frameCount;
+ TQStringList frameNames, frameServiceTypes, docState, frameServiceNames;
+ KURL::List frameURLs;
+ TQValueList<TQByteArray> frameStateBuffers;
+ TQValueList<int> fSizes;
+ TQString encoding, sheetUsed;
+ long old_cacheId = d->m_cacheId;
+
+ stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
+
+ d->m_view->setMarginWidth( mWidth );
+ d->m_view->setMarginHeight( mHeight );
+
+ // restore link cursor position
+ // nth node is active. value is set in checkCompleted()
+ stream >> d->m_focusNodeNumber;
+ d->m_focusNodeRestored = false;
+
+ stream >> d->m_cacheId;
+
+ stream >> encoding >> sheetUsed >> docState;
+
+ d->m_encoding = encoding;
+ d->m_sheetUsed = sheetUsed;
+
+ int zoomFactor;
+ stream >> zoomFactor;
+ setZoomFactor(zoomFactor);
+
+ stream >> d->m_httpHeaders;
+ stream >> d->m_pageServices;
+ stream >> d->m_pageReferrer;
+
+ // Restore ssl data
+ stream >> d->m_ssl_in_use
+ >> d->m_ssl_peer_certificate
+ >> d->m_ssl_peer_chain
+ >> d->m_ssl_peer_ip
+ >> d->m_ssl_cipher
+ >> d->m_ssl_cipher_desc
+ >> d->m_ssl_cipher_version
+ >> d->m_ssl_cipher_used_bits
+ >> d->m_ssl_cipher_bits
+ >> d->m_ssl_cert_state
+ >> d->m_ssl_parent_ip
+ >> d->m_ssl_parent_cert;
+
+ setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
+
+ stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
+ >> frameURLs >> frameStateBuffers;
+
+ d->m_bComplete = false;
+ d->m_bLoadEventEmitted = false;
+
+// kdDebug( 6050 ) << "restoreState() docState.count() = " << docState.count() << endl;
+// kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
+// kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
+
+ if (d->m_cacheId == old_cacheId)
+ {
+ // Partial restore
+ d->m_redirectionTimer.stop();
+
+ FrameIt fIt = d->m_frames.begin();
+ const FrameIt fEnd = d->m_frames.end();
+
+ for (; fIt != fEnd; ++fIt )
+ (*fIt)->m_bCompleted = false;
+
+ fIt = d->m_frames.begin();
+
+ TQStringList::ConstIterator fNameIt = frameNames.begin();
+ TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
+ TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
+ KURL::List::ConstIterator fURLIt = frameURLs.begin();
+ TQValueList<TQByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
+
+ for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
+ {
+ tdehtml::ChildFrame* const child = *fIt;
+
+// kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
+
+ if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
+ {
+ child->m_bPreloaded = true;
+ child->m_name = *fNameIt;
+ child->m_serviceName = *fServiceNameIt;
+ processObjectRequest( child, *fURLIt, *fServiceTypeIt );
+ }
+ if ( child->m_part )
+ {
+ child->m_bCompleted = false;
+ if ( child->m_extension && !(*fBufferIt).isEmpty() )
+ {
+ TQDataStream frameStream( *fBufferIt, IO_ReadOnly );
+ child->m_extension->restoreState( frameStream );
+ }
+ else
+ child->m_part->openURL( *fURLIt );
+ }
+ }
+
+ KParts::URLArgs args( d->m_extension->urlArgs() );
+ args.xOffset = xOffset;
+ args.yOffset = yOffset;
+ args.docState = docState;
+ d->m_extension->setURLArgs( args );
+
+ d->m_view->resizeContents( wContents, hContents);
+ d->m_view->setContentsPos( xOffset, yOffset );
+
+ m_url = u;
+ }
+ else
+ {
+ // Full restore.
+ closeURL();
+ // We must force a clear because we want to be sure to delete all
+ // frames.
+ d->m_bCleared = false;
+ clear();
+ d->m_encoding = encoding;
+ d->m_sheetUsed = sheetUsed;
+
+ TQStringList::ConstIterator fNameIt = frameNames.begin();
+ const TQStringList::ConstIterator fNameEnd = frameNames.end();
+
+ TQStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
+ TQStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
+ KURL::List::ConstIterator fURLIt = frameURLs.begin();
+ TQValueList<TQByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
+
+ for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
+ {
+ tdehtml::ChildFrame* const newChild = new tdehtml::ChildFrame;
+ newChild->m_bPreloaded = true;
+ newChild->m_name = *fNameIt;
+ newChild->m_serviceName = *fServiceNameIt;
+
+// kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
+
+ const FrameIt childFrame = d->m_frames.append( newChild );
+
+ processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
+
+ (*childFrame)->m_bPreloaded = true;
+
+ if ( (*childFrame)->m_part )
+ {
+ if ( (*childFrame)->m_extension )
+ if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
+ {
+ TQDataStream frameStream( *fBufferIt, IO_ReadOnly );
+ (*childFrame)->m_extension->restoreState( frameStream );
+ }
+ else
+ (*childFrame)->m_part->openURL( *fURLIt );
+ }
+ }
+
+ KParts::URLArgs args( d->m_extension->urlArgs() );
+ args.xOffset = xOffset;
+ args.yOffset = yOffset;
+ args.docState = docState;
+
+ d->m_extension->setURLArgs( args );
+ if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
+ {
+ d->m_restored = true;
+ openURL( u );
+ d->m_restored = false;
+ }
+ else
+ {
+ restoreURL( u );
+ }
+ }
+
+}
+
+void KHTMLPart::show()
+{
+ if ( d->m_view )
+ d->m_view->show();
+}
+
+void KHTMLPart::hide()
+{
+ if ( d->m_view )
+ d->m_view->hide();
+}
+
+DOM::Node KHTMLPart::nodeUnderMouse() const
+{
+ return d->m_view->nodeUnderMouse();
+}
+
+DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
+{
+ return d->m_view->nonSharedNodeUnderMouse();
+}
+
+void KHTMLPart::emitSelectionChanged()
+{
+ emit d->m_extension->enableAction( "copy", hasSelection() );
+ if ( d->m_findDialog )
+ d->m_findDialog->setHasSelection( hasSelection() );
+
+ emit d->m_extension->selectionInfo( selectedText() );
+ emit selectionChanged();
+}
+
+int KHTMLPart::zoomFactor() const
+{
+ return d->m_zoomFactor;
+}
+
+// ### make the list configurable ?
+static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
+static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
+static const int minZoom = 20;
+static const int maxZoom = 300;
+
+// My idea of useful stepping ;-) (LS)
+extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
+extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
+
+void KHTMLPart::slotIncZoom()
+{
+ zoomIn(zoomSizes, zoomSizeCount);
+}
+
+void KHTMLPart::slotDecZoom()
+{
+ zoomOut(zoomSizes, zoomSizeCount);
+}
+
+void KHTMLPart::slotIncZoomFast()
+{
+ zoomIn(fastZoomSizes, fastZoomSizeCount);
+}
+
+void KHTMLPart::slotDecZoomFast()
+{
+ zoomOut(fastZoomSizes, fastZoomSizeCount);
+}
+
+void KHTMLPart::zoomIn(const int stepping[], int count)
+{
+ int zoomFactor = d->m_zoomFactor;
+
+ if (zoomFactor < maxZoom) {
+ // find the entry nearest to the given zoomsizes
+ for (int i = 0; i < count; ++i)
+ if (stepping[i] > zoomFactor) {
+ zoomFactor = stepping[i];
+ break;
+ }
+ setZoomFactor(zoomFactor);
+ }
+}
+
+void KHTMLPart::zoomOut(const int stepping[], int count)
+{
+ int zoomFactor = d->m_zoomFactor;
+ if (zoomFactor > minZoom) {
+ // find the entry nearest to the given zoomsizes
+ for (int i = count-1; i >= 0; --i)
+ if (stepping[i] < zoomFactor) {
+ zoomFactor = stepping[i];
+ break;
+ }
+ setZoomFactor(zoomFactor);
+ }
+}
+
+void KHTMLPart::setZoomFactor (int percent)
+{
+ if (percent < minZoom) percent = minZoom;
+ if (percent > maxZoom) percent = maxZoom;
+ if (d->m_zoomFactor == percent) return;
+ d->m_zoomFactor = percent;
+
+ if(d->m_doc) {
+ TQApplication::setOverrideCursor( tqwaitCursor );
+ if (d->m_doc->styleSelector())
+ d->m_doc->styleSelector()->computeFontSizes(d->m_doc->paintDeviceMetrics(), d->m_zoomFactor);
+ d->m_doc->recalcStyle( NodeImpl::Force );
+ TQApplication::restoreOverrideCursor();
+ }
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
+ KParts::ReadOnlyPart* const p = ( *it )->m_part;
+ static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
+ }
+
+ if ( d->m_guiProfile == BrowserViewGUI ) {
+ d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
+ d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
+ }
+}
+
+void KHTMLPart::slotZoomView( int delta )
+{
+ if ( delta < 0 )
+ slotIncZoom();
+ else
+ slotDecZoom();
+}
+
+void KHTMLPart::setStatusBarText( const TQString& text, StatusBarPriority p)
+{
+ if (!d->m_statusMessagesEnabled)
+ return;
+
+ d->m_statusBarText[p] = text;
+
+ // shift handling ?
+ TQString tobe = d->m_statusBarText[BarHoverText];
+ if (tobe.isEmpty())
+ tobe = d->m_statusBarText[BarOverrideText];
+ if (tobe.isEmpty()) {
+ tobe = d->m_statusBarText[BarDefaultText];
+ if (!tobe.isEmpty() && d->m_jobspeed)
+ tobe += " ";
+ if (d->m_jobspeed)
+ tobe += i18n( "(%1/s)" ).arg( TDEIO::convertSize( d->m_jobspeed ) );
+ }
+ tobe = "<qt>"+tobe;
+
+ emit ReadOnlyPart::setStatusBarText(tobe);
+}
+
+
+void KHTMLPart::setJSStatusBarText( const TQString &text )
+{
+ setStatusBarText(text, BarOverrideText);
+}
+
+void KHTMLPart::setJSDefaultStatusBarText( const TQString &text )
+{
+ setStatusBarText(text, BarDefaultText);
+}
+
+TQString KHTMLPart::jsStatusBarText() const
+{
+ return d->m_statusBarText[BarOverrideText];
+}
+
+TQString KHTMLPart::jsDefaultStatusBarText() const
+{
+ return d->m_statusBarText[BarDefaultText];
+}
+
+TQString KHTMLPart::referrer() const
+{
+ return d->m_referrer;
+}
+
+TQString KHTMLPart::pageReferrer() const
+{
+ KURL referrerURL = KURL( d->m_pageReferrer );
+ if (referrerURL.isValid())
+ {
+ TQString protocol = referrerURL.protocol();
+
+ if ((protocol == "http") ||
+ ((protocol == "https") && (m_url.protocol() == "https")))
+ {
+ referrerURL.setRef(TQString());
+ referrerURL.setUser(TQString());
+ referrerURL.setPass(TQString());
+ return referrerURL.url();
+ }
+ }
+
+ return TQString();
+}
+
+
+TQString KHTMLPart::lastModified() const
+{
+ if ( d->m_lastModified.isEmpty() && m_url.isLocalFile() ) {
+ // Local file: set last-modified from the file's mtime.
+ // Done on demand to save time when this isn't needed - but can lead
+ // to slightly wrong results if updating the file on disk w/o reloading.
+ TQDateTime lastModif = TQFileInfo( m_url.path() ).lastModified();
+ d->m_lastModified = lastModif.toString( Qt::LocalDate );
+ }
+ //kdDebug(6050) << "KHTMLPart::lastModified: " << d->m_lastModified << endl;
+ return d->m_lastModified;
+}
+
+void KHTMLPart::slotLoadImages()
+{
+ if (d->m_doc )
+ d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
+ KParts::ReadOnlyPart* const p = ( *it )->m_part;
+ static_cast<KHTMLPart*>( p )->slotLoadImages();
+ }
+}
+
+void KHTMLPart::reparseConfiguration()
+{
+ KHTMLSettings *settings = KHTMLFactory::defaultHTMLSettings();
+ settings->init();
+
+ setAutoloadImages( settings->autoLoadImages() );
+ if (d->m_doc)
+ d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
+
+ d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
+ d->m_bBackRightClick = settings->isBackRightClickEnabled();
+ d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
+ setDebugScript( settings->isJavaScriptDebugEnabled() );
+ d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
+ d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
+ d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
+
+ delete d->m_settings;
+ d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
+
+ TQApplication::setOverrideCursor( tqwaitCursor );
+ tdehtml::CSSStyleSelector::reparseConfiguration();
+ if(d->m_doc) d->m_doc->updateStyleSelector();
+ TQApplication::restoreOverrideCursor();
+
+ if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
+ runAdFilter();
+}
+
+TQStringList KHTMLPart::frameNames() const
+{
+ TQStringList res;
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if (!(*it)->m_bPreloaded)
+ res += (*it)->m_name;
+
+ return res;
+}
+
+TQPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
+{
+ TQPtrList<KParts::ReadOnlyPart> res;
+
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it )
+ if (!(*it)->m_bPreloaded)
+ res.append( (*it)->m_part );
+
+ return res;
+}
+
+bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
+{
+ kdDebug( 6050 ) << this << "KHTMLPart::openURLInFrame " << url << endl;
+ FrameIt it = d->m_frames.find( urlArgs.frameName );
+
+ if ( it == d->m_frames.end() )
+ return false;
+
+ // Inform someone that we are about to show something else.
+ if ( !urlArgs.lockHistory() )
+ emit d->m_extension->openURLNotify();
+
+ requestObject( *it, url, urlArgs );
+
+ return true;
+}
+
+void KHTMLPart::setDNDEnabled( bool b )
+{
+ d->m_bDnd = b;
+}
+
+bool KHTMLPart::dndEnabled() const
+{
+ return d->m_bDnd;
+}
+
+void KHTMLPart::customEvent( TQCustomEvent *event )
+{
+ if ( tdehtml::MousePressEvent::test( event ) )
+ {
+ tdehtmlMousePressEvent( static_cast<tdehtml::MousePressEvent *>( event ) );
+ return;
+ }
+
+ if ( tdehtml::MouseDoubleClickEvent::test( event ) )
+ {
+ tdehtmlMouseDoubleClickEvent( static_cast<tdehtml::MouseDoubleClickEvent *>( event ) );
+ return;
+ }
+
+ if ( tdehtml::MouseMoveEvent::test( event ) )
+ {
+ tdehtmlMouseMoveEvent( static_cast<tdehtml::MouseMoveEvent *>( event ) );
+ return;
+ }
+
+ if ( tdehtml::MouseReleaseEvent::test( event ) )
+ {
+ tdehtmlMouseReleaseEvent( static_cast<tdehtml::MouseReleaseEvent *>( event ) );
+ return;
+ }
+
+ if ( tdehtml::DrawContentsEvent::test( event ) )
+ {
+ tdehtmlDrawContentsEvent( static_cast<tdehtml::DrawContentsEvent *>( event ) );
+ return;
+ }
+
+ KParts::ReadOnlyPart::customEvent( event );
+}
+
+/** returns the position of the first inline text box of the line at
+ * coordinate y in renderNode
+ *
+ * This is a helper function for line-by-line text selection.
+ */
+static bool firstRunAt(tdehtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
+{
+ for (tdehtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
+ if (n->isText()) {
+ tdehtml::RenderText* const textRenderer = static_cast<tdehtml::RenderText *>(n);
+ const tdehtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
+ const unsigned lim = runs.count();
+ for (unsigned i = 0; i != lim; ++i) {
+ if (runs[i]->m_y == y && textRenderer->element()) {
+ startNode = textRenderer->element();
+ startOffset = runs[i]->m_start;
+ return true;
+ }
+ }
+ }
+
+ if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/** returns the position of the last inline text box of the line at
+ * coordinate y in renderNode
+ *
+ * This is a helper function for line-by-line text selection.
+ */
+static bool lastRunAt(tdehtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
+{
+ tdehtml::RenderObject *n = renderNode;
+ if (!n) {
+ return false;
+ }
+ tdehtml::RenderObject *next;
+ while ((next = n->nextSibling())) {
+ n = next;
+ }
+
+ while (1) {
+ if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
+ return true;
+ }
+
+ if (n->isText()) {
+ tdehtml::RenderText* const textRenderer = static_cast<tdehtml::RenderText *>(n);
+ const tdehtml::InlineTextBoxArray &runs = textRenderer->inlineTextBoxes();
+ for (int i = (int)runs.count()-1; i >= 0; --i) {
+ if (runs[i]->m_y == y && textRenderer->element()) {
+ endNode = textRenderer->element();
+ endOffset = runs[i]->m_start + runs[i]->m_len;
+ return true;
+ }
+ }
+ }
+
+ if (n == renderNode) {
+ return false;
+ }
+
+ n = n->previousSibling();
+ }
+}
+
+void KHTMLPart::tdehtmlMousePressEvent( tdehtml::MousePressEvent *event )
+{
+ DOM::DOMString url = event->url();
+ TQMouseEvent *_mouse = event->qmouseEvent();
+ DOM::Node innerNode = event->innerNode();
+ d->m_mousePressNode = innerNode;
+
+ d->m_dragStartPos = _mouse->pos();
+
+ if ( !event->url().isNull() ) {
+ d->m_strSelectedURL = event->url().string();
+ d->m_strSelectedURLTarget = event->target().string();
+ }
+ else
+ d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
+
+ if ( _mouse->button() == Qt::LeftButton ||
+ _mouse->button() == Qt::MidButton )
+ {
+ d->m_bMousePressed = true;
+
+#ifndef KHTML_NO_SELECTION
+ if ( _mouse->button() == Qt::LeftButton )
+ {
+ if ( (!d->m_strSelectedURL.isNull() && !isEditable())
+ || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
+ return;
+ if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
+ int offset = 0;
+ DOM::NodeImpl* node = 0;
+ tdehtml::RenderObject::SelPointState state;
+ innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
+ event->absX()-innerNode.handle()->renderer()->xPos(),
+ event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state );
+ d->m_extendMode = d->ExtendByChar;
+#ifdef KHTML_NO_CARET
+ d->m_selectionStart = node;
+ d->m_startOffset = offset;
+ //if ( node )
+ // kdDebug(6005) << "KHTMLPart::tdehtmlMousePressEvent selectionStart=" << d->m_selectionStart.handle()->renderer()
+ // << " offset=" << d->m_startOffset << endl;
+ //else
+ // kdDebug(6005) << "KHTML::tdehtmlMousePressEvent selectionStart=(nil)" << endl;
+ d->m_selectionEnd = d->m_selectionStart;
+ d->m_endOffset = d->m_startOffset;
+ d->m_doc->clearSelection();
+#else // KHTML_NO_CARET
+ d->m_view->moveCaretTo(node, offset, (_mouse->state() & ShiftButton) == 0);
+#endif // KHTML_NO_CARET
+ d->m_initialNode = d->m_selectionStart;
+ d->m_initialOffset = d->m_startOffset;
+// kdDebug(6000) << "press: initOfs " << d->m_initialOffset << endl;
+ }
+ else
+ {
+#ifndef KHTML_NO_CARET
+ // simply leave it. Is this a good idea?
+#else
+ d->m_selectionStart = DOM::Node();
+ d->m_selectionEnd = DOM::Node();
+#endif
+ }
+ emitSelectionChanged();
+ startAutoScroll();
+ }
+#else
+ d->m_dragLastPos = _mouse->globalPos();
+#endif
+ }
+
+ if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
+ {
+ d->m_bRightMousePressed = true;
+ } else if ( _mouse->button() == Qt::RightButton )
+ {
+ popupMenu( d->m_strSelectedURL );
+ // might be deleted, don't touch "this"
+ }
+}
+
+void KHTMLPart::tdehtmlMouseDoubleClickEvent( tdehtml::MouseDoubleClickEvent *event )
+{
+ TQMouseEvent *_mouse = event->qmouseEvent();
+ if ( _mouse->button() == Qt::LeftButton )
+ {
+ d->m_bMousePressed = true;
+ DOM::Node innerNode = event->innerNode();
+ // Find selectionStart again, tdehtmlMouseReleaseEvent lost it
+ if ( !innerNode.isNull() && innerNode.handle()->renderer()) {
+ int offset = 0;
+ DOM::NodeImpl* node = 0;
+ tdehtml::RenderObject::SelPointState state;
+ innerNode.handle()->renderer()->checkSelectionPoint( event->x(), event->y(),
+ event->absX()-innerNode.handle()->renderer()->xPos(),
+ event->absY()-innerNode.handle()->renderer()->yPos(), node, offset, state);
+
+ //kdDebug() << k_funcinfo << "checkSelectionPoint returned node=" << node << " offset=" << offset << endl;
+
+ if ( node && node->renderer() )
+ {
+ // Extend selection to a complete word (double-click) or line (triple-click)
+ bool selectLine = (event->clickCount() == 3);
+ d->m_extendMode = selectLine ? d->ExtendByLine : d->ExtendByWord;
+
+ // Extend existing selection if Shift was pressed
+ if (_mouse->state() & ShiftButton) {
+ d->caretNode() = node;
+ d->caretOffset() = offset;
+ d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
+ d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
+ d->m_initialNode = d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd;
+ d->m_initialOffset = d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset;
+ } else {
+ d->m_selectionStart = d->m_selectionEnd = node;
+ d->m_startOffset = d->m_endOffset = offset;
+ d->m_startBeforeEnd = true;
+ d->m_initialNode = node;
+ d->m_initialOffset = offset;
+ }
+// kdDebug(6000) << "dblclk: initOfs " << d->m_initialOffset << endl;
+
+ // Extend the start
+ extendSelection( d->m_selectionStart.handle(), d->m_startOffset, d->m_selectionStart, d->m_startOffset, !d->m_startBeforeEnd, selectLine );
+ // Extend the end
+ extendSelection( d->m_selectionEnd.handle(), d->m_endOffset, d->m_selectionEnd, d->m_endOffset, d->m_startBeforeEnd, selectLine );
+
+ //kdDebug() << d->m_selectionStart.handle() << " " << d->m_startOffset << " - " <<
+ // d->m_selectionEnd.handle() << " " << d->m_endOffset << endl;
+
+ emitSelectionChanged();
+ d->m_doc
+ ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+ d->m_selectionEnd.handle(),d->m_endOffset);
+#ifndef KHTML_NO_CARET
+ bool v = d->m_view->placeCaret();
+ emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
+#endif
+ startAutoScroll();
+ }
+ }
+ }
+}
+
+void KHTMLPart::extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool selectLines )
+{
+ tdehtml::RenderObject* obj = node->renderer();
+
+ if (obj->isText() && selectLines) {
+ int pos;
+ tdehtml::RenderText *renderer = static_cast<tdehtml::RenderText *>(obj);
+ tdehtml::InlineTextBox *run = renderer->findInlineTextBox( offset, pos );
+ DOMString t = node->nodeValue();
+ DOM::NodeImpl* selNode = 0;
+ long selOfs = 0;
+
+ if (!run)
+ return;
+
+ int selectionPointY = run->m_y;
+
+ // Go up to first non-inline element.
+ tdehtml::RenderObject *renderNode = renderer;
+ while (renderNode && renderNode->isInline())
+ renderNode = renderNode->parent();
+
+ renderNode = renderNode->firstChild();
+
+ if (right) {
+ // Look for all the last child in the block that is on the same line
+ // as the selection point.
+ if (!lastRunAt (renderNode, selectionPointY, selNode, selOfs))
+ return;
+ } else {
+ // Look for all the first child in the block that is on the same line
+ // as the selection point.
+ if (!firstRunAt (renderNode, selectionPointY, selNode, selOfs))
+ return;
+ }
+
+ selectionNode = selNode;
+ selectionOffset = selOfs;
+ return;
+ }
+
+ TQString str;
+ int len = 0;
+ if ( obj->isText() ) { // can be false e.g. when double-clicking on a disabled submit button
+ str = static_cast<tdehtml::RenderText *>(obj)->data().string();
+ len = str.length();
+ }
+ //kdDebug() << "extendSelection right=" << right << " offset=" << offset << " len=" << len << " Starting at obj=" << obj << endl;
+ TQChar ch;
+ do {
+ // Last char was ok, point to it
+ if ( node ) {
+ selectionNode = node;
+ selectionOffset = offset;
+ }
+
+ // Get another char
+ while ( obj && ( (right && offset >= len-1) || (!right && offset <= 0) ) )
+ {
+ obj = right ? obj->objectBelow() : obj->objectAbove();
+ //kdDebug() << "obj=" << obj << endl;
+ if ( obj ) {
+ //kdDebug() << "isText=" << obj->isText() << endl;
+ str = TQString();
+ if ( obj->isText() )
+ str = static_cast<tdehtml::RenderText *>(obj)->data().string();
+ else if ( obj->isBR() )
+ str = '\n';
+ else if ( !obj->isInline() ) {
+ obj = 0L; // parag limit -> done
+ break;
+ }
+ len = str.length();
+ //kdDebug() << "str=" << str << " length=" << len << endl;
+ // set offset - note that the first thing will be a ++ or -- on it.
+ if ( right )
+ offset = -1;
+ else
+ offset = len;
+ }
+ }
+ if ( !obj ) // end of parag or document
+ break;
+ node = obj->element();
+ if ( right )
+ {
+ Q_ASSERT( offset < len-1 );
+ ++offset;
+ }
+ else
+ {
+ Q_ASSERT( offset > 0 );
+ --offset;
+ }
+
+ // Test that char
+ ch = str[ (int)offset ];
+ //kdDebug() << " offset=" << offset << " ch=" << TQString(ch) << endl;
+ } while ( !ch.isSpace() && !ch.isPunct() );
+
+ // make offset point after last char
+ if (right) ++selectionOffset;
+}
+
+#ifndef KHTML_NO_SELECTION
+void KHTMLPart::extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode)
+{
+ int offset;
+ //kdDebug(6000) << "KHTMLPart::tdehtmlMouseMoveEvent x=" << event->x() << " y=" << event->y() << endl;
+ DOM::NodeImpl* node=0;
+ tdehtml::RenderObject::SelPointState state;
+ innerNode.handle()->renderer()->checkSelectionPoint( x, y,
+ absX-innerNode.handle()->renderer()->xPos(),
+ absY-innerNode.handle()->renderer()->yPos(), node, offset, state);
+ if (!node || !node->renderer()) return;
+
+ // Words at the beginning/end of line cannot be deselected in
+ // ExtendByWord mode. Therefore, do not enforce it if the selection
+ // point does not match the node under the mouse cursor.
+ bool withinNode = innerNode == node;
+
+ // we have to get to know if end is before start or not...
+ // shouldn't be null but it can happen with dynamic updating of nodes
+ if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
+ d->m_initialNode.isNull() ||
+ !d->m_selectionStart.handle()->renderer() ||
+ !d->m_selectionEnd.handle()->renderer()) return;
+
+ if (d->m_extendMode != d->ExtendByChar) {
+ // check whether we should extend at the front, or at the back
+ bool caretBeforeInit = RangeImpl::compareBoundaryPoints(
+ d->caretNode().handle(), d->caretOffset(),
+ d->m_initialNode.handle(), d->m_initialOffset) <= 0;
+ bool nodeBeforeInit = RangeImpl::compareBoundaryPoints(node, offset,
+ d->m_initialNode.handle(), d->m_initialOffset) <= 0;
+ // have to fix up start to point to the original end
+ if (caretBeforeInit != nodeBeforeInit) {
+// kdDebug(6000) << "extto cbi: " << caretBeforeInit << " startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
+ extendSelection(d->m_initialNode.handle(), d->m_initialOffset,
+ d->m_extendAtEnd ? d->m_selectionStart : d->m_selectionEnd,
+ d->m_extendAtEnd ? d->m_startOffset : d->m_endOffset,
+ nodeBeforeInit, d->m_extendMode == d->ExtendByLine);
+ }
+ }
+
+ d->caretNode() = node;
+ d->caretOffset() = offset;
+ //kdDebug( 6000 ) << "setting end of selection to " << d->m_selectionEnd.handle() << "/" << d->m_endOffset << endl;
+
+ d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
+ d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
+
+ if ( !d->m_selectionStart.isNull() && !d->m_selectionEnd.isNull() )
+ {
+// kdDebug(6000) << "extto: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << " initOfs " << d->m_initialOffset << endl;
+ if (d->m_extendMode != d->ExtendByChar && withinNode)
+ extendSelection( node, offset, d->caretNode(), d->caretOffset(), d->m_startBeforeEnd ^ !d->m_extendAtEnd, d->m_extendMode == d->ExtendByLine );
+
+ if (d->m_selectionEnd == d->m_selectionStart && d->m_endOffset < d->m_startOffset)
+ d->m_doc
+ ->setSelection(d->m_selectionStart.handle(),d->m_endOffset,
+ d->m_selectionEnd.handle(),d->m_startOffset);
+ else if (d->m_startBeforeEnd)
+ d->m_doc
+ ->setSelection(d->m_selectionStart.handle(),d->m_startOffset,
+ d->m_selectionEnd.handle(),d->m_endOffset);
+ else
+ d->m_doc
+ ->setSelection(d->m_selectionEnd.handle(),d->m_endOffset,
+ d->m_selectionStart.handle(),d->m_startOffset);
+ }
+#ifndef KHTML_NO_CARET
+ d->m_view->placeCaret();
+#endif
+}
+
+bool KHTMLPart::isExtendingSelection() const
+{
+ // This is it, the whole detection. tdehtmlMousePressEvent only sets this
+ // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
+ // it's sufficient to only rely on this flag to detect selection extension.
+ return d->m_bMousePressed;
+}
+#endif // KHTML_NO_SELECTION
+
+void KHTMLPart::tdehtmlMouseMoveEvent( tdehtml::MouseMoveEvent *event )
+{
+ TQMouseEvent *_mouse = event->qmouseEvent();
+
+ if( d->m_bRightMousePressed && parentPart() != 0 && d->m_bBackRightClick )
+ {
+ popupMenu( d->m_strSelectedURL );
+ d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
+ d->m_bRightMousePressed = false;
+ }
+
+ DOM::DOMString url = event->url();
+ DOM::DOMString target = event->target();
+ DOM::Node innerNode = event->innerNode();
+
+#ifndef QT_NO_DRAGANDDROP
+ if( d->m_bDnd && d->m_bMousePressed &&
+ ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
+ || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) ) {
+ if ( ( d->m_dragStartPos - _mouse->pos() ).manhattanLength() <= TDEGlobalSettings::dndEventDelay() )
+ return;
+
+ TQPixmap pix;
+ HTMLImageElementImpl *img = 0L;
+ TQDragObject *drag = 0;
+ KURL u;
+
+ // tqDebug("****************** Event URL: %s", url.string().latin1());
+ // tqDebug("****************** Event Target: %s", target.string().latin1());
+
+ // Normal image...
+ if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
+ {
+ img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+ u = KURL( completeURL( tdehtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
+ pix = KMimeType::mimeType("image/png")->pixmap(KIcon::Desktop);
+ }
+ else
+ {
+ // Text or image link...
+ u = completeURL( d->m_strSelectedURL );
+ pix = KMimeType::pixmapForURL(u, 0, KIcon::Desktop, KIcon::SizeMedium);
+ }
+
+ u.setPass(TQString());
+
+ KURLDrag* urlDrag = new KURLDrag( u, img ? 0 : d->m_view->viewport() );
+ if ( !d->m_referrer.isEmpty() )
+ urlDrag->metaData()["referrer"] = d->m_referrer;
+
+ if( img && img->complete()) {
+ KMultipleDrag *mdrag = new KMultipleDrag( d->m_view->viewport() );
+ mdrag->addDragObject( new TQImageDrag( img->currentImage(), 0L ) );
+ mdrag->addDragObject( urlDrag );
+ drag = mdrag;
+ }
+ else
+ drag = urlDrag;
+
+ if ( !pix.isNull() )
+ drag->setPixmap( pix );
+
+ stopAutoScroll();
+ if(drag)
+ drag->drag();
+
+ // when we finish our drag, we need to undo our mouse press
+ d->m_bMousePressed = false;
+ d->m_strSelectedURL = d->m_strSelectedURLTarget = TQString();
+ return;
+ }
+#endif
+
+ // Not clicked -> mouse over stuff
+ if ( !d->m_bMousePressed )
+ {
+ // The mouse is over something
+ if ( url.length() )
+ {
+ bool shiftPressed = ( _mouse->state() & ShiftButton );
+
+ // Image map
+ if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
+ {
+ HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
+ if ( i && i->isServerMap() )
+ {
+ tdehtml::RenderObject *r = i->renderer();
+ if(r)
+ {
+ int absx, absy, vx, vy;
+ r->absolutePosition(absx, absy);
+ view()->contentsToViewport( absx, absy, vx, vy );
+
+ int x(_mouse->x() - vx), y(_mouse->y() - vy);
+
+ d->m_overURL = url.string() + TQString("?%1,%2").arg(x).arg(y);
+ d->m_overURLTarget = target.string();
+ overURL( d->m_overURL, target.string(), shiftPressed );
+ return;
+ }
+ }
+ }
+
+ // normal link
+ if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
+ {
+ d->m_overURL = url.string();
+ d->m_overURLTarget = target.string();
+ overURL( d->m_overURL, target.string(), shiftPressed );
+ }
+ }
+ else // Not over a link...
+ {
+ // reset to "default statusbar text"
+ resetHoverText();
+ }
+ }
+ else {
+#ifndef KHTML_NO_SELECTION
+ // selection stuff
+ if( d->m_bMousePressed && innerNode.handle() && innerNode.handle()->renderer() &&
+ ( (_mouse->state() & Qt::LeftButton) != 0 )) {
+ extendSelectionTo(event->x(), event->y(),
+ event->absX(), event->absY(), innerNode);
+#else
+ if ( d->m_doc && d->m_view ) {
+ TQPoint diff( _mouse->globalPos() - d->m_dragLastPos );
+
+ if ( abs( diff.x() ) > 64 || abs( diff.y() ) > 64 ) {
+ d->m_view->scrollBy( -diff.x(), -diff.y() );
+ d->m_dragLastPos = _mouse->globalPos();
+ }
+#endif
+ }
+ }
+
+}
+
+void KHTMLPart::tdehtmlMouseReleaseEvent( tdehtml::MouseReleaseEvent *event )
+{
+ DOM::Node innerNode = event->innerNode();
+ d->m_mousePressNode = DOM::Node();
+
+ if ( d->m_bMousePressed ) {
+ setStatusBarText(TQString(), BarHoverText);
+ stopAutoScroll();
+ }
+
+ // Used to prevent mouseMoveEvent from initiating a drag before
+ // the mouse is pressed again.
+ d->m_bMousePressed = false;
+
+ TQMouseEvent *_mouse = event->qmouseEvent();
+ if ( _mouse->button() == Qt::RightButton && parentPart() != 0 && d->m_bBackRightClick )
+ {
+ d->m_bRightMousePressed = false;
+ KParts::BrowserInterface *tmp_iface = d->m_extension->browserInterface();
+ if( tmp_iface ) {
+ tmp_iface->callMethod( "goHistory(int)", -1 );
+ }
+ }
+#ifndef QT_NO_CLIPBOARD
+ if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == Qt::MidButton) && (event->url().isNull())) {
+ kdDebug( 6050 ) << "KHTMLPart::tdehtmlMouseReleaseEvent() MMB shouldOpen="
+ << d->m_bOpenMiddleClick << endl;
+
+ if (d->m_bOpenMiddleClick) {
+ KHTMLPart *p = this;
+ while (p->parentPart()) p = p->parentPart();
+ p->d->m_extension->pasteRequest();
+ }
+ }
+#endif
+
+#ifndef KHTML_NO_SELECTION
+ // delete selection in case start and end position are at the same point
+ if(d->m_selectionStart == d->m_selectionEnd && d->m_startOffset == d->m_endOffset) {
+#ifndef KHTML_NO_CARET
+ d->m_extendAtEnd = true;
+#else
+ d->m_selectionStart = 0;
+ d->m_selectionEnd = 0;
+ d->m_startOffset = 0;
+ d->m_endOffset = 0;
+#endif
+ emitSelectionChanged();
+ } else {
+ // we have to get to know if end is before start or not...
+// kdDebug(6000) << "rel: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << ")" << endl;
+ DOM::Node n = d->m_selectionStart;
+ d->m_startBeforeEnd = false;
+ if( d->m_selectionStart == d->m_selectionEnd ) {
+ if( d->m_startOffset < d->m_endOffset )
+ d->m_startBeforeEnd = true;
+ } else {
+#if 0
+ while(!n.isNull()) {
+ if(n == d->m_selectionEnd) {
+ d->m_startBeforeEnd = true;
+ break;
+ }
+ DOM::Node next = n.firstChild();
+ if(next.isNull()) next = n.nextSibling();
+ while( next.isNull() && !n.parentNode().isNull() ) {
+ n = n.parentNode();
+ next = n.nextSibling();
+ }
+ n = next;
+ }
+#else
+ // shouldn't be null but it can happen with dynamic updating of nodes
+ if (d->m_selectionStart.isNull() || d->m_selectionEnd.isNull() ||
+ !d->m_selectionStart.handle()->renderer() ||
+ !d->m_selectionEnd.handle()->renderer()) return;
+ d->m_startBeforeEnd = RangeImpl::compareBoundaryPoints(
+ d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset) <= 0;
+#endif
+ }
+ if(!d->m_startBeforeEnd)
+ {
+ DOM::Node tmpNode = d->m_selectionStart;
+ int tmpOffset = d->m_startOffset;
+ d->m_selectionStart = d->m_selectionEnd;
+ d->m_startOffset = d->m_endOffset;
+ d->m_selectionEnd = tmpNode;
+ d->m_endOffset = tmpOffset;
+ d->m_startBeforeEnd = true;
+ d->m_extendAtEnd = !d->m_extendAtEnd;
+ }
+#ifndef KHTML_NO_CARET
+ bool v = d->m_view->placeCaret();
+ emitCaretPositionChanged(v ? d->caretNode() : 0, d->caretOffset());
+#endif
+ // get selected text and paste to the clipboard
+#ifndef QT_NO_CLIPBOARD
+ TQString text = selectedText();
+ text.replace(TQChar(0xa0), ' ');
+ disconnect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), this, TQT_SLOT( slotClearSelection()));
+ kapp->clipboard()->setText(text,TQClipboard::Selection);
+ connect( kapp->clipboard(), TQT_SIGNAL( selectionChanged()), TQT_SLOT( slotClearSelection()));
+#endif
+ //kdDebug( 6000 ) << "selectedText = " << text << endl;
+ emitSelectionChanged();
+//kdDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset() << endl;
+ }
+#endif
+ d->m_initialNode = 0; // don't hold nodes longer than necessary
+ d->m_initialOffset = 0;
+
+}
+
+void KHTMLPart::tdehtmlDrawContentsEvent( tdehtml::DrawContentsEvent * )
+{
+}
+
+void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
+{
+ if ( event->activated() )
+ {
+ emitSelectionChanged();
+ emit d->m_extension->enableAction( "print", d->m_doc != 0 );
+
+ if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
+ {
+ TQPtrList<KAction> lst;
+ lst.append( d->m_paLoadImages );
+ plugActionList( "loadImages", lst );
+ }
+ }
+}
+
+void KHTMLPart::slotPrintFrame()
+{
+ if ( d->m_frames.count() == 0 )
+ return;
+
+ KParts::ReadOnlyPart *frame = currentFrame();
+ if (!frame)
+ return;
+
+ KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
+
+ if ( !ext )
+ return;
+
+ TQMetaObject *mo = ext->metaObject();
+
+ int idx = mo->findSlot( "print()", true );
+ if ( idx >= 0 ) {
+ TQUObject o[ 1 ];
+ ext->tqt_invoke( idx, o );
+ }
+}
+
+void KHTMLPart::slotSelectAll()
+{
+ KParts::ReadOnlyPart *part = currentFrame();
+ if (part && part->inherits("KHTMLPart"))
+ static_cast<KHTMLPart *>(part)->selectAll();
+}
+
+void KHTMLPart::startAutoScroll()
+{
+ connect(&d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ));
+ d->m_scrollTimer.start(100, false);
+}
+
+void KHTMLPart::stopAutoScroll()
+{
+ disconnect(&d->m_scrollTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotAutoScroll() ));
+ if (d->m_scrollTimer.isActive())
+ d->m_scrollTimer.stop();
+}
+
+
+void KHTMLPart::slotAutoScroll()
+{
+ if (d->m_view)
+ d->m_view->doAutoScroll();
+ else
+ stopAutoScroll(); // Safety
+}
+
+void KHTMLPart::runAdFilter()
+{
+ if ( parentPart() )
+ parentPart()->runAdFilter();
+
+ if ( !d->m_doc )
+ return;
+
+ TQPtrDictIterator<tdehtml::CachedObject> it( d->m_doc->docLoader()->m_docObjects );
+ for ( ; it.current(); ++it )
+ if ( it.current()->type() == tdehtml::CachedObject::Image ) {
+ tdehtml::CachedImage *image = static_cast<tdehtml::CachedImage *>(it.current());
+ bool wasBlocked = image->m_wasBlocked;
+ image->m_wasBlocked = KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( (*it).url().string() ) );
+ if ( image->m_wasBlocked != wasBlocked )
+ image->do_notify(image->pixmap(), image->valid_rect());
+ }
+
+ if ( KHTMLFactory::defaultHTMLSettings()->isHideAdsEnabled() ) {
+ for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
+
+ // We might be deleting 'node' shortly.
+ nextNode = node->traverseNextNode();
+
+ if ( node->id() == ID_IMG ||
+ node->id() == ID_IFRAME ||
+ (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
+ {
+ if ( KHTMLFactory::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
+ {
+ // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
+ node->ref();
+ NodeImpl *parent = node->parent();
+ if( parent )
+ {
+ int exception = 0;
+ parent->removeChild(node, exception);
+ }
+ node->deref();
+ }
+ }
+ }
+ }
+}
+
+void KHTMLPart::selectAll()
+{
+ if (!d->m_doc) return;
+
+ NodeImpl *first;
+ if (d->m_doc->isHTMLDocument())
+ first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
+ else
+ first = d->m_doc;
+ NodeImpl *next;
+
+ // Look for first text/cdata node that has a renderer,
+ // or first childless replaced element
+ while ( first && !(first->renderer()
+ && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
+ || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
+ {
+ next = first->firstChild();
+ if ( !next ) next = first->nextSibling();
+ while( first && !next )
+ {
+ first = first->parentNode();
+ if ( first )
+ next = first->nextSibling();
+ }
+ first = next;
+ }
+
+ NodeImpl *last;
+ if (d->m_doc->isHTMLDocument())
+ last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
+ else
+ last = d->m_doc;
+ // Look for last text/cdata node that has a renderer,
+ // or last childless replaced element
+ // ### Instead of changing this loop, use findLastSelectableNode
+ // in render_table.cpp (LS)
+ while ( last && !(last->renderer()
+ && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
+ || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
+ {
+ next = last->lastChild();
+ if ( !next ) next = last->previousSibling();
+ while ( last && !next )
+ {
+ last = last->parentNode();
+ if ( last )
+ next = last->previousSibling();
+ }
+ last = next;
+ }
+
+ if ( !first || !last )
+ return;
+ Q_ASSERT(first->renderer());
+ Q_ASSERT(last->renderer());
+ d->m_selectionStart = first;
+ d->m_startOffset = 0;
+ d->m_selectionEnd = last;
+ d->m_endOffset = last->nodeValue().length();
+ d->m_startBeforeEnd = true;
+
+ d->m_doc->setSelection( d->m_selectionStart.handle(), d->m_startOffset,
+ d->m_selectionEnd.handle(), d->m_endOffset );
+
+ emitSelectionChanged();
+}
+
+bool KHTMLPart::checkLinkSecurity(const KURL &linkURL,const TQString &message, const TQString &button)
+{
+ bool linkAllowed = true;
+
+ if ( d->m_doc )
+ linkAllowed = kapp && kapp->authorizeURLAction("redirect", url(), linkURL);
+
+ if ( !linkAllowed ) {
+ tdehtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
+ if (tokenizer)
+ tokenizer->setOnHold(true);
+
+ int response = KMessageBox::Cancel;
+ if (!message.isEmpty())
+ {
+ response = KMessageBox::warningContinueCancel( 0,
+ message.arg(linkURL.htmlURL()),
+ i18n( "Security Warning" ),
+ button);
+ }
+ else
+ {
+ KMessageBox::error( 0,
+ i18n( "<qt>Access by untrusted page to<BR><B>%1</B><BR> denied.").arg(linkURL.htmlURL()),
+ i18n( "Security Alert" ));
+ }
+
+ if (tokenizer)
+ tokenizer->setOnHold(false);
+ return (response==KMessageBox::Continue);
+ }
+ return true;
+}
+
+void KHTMLPart::slotPartRemoved( KParts::Part *part )
+{
+// kdDebug(6050) << "KHTMLPart::slotPartRemoved " << part << endl;
+ if ( part == d->m_activeFrame )
+ {
+ d->m_activeFrame = 0L;
+ if ( !part->inherits( "KHTMLPart" ) )
+ {
+ if (factory()) {
+ factory()->removeClient( part );
+ }
+ if (childClients()->containsRef(part)) {
+ removeChildClient( part );
+ }
+ }
+ }
+}
+
+void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
+{
+// kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged this=" << this << "part=" << part << endl;
+ if ( part == this )
+ {
+ kdError(6050) << "strange error! we activated ourselves" << endl;
+ assert( false );
+ return;
+ }
+// kdDebug(6050) << "KHTMLPart::slotActiveFrameChanged d->m_activeFrame=" << d->m_activeFrame << endl;
+ if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( TQFRAME_OBJECT_NAME_STRING ) )
+ {
+ TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
+ if (frame->frameStyle() != TQFrame::NoFrame)
+ {
+ frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken);
+ frame->repaint();
+ }
+ }
+
+ if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
+ {
+ if (factory()) {
+ factory()->removeClient( d->m_activeFrame );
+ }
+ removeChildClient( d->m_activeFrame );
+ }
+ if( part && !part->inherits( "KHTMLPart" ) )
+ {
+ if (factory()) {
+ factory()->addClient( part );
+ }
+ insertChildClient( part );
+ }
+
+
+ d->m_activeFrame = part;
+
+ if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( TQFRAME_OBJECT_NAME_STRING ) )
+ {
+ TQFrame *frame = static_cast<TQFrame *>( d->m_activeFrame->widget() );
+ if (frame->frameStyle() != TQFrame::NoFrame)
+ {
+ frame->setFrameStyle( TQFrame::StyledPanel | TQFrame::Plain);
+ frame->repaint();
+ }
+ kdDebug(6050) << "new active frame " << d->m_activeFrame << endl;
+ }
+
+ updateActions();
+
+ // (note: childObject returns 0 if the argument is 0)
+ d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
+}
+
+void KHTMLPart::setActiveNode(const DOM::Node &node)
+{
+ if (!d->m_doc || !d->m_view)
+ return;
+
+ // Set the document's active node
+ d->m_doc->setFocusNode(node.handle());
+
+ // Scroll the view if necessary to ensure that the new focus node is visible
+ TQRect rect = node.handle()->getRect();
+ d->m_view->ensureVisible(rect.right(), rect.bottom());
+ d->m_view->ensureVisible(rect.left(), rect.top());
+}
+
+DOM::Node KHTMLPart::activeNode() const
+{
+ return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
+}
+
+DOM::EventListener *KHTMLPart::createHTMLEventListener( TQString code, TQString name, NodeImpl* node )
+{
+ KJSProxy *proxy = jScript();
+
+ if (!proxy)
+ return 0;
+
+ return proxy->createHTMLEventHandler( m_url.url(), name, code, node );
+}
+
+KHTMLPart *KHTMLPart::opener()
+{
+ return d->m_opener;
+}
+
+void KHTMLPart::setOpener(KHTMLPart *_opener)
+{
+ d->m_opener = _opener;
+}
+
+bool KHTMLPart::openedByJS()
+{
+ return d->m_openedByJS;
+}
+
+void KHTMLPart::setOpenedByJS(bool _openedByJS)
+{
+ d->m_openedByJS = _openedByJS;
+}
+
+void KHTMLPart::preloadStyleSheet(const TQString &url, const TQString &stylesheet)
+{
+ tdehtml::Cache::preloadStyleSheet(url, stylesheet);
+}
+
+void KHTMLPart::preloadScript(const TQString &url, const TQString &script)
+{
+ tdehtml::Cache::preloadScript(url, script);
+}
+
+TQCString KHTMLPart::dcopObjectId() const
+{
+ TQCString id;
+ id.sprintf("html-widget%d", d->m_dcop_counter);
+ return id;
+}
+
+long KHTMLPart::cacheId() const
+{
+ return d->m_cacheId;
+}
+
+bool KHTMLPart::restored() const
+{
+ return d->m_restored;
+}
+
+bool KHTMLPart::pluginPageQuestionAsked(const TQString& mimetype) const
+{
+ // parentPart() should be const!
+ KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
+ if ( parent )
+ return parent->pluginPageQuestionAsked(mimetype);
+
+ return d->m_pluginPageQuestionAsked.contains(mimetype);
+}
+
+void KHTMLPart::setPluginPageQuestionAsked(const TQString& mimetype)
+{
+ if ( parentPart() )
+ parentPart()->setPluginPageQuestionAsked(mimetype);
+
+ d->m_pluginPageQuestionAsked.append(mimetype);
+}
+
+void KHTMLPart::slotAutomaticDetectionLanguage( int _id )
+{
+ d->m_automaticDetection->setItemChecked( _id, true );
+
+ switch ( _id ) {
+ case 0 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::SemiautomaticDetection;
+ break;
+ case 1 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Arabic;
+ break;
+ case 2 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Baltic;
+ break;
+ case 3 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::CentralEuropean;
+ break;
+ case 4 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Chinese;
+ break;
+ case 5 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Greek;
+ break;
+ case 6 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Hebrew;
+ break;
+ case 7 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Japanese;
+ break;
+ case 8 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Korean;
+ break;
+ case 9 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Russian;
+ break;
+ case 10 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Thai;
+ break;
+ case 11 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Turkish;
+ break;
+ case 12 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Ukrainian;
+ break;
+ case 13 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::Unicode;
+ break;
+ case 14 :
+ d->m_autoDetectLanguage = tdehtml::Decoder::WesternEuropean;
+ break;
+ default :
+ d->m_autoDetectLanguage = tdehtml::Decoder::SemiautomaticDetection;
+ break;
+ }
+
+ for ( int i = 0; i <= 14; ++i ) {
+ if ( i != _id )
+ d->m_automaticDetection->setItemChecked( i, false );
+ }
+
+ d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
+
+ setEncoding( TQString(), false );
+
+ if( d->m_manualDetection )
+ d->m_manualDetection->setCurrentItem( -1 );
+ d->m_paSetEncoding->popupMenu()->setItemChecked( d->m_paSetEncoding->popupMenu()->idAt( 2 ), false );
+}
+
+tdehtml::Decoder *KHTMLPart::createDecoder()
+{
+ tdehtml::Decoder *dec = new tdehtml::Decoder();
+ if( !d->m_encoding.isNull() )
+ dec->setEncoding( d->m_encoding.latin1(),
+ d->m_haveEncoding ? tdehtml::Decoder::UserChosenEncoding : tdehtml::Decoder::EncodingFromHTTPHeader);
+ else {
+ // Inherit the default encoding from the parent frame if there is one.
+ const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
+ ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
+ dec->setEncoding(defaultEncoding, tdehtml::Decoder::DefaultEncoding);
+ }
+#ifdef APPLE_CHANGES
+ if (d->m_doc)
+ d->m_doc->setDecoder(d->m_decoder);
+#endif
+ dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
+ return dec;
+}
+
+void KHTMLPart::emitCaretPositionChanged(const DOM::Node &node, long offset) {
+ emit caretPositionChanged(node, offset);
+}
+
+void KHTMLPart::restoreScrollPosition()
+{
+ KParts::URLArgs args = d->m_extension->urlArgs();
+
+ if ( m_url.hasRef() && !d->m_restoreScrollPosition && !args.reload) {
+ if ( !d->m_doc || !d->m_doc->parsing() )
+ disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+ if ( !gotoAnchor(m_url.encodedHtmlRef()) )
+ gotoAnchor(m_url.htmlRef());
+ return;
+ }
+
+ // Check whether the viewport has become large enough to encompass the stored
+ // offsets. If the document has been fully loaded, force the new coordinates,
+ // even if the canvas is too short (can happen when user resizes the window
+ // during loading).
+ if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset
+ || d->m_bComplete) {
+ d->m_view->setContentsPos(args.xOffset, args.yOffset);
+ disconnect(d->m_view, TQT_SIGNAL(finishedLayout()), this, TQT_SLOT(restoreScrollPosition()));
+ }
+}
+
+
+void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
+{
+#ifndef KHTML_NO_WALLET
+ KHTMLPart *p;
+
+ for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
+ }
+
+ if (p) {
+ p->openWallet(form);
+ return;
+ }
+
+ if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
+ return;
+ }
+
+ if (d->m_wallet) {
+ if (d->m_bWalletOpened) {
+ if (d->m_wallet->isOpen()) {
+ form->walletOpened(d->m_wallet);
+ return;
+ }
+ d->m_wallet->deleteLater();
+ d->m_wallet = 0L;
+ d->m_bWalletOpened = false;
+ }
+ }
+
+ if (!d->m_wq) {
+ KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
+ d->m_wq = new KHTMLWalletQueue(this);
+ d->m_wq->wallet = wallet;
+ connect(wallet, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
+ connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_SLOT(walletOpened(KWallet::Wallet*)));
+ }
+ assert(form);
+ d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->getDocument()));
+#endif // KHTML_NO_WALLET
+}
+
+
+void KHTMLPart::saveToWallet(const TQString& key, const TQMap<TQString,TQString>& data)
+{
+#ifndef KHTML_NO_WALLET
+ KHTMLPart *p;
+
+ for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
+ }
+
+ if (p) {
+ p->saveToWallet(key, data);
+ return;
+ }
+
+ if (d->m_wallet) {
+ if (d->m_bWalletOpened) {
+ if (d->m_wallet->isOpen()) {
+ if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
+ d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
+ }
+ d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
+ d->m_wallet->writeMap(key, data);
+ return;
+ }
+ d->m_wallet->deleteLater();
+ d->m_wallet = 0L;
+ d->m_bWalletOpened = false;
+ }
+ }
+
+ if (!d->m_wq) {
+ KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
+ d->m_wq = new KHTMLWalletQueue(this);
+ d->m_wq->wallet = wallet;
+ connect(wallet, TQT_SIGNAL(walletOpened(bool)), d->m_wq, TQT_SLOT(walletOpened(bool)));
+ connect(d->m_wq, TQT_SIGNAL(walletOpened(KWallet::Wallet*)), this, TQT_SLOT(walletOpened(KWallet::Wallet*)));
+ }
+ d->m_wq->savers.append(qMakePair(key, data));
+#endif // KHTML_NO_WALLET
+}
+
+
+void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
+#ifndef KHTML_NO_WALLET
+ KHTMLPart *p;
+
+ for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
+ }
+
+ if (p) {
+ p->dequeueWallet(form);
+ return;
+ }
+
+ if (d->m_wq) {
+ d->m_wq->callers.remove(KHTMLWalletQueue::Caller(form, form->getDocument()));
+ }
+#endif // KHTML_NO_WALLET
+}
+
+
+void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
+#ifndef KHTML_NO_WALLET
+ assert(!d->m_wallet);
+ assert(d->m_wq);
+
+ d->m_wq->deleteLater(); // safe?
+ d->m_wq = 0L;
+
+ if (!wallet) {
+ d->m_bWalletOpened = false;
+ return;
+ }
+
+ d->m_wallet = wallet;
+ d->m_bWalletOpened = true;
+ connect(d->m_wallet, TQT_SIGNAL(walletClosed()), TQT_SLOT(slotWalletClosed()));
+
+ if (!d->m_statusBarWalletLabel) {
+ d->m_statusBarWalletLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
+ d->m_statusBarWalletLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
+ d->m_statusBarWalletLabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ d->m_statusBarWalletLabel->setUseCursor(false);
+ d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
+ d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet_open", instance()));
+ connect(d->m_statusBarWalletLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(launchWalletManager()));
+ connect(d->m_statusBarWalletLabel, TQT_SIGNAL(rightClickedURL()), TQT_SLOT(walletMenu()));
+ } else {
+ TQToolTip::remove(d->m_statusBarWalletLabel);
+ }
+ TQToolTip::add(d->m_statusBarWalletLabel, i18n("The wallet '%1' is open and being used for form data and passwords.").arg(KWallet::Wallet::NetworkWallet()));
+#endif // KHTML_NO_WALLET
+}
+
+
+KWallet::Wallet *KHTMLPart::wallet()
+{
+#ifndef KHTML_NO_WALLET
+ KHTMLPart *p;
+
+ for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
+ ;
+
+ if (p)
+ return p->wallet();
+
+#endif // KHTML_NO_WALLET
+ return d->m_wallet;
+}
+
+
+void KHTMLPart::slotWalletClosed()
+{
+#ifndef KHTML_NO_WALLET
+ if (d->m_wallet) {
+ d->m_wallet->deleteLater();
+ d->m_wallet = 0L;
+ }
+ d->m_bWalletOpened = false;
+ if (d->m_statusBarWalletLabel) {
+ d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
+ delete d->m_statusBarWalletLabel;
+ d->m_statusBarWalletLabel = 0L;
+ }
+#endif // KHTML_NO_WALLET
+}
+
+void KHTMLPart::launchWalletManager()
+{
+#ifndef KHTML_NO_WALLET
+ if (!DCOPClient::mainClient()->isApplicationRegistered("tdewalletmanager")) {
+ TDEApplication::startServiceByDesktopName("tdewalletmanager_show");
+ } else {
+ DCOPRef r("tdewalletmanager", "tdewalletmanager-mainwindow#1");
+ r.send("show");
+ r.send("raise");
+ }
+#endif // KHTML_NO_WALLET
+}
+
+void KHTMLPart::walletMenu()
+{
+#ifndef KHTML_NO_WALLET
+ KPopupMenu *m = new KPopupMenu(0L);
+ m->insertItem(i18n("&Close Wallet"), this, TQT_SLOT(slotWalletClosed()));
+ m->popup(TQCursor::pos());
+#endif // KHTML_NO_WALLET
+}
+
+void KHTMLPart::slotToggleCaretMode()
+{
+ setCaretMode(d->m_paToggleCaretMode->isChecked());
+}
+
+void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
+ d->m_formNotification = fn;
+}
+
+KHTMLPart::FormNotification KHTMLPart::formNotification() const {
+ return d->m_formNotification;
+}
+
+KURL KHTMLPart::toplevelURL()
+{
+ KHTMLPart* part = this;
+ while (part->parentPart())
+ part = part->parentPart();
+
+ if (!part)
+ return KURL();
+
+ return part->url();
+}
+
+bool KHTMLPart::isModified() const
+{
+ if ( !d->m_doc )
+ return false;
+
+ return d->m_doc->unsubmittedFormChanges();
+}
+
+void KHTMLPart::setDebugScript( bool enable )
+{
+ unplugActionList( "debugScriptList" );
+ if ( enable ) {
+ if (!d->m_paDebugScript) {
+ d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), 0, this, TQT_SLOT( slotDebugScript() ), actionCollection(), "debugScript" );
+ }
+ d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
+ TQPtrList<KAction> lst;
+ lst.append( d->m_paDebugScript );
+ plugActionList( "debugScriptList", lst );
+ }
+ d->m_bJScriptDebugEnabled = enable;
+}
+
+void KHTMLPart::setSuppressedPopupIndicator( bool enable )
+{
+ setSuppressedPopupIndicator( enable, 0 );
+}
+
+void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
+{
+ if ( parentPart() ) {
+ parentPart()->setSuppressedPopupIndicator( enable, originPart );
+ return;
+ }
+
+ if ( enable && originPart ) {
+ d->m_openableSuppressedPopups++;
+ if ( d->m_suppressedPopupOriginParts.findIndex( originPart ) == -1 )
+ d->m_suppressedPopupOriginParts.append( originPart );
+ }
+
+ if ( enable && !d->m_statusBarPopupLabel ) {
+ d->m_statusBarPopupLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
+ d->m_statusBarPopupLabel->setFixedHeight( instance()->iconLoader()->currentSize( KIcon::Small) );
+ d->m_statusBarPopupLabel->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ));
+ d->m_statusBarPopupLabel->setUseCursor( false );
+ d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
+ d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window_suppressed", instance() ) );
+ TQToolTip::add( d->m_statusBarPopupLabel, i18n("This page was prevented from opening a new window via JavaScript." ) );
+
+ connect(d->m_statusBarPopupLabel, TQT_SIGNAL(leftClickedURL()), TQT_SLOT(suppressedPopupMenu()));
+ if (d->m_settings->jsPopupBlockerPassivePopup()) {
+ TQPixmap px;
+ px = MainBarIcon( "window_suppressed" );
+ KPassivePopup::message(i18n("Popup Window Blocked"),i18n("This page has attempted to open a popup window but was blocked.\nYou can click on this icon in the status bar to control this behavior\nor to open the popup."),px,d->m_statusBarPopupLabel);
+ }
+ } else if ( !enable && d->m_statusBarPopupLabel ) {
+ TQToolTip::remove( d->m_statusBarPopupLabel );
+ d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
+ delete d->m_statusBarPopupLabel;
+ d->m_statusBarPopupLabel = 0L;
+ }
+}
+
+void KHTMLPart::suppressedPopupMenu() {
+ KPopupMenu *m = new KPopupMenu(0L);
+ m->setCheckable(true);
+ if ( d->m_openableSuppressedPopups )
+ m->insertItem(i18n("&Show Blocked Popup Window","Show %n Blocked Popup Windows", d->m_openableSuppressedPopups), this, TQT_SLOT(showSuppressedPopups()));
+ m->insertItem(i18n("Show Blocked Window Passive Popup &Notification"), this, TQT_SLOT(togglePopupPassivePopup()),0,57);
+ m->setItemChecked(57,d->m_settings->jsPopupBlockerPassivePopup());
+ m->insertItem(i18n("&Configure JavaScript New Window Policies..."), this, TQT_SLOT(launchJSConfigDialog()));
+ m->popup(TQCursor::pos());
+}
+
+void KHTMLPart::togglePopupPassivePopup() {
+ // Same hack as in disableJSErrorExtension()
+ d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
+ DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQByteArray());
+}
+
+void KHTMLPart::showSuppressedPopups() {
+ for ( TQValueListIterator<TQGuardedPtr<KHTMLPart> > i = d->m_suppressedPopupOriginParts.begin();
+ i != d->m_suppressedPopupOriginParts.end(); ++i ) {
+ if (KHTMLPart* part = *i) {
+ KJS::Window *w = KJS::Window::retrieveWindow( part );
+ if (w) {
+ w->showSuppressedWindows();
+ w->forgetSuppressedWindows();
+ }
+ }
+ }
+ setSuppressedPopupIndicator( false );
+ d->m_openableSuppressedPopups = 0;
+ d->m_suppressedPopupOriginParts.clear();
+}
+
+// Extension to use for "view document source", "save as" etc.
+// Using the right extension can help the viewer get into the right mode (#40496)
+TQString KHTMLPart::defaultExtension() const
+{
+ if ( !d->m_doc )
+ return ".html";
+ if ( !d->m_doc->isHTMLDocument() )
+ return ".xml";
+ return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
+}
+
+bool KHTMLPart::inProgress() const
+{
+ if (d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
+ return true;
+
+ // Any frame that hasn't completed yet ?
+ ConstFrameIt it = d->m_frames.begin();
+ const ConstFrameIt end = d->m_frames.end();
+ for (; it != end; ++it ) {
+ if ((*it)->m_run || !(*it)->m_bCompleted)
+ return true;
+ }
+
+ return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
+}
+
+using namespace KParts;
+#include "tdehtml_part.moc"
+#include "tdehtmlpart_p.moc"
diff --git a/tdehtml/tdehtml_part.h b/tdehtml/tdehtml_part.h
new file mode 100644
index 000000000..e4e20c03c
--- /dev/null
+++ b/tdehtml/tdehtml_part.h
@@ -0,0 +1,1683 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999-2001 Lars Knoll <knoll@kde.org>
+ * 1999-2001 Antti Koivisto <koivisto@kde.org>
+ * 2000-2001 Simon Hausmann <hausmann@kde.org>
+ * 2000-2001 Dirk Mueller <mueller@kde.org>
+ * 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.
+ */
+#ifndef __tdehtml_part_h__
+#define __tdehtml_part_h__
+
+#include "dom/html_document.h"
+#include "dom/dom2_range.h"
+
+#include <tdeparts/part.h>
+#include <tdeparts/browserextension.h>
+#include <kdemacros.h>
+#include <kfinddialog.h>
+
+#include <tqregexp.h>
+
+class KHTMLPartPrivate;
+class KHTMLPartBrowserExtension;
+class KJSProxy;
+class KHTMLView;
+class KHTMLSettings;
+class KJavaAppletContext;
+class KJSErrorDlg;
+
+namespace DOM
+{
+ class HTMLDocument;
+ class HTMLDocumentImpl;
+ class DocumentImpl;
+ class HTMLTitleElementImpl;
+ class HTMLElementImpl;
+ class HTMLFrameElementImpl;
+ class HTMLIFrameElementImpl;
+ class HTMLObjectElementImpl;
+ class HTMLFormElementImpl;
+ class HTMLAnchorElementImpl;
+ class HTMLMetaElementImpl;
+ class NodeImpl;
+ class Node;
+ class HTMLEventListener;
+ class EventListener;
+}
+
+namespace KJS
+{
+ class Interpreter;
+}
+
+namespace tdehtml
+{
+ class DocLoader;
+ class RenderPart;
+ class RenderPartObject;
+ class ChildFrame;
+ class MouseEvent;
+ class MousePressEvent;
+ class MouseDoubleClickEvent;
+ class MouseMoveEvent;
+ class MouseReleaseEvent;
+ class DrawContentsEvent;
+ class CachedObject;
+ class RenderWidget;
+ class CSSStyleSelector;
+ class HTMLTokenizer;
+ class Decoder;
+ class XMLTokenizer;
+}
+
+namespace KJS {
+ class Window;
+ class WindowFunc;
+ class ExternalFunc;
+ class JSEventListener;
+ class JSLazyEventListener;
+ class JSNodeFilter;
+ class DOMDocument;
+ class SourceFile;
+ class ScheduledAction;
+}
+
+namespace KParts
+{
+ class PartManager;
+ class LiveConnectExtension;
+}
+
+namespace KWallet
+{
+ class Wallet;
+}
+
+/**
+ * This class is tdehtml's main class. It features an almost complete
+ * web browser, and html renderer.
+ *
+ * The easiest way to use this class (if you just want to display an HTML
+ * page at some URL) is the following:
+ *
+ * \code
+ * KURL url = "http://www.kde.org";
+ * KHTMLPart *w = new KHTMLPart();
+ * w->openURL(url);
+ * w->view()->resize(500, 400);
+ * w->show();
+ * \endcode
+ *
+ * Java and JavaScript are enabled by default depending on the user's
+ * settings. If you do not need them, and especially if you display
+ * unfiltered data from untrusted sources, it is strongly recommended to
+ * turn them off. In that case, you should also turn off the automatic
+ * redirect and plugins:
+ *
+ * \code
+ * w->setJScriptEnabled(false);
+ * w->setJavaEnabled(false);
+ * w->setMetaRefreshEnabled(false);
+ * w->setPluginsEnabled(false);
+ * \endcode
+ *
+ * You may also wish to disable external references. This will prevent KHTML
+ * from loading images, frames, etc, or redirecting to external sites.
+ *
+ * \code
+ * w->setOnlyLocalReferences(true);
+ * \endcode
+ *
+ * Some apps want to write their HTML code directly into the widget instead of
+ * opening an url. You can do this in the following way:
+ *
+ * \code
+ * TQString myHTMLCode = ...;
+ * KHTMLPart *w = new KHTMLPart();
+ * w->begin();
+ * w->write(myHTMLCode);
+ * ...
+ * w->end();
+ * \endcode
+ *
+ * You can do as many calls to write() as you wish. There are two
+ * write() methods, one accepting a TQString and one accepting a
+ * @p char @p * argument. You should use one or the other
+ * (but not both) since the method using
+ * the @p char @p * argument does an additional decoding step to convert the
+ * written data to Unicode.
+ *
+ * It is also possible to write content to the HTML part using the
+ * standard streaming API from KParts::ReadOnlyPart. The usage of
+ * the API is similar to that of the begin(), write(), end() process
+ * described above as the following example shows:
+ *
+ * \code
+ * KHTMLPart *doc = new KHTMLPart();
+ * doc->openStream( "text/html", KURL() );
+ * doc->writeStream( TQCString( "<html><body><p>KHTML Rocks!</p></body></html>" ) );
+ * doc->closeStream();
+ * \endcode
+ *
+ * @short HTML Browser Widget
+ * @author Lars Knoll (knoll@kde.org)
+ *
+ */
+class KHTML_EXPORT KHTMLPart : public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+ friend class KHTMLView;
+ friend class DOM::HTMLTitleElementImpl;
+ friend class DOM::HTMLFrameElementImpl;
+ friend class DOM::HTMLIFrameElementImpl;
+ friend class DOM::HTMLObjectElementImpl;
+ friend class DOM::HTMLAnchorElementImpl;
+ friend class DOM::HTMLMetaElementImpl;
+ friend class DOM::NodeImpl;
+ friend class KHTMLRun;
+ friend class DOM::HTMLFormElementImpl;
+ friend class tdehtml::RenderPartObject;
+ friend class KJS::Window;
+ friend class KJS::ScheduledAction;
+ friend class KJS::JSNodeFilter;
+ friend class KJS::WindowFunc;
+ friend class KJS::ExternalFunc;
+ friend class KJS::JSEventListener;
+ friend class KJS::JSLazyEventListener;
+ friend class KJS::DOMDocument;
+ friend class KJS::SourceFile;
+ friend class KJSProxy;
+ friend class KHTMLPartBrowserExtension;
+ friend class DOM::DocumentImpl;
+ friend class DOM::HTMLDocumentImpl;
+ friend class KHTMLPartBrowserHostExtension;
+ friend class tdehtml::HTMLTokenizer;
+ friend class tdehtml::XMLTokenizer;
+ friend class tdehtml::RenderWidget;
+ friend class tdehtml::CSSStyleSelector;
+ friend class KHTMLPartIface;
+ friend class KHTMLPartFunction;
+ friend class KHTMLPopupGUIClient;
+
+ TQ_PROPERTY( bool javaScriptEnabled READ jScriptEnabled WRITE setJScriptEnabled )
+ TQ_PROPERTY( bool javaEnabled READ javaEnabled WRITE setJavaEnabled )
+ TQ_PROPERTY( bool autoloadImages READ autoloadImages WRITE setAutoloadImages )
+ TQ_PROPERTY( bool dndEnabled READ dndEnabled WRITE setDNDEnabled )
+ TQ_PROPERTY( bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled )
+
+ /*
+ *
+ * Don't add setOnlyLocalReferences here. It shouldn't be accessible via DCOP.
+ *
+ **/
+ TQ_PROPERTY( TQCString dcopObjectId READ dcopObjectId )
+ TQ_PROPERTY( bool modified READ isModified )
+
+public:
+ enum GUIProfile { DefaultGUI, BrowserViewGUI /* ... */ };
+
+ /**
+ * Constructs a new KHTMLPart.
+ *
+ * KHTML basically consists of two objects: The KHTMLPart itself,
+ * holding the document data (DOM document), and the KHTMLView,
+ * derived from TQScrollView, in which the document content is
+ * rendered in. You can specify two different parent objects for a
+ * KHTMLPart, one parent for the KHTMLPart document and on parent
+ * for the KHTMLView. If the second @p parent argument is 0L, then
+ * @p parentWidget is used as parent for both objects, the part and
+ * the view.
+ */
+ KHTMLPart( TQWidget *parentWidget = 0, const char *widgetname = 0,
+ TQObject *parent = 0, const char *name = 0, GUIProfile prof = DefaultGUI );
+
+ KHTMLPart( KHTMLView *view, TQObject *parent = 0, const char *name = 0, GUIProfile prof = DefaultGUI );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KHTMLPart();
+
+ /**
+ * Opens the specified URL @p url.
+ *
+ * Reimplemented from KParts::ReadOnlyPart::openURL .
+ */
+ virtual bool openURL( const KURL &url );
+
+ /**
+ * Stops loading the document and kills all data requests (for images, etc.)
+ */
+ virtual bool closeURL();
+
+ /**
+ * Called when a certain error situation (i.e. connection timed out) occurred.
+ * The default implementation either shows a KIO error dialog or loads a more
+ * verbose error description a as page, depending on the users configuration.
+ * @p job is the job that signaled the error situation
+ */
+ virtual void showError( TDEIO::Job* job );
+
+ /**
+ * Returns a reference to the DOM HTML document (for non-HTML documents, returns null)
+ */
+ DOM::HTMLDocument htmlDocument() const;
+
+ /**
+ * Returns a reference to the DOM document.
+ */
+ DOM::Document document() const;
+
+ /**
+ * Returns the content of the source document.
+ * @since 3.4
+ */
+ TQString documentSource() const;
+
+ /**
+ * Returns the node that has the keyboard focus.
+ */
+ DOM::Node activeNode() const;
+
+ /**
+ * Returns a pointer to the KParts::BrowserExtension.
+ */
+ KParts::BrowserExtension *browserExtension() const;
+ KParts::LiveConnectExtension *liveConnectExtension( const tdehtml::RenderPart *) const;
+ KParts::BrowserHostExtension *browserHostExtension() const;
+
+ /**
+ * Returns a pointer to the HTML document's view.
+ */
+ KHTMLView *view() const;
+
+ /**
+ * Enable/disable Javascript support. Note that this will
+ * in either case permanently override the default usersetting.
+ * If you want to have the default UserSettings, don't call this
+ * method.
+ */
+ void setJScriptEnabled( bool enable );
+
+ /**
+ * Returns @p true if Javascript support is enabled or @p false
+ * otherwise.
+ */
+ bool jScriptEnabled() const;
+
+ /**
+ * Returns the JavaScript interpreter the part is using. This method is
+ * mainly intended for applications which embed and extend the part and
+ * provides a mechanism for adding additional native objects to the
+ * interpreter (or removing the built-ins).
+ *
+ * One thing people using this method to add things to the interpreter must
+ * consider, is that when you start writing new content to the part, the
+ * interpreter is cleared. This includes both use of the
+ * begin( const KURL &, int, int ) method, and the openURL( const KURL & )
+ * method. If you want your objects to have a longer lifespan, then you must
+ * retain a KJS::Object yourself to ensure that the reference count of your
+ * custom objects never reaches 0. You will also need to re-add your
+ * bindings everytime this happens - one way to detect the need for this is
+ * to connect to the docCreated() signal, another is to reimplement the
+ * begin() method.
+ */
+ KJS::Interpreter *jScriptInterpreter();
+
+ /**
+ * Enable/disable statusbar messages.
+ * When this class wants to set the statusbar text, it emits
+ * setStatusBarText(const TQString & text)
+ * If you want to catch this for your own statusbar, note that it returns
+ * back a rich text string, starting with "<qt>". This you need to
+ * either pass this into your own TQLabel or to strip out the tags
+ * before passing it to TQStatusBar::message(const TQString & message)
+ *
+ * @see KParts::Part::setStatusBarText( const TQString & text )
+ */
+ void setStatusMessagesEnabled( bool enable );
+
+ /**
+ * Returns @p true if status messages are enabled.
+ */
+ bool statusMessagesEnabled() const;
+
+ /**
+ * Enable/disable automatic forwarding by &lt;meta http-equiv="refresh" ....&gt;
+ */
+ void setMetaRefreshEnabled( bool enable );
+
+ /**
+ * Returns @p true if automatic forwarding is enabled.
+ */
+ bool metaRefreshEnabled() const;
+
+ /**
+ * Same as executeScript( const TQString & ) except with the Node parameter
+ * specifying the 'this' value.
+ */
+ TQVariant executeScript( const DOM::Node &n, const TQString &script );
+
+ /**
+ * Enables or disables Drag'n'Drop support. A drag operation is started if
+ * the users drags a link.
+ */
+ void setDNDEnabled( bool b );
+
+ /**
+ * Returns whether Dragn'n'Drop support is enabled or not.
+ */
+ bool dndEnabled() const;
+
+ /**
+ * Enables/disables Java applet support. Note that calling this function
+ * will permanently override the User settings about Java applet support.
+ * Not calling this function is the only way to let the default settings
+ * apply.
+ */
+ void setJavaEnabled( bool enable );
+
+ /**
+ * Return true if Java applet support is enabled, false if disabled
+ */
+ bool javaEnabled() const;
+
+ /**
+ * Returns the java context of the applets. If no applet exists, 0 is returned.
+ */
+ KJavaAppletContext *javaContext();
+
+ /**
+ * Returns the java context of the applets. If no context exists yet, a
+ * new one is created.
+ */
+ KJavaAppletContext *createJavaContext();
+
+ /**
+ * Enables or disables plugins, default is enabled
+ */
+ void setPluginsEnabled( bool enable );
+
+ /**
+ * Returns true if plugins are enabled/disabled.
+ */
+ bool pluginsEnabled() const;
+
+ /**
+ * Specifies whether images contained in the document should be loaded
+ * automatically or not.
+ *
+ * @note Request will be ignored if called before begin().
+ */
+ void setAutoloadImages( bool enable );
+ /**
+ * Returns whether images contained in the document are loaded automatically
+ * or not.
+ * @note that the returned information is unrelieable as long as no begin()
+ * was called.
+ */
+ bool autoloadImages() const;
+
+ /**
+ * Security option.
+ *
+ * Specify whether only file:/ or data:/ urls are allowed to be loaded without
+ * user confirmation by KHTML.
+ * ( for example referenced by stylesheets, images, scripts, subdocuments, embedded elements ).
+ *
+ * This option is mainly intended for enabling the "mail reader mode", where you load untrusted
+ * content with a file:/ url.
+ *
+ * Please note that enabling this option currently automatically disables Javascript,
+ * Java and Plugins support. This might change in the future if the security model
+ * is becoming more sophisticated, so don't rely on this behaviour.
+ *
+ * ( default false - everything is loaded unless forbidden by TDEApplication::authorizeURLAction).
+ */
+ void setOnlyLocalReferences( bool enable );
+
+ /**
+ * Returns whether only file:/ or data:/ references are allowed
+ * to be loaded ( default false ). See setOnlyLocalReferences.
+ **/
+ bool onlyLocalReferences() const;
+
+ /** Returns whether caret mode is on/off.
+ * @since 3.2
+ */
+ bool isCaretMode() const;
+
+ /**
+ * Returns @p true if the document is editable, @p false otherwise.
+ * @since 3.2
+ */
+ bool isEditable() const;
+
+ /**
+ * Sets the caret to the given position.
+ *
+ * If the given location is invalid, it will snap to the nearest valid
+ * location. Immediately afterwards a @p caretPositionChanged signal
+ * containing the effective position is emitted
+ * @param node node to set to
+ * @param offset zero-based offset within the node
+ * @param extendSelection If @p true, a selection will be spanned from the
+ * last caret position to the given one. Otherwise, any existing selection
+ * will be deselected.
+ * @since 3.2
+ */
+ void setCaretPosition(DOM::Node node, long offset, bool extendSelection = false);
+
+ /**
+ * Enumeration for displaying the caret.
+ * @param Visible caret is displayed
+ * @param Invisible caret is not displayed
+ * @param Blink caret toggles between visible and invisible
+ * @since 3.2
+ */
+ enum CaretDisplayPolicy {
+ CaretVisible, CaretInvisible, CaretBlink
+ };
+
+ /**
+ * Returns the current caret policy when the view is not focused.
+ * @since 3.2
+ */
+ CaretDisplayPolicy caretDisplayPolicyNonFocused() const;
+
+ /**
+ * Sets the caret display policy when the view is not focused.
+ *
+ * Whenever the caret is in use, this property determines how the
+ * caret should be displayed when the document view is not focused.
+ *
+ * The default policy is CaretInvisible.
+ * @param policy new display policy
+ * @since 3.2
+ */
+ void setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy);
+
+#ifndef KDE_NO_COMPAT
+ void enableJScript( bool e ) { setJScriptEnabled(e); }
+ void enableJava( bool e ) { setJavaEnabled(e); }
+ void enablePlugins( bool e ) { setPluginsEnabled(e); }
+ void autoloadImages( bool e ) { setAutoloadImages(e); }
+ void enableMetaRefresh( bool e ) { setMetaRefreshEnabled(e); }
+ bool setCharset( const TQString &, bool ) { return true; }
+
+ KURL baseURL() const;
+ TQString baseTarget() const;
+#endif
+
+ /**
+ * Returns the URL for the background Image (used by save background)
+ */
+ KURL backgroundURL() const;
+
+ /**
+ * Schedules a redirection after @p delay seconds.
+ */
+ void scheduleRedirection( int delay, const TQString &url, bool lockHistory = true );
+
+ /**
+ * Clears the widget and prepares it for new content.
+ *
+ * If you want url() to return
+ * for example "file:/tmp/test.html", you can use the following code:
+ * \code
+ * view->begin( KURL("file:/tmp/test.html" ) );
+ * \endcode
+ *
+ * @param url is the url of the document to be displayed. Even if you
+ * are generating the HTML on the fly, it may be useful to specify
+ * a directory so that any pixmaps are found.
+ *
+ * @param xOffset is the initial horizontal scrollbar value. Usually
+ * you don't want to use this.
+ *
+ * @param yOffset is the initial vertical scrollbar value. Usually
+ * you don't want to use this.
+ *
+ * All child frames and the old document are removed if you call
+ * this method.
+ */
+ virtual void begin( const KURL &url = KURL(), int xOffset = 0, int yOffset = 0 );
+
+ /**
+ * Writes another part of the HTML code to the widget.
+ *
+ * You may call
+ * this function many times in sequence. But remember: The fewer calls
+ * you make, the faster the widget will be.
+ *
+ * The HTML code is send through a decoder which decodes the stream to
+ * Unicode.
+ *
+ * The @p len parameter is needed for streams encoded in utf-16,
+ * since these can have \\0 chars in them. In case the encoding
+ * you're using isn't utf-16, you can safely leave out the length
+ * parameter.
+ *
+ * Attention: Don't mix calls to write( const char *) with calls
+ * to write( const TQString & ).
+ *
+ * The result might not be what you want.
+ */
+ virtual void write( const char *str, int len = -1 );
+
+ /**
+ * Writes another part of the HTML code to the widget.
+ *
+ * You may call
+ * this function many times in sequence. But remember: The fewer calls
+ * you make, the faster the widget will be.
+ */
+ virtual void write( const TQString &str );
+
+ /**
+ * Call this after your last call to write().
+ */
+ virtual void end();
+
+ /*
+ * Prints the current HTML page laid out for the printer.
+ *
+ * (not implemented at the moment)
+ */
+ // void print(TQPainter *, int pageHeight, int pageWidth);
+
+ /**
+ * Paints the HTML page to a TQPainter. See KHTMLView::paint for details
+ */
+ void paint( TQPainter *, const TQRect &, int = 0, bool * = 0 );
+
+ /**
+ * Sets the encoding the page uses.
+ *
+ * This can be different from the charset. The widget will try to reload the current page in the new
+ * encoding, if url() is not empty.
+ */
+ bool setEncoding( const TQString &name, bool override = false );
+
+ /**
+ * Returns the encoding the page currently uses.
+ *
+ * Note that the encoding might be different from the charset.
+ */
+ TQString encoding() const;
+
+ /**
+ * Sets a user defined style sheet to be used on top of the HTML 4
+ * default style sheet.
+ *
+ * This gives a wide range of possibilities to
+ * change the layout of the page.
+ *
+ * To have an effect this function has to be called after calling begin().
+ */
+ void setUserStyleSheet( const KURL &url );
+
+ /**
+ * Sets a user defined style sheet to be used on top of the HTML 4
+ * default style sheet.
+ *
+ * This gives a wide range of possibilities to
+ * change the layout of the page.
+ *
+ * To have an effect this function has to be called after calling begin().
+ */
+ void setUserStyleSheet( const TQString &styleSheet );
+
+public:
+
+ /**
+ * Sets the standard font style.
+ *
+ * @param name The font name to use for standard text.
+ */
+ void setStandardFont( const TQString &name );
+
+ /**
+ * Sets the fixed font style.
+ *
+ * @param name The font name to use for fixed text, e.g.
+ * the <tt>&lt;pre&gt;</tt> tag.
+ */
+ void setFixedFont( const TQString &name );
+
+ /**
+ * Finds the anchor named @p name.
+ *
+ * If the anchor is found, the widget
+ * scrolls to the closest position. Returns @p if the anchor has
+ * been found.
+ */
+ bool gotoAnchor( const TQString &name );
+
+ /**
+ * Go to the next anchor
+ *
+ * This is useful to navigate from outside the navigator
+ * @since 3.2
+ */
+ bool nextAnchor();
+
+ /**
+ * Go to previous anchor
+ * @since 3.2
+ */
+ bool prevAnchor();
+
+ /**
+ * Sets the cursor to use when the cursor is on a link.
+ */
+ void setURLCursor( const TQCursor &c );
+
+ /**
+ * Returns the cursor which is used when the cursor is on a link.
+ */
+ TQCursor urlCursor() const;
+
+ /**
+ * Extra Find options that can be used when calling the extended findText().
+ * @since 3.3
+ */
+ enum FindOptions
+ {
+ FindLinksOnly = 1 * KFindDialog::MinimumUserOption,
+ FindNoPopups = 2 * KFindDialog::MinimumUserOption
+ //FindIncremental = 4 * KFindDialog::MinimumUserOption
+ };
+
+ /**
+ * Starts a new search by popping up a dialog asking the user what he wants to
+ * search for.
+ * @since 3.3
+ */
+ void findText();
+
+ /**
+ * Starts a new search, but bypasses the user dialog.
+ * @param str The string to search for.
+ * @param options Find options.
+ * @param parent Parent used for centering popups like "string not found".
+ * @param findDialog Optionally, you can supply your own dialog.
+ * @since 3.3
+ */
+ void findText( const TQString &str, long options, TQWidget *parent = 0,
+ KFindDialog *findDialog = 0 );
+
+ /**
+ * Initiates a text search.
+ */
+ void findTextBegin();
+
+ /**
+ * Finds the next occurrence of the string or expression.
+ * If isRegExp is true then str is converted to a TQRegExp, and caseSensitive is ignored.
+ * @deprecated, use findText( str, options, parent, findDialog )
+ */
+ bool findTextNext( const TQString &str, bool forward, bool caseSensitive, bool isRegExp );
+
+ /**
+ * Finds the next occurence of a string set by @ref findText()
+ * @return true if a new match was found.
+ * @since 3.3
+ */
+ bool findTextNext();
+
+ /**
+ * Finds the next occurence of a string set by @ref findText()
+ * @param reverse if true, revert seach direction (only if no find dialog is used)
+ * @return true if a new match was found.
+ * @since 3.5
+ */
+ // KDE4 merge with default = false
+ bool findTextNext( bool reverse );
+
+ /**
+ * Sets the Zoom factor. The value is given in percent, larger values mean a
+ * generally larger font and larger page contents. It is not guaranteed that
+ * all parts of the page are scaled with the same factor though.
+ *
+ * The given value should be in the range of 20..300, values outside that
+ * range are not guaranteed to work. A value of 100 will disable all zooming
+ * and show the page with the sizes determined via the given lengths in the
+ * stylesheets.
+ */
+ void setZoomFactor(int percent);
+
+ /**
+ * Returns the current zoom factor.
+ */
+ int zoomFactor() const;
+
+ /**
+ * Returns the text the user has marked.
+ */
+ virtual TQString selectedText() const;
+
+ /**
+ * Return the text the user has marked. This is guaranteed to be valid xml,
+ * and to contain the \<html> and \<body> tags.
+ *
+ * FIXME probably should make virtual for 4.0 ?
+ *
+ * @since 3.4
+ */
+ TQString selectedTextAsHTML() const;
+
+ /**
+ * Returns the selected part of the HTML.
+ */
+ DOM::Range selection() const;
+
+ /**
+ * Returns the selected part of the HTML by returning the starting and end
+ * position.
+ *
+ * If there is no selection, both nodes and offsets are equal.
+ * @param startNode returns node selection starts in
+ * @param startOffset returns offset within starting node
+ * @param endNode returns node selection ends in
+ * @param endOffset returns offset within end node.
+ * @since 3.2
+ */
+ void selection(DOM::Node &startNode, long &startOffset,
+ DOM::Node &endNode, long &endOffset) const;
+
+ /**
+ * Sets the current selection.
+ */
+ void setSelection( const DOM::Range & );
+
+ /**
+ * Has the user selected anything?
+ *
+ * Call selectedText() to
+ * retrieve the selected text.
+ *
+ * @return @p true if there is text selected.
+ */
+ bool hasSelection() const;
+
+ /**
+ * Marks all text in the document as selected.
+ */
+ void selectAll();
+
+ /**
+ * Convenience method to show the document's view.
+ *
+ * Equivalent to widget()->show() or view()->show() .
+ */
+ void show();
+
+ /**
+ * Convenience method to hide the document's view.
+ *
+ * Equivalent to widget()->hide() or view()->hide().
+ */
+ void hide();
+
+ /**
+ * Returns a reference to the partmanager instance which
+ * manages html frame objects.
+ */
+ KParts::PartManager *partManager();
+
+ /**
+ * Saves the KHTMLPart's complete state (including child frame
+ * objects) to the provided TQDataStream.
+ *
+ * This is called from the saveState() method of the
+ * browserExtension().
+ */
+ virtual void saveState( TQDataStream &stream );
+ /**
+ * Restores the KHTMLPart's previously saved state (including
+ * child frame objects) from the provided TQDataStream.
+ *
+ * @see saveState()
+ *
+ * This is called from the restoreState() method of the
+ * browserExtension() .
+ **/
+ virtual void restoreState( TQDataStream &stream );
+
+ /**
+ * Returns the @p Node currently under the mouse.
+ *
+ * The returned node may be a shared node (e. g. an \<area> node if the
+ * mouse is hovering over an image map).
+ */
+ DOM::Node nodeUnderMouse() const;
+
+ /**
+ * Returns the @p Node currently under the mouse that is not shared.
+ *
+ * The returned node is always the node that is physically under the mouse
+ * pointer (irrespective of logically overlying elements like, e. g.,
+ * \<area> on image maps).
+ * @since 3.3
+ */
+ DOM::Node nonSharedNodeUnderMouse() const;
+
+ /**
+ * @internal
+ */
+ const KHTMLSettings *settings() const;
+
+ /**
+ * Returns a pointer to the parent KHTMLPart if the part is a frame
+ * in an HTML frameset.
+ *
+ * Returns 0L otherwise.
+ */
+ KHTMLPart *parentPart();
+
+ /**
+ * Returns a list of names of all frame (including iframe) objects of
+ * the current document. Note that this method is not working recursively
+ * for sub-frames.
+ */
+ TQStringList frameNames() const;
+
+ TQPtrList<KParts::ReadOnlyPart> frames() const;
+
+ /**
+ * Finds a frame by name. Returns 0L if frame can't be found.
+ */
+ KHTMLPart *findFrame( const TQString &f );
+
+ /**
+ * Recursively finds the part containing the frame with name @p f
+ * and checks if it is accessible by @p callingPart
+ * Returns 0L if no suitable frame can't be found.
+ * Returns parent part if a suitable frame was found and
+ * frame info in @p *childFrame
+ * @since 3.3
+ */
+ KHTMLPart *findFrameParent( KParts::ReadOnlyPart *callingPart, const TQString &f, tdehtml::ChildFrame **childFrame=0 );
+
+ /**
+ * Return the current frame (the one that has focus)
+ * Not necessarily a direct child of ours, framesets can be nested.
+ * Returns "this" if this part isn't a frameset.
+ */
+ KParts::ReadOnlyPart *currentFrame() const;
+
+ /**
+ * Returns whether a frame with the specified name is exists or not.
+ * In contrary to the findFrame method this one also returns true
+ * if the frame is defined but no displaying component has been
+ * found/loaded, yet.
+ */
+ bool frameExists( const TQString &frameName );
+
+ /**
+ * Returns child frame framePart its script interpreter
+ */
+ KJSProxy *framejScript(KParts::ReadOnlyPart *framePart);
+
+ /**
+ * Finds a frame by name. Returns 0L if frame can't be found.
+ */
+ KParts::ReadOnlyPart *findFramePart( const TQString &f );
+ /**
+ * Called by KJS.
+ * Sets the StatusBarText assigned
+ * via window.status
+ */
+ void setJSStatusBarText( const TQString &text );
+
+ /**
+ * Called by KJS.
+ * Sets the DefaultStatusBarText assigned
+ * via window.defaultStatus
+ */
+ void setJSDefaultStatusBarText( const TQString &text );
+
+ /**
+ * Called by KJS.
+ * Returns the StatusBarText assigned
+ * via window.status
+ */
+ TQString jsStatusBarText() const;
+
+ /**
+ * Called by KJS.
+ * Returns the DefaultStatusBarText assigned
+ * via window.defaultStatus
+ */
+ TQString jsDefaultStatusBarText() const;
+
+ /**
+ * Referrer used for links in this page.
+ */
+ TQString referrer() const;
+
+ /**
+ * Referrer used to obtain this page.
+ */
+ TQString pageReferrer() const;
+
+ /**
+ * Last-modified date (in raw string format), if received in the [HTTP] headers.
+ */
+ TQString lastModified() const;
+
+ /**
+ * Loads a style sheet into the stylesheet cache.
+ */
+ void preloadStyleSheet( const TQString &url, const TQString &stylesheet );
+
+ /**
+ * Loads a script into the script cache.
+ */
+ void preloadScript( const TQString &url, const TQString &script );
+
+ /**
+ * @internal
+ */
+ bool restored() const;
+
+ // ### KDE4 remove me
+ enum FormNotification { NoNotification = 0, Before, Only, Unused=255 };
+ /**
+ * Determine if signal should be emitted before, instead or never when a
+ * submitForm() happens.
+ * @since 3.2
+ * ### KDE4 remove me
+ */
+ void setFormNotification(FormNotification fn);
+
+ /**
+ * Determine if signal should be emitted before, instead or never when a
+ * submitForm() happens.
+ * ### KDE4 remove me
+ * @since 3.2
+ */
+ FormNotification formNotification() const;
+
+ /**
+ * Returns the toplevel (origin) URL of this document, even if this
+ * part is a frame or an iframe.
+ *
+ * @return the actual original url.
+ * @since 3.2
+ */
+ KURL toplevelURL();
+
+ /**
+ * Checks whether the page contains unsubmitted form changes.
+ *
+ * @return true if form changes exist
+ * @since 3.3
+ */
+ bool isModified() const;
+
+ /**
+ * Shows or hides the suppressed popup indicator
+ * @deprecated
+ * @since 3.4
+ */
+ void setSuppressedPopupIndicator( bool enable );
+
+ /**
+ * Shows or hides the suppressed popup indicator
+ * @since 3.5
+ */
+ void setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart );
+
+ /**
+ * @internal
+ * @since 3.5
+ */
+ bool inProgress() const;
+
+signals:
+ /**
+ * Emitted if the cursor is moved over an URL.
+ */
+ void onURL( const TQString &url );
+
+ /**
+ * Emitted when the user clicks the right mouse button on the document.
+ */
+ void popupMenu( const TQString &url, const TQPoint &point );
+
+ /**
+ * This signal is emitted when the selection changes.
+ */
+ void selectionChanged();
+
+ /**
+ * This signal is emitted when an element retrieves the
+ * keyboard focus. Note that the signal argument can be
+ * a null node if no element is active, meaning a node
+ * has explicitly been deactivated without a new one
+ * becoming active.
+ */
+ void nodeActivated( const DOM::Node & );
+
+ /**
+ * @internal */
+ void docCreated();
+
+ /**
+ * This signal is emitted whenever the caret position has been changed.
+ *
+ * The signal transmits the position the DOM::Range way, the node and
+ * the zero-based offset within this node.
+ * @param node node which the caret is in. This can be null if the caret
+ * has been deactivated.
+ * @param offset offset within the node. If the node is null, the offset
+ * is meaningless.
+ * @since 3.2
+ */
+ void caretPositionChanged(const DOM::Node &node, long offset);
+
+
+ /**
+ * If form notification is on, this will be emitted either for a form
+ * submit or before the form submit according to the setting.
+ * @since 3.2
+ * ### KDE4 remove me
+ */
+ void formSubmitNotification(const char *action, const TQString& url,
+ const TQByteArray& formData, const TQString& target,
+ const TQString& contentType, const TQString& boundary);
+
+
+protected:
+
+ /**
+ * returns a KURL object for the given url. Use when
+ * you know what you're doing.
+ */
+ KURL completeURL( const TQString &url );
+
+ /**
+ * presents a detailed error message to the user.
+ * @p errorCode kio error code, eg TDEIO::ERR_SERVER_TIMEOUT.
+ * @p text kio additional information text.
+ * @p url the url that triggered the error.
+ */
+ void htmlError( int errorCode, const TQString& text, const KURL& reqUrl );
+
+ virtual void customEvent( TQCustomEvent *event );
+
+ /**
+ * Eventhandler of the tdehtml::MousePressEvent.
+ */
+ virtual void tdehtmlMousePressEvent( tdehtml::MousePressEvent *event );
+ /**
+ * Eventhandler for the tdehtml::MouseDoubleClickEvent.
+ */
+ virtual void tdehtmlMouseDoubleClickEvent( tdehtml::MouseDoubleClickEvent * );
+ /**
+ * Eventhandler for the tdehtml::MouseMouseMoveEvent.
+ */
+ virtual void tdehtmlMouseMoveEvent( tdehtml::MouseMoveEvent *event );
+ /**
+ * Eventhandler for the tdehtml::MouseMouseReleaseEvent.
+ */
+ virtual void tdehtmlMouseReleaseEvent( tdehtml::MouseReleaseEvent *event );
+ /**
+ * Eventhandler for the tdehtml::DrawContentsEvent.
+ */
+ virtual void tdehtmlDrawContentsEvent( tdehtml::DrawContentsEvent * );
+
+ /**
+ * Internal reimplementation of KParts::Part::guiActivateEvent .
+ */
+ virtual void guiActivateEvent( KParts::GUIActivateEvent *event );
+
+ /**
+ * Internal empty reimplementation of KParts::ReadOnlyPart::openFile .
+ */
+ virtual bool openFile();
+
+ virtual void urlSelected( const TQString &url, int button, int state,
+ const TQString &_target, KParts::URLArgs args = KParts::URLArgs());
+
+ /**
+ * This method is called when a new embedded object (include html frames) is to be created.
+ * Reimplement it if you want to add support for certain embeddable objects without registering
+ * them in the KDE wide registry system (KSyCoCa) . Another reason for re-implementing this
+ * method could be if you want to derive from KTHMLPart and also want all html frame objects
+ * to be a object of your derived type, in which case you should return a new instance for
+ * the mimetype 'text/html' .
+ */
+ virtual KParts::ReadOnlyPart *createPart( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name,
+ const TQString &mimetype, TQString &serviceName,
+ TQStringList &serviceTypes, const TQStringList &params);
+
+ // This is for RenderPartObject. We want to ask the 'download plugin?'
+ // question only once per mimetype
+ bool pluginPageQuestionAsked( const TQString& mimetype ) const;
+ void setPluginPageQuestionAsked( const TQString& mimetype );
+
+ enum PageSecurity { NotCrypted, Encrypted, Mixed };
+ void setPageSecurity( PageSecurity sec );
+
+ /**
+ * Implements the streaming API of KParts::ReadOnlyPart.
+ */
+ virtual bool doOpenStream( const TQString& mimeType );
+
+ /**
+ * Implements the streaming API of KParts::ReadOnlyPart.
+ */
+ virtual bool doWriteStream( const TQByteArray& data );
+
+ /**
+ * Implements the streaming API of KParts::ReadOnlyPart.
+ */
+ virtual bool doCloseStream();
+
+public slots:
+
+ /**
+ * Sets the focused node of the document to the specified node. If the node is a form control, the control will
+ * receive focus in the same way that it would if the user had clicked on it or tabbed to it with the keyboard. For
+ * most other types of elements, there is no visual indication of whether or not they are focused.
+ *
+ * See activeNode
+ *
+ * @param node The node to focus
+ */
+ void setActiveNode( const DOM::Node &node );
+
+ /**
+ * Stops all animated images on the current and child pages
+ */
+ void stopAnimations();
+
+ TQCString dcopObjectId() const;
+
+ /**
+ * Execute the specified snippet of JavaScript code.
+ *
+ * Returns @p true if JavaScript was enabled, no error occurred
+ * and the code returned true itself or @p false otherwise.
+ * @deprecated, use executeString( DOM::Node(), script)
+ */
+ TQVariant executeScript( const TQString &script );
+
+ /**
+ * Enables/disables caret mode.
+ *
+ * Enabling caret mode displays a caret which can be used to navigate
+ * the document using the keyboard only. Caret mode is switched off by
+ * default.
+ *
+ * @param enable @p true to enable, @p false to disable caret mode.
+ * @since 3.2
+ */
+ void setCaretMode(bool enable);
+
+ /**
+ * Makes the document editable.
+ *
+ * Setting this property to @p true makes the document, and its
+ * subdocuments (such as frames, iframes, objects) editable as a whole.
+ * FIXME: insert more information about navigation, features etc. as seen fit
+ *
+ * @param enable @p true to set document editable, @p false to set it
+ * read-only.
+ * @since 3.2 (pending, do not use)
+ */
+ void setEditable(bool enable);
+
+ /**
+ * Sets the visibility of the caret.
+ *
+ * This methods displays or hides the caret regardless of the current
+ * caret display policy (see setCaretDisplayNonFocused), and regardless
+ * of focus.
+ *
+ * The caret will be shown/hidden only under at least one of
+ * the following conditions:
+ * @li the document is editable
+ * @li the document is in caret mode
+ * @li the document's currently focused element is editable
+ *
+ * @param show @p true to make visible, @p false to hide.
+ * @since 3.2
+ */
+ void setCaretVisible(bool show);
+
+ // ### KDE4 FIXME:
+ // Remove this and make the one below protected+virtual slot.
+ // Warning: this is effectively "internal". Be careful.
+ // @since 3.2
+ void submitFormProxy( const char *action, const TQString &url,
+ const TQByteArray &formData,
+ const TQString &target,
+ const TQString& contentType = TQString::null,
+ const TQString& boundary = TQString::null );
+
+private slots:
+
+ /**
+ * @internal
+ */
+ void reparseConfiguration();
+
+ /**
+ * @internal
+ */
+ void slotData( TDEIO::Job*, const TQByteArray &data );
+ /**
+ * @internal
+ */
+ void slotInfoMessage( TDEIO::Job*, const TQString& msg );
+ /**
+ * @internal
+ */
+ void slotRestoreData( const TQByteArray &data );
+ /**
+ * @internal
+ */
+ void slotFinished( TDEIO::Job* );
+ /**
+ * @internal
+ */
+ void slotFinishedParsing();
+ /**
+ * @internal
+ */
+ void slotRedirect();
+ /**
+ * @internal
+ */
+ void slotRedirection( TDEIO::Job*, const KURL& );
+ /**
+ * @internal
+ */
+ void slotDebugScript();
+ /**
+ * @internal
+ */
+ void slotDebugDOMTree();
+ /**
+ * @internal
+ */
+ void slotDebugRenderTree();
+ /**
+ * @internal
+ */
+ void slotStopAnimations();
+ /**
+ * @internal
+ */
+ virtual void slotViewDocumentSource();
+ /**
+ * @internal
+ */
+ virtual void slotViewFrameSource();
+ /**
+ * @internal
+ */
+ void slotViewPageInfo();
+ /**
+ * @internal
+ */
+ virtual void slotSaveBackground();
+ /**
+ * @internal
+ */
+ virtual void slotSaveDocument();
+ /**
+ * @internal
+ */
+ virtual void slotSaveFrame();
+ /**
+ * @internal
+ */
+ virtual void slotSecurity();
+ /**
+ * @internal
+ */
+ virtual void slotSetEncoding();
+
+ /**
+ * @internal
+ */
+ virtual void slotUseStylesheet();
+
+ virtual void slotFind();
+ virtual void slotFindDone(); // ### remove me
+ virtual void slotFindDialogDestroyed();
+ void slotFindNext();
+ void slotFindPrev();
+ void slotFindAheadText();
+ void slotFindAheadLink();
+
+ void slotIncZoom();
+ void slotDecZoom();
+ void slotIncZoomFast();
+ void slotDecZoomFast();
+
+ void slotLoadImages();
+ void slotWalletClosed();
+ void launchWalletManager();
+ void walletMenu();
+
+ /**
+ * @internal
+ */
+ void submitFormAgain();
+
+ /**
+ * @internal
+ */
+ void updateActions();
+ /**
+ * @internal
+ */
+ void slotPartRemoved( KParts::Part *part );
+ /**
+ * @internal
+ */
+ void slotActiveFrameChanged( KParts::Part *part );
+ /**
+ * @internal
+ */
+ void slotChildStarted( TDEIO::Job *job );
+ /**
+ * @internal
+ */
+ void slotChildCompleted();
+ /**
+ * @internal
+ */
+ void slotChildCompleted( bool );
+ /**
+ * @internal
+ */
+ void slotParentCompleted();
+ /**
+ * @internal
+ */
+ void slotChildURLRequest( const KURL &url, const KParts::URLArgs &args );
+ /**
+ * @internal
+ */
+ void slotChildDocCreated();
+ /**
+ * @internal
+ */
+ void slotRequestFocus( KParts::ReadOnlyPart * );
+ void slotLoaderRequestStarted( tdehtml::DocLoader*, tdehtml::CachedObject* obj);
+ void slotLoaderRequestDone( tdehtml::DocLoader*, tdehtml::CachedObject *obj );
+ void checkCompleted();
+
+ /**
+ * @internal
+ */
+ void slotAutoScroll();
+
+ void slotPrintFrame();
+
+ void slotSelectAll();
+
+ /**
+ * @internal
+ */
+ void slotProgressUpdate();
+
+ /*
+ * @internal
+ */
+ void slotJobPercent( TDEIO::Job*, unsigned long );
+
+ /*
+ * @internal
+ */
+ void slotJobDone( TDEIO::Job* );
+
+ /*
+ * @internal
+ */
+ void slotUserSheetStatDone( TDEIO::Job* );
+
+ /*
+ * @internal
+ */
+ void slotJobSpeed( TDEIO::Job*, unsigned long );
+
+ /**
+ * @internal
+ */
+ void slotClearSelection();
+
+ /**
+ * @internal
+ */
+ void slotZoomView( int );
+
+ /**
+ * @internal
+ */
+ void slotHighlight( const TQString &, int index, int length );
+
+ /**
+ * @internal
+ */
+ void slotAutomaticDetectionLanguage( int _id );
+
+ /**
+ * @internal
+ */
+ void slotToggleCaretMode();
+
+ /**
+ * @internal
+ */
+ void suppressedPopupMenu();
+
+ /**
+ * @internal
+ */
+ void togglePopupPassivePopup();
+
+ /**
+ * @internal
+ */
+ void showSuppressedPopups();
+
+ /**
+ * @internal
+ */
+ void launchJSConfigDialog();
+
+ /**
+ * @internal
+ */
+ void launchJSErrorDialog();
+
+ /**
+ * @internal
+ */
+ void removeJSErrorExtension();
+
+ /**
+ * @internal
+ */
+ void disableJSErrorExtension();
+
+ /**
+ * @internal
+ */
+ void jsErrorDialogContextMenu();
+
+ /**
+ * @internal
+ * used to restore or reset the view's scroll position (including positioning on anchors)
+ * once a sufficient portion of the document as been laid out.
+ */
+ void restoreScrollPosition();
+
+ void walletOpened(KWallet::Wallet*);
+
+private:
+
+ KJSErrorDlg *jsErrorExtension();
+
+ enum StatusBarPriority { BarDefaultText, BarHoverText, BarOverrideText };
+ void setStatusBarText( const TQString& text, StatusBarPriority p);
+
+ bool restoreURL( const KURL &url );
+ void resetFromScript();
+ void emitSelectionChanged();
+ // Returns whether callingHtmlPart may access this part
+ bool checkFrameAccess(KHTMLPart *callingHtmlPart);
+ bool openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs );
+ bool urlSelectedIntern( const TQString &url, int button, int state,
+ const TQString &_target, KParts::URLArgs args = KParts::URLArgs());
+ void startAutoScroll();
+ void stopAutoScroll();
+ void overURL( const TQString &url, const TQString &target, bool shiftPressed = false );
+ void resetHoverText(); // Undo overURL and reset HoverText
+
+ bool processObjectRequest( tdehtml::ChildFrame *child, const KURL &url, const TQString &mimetype );
+
+ KWallet::Wallet* wallet();
+
+ void openWallet(DOM::HTMLFormElementImpl*);
+ void saveToWallet(const TQString& key, const TQMap<TQString,TQString>& data);
+ void dequeueWallet(DOM::HTMLFormElementImpl*);
+
+ void enableFindAheadActions(bool);
+
+ /**
+ * @internal
+ */
+ // ### KDE4 FIXME:
+ // It is desirable to be able to filter form submissions as well.
+ // For instance, forms can have a target and an inheriting class
+ // might want to filter based on the target. Make this protected
+ // and virtual, or provide a better solution.
+ // See the web_module for the sidebar for an example where this is
+ // necessary.
+ void submitForm( const char *action, const TQString &url, const TQByteArray &formData,
+ const TQString &target, const TQString& contentType = TQString::null,
+ const TQString& boundary = TQString::null );
+
+ void popupMenu( const TQString &url );
+
+ void init( KHTMLView *view, GUIProfile prof );
+
+
+ void clear();
+
+ bool scheduleScript( const DOM::Node &n, const TQString& script);
+
+ TQVariant crossFrameExecuteScript(const TQString& target, const TQString& script);
+ TQVariant executeScheduledScript();
+
+ bool requestFrame( tdehtml::RenderPart *frame, const TQString &url, const TQString &frameName,
+ const TQStringList &args = TQStringList(), bool isIFrame = false );
+
+ /**
+ * @internal returns a name for a frame without a name.
+ * This function returns a sequence of names.
+ * All names in a sequence are different but the sequence is
+ * always the same.
+ * The sequence is reset in clear().
+ */
+ TQString requestFrameName();
+
+ bool requestObject( tdehtml::RenderPart *frame, const TQString &url, const TQString &serviceType,
+ const TQStringList &args = TQStringList() );
+
+ bool requestObject( tdehtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &args = KParts::URLArgs() );
+
+ DOM::EventListener *createHTMLEventListener( TQString code, TQString name, DOM::NodeImpl *node );
+
+ DOM::HTMLDocumentImpl *docImpl() const;
+ DOM::DocumentImpl *xmlDocImpl() const;
+ tdehtml::ChildFrame *frame( const TQObject *obj );
+
+ tdehtml::ChildFrame *recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KURL &url, const KParts::URLArgs &args, bool callParent = true );
+
+ bool checkLinkSecurity( const KURL &linkURL,const TQString &message = TQString::null, const TQString &button = TQString::null );
+ TQVariant executeScript( const TQString& filename, int baseLine, const DOM::Node &n, const TQString& script );
+
+ KJSProxy *jScript();
+
+ KHTMLPart *opener();
+ long cacheId() const;
+ void setOpener( KHTMLPart *_opener );
+ bool openedByJS();
+ void setOpenedByJS( bool _openedByJS );
+
+ void checkEmitLoadEvent();
+ void emitLoadEvent();
+
+ bool initFindNode( bool selection, bool reverse, bool fromCursor );
+
+ void extendSelection( DOM::NodeImpl* node, long offset, DOM::Node& selectionNode, long& selectionOffset, bool right, bool paragraph );
+ /** extends the current selection to the given content-coordinates @p x, @p y
+ * @param x content x-coordinate
+ * @param y content y-coordinate
+ * @param absX absolute x-coordinate of @p innerNode
+ * @param absY absolute y-coordinate of @p innerNode
+ * @param innerNode node from which to start extending the selection. The
+ * caller has to ensure that the node has a renderer.
+ * @internal
+ */
+ void extendSelectionTo(int x, int y, int absX, int absY, const DOM::Node &innerNode);
+ /** checks whether a selection is extended.
+ * @return @p true if a selection is extended by the mouse.
+ */
+ bool isExtendingSelection() const;
+ tdehtml::Decoder *createDecoder();
+ TQString defaultEncoding() const;
+
+ /** .html, .xhtml or .xml */
+ TQString defaultExtension() const;
+
+ /** @internal
+ * generic zoom in
+ */
+ void zoomIn(const int stepping[], int count);
+ /** @internal
+ * generic zoom out
+ */
+ void zoomOut(const int stepping[], int count);
+
+ void emitCaretPositionChanged(const DOM::Node &node, long offset);
+
+ void setDebugScript( bool enable );
+
+ void runAdFilter();
+
+ KHTMLPartPrivate *d;
+ friend class KHTMLPartPrivate;
+};
+
+
+#endif
diff --git a/tdehtml/tdehtml_popupmenu.rc b/tdehtml/tdehtml_popupmenu.rc
new file mode 100644
index 000000000..0570313d2
--- /dev/null
+++ b/tdehtml/tdehtml_popupmenu.rc
@@ -0,0 +1,39 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"><kpartgui name="tdehtmlpart_popupmenu" version="14">
+<Menu name="popupmenu">
+ <Action name="copy" group="editactions"/>
+ <Action name="selectAll" group="editactions"/>
+ <Action name="searchProvider" group="editactions"/>
+ <Action name="searchProviderList" group="editactions"/>
+ <Action name="openSelection" group="editactions"/>
+ <Separator weakSeparator="1" group="editactions"/>
+ <Action name="savelinkas" group="linkactions"/>
+ <Action name="copylinklocation" group="linkactions"/>
+ <Menu name="frame"><text>Frame</text>
+ <Action name="frameinwindow"/>
+ <Action name="frameintop"/>
+ <Action name="frameintab"/>
+ <Separator weakSeparator="1" />
+ <Action name="reloadframe"/>
+ <Action name="printFrame"/>
+ <Action name="saveFrame"/>
+ <Action name="viewFrameSource" />
+ <Action name="viewFrameInfo" />
+ <Separator weakSeparator="1" />
+ <Action name="blockiframe" />
+ </Menu>
+ <Separator weakSeparator="1" />
+ <Action name="saveimageas" />
+ <Action name="sendimage" />
+ <Action name="copyimage" />
+ <Action name="copyimagelocation" />
+ <Action name="viewimage" />
+ <Action name="blockimage" />
+ <Action name="blockhost" />
+ <Separator weakSeparator="1" />
+ <Action name="stopanimations" />
+ <Separator weakSeparator="1" />
+ <Action name="viewDocumentSource" />
+ <Action name="security" />
+ <Action name="setEncoding" />
+</Menu>
+</kpartgui>
diff --git a/tdehtml/tdehtml_printsettings.cpp b/tdehtml/tdehtml_printsettings.cpp
new file mode 100644
index 000000000..41b87244a
--- /dev/null
+++ b/tdehtml/tdehtml_printsettings.cpp
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2002 Michael Goffioul <tdeprint@swing.be>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 "tdehtml_printsettings.h"
+
+#include <klocale.h>
+#include <tqcheckbox.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+KHTMLPrintSettings::KHTMLPrintSettings(TQWidget *parent, const char *name)
+: KPrintDialogPage(parent, name)
+{
+ //WhatsThis strings.... (added by pfeifle@kde.org)
+ TQString whatsThisPrintImages = i18n( "<qt>"
+ "<p><strong>'Print images'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, images contained in the HTML page will "
+ "be printed. Printing may take longer and use more ink or toner."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, only the text of the HTML page will be "
+ "printed, without the included images. Printing will be faster and use "
+ "less ink or toner."
+ "</p>"
+ " </qt>" );
+ TQString whatsThisPrintHeader = i18n( "<qt>"
+ "<p><strong>'Print header'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, the printout of the HTML document will "
+ "contain a header line at the top of each page. This header contains "
+ "the current date, the location URL of the printed page and the page "
+ "number."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, the printout of the HTML document will "
+ "not contain such a header line."
+ "</p>"
+ " </qt>" );
+ TQString whatsThisPrinterFriendlyMode = i18n( "<qt>"
+ "<p><strong>'Printerfriendly mode'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, the printout of the HTML document will "
+ "be black and white only, and all colored background will be converted "
+ "into white. Printout will be faster and use less ink or toner."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, the printout of the HTML document will "
+ "happen in the original color settings as you see in your application. "
+ "This may result in areas of full-page color (or grayscale, if you use "
+ "a black+white printer). Printout will possibly happen slower and will "
+ "certainly use much more toner or ink."
+ "</p>"
+ " </qt>" );
+ setTitle(i18n("HTML Settings"));
+
+ m_printfriendly = new TQCheckBox(i18n("Printer friendly mode (black text, no background)"), this);
+ TQWhatsThis::add(m_printfriendly, whatsThisPrinterFriendlyMode);
+ m_printfriendly->setChecked(true);
+ m_printimages = new TQCheckBox(i18n("Print images"), this);
+ TQWhatsThis::add(m_printimages, whatsThisPrintImages);
+ m_printimages->setChecked(true);
+ m_printheader = new TQCheckBox(i18n("Print header"), this);
+ TQWhatsThis::add(m_printheader, whatsThisPrintHeader);
+ m_printheader->setChecked(true);
+
+ TQVBoxLayout *l0 = new TQVBoxLayout(this, 0, 10);
+ l0->addWidget(m_printfriendly);
+ l0->addWidget(m_printimages);
+ l0->addWidget(m_printheader);
+ l0->addStretch(1);
+}
+
+KHTMLPrintSettings::~KHTMLPrintSettings()
+{
+}
+
+void KHTMLPrintSettings::getOptions(TQMap<TQString,TQString>& opts, bool /*incldef*/)
+{
+ opts["app-tdehtml-printfriendly"] = (m_printfriendly->isChecked() ? "true" : "false");
+ opts["app-tdehtml-printimages"] = (m_printimages->isChecked() ? "true" : "false");
+ opts["app-tdehtml-printheader"] = (m_printheader->isChecked() ? "true" : "false");
+}
+
+void KHTMLPrintSettings::setOptions(const TQMap<TQString,TQString>& opts)
+{
+ m_printfriendly->setChecked(opts["app-tdehtml-printfriendly"] != "false");
+ m_printimages->setChecked(opts["app-tdehtml-printimages"] != "false");
+ m_printheader->setChecked(opts["app-tdehtml-printheader"] != "false");
+}
+
+#include "tdehtml_printsettings.moc"
diff --git a/tdehtml/tdehtml_printsettings.h b/tdehtml/tdehtml_printsettings.h
new file mode 100644
index 000000000..9f69d9b88
--- /dev/null
+++ b/tdehtml/tdehtml_printsettings.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2002 Michael Goffioul <tdeprint@swing.be>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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 KHTML_PRINTSETTINGS_H
+#define KHTML_PRINTSETTINGS_H
+
+#include <tdeprint/kprintdialogpage.h>
+
+class TQCheckBox;
+
+class KHTMLPrintSettings : public KPrintDialogPage
+{
+ Q_OBJECT
+public:
+ KHTMLPrintSettings(TQWidget *parent = 0, const char *name = 0);
+ ~KHTMLPrintSettings();
+
+ void getOptions(TQMap<TQString,TQString>& opts, bool incldef = false);
+ void setOptions(const TQMap<TQString,TQString>& opts);
+
+private:
+ TQCheckBox *m_printfriendly;
+ TQCheckBox *m_printimages;
+ TQCheckBox *m_printheader;
+};
+
+#endif
diff --git a/tdehtml/tdehtml_run.cpp b/tdehtml/tdehtml_run.cpp
new file mode 100644
index 000000000..e1c34915a
--- /dev/null
+++ b/tdehtml/tdehtml_run.cpp
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999 Lars Knoll <knoll@kde.org>
+ * 1999 Antti Koivisto <koivisto@kde.org>
+ * 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.
+ */
+#include "tdehtmlpart_p.h"
+#include "tdehtml_run.h"
+#include <kio/job.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include "tdehtml_ext.h"
+#include <tqwidget.h>
+
+KHTMLRun::KHTMLRun( KHTMLPart *part, tdehtml::ChildFrame *child, const KURL &url,
+ const KParts::URLArgs &args, bool hideErrorDialog )
+ : KParts::BrowserRun( url, args, part, part->widget() ? part->widget()->topLevelWidget() : 0,
+ false, false, hideErrorDialog ),
+ m_child( child )
+{
+ // Don't use an external browser for parts of a webpage we are rendering. (iframes at least are one example)
+ setEnableExternalBrowser(false);
+
+ // get the wheel to start spinning
+ part->started(0L);
+}
+
+//KHTMLPart *KHTMLRun::htmlPart() const
+//{ return static_cast<KHTMLPart *>(m_part); }
+
+void KHTMLRun::foundMimeType( const TQString &_type )
+{
+ Q_ASSERT(!m_bFinished);
+ TQString mimeType = _type; // this ref comes from the job, we lose it when using KIO again
+ if ( static_cast<KHTMLPart *>(m_part)->processObjectRequest( m_child, m_strURL, mimeType ) )
+ m_bFinished = true;
+ else {
+ if ( m_bFinished ) // abort was called (this happens with the activex fallback for instance)
+ return;
+ // Couldn't embed -> call BrowserRun::handleNonEmbeddable()
+ KParts::BrowserRun::NonEmbeddableResult res = handleNonEmbeddable( mimeType );
+ if ( res == KParts::BrowserRun::Delayed )
+ return;
+ m_bFinished = ( res == KParts::BrowserRun::Handled );
+ if ( m_bFinished ) { // saved or canceled -> flag completed
+ m_child->m_bCompleted = true;
+ static_cast<KHTMLPart *>(m_part)->checkCompleted();
+ }
+ }
+
+ if ( m_bFinished )
+ {
+ m_timer.start( 0, true );
+ return;
+ }
+
+ //kdDebug(6050) << "KHTMLRun::foundMimeType " << _type << " couldn't open" << endl;
+ KRun::foundMimeType( mimeType );
+
+ // "open" is finished -> flag completed
+ m_child->m_bCompleted = true;
+ static_cast<KHTMLPart *>(m_part)->checkCompleted();
+}
+
+void KHTMLRun::save( const KURL & url, const TQString & suggestedFilename )
+{
+ KHTMLPopupGUIClient::saveURL( m_part->widget(), i18n( "Save As" ), url, m_args.metaData(), TQString::null, 0, suggestedFilename );
+}
+
+// KDE4: remove
+void KHTMLRun::handleError( TDEIO::Job *job )
+{
+ KParts::BrowserRun::handleError( job );
+}
+
+#include "tdehtml_run.moc"
diff --git a/tdehtml/tdehtml_run.h b/tdehtml/tdehtml_run.h
new file mode 100644
index 000000000..e549f9b2d
--- /dev/null
+++ b/tdehtml/tdehtml_run.h
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999 Lars Knoll <knoll@kde.org>
+ * 1999 Antti Koivisto <koivisto@kde.org>
+ * 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 __tdehtml_run_h__
+#define __tdehtml_run_h__
+
+#include <tdeparts/browserrun.h>
+#include <kurl.h>
+#include <kservice.h>
+#include <tdeparts/browserextension.h>
+
+class KHTMLPart;
+
+namespace tdehtml
+{
+ class ChildFrame;
+}
+
+class KHTMLRun : public KParts::BrowserRun
+{
+ Q_OBJECT
+public:
+ KHTMLRun( KHTMLPart *part, tdehtml::ChildFrame *child, const KURL &url,
+ const KParts::URLArgs &args, bool hideErrorDialog );
+
+ virtual void foundMimeType( const TQString &mimetype );
+
+ //KHTMLPart *htmlPart() const;
+
+protected:
+ virtual void handleError( TDEIO::Job * job );
+
+ virtual void save( const KURL & url, const TQString & suggestedFilename );
+ bool askSave( const KURL & url, KService::Ptr offer, const TQString & mimeType, const TQString & suggestedFilename );
+
+private:
+ tdehtml::ChildFrame *m_child;
+};
+
+#endif
diff --git a/tdehtml/tdehtml_settings.cc b/tdehtml/tdehtml_settings.cc
new file mode 100644
index 000000000..4d65aa99b
--- /dev/null
+++ b/tdehtml/tdehtml_settings.cc
@@ -0,0 +1,1064 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 David Faure <faure@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 <tqfontdatabase.h>
+
+#include "tdehtml_settings.h"
+#include "tdehtmldefaults.h"
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <tqregexp.h>
+#include <tqvaluevector.h>
+#include <kmessagebox.h>
+
+/**
+ * @internal
+ * Contains all settings which are both available globally and per-domain
+ */
+struct KPerDomainSettings {
+ bool m_bEnableJava : 1;
+ bool m_bEnableJavaScript : 1;
+ bool m_bEnablePlugins : 1;
+ // don't forget to maintain the bitfields as the enums grow
+ KHTMLSettings::KJSWindowOpenPolicy m_windowOpenPolicy : 2;
+ KHTMLSettings::KJSWindowStatusPolicy m_windowStatusPolicy : 1;
+ KHTMLSettings::KJSWindowFocusPolicy m_windowFocusPolicy : 1;
+ KHTMLSettings::KJSWindowMovePolicy m_windowMovePolicy : 1;
+ KHTMLSettings::KJSWindowResizePolicy m_windowResizePolicy : 1;
+
+#ifdef DEBUG_SETTINGS
+ void dump(const TQString &infix = TQString::null) const {
+ kdDebug() << "KPerDomainSettings " << infix << " @" << this << ":" << endl;
+ kdDebug() << " m_bEnableJava: " << m_bEnableJava << endl;
+ kdDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript << endl;
+ kdDebug() << " m_bEnablePlugins: " << m_bEnablePlugins << endl;
+ kdDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy << endl;
+ kdDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy << endl;
+ kdDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy << endl;
+ kdDebug() << " m_windowMovePolicy: " << m_windowMovePolicy << endl;
+ kdDebug() << " m_windowResizePolicy: " << m_windowResizePolicy << endl;
+ }
+#endif
+};
+
+typedef TQMap<TQString,KPerDomainSettings> PolicyMap;
+
+class KHTMLSettingsPrivate
+{
+public:
+ bool m_bChangeCursor : 1;
+ bool m_bOpenMiddleClick : 1;
+ bool m_bBackRightClick : 1;
+ bool m_underlineLink : 1;
+ bool m_hoverLink : 1;
+ bool m_bEnableJavaScriptDebug : 1;
+ bool m_bEnableJavaScriptErrorReporting : 1;
+ bool enforceCharset : 1;
+ bool m_bAutoLoadImages : 1;
+ bool m_bUnfinishedImageFrame : 1;
+ bool m_formCompletionEnabled : 1;
+ bool m_autoDelayedActionsEnabled : 1;
+ bool m_jsErrorsEnabled : 1;
+ bool m_follow_system_colors : 1;
+ bool m_allowTabulation : 1;
+ bool m_autoSpellCheck : 1;
+ bool m_adFilterEnabled : 1;
+ bool m_hideAdsEnabled : 1;
+ bool m_jsPopupBlockerPassivePopup : 1;
+ bool m_accessKeysEnabled : 1;
+
+ // the virtual global "domain"
+ KPerDomainSettings global;
+
+ int m_fontSize;
+ int m_minFontSize;
+ int m_maxFormCompletionItems;
+ KHTMLSettings::KAnimationAdvice m_showAnimations;
+
+ TQString m_encoding;
+ TQString m_userSheet;
+
+ TQColor m_textColor;
+ TQColor m_baseColor;
+ TQColor m_linkColor;
+ TQColor m_vLinkColor;
+
+ PolicyMap domainPolicy;
+ TQStringList fonts;
+ TQStringList defaultFonts;
+
+ TQValueVector<TQRegExp> adFilters;
+ TQValueList< TQPair< TQString, TQChar > > m_fallbackAccessKeysAssignments;
+};
+
+
+/** Returns a writeable per-domains settings instance for the given domain
+ * or a deep copy of the global settings if not existent.
+ */
+static KPerDomainSettings &setup_per_domain_policy(
+ KHTMLSettingsPrivate *d,
+ const TQString &domain) {
+ if (domain.isEmpty()) {
+ kdWarning() << "setup_per_domain_policy: domain is empty" << endl;
+ }
+ const TQString ldomain = domain.lower();
+ PolicyMap::iterator it = d->domainPolicy.find(ldomain);
+ if (it == d->domainPolicy.end()) {
+ // simply copy global domain settings (they should have been initialized
+ // by this time)
+ it = d->domainPolicy.insert(ldomain,d->global);
+ }
+ return *it;
+}
+
+
+KHTMLSettings::KJavaScriptAdvice KHTMLSettings::strToAdvice(const TQString& _str)
+{
+ KJavaScriptAdvice ret = KJavaScriptDunno;
+
+ if (!_str)
+ ret = KJavaScriptDunno;
+
+ if (_str.lower() == TQString::fromLatin1("accept"))
+ ret = KJavaScriptAccept;
+ else if (_str.lower() == TQString::fromLatin1("reject"))
+ ret = KJavaScriptReject;
+
+ return ret;
+}
+
+const char* KHTMLSettings::adviceToStr(KJavaScriptAdvice _advice)
+{
+ switch( _advice ) {
+ case KJavaScriptAccept: return I18N_NOOP("Accept");
+ case KJavaScriptReject: return I18N_NOOP("Reject");
+ default: return 0;
+ }
+ return 0;
+}
+
+
+void KHTMLSettings::splitDomainAdvice(const TQString& configStr, TQString &domain,
+ KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice)
+{
+ TQString tmp(configStr);
+ int splitIndex = tmp.find(':');
+ if ( splitIndex == -1)
+ {
+ domain = configStr.lower();
+ javaAdvice = KJavaScriptDunno;
+ javaScriptAdvice = KJavaScriptDunno;
+ }
+ else
+ {
+ domain = tmp.left(splitIndex).lower();
+ TQString adviceString = tmp.mid( splitIndex+1, tmp.length() );
+ int splitIndex2 = adviceString.find( ':' );
+ if( splitIndex2 == -1 ) {
+ // Java advice only
+ javaAdvice = strToAdvice( adviceString );
+ javaScriptAdvice = KJavaScriptDunno;
+ } else {
+ // Java and JavaScript advice
+ javaAdvice = strToAdvice( adviceString.left( splitIndex2 ) );
+ javaScriptAdvice = strToAdvice( adviceString.mid( splitIndex2+1,
+ adviceString.length() ) );
+ }
+ }
+}
+
+void KHTMLSettings::readDomainSettings(TDEConfig *config, bool reset,
+ bool global, KPerDomainSettings &pd_settings) {
+ TQString jsPrefix = global ? TQString::null
+ : TQString::fromLatin1("javascript.");
+ TQString javaPrefix = global ? TQString::null
+ : TQString::fromLatin1("java.");
+ TQString pluginsPrefix = global ? TQString::null
+ : TQString::fromLatin1("plugins.");
+
+ // The setting for Java
+ TQString key = javaPrefix + TQString::fromLatin1("EnableJava");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_bEnableJava = config->readBoolEntry( key, false );
+ else if ( !global )
+ pd_settings.m_bEnableJava = d->global.m_bEnableJava;
+
+ // The setting for Plugins
+ key = pluginsPrefix + TQString::fromLatin1("EnablePlugins");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_bEnablePlugins = config->readBoolEntry( key, true );
+ else if ( !global )
+ pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins;
+
+ // The setting for JavaScript
+ key = jsPrefix + TQString::fromLatin1("EnableJavaScript");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_bEnableJavaScript = config->readBoolEntry( key, true );
+ else if ( !global )
+ pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript;
+
+ // window property policies
+ key = jsPrefix + TQString::fromLatin1("WindowOpenPolicy");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_windowOpenPolicy = (KJSWindowOpenPolicy)
+ config->readUnsignedNumEntry( key, KJSWindowOpenSmart );
+ else if ( !global )
+ pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy;
+
+ key = jsPrefix + TQString::fromLatin1("WindowMovePolicy");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_windowMovePolicy = (KJSWindowMovePolicy)
+ config->readUnsignedNumEntry( key, KJSWindowMoveAllow );
+ else if ( !global )
+ pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy;
+
+ key = jsPrefix + TQString::fromLatin1("WindowResizePolicy");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_windowResizePolicy = (KJSWindowResizePolicy)
+ config->readUnsignedNumEntry( key, KJSWindowResizeAllow );
+ else if ( !global )
+ pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy;
+
+ key = jsPrefix + TQString::fromLatin1("WindowStatusPolicy");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_windowStatusPolicy = (KJSWindowStatusPolicy)
+ config->readUnsignedNumEntry( key, KJSWindowStatusAllow );
+ else if ( !global )
+ pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy;
+
+ key = jsPrefix + TQString::fromLatin1("WindowFocusPolicy");
+ if ( (global && reset) || config->hasKey( key ) )
+ pd_settings.m_windowFocusPolicy = (KJSWindowFocusPolicy)
+ config->readUnsignedNumEntry( key, KJSWindowFocusAllow );
+ else if ( !global )
+ pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy;
+
+}
+
+
+KHTMLSettings::KHTMLSettings()
+{
+ d = new KHTMLSettingsPrivate();
+ init();
+}
+
+KHTMLSettings::KHTMLSettings(const KHTMLSettings &other)
+{
+ d = new KHTMLSettingsPrivate();
+ *d = *other.d;
+}
+
+KHTMLSettings::~KHTMLSettings()
+{
+ delete d;
+}
+
+bool KHTMLSettings::changeCursor() const
+{
+ return d->m_bChangeCursor;
+}
+
+bool KHTMLSettings::underlineLink() const
+{
+ return d->m_underlineLink;
+}
+
+bool KHTMLSettings::hoverLink() const
+{
+ return d->m_hoverLink;
+}
+
+void KHTMLSettings::init()
+{
+ TDEConfig global( "tdehtmlrc", true, false );
+ init( &global, true );
+
+ TDEConfig *local = TDEGlobal::config();
+ if ( !local )
+ return;
+
+ init( local, false );
+}
+
+void KHTMLSettings::init( TDEConfig * config, bool reset )
+{
+ TQString group_save = config->group();
+ if (reset || config->hasGroup("MainView Settings"))
+ {
+ config->setGroup( "MainView Settings" );
+
+ if ( reset || config->hasKey( "OpenMiddleClick" ) )
+ d->m_bOpenMiddleClick = config->readBoolEntry( "OpenMiddleClick", true );
+
+ if ( reset || config->hasKey( "BackRightClick" ) )
+ d->m_bBackRightClick = config->readBoolEntry( "BackRightClick", false );
+ }
+
+ if (reset || config->hasGroup("Access Keys")) {
+ config->setGroup( "Access Keys" );
+ d->m_accessKeysEnabled = config->readBoolEntry( "Enabled", true );
+ }
+
+ if (reset || config->hasGroup("Filter Settings"))
+ {
+ config->setGroup( "Filter Settings" );
+ d->m_adFilterEnabled = config->readBoolEntry("Enabled", false);
+ d->m_hideAdsEnabled = config->readBoolEntry("Shrink", false);
+
+ d->adFilters.clear();
+
+ TQMap<TQString,TQString> entryMap = config->entryMap("Filter Settings");
+ TQMap<TQString,TQString>::ConstIterator it;
+ d->adFilters.reserve(entryMap.count());
+ for( it = entryMap.constBegin(); it != entryMap.constEnd(); ++it )
+ {
+ TQString name = it.key();
+ TQString url = it.data();
+
+ if (url.startsWith("!"))
+ continue;
+
+ if (name.startsWith("Filter"))
+ {
+ if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/')
+ {
+ TQString inside = url.mid(1, url.length()-2);
+ TQRegExp rx(inside);
+ d->adFilters.append(rx);
+ }
+ else
+ {
+ TQRegExp rx;
+ int left,right;
+
+ for (right=url.length(); right>0 && url[right-1]=='*' ; --right);
+ for (left=0; left<right && url[left]=='*' ; ++left);
+
+ rx.setWildcard(true);
+ rx.setPattern(url.mid(left,right-left));
+
+ d->adFilters.append(rx);
+ }
+ }
+ }
+ }
+
+
+ if (reset || config->hasGroup("HTML Settings"))
+ {
+ config->setGroup( "HTML Settings" );
+ // Fonts and colors
+ if( reset ) {
+ d->defaultFonts = TQStringList();
+ d->defaultFonts.append( config->readEntry( "StandardFont", TDEGlobalSettings::generalFont().family() ) );
+ d->defaultFonts.append( config->readEntry( "FixedFont", TDEGlobalSettings::fixedFont().family() ) );
+ d->defaultFonts.append( config->readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) );
+ d->defaultFonts.append( config->readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) );
+ d->defaultFonts.append( config->readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) );
+ d->defaultFonts.append( config->readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) );
+ d->defaultFonts.append( TQString( "0" ) ); // font size adjustment
+ }
+
+ if ( reset || config->hasKey( "MinimumFontSize" ) )
+ d->m_minFontSize = config->readNumEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE );
+
+ if ( reset || config->hasKey( "MediumFontSize" ) )
+ d->m_fontSize = config->readNumEntry( "MediumFontSize", 12 );
+
+ d->fonts = config->readListEntry( "Fonts" );
+
+ if ( reset || config->hasKey( "DefaultEncoding" ) )
+ d->m_encoding = config->readEntry( "DefaultEncoding", "" );
+
+ if ( reset || config->hasKey( "EnforceDefaultCharset" ) )
+ d->enforceCharset = config->readBoolEntry( "EnforceDefaultCharset", false );
+
+ // Behavior
+ if ( reset || config->hasKey( "ChangeCursor" ) )
+ d->m_bChangeCursor = config->readBoolEntry( "ChangeCursor", KDE_DEFAULT_CHANGECURSOR );
+
+ if ( reset || config->hasKey("UnderlineLinks") )
+ d->m_underlineLink = config->readBoolEntry( "UnderlineLinks", true );
+
+ if ( reset || config->hasKey( "HoverLinks" ) )
+ {
+ if ( ( d->m_hoverLink = config->readBoolEntry( "HoverLinks", false ) ) )
+ d->m_underlineLink = false;
+ }
+
+ if ( reset || config->hasKey( "AllowTabulation" ) )
+ d->m_allowTabulation = config->readBoolEntry( "AllowTabulation", false );
+
+ if ( reset || config->hasKey( "AutoSpellCheck" ) )
+ d->m_autoSpellCheck = config->readBoolEntry( "AutoSpellCheck", true );
+
+ // Other
+ if ( reset || config->hasKey( "AutoLoadImages" ) )
+ d->m_bAutoLoadImages = config->readBoolEntry( "AutoLoadImages", true );
+
+ if ( reset || config->hasKey( "UnfinishedImageFrame" ) )
+ d->m_bUnfinishedImageFrame = config->readBoolEntry( "UnfinishedImageFrame", true );
+
+ if ( reset || config->hasKey( "ShowAnimations" ) )
+ {
+ TQString value = config->readEntry( "ShowAnimations").lower();
+ if (value == "disabled")
+ d->m_showAnimations = KAnimationDisabled;
+ else if (value == "looponce")
+ d->m_showAnimations = KAnimationLoopOnce;
+ else
+ d->m_showAnimations = KAnimationEnabled;
+ }
+
+ if ( config->readBoolEntry( "UserStyleSheetEnabled", false ) == true ) {
+ if ( reset || config->hasKey( "UserStyleSheet" ) )
+ d->m_userSheet = config->readEntry( "UserStyleSheet", "" );
+ }
+
+ d->m_formCompletionEnabled = config->readBoolEntry("FormCompletion", true);
+ d->m_maxFormCompletionItems = config->readNumEntry("MaxFormCompletionItems", 10);
+ d->m_autoDelayedActionsEnabled = config->readBoolEntry ("AutoDelayedActions", true);
+ d->m_jsErrorsEnabled = config->readBoolEntry("ReportJSErrors", true);
+ TQStringList accesskeys = config->readListEntry("FallbackAccessKeysAssignments");
+ d->m_fallbackAccessKeysAssignments.clear();
+ for( TQStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it )
+ if( (*it).length() > 2 && (*it)[ 1 ] == ':' )
+ d->m_fallbackAccessKeysAssignments.append( tqMakePair( (*it).mid( 2 ), (*it)[ 0 ] ));
+ }
+
+ // Colors
+
+ if ( reset || config->hasKey( "FollowSystemColors" ) )
+ d->m_follow_system_colors = config->readBoolEntry( "FollowSystemColors", false );
+
+ if ( reset || config->hasGroup( "General" ) )
+ {
+ config->setGroup( "General" ); // group will be restored by cgs anyway
+ if ( reset || config->hasKey( "foreground" ) )
+ d->m_textColor = config->readColorEntry( "foreground", &HTML_DEFAULT_TXT_COLOR );
+
+ if ( reset || config->hasKey( "linkColor" ) )
+ d->m_linkColor = config->readColorEntry( "linkColor", &HTML_DEFAULT_LNK_COLOR );
+
+ if ( reset || config->hasKey( "visitedLinkColor" ) )
+ d->m_vLinkColor = config->readColorEntry( "visitedLinkColor", &HTML_DEFAULT_VLNK_COLOR);
+
+ if ( reset || config->hasKey( "background" ) )
+ d->m_baseColor = config->readColorEntry( "background", &HTML_DEFAULT_BASE_COLOR);
+ }
+
+ if( reset || config->hasGroup( "Java/JavaScript Settings" ) )
+ {
+ config->setGroup( "Java/JavaScript Settings" );
+
+ // The global setting for JavaScript debugging
+ // This is currently always enabled by default
+ if ( reset || config->hasKey( "EnableJavaScriptDebug" ) )
+ d->m_bEnableJavaScriptDebug = config->readBoolEntry( "EnableJavaScriptDebug", false );
+
+ // The global setting for JavaScript error reporting
+ if ( reset || config->hasKey( "ReportJavaScriptErrors" ) )
+ d->m_bEnableJavaScriptErrorReporting = config->readBoolEntry( "ReportJavaScriptErrors", false );
+
+ // The global setting for popup block passive popup
+ if ( reset || config->hasKey( "PopupBlockerPassivePopup" ) )
+ d->m_jsPopupBlockerPassivePopup = config->readBoolEntry("PopupBlockerPassivePopup", true);
+
+ // Read options from the global "domain"
+ readDomainSettings(config,reset,true,d->global);
+#ifdef DEBUG_SETTINGS
+ d->global.dump("init global");
+#endif
+
+ // The domain-specific settings.
+
+ static const char *const domain_keys[] = { // always keep order of keys
+ "ECMADomains", "JavaDomains", "PluginDomains"
+ };
+ bool check_old_ecma_settings = true;
+ bool check_old_java_settings = true;
+ // merge all domains into one list
+ TQMap<TQString,int> domainList; // why can't Qt have a QSet?
+ for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) {
+ if ( reset || config->hasKey(domain_keys[i]) ) {
+ if (i == 0) check_old_ecma_settings = false;
+ else if (i == 1) check_old_java_settings = false;
+ const TQStringList dl = config->readListEntry( domain_keys[i] );
+ const TQMap<TQString,int>::Iterator notfound = domainList.end();
+ TQStringList::ConstIterator it = dl.begin();
+ const TQStringList::ConstIterator itEnd = dl.end();
+ for (; it != itEnd; ++it) {
+ const TQString domain = (*it).lower();
+ TQMap<TQString,int>::Iterator pos = domainList.find(domain);
+ if (pos == notfound) domainList.insert(domain,0);
+ }/*next it*/
+ }
+ }/*next i*/
+
+ if (reset)
+ d->domainPolicy.clear();
+
+ TQString js_group_save = config->group();
+ {
+ TQMap<TQString,int>::ConstIterator it = domainList.begin();
+ const TQMap<TQString,int>::ConstIterator itEnd = domainList.end();
+ for ( ; it != itEnd; ++it)
+ {
+ const TQString domain = it.key();
+ config->setGroup(domain);
+ readDomainSettings(config,reset,false,d->domainPolicy[domain]);
+#ifdef DEBUG_SETTINGS
+ d->domainPolicy[domain].dump("init "+domain);
+#endif
+ }
+ }
+ config->setGroup(js_group_save);
+
+ bool check_old_java = true;
+ if( ( reset || config->hasKey( "JavaDomainSettings" ) )
+ && check_old_java_settings )
+ {
+ check_old_java = false;
+ const TQStringList domainList = config->readListEntry( "JavaDomainSettings" );
+ TQStringList::ConstIterator it = domainList.begin();
+ const TQStringList::ConstIterator itEnd = domainList.end();
+ for ( ; it != itEnd; ++it)
+ {
+ TQString domain;
+ KJavaScriptAdvice javaAdvice;
+ KJavaScriptAdvice javaScriptAdvice;
+ splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
+ setup_per_domain_policy(d,domain).m_bEnableJava =
+ javaAdvice == KJavaScriptAccept;
+#ifdef DEBUG_SETTINGS
+ setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain);
+#endif
+ }
+ }
+
+ bool check_old_ecma = true;
+ if( ( reset || config->hasKey( "ECMADomainSettings" ) )
+ && check_old_ecma_settings )
+ {
+ check_old_ecma = false;
+ const TQStringList domainList = config->readListEntry( "ECMADomainSettings" );
+ TQStringList::ConstIterator it = domainList.begin();
+ const TQStringList::ConstIterator itEnd = domainList.end();
+ for ( ; it != itEnd; ++it)
+ {
+ TQString domain;
+ KJavaScriptAdvice javaAdvice;
+ KJavaScriptAdvice javaScriptAdvice;
+ splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
+ setup_per_domain_policy(d,domain).m_bEnableJavaScript =
+ javaScriptAdvice == KJavaScriptAccept;
+#ifdef DEBUG_SETTINGS
+ setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain);
+#endif
+ }
+ }
+
+ if( ( reset || config->hasKey( "JavaScriptDomainAdvice" ) )
+ && ( check_old_java || check_old_ecma )
+ && ( check_old_ecma_settings || check_old_java_settings ) )
+ {
+ const TQStringList domainList = config->readListEntry( "JavaScriptDomainAdvice" );
+ TQStringList::ConstIterator it = domainList.begin();
+ const TQStringList::ConstIterator itEnd = domainList.end();
+ for ( ; it != itEnd; ++it)
+ {
+ TQString domain;
+ KJavaScriptAdvice javaAdvice;
+ KJavaScriptAdvice javaScriptAdvice;
+ splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
+ if( check_old_java )
+ setup_per_domain_policy(d,domain).m_bEnableJava =
+ javaAdvice == KJavaScriptAccept;
+ if( check_old_ecma )
+ setup_per_domain_policy(d,domain).m_bEnableJavaScript =
+ javaScriptAdvice == KJavaScriptAccept;
+#ifdef DEBUG_SETTINGS
+ setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain);
+#endif
+ }
+
+ //save all the settings into the new keywords if they don't exist
+#if 0
+ if( check_old_java )
+ {
+ TQStringList domainConfig;
+ PolicyMap::Iterator it;
+ for( it = d->javaDomainPolicy.begin(); it != d->javaDomainPolicy.end(); ++it )
+ {
+ TQCString javaPolicy = adviceToStr( it.data() );
+ TQCString javaScriptPolicy = adviceToStr( KJavaScriptDunno );
+ domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
+ }
+ config->writeEntry( "JavaDomainSettings", domainConfig );
+ }
+
+ if( check_old_ecma )
+ {
+ TQStringList domainConfig;
+ PolicyMap::Iterator it;
+ for( it = d->javaScriptDomainPolicy.begin(); it != d->javaScriptDomainPolicy.end(); ++it )
+ {
+ TQCString javaPolicy = adviceToStr( KJavaScriptDunno );
+ TQCString javaScriptPolicy = adviceToStr( it.data() );
+ domainConfig.append(TQString::fromLatin1("%1:%2:%3").arg(it.key()).arg(javaPolicy).arg(javaScriptPolicy));
+ }
+ config->writeEntry( "ECMADomainSettings", domainConfig );
+ }
+#endif
+ }
+ }
+ config->setGroup(group_save);
+}
+
+
+/** Local helper for retrieving per-domain settings.
+ *
+ * In case of doubt, the global domain is returned.
+ */
+static const KPerDomainSettings &lookup_hostname_policy(
+ const KHTMLSettingsPrivate *d,
+ const TQString& hostname)
+{
+#ifdef DEBUG_SETTINGS
+ kdDebug() << "lookup_hostname_policy(" << hostname << ")" << endl;
+#endif
+ if (hostname.isEmpty()) {
+#ifdef DEBUG_SETTINGS
+ d->global.dump("global");
+#endif
+ return d->global;
+ }
+
+ const PolicyMap::const_iterator notfound = d->domainPolicy.end();
+
+ // First check whether there is a perfect match.
+ PolicyMap::const_iterator it = d->domainPolicy.find(hostname);
+ if( it != notfound ) {
+#ifdef DEBUG_SETTINGS
+ kdDebug() << "perfect match" << endl;
+ (*it).dump(hostname);
+#endif
+ // yes, use it (unless dunno)
+ return *it;
+ }
+
+ // Now, check for partial match. Chop host from the left until
+ // there's no dots left.
+ TQString host_part = hostname;
+ int dot_idx = -1;
+ while( (dot_idx = host_part.find(TQChar('.'))) >= 0 ) {
+ host_part.remove(0,dot_idx);
+ it = d->domainPolicy.find(host_part);
+ Q_ASSERT(notfound == d->domainPolicy.end());
+ if( it != notfound ) {
+#ifdef DEBUG_SETTINGS
+ kdDebug() << "partial match" << endl;
+ (*it).dump(host_part);
+#endif
+ return *it;
+ }
+ // assert(host_part[0] == TQChar('.'));
+ host_part.remove(0,1); // Chop off the dot.
+ }
+
+ // No domain-specific entry: use global domain
+#ifdef DEBUG_SETTINGS
+ kdDebug() << "no match" << endl;
+ d->global.dump("global");
+#endif
+ return d->global;
+}
+
+bool KHTMLSettings::isOpenMiddleClickEnabled()
+{
+ return d->m_bOpenMiddleClick;
+}
+
+bool KHTMLSettings::isBackRightClickEnabled()
+{
+ return d->m_bBackRightClick;
+}
+
+bool KHTMLSettings::accessKeysEnabled() const
+{
+ return d->m_accessKeysEnabled;
+}
+
+bool KHTMLSettings::isAdFilterEnabled() const
+{
+ return d->m_adFilterEnabled;
+}
+
+bool KHTMLSettings::isHideAdsEnabled() const
+{
+ return d->m_hideAdsEnabled;
+}
+
+bool KHTMLSettings::isAdFiltered( const TQString &url ) const
+{
+ if (d->m_adFilterEnabled)
+ {
+ if (!url.startsWith("data:"))
+ {
+ TQValueVector<TQRegExp>::const_iterator it(d->adFilters.constBegin());
+ TQValueVector<TQRegExp>::const_iterator end(d->adFilters.constEnd());
+ for (; it != end; ++it)
+ {
+ if ((*it).search(url) != -1)
+ {
+ kdDebug( 6080 ) << "Filtered: " << url << endl;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void KHTMLSettings::addAdFilter( const TQString &url )
+{
+ TDEConfig config( "tdehtmlrc", false, false );
+ config.setGroup( "Filter Settings" );
+
+ TQRegExp rx;
+ if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/')
+ {
+ TQString inside = url.mid(1, url.length()-2);
+ rx.setWildcard(false);
+ rx.setPattern(inside);
+ }
+ else
+ {
+ int left,right;
+
+ rx.setWildcard(true);
+ for (right=url.length(); right>0 && url[right-1]=='*' ; --right);
+ for (left=0; left<right && url[left]=='*' ; ++left);
+
+ rx.setPattern(url.mid(left,right-left));
+ }
+
+ if (rx.isValid())
+ {
+ int last=config.readNumEntry("Count",0);
+ TQString key = "Filter-" + TQString::number(last);
+ config.writeEntry(key, url);
+ config.writeEntry("Count",last+1);
+ config.sync();
+
+ d->adFilters.append(rx);
+ }
+ else
+ {
+ KMessageBox::error(0,
+ rx.errorString(),
+ i18n("Filter error"));
+ }
+}
+
+bool KHTMLSettings::isJavaEnabled( const TQString& hostname )
+{
+ return lookup_hostname_policy(d,hostname.lower()).m_bEnableJava;
+}
+
+bool KHTMLSettings::isJavaScriptEnabled( const TQString& hostname )
+{
+ return lookup_hostname_policy(d,hostname.lower()).m_bEnableJavaScript;
+}
+
+bool KHTMLSettings::isJavaScriptDebugEnabled( const TQString& /*hostname*/ )
+{
+ // debug setting is global for now, but could change in the future
+ return d->m_bEnableJavaScriptDebug;
+}
+
+bool KHTMLSettings::isJavaScriptErrorReportingEnabled( const TQString& /*hostname*/ ) const
+{
+ // error reporting setting is global for now, but could change in the future
+ return d->m_bEnableJavaScriptErrorReporting;
+}
+
+bool KHTMLSettings::isPluginsEnabled( const TQString& hostname )
+{
+ return lookup_hostname_policy(d,hostname.lower()).m_bEnablePlugins;
+}
+
+KHTMLSettings::KJSWindowOpenPolicy KHTMLSettings::windowOpenPolicy(
+ const TQString& hostname) const {
+ return lookup_hostname_policy(d,hostname.lower()).m_windowOpenPolicy;
+}
+
+KHTMLSettings::KJSWindowMovePolicy KHTMLSettings::windowMovePolicy(
+ const TQString& hostname) const {
+ return lookup_hostname_policy(d,hostname.lower()).m_windowMovePolicy;
+}
+
+KHTMLSettings::KJSWindowResizePolicy KHTMLSettings::windowResizePolicy(
+ const TQString& hostname) const {
+ return lookup_hostname_policy(d,hostname.lower()).m_windowResizePolicy;
+}
+
+KHTMLSettings::KJSWindowStatusPolicy KHTMLSettings::windowStatusPolicy(
+ const TQString& hostname) const {
+ return lookup_hostname_policy(d,hostname.lower()).m_windowStatusPolicy;
+}
+
+KHTMLSettings::KJSWindowFocusPolicy KHTMLSettings::windowFocusPolicy(
+ const TQString& hostname) const {
+ return lookup_hostname_policy(d,hostname.lower()).m_windowFocusPolicy;
+}
+
+int KHTMLSettings::mediumFontSize() const
+{
+ return d->m_fontSize;
+}
+
+int KHTMLSettings::minFontSize() const
+{
+ return d->m_minFontSize;
+}
+
+TQString KHTMLSettings::settingsToCSS() const
+{
+ // lets start with the link properties
+ TQString str = "a:link {\ncolor: ";
+ str += d->m_linkColor.name();
+ str += ";";
+ if(d->m_underlineLink)
+ str += "\ntext-decoration: underline;";
+
+ if( d->m_bChangeCursor )
+ {
+ str += "\ncursor: pointer;";
+ str += "\n}\ninput[type=image] { cursor: pointer;";
+ }
+ str += "\n}\n";
+ str += "a:visited {\ncolor: ";
+ str += d->m_vLinkColor.name();
+ str += ";";
+ if(d->m_underlineLink)
+ str += "\ntext-decoration: underline;";
+
+ if( d->m_bChangeCursor )
+ str += "\ncursor: pointer;";
+ str += "\n}\n";
+
+ if(d->m_hoverLink)
+ str += "a:link:hover, a:visited:hover { text-decoration: underline; }\n";
+
+ return str;
+}
+
+const TQString &KHTMLSettings::availableFamilies()
+{
+ if ( !avFamilies ) {
+ avFamilies = new TQString;
+ TQFontDatabase db;
+ TQStringList families = db.families();
+ TQStringList s;
+ TQRegExp foundryExp(" \\[.+\\]");
+
+ //remove foundry info
+ TQStringList::Iterator f = families.begin();
+ const TQStringList::Iterator fEnd = families.end();
+
+ for ( ; f != fEnd; ++f ) {
+ (*f).replace( foundryExp, "");
+ if (!s.contains(*f))
+ s << *f;
+ }
+ s.sort();
+
+ *avFamilies = ',' + s.join(",") + ',';
+ }
+
+ return *avFamilies;
+}
+
+TQString KHTMLSettings::lookupFont(int i) const
+{
+ TQString font;
+ if (d->fonts.count() > (uint) i)
+ font = d->fonts[i];
+ if (font.isEmpty())
+ font = d->defaultFonts[i];
+ return font;
+}
+
+TQString KHTMLSettings::stdFontName() const
+{
+ return lookupFont(0);
+}
+
+TQString KHTMLSettings::fixedFontName() const
+{
+ return lookupFont(1);
+}
+
+TQString KHTMLSettings::serifFontName() const
+{
+ return lookupFont(2);
+}
+
+TQString KHTMLSettings::sansSerifFontName() const
+{
+ return lookupFont(3);
+}
+
+TQString KHTMLSettings::cursiveFontName() const
+{
+ return lookupFont(4);
+}
+
+TQString KHTMLSettings::fantasyFontName() const
+{
+ return lookupFont(5);
+}
+
+void KHTMLSettings::setStdFontName(const TQString &n)
+{
+ while(d->fonts.count() <= 0)
+ d->fonts.append(TQString::null);
+ d->fonts[0] = n;
+}
+
+void KHTMLSettings::setFixedFontName(const TQString &n)
+{
+ while(d->fonts.count() <= 1)
+ d->fonts.append(TQString::null);
+ d->fonts[1] = n;
+}
+
+TQString KHTMLSettings::userStyleSheet() const
+{
+ return d->m_userSheet;
+}
+
+bool KHTMLSettings::isFormCompletionEnabled() const
+{
+ return d->m_formCompletionEnabled;
+}
+
+int KHTMLSettings::maxFormCompletionItems() const
+{
+ return d->m_maxFormCompletionItems;
+}
+
+const TQString &KHTMLSettings::encoding() const
+{
+ return d->m_encoding;
+}
+
+bool KHTMLSettings::followSystemColors() const
+{
+ return d->m_follow_system_colors;
+}
+
+const TQColor& KHTMLSettings::textColor() const
+{
+ return d->m_textColor;
+}
+
+const TQColor& KHTMLSettings::baseColor() const
+{
+ return d->m_baseColor;
+}
+
+const TQColor& KHTMLSettings::linkColor() const
+{
+ return d->m_linkColor;
+}
+
+const TQColor& KHTMLSettings::vLinkColor() const
+{
+ return d->m_vLinkColor;
+}
+
+bool KHTMLSettings::autoLoadImages() const
+{
+ return d->m_bAutoLoadImages;
+}
+
+bool KHTMLSettings::unfinishedImageFrame() const
+{
+ return d->m_bUnfinishedImageFrame;
+}
+
+KHTMLSettings::KAnimationAdvice KHTMLSettings::showAnimations() const
+{
+ return d->m_showAnimations;
+}
+
+bool KHTMLSettings::isAutoDelayedActionsEnabled() const
+{
+ return d->m_autoDelayedActionsEnabled;
+}
+
+bool KHTMLSettings::jsErrorsEnabled() const
+{
+ return d->m_jsErrorsEnabled;
+}
+
+void KHTMLSettings::setJSErrorsEnabled(bool enabled)
+{
+ d->m_jsErrorsEnabled = enabled;
+ // save it
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup("HTML Settings");
+ config->writeEntry("ReportJSErrors", enabled);
+ config->sync();
+}
+
+bool KHTMLSettings::allowTabulation() const
+{
+ return d->m_allowTabulation;
+}
+
+bool KHTMLSettings::autoSpellCheck() const
+{
+ return d->m_autoSpellCheck;
+}
+
+TQValueList< TQPair< TQString, TQChar > > KHTMLSettings::fallbackAccessKeysAssignments() const
+{
+ return d->m_fallbackAccessKeysAssignments;
+}
+
+void KHTMLSettings::setJSPopupBlockerPassivePopup(bool enabled)
+{
+ d->m_jsPopupBlockerPassivePopup = enabled;
+ // save it
+ TDEConfig *config = TDEGlobal::config();
+ config->setGroup("Java/JavaScript Settings");
+ config->writeEntry("PopupBlockerPassivePopup", enabled);
+ config->sync();
+}
+
+bool KHTMLSettings::jsPopupBlockerPassivePopup() const
+{
+ return d->m_jsPopupBlockerPassivePopup;
+}
diff --git a/tdehtml/tdehtml_settings.h b/tdehtml/tdehtml_settings.h
new file mode 100644
index 000000000..4d68845f7
--- /dev/null
+++ b/tdehtml/tdehtml_settings.h
@@ -0,0 +1,232 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 David Faure <faure@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 __konq_htmlsettings_h__
+#define __konq_htmlsettings_h__
+
+class TDEConfig;
+#include <tqcolor.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqfont.h>
+#include <tqmap.h>
+
+#include <tdelibs_export.h>
+
+struct KPerDomainSettings;
+class KHTMLSettingsPrivate;
+
+/**
+ * Settings for the HTML view.
+ */
+class KHTML_EXPORT KHTMLSettings
+{
+public:
+
+ /**
+ * This enum specifies whether Java/JavaScript execution is allowed.
+ */
+ enum KJavaScriptAdvice {
+ KJavaScriptDunno=0,
+ KJavaScriptAccept,
+ KJavaScriptReject
+ };
+
+ enum KAnimationAdvice {
+ KAnimationDisabled=0,
+ KAnimationLoopOnce,
+ KAnimationEnabled
+ };
+
+ /**
+ * This enum specifies the policy for window.open
+ */
+ enum KJSWindowOpenPolicy {
+ KJSWindowOpenAllow=0,
+ KJSWindowOpenAsk,
+ KJSWindowOpenDeny,
+ KJSWindowOpenSmart
+ };
+
+ /**
+ * This enum specifies the policy for window.status and .defaultStatus
+ */
+ enum KJSWindowStatusPolicy {
+ KJSWindowStatusAllow=0,
+ KJSWindowStatusIgnore
+ };
+
+ /**
+ * This enum specifies the policy for window.moveBy and .moveTo
+ */
+ enum KJSWindowMovePolicy {
+ KJSWindowMoveAllow=0,
+ KJSWindowMoveIgnore
+ };
+
+ /**
+ * This enum specifies the policy for window.resizeBy and .resizeTo
+ */
+ enum KJSWindowResizePolicy {
+ KJSWindowResizeAllow=0,
+ KJSWindowResizeIgnore
+ };
+
+ /**
+ * This enum specifies the policy for window.focus
+ */
+ enum KJSWindowFocusPolicy {
+ KJSWindowFocusAllow=0,
+ KJSWindowFocusIgnore
+ };
+
+ /**
+ * @internal Constructor
+ */
+ KHTMLSettings();
+ KHTMLSettings(const KHTMLSettings &other);
+
+ /**
+ * Called by constructor and reparseConfiguration
+ */
+ void init();
+
+ /** Read settings from @p config.
+ * @param config is a pointer to TDEConfig object.
+ * @param reset if true, settings are always set; if false,
+ * settings are only set if the config file has a corresponding key.
+ */
+ void init( TDEConfig * config, bool reset = true );
+
+ /**
+ * Destructor. Don't delete any instance by yourself.
+ */
+ virtual ~KHTMLSettings();
+
+ // Behavior settings
+ bool changeCursor() const;
+ bool underlineLink() const;
+ bool hoverLink() const;
+ bool allowTabulation() const;
+ bool autoSpellCheck() const;
+ KAnimationAdvice showAnimations() const;
+
+ // Font settings
+ TQString stdFontName() const;
+ TQString fixedFontName() const;
+ TQString serifFontName() const;
+ TQString sansSerifFontName() const;
+ TQString cursiveFontName() const;
+ TQString fantasyFontName() const;
+
+ // these two can be set. Mainly for historical reasons (the method in KHTMLPart exists...)
+ void setStdFontName(const TQString &n);
+ void setFixedFontName(const TQString &n);
+
+ int minFontSize() const;
+ int mediumFontSize() const;
+
+ bool jsErrorsEnabled() const;
+ void setJSErrorsEnabled(bool enabled);
+
+ const TQString &encoding() const;
+
+ bool followSystemColors() const;
+
+ // Color settings
+ const TQColor& textColor() const;
+ const TQColor& baseColor() const;
+ const TQColor& linkColor() const;
+ const TQColor& vLinkColor() const;
+
+ // Autoload images
+ bool autoLoadImages() const;
+ bool unfinishedImageFrame() const;
+
+ bool isOpenMiddleClickEnabled();
+ bool isBackRightClickEnabled();
+
+ // Java and JavaScript
+ // ### BIC make these const
+ bool isJavaEnabled( const TQString& hostname = TQString::null );
+ bool isJavaScriptEnabled( const TQString& hostname = TQString::null );
+ bool isJavaScriptDebugEnabled( const TQString& hostname = TQString::null );
+ bool isJavaScriptErrorReportingEnabled( const TQString& hostname = TQString::null ) const;
+ bool isPluginsEnabled( const TQString& hostname = TQString::null );
+
+ // AdBlocK Filtering
+ bool isAdFiltered( const TQString &url ) const;
+ bool isAdFilterEnabled() const;
+ bool isHideAdsEnabled() const;
+ void addAdFilter( const TQString &url );
+
+ // Access Keys
+ bool accessKeysEnabled() const;
+
+ KJSWindowOpenPolicy windowOpenPolicy( const TQString& hostname = TQString::null ) const;
+ KJSWindowMovePolicy windowMovePolicy( const TQString& hostname = TQString::null ) const;
+ KJSWindowResizePolicy windowResizePolicy( const TQString& hostname = TQString::null ) const;
+ KJSWindowStatusPolicy windowStatusPolicy( const TQString& hostname = TQString::null ) const;
+ KJSWindowFocusPolicy windowFocusPolicy( const TQString& hostname = TQString::null ) const;
+
+ // helpers for parsing domain-specific configuration, used in KControl module as well
+ static KJavaScriptAdvice strToAdvice(const TQString& _str);
+ static void splitDomainAdvice(const TQString& configStr, TQString &domain,
+ KJavaScriptAdvice &javaAdvice, KJavaScriptAdvice& javaScriptAdvice);
+ static const char* adviceToStr(KJavaScriptAdvice _advice);
+
+ /** reads from @p config's current group, forcing initialization
+ * if @p reset is true.
+ * @param config is a pointer to TDEConfig object.
+ * @param reset true if initialization is to be forced.
+ * @param global true if the global domain is to be read.
+ * @param pd_settings will be initialised with the computed (inherited)
+ * settings.
+ */
+ void readDomainSettings(TDEConfig *config, bool reset,
+ bool global, KPerDomainSettings &pd_settings);
+
+ TQString settingsToCSS() const;
+ static const TQString &availableFamilies();
+
+ TQString userStyleSheet() const;
+
+ // Form completion
+ bool isFormCompletionEnabled() const;
+ int maxFormCompletionItems() const;
+
+ // Meta refresh/redirect (http-equiv)
+ bool isAutoDelayedActionsEnabled () const;
+
+ TQValueList< TQPair< TQString, TQChar > > fallbackAccessKeysAssignments() const;
+
+ // Whether to show passive popup when windows are blocked
+ // @since 3.5
+ void setJSPopupBlockerPassivePopup(bool enabled);
+ bool jsPopupBlockerPassivePopup() const;
+
+private:
+ friend class KHTMLFactory;
+ TQString lookupFont(int i) const;
+
+ KHTMLSettingsPrivate *d;
+ static TQString *avFamilies;
+};
+
+#endif
diff --git a/tdehtml/tdehtmldefaults.h b/tdehtml/tdehtmldefaults.h
new file mode 100644
index 000000000..8b674ffe0
--- /dev/null
+++ b/tdehtml/tdehtmldefaults.h
@@ -0,0 +1,33 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ Copyright (C) 1999 David Faure <faure@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.
+*/
+
+// browser window color defaults -- Bernd
+#define HTML_DEFAULT_LNK_COLOR TQt::blue
+#define HTML_DEFAULT_TXT_COLOR TQt::black
+#define HTML_DEFAULT_VLNK_COLOR TQt::magenta
+#define HTML_DEFAULT_BASE_COLOR TQt::white
+
+#define HTML_DEFAULT_VIEW_FONT "Sans Serif"
+#define HTML_DEFAULT_VIEW_FIXED_FONT "Monospace"
+#define HTML_DEFAULT_VIEW_SERIF_FONT "Serif"
+#define HTML_DEFAULT_VIEW_SANSSERIF_FONT "Sans Serif"
+#define HTML_DEFAULT_VIEW_CURSIVE_FONT "Sans Serif"
+#define HTML_DEFAULT_VIEW_FANTASY_FONT "Sans Serif"
+#define HTML_DEFAULT_MIN_FONT_SIZE 7 // everything smaller is usually unreadable.
diff --git a/tdehtml/tdehtmlimage.cpp b/tdehtml/tdehtmlimage.cpp
new file mode 100644
index 000000000..cc244ed80
--- /dev/null
+++ b/tdehtml/tdehtmlimage.cpp
@@ -0,0 +1,357 @@
+/* This file is part of the KDE project
+ Copyright (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.
+*/
+
+#include "tdehtmlimage.h"
+#include "tdehtmlview.h"
+#include "tdehtml_ext.h"
+#include "xml/dom_docimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_elementimpl.h"
+#include "rendering/render_image.h"
+#include "misc/loader.h"
+
+#include <tqvbox.h>
+#include <tqtimer.h>
+
+#include <kio/job.h>
+#include <kinstance.h>
+#include <kmimetype.h>
+#include <klocale.h>
+
+K_EXPORT_COMPONENT_FACTORY( tdehtmlimagefactory /*NOT the part name, see Makefile.am*/, KHTMLImageFactory )
+
+TDEInstance *KHTMLImageFactory::s_instance = 0;
+
+KHTMLImageFactory::KHTMLImageFactory()
+{
+ s_instance = new TDEInstance( "tdehtmlimage" );
+}
+
+KHTMLImageFactory::~KHTMLImageFactory()
+{
+ delete s_instance;
+}
+
+KParts::Part *KHTMLImageFactory::createPartObject( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name,
+ const char *className, const TQStringList & )
+{
+ KHTMLPart::GUIProfile prof = KHTMLPart::DefaultGUI;
+ if ( strcmp( className, "Browser/View" ) == 0 )
+ prof = KHTMLPart::BrowserViewGUI;
+ return new KHTMLImage( parentWidget, widgetName, parent, name, prof );
+}
+
+KHTMLImage::KHTMLImage( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name, KHTMLPart::GUIProfile prof )
+ : KParts::ReadOnlyPart( parent, name ), m_image( 0 )
+{
+ KHTMLPart* parentPart = ::tqqt_cast<KHTMLPart *>( parent );
+ setInstance( KHTMLImageFactory::instance(), prof == KHTMLPart::BrowserViewGUI && !parentPart );
+
+ TQVBox *box = new TQVBox( parentWidget, widgetName );
+
+ m_tdehtml = new KHTMLPart( box, widgetName, this, "htmlimagepart", prof );
+ m_tdehtml->setAutoloadImages( true );
+ m_tdehtml->widget()->installEventFilter(this);
+ connect( m_tdehtml->view(), TQT_SIGNAL( finishedLayout() ), this, TQT_SLOT( restoreScrollPosition() ) );
+
+ setWidget( box );
+
+ // VBox can't take focus, so pass it on to sub-widget
+ box->setFocusProxy( m_tdehtml->widget() );
+
+ m_ext = new KHTMLImageBrowserExtension( this, "be" );
+
+ // Remove unnecessary actions.
+ KAction *encodingAction = actionCollection()->action( "setEncoding" );
+ if ( encodingAction )
+ {
+ encodingAction->unplugAll();
+ delete encodingAction;
+ }
+ KAction *viewSourceAction= actionCollection()->action( "viewDocumentSource" );
+ if ( viewSourceAction )
+ {
+ viewSourceAction->unplugAll();
+ delete viewSourceAction;
+ }
+
+ KAction *selectAllAction= actionCollection()->action( "selectAll" );
+ if ( selectAllAction )
+ {
+ selectAllAction->unplugAll();
+ delete selectAllAction;
+ }
+
+ // forward important signals from the tdehtml part
+
+ // forward opening requests to parent frame (if existing)
+ KHTMLPart *p = ::tqqt_cast<KHTMLPart *>(parent);
+ KParts::BrowserExtension *be = p ? p->browserExtension() : m_ext;
+ connect(m_tdehtml->browserExtension(), TQT_SIGNAL(openURLRequestDelayed(const KURL &, const KParts::URLArgs &)),
+ be, TQT_SIGNAL(openURLRequestDelayed(const KURL &, const KParts::URLArgs &)));
+
+ connect( m_tdehtml->browserExtension(), TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &,
+ const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t) ), m_ext, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &,
+ const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t) ) );
+
+ connect( m_tdehtml->browserExtension(), TQT_SIGNAL( enableAction( const char *, bool ) ),
+ m_ext, TQT_SIGNAL( enableAction( const char *, bool ) ) );
+
+ m_ext->setURLDropHandlingEnabled( true );
+}
+
+KHTMLImage::~KHTMLImage()
+{
+ disposeImage();
+
+ // important: delete the html part before the part or qobject destructor runs.
+ // we now delete the htmlpart which deletes the part's widget which makes
+ // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the
+ // widget ;-)
+ // ### additional note: it _can_ be that the part has been deleted before:
+ // when we're in a html frameset and the view dies first, then it will also
+ // kill the htmlpart
+ if ( m_tdehtml )
+ delete static_cast<KHTMLPart *>( m_tdehtml );
+}
+
+bool KHTMLImage::openURL( const KURL &url )
+{
+ static const TQString &html = TDEGlobal::staticQString( "<html><body><img src=\"%1\"></body></html>" );
+
+ disposeImage();
+
+ m_url = url;
+
+ emit started( 0 );
+
+ KParts::URLArgs args = m_ext->urlArgs();
+ m_mimeType = args.serviceType;
+
+ emit setWindowCaption( url.prettyURL() );
+
+ // Need to keep a copy of the offsets since they are cleared when emitting completed
+ m_xOffset = args.xOffset;
+ m_yOffset = args.yOffset;
+
+ m_tdehtml->begin( m_url );
+ m_tdehtml->setAutoloadImages( true );
+
+ DOM::DocumentImpl *impl = dynamic_cast<DOM::DocumentImpl *>( m_tdehtml->document().handle() ); // ### hack ;-)
+ if (!impl) return false;
+ if ( m_ext->urlArgs().reload )
+ impl->docLoader()->setCachePolicy( TDEIO::CC_Reload );
+
+ tdehtml::DocLoader *dl = impl->docLoader();
+ m_image = dl->requestImage( m_url.url() );
+ if ( m_image )
+ m_image->ref( this );
+
+ m_tdehtml->write( html.arg( m_url.url() ) );
+ m_tdehtml->end();
+
+ /*
+ connect( tdehtml::Cache::loader(), TQT_SIGNAL( requestDone( tdehtml::DocLoader*, tdehtml::CachedObject *) ),
+ this, TQT_SLOT( updateWindowCaption() ) );
+ */
+ return true;
+}
+
+bool KHTMLImage::closeURL()
+{
+ disposeImage();
+ return m_tdehtml->closeURL();
+}
+
+// This can happen after openURL returns, or directly from m_image->ref()
+void KHTMLImage::notifyFinished( tdehtml::CachedObject *o )
+{
+ if ( !m_image || o != m_image )
+ return;
+
+ const TQPixmap &pix = m_image->pixmap();
+ TQString caption;
+
+ KMimeType::Ptr mimeType;
+ if ( !m_mimeType.isEmpty() )
+ mimeType = KMimeType::mimeType( m_mimeType );
+
+ if ( mimeType ) {
+ if (m_image && !m_image->suggestedTitle().isEmpty()) {
+ caption = i18n( "%1 (%2 - %3x%4 Pixels)" ).arg( m_image->suggestedTitle(), mimeType->comment() ).arg( pix.width() ).arg( pix.height() );
+ } else {
+ caption = i18n( "%1 - %2x%3 Pixels" ).arg( mimeType->comment() )
+ .arg( pix.width() ).arg( pix.height() );
+ }
+ } else {
+ if (m_image && !m_image->suggestedTitle().isEmpty()) {
+ caption = i18n( "%1 (%2x%3 Pixels)" ).arg(m_image->suggestedTitle()).arg( pix.width() ).arg( pix.height() );
+ } else {
+ caption = i18n( "Image - %1x%2 Pixels" ).arg( pix.width() ).arg( pix.height() );
+ }
+ }
+
+ emit setWindowCaption( caption );
+ emit completed();
+ emit setStatusBarText(i18n("Done."));
+}
+
+void KHTMLImage::restoreScrollPosition()
+{
+ if ( m_tdehtml->view()->contentsY() == 0 ) {
+ m_tdehtml->view()->setContentsPos( m_xOffset, m_yOffset );
+ }
+}
+
+void KHTMLImage::guiActivateEvent( KParts::GUIActivateEvent *e )
+{
+ // prevent the base implementation from emitting setWindowCaption with
+ // our url. It destroys our pretty, previously caption. Konq saves/restores
+ // the caption for us anyway.
+ if ( e->activated() )
+ return;
+ KParts::ReadOnlyPart::guiActivateEvent(e);
+}
+
+/*
+void KHTMLImage::slotImageJobFinished( TDEIO::Job *job )
+{
+ if ( job->error() )
+ {
+ job->showErrorDialog();
+ emit canceled( job->errorString() );
+ }
+ else
+ {
+ emit completed();
+ TQTimer::singleShot( 0, this, TQT_SLOT( updateWindowCaption() ) );
+ }
+}
+
+void KHTMLImage::updateWindowCaption()
+{
+ if ( !m_tdehtml )
+ return;
+
+ DOM::HTMLDocumentImpl *impl = dynamic_cast<DOM::HTMLDocumentImpl *>( m_tdehtml->document().handle() );
+ if ( !impl )
+ return;
+
+ DOM::HTMLElementImpl *body = impl->body();
+ if ( !body )
+ return;
+
+ DOM::NodeImpl *image = body->firstChild();
+ if ( !image )
+ return;
+
+ tdehtml::RenderImage *renderImage = dynamic_cast<tdehtml::RenderImage *>( image->renderer() );
+ if ( !renderImage )
+ return;
+
+ TQPixmap pix = renderImage->pixmap();
+
+ TQString caption;
+
+ KMimeType::Ptr mimeType;
+ if ( !m_mimeType.isEmpty() )
+ mimeType = KMimeType::mimeType( m_mimeType );
+
+ if ( mimeType )
+ caption = i18n( "%1 - %2x%3 Pixels" ).arg( mimeType->comment() )
+ .arg( pix.width() ).arg( pix.height() );
+ else
+ caption = i18n( "Image - %1x%2 Pixels" ).arg( pix.width() ).arg( pix.height() );
+
+ emit setWindowCaption( caption );
+ emit completed();
+ emit setStatusBarText(i18n("Done."));
+}
+*/
+
+void KHTMLImage::disposeImage()
+{
+ if ( !m_image )
+ return;
+
+ m_image->deref( this );
+ m_image = 0;
+}
+
+bool KHTMLImage::eventFilter(TQObject *, TQEvent *e) {
+ switch (e->type()) {
+ case TQEvent::DragEnter:
+ case TQEvent::DragMove:
+ case TQEvent::DragLeave:
+ case TQEvent::Drop: {
+ // find out if this part is embedded in a frame, and send the
+ // event to its outside widget
+ KHTMLPart *p = ::tqqt_cast<KHTMLPart *>(parent());
+ if (p)
+ return TQApplication::sendEvent(p->widget(), e);
+ // otherwise simply forward all dnd events to the part widget,
+ // konqueror will handle them properly there
+ return TQApplication::sendEvent(widget(), e);
+ }
+ default: ;
+ }
+ return false;
+}
+
+KHTMLImageBrowserExtension::KHTMLImageBrowserExtension( KHTMLImage *parent, const char *name )
+ : KParts::BrowserExtension( parent, name )
+{
+ m_imgPart = parent;
+}
+
+int KHTMLImageBrowserExtension::xOffset()
+{
+ return m_imgPart->doc()->view()->contentsX();
+}
+
+int KHTMLImageBrowserExtension::yOffset()
+{
+ return m_imgPart->doc()->view()->contentsY();
+}
+
+void KHTMLImageBrowserExtension::print()
+{
+ static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print();
+}
+
+void KHTMLImageBrowserExtension::reparseConfiguration()
+{
+ static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration();
+ m_imgPart->doc()->setAutoloadImages( true );
+}
+
+
+void KHTMLImageBrowserExtension::disableScrolling()
+{
+ static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->disableScrolling();
+}
+
+using namespace KParts;
+
+/* vim: et sw=4 ts=4
+ */
+
+#include "tdehtmlimage.moc"
diff --git a/tdehtml/tdehtmlimage.desktop b/tdehtml/tdehtmlimage.desktop
new file mode 100644
index 000000000..4703bbabb
--- /dev/null
+++ b/tdehtml/tdehtmlimage.desktop
@@ -0,0 +1,170 @@
+[Desktop Entry]
+Type=Service
+Comment=Embeddable Image Viewing Component
+Comment[af]=Inlegbare Beeld Aansig Komponent
+Comment[ar]=مكون عرض صور قابل للدمج
+Comment[az]=Daxili Rəsm Nümayiş Vasitəsi
+Comment[be]=Унутраны праглÑдальнік відарыÑаў
+Comment[bg]=Вграден компонент за преглед на изображениÑ
+Comment[bn]=অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ চিতà§à¦° পà§à¦°à¦¦à¦°à§à¦¶à¦• উপাদান
+Comment[br]=Parzh skeudenn gweler enframmus
+Comment[bs]=Umetljiva komponenta za pregled slika
+Comment[ca]=Component encastable per a visualitzar imatges
+Comment[cs]=Komponenta pro zobrazování obrázků
+Comment[csb]=Kòmpònent do przezeraniô òbrôzów
+Comment[cy]=Cydran Gweld Delwedd Mewnadeiladadwy
+Comment[da]=Billedvisningskomponent som kan indlejres
+Comment[de]=Einbettungsfähige Bildbetrachter-Komponente
+Comment[el]=Ενσωματώσιμο στοιχείο Ï€Ïοβολής εικόνων
+Comment[eo]=Enkonstruebla bildrigardilo
+Comment[es]=Componente incrustable para visualizar imágenes
+Comment[et]=Põimitav pildifailide näitamise komponent
+Comment[eu]=Kapsulatutako irudi-ikustailea
+Comment[fa]=مولÙÛ€ مشاهدۀ تصویر نهÙته
+Comment[fi]=Upotettava kuviennäyttökomponentti
+Comment[fr]=Composant d'affichage d'images intégrable
+Comment[fy]=Yn te sluten komponint foar byldwerjefte
+Comment[ga]=Comhpháirt inleabaithe amharctha íomhá
+Comment[gl]=Compoñente incrustábel de visualización de imaxes
+Comment[he]=רכיב בר־הטבעה להצגת תמונות
+Comment[hi]=अंतरà¥à¤¨à¤¿à¤¹à¤¿à¤¤ योगà¥à¤¯ छवि दरà¥à¤¶à¤• घटक
+Comment[hr]=Ugradiva komponenta za pregledavanje slika
+Comment[hu]=Beágyazható képnéző komponens
+Comment[id]=Komponen melihat gambar yang embeddable
+Comment[is]=Ãvefjanleg myndsjáreining
+Comment[it]=Componente integrabile per la visualizzazione di immagini
+Comment[ja]=埋ã‚è¾¼ã¿å¯èƒ½ãªç”»åƒãƒ“ューアコンãƒãƒ¼ãƒãƒ³ãƒˆ
+Comment[ka]=ნáƒáƒ®áƒáƒ¢áƒ”ბის ჩვენების ჩáƒáƒ“გმáƒáƒ“ი კáƒáƒ›áƒžáƒáƒœáƒ”ნტი
+Comment[kk]=Ендірілетін кеÑкін қарау компоненті
+Comment[km]=សមាសភាគ​មើល​រូបភាព​ដែល​អាច​បង្កប់
+Comment[ko]=ë¼ì›Œë„£ëŠ” 그림 보기 구성 요소
+Comment[lb]=Abettbar Bild-Uweisungskomponent
+Comment[lt]=Įdedamas piešinių peržiūros komponentas
+Comment[lv]=IegultÄ AttÄ“lu SkatÄ«Å¡anas Komponente
+Comment[mk]=Вгнездлива компонента за гледање Ñлики
+Comment[mn]=Суулгаж болох Зураг Харагч БүрÑл Ñ…ÑÑÑг
+Comment[ms]=Komponen Pelihat Imej Boleh-serta
+Comment[mt]=Komponent integrat għall wiri tal-istampi
+Comment[nb]=Innebyggbar bildevisningskomponent
+Comment[nds]=Inbettbor Kieker-Komponent för Biller
+Comment[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ गरà¥à¤¨ सकिने छवि दृशà¥à¤¯ अवयव
+Comment[nl]=Ingebed afbeeldingenweergavecomponent
+Comment[nn]=Inkluderbart komponent for biletvising
+Comment[nso]=Seripa seo se Robatsegsgo sa Pono ya Ponagalo
+Comment[pa]=ਸ਼ਾਮਿਲਯੋਗ ਚਿੱਤਰ ਦਰਸ਼ਕ ਹਿੱਸਾ
+Comment[pl]=Składnik do przeglądania obrazków
+Comment[pt]=Componente incorporada para visualizar imagens
+Comment[pt_BR]=Componente integrado de visualização de imagens
+Comment[ro]=Componentă înglobată de vizualizare imagini
+Comment[ru]=Ð’Ñтраиваемый модуль проÑмотра изображений
+Comment[rw]=Inyangingo yo Kugaragaza Ishusho Ishyirwamo
+Comment[se]=Vuojuhanláhkái govvaÄájehanoassi
+Comment[sk]=Vložiteľný komponent prehliadaÄ obrázkov
+Comment[sl]=Integrirana komponenta za ogledovanje slik
+Comment[sq]=Element për Shikimin e Imazheve që mund të ngulitet
+Comment[sr]=Уградива компонента за приказивање Ñлика
+Comment[sr@Latn]=Ugradiva komponenta za prikazivanje slika
+Comment[ss]=Incenye yekubuka umfanekiso lelalisekekako
+Comment[sv]=Inbäddningsbar bildvisande komponent
+Comment[ta]=உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ பிமà¯à®ªà®•à¯ காடà¯à®Ÿà®¿à®•à¯ பகà¯à®¤à®¿
+Comment[te]=పొదగదగà±à°— à°ªà±à°°à°¤à°¿à°¬à°¿à°‚బాల వికà±à°·à°£à°¾à°‚శం
+Comment[tg]=ҚиÑмати ТаÑвири Биниш дар Дарун Сохтан
+Comment[th]=ส่วนประà¸à¸­à¸šà¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸ªà¸”งภาพที่à¸à¸±à¸‡à¹„ด้
+Comment[tr]=Gömülebilir Resim Görüntüleme Aracı
+Comment[tt]=Sürät Qaraw öçen Quşılma Komponent
+Comment[uk]=Вбудований компонент переглÑдача зображень
+Comment[uz]=Ichiga oʻrnatib boʻladigan rasm koʻruvchi komponent
+Comment[uz@cyrillic]=Ичига ўрнатиб бўладиган раÑм кўрувчи компонент
+Comment[ven]=Khomphonente yau vhona tshifanyiso
+Comment[vi]=Thành phần xem ảnh có khả năng nhúng.
+Comment[xh]=Ingxenye Yemboniselo Yomfanekiso Olungisiweyo
+Comment[zh_CN]=å¯åµŒå…¥çš„图åƒæŸ¥çœ‹éƒ¨ä»¶
+Comment[zh_HK]=å¯åµŒå…¥çš„圖檔檢視元件
+Comment[zh_TW]=å¯åµŒå…¥çš„å½±åƒæª¢è¦–元件
+Comment[zu]=Ilunga Lokubukisa Isithombe Elishuthekayo
+MimeType=image/gif;image/x-xpm;image/x-xbm;image/jpeg;image/x-bmp;image/png;image/x-jng;image/x-ico;image/x-portable-bitmap;image/x-portable-pixmap;image/x-portable-greymap;image/tiff;video/x-mng;image/x-targa;
+Name=Embeddable Image Viewer
+Name[af]=Inlegbare Beeld Aansig
+Name[ar]=عارض الصور القابل للدمج
+Name[az]=Daxili Rəsm Nümayişçisi
+Name[be]=Унутраны праглÑдальнік відарыÑаў
+Name[bg]=Вграден компонент за преглед на изображениÑ
+Name[bn]=অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ চিতà§à¦° পà§à¦°à¦¦à¦°à§à¦¶à¦•
+Name[br]=Gweler Skeudennoù Enklozet
+Name[ca]=Visor encastable d'imatges
+Name[cs]=Zabudovaný prohlížeÄ obrázků
+Name[csb]=Wbùdowóny przezérnik òbrôzów
+Name[cy]=Gwelydd Delweddau Mewnadeiladadwy
+Name[da]=Billedfremviser som kan indlejres
+Name[de]=Eingebetteter Bildbetrachter
+Name[el]=Ενσωματώσιμος Ï€Ïοβολέας εικόνων
+Name[eo]=Enkonstruita bildrigardilo
+Name[es]=Visor de imágenes incrustable
+Name[et]=Põimitav pildifailide näitaja
+Name[eu]=Kapsulatutako irudi-ikustailea
+Name[fa]=مشاهده‌گر تصویر نهÙته
+Name[fi]=Upotettava kuvannäyttäjä
+Name[fr]=Afficheur d'images intégrable
+Name[fy]=Yn te sluten byldwerjefte
+Name[ga]=Amharcán Ãomhánna Inleabaithe
+Name[gl]=Visualizador de Imaxes Incrustábel
+Name[he]=מציג תמונות בר־הטבעה
+Name[hi]=अंतरà¥à¤¨à¤¿à¤¹à¤¿à¤¤ छवि दरà¥à¤¶à¤•
+Name[hr]=Ugradivi preglednik slika
+Name[hu]=Beágyazható képnézegető
+Name[id]=Viewer gambar yang embeddable
+Name[is]=Ãvefjanleg myndsjá
+Name[it]=Visualizzatore integrabile di immagini
+Name[ja]=埋ã‚è¾¼ã¿ç”»åƒãƒ“ューア
+Name[ka]=ნáƒáƒ®áƒáƒ¢áƒ”ბის ჩვენების ჩáƒáƒ“გმáƒáƒ“ი მáƒáƒ“ული
+Name[kk]=Ендірілетін кеÑкін қарау құралы
+Name[km]=កម្មវិធី​មើល​រូបភាព​ដែល​អាច​បង្កប់
+Name[ko]=ë¼ì›Œë„£ëŠ” 그림 보기
+Name[lb]=Abettbare Bild-Uweiser
+Name[lt]=Įdedamas piešinių žiūriklis
+Name[lv]=Iegultais AttÄ“lu SkatÄ«tÄjs
+Name[mk]=Вгнездлив гледач на Ñлики
+Name[mn]=Суулгаж болох Зураг Харагч
+Name[ms]=Pelihat Imej Boleh-serta
+Name[mt]=Werrej integrat tal-istampi
+Name[nb]=Bildeviser for innebyggbare bilder
+Name[nds]=Inbettbor Bildkieker
+Name[ne]=समà¥à¤®à¤¿à¤²à¤¿à¤¤ गरà¥à¤¨ सकिने छवि दरà¥à¤¶à¤•
+Name[nl]=Ingebedde afbeeldingenweergave
+Name[nn]=Innebygd biletvisar
+Name[nso]=Molebeledi yo a Robatsegago wa Ponagalo
+Name[pa]=ਸ਼ਾਮਿਲ ਚਿੱਤਰ ਦਰਸ਼ਕ
+Name[pl]=Wbudowana przeglądarka obrazków
+Name[pt]=Visualizador de Imagens Embebido
+Name[pt_BR]=Visualizador embutido de imagens
+Name[ro]=Vizualizor înglobat de imagini
+Name[ru]=Ð’Ñтраиваемый модуль проÑмотра изображений
+Name[rw]=Mugaragaza Ishusho Ishyirwamo
+Name[se]=Vuojuhanláhkái govvaÄájeheaddji
+Name[sk]=Vložiteľný prehliadaÄ obrázkov
+Name[sl]=Vgrajeni pregledovalnik slik
+Name[sq]=Shikues i Imazheve që mund të ngulitet
+Name[sr]=Уградиви приказивач Ñлика
+Name[sr@Latn]=Ugradivi prikazivaÄ slika
+Name[ss]=Sibuki semfanekiso lesilalisekako
+Name[sv]=Inbäddningsbar bildvisare
+Name[ta]=உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ பிமà¯à®ªà®•à¯ காடà¯à®Ÿà®¿
+Name[te]=పొదిగిన à°ªà±à°°à°¤à°¿à°¬à°¿à°‚à°¬ చూపరి
+Name[tg]=ТаÑвири Биниш дар Дарун Сохтан
+Name[th]=ตัวà¹à¸ªà¸”งภาพที่à¸à¸±à¸‡à¸•à¸±à¸§à¹„ด้
+Name[tr]=Gömülü Resim Görüntüleyici
+Name[tt]=Sürät öçen Qusılma-Kürsätkeç
+Name[uk]=Вмонтований переглÑдач зображень
+Name[uz]=Rasm koʻruvchi
+Name[uz@cyrillic]=РаÑм кўрувчи
+Name[ven]=Muvhoni wa tshifanyiso o dzheniswaho
+Name[vi]=Bộ xem ảnh có khả năng nhúng
+Name[wa]=Ravalé håyneu d' imådjes
+Name[xh]=Umboniseli Womfanekiso Olungisiweyo
+Name[zh_CN]=å¯åµŒå…¥çš„图åƒæŸ¥çœ‹å™¨
+Name[zh_HK]=å¯åµŒå…¥çš„圖檔檢視器
+Name[zh_TW]=å¯åµŒå…¥çš„å½±åƒæª¢è¦–器
+Name[zu]=Isithombe Sombukisi Oshuthisekayo
+ServiceTypes=KParts/ReadOnlyPart,Browser/View
+InitialPreference=4
+X-TDE-Library=tdehtmlimagepart
diff --git a/tdehtml/tdehtmlimage.h b/tdehtml/tdehtmlimage.h
new file mode 100644
index 000000000..b8d2d86d4
--- /dev/null
+++ b/tdehtml/tdehtmlimage.h
@@ -0,0 +1,119 @@
+/* This file is part of the KDE project
+ Copyright (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 __tdehtmlimage_h__
+#define __tdehtmlimage_h__
+
+#include "tdehtml_part.h"
+#include <tdeparts/factory.h>
+#include <tdeparts/browserextension.h>
+
+#include "misc/loader_client.h"
+
+class KHTMLPart;
+class TDEInstance;
+
+namespace tdehtml
+{
+ class CachedImage;
+}
+
+/**
+ * @internal
+ */
+class KHTMLImageFactory : public KParts::Factory
+{
+ Q_OBJECT
+public:
+ KHTMLImageFactory();
+ virtual ~KHTMLImageFactory();
+
+ virtual KParts::Part *createPartObject( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name,
+ const char *className, const TQStringList &args );
+
+ static TDEInstance *instance() { return s_instance; }
+
+private:
+ static TDEInstance *s_instance;
+};
+
+/**
+ * @internal
+ */
+class KHTMLImage : public KParts::ReadOnlyPart, public tdehtml::CachedObjectClient
+{
+ Q_OBJECT
+public:
+ KHTMLImage( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name, KHTMLPart::GUIProfile prof );
+ virtual ~KHTMLImage();
+
+ virtual bool openFile() { return true; } // grmbl, should be non-pure in part.h, IMHO
+
+ virtual bool openURL( const KURL &url );
+
+ virtual bool closeURL();
+
+ KHTMLPart *doc() const { return m_tdehtml; }
+
+ virtual void notifyFinished( tdehtml::CachedObject *o );
+
+protected:
+ virtual void guiActivateEvent( KParts::GUIActivateEvent *e );
+ virtual bool eventFilter( TQObject *filterTarget, TQEvent *e );
+
+private slots:
+ void restoreScrollPosition();
+// void slotImageJobFinished( TDEIO::Job *job );
+
+// void updateWindowCaption();
+
+private:
+ void disposeImage();
+
+ TQGuardedPtr<KHTMLPart> m_tdehtml;
+ KParts::BrowserExtension *m_ext;
+ TQString m_mimeType;
+ tdehtml::CachedImage *m_image;
+ int m_xOffset, m_yOffset;
+};
+
+/**
+ * @internal
+ */
+class KHTMLImageBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+public:
+ KHTMLImageBrowserExtension( KHTMLImage *parent, const char *name = 0 );
+
+ virtual int xOffset();
+ virtual int yOffset();
+
+protected slots:
+ void print();
+ void reparseConfiguration();
+ void disableScrolling();
+
+private:
+ KHTMLImage *m_imgPart;
+};
+
+#endif
diff --git a/tdehtml/tdehtmlpart_p.h b/tdehtml/tdehtmlpart_p.h
new file mode 100644
index 000000000..a18aa5cf8
--- /dev/null
+++ b/tdehtml/tdehtmlpart_p.h
@@ -0,0 +1,569 @@
+#ifndef tdehtmlpart_p_h
+#define tdehtmlpart_p_h
+
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999-2001 Lars Knoll <knoll@kde.org>
+ * 1999-2001 Antti Koivisto <koivisto@kde.org>
+ * 2000-2001 Simon Hausmann <hausmann@kde.org>
+ * 2000-2001 Dirk Mueller <mueller@kde.org>
+ * 2000 Stefan Schimanski <1Stein@gmx.de>
+ * 2001-2003 George Stiakos <staikos@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 <kcursor.h>
+#include <klibloader.h>
+#include <kxmlguifactory.h>
+#include <kaction.h>
+#include <tdeparts/partmanager.h>
+#include <tdeparts/statusbarextension.h>
+#include <tdeparts/browserextension.h>
+#ifndef KHTML_NO_WALLET
+#include <tdewallet.h>
+#endif
+
+#include <tqguardedptr.h>
+#include <tqmap.h>
+#include <tqtimer.h>
+#include <tqvaluelist.h>
+
+#include "html/html_formimpl.h"
+#include "tdehtml_run.h"
+#include "tdehtml_factory.h"
+#include "tdehtml_events.h"
+#include "tdehtml_ext.h"
+#include "tdehtml_iface.h"
+#include "tdehtml_settings.h"
+#include "misc/decoder.h"
+#include "ecma/kjs_proxy.h"
+
+class KFind;
+class KFindDialog;
+class KPopupMenu;
+class KSelectAction;
+class KURLLabel;
+class KJavaAppletContext;
+class KJSErrorDlg;
+
+namespace TDEIO
+{
+ class Job;
+ class TransferJob;
+}
+namespace KParts
+{
+ class StatusBarExtension;
+}
+
+namespace tdehtml
+{
+ class KDE_EXPORT ChildFrame : public TQObject
+ {
+ Q_OBJECT
+ public:
+ enum Type { Frame, IFrame, Object };
+
+ ChildFrame() : TQObject (0L, "tdehtml_child_frame") {
+ m_jscript = 0L;
+ m_kjs_lib = 0;
+ m_bCompleted = false; m_bPreloaded = false; m_type = Frame; m_bNotify = false;
+ m_bPendingRedirection = false;
+ }
+
+ ~ChildFrame() {
+ if (m_run) m_run->abort();
+ delete m_jscript;
+ if ( m_kjs_lib)
+ m_kjs_lib->unload();
+ }
+
+ TQGuardedPtr<tdehtml::RenderPart> m_frame;
+ TQGuardedPtr<KParts::ReadOnlyPart> m_part;
+ TQGuardedPtr<KParts::BrowserExtension> m_extension;
+ TQGuardedPtr<KParts::LiveConnectExtension> m_liveconnect;
+ TQString m_serviceName;
+ TQString m_serviceType;
+ KJSProxy *m_jscript;
+ KLibrary *m_kjs_lib;
+ bool m_bCompleted;
+ TQString m_name;
+ KParts::URLArgs m_args;
+ TQGuardedPtr<KHTMLRun> m_run;
+ bool m_bPreloaded;
+ KURL m_workingURL;
+ Type m_type;
+ TQStringList m_params;
+ bool m_bNotify;
+ bool m_bPendingRedirection;
+ protected slots:
+ void liveConnectEvent(const unsigned long, const TQString&, const KParts::LiveConnectExtension::ArgList&);
+ };
+
+}
+
+struct KHTMLFrameList : public TQValueList<tdehtml::ChildFrame*>
+{
+ Iterator find( const TQString &name ) KDE_NO_EXPORT;
+};
+
+typedef KHTMLFrameList::ConstIterator ConstFrameIt;
+typedef KHTMLFrameList::Iterator FrameIt;
+
+static int tdehtml_part_dcop_counter = 0;
+
+
+class KHTMLWalletQueue : public TQObject
+{
+ Q_OBJECT
+ public:
+ KHTMLWalletQueue(TQObject *parent) : TQObject(parent) {
+#ifndef KHTML_NO_WALLET
+ wallet = 0L;
+#endif // KHTML_NO_WALLET
+ }
+
+ virtual ~KHTMLWalletQueue() {
+#ifndef KHTML_NO_WALLET
+ delete wallet;
+ wallet = 0L;
+#endif // KHTML_NO_WALLET
+ }
+#ifndef KHTML_NO_WALLET
+ KWallet::Wallet *wallet;
+#endif // KHTML_NO_WALLET
+ typedef QPair<DOM::HTMLFormElementImpl*, TQGuardedPtr<DOM::DocumentImpl> > Caller;
+ typedef TQValueList<Caller> CallerList;
+ CallerList callers;
+ TQValueList<QPair<TQString, TQMap<TQString, TQString> > > savers;
+
+ signals:
+ void walletOpened(KWallet::Wallet*);
+
+ public slots:
+ void walletOpened(bool success) {
+#ifndef KHTML_NO_WALLET
+ if (!success) {
+ delete wallet;
+ wallet = 0L;
+ }
+ emit walletOpened(wallet);
+ if (wallet) {
+ if (!wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
+ wallet->createFolder(KWallet::Wallet::FormDataFolder());
+ }
+ for (CallerList::Iterator i = callers.begin(); i != callers.end(); ++i) {
+ if ((*i).first && (*i).second) {
+ (*i).first->walletOpened(wallet);
+ }
+ }
+ wallet->setFolder(KWallet::Wallet::FormDataFolder());
+ for (TQValueList<QPair<TQString, TQMap<TQString, TQString> > >::Iterator i = savers.begin(); i != savers.end(); ++i) {
+ wallet->writeMap((*i).first, (*i).second);
+ }
+ }
+ callers.clear();
+ savers.clear();
+ wallet = 0L; // gave it away
+#endif // KHTML_NO_WALLET
+ }
+};
+
+class KHTMLPartPrivate
+{
+ KHTMLPartPrivate(const KHTMLPartPrivate & other);
+ KHTMLPartPrivate& operator=(const KHTMLPartPrivate&);
+public:
+ KHTMLPartPrivate(TQObject* parent)
+ {
+ m_doc = 0L;
+ m_decoder = 0L;
+ m_wallet = 0L;
+ m_bWalletOpened = false;
+ m_runningScripts = 0;
+ m_job = 0L;
+ m_bComplete = true;
+ m_bLoadEventEmitted = true;
+ m_cachePolicy = TDEIO::CC_Verify;
+ m_manager = 0L;
+ m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
+ m_bClearing = false;
+ m_bCleared = false;
+ m_zoomFactor = 100;
+ m_bDnd = true;
+ m_startOffset = m_endOffset = 0;
+ m_startBeforeEnd = true;
+ m_extendAtEnd = true;
+ m_linkCursor = KCursor::handCursor();
+ m_loadedObjects = 0;
+ m_totalObjectCount = 0;
+ m_jobPercent = 0;
+ m_haveEncoding = false;
+ m_activeFrame = 0L;
+ m_find = 0;
+ m_findDialog = 0;
+ m_ssl_in_use = false;
+ m_jsedlg = 0;
+ m_formNotification = KHTMLPart::NoNotification;
+
+#ifndef Q_WS_QWS
+ m_javaContext = 0;
+#endif
+ m_cacheId = 0;
+ m_frameNameId = 1;
+
+ m_restored = false;
+ m_restoreScrollPosition = false;
+
+ m_focusNodeNumber = -1;
+ m_focusNodeRestored = false;
+
+ m_bJScriptForce = false;
+ m_bJScriptOverride = false;
+ m_bJavaForce = false;
+ m_bJavaOverride = false;
+ m_bPluginsForce = false;
+ m_bPluginsOverride = false;
+ m_onlyLocalReferences = false;
+
+ m_caretMode = false;
+ m_designMode = false;
+
+ m_metaRefreshEnabled = true;
+ m_statusMessagesEnabled = true;
+
+ m_bFirstData = true;
+ m_submitForm = 0;
+ m_delayRedirect = 0;
+ m_autoDetectLanguage = tdehtml::Decoder::SemiautomaticDetection;
+
+ // inherit settings from parent
+ if(parent && parent->inherits("KHTMLPart"))
+ {
+ KHTMLPart* part = static_cast<KHTMLPart*>(parent);
+ if(part->d)
+ {
+ m_bJScriptForce = part->d->m_bJScriptForce;
+ m_bJScriptOverride = part->d->m_bJScriptOverride;
+ m_bJavaForce = part->d->m_bJavaForce;
+ m_bJavaOverride = part->d->m_bJavaOverride;
+ m_bPluginsForce = part->d->m_bPluginsForce;
+ m_bPluginsOverride = part->d->m_bPluginsOverride;
+ // Same for SSL settings
+ m_ssl_in_use = part->d->m_ssl_in_use;
+ m_onlyLocalReferences = part->d->m_onlyLocalReferences;
+ m_caretMode = part->d->m_caretMode;
+ m_designMode = part->d->m_designMode;
+ m_zoomFactor = part->d->m_zoomFactor;
+ m_autoDetectLanguage = part->d->m_autoDetectLanguage;
+ m_encoding = part->d->m_encoding;
+ m_haveEncoding = part->d->m_haveEncoding;
+ }
+ }
+
+ m_focusNodeNumber = -1;
+ m_focusNodeRestored = false;
+ m_opener = 0;
+ m_openedByJS = false;
+ m_newJSInterpreterExists = false;
+ m_dcopobject = 0;
+ m_jobspeed = 0;
+ m_dcop_counter = ++tdehtml_part_dcop_counter;
+ m_statusBarWalletLabel = 0L;
+ m_statusBarUALabel = 0L;
+ m_statusBarJSErrorLabel = 0L;
+ m_userStyleSheetLastModified = 0;
+ m_wq = 0;
+ }
+ ~KHTMLPartPrivate()
+ {
+ delete m_dcopobject;
+ delete m_statusBarExtension;
+ delete m_extension;
+ delete m_settings;
+#ifndef KHTML_NO_WALLET
+ delete m_wallet;
+#endif
+#ifndef Q_WS_QWS
+ //delete m_javaContext;
+#endif
+ }
+
+ TQGuardedPtr<tdehtml::ChildFrame> m_frame;
+ KHTMLFrameList m_frames;
+ KHTMLFrameList m_objects;
+
+ TQGuardedPtr<KHTMLView> m_view;
+ KHTMLPartBrowserExtension *m_extension;
+ KParts::StatusBarExtension *m_statusBarExtension;
+ KHTMLPartBrowserHostExtension *m_hostExtension;
+ KURLLabel* m_statusBarIconLabel;
+ KURLLabel* m_statusBarWalletLabel;
+ KURLLabel* m_statusBarUALabel;
+ KURLLabel* m_statusBarJSErrorLabel;
+ KURLLabel* m_statusBarPopupLabel;
+ TQValueList<TQGuardedPtr<KHTMLPart> > m_suppressedPopupOriginParts;
+ int m_openableSuppressedPopups;
+ DOM::DocumentImpl *m_doc;
+ tdehtml::Decoder *m_decoder;
+ TQString m_encoding;
+ TQString m_sheetUsed;
+ long m_cacheId;
+ TQString scheduledScript;
+ DOM::Node scheduledScriptNode;
+
+ KWallet::Wallet* m_wallet;
+ int m_runningScripts;
+ bool m_bOpenMiddleClick :1;
+ bool m_bBackRightClick :1;
+ bool m_bJScriptEnabled :1;
+ bool m_bJScriptDebugEnabled :1;
+ bool m_bJavaEnabled :1;
+ bool m_bPluginsEnabled :1;
+ bool m_bJScriptForce :1;
+ bool m_bJScriptOverride :1;
+ bool m_bJavaForce :1;
+ bool m_bJavaOverride :1;
+ bool m_bPluginsForce :1;
+ bool m_metaRefreshEnabled :1;
+ bool m_bPluginsOverride :1;
+ bool m_restored :1;
+ bool m_restoreScrollPosition :1;
+ bool m_statusMessagesEnabled :1;
+ bool m_bWalletOpened :1;
+ bool m_urlSelectedOpenedURL:1; // KDE4: remove
+ int m_frameNameId;
+ int m_dcop_counter;
+ DCOPObject *m_dcopobject;
+
+#ifndef Q_WS_QWS
+ KJavaAppletContext *m_javaContext;
+#endif
+
+ KHTMLSettings *m_settings;
+
+ TDEIO::TransferJob * m_job;
+
+ TQString m_statusBarText[3];
+ unsigned long m_jobspeed;
+ TQString m_lastModified;
+ TQString m_httpHeaders;
+ TQString m_pageServices;
+
+ // QStrings for SSL metadata
+ // Note: When adding new variables don't forget to update ::saveState()/::restoreState()!
+ bool m_ssl_in_use;
+ TQString m_ssl_peer_certificate,
+ m_ssl_peer_chain,
+ m_ssl_peer_ip,
+ m_ssl_cipher,
+ m_ssl_cipher_desc,
+ m_ssl_cipher_version,
+ m_ssl_cipher_used_bits,
+ m_ssl_cipher_bits,
+ m_ssl_cert_state,
+ m_ssl_parent_ip,
+ m_ssl_parent_cert;
+
+ bool m_bComplete:1;
+ bool m_bLoadEventEmitted:1;
+ bool m_haveEncoding:1;
+ bool m_onlyLocalReferences :1;
+ bool m_redirectLockHistory:1;
+
+ KURL m_workingURL;
+
+ TDEIO::CacheControl m_cachePolicy;
+ TQTimer m_redirectionTimer;
+ TQTime m_parsetime;
+ int m_delayRedirect;
+ TQString m_redirectURL;
+
+ KAction *m_paViewDocument;
+ KAction *m_paViewFrame;
+ KAction *m_paViewInfo;
+ KAction *m_paSaveBackground;
+ KAction *m_paSaveDocument;
+ KAction *m_paSaveFrame;
+ KAction *m_paSecurity;
+ KActionMenu *m_paSetEncoding;
+ KSelectAction *m_paUseStylesheet;
+ KHTMLZoomFactorAction *m_paIncZoomFactor;
+ KHTMLZoomFactorAction *m_paDecZoomFactor;
+ KAction *m_paLoadImages;
+ KAction *m_paFind;
+ KAction *m_paFindNext;
+ KAction *m_paFindPrev;
+ KAction *m_paFindAheadText;
+ KAction *m_paFindAheadLinks;
+ KAction *m_paPrintFrame;
+ KAction *m_paSelectAll;
+ KAction *m_paDebugScript;
+ KAction *m_paDebugDOMTree;
+ KAction *m_paDebugRenderTree;
+ KAction *m_paStopAnimations;
+ KToggleAction *m_paToggleCaretMode;
+
+ KParts::PartManager *m_manager;
+
+ TQString m_popupMenuXML;
+ KHTMLPart::GUIProfile m_guiProfile;
+
+ int m_zoomFactor;
+
+ TQString m_strSelectedURL;
+ TQString m_strSelectedURLTarget;
+ TQString m_referrer;
+ TQString m_pageReferrer;
+
+ struct SubmitForm
+ {
+ const char *submitAction;
+ TQString submitUrl;
+ TQByteArray submitFormData;
+ TQString target;
+ TQString submitContentType;
+ TQString submitBoundary;
+ };
+
+ SubmitForm *m_submitForm;
+
+ bool m_bMousePressed;
+ bool m_bRightMousePressed;
+ DOM::Node m_mousePressNode; //node under the mouse when the mouse was pressed (set in the mouse handler)
+
+ // simply using the selection limits for the caret position does not suffice
+ // as we need to know on which side to extend the selection
+// DOM::Node m_caretNode; // node containing the caret
+// long m_caretOffset; // offset within this node (0-based)
+
+ // the caret uses the selection variables for its position. If m_extendAtEnd
+ // is true, m_selectionEnd and m_endOffset contain the mandatory caret
+ // position, otherwise it's m_selectionStart and m_startOffset.
+ DOM::Node m_selectionStart;
+ long m_startOffset;
+ DOM::Node m_selectionEnd;
+ long m_endOffset;
+ DOM::Node m_initialNode; // (Node, Offset) pair on which the
+ long m_initialOffset; // selection has been initiated
+ TQString m_overURL;
+ TQString m_overURLTarget;
+
+ bool m_startBeforeEnd;
+ bool m_extendAtEnd; // true if selection is to be extended at its end
+ enum { ExtendByChar, ExtendByWord, ExtendByLine } m_extendMode;
+ bool m_bDnd;
+ bool m_bFirstData;
+ bool m_bClearing;
+ bool m_bCleared;
+ bool m_bSecurityInQuestion;
+ bool m_focusNodeRestored;
+
+ int m_focusNodeNumber;
+
+ TQPoint m_dragStartPos;
+#ifdef KHTML_NO_SELECTION
+ TQPoint m_dragLastPos;
+#endif
+
+ bool m_designMode;
+ bool m_caretMode;
+
+ TQCursor m_linkCursor;
+ TQTimer m_scrollTimer;
+
+ unsigned long m_loadedObjects;
+ unsigned long m_totalObjectCount;
+ unsigned int m_jobPercent;
+
+ KHTMLPart::FormNotification m_formNotification;
+ TQTimer m_progressUpdateTimer;
+
+ TQStringList m_pluginPageQuestionAsked;
+
+ /////////// 'Find' feature
+ struct StringPortion
+ {
+ // Just basic ref/deref on our node to make sure it doesn't get deleted
+ StringPortion( int i, DOM::NodeImpl* n ) : index(i), node(n) { if (node) node->ref(); }
+ StringPortion() : index(0), node(0) {} // for QValueList
+ StringPortion( const StringPortion& other ) : node(0) { operator=(other); }
+ StringPortion& operator=( const StringPortion& other ) {
+ index=other.index;
+ if (other.node) other.node->ref();
+ if (node) node->deref();
+ node=other.node;
+ return *this;
+ }
+ ~StringPortion() { if (node) node->deref(); }
+
+ int index;
+ DOM::NodeImpl *node;
+ };
+ TQValueList<StringPortion> m_stringPortions;
+
+ KFind *m_find;
+ KFindDialog *m_findDialog;
+
+ struct findState
+ {
+ findState() : options( 0 ), last_dir( -1 ) {}
+ TQStringList history;
+ TQString text;
+ int options;
+ int last_dir; // -1=unknown,0=forward,1=backward
+ };
+
+ findState m_lastFindState;
+
+ KJSErrorDlg *m_jsedlg;
+
+ DOM::NodeImpl *m_findNode; // current node
+ DOM::NodeImpl *m_findNodeEnd; // end node
+ DOM::NodeImpl *m_findNodeStart; // start node
+ DOM::NodeImpl *m_findNodePrevious; // previous node used for find
+ int m_findPos; // current pos in current node
+ int m_findPosEnd; // pos in end node
+ int m_findPosStart; // pos in start node
+ /////////
+
+ //TQGuardedPtr<KParts::Part> m_activeFrame;
+ KParts::Part * m_activeFrame;
+ TQGuardedPtr<KHTMLPart> m_opener;
+ bool m_openedByJS;
+ bool m_newJSInterpreterExists; // set to 1 by setOpenedByJS, for window.open
+
+ tdehtml::Decoder::AutoDetectLanguage m_autoDetectLanguage;
+ KPopupMenu *m_automaticDetection;
+ KSelectAction *m_manualDetection;
+
+ void setFlagRecursively(bool KHTMLPartPrivate::*flag, bool value);
+ /** returns the caret node */
+ DOM::Node &caretNode() {
+ return m_extendAtEnd ? m_selectionEnd : m_selectionStart;
+ }
+ /** returns the caret offset */
+ long &caretOffset() {
+ return m_extendAtEnd ? m_endOffset : m_startOffset;
+ }
+
+ time_t m_userStyleSheetLastModified;
+
+ KHTMLWalletQueue *m_wq;
+};
+
+#endif
diff --git a/tdehtml/tdehtmlview.cpp b/tdehtml/tdehtmlview.cpp
new file mode 100644
index 000000000..383c7628a
--- /dev/null
+++ b/tdehtml/tdehtmlview.cpp
@@ -0,0 +1,4623 @@
+/* This file is part of the KDE project
+ *
+ * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ * 1999 Lars Knoll <knoll@kde.org>
+ * 1999 Antti Koivisto <koivisto@kde.org>
+ * 2000-2004 Dirk Mueller <mueller@kde.org>
+ * 2003 Leo Savernik <l.savernik@aon.at>
+ * 2003-2004 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 "tdehtmlview.moc"
+
+#include "tdehtmlview.h"
+
+#include "tdehtml_part.h"
+#include "tdehtml_events.h"
+
+#include "html/html_documentimpl.h"
+#include "html/html_inlineimpl.h"
+#include "html/html_formimpl.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_frames.h"
+#include "rendering/render_replaced.h"
+#include "rendering/render_layer.h"
+#include "rendering/render_line.h"
+#include "rendering/render_table.h"
+// removeme
+#define protected public
+#include "rendering/render_text.h"
+#undef protected
+#include "xml/dom2_eventsimpl.h"
+#include "css/cssstyleselector.h"
+#include "css/csshelper.h"
+#include "misc/htmlhashes.h"
+#include "misc/helper.h"
+#include "misc/loader.h"
+#include "tdehtml_settings.h"
+#include "tdehtml_printsettings.h"
+
+#include "tdehtmlpart_p.h"
+
+#ifndef KHTML_NO_CARET
+#include "tdehtml_caret_p.h"
+#include "xml/dom2_rangeimpl.h"
+#endif
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kiconloader.h>
+#include <kimageio.h>
+#include <klocale.h>
+#include <knotifyclient.h>
+#include <kprinter.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+#include <kstdaccel.h>
+#include <kstringhandler.h>
+#include <kurldrag.h>
+
+#include <tqbitmap.h>
+#include <tqlabel.h>
+#include <tqobjectlist.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqpainter.h>
+#include <tqptrdict.h>
+#include <tqtooltip.h>
+#include <tqstring.h>
+#include <tqstylesheet.h>
+#include <tqtimer.h>
+#include <tqvaluevector.h>
+
+//#define DEBUG_NO_PAINT_BUFFER
+
+//#define DEBUG_FLICKER
+
+//#define DEBUG_PIXEL
+
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+#endif
+
+#define PAINT_BUFFER_HEIGHT 128
+
+#if 0
+namespace tdehtml {
+ void dumpLineBoxes(RenderFlow *flow);
+}
+#endif
+
+using namespace DOM;
+using namespace tdehtml;
+class KHTMLToolTip;
+
+
+#ifndef QT_NO_TOOLTIP
+
+class KHTMLToolTip : public TQToolTip
+{
+public:
+ KHTMLToolTip(KHTMLView *view, KHTMLViewPrivate* vp) : TQToolTip(view->viewport())
+ {
+ m_view = view;
+ m_viewprivate = vp;
+ };
+
+protected:
+ virtual void maybeTip(const TQPoint &);
+
+private:
+ KHTMLView *m_view;
+ KHTMLViewPrivate* m_viewprivate;
+};
+
+#endif
+
+class KHTMLViewPrivate {
+ friend class KHTMLToolTip;
+public:
+
+ enum PseudoFocusNodes {
+ PFNone,
+ PFTop,
+ PFBottom
+ };
+
+ enum CompletedState {
+ CSNone = 0,
+ CSFull,
+ CSActionPending
+ };
+
+ KHTMLViewPrivate()
+ : underMouse( 0 ), underMouseNonShared( 0 ), visibleWidgets( 107 )
+#ifndef NO_SMOOTH_SCROLL_HACK
+ , dx(0), dy(0), ddx(0), ddy(0), rdx(0), rdy(0), scrolling(false)
+#endif
+ {
+#ifndef KHTML_NO_CARET
+ m_caretViewContext = 0;
+ m_editorContext = 0;
+#endif // KHTML_NO_CARET
+ postponed_autorepeat = NULL;
+ reset();
+ vmode = TQScrollView::Auto;
+ hmode = TQScrollView::Auto;
+ tp=0;
+ paintBuffer=0;
+ vertPaintBuffer=0;
+ formCompletions=0;
+ prevScrollbarVisible = true;
+ tooltip = 0;
+ possibleTripleClick = false;
+ emitCompletedAfterRepaint = CSNone;
+ cursor_icon_widget = NULL;
+ m_mouseScrollTimer = 0;
+ m_mouseScrollIndicator = 0;
+ }
+ ~KHTMLViewPrivate()
+ {
+ delete formCompletions;
+ delete tp; tp = 0;
+ delete paintBuffer; paintBuffer =0;
+ delete vertPaintBuffer;
+ delete postponed_autorepeat;
+ if (underMouse)
+ underMouse->deref();
+ if (underMouseNonShared)
+ underMouseNonShared->deref();
+ delete tooltip;
+#ifndef KHTML_NO_CARET
+ delete m_caretViewContext;
+ delete m_editorContext;
+#endif // KHTML_NO_CARET
+ delete cursor_icon_widget;
+ delete m_mouseScrollTimer;
+ delete m_mouseScrollIndicator;
+ }
+ void reset()
+ {
+ if (underMouse)
+ underMouse->deref();
+ underMouse = 0;
+ if (underMouseNonShared)
+ underMouseNonShared->deref();
+ underMouseNonShared = 0;
+ linkPressed = false;
+ useSlowRepaints = false;
+ tabMovePending = false;
+ lastTabbingDirection = true;
+ pseudoFocusNode = PFNone;
+#ifndef KHTML_NO_SCROLLBARS
+ //We don't turn off the toolbars here
+ //since if the user turns them
+ //off, then chances are they want them turned
+ //off always - even after a reset.
+#else
+ vmode = TQScrollView::AlwaysOff;
+ hmode = TQScrollView::AlwaysOff;
+#endif
+#ifdef DEBUG_PIXEL
+ timer.start();
+ pixelbooth = 0;
+ repaintbooth = 0;
+#endif
+ scrollBarMoved = false;
+ contentsMoving = false;
+ ignoreWheelEvents = false;
+ borderX = 30;
+ borderY = 30;
+ paged = false;
+ clickX = -1;
+ clickY = -1;
+ prevMouseX = -1;
+ prevMouseY = -1;
+ clickCount = 0;
+ isDoubleClick = false;
+ scrollingSelf = false;
+ delete postponed_autorepeat;
+ postponed_autorepeat = NULL;
+ layoutTimerId = 0;
+ repaintTimerId = 0;
+ scrollTimerId = 0;
+ scrollSuspended = false;
+ scrollSuspendPreActivate = false;
+ complete = false;
+ firstRelayout = true;
+ needsFullRepaint = true;
+ dirtyLayout = false;
+ layoutSchedulingEnabled = true;
+ painting = false;
+ updateRegion = TQRegion();
+ m_dialogsAllowed = true;
+#ifndef KHTML_NO_CARET
+ if (m_caretViewContext) {
+ m_caretViewContext->caretMoved = false;
+ m_caretViewContext->keyReleasePending = false;
+ }/*end if*/
+#endif // KHTML_NO_CARET
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ typeAheadActivated = false;
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+ accessKeysActivated = false;
+ accessKeysPreActivate = false;
+
+ // We ref/deref to ensure defaultHTMLSettings is available
+ KHTMLFactory::ref();
+ accessKeysEnabled = KHTMLFactory::defaultHTMLSettings()->accessKeysEnabled();
+ KHTMLFactory::deref();
+
+ emitCompletedAfterRepaint = CSNone;
+ }
+ void newScrollTimer(TQWidget *view, int tid)
+ {
+ //kdDebug(6000) << "newScrollTimer timer " << tid << endl;
+ view->killTimer(scrollTimerId);
+ scrollTimerId = tid;
+ scrollSuspended = false;
+ }
+ enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown };
+
+ void adjustScroller(TQWidget *view, ScrollDirection direction, ScrollDirection oppositedir)
+ {
+ static const struct { int msec, pixels; } timings [] = {
+ {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1},
+ {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0}
+ };
+ if (!scrollTimerId ||
+ (static_cast<int>(scrollDirection) != direction &&
+ (static_cast<int>(scrollDirection) != oppositedir || scrollSuspended))) {
+ scrollTiming = 6;
+ scrollBy = timings[scrollTiming].pixels;
+ scrollDirection = direction;
+ newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
+ } else if (scrollDirection == direction &&
+ timings[scrollTiming+1].msec && !scrollSuspended) {
+ scrollBy = timings[++scrollTiming].pixels;
+ newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
+ } else if (scrollDirection == oppositedir) {
+ if (scrollTiming) {
+ scrollBy = timings[--scrollTiming].pixels;
+ newScrollTimer(view, view->startTimer(timings[scrollTiming].msec));
+ }
+ }
+ scrollSuspended = false;
+ }
+
+#ifndef KHTML_NO_CARET
+ /** this function returns an instance of the caret view context. If none
+ * exists, it will be instantiated.
+ */
+ CaretViewContext *caretViewContext() {
+ if (!m_caretViewContext) m_caretViewContext = new CaretViewContext();
+ return m_caretViewContext;
+ }
+ /** this function returns an instance of the editor context. If none
+ * exists, it will be instantiated.
+ */
+ EditorContext *editorContext() {
+ if (!m_editorContext) m_editorContext = new EditorContext();
+ return m_editorContext;
+ }
+#endif // KHTML_NO_CARET
+
+#ifdef DEBUG_PIXEL
+ TQTime timer;
+ unsigned int pixelbooth;
+ unsigned int repaintbooth;
+#endif
+
+ TQPainter *tp;
+ TQPixmap *paintBuffer;
+ TQPixmap *vertPaintBuffer;
+ NodeImpl *underMouse;
+ NodeImpl *underMouseNonShared;
+
+ bool tabMovePending:1;
+ bool lastTabbingDirection:1;
+ PseudoFocusNodes pseudoFocusNode:2;
+ bool scrollBarMoved:1;
+ bool contentsMoving:1;
+
+ TQScrollView::ScrollBarMode vmode;
+ TQScrollView::ScrollBarMode hmode;
+ bool prevScrollbarVisible:1;
+ bool linkPressed:1;
+ bool useSlowRepaints:1;
+ bool ignoreWheelEvents:1;
+
+ int borderX, borderY;
+ KSimpleConfig *formCompletions;
+
+ bool paged;
+
+ int clickX, clickY, clickCount;
+ bool isDoubleClick;
+
+ int prevMouseX, prevMouseY;
+ bool scrollingSelf;
+ int layoutTimerId;
+ TQKeyEvent* postponed_autorepeat;
+
+ int repaintTimerId;
+ int scrollTimerId;
+ int scrollTiming;
+ int scrollBy;
+ ScrollDirection scrollDirection :2;
+ bool scrollSuspended :1;
+ bool scrollSuspendPreActivate :1;
+ bool complete :1;
+ bool firstRelayout :1;
+ bool layoutSchedulingEnabled :1;
+ bool needsFullRepaint :1;
+ bool painting :1;
+ bool possibleTripleClick :1;
+ bool dirtyLayout :1;
+ bool m_dialogsAllowed :1;
+ TQRegion updateRegion;
+ KHTMLToolTip *tooltip;
+ TQPtrDict<TQWidget> visibleWidgets;
+#ifndef KHTML_NO_CARET
+ CaretViewContext *m_caretViewContext;
+ EditorContext *m_editorContext;
+#endif // KHTML_NO_CARET
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ TQString findString;
+ TQTimer timer;
+ bool findLinksOnly;
+ bool typeAheadActivated;
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+ bool accessKeysEnabled;
+ bool accessKeysActivated;
+ bool accessKeysPreActivate;
+ CompletedState emitCompletedAfterRepaint;
+
+ TQWidget* cursor_icon_widget;
+
+ // scrolling activated by MMB
+ short m_mouseScroll_byX;
+ short m_mouseScroll_byY;
+ TQTimer *m_mouseScrollTimer;
+ TQWidget *m_mouseScrollIndicator;
+#ifndef NO_SMOOTH_SCROLL_HACK
+ TQTimer timer2;
+ int dx;
+ int dy;
+ // Step size * 16 and residual to avoid huge difference between 1px/step and 2px/step
+ int ddx;
+ int ddy;
+ int rdx;
+ int rdy;
+ bool scrolling;
+#endif
+};
+
+#ifndef QT_NO_TOOLTIP
+
+/** calculates the client-side image map rectangle for the given image element
+ * @param img image element
+ * @param scrollOfs scroll offset of viewport in content coordinates
+ * @param p position to be probed in viewport coordinates
+ * @param r returns the bounding rectangle in content coordinates
+ * @param s returns the title string
+ * @return true if an appropriate area was found -- only in this case r and
+ * s are valid, false otherwise
+ */
+static bool findImageMapRect(HTMLImageElementImpl *img, const TQPoint &scrollOfs,
+ const TQPoint &p, TQRect &r, TQString &s)
+{
+ HTMLMapElementImpl* map;
+ if (img && img->getDocument()->isHTMLDocument() &&
+ (map = static_cast<HTMLDocumentImpl*>(img->getDocument())->getMap(img->imageMap()))) {
+ RenderObject::NodeInfo info(true, false);
+ RenderObject *rend = img->renderer();
+ int ax, ay;
+ if (!rend || !rend->absolutePosition(ax, ay))
+ return false;
+ // we're a client side image map
+ bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(),
+ p.y() - ay + scrollOfs.y(), rend->contentWidth(),
+ rend->contentHeight(), info);
+ if (inside && info.URLElement()) {
+ HTMLAreaElementImpl *area = static_cast<HTMLAreaElementImpl *>(info.URLElement());
+ Q_ASSERT(area->id() == ID_AREA);
+ s = area->getAttribute(ATTR_TITLE).string();
+ TQRegion reg = area->cachedRegion();
+ if (!s.isEmpty() && !reg.isEmpty()) {
+ r = reg.boundingRect();
+ r.moveBy(ax, ay);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void KHTMLToolTip::maybeTip(const TQPoint& p)
+{
+ DOM::NodeImpl *node = m_viewprivate->underMouseNonShared;
+ TQRect region;
+ while ( node ) {
+ if ( node->isElementNode() ) {
+ DOM::ElementImpl *e = static_cast<DOM::ElementImpl*>( node );
+ TQRect r;
+ TQString s;
+ bool found = false;
+ // for images, check if it is part of a client-side image map,
+ // and query the <area>s' title attributes, too
+ if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) {
+ found = findImageMapRect(static_cast<HTMLImageElementImpl *>(e),
+ m_view->viewportToContents(TQPoint(0, 0)), p, r, s);
+ }
+ if (!found) {
+ s = e->getAttribute( ATTR_TITLE ).string();
+ r = node->getRect();
+ }
+ region |= TQRect( m_view->contentsToViewport( r.topLeft() ), r.size() );
+ if ( !s.isEmpty() ) {
+ tip( region, TQStyleSheet::convertFromPlainText( s, TQStyleSheetItem::WhiteSpaceNormal ) );
+ break;
+ }
+ }
+ node = node->parentNode();
+ }
+}
+#endif
+
+KHTMLView::KHTMLView( KHTMLPart *part, TQWidget *parent, const char *name)
+ : TQScrollView( parent, name, (WFlags)(WResizeNoErase | WRepaintNoErase) )
+{
+ m_medium = "screen";
+
+ m_part = part;
+ d = new KHTMLViewPrivate;
+ TQScrollView::setVScrollBarMode(d->vmode);
+ TQScrollView::setHScrollBarMode(d->hmode);
+ connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), this, TQT_SLOT(slotPaletteChanged()));
+ connect(this, TQT_SIGNAL(contentsMoving(int, int)), this, TQT_SLOT(slotScrollBarMoved()));
+
+ // initialize QScrollView
+ enableClipper(true);
+ // hack to get unclipped painting on the viewport.
+ static_cast<KHTMLView *>(TQT_TQWIDGET(viewport()))->setWFlags(WPaintUnclipped);
+
+ setResizePolicy(Manual);
+ viewport()->setMouseTracking(true);
+ viewport()->setBackgroundMode(NoBackground);
+
+ KImageIO::registerFormats();
+
+#ifndef QT_NO_TOOLTIP
+ d->tooltip = new KHTMLToolTip( this, d );
+#endif
+
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ connect(&d->timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(findTimeout()));
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+
+ init();
+
+ viewport()->show();
+#ifndef NO_SMOOTH_SCROLL_HACK
+#define timer timer2
+ connect(&d->timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(scrollTick()));
+#undef timer
+#endif
+}
+
+KHTMLView::~KHTMLView()
+{
+ closeChildDialogs();
+ if (m_part)
+ {
+ //WABA: Is this Ok? Do I need to deref it as well?
+ //Does this need to be done somewhere else?
+ DOM::DocumentImpl *doc = m_part->xmlDocImpl();
+ if (doc)
+ doc->detach();
+ }
+ delete d; d = 0;
+}
+
+void KHTMLView::init()
+{
+ if(!d->paintBuffer) d->paintBuffer = new TQPixmap(PAINT_BUFFER_HEIGHT, PAINT_BUFFER_HEIGHT);
+ if(!d->vertPaintBuffer)
+ d->vertPaintBuffer = new TQPixmap(10, PAINT_BUFFER_HEIGHT);
+ if(!d->tp) d->tp = new TQPainter();
+
+ setFocusPolicy(TQ_StrongFocus);
+ viewport()->setFocusProxy(this);
+
+ _marginWidth = -1; // undefined
+ _marginHeight = -1;
+ _width = 0;
+ _height = 0;
+
+ installEventFilter(this);
+
+ setAcceptDrops(true);
+ TQSize s = viewportSize(4095, 4095);
+ resizeContents(s.width(), s.height());
+}
+
+void KHTMLView::clear()
+{
+ // work around QScrollview's unbelievable bugginess
+ setStaticBackground(true);
+#ifndef KHTML_NO_CARET
+ if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff();
+#endif
+
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ if( d->typeAheadActivated )
+ findTimeout();
+#endif
+ if (d->accessKeysEnabled && d->accessKeysActivated)
+ accessKeysTimeout();
+ viewport()->unsetCursor();
+ if ( d->cursor_icon_widget )
+ d->cursor_icon_widget->hide();
+ d->reset();
+ TQT_TQOBJECT(this)->killTimers();
+ emit cleared();
+
+ TQScrollView::setHScrollBarMode(d->hmode);
+ TQScrollView::setVScrollBarMode(d->vmode);
+ verticalScrollBar()->setEnabled( false );
+ horizontalScrollBar()->setEnabled( false );
+}
+
+void KHTMLView::hideEvent(TQHideEvent* e)
+{
+ TQScrollView::hideEvent(e);
+ if ( m_part && m_part->xmlDocImpl() )
+ m_part->xmlDocImpl()->docLoader()->pauseAnimations();
+}
+
+void KHTMLView::showEvent(TQShowEvent* e)
+{
+ TQScrollView::showEvent(e);
+ if ( m_part && m_part->xmlDocImpl() )
+ m_part->xmlDocImpl()->docLoader()->resumeAnimations();
+}
+
+void KHTMLView::resizeEvent (TQResizeEvent* e)
+{
+ int dw = e->oldSize().width() - e->size().width();
+ int dh = e->oldSize().height() - e->size().height();
+
+ // if we are shrinking the view, don't allow the content to overflow
+ // before the layout occurs - we don't know if we need scrollbars yet
+ dw = dw>0 ? kMax(0, contentsWidth()-dw) : contentsWidth();
+ dh = dh>0 ? kMax(0, contentsHeight()-dh) : contentsHeight();
+
+ resizeContents(dw, dh);
+
+ TQScrollView::resizeEvent(e);
+
+ if ( m_part && m_part->xmlDocImpl() )
+ m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false );
+}
+
+void KHTMLView::viewportResizeEvent (TQResizeEvent* e)
+{
+ TQScrollView::viewportResizeEvent(e);
+
+ //int w = visibleWidth();
+ //int h = visibleHeight();
+
+ if (d->layoutSchedulingEnabled)
+ layout();
+#ifndef KHTML_NO_CARET
+ else {
+ hideCaret();
+ recalcAndStoreCaretPos();
+ showCaret();
+ }/*end if*/
+#endif
+
+ TDEApplication::sendPostedEvents(viewport(), TQEvent::Paint);
+}
+
+// this is to get rid of a compiler virtual overload mismatch warning. do not remove
+void KHTMLView::drawContents( TQPainter*)
+{
+}
+
+void KHTMLView::drawContents( TQPainter *p, int ex, int ey, int ew, int eh )
+{
+#ifdef DEBUG_PIXEL
+
+ if ( d->timer.elapsed() > 5000 ) {
+ tqDebug( "drawed %d pixels in %d repaints the last %d milliseconds",
+ d->pixelbooth, d->repaintbooth, d->timer.elapsed() );
+ d->timer.restart();
+ d->pixelbooth = 0;
+ d->repaintbooth = 0;
+ }
+ d->pixelbooth += ew*eh;
+ d->repaintbooth++;
+#endif
+
+ //kdDebug( 6000 ) << "drawContents this="<< this <<" x=" << ex << ",y=" << ey << ",w=" << ew << ",h=" << eh << endl;
+ if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) {
+ p->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base));
+ return;
+ } else if ( d->complete && static_cast<RenderCanvas*>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
+ // an external update request happens while we have a layout scheduled
+ unscheduleRelayout();
+ layout();
+ }
+
+ if (d->painting) {
+ kdDebug( 6000 ) << "WARNING: drawContents reentered! " << endl;
+ return;
+ }
+ d->painting = true;
+
+ TQPoint pt = contentsToViewport(TQPoint(ex, ey));
+ TQRegion cr = TQRect(pt.x(), pt.y(), ew, eh);
+
+ // kdDebug(6000) << "clip rect: " << TQRect(pt.x(), pt.y(), ew, eh) << endl;
+ for (TQPtrDictIterator<TQWidget> it(d->visibleWidgets); it.current(); ++it) {
+ TQWidget *w = it.current();
+ RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
+ if (w && rw && !rw->isKHTMLWidget()) {
+ int x, y;
+ rw->absolutePosition(x, y);
+ contentsToViewport(x, y, x, y);
+ int pbx = rw->borderLeft()+rw->paddingLeft();
+ int pby = rw->borderTop()+rw->paddingTop();
+ TQRect g = TQRect(x+pbx, y+pby,
+ rw->width()-pbx-rw->borderRight()-rw->paddingRight(),
+ rw->height()-pby-rw->borderBottom()-rw->paddingBottom());
+ if ( !rw->isFrame() && ((g.top() > pt.y()+eh) || (g.bottom() <= pt.y()) ||
+ (g.right() <= pt.x()) || (g.left() > pt.x()+ew) ))
+ continue;
+ RenderLayer* rl = rw->needsMask() ? rw->enclosingStackingContext() : 0;
+ TQRegion mask = rl ? rl->getMask() : TQRegion();
+ if (!mask.isNull()) {
+ TQPoint o(0,0);
+ o = contentsToViewport(o);
+ mask.translate(o.x(),o.y());
+ mask = mask.intersect( TQRect(g.x(),g.y(),g.width(),g.height()) );
+ cr -= mask;
+ } else {
+ cr -= g;
+ }
+ }
+ }
+
+#if 0
+ // this is commonly the case with framesets. we still do
+ // want to paint them, otherwise the widgets don't get placed.
+ if (cr.isEmpty()) {
+ d->painting = false;
+ return;
+ }
+#endif
+
+#ifndef DEBUG_NO_PAINT_BUFFER
+ p->setClipRegion(cr);
+
+ if (eh > PAINT_BUFFER_HEIGHT && ew <= 10) {
+ if ( d->vertPaintBuffer->height() < visibleHeight() )
+ d->vertPaintBuffer->resize(10, visibleHeight());
+ d->tp->begin(d->vertPaintBuffer);
+ d->tp->translate(-ex, -ey);
+ d->tp->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base));
+ m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, TQRect(ex, ey, ew, eh));
+ d->tp->end();
+ p->drawPixmap(ex, ey, *d->vertPaintBuffer, 0, 0, ew, eh);
+ }
+ else {
+ if ( d->paintBuffer->width() < visibleWidth() )
+ d->paintBuffer->resize(visibleWidth(),PAINT_BUFFER_HEIGHT);
+
+ int py=0;
+ while (py < eh) {
+ int ph = eh-py < PAINT_BUFFER_HEIGHT ? eh-py : PAINT_BUFFER_HEIGHT;
+ d->tp->begin(d->paintBuffer);
+ d->tp->translate(-ex, -ey-py);
+ d->tp->fillRect(ex, ey+py, ew, ph, palette().active().brush(TQColorGroup::Base));
+ m_part->xmlDocImpl()->renderer()->layer()->paint(d->tp, TQRect(ex, ey+py, ew, ph));
+ d->tp->end();
+
+ p->drawPixmap(ex, ey+py, *d->paintBuffer, 0, 0, ew, ph);
+ py += PAINT_BUFFER_HEIGHT;
+ }
+ }
+#else // !DEBUG_NO_PAINT_BUFFER
+static int cnt=0;
+ ex = contentsX(); ey = contentsY();
+ ew = visibleWidth(); eh = visibleHeight();
+ TQRect pr(ex,ey,ew,eh);
+ kdDebug() << "[" << ++cnt << "]" << " clip region: " << pr << endl;
+// p->setClipRegion(TQRect(0,0,ew,eh));
+// p->translate(-ex, -ey);
+ p->fillRect(ex, ey, ew, eh, palette().active().brush(TQColorGroup::Base));
+ m_part->xmlDocImpl()->renderer()->layer()->paint(p, pr);
+#endif // DEBUG_NO_PAINT_BUFFER
+
+#ifndef KHTML_NO_CARET
+ if (d->m_caretViewContext && d->m_caretViewContext->visible) {
+ TQRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width, d->m_caretViewContext->height);
+ if (pos.intersects(TQRect(ex, ey, ew, eh))) {
+ p->setRasterOp(XorROP);
+ p->setPen(white);
+ if (pos.width() == 1)
+ p->drawLine(pos.topLeft(), pos.bottomRight());
+ else {
+ p->fillRect(pos, white);
+ }/*end if*/
+ }/*end if*/
+ }/*end if*/
+#endif // KHTML_NO_CARET
+
+// p->setPen(TQPen(magenta,0,DashDotDotLine));
+// p->drawRect(dbg_paint_rect);
+
+ tdehtml::DrawContentsEvent event( p, ex, ey, ew, eh );
+ TQApplication::sendEvent( m_part, &event );
+
+ d->painting = false;
+}
+
+void KHTMLView::setMarginWidth(int w)
+{
+ // make it update the rendering area when set
+ _marginWidth = w;
+}
+
+void KHTMLView::setMarginHeight(int h)
+{
+ // make it update the rendering area when set
+ _marginHeight = h;
+}
+
+void KHTMLView::layout()
+{
+ if( m_part && m_part->xmlDocImpl() ) {
+ DOM::DocumentImpl *document = m_part->xmlDocImpl();
+
+ tdehtml::RenderCanvas* canvas = static_cast<tdehtml::RenderCanvas *>(document->renderer());
+ if ( !canvas ) return;
+
+ d->layoutSchedulingEnabled=false;
+
+ // the reference object for the overflow property on canvas
+ RenderObject * ref = 0;
+ RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0;
+
+ if (document->isHTMLDocument()) {
+ NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
+ if(body && body->renderer() && body->id() == ID_FRAMESET) {
+ TQScrollView::setVScrollBarMode(AlwaysOff);
+ TQScrollView::setHScrollBarMode(AlwaysOff);
+ body->renderer()->setNeedsLayout(true);
+// if (d->tooltip) {
+// delete d->tooltip;
+// d->tooltip = 0;
+// }
+ }
+ else {
+ if (!d->tooltip)
+ d->tooltip = new KHTMLToolTip( this, d );
+ // only apply body's overflow to canvas if root as a visible overflow
+ if (root)
+ ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer();
+ }
+ } else {
+ ref = root;
+ }
+ if (ref) {
+ if( ref->style()->overflowX() == OHIDDEN ) {
+ if (d->hmode == Auto) TQScrollView::setHScrollBarMode(AlwaysOff);
+ } else if (ref->style()->overflowX() == OSCROLL ) {
+ if (d->hmode == Auto) TQScrollView::setHScrollBarMode(AlwaysOn);
+ } else {
+ if (TQScrollView::hScrollBarMode() == AlwaysOff) TQScrollView::setHScrollBarMode(d->hmode);
+ } if ( ref->style()->overflowY() == OHIDDEN ) {
+ if (d->vmode == Auto) TQScrollView::setVScrollBarMode(AlwaysOff);
+ } else if (ref->style()->overflowY() == OSCROLL ) {
+ if (d->vmode == Auto) TQScrollView::setVScrollBarMode(AlwaysOn);
+ } else {
+ if (TQScrollView::vScrollBarMode() == AlwaysOff) TQScrollView::setVScrollBarMode(d->vmode);
+ }
+ }
+ d->needsFullRepaint = d->firstRelayout;
+ if (_height != visibleHeight() || _width != visibleWidth()) {;
+ d->needsFullRepaint = true;
+ _height = visibleHeight();
+ _width = visibleWidth();
+ }
+ //TQTime qt;
+ //qt.start();
+ canvas->layout();
+
+ emit finishedLayout();
+ if (d->firstRelayout) {
+ // make sure firstRelayout is set to false now in case this layout
+ // wasn't scheduled
+ d->firstRelayout = false;
+ verticalScrollBar()->setEnabled( true );
+ horizontalScrollBar()->setEnabled( true );
+ }
+#if 0
+ ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
+ if (listitem) kdDebug(6000) << "after layout, before repaint" << endl;
+ if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
+#endif
+#ifndef KHTML_NO_CARET
+ hideCaret();
+ if ((m_part->isCaretMode() || m_part->isEditable())
+ && !d->complete && d->m_caretViewContext
+ && !d->m_caretViewContext->caretMoved) {
+ initCaret();
+ } else {
+ recalcAndStoreCaretPos();
+ showCaret();
+ }/*end if*/
+#endif
+ if (d->accessKeysEnabled && d->accessKeysActivated) {
+ emit hideAccessKeys();
+ displayAccessKeys();
+ }
+ //kdDebug( 6000 ) << "TIME: layout() dt=" << qt.elapsed() << endl;
+ }
+ else
+ _width = visibleWidth();
+
+ killTimer(d->layoutTimerId);
+ d->layoutTimerId = 0;
+ d->layoutSchedulingEnabled=true;
+}
+
+void KHTMLView::closeChildDialogs()
+{
+ TQObjectList *dlgs = queryList(TQDIALOG_OBJECT_NAME_STRING);
+ for (TQObject *dlg = dlgs->first(); dlg; dlg = dlgs->next())
+ {
+ KDialogBase* dlgbase = dynamic_cast<KDialogBase *>( dlg );
+ if ( dlgbase ) {
+ if ( dlgbase->testWFlags( WShowModal ) ) {
+ kdDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase << endl;
+ // close() ends up calling TQButton::animateClick, which isn't immediate
+ // we need something the exits the event loop immediately (#49068)
+ dlgbase->cancel();
+ }
+ }
+ else
+ {
+ kdWarning() << "closeChildDialogs: not a KDialogBase! Don't use QDialogs in KDE! " << TQT_TQWIDGET(dlg) << endl;
+ TQT_TQWIDGET(dlg)->hide();
+ }
+ }
+ delete dlgs;
+ d->m_dialogsAllowed = false;
+}
+
+bool KHTMLView::dialogsAllowed() {
+ bool allowed = d->m_dialogsAllowed;
+ KHTMLPart* p = m_part->parentPart();
+ if (p && p->view())
+ allowed &= p->view()->dialogsAllowed();
+ return allowed;
+}
+
+void KHTMLView::closeEvent( TQCloseEvent* ev )
+{
+ closeChildDialogs();
+ TQScrollView::closeEvent( ev );
+}
+
+//
+// Event Handling
+//
+/////////////////
+
+void KHTMLView::viewportMousePressEvent( TQMouseEvent *_mouse )
+{
+ if (!m_part->xmlDocImpl()) return;
+ if (d->possibleTripleClick && ( _mouse->button() & Qt::MouseButtonMask ) == Qt::LeftButton)
+ {
+ viewportMouseDoubleClickEvent( _mouse ); // it handles triple clicks too
+ return;
+ }
+
+ int xm, ym;
+ viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
+ //kdDebug( 6000 ) << "mousePressEvent: viewport=("<<_mouse->x()<<"/"<<_mouse->y()<<"), contents=(" << xm << "/" << ym << ")\n";
+
+ d->isDoubleClick = false;
+
+ DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MousePress );
+ m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
+
+ //kdDebug(6000) << "innerNode="<<mev.innerNode.nodeName().string()<<endl;
+
+ if ( (_mouse->button() == Qt::MidButton) &&
+ !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer &&
+ mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) {
+ TQPoint point = mapFromGlobal( _mouse->globalPos() );
+
+ d->m_mouseScroll_byX = 0;
+ d->m_mouseScroll_byY = 0;
+
+ d->m_mouseScrollTimer = new TQTimer( this );
+ connect( d->m_mouseScrollTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotMouseScrollTimer()) );
+
+ if ( !d->m_mouseScrollIndicator ) {
+ TQPixmap pixmap, icon;
+ pixmap.resize( 48, 48 );
+ pixmap.fill( TQColor( tqRgba( 127, 127, 127, 127 ) ) );
+
+ TQPainter p( &pixmap );
+ icon = TDEGlobal::iconLoader()->loadIcon( "1uparrow", KIcon::Small );
+ p.drawPixmap( 16, 0, icon );
+ icon = TDEGlobal::iconLoader()->loadIcon( "1leftarrow", KIcon::Small );
+ p.drawPixmap( 0, 16, icon );
+ icon = TDEGlobal::iconLoader()->loadIcon( "1downarrow", KIcon::Small );
+ p.drawPixmap( 16, 32,icon );
+ icon = TDEGlobal::iconLoader()->loadIcon( "1rightarrow", KIcon::Small );
+ p.drawPixmap( 32, 16, icon );
+ p.drawEllipse( 23, 23, 2, 2 );
+
+ d->m_mouseScrollIndicator = new TQWidget( this, 0 );
+ d->m_mouseScrollIndicator->setFixedSize( 48, 48 );
+ d->m_mouseScrollIndicator->setPaletteBackgroundPixmap( pixmap );
+ }
+ d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 );
+
+ bool hasHorBar = visibleWidth() < contentsWidth();
+ bool hasVerBar = visibleHeight() < contentsHeight();
+
+ TDEConfig *config = TDEGlobal::config();
+ TDEConfigGroupSaver saver( config, "HTML Settings" );
+ if ( config->readBoolEntry( "ShowMouseScrollIndicator", true ) ) {
+ d->m_mouseScrollIndicator->show();
+ d->m_mouseScrollIndicator->unsetCursor();
+
+ TQBitmap mask = d->m_mouseScrollIndicator->paletteBackgroundPixmap()->createHeuristicMask( true );
+
+ if ( hasHorBar && !hasVerBar ) {
+ TQBitmap bm( 16, 16, true );
+ bitBlt( &mask, 16, 0, &bm, 0, 0, -1, -1 );
+ bitBlt( &mask, 16, 32, &bm, 0, 0, -1, -1 );
+ d->m_mouseScrollIndicator->setCursor( KCursor::SizeHorCursor );
+ }
+ else if ( !hasHorBar && hasVerBar ) {
+ TQBitmap bm( 16, 16, true );
+ bitBlt( &mask, 0, 16, &bm, 0, 0, -1, -1 );
+ bitBlt( &mask, 32, 16, &bm, 0, 0, -1, -1 );
+ d->m_mouseScrollIndicator->setCursor( KCursor::SizeVerCursor );
+ }
+ else
+ d->m_mouseScrollIndicator->setCursor( KCursor::SizeAllCursor );
+
+ d->m_mouseScrollIndicator->setMask( mask );
+ }
+ else {
+ if ( hasHorBar && !hasVerBar )
+ viewport()->setCursor( KCursor::SizeHorCursor );
+ else if ( !hasHorBar && hasVerBar )
+ viewport()->setCursor( KCursor::SizeVerCursor );
+ else
+ viewport()->setCursor( KCursor::SizeAllCursor );
+ }
+
+ return;
+ }
+ else if ( d->m_mouseScrollTimer ) {
+ delete d->m_mouseScrollTimer;
+ d->m_mouseScrollTimer = 0;
+
+ if ( d->m_mouseScrollIndicator )
+ d->m_mouseScrollIndicator->hide();
+ }
+
+ d->clickCount = 1;
+ d->clickX = xm;
+ d->clickY = ym;
+
+ bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
+ d->clickCount,_mouse,true,DOM::NodeImpl::MousePress);
+
+ tdehtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
+ if (r && r->isWidget())
+ _mouse->ignore();
+
+ if (!swallowEvent) {
+ emit m_part->nodeActivated(mev.innerNode);
+
+ tdehtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
+ TQApplication::sendEvent( m_part, &event );
+ // we might be deleted after this
+ }
+}
+
+void KHTMLView::viewportMouseDoubleClickEvent( TQMouseEvent *_mouse )
+{
+ if(!m_part->xmlDocImpl()) return;
+
+ int xm, ym;
+ viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
+
+ kdDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym << endl;
+
+ d->isDoubleClick = true;
+
+ DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseDblClick );
+ m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
+
+ // We do the same thing as viewportMousePressEvent() here, since the DOM does not treat
+ // single and double-click events as separate (only the detail, i.e. number of clicks differs)
+ if (d->clickCount > 0 &&
+ TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= TQApplication::startDragDistance())
+ d->clickCount++;
+ else { // shouldn't happen, if Qt has the same criterias for double clicks.
+ d->clickCount = 1;
+ d->clickX = xm;
+ d->clickY = ym;
+ }
+ bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
+ d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick);
+
+ tdehtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
+ if (r && r->isWidget())
+ _mouse->ignore();
+
+ if (!swallowEvent) {
+ tdehtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount );
+ TQApplication::sendEvent( m_part, &event );
+ }
+
+ d->possibleTripleClick=true;
+ TQTimer::singleShot(TQApplication::doubleClickInterval(),this,TQT_SLOT(tripleClickTimeout()));
+}
+
+void KHTMLView::tripleClickTimeout()
+{
+ d->possibleTripleClick = false;
+ d->clickCount = 0;
+}
+
+static inline void forwardPeripheralEvent(tdehtml::RenderWidget* r, TQMouseEvent* me, int x, int y)
+{
+ int absx = 0;
+ int absy = 0;
+ r->absolutePosition(absx, absy);
+ TQPoint p(x-absx, y-absy);
+ TQMouseEvent fw(me->type(), p, me->button(), me->state());
+ TQWidget* w = r->widget();
+ TQScrollView* sc = ::tqqt_cast<TQScrollView*>(w);
+ if (sc && !::tqqt_cast<TQListBox*>(w))
+ static_cast<tdehtml::RenderWidget::ScrollViewEventPropagator*>(sc)->sendEvent(TQT_TQEVENT(&fw));
+ else if(w)
+ static_cast<tdehtml::RenderWidget::EventPropagator*>(w)->sendEvent(TQT_TQEVENT(&fw));
+}
+
+
+static bool targetOpensNewWindow(KHTMLPart *part, TQString target)
+{
+ if (!target.isEmpty() && (target.lower() != "_top") &&
+ (target.lower() != "_self") && (target.lower() != "_parent")) {
+ if (target.lower() == "_blank")
+ return true;
+ else {
+ while (part->parentPart())
+ part = part->parentPart();
+ if (!part->frameExists(target))
+ return true;
+ }
+ }
+ return false;
+}
+
+void KHTMLView::viewportMouseMoveEvent( TQMouseEvent * _mouse )
+{
+ if ( d->m_mouseScrollTimer ) {
+ TQPoint point = mapFromGlobal( _mouse->globalPos() );
+
+ int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24;
+ int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24;
+
+ (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1;
+ (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1;
+
+ double adX = TQABS(deltaX)/30.0;
+ double adY = TQABS(deltaY)/30.0;
+
+ d->m_mouseScroll_byX = kMax(kMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN);
+ d->m_mouseScroll_byY = kMax(kMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN);
+
+ if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) {
+ d->m_mouseScrollTimer->stop();
+ }
+ else if (!d->m_mouseScrollTimer->isActive()) {
+ d->m_mouseScrollTimer->changeInterval( 20 );
+ }
+ }
+
+ if(!m_part->xmlDocImpl()) return;
+
+ int xm, ym;
+ viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
+
+ DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseMove );
+ // Do not modify :hover/:active state while mouse is pressed.
+ m_part->xmlDocImpl()->prepareMouseEvent( _mouse->state() & Qt::MouseButtonMask /*readonly ?*/, xm, ym, &mev );
+
+// kdDebug(6000) << "mouse move: " << _mouse->pos()
+// << " button " << _mouse->button()
+// << " state " << _mouse->state() << endl;
+
+ bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),false,
+ 0,_mouse,true,DOM::NodeImpl::MouseMove);
+
+ if (d->clickCount > 0 &&
+ TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > TQApplication::startDragDistance()) {
+ d->clickCount = 0; // moving the mouse outside the threshold invalidates the click
+ }
+
+ // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events
+ m_part->executeScheduledScript();
+
+ DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
+ if (fn && fn != mev.innerNode.handle() &&
+ fn->renderer() && fn->renderer()->isWidget()) {
+ forwardPeripheralEvent(static_cast<tdehtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
+ }
+
+ tdehtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
+ tdehtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
+ TQCursor c;
+ bool mailtoCursor = false;
+ bool newWindowCursor = false;
+ switch ( style ? style->cursor() : CURSOR_AUTO) {
+ case CURSOR_AUTO:
+ if ( r && r->isText() )
+ c = KCursor::ibeamCursor();
+ if ( mev.url.length() && m_part->settings()->changeCursor() ) {
+ c = m_part->urlCursor();
+ if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
+ mailtoCursor = true;
+ else
+ newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
+ }
+
+ if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
+ c = TQCursor(static_cast<RenderFrameSet*>(r)->cursorShape());
+
+ break;
+ case CURSOR_CROSS:
+ c = KCursor::crossCursor();
+ break;
+ case CURSOR_POINTER:
+ c = m_part->urlCursor();
+ if (mev.url.string().startsWith("mailto:") && mev.url.string().find('@')>0)
+ mailtoCursor = true;
+ else
+ newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
+ break;
+ case CURSOR_PROGRESS:
+ c = KCursor::workingCursor();
+ break;
+ case CURSOR_MOVE:
+ c = KCursor::sizeAllCursor();
+ break;
+ case CURSOR_E_RESIZE:
+ case CURSOR_W_RESIZE:
+ c = KCursor::sizeHorCursor();
+ break;
+ case CURSOR_N_RESIZE:
+ case CURSOR_S_RESIZE:
+ c = KCursor::sizeVerCursor();
+ break;
+ case CURSOR_NE_RESIZE:
+ case CURSOR_SW_RESIZE:
+ c = KCursor::sizeBDiagCursor();
+ break;
+ case CURSOR_NW_RESIZE:
+ case CURSOR_SE_RESIZE:
+ c = KCursor::sizeFDiagCursor();
+ break;
+ case CURSOR_TEXT:
+ c = KCursor::ibeamCursor();
+ break;
+ case CURSOR_WAIT:
+ c = KCursor::waitCursor();
+ break;
+ case CURSOR_HELP:
+ c = KCursor::whatsThisCursor();
+ break;
+ case CURSOR_DEFAULT:
+ break;
+ }
+
+ if ( viewport()->cursor().handle() != c.handle() ) {
+ if( c.handle() == KCursor::arrowCursor().handle()) {
+ for (KHTMLPart* p = m_part; p; p = p->parentPart())
+ p->view()->viewport()->unsetCursor();
+ }
+ else {
+ viewport()->setCursor( c );
+ }
+ }
+
+ if ( ( mailtoCursor || newWindowCursor ) && isVisible() && hasFocus() ) {
+#ifdef Q_WS_X11
+ TQPixmap icon_pixmap = TDEGlobal::iconLoader()->loadIcon( mailtoCursor ? "mail_generic" : "window_new", KIcon::Small, 0, KIcon::DefaultState, 0, true );
+
+ if (d->cursor_icon_widget) {
+ const TQPixmap *pm = d->cursor_icon_widget->backgroundPixmap();
+ if (!pm || pm->serialNumber()!=icon_pixmap.serialNumber()) {
+ delete d->cursor_icon_widget;
+ d->cursor_icon_widget = 0;
+ }
+ }
+
+ if( !d->cursor_icon_widget ) {
+ d->cursor_icon_widget = new TQWidget( NULL, NULL, WX11BypassWM );
+ XSetWindowAttributes attr;
+ attr.save_under = True;
+ XChangeWindowAttributes( tqt_xdisplay(), d->cursor_icon_widget->winId(), CWSaveUnder, &attr );
+ d->cursor_icon_widget->resize( icon_pixmap.width(), icon_pixmap.height());
+ if( icon_pixmap.mask() )
+ d->cursor_icon_widget->setMask( *icon_pixmap.mask());
+ else
+ d->cursor_icon_widget->clearMask();
+ d->cursor_icon_widget->setBackgroundPixmap( icon_pixmap );
+ d->cursor_icon_widget->erase();
+ }
+ TQPoint c_pos = TQCursor::pos();
+ d->cursor_icon_widget->move( c_pos.x() + 15, c_pos.y() + 15 );
+ XRaiseWindow( tqt_xdisplay(), d->cursor_icon_widget->winId());
+ TQApplication::flushX();
+ d->cursor_icon_widget->show();
+#endif
+ }
+ else if ( d->cursor_icon_widget )
+ d->cursor_icon_widget->hide();
+
+ if (r && r->isWidget()) {
+ _mouse->ignore();
+ }
+
+
+ d->prevMouseX = xm;
+ d->prevMouseY = ym;
+
+ if (!swallowEvent) {
+ tdehtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
+ TQApplication::sendEvent( m_part, &event );
+ }
+}
+
+void KHTMLView::viewportMouseReleaseEvent( TQMouseEvent * _mouse )
+{
+ bool swallowEvent = false;
+ int xm, ym;
+ viewportToContents(_mouse->x(), _mouse->y(), xm, ym);
+ DOM::NodeImpl::MouseEvent mev( _mouse->stateAfter(), DOM::NodeImpl::MouseRelease );
+
+ if ( m_part->xmlDocImpl() )
+ {
+ m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev );
+
+ swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
+ d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease);
+
+ if (d->clickCount > 0 &&
+ TQPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= TQApplication::startDragDistance()) {
+ TQMouseEvent me(d->isDoubleClick ? TQEvent::MouseButtonDblClick : TQEvent::MouseButtonRelease,
+ _mouse->pos(), _mouse->button(), _mouse->state());
+ dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true,
+ d->clickCount, &me, true, DOM::NodeImpl::MouseRelease);
+ }
+
+ DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode();
+ if (fn && fn != mev.innerNode.handle() &&
+ fn->renderer() && fn->renderer()->isWidget() &&
+ _mouse->button() != Qt::MidButton) {
+ forwardPeripheralEvent(static_cast<tdehtml::RenderWidget*>(fn->renderer()), _mouse, xm, ym);
+ }
+
+ tdehtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0;
+ if (r && r->isWidget())
+ _mouse->ignore();
+ }
+
+ if (!swallowEvent) {
+ tdehtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode );
+ TQApplication::sendEvent( m_part, &event );
+ }
+}
+
+// returns true if event should be swallowed
+bool KHTMLView::dispatchKeyEvent( TQKeyEvent *_ke )
+{
+ if (!m_part->xmlDocImpl())
+ return false;
+ // Pressing and releasing a key should generate keydown, keypress and keyup events
+ // Holding it down should generated keydown, keypress (repeatedly) and keyup events
+ // The problem here is that Qt generates two autorepeat events (keyrelease+keypress)
+ // for autorepeating, while DOM wants only one autorepeat event (keypress), so one
+ // of the Qt events shouldn't be passed to DOM, but it should be still filtered
+ // out if DOM would filter the autorepeat event. Additional problem is that Qt keyrelease
+ // events don't have text() set (Qt bug?), so DOM often would ignore the keypress event
+ // if it was created using Qt keyrelease, but Qt autorepeat keyrelease comes
+ // before Qt autorepeat keypress (i.e. problem whether to filter it out or not).
+ // The solution is to filter out and postpone the Qt autorepeat keyrelease until
+ // the following Qt keypress event comes. If DOM accepts the DOM keypress event,
+ // the postponed event will be simply discarded. If not, it will be passed to keyPressEvent()
+ // again, and here it will be ignored.
+ //
+ // Qt: Press | Release(autorepeat) Press(autorepeat) etc. | Release
+ // DOM: Down + Press | (nothing) Press | Up
+
+ // It's also possible to get only Releases. E.g. the release of alt-tab,
+ // or when the keypresses get captured by an accel.
+
+ if( _ke == d->postponed_autorepeat ) // replayed event
+ {
+ return false;
+ }
+
+ if( _ke->type() == TQEvent::KeyPress )
+ {
+ if( !_ke->isAutoRepeat())
+ {
+ bool ret = dispatchKeyEventHelper( _ke, false ); // keydown
+ // don't send keypress even if keydown was blocked, like IE (and unlike Mozilla)
+ if( !ret && dispatchKeyEventHelper( _ke, true )) // keypress
+ ret = true;
+ return ret;
+ }
+ else // autorepeat
+ {
+ bool ret = dispatchKeyEventHelper( _ke, true ); // keypress
+ if( !ret && d->postponed_autorepeat )
+ keyPressEvent( d->postponed_autorepeat );
+ delete d->postponed_autorepeat;
+ d->postponed_autorepeat = NULL;
+ return ret;
+ }
+ }
+ else // TQEvent::KeyRelease
+ {
+ // Discard postponed "autorepeat key-release" events that didn't see
+ // a keypress after them (e.g. due to TQAccel)
+ if ( d->postponed_autorepeat ) {
+ delete d->postponed_autorepeat;
+ d->postponed_autorepeat = 0;
+ }
+
+ if( !_ke->isAutoRepeat()) {
+ return dispatchKeyEventHelper( _ke, false ); // keyup
+ }
+ else
+ {
+ d->postponed_autorepeat = new TQKeyEvent( _ke->type(), _ke->key(), _ke->ascii(), _ke->state(),
+ _ke->text(), _ke->isAutoRepeat(), _ke->count());
+ if( _ke->isAccepted())
+ d->postponed_autorepeat->accept();
+ else
+ d->postponed_autorepeat->ignore();
+ return true;
+ }
+ }
+}
+
+// returns true if event should be swallowed
+bool KHTMLView::dispatchKeyEventHelper( TQKeyEvent *_ke, bool keypress )
+{
+ DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode();
+ if (keyNode) {
+ return keyNode->dispatchKeyEvent(_ke, keypress);
+ } else { // no focused node, send to document
+ return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress);
+ }
+}
+
+void KHTMLView::keyPressEvent( TQKeyEvent *_ke )
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ if(d->typeAheadActivated)
+ {
+ // type-ahead find aka find-as-you-type
+ if(_ke->key() == Key_BackSpace)
+ {
+ d->findString = d->findString.left(d->findString.length() - 1);
+
+ if(!d->findString.isEmpty())
+ {
+ findAhead(false);
+ }
+ else
+ {
+ findTimeout();
+ }
+
+ d->timer.start(3000, true);
+ _ke->accept();
+ return;
+ }
+ else if(_ke->key() == Key_Escape)
+ {
+ findTimeout();
+
+ _ke->accept();
+ return;
+ }
+ else if(_ke->key() == Key_Space || !TQString(_ke->text()).stripWhiteSpace().isEmpty())
+ {
+ d->findString += _ke->text();
+
+ findAhead(true);
+
+ d->timer.start(3000, true);
+ _ke->accept();
+ return;
+ }
+ }
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+
+#ifndef KHTML_NO_CARET
+ if (m_part->isEditable() || m_part->isCaretMode()
+ || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
+ && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
+ d->caretViewContext()->keyReleasePending = true;
+ caretKeyPressEvent(_ke);
+ return;
+ }
+#endif // KHTML_NO_CARET
+
+ // If CTRL was hit, be prepared for access keys
+ if (d->accessKeysEnabled && _ke->key() == Key_Control && _ke->state()==0 && !d->accessKeysActivated)
+ {
+ d->accessKeysPreActivate=true;
+ _ke->accept();
+ return;
+ }
+
+ if (_ke->key() == Key_Shift && _ke->state()==0)
+ d->scrollSuspendPreActivate=true;
+
+ // accesskey handling needs to be done before dispatching, otherwise e.g. lineedits
+ // may eat the event
+
+ if (d->accessKeysEnabled && d->accessKeysActivated)
+ {
+ int state = ( _ke->state() & ( ShiftButton | ControlButton | AltButton | MetaButton ));
+ if ( state==0 || state==ShiftButton) {
+ if (_ke->key() != Key_Shift) accessKeysTimeout();
+ handleAccessKey( _ke );
+ _ke->accept();
+ return;
+ }
+ accessKeysTimeout();
+ }
+
+ if ( dispatchKeyEvent( _ke )) {
+ // If either keydown or keypress was accepted by a widget, or canceled by JS, stop here.
+ _ke->accept();
+ return;
+ }
+
+ int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
+ if (_ke->state() & TQt::ShiftButton)
+ switch(_ke->key())
+ {
+ case Key_Space:
+ scrollBy( 0, -clipper()->height() + offs );
+ if(d->scrollSuspended)
+ d->newScrollTimer(this, 0);
+ break;
+
+ case Key_Down:
+ case Key_J:
+ d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp);
+ break;
+
+ case Key_Up:
+ case Key_K:
+ d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown);
+ break;
+
+ case Key_Left:
+ case Key_H:
+ d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight);
+ break;
+
+ case Key_Right:
+ case Key_L:
+ d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft);
+ break;
+ }
+ else
+ switch ( _ke->key() )
+ {
+ case Key_Down:
+ case Key_J:
+ if (!d->scrollTimerId || d->scrollSuspended)
+ scrollBy( 0, 10 * _ke->count() );
+ if (d->scrollTimerId)
+ d->newScrollTimer(this, 0);
+ break;
+
+ case Key_Space:
+ case Key_Next:
+ scrollBy( 0, clipper()->height() - offs );
+ if(d->scrollSuspended)
+ d->newScrollTimer(this, 0);
+ break;
+
+ case Key_Up:
+ case Key_K:
+ if (!d->scrollTimerId || d->scrollSuspended)
+ scrollBy( 0, -10 * _ke->count());
+ if (d->scrollTimerId)
+ d->newScrollTimer(this, 0);
+ break;
+
+ case Key_Prior:
+ scrollBy( 0, -clipper()->height() + offs );
+ if(d->scrollSuspended)
+ d->newScrollTimer(this, 0);
+ break;
+ case Key_Right:
+ case Key_L:
+ if (!d->scrollTimerId || d->scrollSuspended)
+ scrollBy( 10 * _ke->count(), 0 );
+ if (d->scrollTimerId)
+ d->newScrollTimer(this, 0);
+ break;
+ case Key_Left:
+ case Key_H:
+ if (!d->scrollTimerId || d->scrollSuspended)
+ scrollBy( -10 * _ke->count(), 0 );
+ if (d->scrollTimerId)
+ d->newScrollTimer(this, 0);
+ break;
+ case Key_Enter:
+ case Key_Return:
+ // ### FIXME:
+ // or even better to HTMLAnchorElementImpl::event()
+ if (m_part->xmlDocImpl()) {
+ NodeImpl *n = m_part->xmlDocImpl()->focusNode();
+ if (n)
+ n->setActive();
+ }
+ break;
+ case Key_Home:
+ setContentsPos( 0, 0 );
+ if(d->scrollSuspended)
+ d->newScrollTimer(this, 0);
+ break;
+ case Key_End:
+ setContentsPos( 0, contentsHeight() - visibleHeight() );
+ if(d->scrollSuspended)
+ d->newScrollTimer(this, 0);
+ break;
+ case Key_Shift:
+ // what are you doing here?
+ _ke->ignore();
+ return;
+ default:
+ if (d->scrollTimerId)
+ d->newScrollTimer(this, 0);
+ _ke->ignore();
+ return;
+ }
+
+ _ke->accept();
+}
+
+void KHTMLView::findTimeout()
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ d->typeAheadActivated = false;
+ d->findString = "";
+ m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText);
+ m_part->enableFindAheadActions( true );
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+}
+
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+void KHTMLView::startFindAhead( bool linksOnly )
+{
+ if( linksOnly )
+ {
+ d->findLinksOnly = true;
+ m_part->setStatusBarText(i18n("Starting -- find links as you type"),
+ KHTMLPart::BarDefaultText);
+ }
+ else
+ {
+ d->findLinksOnly = false;
+ m_part->setStatusBarText(i18n("Starting -- find text as you type"),
+ KHTMLPart::BarDefaultText);
+ }
+
+ m_part->findTextBegin();
+ d->typeAheadActivated = true;
+ // disable, so that the shortcut ( / or ' by default ) doesn't interfere
+ m_part->enableFindAheadActions( false );
+ d->timer.start(3000, true);
+}
+
+void KHTMLView::findAhead(bool increase)
+{
+ TQString status;
+
+ if(d->findLinksOnly)
+ {
+ m_part->findText(d->findString, KHTMLPart::FindNoPopups |
+ KHTMLPart::FindLinksOnly, this);
+ if(m_part->findTextNext())
+ {
+ status = i18n("Link found: \"%1\".");
+ }
+ else
+ {
+ if(increase) KNotifyClient::beep();
+ status = i18n("Link not found: \"%1\".");
+ }
+ }
+ else
+ {
+ m_part->findText(d->findString, KHTMLPart::FindNoPopups, this);
+ if(m_part->findTextNext())
+ {
+ status = i18n("Text found: \"%1\".");
+ }
+ else
+ {
+ if(increase) KNotifyClient::beep();
+ status = i18n("Text not found: \"%1\".");
+ }
+ }
+
+ m_part->setStatusBarText(status.arg(d->findString.lower()),
+ KHTMLPart::BarDefaultText);
+}
+
+void KHTMLView::updateFindAheadTimeout()
+{
+ if( d->typeAheadActivated )
+ d->timer.start( 3000, true );
+}
+
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+
+void KHTMLView::keyReleaseEvent(TQKeyEvent *_ke)
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ if(d->typeAheadActivated) {
+ _ke->accept();
+ return;
+ }
+#endif
+ if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) {
+ //caretKeyReleaseEvent(_ke);
+ d->m_caretViewContext->keyReleasePending = false;
+ return;
+ }
+
+ if( d->scrollSuspendPreActivate && _ke->key() != Key_Shift )
+ d->scrollSuspendPreActivate = false;
+ if( _ke->key() == Key_Shift && d->scrollSuspendPreActivate && _ke->state() == TQt::ShiftButton
+ && !(TDEApplication::keyboardMouseState() & TQt::ShiftButton))
+ {
+ if (d->scrollTimerId)
+ {
+ d->scrollSuspended = !d->scrollSuspended;
+#ifndef NO_SMOOTH_SCROLL_HACK
+ if( d->scrollSuspended )
+ stopScrolling();
+#endif
+ }
+ }
+
+ if (d->accessKeysEnabled)
+ {
+ if (d->accessKeysPreActivate && _ke->key() != Key_Control)
+ d->accessKeysPreActivate=false;
+ if (d->accessKeysPreActivate && _ke->state() == TQt::ControlButton && !(TDEApplication::keyboardMouseState() & TQt::ControlButton))
+ {
+ displayAccessKeys();
+ m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText);
+ d->accessKeysActivated = true;
+ d->accessKeysPreActivate = false;
+ _ke->accept();
+ return;
+ }
+ else if (d->accessKeysActivated)
+ {
+ accessKeysTimeout();
+ _ke->accept();
+ return;
+ }
+ }
+
+ // Send keyup event
+ if ( dispatchKeyEvent( _ke ) )
+ {
+ _ke->accept();
+ return;
+ }
+
+ TQScrollView::keyReleaseEvent(_ke);
+}
+
+void KHTMLView::contentsContextMenuEvent ( TQContextMenuEvent * /*ce*/ )
+{
+// ### what kind of c*** is that ?
+#if 0
+ if (!m_part->xmlDocImpl()) return;
+ int xm = _ce->x();
+ int ym = _ce->y();
+
+ DOM::NodeImpl::MouseEvent mev( _ce->state(), DOM::NodeImpl::MouseMove ); // ### not a mouse event!
+ m_part->xmlDocImpl()->prepareMouseEvent( xm, ym, &mev );
+
+ NodeImpl *targetNode = mev.innerNode.handle();
+ if (targetNode && targetNode->renderer() && targetNode->renderer()->isWidget()) {
+ int absx = 0;
+ int absy = 0;
+ targetNode->renderer()->absolutePosition(absx,absy);
+ TQPoint pos(xm-absx,ym-absy);
+
+ TQWidget *w = static_cast<RenderWidget*>(targetNode->renderer())->widget();
+ TQContextMenuEvent cme(_ce->reason(),pos,_ce->globalPos(),_ce->state());
+ setIgnoreEvents(true);
+ TQApplication::sendEvent(w,&cme);
+ setIgnoreEvents(false);
+ }
+#endif
+}
+
+bool KHTMLView::focusNextPrevChild( bool next )
+{
+ // Now try to find the next child
+ if (m_part->xmlDocImpl() && focusNextPrevNode(next))
+ {
+ if (m_part->xmlDocImpl()->focusNode())
+ kdDebug() << "focusNode.name: "
+ << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl;
+ return true; // focus node found
+ }
+
+ // If we get here, pass tabbing control up to the next/previous child in our parent
+ d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
+ if (m_part->parentPart() && m_part->parentPart()->view())
+ return m_part->parentPart()->view()->focusNextPrevChild(next);
+
+ return TQWidget::focusNextPrevChild(next);
+}
+
+void KHTMLView::doAutoScroll()
+{
+ TQPoint pos = TQCursor::pos();
+ pos = viewport()->mapFromGlobal( pos );
+
+ int xm, ym;
+ viewportToContents(pos.x(), pos.y(), xm, ym);
+
+ pos = TQPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
+ if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
+ (pos.x() < 0) || (pos.x() > visibleWidth()) )
+ {
+ ensureVisible( xm, ym, 0, 5 );
+
+#ifndef KHTML_NO_SELECTION
+ // extend the selection while scrolling
+ DOM::Node innerNode;
+ if (m_part->isExtendingSelection()) {
+ RenderObject::NodeInfo renderInfo(true/*readonly*/, false/*active*/);
+ m_part->xmlDocImpl()->renderer()->layer()
+ ->nodeAtPoint(renderInfo, xm, ym);
+ innerNode = renderInfo.innerNode();
+ }/*end if*/
+
+ if (innerNode.handle() && innerNode.handle()->renderer()) {
+ int absX, absY;
+ innerNode.handle()->renderer()->absolutePosition(absX, absY);
+
+ m_part->extendSelectionTo(xm, ym, absX, absY, innerNode);
+ }/*end if*/
+#endif // KHTML_NO_SELECTION
+ }
+}
+
+
+class HackWidget : public TQWidget
+{
+ public:
+ inline void setNoErase() { setWFlags(getWFlags()|WRepaintNoErase); }
+};
+
+bool KHTMLView::eventFilter(TQObject *o, TQEvent *e)
+{
+ if ( e->type() == TQEvent::AccelOverride ) {
+ TQKeyEvent* ke = (TQKeyEvent*) e;
+//kdDebug(6200) << "TQEvent::AccelOverride" << endl;
+ if (m_part->isEditable() || m_part->isCaretMode()
+ || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode()
+ && m_part->xmlDocImpl()->focusNode()->contentEditable())) {
+//kdDebug(6200) << "editable/navigable" << endl;
+ if ( (ke->state() & ControlButton) || (ke->state() & ShiftButton) ) {
+ switch ( ke->key() ) {
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ case Key_Home:
+ case Key_End:
+ ke->accept();
+//kdDebug(6200) << "eaten" << endl;
+ return true;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if ( e->type() == TQEvent::Leave ) {
+ if ( d->cursor_icon_widget )
+ d->cursor_icon_widget->hide();
+ m_part->resetHoverText();
+ }
+
+ TQWidget *view = viewport();
+
+ if (TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(view)) {
+ // we need to install an event filter on all children of the viewport to
+ // be able to get correct stacking of children within the document.
+ if(e->type() == TQEvent::ChildInserted) {
+ TQObject *c = TQT_TQOBJECT(TQT_TQCHILDEVENT(e)->child());
+ if (c->isWidgetType()) {
+ TQWidget *w = TQT_TQWIDGET(c);
+ // don't install the event filter on toplevels
+ if (w->parentWidget(true) == view) {
+ if (!strcmp(w->name(), "__tdehtml")) {
+ w->installEventFilter(this);
+ w->unsetCursor();
+ if (!::tqqt_cast<TQFrame*>(w))
+ w->setBackgroundMode( TQWidget::NoBackground );
+ static_cast<HackWidget *>(w)->setNoErase();
+ if (!w->childrenListObject().isEmpty()) {
+ TQObjectListIterator it(w->childrenListObject());
+ for (; it.current(); ++it) {
+ TQWidget *widget = ::tqqt_cast<TQWidget *>(it.current());
+ if (widget && !widget->isTopLevel()) {
+ if (!::tqqt_cast<TQFrame*>(w))
+ widget->setBackgroundMode( TQWidget::NoBackground );
+ static_cast<HackWidget *>(widget)->setNoErase();
+ widget->installEventFilter(this);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (o->isWidgetType()) {
+ TQWidget *v = TQT_TQWIDGET(o);
+ TQWidget *c = v;
+ while (v && v != view) {
+ c = v;
+ v = v->parentWidget(true);
+ }
+
+ if (v && !strcmp(c->name(), "__tdehtml")) {
+ bool block = false;
+ TQWidget *w = TQT_TQWIDGET(o);
+ switch(e->type()) {
+ case TQEvent::Paint:
+ if (!allowWidgetPaintEvents) {
+ // eat the event. Like this we can control exactly when the widget
+ // get's repainted.
+ block = true;
+ int x = 0, y = 0;
+ TQWidget *v = w;
+ while (v && v != view) {
+ x += v->x();
+ y += v->y();
+ v = v->parentWidget();
+ }
+ viewportToContents( x, y, x, y );
+ TQPaintEvent *pe = TQT_TQPAINTEVENT(e);
+ bool asap = !d->contentsMoving && ::tqqt_cast<TQScrollView *>(c);
+
+ // TQScrollView needs fast repaints
+ if ( asap && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() &&
+ !static_cast<tdehtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer())->needsLayout() ) {
+ repaintContents(x + pe->rect().x(), y + pe->rect().y(),
+ pe->rect().width(), pe->rect().height(), true);
+ } else {
+ scheduleRepaint(x + pe->rect().x(), y + pe->rect().y(),
+ pe->rect().width(), pe->rect().height(), asap);
+ }
+ }
+ break;
+ case TQEvent::MouseMove:
+ case TQEvent::MouseButtonPress:
+ case TQEvent::MouseButtonRelease:
+ case TQEvent::MouseButtonDblClick: {
+ if ( (w->parentWidget() == view || ::tqqt_cast<TQScrollView*>(c)) && !::tqqt_cast<TQScrollBar *>(w)) {
+ TQMouseEvent *me = TQT_TQMOUSEEVENT(e);
+ TQPoint pt = w->mapTo( view, me->pos());
+ TQMouseEvent me2(me->type(), pt, me->button(), me->state());
+
+ if (e->type() == TQEvent::MouseMove)
+ viewportMouseMoveEvent(&me2);
+ else if(e->type() == TQEvent::MouseButtonPress)
+ viewportMousePressEvent(&me2);
+ else if(e->type() == TQEvent::MouseButtonRelease)
+ viewportMouseReleaseEvent(&me2);
+ else
+ viewportMouseDoubleClickEvent(&me2);
+ block = true;
+ }
+ break;
+ }
+ case TQEvent::KeyPress:
+ case TQEvent::KeyRelease:
+ if (w->parentWidget() == view && !::tqqt_cast<TQScrollBar *>(w)) {
+ TQKeyEvent *ke = TQT_TQKEYEVENT(e);
+ if (e->type() == TQEvent::KeyPress)
+ keyPressEvent(ke);
+ else
+ keyReleaseEvent(ke);
+ block = true;
+ }
+ default:
+ break;
+ }
+ if (block) {
+ //tqDebug("eating event");
+ return true;
+ }
+ }
+ }
+
+// kdDebug(6000) <<"passing event on to sv event filter object=" << o->className() << " event=" << e->type() << endl;
+ return TQScrollView::eventFilter(o, e);
+}
+
+
+DOM::NodeImpl *KHTMLView::nodeUnderMouse() const
+{
+ return d->underMouse;
+}
+
+DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const
+{
+ return d->underMouseNonShared;
+}
+
+bool KHTMLView::scrollTo(const TQRect &bounds)
+{
+ d->scrollingSelf = true; // so scroll events get ignored
+
+ int x, y, xe, ye;
+ x = bounds.left();
+ y = bounds.top();
+ xe = bounds.right();
+ ye = bounds.bottom();
+
+ //kdDebug(6000)<<"scrolling coords: x="<<x<<" y="<<y<<" width="<<xe-x<<" height="<<ye-y<<endl;
+
+ int deltax;
+ int deltay;
+
+ int curHeight = visibleHeight();
+ int curWidth = visibleWidth();
+
+ if (ye-y>curHeight-d->borderY)
+ ye = y + curHeight - d->borderY;
+
+ if (xe-x>curWidth-d->borderX)
+ xe = x + curWidth - d->borderX;
+
+ // is xpos of target left of the view's border?
+ if (x < contentsX() + d->borderX )
+ deltax = x - contentsX() - d->borderX;
+ // is xpos of target right of the view's right border?
+ else if (xe + d->borderX > contentsX() + curWidth)
+ deltax = xe + d->borderX - ( contentsX() + curWidth );
+ else
+ deltax = 0;
+
+ // is ypos of target above upper border?
+ if (y < contentsY() + d->borderY)
+ deltay = y - contentsY() - d->borderY;
+ // is ypos of target below lower border?
+ else if (ye + d->borderY > contentsY() + curHeight)
+ deltay = ye + d->borderY - ( contentsY() + curHeight );
+ else
+ deltay = 0;
+
+ int maxx = curWidth-d->borderX;
+ int maxy = curHeight-d->borderY;
+
+ int scrollX,scrollY;
+
+ scrollX = deltax > 0 ? (deltax > maxx ? maxx : deltax) : deltax == 0 ? 0 : (deltax>-maxx ? deltax : -maxx);
+ scrollY = deltay > 0 ? (deltay > maxy ? maxy : deltay) : deltay == 0 ? 0 : (deltay>-maxy ? deltay : -maxy);
+
+ if (contentsX() + scrollX < 0)
+ scrollX = -contentsX();
+ else if (contentsWidth() - visibleWidth() - contentsX() < scrollX)
+ scrollX = contentsWidth() - visibleWidth() - contentsX();
+
+ if (contentsY() + scrollY < 0)
+ scrollY = -contentsY();
+ else if (contentsHeight() - visibleHeight() - contentsY() < scrollY)
+ scrollY = contentsHeight() - visibleHeight() - contentsY();
+
+ scrollBy(scrollX, scrollY);
+
+ d->scrollingSelf = false;
+
+ if ( (abs(deltax)<=maxx) && (abs(deltay)<=maxy) )
+ return true;
+ else return false;
+
+}
+
+bool KHTMLView::focusNextPrevNode(bool next)
+{
+ // Sets the focus node of the document to be the node after (or if
+ // next is false, before) the current focus node. Only nodes that
+ // are selectable (i.e. for which isFocusable() returns true) are
+ // taken into account, and the order used is that specified in the
+ // HTML spec (see DocumentImpl::nextFocusNode() and
+ // DocumentImpl::previousFocusNode() for details).
+
+ DocumentImpl *doc = m_part->xmlDocImpl();
+ NodeImpl *oldFocusNode = doc->focusNode();
+
+ // See whether we're in the middle of detach. If so, we want to
+ // clear focus... The document code will be careful to not
+ // emit events in that case..
+ if (oldFocusNode && oldFocusNode->renderer() &&
+ !oldFocusNode->renderer()->parent()) {
+ doc->setFocusNode(0);
+ return true;
+ }
+
+#if 1
+ // If the user has scrolled the document, then instead of picking
+ // the next focusable node in the document, use the first one that
+ // is within the visible area (if possible).
+ if (d->scrollBarMoved)
+ {
+ NodeImpl *toFocus;
+ if (next)
+ toFocus = doc->nextFocusNode(oldFocusNode);
+ else
+ toFocus = doc->previousFocusNode(oldFocusNode);
+
+ if (!toFocus && oldFocusNode)
+ if (next)
+ toFocus = doc->nextFocusNode(NULL);
+ else
+ toFocus = doc->previousFocusNode(NULL);
+
+ while (toFocus && toFocus != oldFocusNode)
+ {
+
+ TQRect focusNodeRect = toFocus->getRect();
+ if ((focusNodeRect.left() > contentsX()) && (focusNodeRect.right() < contentsX() + visibleWidth()) &&
+ (focusNodeRect.top() > contentsY()) && (focusNodeRect.bottom() < contentsY() + visibleHeight())) {
+ {
+ TQRect r = toFocus->getRect();
+ ensureVisible( r.right(), r.bottom());
+ ensureVisible( r.left(), r.top());
+ d->scrollBarMoved = false;
+ d->tabMovePending = false;
+ d->lastTabbingDirection = next;
+ d->pseudoFocusNode = KHTMLViewPrivate::PFNone;
+ m_part->xmlDocImpl()->setFocusNode(toFocus);
+ Node guard(toFocus);
+ if (!toFocus->hasOneRef() )
+ {
+ emit m_part->nodeActivated(Node(toFocus));
+ }
+ return true;
+ }
+ }
+ if (next)
+ toFocus = doc->nextFocusNode(toFocus);
+ else
+ toFocus = doc->previousFocusNode(toFocus);
+
+ if (!toFocus && oldFocusNode)
+ if (next)
+ toFocus = doc->nextFocusNode(NULL);
+ else
+ toFocus = doc->previousFocusNode(NULL);
+ }
+
+ d->scrollBarMoved = false;
+ }
+#endif
+
+ if (!oldFocusNode && d->pseudoFocusNode == KHTMLViewPrivate::PFNone)
+ {
+ ensureVisible(contentsX(), next?0:contentsHeight());
+ d->scrollBarMoved = false;
+ d->pseudoFocusNode = next?KHTMLViewPrivate::PFTop:KHTMLViewPrivate::PFBottom;
+ return true;
+ }
+
+ NodeImpl *newFocusNode = NULL;
+
+ if (d->tabMovePending && next != d->lastTabbingDirection)
+ {
+ //kdDebug ( 6000 ) << " tab move pending and tabbing direction changed!\n";
+ newFocusNode = oldFocusNode;
+ }
+ else if (next)
+ {
+ if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFTop )
+ newFocusNode = doc->nextFocusNode(oldFocusNode);
+ }
+ else
+ {
+ if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom )
+ newFocusNode = doc->previousFocusNode(oldFocusNode);
+ }
+
+ bool targetVisible = false;
+ if (!newFocusNode)
+ {
+ if ( next )
+ {
+ targetVisible = scrollTo(TQRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0));
+ }
+ else
+ {
+ targetVisible = scrollTo(TQRect(contentsX()+visibleWidth()/2,d->borderY,0,0));
+ }
+ }
+ else
+ {
+#ifndef KHTML_NO_CARET
+ // if it's an editable element, activate the caret
+ if (!m_part->isCaretMode() && !m_part->isEditable()
+ && newFocusNode->contentEditable()) {
+ d->caretViewContext();
+ moveCaretTo(newFocusNode, 0L, true);
+ } else {
+ caretOff();
+ }
+#endif // KHTML_NO_CARET
+
+ targetVisible = scrollTo(newFocusNode->getRect());
+ }
+
+ if (targetVisible)
+ {
+ //kdDebug ( 6000 ) << " target reached.\n";
+ d->tabMovePending = false;
+
+ m_part->xmlDocImpl()->setFocusNode(newFocusNode);
+ if (newFocusNode)
+ {
+ Node guard(newFocusNode);
+ if (!newFocusNode->hasOneRef() )
+ {
+ emit m_part->nodeActivated(Node(newFocusNode));
+ }
+ return true;
+ }
+ else
+ {
+ d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop;
+ return false;
+ }
+ }
+ else
+ {
+ if (!d->tabMovePending)
+ d->lastTabbingDirection = next;
+ d->tabMovePending = true;
+ return true;
+ }
+}
+
+void KHTMLView::displayAccessKeys()
+{
+ TQValueVector< TQChar > taken;
+ displayAccessKeys( NULL, this, taken, false );
+ displayAccessKeys( NULL, this, taken, true );
+}
+
+void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, TQValueVector< TQChar >& taken, bool use_fallbacks )
+{
+ TQMap< ElementImpl*, TQChar > fallbacks;
+ if( use_fallbacks )
+ fallbacks = buildFallbackAccessKeys();
+ for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) {
+ if( n->isElementNode()) {
+ ElementImpl* en = static_cast< ElementImpl* >( n );
+ DOMString s = en->getAttribute( ATTR_ACCESSKEY );
+ TQString accesskey;
+ if( s.length() == 1 ) {
+ TQChar a = s.string()[ 0 ].upper();
+ if( tqFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains
+ accesskey = a;
+ }
+ if( accesskey.isNull() && fallbacks.contains( en )) {
+ TQChar a = fallbacks[ en ].upper();
+ if( tqFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains
+ accesskey = TQString( "<qt><i>" ) + a + "</i></qt>";
+ }
+ if( !accesskey.isNull()) {
+ TQRect rec=en->getRect();
+ TQLabel *lab=new TQLabel(accesskey,viewport(),0,(WFlags)WDestructiveClose);
+ connect( origview, TQT_SIGNAL(hideAccessKeys()), lab, TQT_SLOT(close()) );
+ connect( this, TQT_SIGNAL(repaintAccessKeys()), lab, TQT_SLOT(repaint()));
+ lab->setPalette(TQToolTip::palette());
+ lab->setLineWidth(2);
+ lab->setFrameStyle(TQFrame::Box | TQFrame::Plain);
+ lab->setMargin(3);
+ lab->adjustSize();
+ addChild(lab,
+ KMIN(rec.left()+rec.width()/2, contentsWidth() - lab->width()),
+ KMIN(rec.top()+rec.height()/2, contentsHeight() - lab->height()));
+ showChild(lab);
+ taken.append( accesskey[ 0 ] );
+ }
+ }
+ }
+ if( use_fallbacks )
+ return;
+ TQPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
+ for( TQPtrListIterator<KParts::ReadOnlyPart> it( frames );
+ it != NULL;
+ ++it ) {
+ if( !(*it)->inherits( "KHTMLPart" ))
+ continue;
+ KHTMLPart* part = static_cast< KHTMLPart* >( *it );
+ if( part->view() && part->view() != caller )
+ part->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
+ }
+ // pass up to the parent
+ if (m_part->parentPart() && m_part->parentPart()->view()
+ && m_part->parentPart()->view() != caller)
+ m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks );
+}
+
+
+
+void KHTMLView::accessKeysTimeout()
+{
+d->accessKeysActivated=false;
+d->accessKeysPreActivate = false;
+m_part->setStatusBarText(TQString::null, KHTMLPart::BarOverrideText);
+emit hideAccessKeys();
+}
+
+// Handling of the HTML accesskey attribute.
+bool KHTMLView::handleAccessKey( const TQKeyEvent* ev )
+{
+// Qt interprets the keyevent also with the modifiers, and ev->text() matches that,
+// but this code must act as if the modifiers weren't pressed
+ TQChar c;
+ if( ev->key() >= Key_A && ev->key() <= Key_Z )
+ c = 'A' + ev->key() - Key_A;
+ else if( ev->key() >= Key_0 && ev->key() <= Key_9 )
+ c = '0' + ev->key() - Key_0;
+ else {
+ // TODO fake XKeyEvent and XLookupString ?
+ // This below seems to work e.g. for eacute though.
+ if( ev->text().length() == 1 )
+ c = ev->text()[ 0 ];
+ }
+ if( c.isNull())
+ return false;
+ return focusNodeWithAccessKey( c );
+}
+
+bool KHTMLView::focusNodeWithAccessKey( TQChar c, KHTMLView* caller )
+{
+ DocumentImpl *doc = m_part->xmlDocImpl();
+ if( !doc )
+ return false;
+ ElementImpl* node = doc->findAccessKeyElement( c );
+ if( !node ) {
+ TQPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
+ for( TQPtrListIterator<KParts::ReadOnlyPart> it( frames );
+ it != NULL;
+ ++it ) {
+ if( !(*it)->inherits( "KHTMLPart" ))
+ continue;
+ KHTMLPart* part = static_cast< KHTMLPart* >( *it );
+ if( part->view() && part->view() != caller
+ && part->view()->focusNodeWithAccessKey( c, this ))
+ return true;
+ }
+ // pass up to the parent
+ if (m_part->parentPart() && m_part->parentPart()->view()
+ && m_part->parentPart()->view() != caller
+ && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this ))
+ return true;
+ if( caller == NULL ) { // the active frame (where the accesskey was pressed)
+ TQMap< ElementImpl*, TQChar > fallbacks = buildFallbackAccessKeys();
+ for( TQMap< ElementImpl*, TQChar >::ConstIterator it = fallbacks.begin();
+ it != fallbacks.end();
+ ++it )
+ if( *it == c ) {
+ node = it.key();
+ break;
+ }
+ }
+ if( node == NULL )
+ return false;
+ }
+
+ // Scroll the view as necessary to ensure that the new focus node is visible
+#ifndef KHTML_NO_CARET
+ // if it's an editable element, activate the caret
+ if (!m_part->isCaretMode() && !m_part->isEditable()
+ && node->contentEditable()) {
+ d->caretViewContext();
+ moveCaretTo(node, 0L, true);
+ } else {
+ caretOff();
+ }
+#endif // KHTML_NO_CARET
+
+ TQRect r = node->getRect();
+ ensureVisible( r.right(), r.bottom());
+ ensureVisible( r.left(), r.top());
+
+ Node guard( node );
+ if( node->isFocusable()) {
+ if (node->id()==ID_LABEL) {
+ // if Accesskey is a label, give focus to the label's referrer.
+ node=static_cast<ElementImpl *>(static_cast< HTMLLabelElementImpl* >( node )->getFormElement());
+ if (!node) return true;
+ guard = node;
+ }
+ // Set focus node on the document
+#ifdef USE_QT4
+ m_part->xmlDocImpl()->setFocusNode(node);
+#else // USE_QT4
+ TQFocusEvent::setReason( TQFocusEvent::Shortcut );
+ m_part->xmlDocImpl()->setFocusNode(node);
+ TQFocusEvent::resetReason();
+#endif // USE_QT4
+ if( node != NULL && node->hasOneRef()) // deleted, only held by guard
+ return true;
+ emit m_part->nodeActivated(Node(node));
+ if( node != NULL && node->hasOneRef())
+ return true;
+ }
+
+ switch( node->id()) {
+ case ID_A:
+ static_cast< HTMLAnchorElementImpl* >( node )->click();
+ break;
+ case ID_INPUT:
+ static_cast< HTMLInputElementImpl* >( node )->click();
+ break;
+ case ID_BUTTON:
+ static_cast< HTMLButtonElementImpl* >( node )->click();
+ break;
+ case ID_AREA:
+ static_cast< HTMLAreaElementImpl* >( node )->click();
+ break;
+ case ID_TEXTAREA:
+ break; // just focusing it is enough
+ case ID_LEGEND:
+ // TODO
+ break;
+ }
+ return true;
+}
+
+static TQString getElementText( NodeImpl* start, bool after )
+{
+ TQString ret; // nextSibling(), to go after e.g. </select>
+ for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode();
+ n != NULL;
+ n = after ? n->traverseNextNode() : n->traversePreviousNode()) {
+ if( n->isTextNode()) {
+ if( after )
+ ret += static_cast< TextImpl* >( n )->toString().string();
+ else
+ ret.prepend( static_cast< TextImpl* >( n )->toString().string());
+ } else {
+ switch( n->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_CITE:
+ case ID_ABBR:
+ case ID_ACRONYM:
+ case ID_SUB:
+ case ID_SUP:
+ case ID_SPAN:
+ case ID_NOBR:
+ case ID_WBR:
+ break;
+ case ID_TD:
+ if( ret.stripWhiteSpace().isEmpty())
+ break;
+ // fall through
+ default:
+ return ret.simplifyWhiteSpace();
+ }
+ }
+ }
+ return ret.simplifyWhiteSpace();
+}
+
+static TQMap< NodeImpl*, TQString > buildLabels( NodeImpl* start )
+{
+ TQMap< NodeImpl*, TQString > ret;
+ for( NodeImpl* n = start;
+ n != NULL;
+ n = n->traverseNextNode()) {
+ if( n->id() == ID_LABEL ) {
+ HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n );
+ NodeImpl* labelfor = label->getFormElement();
+ if( labelfor )
+ ret[ labelfor ] = label->innerText().string().simplifyWhiteSpace();
+ }
+ }
+ return ret;
+}
+
+namespace tdehtml {
+struct AccessKeyData {
+ ElementImpl* element;
+ TQString text;
+ TQString url;
+ int priority; // 10(highest) - 0(lowest)
+};
+}
+
+TQMap< ElementImpl*, TQChar > KHTMLView::buildFallbackAccessKeys() const
+{
+ // build a list of all possible candidate elements that could use an accesskey
+ TQValueList< AccessKeyData > data;
+ TQMap< NodeImpl*, TQString > labels = buildLabels( m_part->xmlDocImpl());
+ for( NodeImpl* n = m_part->xmlDocImpl();
+ n != NULL;
+ n = n->traverseNextNode()) {
+ if( n->isElementNode()) {
+ ElementImpl* element = static_cast< ElementImpl* >( n );
+ if( element->getAttribute( ATTR_ACCESSKEY ).length() == 1 )
+ continue; // has accesskey set, ignore
+ if( element->renderer() == NULL )
+ continue; // not visible
+ TQString text;
+ TQString url;
+ int priority = 0;
+ bool ignore = false;
+ bool text_after = false;
+ bool text_before = false;
+ switch( element->id()) {
+ case ID_A:
+ url = tdehtml::parseURL(element->getAttribute(ATTR_HREF)).string();
+ if( url.isEmpty()) // doesn't have href, it's only an anchor
+ continue;
+ text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace();
+ priority = 2;
+ break;
+ case ID_INPUT: {
+ HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element );
+ switch( in->inputType()) {
+ case HTMLInputElementImpl::SUBMIT:
+ text = in->value().string();
+ if( text.isEmpty())
+ text = i18n( "Submit" );
+ priority = 7;
+ break;
+ case HTMLInputElementImpl::IMAGE:
+ text = in->altText().string();
+ priority = 7;
+ break;
+ case HTMLInputElementImpl::BUTTON:
+ text = in->value().string();
+ priority = 5;
+ break;
+ case HTMLInputElementImpl::RESET:
+ text = in->value().string();
+ if( text.isEmpty())
+ text = i18n( "Reset" );
+ priority = 5;
+ break;
+ case HTMLInputElementImpl::HIDDEN:
+ ignore = true;
+ break;
+ case HTMLInputElementImpl::CHECKBOX:
+ case HTMLInputElementImpl::RADIO:
+ text_after = true;
+ priority = 5;
+ break;
+ case HTMLInputElementImpl::TEXT:
+ case HTMLInputElementImpl::PASSWORD:
+ case HTMLInputElementImpl::FILE:
+ text_before = true;
+ priority = 5;
+ break;
+ default:
+ priority = 5;
+ break;
+ }
+ break;
+ }
+ case ID_BUTTON:
+ text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplifyWhiteSpace();
+ switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) {
+ case HTMLButtonElementImpl::SUBMIT:
+ if( text.isEmpty())
+ text = i18n( "Submit" );
+ priority = 7;
+ break;
+ case HTMLButtonElementImpl::RESET:
+ if( text.isEmpty())
+ text = i18n( "Reset" );
+ priority = 5;
+ break;
+ default:
+ priority = 5;
+ break;
+ break;
+ }
+ case ID_SELECT: // these don't have accesskey attribute, but quick access may be handy
+ text_before = true;
+ text_after = true;
+ priority = 5;
+ break;
+ case ID_FRAME:
+ ignore = true;
+ break;
+ default:
+ ignore = !element->isFocusable();
+ priority = 2;
+ break;
+ }
+ if( ignore )
+ continue;
+ if( text.isNull() && labels.contains( element ))
+ text = labels[ element ];
+ if( text.isNull() && text_before )
+ text = getElementText( element, false );
+ if( text.isNull() && text_after )
+ text = getElementText( element, true );
+ text = text.stripWhiteSpace();
+ // increase priority of items which have explicitly specified accesskeys in the config
+ TQValueList< TQPair< TQString, TQChar > > priorities
+ = m_part->settings()->fallbackAccessKeysAssignments();
+ for( TQValueList< TQPair< TQString, TQChar > >::ConstIterator it = priorities.begin();
+ it != priorities.end();
+ ++it ) {
+ if( text == (*it).first )
+ priority = 10;
+ }
+ AccessKeyData tmp = { element, text, url, priority };
+ data.append( tmp );
+ }
+ }
+
+ TQValueList< TQChar > keys;
+ for( char c = 'A'; c <= 'Z'; ++c )
+ keys << c;
+ for( char c = '0'; c <= '9'; ++c )
+ keys << c;
+ for( NodeImpl* n = m_part->xmlDocImpl();
+ n != NULL;
+ n = n->traverseNextNode()) {
+ if( n->isElementNode()) {
+ ElementImpl* en = static_cast< ElementImpl* >( n );
+ DOMString s = en->getAttribute( ATTR_ACCESSKEY );
+ if( s.length() == 1 ) {
+ TQChar c = s.string()[ 0 ].upper();
+ keys.remove( c ); // remove manually assigned accesskeys
+ }
+ }
+ }
+
+ TQMap< ElementImpl*, TQChar > ret;
+ for( int priority = 10;
+ priority >= 0;
+ --priority ) {
+ for( TQValueList< AccessKeyData >::Iterator it = data.begin();
+ it != data.end();
+ ) {
+ if( (*it).priority != priority ) {
+ ++it;
+ continue;
+ }
+ if( keys.isEmpty())
+ break;
+ TQString text = (*it).text;
+ TQChar key;
+ if( key.isNull() && !text.isEmpty()) {
+ TQValueList< TQPair< TQString, TQChar > > priorities
+ = m_part->settings()->fallbackAccessKeysAssignments();
+ for( TQValueList< TQPair< TQString, TQChar > >::ConstIterator it = priorities.begin();
+ it != priorities.end();
+ ++it )
+ if( text == (*it).first && keys.contains( (*it).second )) {
+ key = (*it).second;
+ break;
+ }
+ }
+ // try first to select the first character as the accesskey,
+ // then first character of the following words,
+ // and then simply the first free character
+ if( key.isNull() && !text.isEmpty()) {
+ TQStringList words = TQStringList::split( ' ', text );
+ for( TQStringList::ConstIterator it = words.begin();
+ it != words.end();
+ ++it ) {
+ if( keys.contains( (*it)[ 0 ].upper())) {
+ key = (*it)[ 0 ].upper();
+ break;
+ }
+ }
+ }
+ if( key.isNull() && !text.isEmpty()) {
+ for( unsigned int i = 0;
+ i < text.length();
+ ++i ) {
+ if( keys.contains( text[ i ].upper())) {
+ key = text[ i ].upper();
+ break;
+ }
+ }
+ }
+ if( key.isNull())
+ key = keys.front();
+ ret[ (*it).element ] = key;
+ keys.remove( key );
+ TQString url = (*it).url;
+ it = data.remove( it );
+ // assign the same accesskey also to other elements pointing to the same url
+ if( !url.isEmpty() && !url.startsWith( "javascript:", false )) {
+ for( TQValueList< AccessKeyData >::Iterator it2 = data.begin();
+ it2 != data.end();
+ ) {
+ if( (*it2).url == url ) {
+ ret[ (*it2).element ] = key;
+ if( it == it2 )
+ ++it;
+ it2 = data.remove( it2 );
+ } else
+ ++it2;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+void KHTMLView::setMediaType( const TQString &medium )
+{
+ m_medium = medium;
+}
+
+TQString KHTMLView::mediaType() const
+{
+ return m_medium;
+}
+
+bool KHTMLView::pagedMode() const
+{
+ return d->paged;
+}
+
+void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis)
+{
+ if (vis) {
+ d->visibleWidgets.replace(w, w->widget());
+ }
+ else
+ d->visibleWidgets.remove(w);
+}
+
+bool KHTMLView::needsFullRepaint() const
+{
+ return d->needsFullRepaint;
+}
+
+void KHTMLView::print()
+{
+ print( false );
+}
+
+void KHTMLView::print(bool quick)
+{
+ if(!m_part->xmlDocImpl()) return;
+ tdehtml::RenderCanvas *root = static_cast<tdehtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
+ if(!root) return;
+
+ KPrinter *printer = new KPrinter(true, TQPrinter::ScreenResolution);
+ printer->addDialogPage(new KHTMLPrintSettings());
+ TQString docname = m_part->xmlDocImpl()->URL().prettyURL();
+ if ( !docname.isEmpty() )
+ docname = KStringHandler::csqueeze(docname, 80);
+ if(quick || printer->setup(this, i18n("Print %1").arg(docname))) {
+ viewport()->setCursor( tqwaitCursor ); // only viewport(), no TQApplication::, otherwise we get the busy cursor in tdeprint's dialogs
+ // set up KPrinter
+ printer->setFullPage(false);
+ printer->setCreator(TQString("KDE %1.%2.%3 HTML Library").arg(TDE_VERSION_MAJOR).arg(TDE_VERSION_MINOR).arg(TDE_VERSION_RELEASE));
+ printer->setDocName(docname);
+
+ TQPainter *p = new TQPainter;
+ p->begin( printer );
+ tdehtml::setPrintPainter( p );
+
+ m_part->xmlDocImpl()->setPaintDevice( printer );
+ TQString oldMediaType = mediaType();
+ setMediaType( "print" );
+ // We ignore margin settings for html and body when printing
+ // and use the default margins from the print-system
+ // (In Qt 3.0.x the default margins are hardcoded in Qt)
+ m_part->xmlDocImpl()->setPrintStyleSheet( printer->option("app-tdehtml-printfriendly") == "true" ?
+ "* { background-image: none !important;"
+ " background-color: white !important;"
+ " color: black !important; }"
+ "body { margin: 0px !important; }"
+ "html { margin: 0px !important; }" :
+ "body { margin: 0px !important; }"
+ "html { margin: 0px !important; }"
+ );
+
+ TQPaintDeviceMetrics metrics( printer );
+
+ kdDebug(6000) << "printing: physical page width = " << metrics.width()
+ << " height = " << metrics.height() << endl;
+ root->setStaticMode(true);
+ root->setPagedMode(true);
+ root->setWidth(metrics.width());
+// root->setHeight(metrics.height());
+ root->setPageTop(0);
+ root->setPageBottom(0);
+ d->paged = true;
+
+ m_part->xmlDocImpl()->styleSelector()->computeFontSizes(&metrics, 100);
+ m_part->xmlDocImpl()->updateStyleSelector();
+ root->setPrintImages( printer->option("app-tdehtml-printimages") == "true");
+ root->makePageBreakAvoidBlocks();
+
+ root->setNeedsLayoutAndMinMaxRecalc();
+ root->layout();
+ tdehtml::RenderWidget::flushWidgetResizes(); // make sure widgets have their final size
+
+ // check sizes ask for action.. (scale or clip)
+
+ bool printHeader = (printer->option("app-tdehtml-printheader") == "true");
+
+ int headerHeight = 0;
+ TQFont headerFont("Sans Serif", 8);
+
+ TQString headerLeft = TDEGlobal::locale()->formatDate(TQDate::currentDate(),true);
+ TQString headerMid = docname;
+ TQString headerRight;
+
+ if (printHeader)
+ {
+ p->setFont(headerFont);
+ headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2;
+ }
+
+ // ok. now print the pages.
+ kdDebug(6000) << "printing: html page width = " << root->docWidth()
+ << " height = " << root->docHeight() << endl;
+ kdDebug(6000) << "printing: margins left = " << printer->margins().width()
+ << " top = " << printer->margins().height() << endl;
+ kdDebug(6000) << "printing: paper width = " << metrics.width()
+ << " height = " << metrics.height() << endl;
+ // if the width is too large to fit on the paper we just scale
+ // the whole thing.
+ int pageWidth = metrics.width();
+ int pageHeight = metrics.height();
+ p->setClipRect(0,0, pageWidth, pageHeight);
+
+ pageHeight -= headerHeight;
+
+ bool scalePage = false;
+ double scale = 0.0;
+#ifndef QT_NO_TRANSFORMATIONS
+ if(root->docWidth() > metrics.width()) {
+ scalePage = true;
+ scale = ((double) metrics.width())/((double) root->docWidth());
+ pageHeight = (int) (pageHeight/scale);
+ pageWidth = (int) (pageWidth/scale);
+ headerHeight = (int) (headerHeight/scale);
+ }
+#endif
+ kdDebug(6000) << "printing: scaled html width = " << pageWidth
+ << " height = " << pageHeight << endl;
+
+ root->setHeight(pageHeight);
+ root->setPageBottom(pageHeight);
+ root->setNeedsLayout(true);
+ root->layoutIfNeeded();
+// m_part->slotDebugRenderTree();
+
+ // Squeeze header to make it it on the page.
+ if (printHeader)
+ {
+ int available_width = metrics.width() - 10 -
+ 2 * kMax(p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(),
+ p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width());
+ if (available_width < 150)
+ available_width = 150;
+ int mid_width;
+ int squeeze = 120;
+ do {
+ headerMid = KStringHandler::csqueeze(docname, squeeze);
+ mid_width = p->boundingRect(0, 0, metrics.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width();
+ squeeze -= 10;
+ } while (mid_width > available_width);
+ }
+
+ int top = 0;
+ int bottom = 0;
+ int page = 1;
+ while(top < root->docHeight()) {
+ if(top > 0) printer->newPage();
+ p->setClipRect(0, 0, pageWidth, headerHeight, TQPainter::CoordDevice);
+ if (printHeader)
+ {
+ int dy = p->fontMetrics().lineSpacing();
+ p->setPen(Qt::black);
+ p->setFont(headerFont);
+
+ headerRight = TQString("#%1").arg(page);
+
+ p->drawText(0, 0, metrics.width(), dy, Qt::AlignLeft, headerLeft);
+ p->drawText(0, 0, metrics.width(), dy, Qt::AlignHCenter, headerMid);
+ p->drawText(0, 0, metrics.width(), dy, Qt::AlignRight, headerRight);
+ }
+
+
+#ifndef QT_NO_TRANSFORMATIONS
+ if (scalePage)
+ p->scale(scale, scale);
+#endif
+
+ p->setClipRect(0, headerHeight, pageWidth, pageHeight, TQPainter::CoordDevice);
+ p->translate(0, headerHeight-top);
+
+ bottom = top+pageHeight;
+
+ root->setPageTop(top);
+ root->setPageBottom(bottom);
+ root->setPageNumber(page);
+
+ root->layer()->paint(p, TQRect(0, top, pageWidth, pageHeight));
+// m_part->xmlDocImpl()->renderer()->layer()->paint(p, TQRect(0, top, pageWidth, pageHeight));
+// root->repaint();
+// p->flush();
+ kdDebug(6000) << "printed: page " << page <<" bottom At = " << bottom << endl;
+
+ top = bottom;
+ p->resetXForm();
+ page++;
+ }
+
+ p->end();
+ delete p;
+
+ // and now reset the layout to the usual one...
+ root->setPagedMode(false);
+ root->setStaticMode(false);
+ d->paged = false;
+ tdehtml::setPrintPainter( 0 );
+ setMediaType( oldMediaType );
+ m_part->xmlDocImpl()->setPaintDevice( TQT_TQPAINTDEVICE(this) );
+ m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->paintDeviceMetrics(), m_part->zoomFactor());
+ m_part->xmlDocImpl()->updateStyleSelector();
+ viewport()->unsetCursor();
+ }
+ delete printer;
+}
+
+void KHTMLView::slotPaletteChanged()
+{
+ if(!m_part->xmlDocImpl()) return;
+ DOM::DocumentImpl *document = m_part->xmlDocImpl();
+ if (!document->isHTMLDocument()) return;
+ tdehtml::RenderCanvas *root = static_cast<tdehtml::RenderCanvas *>(document->renderer());
+ if(!root) return;
+ root->style()->resetPalette();
+ NodeImpl *body = static_cast<HTMLDocumentImpl*>(document)->body();
+ if(!body) return;
+ body->setChanged(true);
+ body->recalcStyle( NodeImpl::Force );
+}
+
+void KHTMLView::paint(TQPainter *p, const TQRect &rc, int yOff, bool *more)
+{
+ if(!m_part->xmlDocImpl()) return;
+ tdehtml::RenderCanvas *root = static_cast<tdehtml::RenderCanvas *>(m_part->xmlDocImpl()->renderer());
+ if(!root) return;
+
+ m_part->xmlDocImpl()->setPaintDevice(p->device());
+ root->setPagedMode(true);
+ root->setStaticMode(true);
+ root->setWidth(rc.width());
+
+ p->save();
+ p->setClipRect(rc);
+ p->translate(rc.left(), rc.top());
+ double scale = ((double) rc.width()/(double) root->docWidth());
+ int height = (int) ((double) rc.height() / scale);
+#ifndef QT_NO_TRANSFORMATIONS
+ p->scale(scale, scale);
+#endif
+ root->setPageTop(yOff);
+ root->setPageBottom(yOff+height);
+
+ root->layer()->paint(p, TQRect(0, yOff, root->docWidth(), height));
+ if (more)
+ *more = yOff + height < root->docHeight();
+ p->restore();
+
+ root->setPagedMode(false);
+ root->setStaticMode(false);
+ m_part->xmlDocImpl()->setPaintDevice( TQT_TQPAINTDEVICE(this) );
+}
+
+
+void KHTMLView::useSlowRepaints()
+{
+ d->useSlowRepaints = true;
+ setStaticBackground(true);
+}
+
+
+void KHTMLView::setVScrollBarMode ( ScrollBarMode mode )
+{
+#ifndef KHTML_NO_SCROLLBARS
+ d->vmode = mode;
+ TQScrollView::setVScrollBarMode(mode);
+#else
+ Q_UNUSED( mode );
+#endif
+}
+
+void KHTMLView::setHScrollBarMode ( ScrollBarMode mode )
+{
+#ifndef KHTML_NO_SCROLLBARS
+ d->hmode = mode;
+ TQScrollView::setHScrollBarMode(mode);
+#else
+ Q_UNUSED( mode );
+#endif
+}
+
+void KHTMLView::restoreScrollBar()
+{
+ int ow = visibleWidth();
+ TQScrollView::setVScrollBarMode(d->vmode);
+ if (visibleWidth() != ow)
+ layout();
+ d->prevScrollbarVisible = verticalScrollBar()->isVisible();
+}
+
+TQStringList KHTMLView::formCompletionItems(const TQString &name) const
+{
+ if (!m_part->settings()->isFormCompletionEnabled())
+ return TQStringList();
+ if (!d->formCompletions)
+ d->formCompletions = new KSimpleConfig(locateLocal("data", "tdehtml/formcompletions"));
+ return d->formCompletions->readListEntry(name);
+}
+
+void KHTMLView::clearCompletionHistory(const TQString& name)
+{
+ if (!d->formCompletions)
+ {
+ d->formCompletions = new KSimpleConfig(locateLocal("data", "tdehtml/formcompletions"));
+ }
+ d->formCompletions->writeEntry(name, "");
+ d->formCompletions->sync();
+}
+
+void KHTMLView::addFormCompletionItem(const TQString &name, const TQString &value)
+{
+ if (!m_part->settings()->isFormCompletionEnabled())
+ return;
+ // don't store values that are all numbers or just numbers with
+ // dashes or spaces as those are likely credit card numbers or
+ // something similar
+ bool cc_number(true);
+ for (unsigned int i = 0; i < value.length(); ++i)
+ {
+ TQChar c(value[i]);
+ if (!c.isNumber() && c != '-' && !c.isSpace())
+ {
+ cc_number = false;
+ break;
+ }
+ }
+ if (cc_number)
+ return;
+ TQStringList items = formCompletionItems(name);
+ if (!items.contains(value))
+ items.prepend(value);
+ while ((int)items.count() > m_part->settings()->maxFormCompletionItems())
+ items.remove(items.fromLast());
+ d->formCompletions->writeEntry(name, items);
+}
+
+void KHTMLView::removeFormCompletionItem(const TQString &name, const TQString &value)
+{
+ if (!m_part->settings()->isFormCompletionEnabled())
+ return;
+
+ TQStringList items = formCompletionItems(name);
+ if (items.remove(value))
+ d->formCompletions->writeEntry(name, items);
+}
+
+void KHTMLView::addNonPasswordStorableSite(const TQString& host)
+{
+ if (!d->formCompletions) {
+ d->formCompletions = new KSimpleConfig(locateLocal("data", "tdehtml/formcompletions"));
+ }
+
+ d->formCompletions->setGroup("NonPasswordStorableSites");
+ TQStringList sites = d->formCompletions->readListEntry("Sites");
+ sites.append(host);
+ d->formCompletions->writeEntry("Sites", sites);
+ d->formCompletions->sync();
+ d->formCompletions->setGroup(TQString::null);//reset
+}
+
+bool KHTMLView::nonPasswordStorableSite(const TQString& host) const
+{
+ if (!d->formCompletions) {
+ d->formCompletions = new KSimpleConfig(locateLocal("data", "tdehtml/formcompletions"));
+ }
+ d->formCompletions->setGroup("NonPasswordStorableSites");
+ TQStringList sites = d->formCompletions->readListEntry("Sites");
+ d->formCompletions->setGroup(TQString::null);//reset
+
+ return (sites.find(host) != sites.end());
+}
+
+// returns true if event should be swallowed
+bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
+ DOM::NodeImpl *targetNodeNonShared, bool cancelable,
+ int detail,TQMouseEvent *_mouse, bool setUnder,
+ int mouseEventType)
+{
+ // if the target node is a text node, dispatch on the parent node - rdar://4196646 (and #76948)
+ if (targetNode && targetNode->isTextNode())
+ targetNode = targetNode->parentNode();
+
+ if (d->underMouse)
+ d->underMouse->deref();
+ d->underMouse = targetNode;
+ if (d->underMouse)
+ d->underMouse->ref();
+
+ if (d->underMouseNonShared)
+ d->underMouseNonShared->deref();
+ d->underMouseNonShared = targetNodeNonShared;
+ if (d->underMouseNonShared)
+ d->underMouseNonShared->ref();
+
+ int exceptioncode = 0;
+ int pageX = 0;
+ int pageY = 0;
+ viewportToContents(_mouse->x(), _mouse->y(), pageX, pageY);
+ int clientX = pageX - contentsX();
+ int clientY = pageY - contentsY();
+ int screenX = _mouse->globalX();
+ int screenY = _mouse->globalY();
+ int button = -1;
+ switch (_mouse->button()) {
+ case Qt::LeftButton:
+ button = 0;
+ break;
+ case Qt::MidButton:
+ button = 1;
+ break;
+ case Qt::RightButton:
+ button = 2;
+ break;
+ default:
+ break;
+ }
+ if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1)
+ d->accessKeysPreActivate=false;
+
+ bool ctrlKey = (_mouse->state() & ControlButton);
+ bool altKey = (_mouse->state() & AltButton);
+ bool shiftKey = (_mouse->state() & ShiftButton);
+ bool metaKey = (_mouse->state() & MetaButton);
+
+ // mouseout/mouseover
+ if (setUnder && (d->prevMouseX != pageX || d->prevMouseY != pageY)) {
+
+ // ### this code sucks. we should save the oldUnder instead of calculating
+ // it again. calculating is expensive! (Dirk)
+ NodeImpl *oldUnder = 0;
+ if (d->prevMouseX >= 0 && d->prevMouseY >= 0) {
+ NodeImpl::MouseEvent mev( _mouse->stateAfter(), static_cast<NodeImpl::MouseEventType>(mouseEventType));
+ m_part->xmlDocImpl()->prepareMouseEvent( true, d->prevMouseX, d->prevMouseY, &mev );
+ oldUnder = mev.innerNode.handle();
+
+ if (oldUnder && oldUnder->isTextNode())
+ oldUnder = oldUnder->parentNode();
+ }
+// tqDebug("oldunder=%p (%s), target=%p (%s) x/y=%d/%d", oldUnder, oldUnder ? oldUnder->renderer()->renderName() : 0, targetNode, targetNode ? targetNode->renderer()->renderName() : 0, _mouse->x(), _mouse->y());
+ if (oldUnder != targetNode) {
+ // send mouseout event to the old node
+ if (oldUnder){
+ oldUnder->ref();
+ MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT,
+ true,true,m_part->xmlDocImpl()->defaultView(),
+ 0,screenX,screenY,clientX,clientY,pageX, pageY,
+ ctrlKey,altKey,shiftKey,metaKey,
+ button,targetNode);
+ me->ref();
+ oldUnder->dispatchEvent(me,exceptioncode,true);
+ me->deref();
+ }
+
+ // send mouseover event to the new node
+ if (targetNode) {
+ MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT,
+ true,true,m_part->xmlDocImpl()->defaultView(),
+ 0,screenX,screenY,clientX,clientY,pageX, pageY,
+ ctrlKey,altKey,shiftKey,metaKey,
+ button,oldUnder);
+
+ me->ref();
+ targetNode->dispatchEvent(me,exceptioncode,true);
+ me->deref();
+ }
+
+ if (oldUnder)
+ oldUnder->deref();
+ }
+ }
+
+ bool swallowEvent = false;
+
+ if (targetNode) {
+ // send the actual event
+ bool dblclick = ( eventId == EventImpl::CLICK_EVENT &&
+ _mouse->type() == TQEvent::MouseButtonDblClick );
+ MouseEventImpl *me = new MouseEventImpl(static_cast<EventImpl::EventId>(eventId),
+ true,cancelable,m_part->xmlDocImpl()->defaultView(),
+ detail,screenX,screenY,clientX,clientY,pageX, pageY,
+ ctrlKey,altKey,shiftKey,metaKey,
+ button,0, _mouse, dblclick );
+ me->ref();
+ targetNode->dispatchEvent(me,exceptioncode,true);
+ bool defaultHandled = me->defaultHandled();
+ if (defaultHandled || me->defaultPrevented())
+ swallowEvent = true;
+ me->deref();
+
+ if (eventId == EventImpl::MOUSEDOWN_EVENT) {
+ // Focus should be shifted on mouse down, not on a click. -dwh
+ // Blur current focus node when a link/button is clicked; this
+ // is expected by some sites that rely on onChange handlers running
+ // from form fields before the button click is processed.
+ DOM::NodeImpl* nodeImpl = targetNode;
+ for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode());
+ if (nodeImpl && nodeImpl->isMouseFocusable())
+ m_part->xmlDocImpl()->setFocusNode(nodeImpl);
+ else if (!nodeImpl || !nodeImpl->focused())
+ m_part->xmlDocImpl()->setFocusNode(0);
+ }
+ }
+
+ return swallowEvent;
+}
+
+void KHTMLView::setIgnoreWheelEvents( bool e )
+{
+ d->ignoreWheelEvents = e;
+}
+
+#ifndef QT_NO_WHEELEVENT
+
+void KHTMLView::viewportWheelEvent(TQWheelEvent* e)
+{
+ if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false;
+
+ if ( ( e->state() & ControlButton) == ControlButton )
+ {
+ emit zoomView( - e->delta() );
+ e->accept();
+ }
+ else if (d->firstRelayout)
+ {
+ e->accept();
+ }
+ else if( ( (e->orientation() == Qt::Vertical &&
+ ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible())
+ || e->delta() > 0 && contentsY() <= 0
+ || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight()))
+ ||
+ (e->orientation() == Qt::Horizontal &&
+ ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible())
+ || e->delta() > 0 && contentsX() <=0
+ || e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth())))
+ && m_part->parentPart())
+ {
+ if ( m_part->parentPart()->view() )
+ m_part->parentPart()->view()->wheelEvent( e );
+ e->ignore();
+ }
+ else
+ {
+ d->scrollBarMoved = true;
+#ifndef NO_SMOOTH_SCROLL_HACK
+ scrollViewWheelEvent( e );
+#else
+ TQScrollView::viewportWheelEvent( e );
+#endif
+
+ TQMouseEvent *tempEvent = new TQMouseEvent( TQEvent::MouseMove, TQPoint(-1,-1), TQPoint(-1,-1), Qt::NoButton, e->state() );
+ emit viewportMouseMoveEvent ( tempEvent );
+ delete tempEvent;
+ }
+
+}
+#endif
+
+void KHTMLView::dragEnterEvent( TQDragEnterEvent* ev )
+{
+ // Handle drops onto frames (#16820)
+ // Drops on the main html part is handled by Konqueror (and shouldn't do anything
+ // in e.g. kmail, so not handled here).
+ if ( m_part->parentPart() )
+ {
+ TQApplication::sendEvent(m_part->parentPart()->widget(), ev);
+ return;
+ }
+ TQScrollView::dragEnterEvent( ev );
+}
+
+void KHTMLView::dropEvent( TQDropEvent *ev )
+{
+ // Handle drops onto frames (#16820)
+ // Drops on the main html part is handled by Konqueror (and shouldn't do anything
+ // in e.g. kmail, so not handled here).
+ if ( m_part->parentPart() )
+ {
+ TQApplication::sendEvent(m_part->parentPart()->widget(), ev);
+ return;
+ }
+ TQScrollView::dropEvent( ev );
+}
+
+void KHTMLView::focusInEvent( TQFocusEvent *e )
+{
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ m_part->enableFindAheadActions( true );
+#endif
+ DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0;
+ if (fn && fn->renderer() && fn->renderer()->isWidget() &&
+ (e->reason() != TQFocusEvent::Mouse) &&
+ static_cast<tdehtml::RenderWidget*>(fn->renderer())->widget())
+ static_cast<tdehtml::RenderWidget*>(fn->renderer())->widget()->setFocus();
+#ifndef KHTML_NO_CARET
+ // Restart blink frequency timer if it has been killed, but only on
+ // editable nodes
+ if (d->m_caretViewContext &&
+ d->m_caretViewContext->freqTimerId == -1 &&
+ fn) {
+ if (m_part->isCaretMode()
+ || m_part->isEditable()
+ || (fn && fn->renderer()
+ && fn->renderer()->style()->userInput()
+ == UI_ENABLED)) {
+ d->m_caretViewContext->freqTimerId = startTimer(500);
+ d->m_caretViewContext->visible = true;
+ }/*end if*/
+ }/*end if*/
+ showCaret();
+#endif // KHTML_NO_CARET
+ TQScrollView::focusInEvent( e );
+}
+
+void KHTMLView::focusOutEvent( TQFocusEvent *e )
+{
+ if(m_part) m_part->stopAutoScroll();
+
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ if(d->typeAheadActivated)
+ {
+ findTimeout();
+ }
+ m_part->enableFindAheadActions( false );
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+
+#ifndef KHTML_NO_CARET
+ if (d->m_caretViewContext) {
+ switch (d->m_caretViewContext->displayNonFocused) {
+ case KHTMLPart::CaretInvisible:
+ hideCaret();
+ break;
+ case KHTMLPart::CaretVisible: {
+ killTimer(d->m_caretViewContext->freqTimerId);
+ d->m_caretViewContext->freqTimerId = -1;
+ NodeImpl *caretNode = m_part->xmlDocImpl()->focusNode();
+ if (!d->m_caretViewContext->visible && (m_part->isCaretMode()
+ || m_part->isEditable()
+ || (caretNode && caretNode->renderer()
+ && caretNode->renderer()->style()->userInput()
+ == UI_ENABLED))) {
+ d->m_caretViewContext->visible = true;
+ showCaret(true);
+ }/*end if*/
+ break;
+ }
+ case KHTMLPart::CaretBlink:
+ // simply leave as is
+ break;
+ }/*end switch*/
+ }/*end if*/
+#endif // KHTML_NO_CARET
+
+ if ( d->cursor_icon_widget )
+ d->cursor_icon_widget->hide();
+
+ TQScrollView::focusOutEvent( e );
+}
+
+void KHTMLView::slotScrollBarMoved()
+{
+ if ( !d->firstRelayout && !d->complete && m_part->xmlDocImpl() &&
+ d->layoutSchedulingEnabled) {
+ // contents scroll while we are not complete: we need to check our layout *now*
+ tdehtml::RenderCanvas* root = static_cast<tdehtml::RenderCanvas *>( m_part->xmlDocImpl()->renderer() );
+ if (root && root->needsLayout()) {
+ unscheduleRelayout();
+ layout();
+ }
+ }
+ if (!d->scrollingSelf) {
+ d->scrollBarMoved = true;
+ d->contentsMoving = true;
+ // ensure quick reset of contentsMoving flag
+ scheduleRepaint(0, 0, 0, 0);
+ }
+
+ if (m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement())
+ m_part->xmlDocImpl()->documentElement()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
+}
+
+void KHTMLView::timerEvent ( TQTimerEvent *e )
+{
+// kdDebug() << "timer event " << e->timerId() << endl;
+ if ( e->timerId() == d->scrollTimerId ) {
+ if( d->scrollSuspended )
+ return;
+ switch (d->scrollDirection) {
+ case KHTMLViewPrivate::ScrollDown:
+ if (contentsY() + visibleHeight () >= contentsHeight())
+ d->newScrollTimer(this, 0);
+ else
+ scrollBy( 0, d->scrollBy );
+ break;
+ case KHTMLViewPrivate::ScrollUp:
+ if (contentsY() <= 0)
+ d->newScrollTimer(this, 0);
+ else
+ scrollBy( 0, -d->scrollBy );
+ break;
+ case KHTMLViewPrivate::ScrollRight:
+ if (contentsX() + visibleWidth () >= contentsWidth())
+ d->newScrollTimer(this, 0);
+ else
+ scrollBy( d->scrollBy, 0 );
+ break;
+ case KHTMLViewPrivate::ScrollLeft:
+ if (contentsX() <= 0)
+ d->newScrollTimer(this, 0);
+ else
+ scrollBy( -d->scrollBy, 0 );
+ break;
+ }
+ return;
+ }
+ else if ( e->timerId() == d->layoutTimerId ) {
+ d->dirtyLayout = true;
+ layout();
+ if (d->firstRelayout) {
+ d->firstRelayout = false;
+ verticalScrollBar()->setEnabled( true );
+ horizontalScrollBar()->setEnabled( true );
+ }
+ }
+#ifndef KHTML_NO_CARET
+ else if (d->m_caretViewContext
+ && e->timerId() == d->m_caretViewContext->freqTimerId) {
+ d->m_caretViewContext->visible = !d->m_caretViewContext->visible;
+ if (d->m_caretViewContext->displayed) {
+ updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ }/*end if*/
+// if (d->m_caretViewContext->visible) cout << "|" << flush;
+// else cout << "" << flush;
+ return;
+ }
+#endif
+
+ d->contentsMoving = false;
+ if( m_part->xmlDocImpl() ) {
+ DOM::DocumentImpl *document = m_part->xmlDocImpl();
+ tdehtml::RenderCanvas* root = static_cast<tdehtml::RenderCanvas *>(document->renderer());
+
+ if ( root && root->needsLayout() ) {
+ killTimer(d->repaintTimerId);
+ d->repaintTimerId = 0;
+ scheduleRelayout();
+ return;
+ }
+ }
+
+ setStaticBackground(d->useSlowRepaints);
+
+// kdDebug() << "scheduled repaint "<< d->repaintTimerId << endl;
+ killTimer(d->repaintTimerId);
+ d->repaintTimerId = 0;
+
+ TQRect updateRegion;
+ TQMemArray<TQRect> rects = d->updateRegion.rects();
+
+ d->updateRegion = TQRegion();
+
+ if ( rects.size() )
+ updateRegion = rects[0];
+
+ for ( unsigned i = 1; i < rects.size(); ++i ) {
+ TQRect newRegion = updateRegion.unite(rects[i]);
+ if (2*newRegion.height() > 3*updateRegion.height() )
+ {
+ repaintContents( updateRegion );
+ updateRegion = rects[i];
+ }
+ else
+ updateRegion = newRegion;
+ }
+
+ if ( !updateRegion.isNull() )
+ repaintContents( updateRegion );
+
+ // As widgets can only be accurately positioned during painting, every layout might
+ // dissociate a widget from its RenderWidget. E.g: if a RenderWidget was visible before layout, but the layout
+ // pushed it out of the viewport, it will not be repainted, and consequently it's assocoated widget won't be repositioned!
+ // Thus we need to check each supposedly 'visible' widget at the end of each layout, and remove it in case it's no more in sight.
+
+ if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) {
+ TQWidget* w;
+ d->dirtyLayout = false;
+
+ TQRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
+ TQPtrList<RenderWidget> toRemove;
+ for (TQPtrDictIterator<TQWidget> it(d->visibleWidgets); it.current(); ++it) {
+ int xp = 0, yp = 0;
+ w = it.current();
+ RenderWidget* rw = static_cast<RenderWidget*>( it.currentKey() );
+ if (!rw->absolutePosition(xp, yp) ||
+ !visibleRect.intersects(TQRect(xp, yp, w->width(), w->height())))
+ toRemove.append(rw);
+ }
+ for (RenderWidget* r = toRemove.first(); r; r = toRemove.next())
+ if ( (w = d->visibleWidgets.take(r) ) )
+ addChild(w, 0, -500000);
+ }
+
+ emit repaintAccessKeys();
+ if (d->emitCompletedAfterRepaint) {
+ bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull;
+ d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone;
+ if ( full )
+ emit m_part->completed();
+ else
+ emit m_part->completed(true);
+ }
+}
+
+void KHTMLView::scheduleRelayout(tdehtml::RenderObject * /*clippedObj*/)
+{
+ if (!d->layoutSchedulingEnabled || d->layoutTimerId)
+ return;
+
+ d->layoutTimerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing()
+ ? 1000 : 0 );
+}
+
+void KHTMLView::unscheduleRelayout()
+{
+ if (!d->layoutTimerId)
+ return;
+
+ killTimer(d->layoutTimerId);
+ d->layoutTimerId = 0;
+}
+
+void KHTMLView::unscheduleRepaint()
+{
+ if (!d->repaintTimerId)
+ return;
+
+ killTimer(d->repaintTimerId);
+ d->repaintTimerId = 0;
+}
+
+void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap)
+{
+ bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing();
+
+// kdDebug() << "parsing " << parsing << endl;
+// kdDebug() << "complete " << d->complete << endl;
+
+ int time = parsing ? 300 : (!asap ? ( !d->complete ? 100 : 20 ) : 0);
+
+#ifdef DEBUG_FLICKER
+ TQPainter p;
+ p.begin( viewport() );
+
+ int vx, vy;
+ contentsToViewport( x, y, vx, vy );
+ p.fillRect( vx, vy, w, h, TQt::red );
+ p.end();
+#endif
+
+ d->updateRegion = d->updateRegion.unite(TQRect(x,y,w,h));
+
+ if (asap && !parsing)
+ unscheduleRepaint();
+
+ if ( !d->repaintTimerId )
+ d->repaintTimerId = startTimer( time );
+
+// kdDebug() << "starting timer " << time << endl;
+}
+
+void KHTMLView::complete( bool pendingAction )
+{
+// kdDebug() << "KHTMLView::complete()" << endl;
+
+ d->complete = true;
+
+ // is there a relayout pending?
+ if (d->layoutTimerId)
+ {
+// kdDebug() << "requesting relayout now" << endl;
+ // do it now
+ killTimer(d->layoutTimerId);
+ d->layoutTimerId = startTimer( 0 );
+ d->emitCompletedAfterRepaint = pendingAction ?
+ KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
+ }
+
+ // is there a repaint pending?
+ if (d->repaintTimerId)
+ {
+// kdDebug() << "requesting repaint now" << endl;
+ // do it now
+ killTimer(d->repaintTimerId);
+ d->repaintTimerId = startTimer( 20 );
+ d->emitCompletedAfterRepaint = pendingAction ?
+ KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull;
+ }
+
+ if (!d->emitCompletedAfterRepaint)
+ {
+ if (!pendingAction)
+ emit m_part->completed();
+ else
+ emit m_part->completed(true);
+ }
+
+}
+
+void KHTMLView::slotMouseScrollTimer()
+{
+ scrollBy( d->m_mouseScroll_byX, d->m_mouseScroll_byY );
+}
+
+#ifndef KHTML_NO_CARET
+
+// ### the dependencies on static functions are a nightmare. just be
+// hacky and include the implementation here. Clean me up, please.
+
+#include "tdehtml_caret.cpp"
+
+void KHTMLView::initCaret(bool keepSelection)
+{
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "begin initCaret" << endl;
+#endif
+ // save caretMoved state as moveCaretTo changes it
+ if (m_part->xmlDocImpl()) {
+#if 0
+ ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__");
+ if (listitem) dumpLineBoxes(static_cast<RenderFlow *>(listitem->renderer()));
+#endif
+ d->caretViewContext();
+ bool cmoved = d->m_caretViewContext->caretMoved;
+ if (m_part->d->caretNode().isNull()) {
+ // set to document, position will be sanitized anyway
+ m_part->d->caretNode() = m_part->document();
+ m_part->d->caretOffset() = 0L;
+ // This sanity check is necessary for the not so unlikely case that
+ // setEditable or setCaretMode is called before any render objects have
+ // been created.
+ if (!m_part->d->caretNode().handle()->renderer()) return;
+ }/*end if*/
+// kdDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle()
+// << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl;
+ // ### does not repaint the selection on keepSelection!=false
+ moveCaretTo(m_part->d->caretNode().handle(), m_part->d->caretOffset(), !keepSelection);
+// kdDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle()
+// << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl;
+ d->m_caretViewContext->caretMoved = cmoved;
+ }/*end if*/
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "end initCaret" << endl;
+#endif
+}
+
+bool KHTMLView::caretOverrides() const
+{
+ bool cm = m_part->isCaretMode();
+ bool dm = m_part->isEditable();
+ return cm && !dm ? false
+ : (dm || m_part->d->caretNode().handle()->contentEditable())
+ && d->editorContext()->override;
+}
+
+void KHTMLView::ensureNodeHasFocus(NodeImpl *node)
+{
+ if (m_part->isCaretMode() || m_part->isEditable()) return;
+ if (node->focused()) return;
+
+ // Find first ancestor whose "user-input" is "enabled"
+ NodeImpl *firstAncestor = 0;
+ while (node) {
+ if (node->renderer()
+ && node->renderer()->style()->userInput() != UI_ENABLED)
+ break;
+ firstAncestor = node;
+ node = node->parentNode();
+ }/*wend*/
+
+ if (!node) firstAncestor = 0;
+
+ DocumentImpl *doc = m_part->xmlDocImpl();
+ // ensure that embedded widgets don't lose their focus
+ if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer()
+ && doc->focusNode()->renderer()->isWidget())
+ return;
+
+ // Set focus node on the document
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << k_funcinfo << "firstAncestor " << firstAncestor << ": "
+ << (firstAncestor ? firstAncestor->nodeName().string() : TQString::null) << endl;
+#endif
+ doc->setFocusNode(firstAncestor);
+ emit m_part->nodeActivated(Node(firstAncestor));
+}
+
+void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox)
+{
+ if (!m_part || m_part->d->caretNode().isNull()) return;
+ d->caretViewContext();
+ NodeImpl *caretNode = m_part->d->caretNode().handle();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ? " "+caretNode->nodeName().string() : TQString::null) << " r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ? " \"" + TQConstString(static_cast<RenderText *>(caretNode->renderer())->str->s, kMin(static_cast<RenderText *>(caretNode->renderer())->str->l, 15u)).string() + "\"" : TQString::null) << endl;
+#endif
+ caretNode->getCaret(m_part->d->caretOffset(), caretOverrides(),
+ d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+
+ if (hintBox && d->m_caretViewContext->x == -1) {
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "using hint inline box coordinates" << endl;
+#endif
+ RenderObject *r = caretNode->renderer();
+ const TQFontMetrics &fm = r->style()->fontMetrics();
+ int absx, absy;
+ r->containingBlock()->absolutePosition(absx, absy,
+ false); // ### what about fixed?
+ d->m_caretViewContext->x = absx + hintBox->xPos();
+ d->m_caretViewContext->y = absy + hintBox->yPos();
+// + hintBox->baseline() - fm.ascent();
+ d->m_caretViewContext->width = 1;
+ // ### firstline not regarded. But I think it can be safely neglected
+ // as hint boxes are only used for empty lines.
+ d->m_caretViewContext->height = fm.height();
+ }/*end if*/
+
+#if DEBUG_CARETMODE > 4
+// kdDebug(6200) << "freqTimerId: "<<d->m_caretViewContext->freqTimerId<<endl;
+#endif
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "caret: ofs="<<m_part->d->caretOffset()<<" "
+ <<" x="<<d->m_caretViewContext->x<<" y="<<d->m_caretViewContext->y
+ <<" h="<<d->m_caretViewContext->height<<endl;
+#endif
+}
+
+void KHTMLView::caretOn()
+{
+ if (d->m_caretViewContext) {
+ killTimer(d->m_caretViewContext->freqTimerId);
+
+ if (hasFocus() || d->m_caretViewContext->displayNonFocused
+ == KHTMLPart::CaretBlink) {
+ d->m_caretViewContext->freqTimerId = startTimer(500);
+ } else {
+ d->m_caretViewContext->freqTimerId = -1;
+ }/*end if*/
+
+ d->m_caretViewContext->visible = true;
+ if ((d->m_caretViewContext->displayed = (hasFocus()
+ || d->m_caretViewContext->displayNonFocused
+ != KHTMLPart::CaretInvisible))) {
+ updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ }/*end if*/
+// kdDebug(6200) << "caret on" << endl;
+ }/*end if*/
+}
+
+void KHTMLView::caretOff()
+{
+ if (d->m_caretViewContext) {
+ killTimer(d->m_caretViewContext->freqTimerId);
+ d->m_caretViewContext->freqTimerId = -1;
+ d->m_caretViewContext->displayed = false;
+ if (d->m_caretViewContext->visible) {
+ d->m_caretViewContext->visible = false;
+ updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ }/*end if*/
+// kdDebug(6200) << "caret off" << endl;
+ }/*end if*/
+}
+
+void KHTMLView::showCaret(bool forceRepaint)
+{
+ if (d->m_caretViewContext) {
+ d->m_caretViewContext->displayed = true;
+ if (d->m_caretViewContext->visible) {
+ if (!forceRepaint) {
+ updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ } else {
+ repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ }/*end if*/
+ }/*end if*/
+// kdDebug(6200) << "caret shown" << endl;
+ }/*end if*/
+}
+
+bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode, long startOffset,
+ NodeImpl *endNode, long endOffset)
+{
+ m_part->d->m_selectionStart = m_part->d->m_selectionEnd = m_part->d->caretNode();
+ m_part->d->m_startOffset = m_part->d->m_endOffset = m_part->d->caretOffset();
+ m_part->d->m_extendAtEnd = true;
+
+ bool folded = startNode != endNode || startOffset != endOffset;
+
+ // Only clear the selection if there has been one.
+ if (folded) {
+ m_part->xmlDocImpl()->clearSelection();
+ }/*end if*/
+
+ return folded;
+}
+
+void KHTMLView::hideCaret()
+{
+ if (d->m_caretViewContext) {
+ if (d->m_caretViewContext->visible) {
+// kdDebug(6200) << "redraw caret hidden" << endl;
+ d->m_caretViewContext->visible = false;
+ // force repaint, otherwise the event won't be handled
+ // before the focus leaves the window
+ repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width,
+ d->m_caretViewContext->height);
+ d->m_caretViewContext->visible = true;
+ }/*end if*/
+ d->m_caretViewContext->displayed = false;
+// kdDebug(6200) << "caret hidden" << endl;
+ }/*end if*/
+}
+
+int KHTMLView::caretDisplayPolicyNonFocused() const
+{
+ if (d->m_caretViewContext)
+ return d->m_caretViewContext->displayNonFocused;
+ else
+ return KHTMLPart::CaretInvisible;
+}
+
+void KHTMLView::setCaretDisplayPolicyNonFocused(int policy)
+{
+ d->caretViewContext();
+// int old = d->m_caretViewContext->displayNonFocused;
+ d->m_caretViewContext->displayNonFocused = (KHTMLPart::CaretDisplayPolicy)policy;
+
+ // make change immediately take effect if not focused
+ if (!hasFocus()) {
+ switch (d->m_caretViewContext->displayNonFocused) {
+ case KHTMLPart::CaretInvisible:
+ hideCaret();
+ break;
+ case KHTMLPart::CaretBlink:
+ if (d->m_caretViewContext->freqTimerId != -1) break;
+ d->m_caretViewContext->freqTimerId = startTimer(500);
+ // fall through
+ case KHTMLPart::CaretVisible:
+ d->m_caretViewContext->displayed = true;
+ showCaret();
+ break;
+ }/*end switch*/
+ }/*end if*/
+}
+
+bool KHTMLView::placeCaret(CaretBox *hintBox)
+{
+ CaretViewContext *cv = d->caretViewContext();
+ caretOff();
+ NodeImpl *caretNode = m_part->d->caretNode().handle();
+ // ### why is it sometimes null?
+ if (!caretNode || !caretNode->renderer()) return false;
+ ensureNodeHasFocus(caretNode);
+ if (m_part->isCaretMode() || m_part->isEditable()
+ || caretNode->renderer()->style()->userInput() == UI_ENABLED) {
+ recalcAndStoreCaretPos(hintBox);
+
+ cv->origX = cv->x;
+
+ caretOn();
+ return true;
+ }/*end if*/
+ return false;
+}
+
+void KHTMLView::ensureCaretVisible()
+{
+ CaretViewContext *cv = d->m_caretViewContext;
+ if (!cv) return;
+ ensureVisible(cv->x, cv->y, cv->width, cv->height);
+ d->scrollBarMoved = false;
+}
+
+bool KHTMLView::extendSelection(NodeImpl *oldStartSel, long oldStartOfs,
+ NodeImpl *oldEndSel, long oldEndOfs)
+{
+ bool changed = false;
+ if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
+ && m_part->d->m_startOffset == m_part->d->m_endOffset) {
+ changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
+ m_part->d->m_extendAtEnd = true;
+ } else do {
+ changed = m_part->d->m_selectionStart.handle() != oldStartSel
+ || m_part->d->m_startOffset != oldStartOfs
+ || m_part->d->m_selectionEnd.handle() != oldEndSel
+ || m_part->d->m_endOffset != oldEndOfs;
+ if (!changed) break;
+
+ // determine start position -- caret position is always at end.
+ NodeImpl *startNode;
+ long startOffset;
+ if (m_part->d->m_extendAtEnd) {
+ startNode = m_part->d->m_selectionStart.handle();
+ startOffset = m_part->d->m_startOffset;
+ } else {
+ startNode = m_part->d->m_selectionEnd.handle();
+ startOffset = m_part->d->m_endOffset;
+ m_part->d->m_selectionEnd = m_part->d->m_selectionStart;
+ m_part->d->m_endOffset = m_part->d->m_startOffset;
+ m_part->d->m_extendAtEnd = true;
+ }/*end if*/
+
+ bool swapNeeded = false;
+ if (!m_part->d->m_selectionEnd.isNull() && startNode) {
+ swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset,
+ m_part->d->m_selectionEnd.handle(),
+ m_part->d->m_endOffset) >= 0;
+ }/*end if*/
+
+ m_part->d->m_selectionStart = startNode;
+ m_part->d->m_startOffset = startOffset;
+
+ if (swapNeeded) {
+ m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionEnd.handle(),
+ m_part->d->m_endOffset, m_part->d->m_selectionStart.handle(),
+ m_part->d->m_startOffset);
+ } else {
+ m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
+ m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
+ m_part->d->m_endOffset);
+ }/*end if*/
+ } while(false);/*end if*/
+ return changed;
+}
+
+void KHTMLView::updateSelection(NodeImpl *oldStartSel, long oldStartOfs,
+ NodeImpl *oldEndSel, long oldEndOfs)
+{
+ if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd
+ && m_part->d->m_startOffset == m_part->d->m_endOffset) {
+ if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) {
+ m_part->emitSelectionChanged();
+ }/*end if*/
+ m_part->d->m_extendAtEnd = true;
+ } else {
+ // check if the extending end has passed the immobile end
+ if (!m_part->d->m_selectionEnd.isNull() && !m_part->d->m_selectionEnd.isNull()) {
+ bool swapNeeded = RangeImpl::compareBoundaryPoints(
+ m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset,
+ m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0;
+ if (swapNeeded) {
+ DOM::Node tmpNode = m_part->d->m_selectionStart;
+ long tmpOffset = m_part->d->m_startOffset;
+ m_part->d->m_selectionStart = m_part->d->m_selectionEnd;
+ m_part->d->m_startOffset = m_part->d->m_endOffset;
+ m_part->d->m_selectionEnd = tmpNode;
+ m_part->d->m_endOffset = tmpOffset;
+ m_part->d->m_startBeforeEnd = true;
+ m_part->d->m_extendAtEnd = !m_part->d->m_extendAtEnd;
+ }/*end if*/
+ }/*end if*/
+
+ m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(),
+ m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(),
+ m_part->d->m_endOffset);
+ m_part->emitSelectionChanged();
+ }/*end if*/
+}
+
+void KHTMLView::caretKeyPressEvent(TQKeyEvent *_ke)
+{
+ NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
+ long oldStartOfs = m_part->d->m_startOffset;
+ NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
+ long oldEndOfs = m_part->d->m_endOffset;
+
+ NodeImpl *oldCaretNode = m_part->d->caretNode().handle();
+ long oldOffset = m_part->d->caretOffset();
+
+ bool ctrl = _ke->state() & ControlButton;
+
+// FIXME: this is that widely indented because I will write ifs around it.
+ switch(_ke->key()) {
+ case Key_Space:
+ break;
+
+ case Key_Down:
+ moveCaretNextLine(1);
+ break;
+
+ case Key_Up:
+ moveCaretPrevLine(1);
+ break;
+
+ case Key_Left:
+ moveCaretBy(false, ctrl ? CaretByWord : CaretByCharacter, 1);
+ break;
+
+ case Key_Right:
+ moveCaretBy(true, ctrl ? CaretByWord : CaretByCharacter, 1);
+ break;
+
+ case Key_Next:
+ moveCaretNextPage();
+ break;
+
+ case Key_Prior:
+ moveCaretPrevPage();
+ break;
+
+ case Key_Home:
+ if (ctrl)
+ moveCaretToDocumentBoundary(false);
+ else
+ moveCaretToLineBegin();
+ break;
+
+ case Key_End:
+ if (ctrl)
+ moveCaretToDocumentBoundary(true);
+ else
+ moveCaretToLineEnd();
+ break;
+
+ }/*end switch*/
+
+ if ((m_part->d->caretNode().handle() != oldCaretNode
+ || m_part->d->caretOffset() != oldOffset)
+ // node should never be null, but faulty conditions may cause it to be
+ && !m_part->d->caretNode().isNull()) {
+
+ d->m_caretViewContext->caretMoved = true;
+
+ if (_ke->state() & ShiftButton) { // extend selection
+ updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
+ } else { // clear any selection
+ if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs))
+ m_part->emitSelectionChanged();
+ }/*end if*/
+
+ m_part->emitCaretPositionChanged(m_part->d->caretNode(), m_part->d->caretOffset());
+ }/*end if*/
+
+ _ke->accept();
+}
+
+bool KHTMLView::moveCaretTo(NodeImpl *node, long offset, bool clearSel)
+{
+ if (!node) return false;
+ ElementImpl *baseElem = determineBaseElement(node);
+ RenderFlow *base = static_cast<RenderFlow *>(baseElem ? baseElem->renderer() : 0);
+ if (!node) return false;
+
+ // need to find out the node's inline box. If there is none, this function
+ // will snap to the next node that has one. This is necessary to make the
+ // caret visible in any case.
+ CaretBoxLineDeleter cblDeleter;
+// RenderBlock *cb;
+ long r_ofs;
+ CaretBoxIterator cbit;
+ CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit);
+ if(!cbl) {
+ kdWarning() << "KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL" << endl;
+ return false;
+ }
+
+#if DEBUG_CARETMODE > 3
+ if (cbl) kdDebug(6200) << cbl->information() << endl;
+#endif
+ CaretBox *box = *cbit;
+ if (cbit != cbl->end() && box->object() != node->renderer()) {
+ if (box->object()->element()) {
+ mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(),
+ box->isOutsideEnd(), node, offset);
+ //if (!outside) offset = node->minOffset();
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "set new node " << node->nodeName().string() << "@" << node << endl;
+#endif
+ } else { // box has no associated element -> do not use
+ // this case should actually never happen.
+ box = 0;
+ kdError(6200) << "Box contains no node! Crash imminent" << endl;
+ }/*end if*/
+ }
+
+ NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle();
+ long oldStartOfs = m_part->d->m_startOffset;
+ NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle();
+ long oldEndOfs = m_part->d->m_endOffset;
+
+ // test for position change
+ bool posChanged = m_part->d->caretNode().handle() != node
+ || m_part->d->caretOffset() != offset;
+ bool selChanged = false;
+
+ m_part->d->caretNode() = node;
+ m_part->d->caretOffset() = offset;
+ if (clearSel || !oldStartSel || !oldEndSel) {
+ selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
+ } else {
+ //kdDebug(6200) << "moveToCaret: extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd << endl;
+ //kdDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")" << endl;
+ selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs);
+ //kdDebug(6200) << "after extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd << endl;
+ //kdDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")" << endl;
+ }/*end if*/
+
+ d->caretViewContext()->caretMoved = true;
+
+ bool visible_caret = placeCaret(box);
+
+ // FIXME: if the old position was !visible_caret, and the new position is
+ // also, then two caretPositionChanged signals with a null Node are
+ // emitted in series.
+ if (posChanged) {
+ m_part->emitCaretPositionChanged(visible_caret ? node : 0, offset);
+ }/*end if*/
+
+ return selChanged;
+}
+
+void KHTMLView::moveCaretByLine(bool next, int count)
+{
+ Node &caretNodeRef = m_part->d->caretNode();
+ if (caretNodeRef.isNull()) return;
+
+ NodeImpl *caretNode = caretNodeRef.handle();
+// kdDebug(6200) << ": caretNode=" << caretNode << endl;
+ long offset = m_part->d->caretOffset();
+
+ CaretViewContext *cv = d->caretViewContext();
+
+ ElementImpl *baseElem = determineBaseElement(caretNode);
+ LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
+
+ ErgonomicEditableLineIterator it(ld.current(), cv->origX);
+
+ // move count lines vertically
+ while (count > 0 && it != ld.end() && it != ld.preBegin()) {
+ count--;
+ if (next) ++it; else --it;
+ }/*wend*/
+
+ // Nothing? Then leave everything as is.
+ if (it == ld.end() || it == ld.preBegin()) return;
+
+ int x, absx, absy;
+ CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
+
+ placeCaretOnLine(caretBox, x, absx, absy);
+}
+
+void KHTMLView::placeCaretOnLine(CaretBox *caretBox, int x, int absx, int absy)
+{
+ // paranoia sanity check
+ if (!caretBox) return;
+
+ RenderObject *caretRender = caretBox->object();
+
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "got valid caretBox " << caretBox << endl;
+ kdDebug(6200) << "xPos: " << caretBox->xPos() << " yPos: " << caretBox->yPos()
+ << " width: " << caretBox->width() << " height: " << caretBox->height() << endl;
+ InlineTextBox *tb = static_cast<InlineTextBox *>(caretBox->inlineBox());
+ if (caretBox->isInlineTextBox()) { kdDebug(6200) << "contains \"" << TQString(static_cast<RenderText *>(tb->object())->str->s + tb->m_start, tb->m_len) << "\"" << endl;}
+#endif
+ // inquire height of caret
+ int caretHeight = caretBox->height();
+ bool isText = caretBox->isInlineTextBox();
+ int yOfs = 0; // y-offset for text nodes
+ if (isText) {
+ // text boxes need extrawurst
+ RenderText *t = static_cast<RenderText *>(caretRender);
+ const TQFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine);
+ caretHeight = fm.height();
+ yOfs = caretBox->inlineBox()->baseline() - fm.ascent();
+ }/*end if*/
+
+ caretOff();
+
+ // set new caret node
+ NodeImpl *caretNode;
+ long &offset = m_part->d->caretOffset();
+ mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(),
+ caretBox->isOutsideEnd(), caretNode, offset);
+
+ // set all variables not needing special treatment
+ d->m_caretViewContext->y = caretBox->yPos() + yOfs;
+ d->m_caretViewContext->height = caretHeight;
+ d->m_caretViewContext->width = 1; // FIXME: regard override
+
+ int xPos = caretBox->xPos();
+ int caretBoxWidth = caretBox->width();
+ d->m_caretViewContext->x = xPos;
+
+ if (!caretBox->isOutside()) {
+ // before or at beginning of inline box -> place at beginning
+ long r_ofs = 0;
+ if (x <= xPos) {
+ r_ofs = caretBox->minOffset();
+ // somewhere within this block
+ } else if (x > xPos && x <= xPos + caretBoxWidth) {
+ if (isText) { // find out where exactly
+ r_ofs = static_cast<InlineTextBox *>(caretBox->inlineBox())
+ ->offsetForPoint(x, d->m_caretViewContext->x);
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "deviation from origX " << d->m_caretViewContext->x - x << endl;
+#endif
+#if 0
+ } else { // snap to nearest end
+ if (xPos + caretBoxWidth - x < x - xPos) {
+ d->m_caretViewContext->x = xPos + caretBoxWidth;
+ r_ofs = caretNode ? caretNode->maxOffset() : 1;
+ } else {
+ d->m_caretViewContext->x = xPos;
+ r_ofs = caretNode ? caretNode->minOffset() : 0;
+ }/*end if*/
+#endif
+ }/*end if*/
+ } else { // after the inline box -> place at end
+ d->m_caretViewContext->x = xPos + caretBoxWidth;
+ r_ofs = caretBox->maxOffset();
+ }/*end if*/
+ offset = r_ofs;
+ }/*end if*/
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "new offset: " << offset << endl;
+#endif
+
+ m_part->d->caretNode() = caretNode;
+ m_part->d->caretOffset() = offset;
+
+ d->m_caretViewContext->x += absx;
+ d->m_caretViewContext->y += absy;
+
+#if DEBUG_CARETMODE > 1
+ kdDebug(6200) << "new caret position: x " << d->m_caretViewContext->x << " y " << d->m_caretViewContext->y << " w " << d->m_caretViewContext->width << " h " << d->m_caretViewContext->height << " absx " << absx << " absy " << absy << endl;
+#endif
+
+ ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width, d->m_caretViewContext->height);
+ d->scrollBarMoved = false;
+
+ ensureNodeHasFocus(caretNode);
+ caretOn();
+}
+
+void KHTMLView::moveCaretToLineBoundary(bool end)
+{
+ Node &caretNodeRef = m_part->d->caretNode();
+ if (caretNodeRef.isNull()) return;
+
+ NodeImpl *caretNode = caretNodeRef.handle();
+// kdDebug(6200) << ": caretNode=" << caretNode << endl;
+ long offset = m_part->d->caretOffset();
+
+ ElementImpl *baseElem = determineBaseElement(caretNode);
+ LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
+
+ EditableLineIterator it = ld.current();
+ if (it == ld.end()) return; // should not happen, but who knows
+
+ EditableCaretBoxIterator fbit(it, end);
+ Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
+ CaretBox *b = *fbit;
+
+ RenderObject *cb = b->containingBlock();
+ int absx, absy;
+
+ if (cb) cb->absolutePosition(absx,absy);
+ else absx = absy = 0;
+
+ int x = b->xPos() + (end && !b->isOutside() ? b->width() : 0);
+ d->m_caretViewContext->origX = absx + x;
+ placeCaretOnLine(b, x, absx, absy);
+}
+
+void KHTMLView::moveCaretToDocumentBoundary(bool end)
+{
+ Node &caretNodeRef = m_part->d->caretNode();
+ if (caretNodeRef.isNull()) return;
+
+ NodeImpl *caretNode = caretNodeRef.handle();
+// kdDebug(6200) << ": caretNode=" << caretNode << endl;
+ long offset = m_part->d->caretOffset();
+
+ ElementImpl *baseElem = determineBaseElement(caretNode);
+ LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem);
+
+ EditableLineIterator it(end ? ld.preEnd() : ld.begin(), end);
+ if (it == ld.end() || it == ld.preBegin()) return; // should not happen, but who knows
+
+ EditableCaretBoxIterator fbit = it;
+ Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin());
+ CaretBox *b = *fbit;
+
+ RenderObject *cb = (*it)->containingBlock();
+ int absx, absy;
+
+ if (cb) cb->absolutePosition(absx, absy);
+ else absx = absy = 0;
+
+ int x = b->xPos()/* + (end ? b->width() : 0) reactivate for rtl*/;
+ d->m_caretViewContext->origX = absx + x;
+ placeCaretOnLine(b, x, absx, absy);
+}
+
+void KHTMLView::moveCaretBy(bool next, CaretMovement cmv, int count)
+{
+ if (!m_part) return;
+ Node &caretNodeRef = m_part->d->caretNode();
+ if (caretNodeRef.isNull()) return;
+
+ NodeImpl *caretNode = caretNodeRef.handle();
+// kdDebug(6200) << ": caretNode=" << caretNode << endl;
+ long &offset = m_part->d->caretOffset();
+
+ ElementImpl *baseElem = determineBaseElement(caretNode);
+ CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly;
+ LinearDocument ld(m_part, caretNode, offset, advpol, baseElem);
+
+ EditableCharacterIterator it(&ld);
+ while (!it.isEnd() && count > 0) {
+ count--;
+ if (cmv == CaretByCharacter) {
+ if (next) ++it;
+ else --it;
+ } else if (cmv == CaretByWord) {
+ if (next) moveItToNextWord(it);
+ else moveItToPrevWord(it);
+ }/*end if*/
+//kdDebug(6200) << "movecaret" << endl;
+ }/*wend*/
+ CaretBox *hintBox = 0; // make gcc uninit warning disappear
+ if (!it.isEnd()) {
+ NodeImpl *node = caretNodeRef.handle();
+ hintBox = it.caretBox();
+//kdDebug(6200) << "hintBox = " << hintBox << endl;
+//kdDebug(6200) << " outside " << hintBox->isOutside() << " outsideEnd " << hintBox->isOutsideEnd() << " r " << it.renderer() << " ofs " << it.offset() << " cb " << hintBox->containingBlock() << endl;
+ mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(),
+ hintBox->isOutsideEnd(), node, offset);
+//kdDebug(6200) << "mapRTD" << endl;
+ caretNodeRef = node;
+#if DEBUG_CARETMODE > 2
+ kdDebug(6200) << "set by valid node " << node << " " << (node?node->nodeName().string():TQString::null) << " offset: " << offset << endl;
+#endif
+ } else {
+ offset = next ? caretNode->maxOffset() : caretNode->minOffset();
+#if DEBUG_CARETMODE > 0
+ kdDebug(6200) << "set by INvalid node. offset: " << offset << endl;
+#endif
+ }/*end if*/
+ placeCaretOnChar(hintBox);
+}
+
+void KHTMLView::placeCaretOnChar(CaretBox *hintBox)
+{
+ caretOff();
+ recalcAndStoreCaretPos(hintBox);
+ ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y,
+ d->m_caretViewContext->width, d->m_caretViewContext->height);
+ d->m_caretViewContext->origX = d->m_caretViewContext->x;
+ d->scrollBarMoved = false;
+#if DEBUG_CARETMODE > 3
+ //if (caretNode->isTextNode()) kdDebug(6200) << "text[0] = " << (int)*((TextImpl *)caretNode)->data().unicode() << " text :\"" << ((TextImpl *)caretNode)->data().string() << "\"" << endl;
+#endif
+ ensureNodeHasFocus(m_part->d->caretNode().handle());
+ caretOn();
+}
+
+void KHTMLView::moveCaretByPage(bool next)
+{
+ Node &caretNodeRef = m_part->d->caretNode();
+ if (caretNodeRef.isNull()) return;
+
+ NodeImpl *caretNode = caretNodeRef.handle();
+// kdDebug(6200) << ": caretNode=" << caretNode << endl;
+ long offset = m_part->d->caretOffset();
+
+ int offs = (clipper()->height() < 30) ? clipper()->height() : 30;
+ // Minimum distance the caret must be moved
+ int mindist = clipper()->height() - offs;
+
+ CaretViewContext *cv = d->caretViewContext();
+// int y = cv->y; // we always measure the top border
+
+ ElementImpl *baseElem = determineBaseElement(caretNode);
+ LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem);
+
+ ErgonomicEditableLineIterator it(ld.current(), cv->origX);
+
+ moveIteratorByPage(ld, it, mindist, next);
+
+ int x, absx, absy;
+ CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy);
+
+ placeCaretOnLine(caretBox, x, absx, absy);
+}
+
+void KHTMLView::moveCaretPrevWord()
+{
+ moveCaretBy(false, CaretByWord, 1);
+}
+
+void KHTMLView::moveCaretNextWord()
+{
+ moveCaretBy(true, CaretByWord, 1);
+}
+
+void KHTMLView::moveCaretPrevLine(int n)
+{
+ moveCaretByLine(false, n);
+}
+
+void KHTMLView::moveCaretNextLine(int n)
+{
+ moveCaretByLine(true, n);
+}
+
+void KHTMLView::moveCaretPrevPage()
+{
+ moveCaretByPage(false);
+}
+
+void KHTMLView::moveCaretNextPage()
+{
+ moveCaretByPage(true);
+}
+
+void KHTMLView::moveCaretToLineBegin()
+{
+ moveCaretToLineBoundary(false);
+}
+
+void KHTMLView::moveCaretToLineEnd()
+{
+ moveCaretToLineBoundary(true);
+}
+
+#endif // KHTML_NO_CARET
+
+#ifndef NO_SMOOTH_SCROLL_HACK
+#define timer timer2
+
+// All scrolls must be completed within 240ms of last keypress
+static const int SCROLL_TIME = 240;
+// Each step is 20 ms == 50 frames/second
+static const int SCROLL_TICK = 20;
+
+void KHTMLView::scrollBy(int dx, int dy)
+{
+ TDEConfigGroup cfg( TDEGlobal::config(), "KDE" );
+ if( !cfg.readBoolEntry( "SmoothScrolling", false )) {
+ TQScrollView::scrollBy( dx, dy );
+ return;
+ }
+ // scrolling destination
+ int full_dx = d->dx + dx;
+ int full_dy = d->dy + dy;
+
+ // scrolling speed
+ int ddx = 0;
+ int ddy = 0;
+
+ int steps = SCROLL_TIME/SCROLL_TICK;
+
+ ddx = (full_dx*16)/steps;
+ ddy = (full_dy*16)/steps;
+
+ // don't go under 1px/step
+ if (ddx > 0 && ddx < 16) ddx = 16;
+ if (ddy > 0 && ddy < 16) ddy = 16;
+ if (ddx < 0 && ddx > -16) ddx = -16;
+ if (ddy < 0 && ddy > -16) ddy = -16;
+
+ d->dx = full_dx;
+ d->dy = full_dy;
+ d->ddx = ddx;
+ d->ddy = ddy;
+
+ if (!d->scrolling) {
+ scrollTick();
+ startScrolling();
+ }
+}
+
+void KHTMLView::scrollTick() {
+ if (d->dx == 0 && d->dy == 0) {
+ stopScrolling();
+ return;
+ }
+
+ int tddx = d->ddx + d->rdx;
+ int tddy = d->ddy + d->rdy;
+
+ int ddx = tddx / 16;
+ int ddy = tddy / 16;
+ d->rdx = tddx % 16;
+ d->rdy = tddy % 16;
+
+ if (d->dx > 0 && ddx > d->dx) ddx = d->dx;
+ else
+ if (d->dx < 0 && ddx < d->dx) ddx = d->dx;
+
+ if (d->dy > 0 && ddy > d->dy) ddy = d->dy;
+ else
+ if (d->dy < 0 && ddy < d->dy) ddy = d->dy;
+
+ d->dx -= ddx;
+ d->dy -= ddy;
+
+// TQScrollView::setContentsPos( contentsX() + ddx, contentsY() + ddy);
+ kapp->syncX();
+ TQScrollView::scrollBy(ddx, ddy);
+// Unaccelerated X can get seriously overloaded by scrolling and for some reason
+// will send KeyPress events only infrequently. This should help to reduce
+// the load.
+ kapp->syncX();
+}
+
+void KHTMLView::startScrolling()
+{
+ d->scrolling = true;
+ d->timer.start(SCROLL_TICK, false);
+}
+
+void KHTMLView::stopScrolling()
+{
+ d->timer.stop();
+ d->dx = d->dy = 0;
+ d->scrolling = false;
+}
+
+// Overloaded from TQScrollView and TQScrollBar
+void KHTMLView::scrollViewWheelEvent( TQWheelEvent *e )
+{
+ int pageStep = verticalScrollBar()->pageStep();
+ int lineStep = verticalScrollBar()->lineStep();
+ int step = TQMIN( TQApplication::wheelScrollLines()*lineStep, pageStep );
+ if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) )
+ step = pageStep;
+
+ if(e->orientation() == Qt::Horizontal)
+ scrollBy(-((e->delta()*step)/120), 0);
+ else if(e->orientation() == Qt::Vertical)
+ scrollBy(0,-((e->delta()*step)/120));
+
+ e->accept();
+}
+
+#undef timer
+
+#endif // NO_SMOOTH_SCROLL_HACK
+
+#undef DEBUG_CARETMODE
diff --git a/tdehtml/tdehtmlview.h b/tdehtml/tdehtmlview.h
new file mode 100644
index 000000000..5448f32f8
--- /dev/null
+++ b/tdehtml/tdehtmlview.h
@@ -0,0 +1,624 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ (C) 1998 Waldo Bastian (bastian@kde.org)
+ (C) 1998, 1999 Torben Weis (weis@kde.org)
+ (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 KHTMLVIEW_H
+#define KHTMLVIEW_H
+
+// qt includes and classes
+#include <tqscrollview.h>
+
+#include <tdelibs_export.h>
+
+class TQPainter;
+class TQRect;
+template< typename T > class TQValueVector;
+
+namespace DOM {
+ class HTMLDocumentImpl;
+ class DocumentImpl;
+ class ElementImpl;
+ class HTMLElementImpl;
+ class HTMLTitleElementImpl;
+ class HTMLGenericFormElementImpl;
+ class HTMLFormElementImpl;
+ class HTMLAnchorElementImpl;
+ class HTMLInputElementImpl;
+ class Range;
+ class NodeImpl;
+ class CSSProperty;
+}
+
+namespace KJS {
+ class WindowFunc;
+ class ExternalFunc;
+}
+
+namespace tdehtml {
+ class RenderObject;
+ class RenderCanvas;
+ class RenderStyle;
+ class RenderLineEdit;
+ class RenderPartObject;
+ class RenderWidget;
+ class CSSStyleSelector;
+ class LineEditWidget;
+ class CaretBox;
+ void applyRule(DOM::CSSProperty *prop);
+}
+
+class KHTMLPart;
+class KHTMLViewPrivate;
+
+/**
+ * Renders and displays HTML in a TQScrollView.
+ *
+ * Suitable for use as an application's main view.
+ **/
+class KHTML_EXPORT KHTMLView : public TQScrollView
+{
+ Q_OBJECT
+
+ friend class DOM::HTMLDocumentImpl;
+ friend class DOM::HTMLTitleElementImpl;
+ friend class DOM::HTMLGenericFormElementImpl;
+ friend class DOM::HTMLFormElementImpl;
+ friend class DOM::HTMLAnchorElementImpl;
+ friend class DOM::HTMLInputElementImpl;
+ friend class DOM::DocumentImpl;
+ friend class KHTMLPart;
+ friend class tdehtml::RenderCanvas;
+ friend class tdehtml::RenderObject;
+ friend class tdehtml::RenderLineEdit;
+ friend class tdehtml::RenderPartObject;
+ friend class tdehtml::RenderWidget;
+ friend class tdehtml::CSSStyleSelector;
+ friend class tdehtml::LineEditWidget;
+ friend class KJS::WindowFunc;
+ friend class KJS::ExternalFunc;
+ friend void tdehtml::applyRule(DOM::CSSProperty *prop);
+
+
+public:
+ /**
+ * Constructs a KHTMLView.
+ */
+ KHTMLView( KHTMLPart *part, TQWidget *parent, const char *name=0 );
+ virtual ~KHTMLView();
+
+ /**
+ * Returns a pointer to the KHTMLPart that is
+ * rendering the page.
+ **/
+ KHTMLPart *part() const { return m_part; }
+
+ int frameWidth() const { return _width; }
+
+ /**
+ * Sets a margin in x direction.
+ */
+ void setMarginWidth(int x);
+
+ /**
+ * Returns the margin width.
+ *
+ * A return value of -1 means the default value will be used.
+ */
+ int marginWidth() const { return _marginWidth; }
+
+ /*
+ * Sets a margin in y direction.
+ */
+ void setMarginHeight(int y);
+
+ /**
+ * Returns the margin height.
+ *
+ * A return value of -1 means the default value will be used.
+ */
+ int marginHeight() { return _marginHeight; }
+
+ /**
+ * Sets verticals scrollbar mode. Reimplemented for internal reasons.
+ */
+ virtual void setVScrollBarMode ( ScrollBarMode mode );
+
+ /**
+ * Sets horizontal scrollbar mode. Reimplemented for internal reasons.
+ */
+ virtual void setHScrollBarMode ( ScrollBarMode mode );
+
+ /**
+ * Prints the HTML document.
+ */
+ void print();
+
+ /**
+ * Prints the HTML document.
+ * @param quick if true, fully automated printing, without print dialog
+ */
+ void print( bool quick ); // KDE 4.0: merge with above
+
+ /**
+ * ensure the display is up to date
+ */
+ void layout(); // KDE 4.0: make private
+ /**
+ * Display all accesskeys in small tooltips
+ */
+ void displayAccessKeys();
+
+
+
+signals:
+ /**
+ * This signal is used for internal layouting. Don't use it to check if rendering finished.
+ * Use @ref KHTMLPart completed() signal instead.
+ */
+ void finishedLayout();
+ void cleared();
+ void zoomView( int );
+ void hideAccessKeys();
+ void repaintAccessKeys();
+ void findAheadActive( bool );
+//#define NO_SMOOTH_SCROLL_HACK
+#ifndef NO_SMOOTH_SCROLL_HACK
+public slots:
+ void scrollBy(int dx, int dy);
+#endif
+
+protected:
+ void clear();
+
+ virtual void resizeEvent ( TQResizeEvent * event );
+ virtual void showEvent ( TQShowEvent * );
+ virtual void hideEvent ( TQHideEvent *);
+ virtual bool focusNextPrevChild( bool next );
+ virtual void drawContents ( TQPainter * p, int clipx, int clipy, int clipw, int cliph );
+ virtual void drawContents( TQPainter* );
+ virtual void viewportMousePressEvent( TQMouseEvent * );
+ virtual void focusInEvent( TQFocusEvent * );
+ virtual void focusOutEvent( TQFocusEvent * );
+ virtual void viewportMouseDoubleClickEvent( TQMouseEvent * );
+ virtual void viewportMouseMoveEvent(TQMouseEvent *);
+ virtual void viewportMouseReleaseEvent(TQMouseEvent *);
+ virtual void viewportResizeEvent(TQResizeEvent*);
+#ifndef QT_NO_WHEELEVENT
+ virtual void viewportWheelEvent(TQWheelEvent*);
+#endif
+ virtual void dragEnterEvent( TQDragEnterEvent* );
+ virtual void dropEvent( TQDropEvent* );
+ virtual void closeEvent ( TQCloseEvent * );
+ virtual bool eventFilter(TQObject *, TQEvent *);
+
+ void keyPressEvent( TQKeyEvent *_ke );
+ void keyReleaseEvent ( TQKeyEvent *_ke );
+ void contentsContextMenuEvent ( TQContextMenuEvent *_ce );
+ void doAutoScroll();
+ void timerEvent ( TQTimerEvent * );
+
+#ifndef NO_SMOOTH_SCROLL_HACK
+ void startScrolling();
+ void stopScrolling();
+#ifndef QT_NO_WHEELEVENT
+ void scrollViewWheelEvent( TQWheelEvent* e );
+#endif
+#endif
+
+protected slots:
+ void slotPaletteChanged();
+ void slotScrollBarMoved();
+#ifndef NO_SMOOTH_SCROLL_HACK
+ void scrollTick();
+#else
+ void scrollTick() {}; // moc cannot handle #if
+#endif
+
+private slots:
+ void tripleClickTimeout();
+ void findTimeout();
+ void accessKeysTimeout();
+
+ /**
+ * @internal
+ * @since 3.4
+ * used for autoscrolling with MMB
+ */
+ void slotMouseScrollTimer();
+
+private:
+
+ void scheduleRelayout(tdehtml::RenderObject* clippedObj=0);
+ void unscheduleRelayout();
+
+ void scheduleRepaint(int x, int y, int w, int h, bool asap=false);
+ void unscheduleRepaint();
+
+ bool needsFullRepaint() const;
+
+ void closeChildDialogs();
+ bool dialogsAllowed();
+
+ /**
+ * Paints the HTML document to a TQPainter.
+ * The document will be scaled to match the width of
+ * rc and clipped to fit in the height.
+ * yOff determines the vertical offset in the document to start with.
+ * more, if nonzero will be set to true if the documents extends
+ * beyond the rc or false if everything below yOff was painted.
+ **/
+ void paint(TQPainter *p, const TQRect &rc, int yOff = 0, bool *more = 0);
+
+#if 0
+ /**
+ * Paints the HTML document to a TQPainter.
+ * The document will be scaled to match the width.
+ **/
+ void paint(TQPainter *p, int width);
+#endif
+
+ /**
+ * Get/set the CSS Media Type.
+ *
+ * Media type is set to "screen" for on-screen rendering and "print"
+ * during printing. Other media types lack the proper support in the
+ * renderer and are not activated. The DOM tree and the parser itself,
+ * however, properly handle other media types. To make them actually work
+ * you only need to enable the media type in the view and if necessary
+ * add the media type dependent changes to the renderer.
+ */
+ void setMediaType( const TQString &medium );
+ TQString mediaType() const;
+
+ bool pagedMode() const;
+
+ bool scrollTo(const TQRect &);
+
+ bool focusNextPrevNode(bool next);
+ bool handleAccessKey(const TQKeyEvent* ev);
+ bool focusNodeWithAccessKey(TQChar c, KHTMLView* caller = NULL);
+ TQMap< DOM::ElementImpl*, TQChar > buildFallbackAccessKeys() const;
+ void displayAccessKeys( KHTMLView* caller, KHTMLView* origview, TQValueVector< TQChar >& taken, bool use_fallbacks );
+
+ void useSlowRepaints();
+
+ void setIgnoreWheelEvents(bool e);
+
+ void init();
+
+ DOM::NodeImpl *nodeUnderMouse() const;
+ DOM::NodeImpl *nonSharedNodeUnderMouse() const;
+
+ void restoreScrollBar();
+
+ TQStringList formCompletionItems(const TQString &name) const;
+ void clearCompletionHistory(const TQString& name);
+ void addFormCompletionItem(const TQString &name, const TQString &value);
+ void removeFormCompletionItem(const TQString &name, const TQString &value);
+
+ void addNonPasswordStorableSite( const TQString& host );
+ bool nonPasswordStorableSite( const TQString& host ) const;
+
+ bool dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode,
+ DOM::NodeImpl *targetNodeNonShared, bool cancelable,
+ int detail,TQMouseEvent *_mouse, bool setUnder,
+ int mouseEventType);
+ bool dispatchKeyEvent( TQKeyEvent *_ke );
+ bool dispatchKeyEventHelper( TQKeyEvent *_ke, bool generate_keypress );
+
+ void complete( bool pendingAction );
+
+#ifndef KHTML_NO_TYPE_AHEAD_FIND
+ void findAhead(bool increase);
+ void updateFindAheadTimeout();
+ void startFindAhead( bool linksOnly );
+#endif // KHTML_NO_TYPE_AHEAD_FIND
+
+#ifndef KHTML_NO_CARET
+ // -- caret-related member functions (for caretMode as well as designMode)
+
+ /** initializes the caret if it hasn't been initialized yet.
+ *
+ * This method determines a suitable starting position, initializes
+ * the internal structures, and calculates the caret's coordinates ready
+ * for display.
+ *
+ * To "deinitialize" the caret, call caretOff
+ * @param keepSelection @p true to keep any active selection. It may have
+ * been extended if the caret position is changed.
+ */
+ void initCaret(bool keepSelection = false);
+ /** returns whether the text under the caret will be overridden.
+ */
+ bool caretOverrides() const;
+ /** ensures that the given element is properly focused.
+ *
+ * If not in caret mode or design mode, keyboard events are only regarded for
+ * focused nodes. Therefore, the function ensured that the focus will be
+ * properly set on unfocused nodes (or on a suitable ancestor).
+ * @param node node to focus
+ */
+ void ensureNodeHasFocus(DOM::NodeImpl *node);
+ /** inquires the current caret position and stores it in the caret view
+ * context. Also resets the blink frequency timer. It will not display
+ * the caret on the canvas.
+ * @param hintBox caret box whose coordinates will be used if the
+ * caret position could not be determined otherwise.
+ */
+ void recalcAndStoreCaretPos(tdehtml::CaretBox *hintBox = 0);
+ /** displays the caret and reinitializes the blink frequency timer.
+ *
+ * The caret will only be displayed on screen if the view has focus, or
+ * the caret display policy allows it. The same holds true for the blink
+ * frequency timer.
+ */
+ void caretOn();
+ /** hides the caret and kills the blink frequency timer.
+ *
+ * These operations are executed unconditionally, regardless of the
+ * focus, and the caret display policy.
+ */
+ void caretOff();
+ /** makes the caret visible, but does not influence the frequency timer.
+ * That means it probably won't get visible immediately.
+ *
+ * These operations are executed unconditionally, regardless of the
+ * focus, and the caret display policy.
+ * @param forceRepaint @p true to force an immediate repaint, otherwise
+ * do a scheduled repaint
+ */
+ void showCaret(bool forceRepaint = false);
+ /** makes the caret invisible, but does not influence the frequency timer.
+ * The caret is immediately hidden.
+ *
+ * These operations are executed unconditionally, regardless of the
+ * focus, and the caret display policy.
+ */
+ void hideCaret();
+ /** shifts the viewport to ensure that the caret is visible.
+ *
+ * Note: this will also work if the caret is hidden.
+ */
+ void ensureCaretVisible();
+
+ /** folds the selection to the current caret position.
+ *
+ * Whatever selection has existed before will be removed by the invocation
+ * of this method. Updates are only done if an actual selection has
+ * been folded. After the call of this method, no selection will exist
+ * any more.
+ *
+ * No validity checking is done on the parameters. Note that the parameters
+ * refer to the old selection, the current caret may be way off.
+ * @param startNode starting node of selection
+ * @param startOffset offset within the start node.
+ * @param endNode ending node of selection
+ * @param endOffset offset within the end node.
+ * @return @p true if there had been a selection, and it was folded.
+ */
+ bool foldSelectionToCaret(DOM::NodeImpl *startNode, long startOffset,
+ DOM::NodeImpl *endNode, long endOffset);
+
+ /** places the caret on the current position.
+ *
+ * The caret is switched off, the position recalculated with respect to
+ * the new position. The caret will only be redisplayed if it is on an
+ * editable node, in design mode, or in caret mode.
+ * @param hintBox caret box whose coordinates will be used if the
+ * caret position could not be determined otherwise.
+ * @return @p true if the caret has been displayed.
+ */
+ bool placeCaret(tdehtml::CaretBox *hintBox = 0);
+
+ /** extends the selection up to the current caret position.
+ *
+ * When a selection exists, the function adds/removes pieces from the
+ * beginning/end of the selection up to the current caret position.
+ *
+ * The selection values are *not* normalized, i. e. the resulting end
+ * position may actually precede the starting position.
+ *
+ * No validity checking is done on the parameters. Note that the parameters
+ * refer to the old selection, the current caret may be way off.
+ * @param startNode starting node of selection
+ * @param startOffset offset within the start node.
+ * @param endNode ending node of selection
+ * @param endOffset offset within the end node.
+ * @return @p true when the current selection has been changed
+ */
+ bool extendSelection(DOM::NodeImpl *startNode, long startOffset,
+ DOM::NodeImpl *endNode, long endOffset);
+
+ /** updates the selection from the last to the current caret position.
+ *
+ * No validity checking is done on the parameters. Note that the parameters
+ * refer to the old selection, the current caret may be way off.
+ * @param startNode starting node of selection
+ * @param startOffset offset within the start node.
+ * @param endNode ending node of selection
+ * @param endOffset offset within the end node.
+ */
+ void updateSelection(DOM::NodeImpl *startNode, long startOffset,
+ DOM::NodeImpl *endNode, long endOffset);
+
+ /**
+ * Returns the current caret policy when the view is not focused.
+ * @return a KHTMLPart::CaretDisplay value
+ */
+ int caretDisplayPolicyNonFocused() const;
+
+ /**
+ * Sets the caret display policy when the view is not focused.
+ * @param policy new display policy as
+ * defined by KHTMLPart::CaretDisplayPolicy
+ * @since 3.2
+ */
+ void setCaretDisplayPolicyNonFocused(int policy);
+
+ // -- caret event handler
+
+ /**
+ * Evaluates key presses on editable nodes.
+ */
+ void caretKeyPressEvent(TQKeyEvent *);
+
+ // -- caret navigation member functions
+
+ /** moves the caret to the given position and displays it.
+ *
+ * If the node resembles an invalid position, the function sets the caret to a
+ * nearby node that is valid.
+ *
+ * @param node node to be set to
+ * @param offset zero-based offset within this node
+ * @param clearSelection @p true if any selection should be cleared
+ * as well.
+ * @return @p true if a previously existing selection has been changed.
+ */
+ bool moveCaretTo(DOM::NodeImpl *node, long offset, bool clearSelection);
+
+ /**
+ * Movement enumeration
+ * @li CaretByCharacter move caret character-wise
+ * @li CaretByWord move caret word-wise
+ */
+ enum CaretMovement { CaretByCharacter, CaretByWord };
+
+ /** moves the caret.
+ *
+ * @param next @p true, move towards the following content, @p false,
+ * move towards the previous
+ * @param cmv CaretMovement operation
+ * @param n count the CaretMovement has to be carried out.
+ * For latin documents, a positive number means moving the caret
+ * these many characters to the right/downwards, a negative number
+ * to the left/upwards. For RTL documents, the opposite applies.
+ */
+ void moveCaretBy(bool next, CaretMovement cmv, int n);
+
+ /** moves the caret by line.
+ */
+ void moveCaretByLine(bool next, int n);
+
+ /** moves the caret to the given line boundary.
+ * @param end @p true if the caret is to be moved to the end of the line,
+ * otherwise to the beginning.
+ */
+ void moveCaretToLineBoundary(bool end);
+
+ /** moves the caret to the given document boundary.
+ * @param end @p true if the caret is to be moved to the end of the
+ * document, otherwise to the beginning.
+ */
+ void moveCaretToDocumentBoundary(bool end);
+
+ /** does the actual caret placement so that it becomes visible at
+ * the new position.
+ *
+ * This method is only suitable if the new caret position has already been
+ * determined.
+ * @param hintBox caret box whose coordinates will be used if the
+ * caret position could not be determined otherwise.
+ */
+ void placeCaretOnChar(tdehtml::CaretBox *hintBox);
+
+ /** does the actual caret placement so that it becomes visible at
+ * the new position.
+ *
+ * Additionally, it calculates the new caret position from the given
+ * box and coordinates.
+ *
+ * @param caretBox caret box serving as a measurement point for offset.
+ * @param x x-coordinate relative to containing block. The offset will
+ * be approximated as closely as possible to this coordinate,
+ * but never less than caretBox->xPos() and greater than
+ * caretBox->xPos() + caretBox->width()
+ * @param absx absolute x-coordinate of containing block, needed for
+ * calculation of final caret position
+ * @param absy absolute y-coordinate of containing block, needed for
+ * calculation of final caret position
+ */
+ void placeCaretOnLine(tdehtml::CaretBox *caretBox, int x, int absx, int absy);
+
+ /** moves the caret by a page length.
+ * @param next @p true, move down, @p false, move up.
+ */
+ void moveCaretByPage(bool next);
+
+ /** moves the caret to the beginning of the previous word.
+ */
+ void moveCaretPrevWord();
+
+ /** moves the caret to the beginning of the next word.
+ */
+ void moveCaretNextWord();
+
+ /** moves the caret to the previous line.
+ *
+ * @param n number of lines to move caret
+ */
+ void moveCaretPrevLine(int n = 1);
+
+ /** moves the caret to the following line.
+ *
+ * @param n number of lines to move caret
+ */
+ void moveCaretNextLine(int n = 1);
+
+ /** moves the caret to the previous page
+ */
+ void moveCaretPrevPage();
+
+ /** moves the caret to the next page
+ */
+ void moveCaretNextPage();
+
+ /** moves the caret to the beginning of the current line.
+ */
+ void moveCaretToLineBegin();
+
+ /** moves the caret to the end of the current line.
+ */
+ void moveCaretToLineEnd();
+
+#endif // KHTML_NO_CARET
+
+ // ------------------------------------- member variables ------------------------------------
+ private:
+
+ void setWidgetVisible(::tdehtml::RenderWidget*, bool visible);
+
+ int _width;
+ int _height;
+
+ int _marginWidth;
+ int _marginHeight;
+
+ KHTMLPart *m_part;
+ KHTMLViewPrivate *d;
+
+ TQString m_medium; // media type
+};
+
+#endif
+
diff --git a/tdehtml/tdemultipart/CMakeLists.txt b/tdehtml/tdemultipart/CMakeLists.txt
new file mode 100644
index 000000000..f0d03953e
--- /dev/null
+++ b/tdehtml/tdemultipart/CMakeLists.txt
@@ -0,0 +1,48 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/tdeutils
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+
+##### other data ################################
+
+install( FILES tdemultipart.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
+
+
+##### libtdemultipart #############################
+
+set( target libtdemultipart )
+
+set( ${target}_SRCS
+ tdemultipart.cpp
+)
+
+tde_add_kpart( ${target} AUTOMOC
+ SOURCES ${${target}_SRCS}
+ LINK httpfilter-static tdeparts-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
diff --git a/tdehtml/tdemultipart/Makefile.am b/tdehtml/tdemultipart/Makefile.am
new file mode 100644
index 000000000..f02b5931e
--- /dev/null
+++ b/tdehtml/tdemultipart/Makefile.am
@@ -0,0 +1,17 @@
+INCLUDES = -I$(top_srcdir)/tdehtml -I$(top_srcdir)/kio/httpfilter -I$(top_srcdir)/tdeutils $(all_includes)
+
+# These are not really libraries, but modules dynamically opened.
+# So they should be installed in kde_module_dir, which is usually $kde_prefix/lib/trinity
+kde_module_LTLIBRARIES = libtdemultipart.la
+
+libtdemultipart_la_SOURCES = tdemultipart.cpp
+libtdemultipart_la_LIBADD = $(LIB_KPARTS) $(top_builddir)/kio/httpfilter/libhttpfilter.la $(LIB_QT) $(LIB_TDECORE) $(LIB_TDEUI) $(LIB_KFILE) $(LIBZ)
+libtdemultipart_la_DEPENDENCIES = $(LIB_KPARTS)
+libtdemultipart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN)
+
+# Automatically generate moc files
+METASOURCES = AUTO
+
+# Install the .desktop file into the kde_services directory
+kde_services_DATA = tdemultipart.desktop
+
diff --git a/tdehtml/tdemultipart/README b/tdehtml/tdemultipart/README
new file mode 100644
index 000000000..c8a342d68
--- /dev/null
+++ b/tdehtml/tdemultipart/README
@@ -0,0 +1,16 @@
+KMultiPart implements "server push" for KHTML/Konqueror:
+it handles the multipart/mixed and multipart/x-mixed-replace
+mimetype, embedding the appropriate component (part).
+
+Documentation at http://www.netscape.com/assist/net_sites/pushpull.html
+
+Typical real-world uses: webchats, webcams...
+
+Testcases:
+ http://stein.cshl.org/WWW/software/CGI/examples/
+
+TODO:
+* Use the new streaming API of KParts to pipe data into the part,
+the current code does that for KHTML only.
+* Change KHTML so that it embeds KMultiPart for images which send multipart/x-mixed-replace
+data.
diff --git a/tdehtml/tdemultipart/tdemultipart.cpp b/tdehtml/tdemultipart/tdemultipart.cpp
new file mode 100644
index 000000000..d5195186d
--- /dev/null
+++ b/tdehtml/tdemultipart/tdemultipart.cpp
@@ -0,0 +1,613 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 David Faure <david@mandrakesoft.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.
+*/
+
+#include "tdemultipart.h"
+
+#include <tqvbox.h>
+#include <kinstance.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kio/job.h>
+#include <tqfile.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <tdeparts/componentfactory.h>
+#include <tdeparts/genericfactory.h>
+#include <tdehtml_part.h>
+#include <unistd.h>
+#include <kxmlguifactory.h>
+#include <tqtimer.h>
+
+typedef KParts::GenericFactory<KMultiPart> KMultiPartFactory; // factory for the part
+K_EXPORT_COMPONENT_FACTORY( libtdemultipart /*library name*/, KMultiPartFactory )
+
+//#define DEBUG_PARSING
+
+class KLineParser
+{
+public:
+ KLineParser() {
+ m_lineComplete = false;
+ }
+ void addChar( char c, bool storeNewline ) {
+ if ( !storeNewline && c == '\r' )
+ return;
+ Q_ASSERT( !m_lineComplete );
+ if ( storeNewline || c != '\n' ) {
+ int sz = m_currentLine.size();
+ m_currentLine.resize( sz+1, TQGArray::SpeedOptim );
+ m_currentLine[sz] = c;
+ }
+ if ( c == '\n' )
+ m_lineComplete = true;
+ }
+ bool isLineComplete() const {
+ return m_lineComplete;
+ }
+ TQByteArray currentLine() const {
+ return m_currentLine;
+ }
+ void clearLine() {
+ Q_ASSERT( m_lineComplete );
+ reset();
+ }
+ void reset() {
+ m_currentLine.resize( 0, TQGArray::SpeedOptim );
+ m_lineComplete = false;
+ }
+private:
+ TQByteArray m_currentLine;
+ bool m_lineComplete; // true when ending with '\n'
+};
+
+/* testcase:
+ Content-type: multipart/mixed;boundary=ThisRandomString
+
+--ThisRandomString
+Content-type: text/plain
+
+Data for the first object.
+
+--ThisRandomString
+Content-type: text/plain
+
+Data for the second and last object.
+
+--ThisRandomString--
+*/
+
+
+KMultiPart::KMultiPart( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name, const TQStringList& )
+ : KParts::ReadOnlyPart( parent, name )
+{
+ m_filter = 0L;
+
+ setInstance( KMultiPartFactory::instance() );
+
+ TQVBox *box = new TQVBox( parentWidget, widgetName );
+ setWidget( box );
+
+ m_extension = new KParts::BrowserExtension( this );
+
+ // We probably need to use m_extension to get the urlArgs in openURL...
+
+ m_part = 0L;
+ m_isHTMLPart = false;
+ m_job = 0L;
+ m_lineParser = new KLineParser;
+ m_tempFile = 0L;
+
+ m_timer = new TQTimer( this );
+ connect( m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressInfo() ) );
+}
+
+KMultiPart::~KMultiPart()
+{
+ // important: delete the nested part before the part or qobject destructor runs.
+ // we now delete the nested part which deletes the part's widget which makes
+ // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the
+ // widget ;-)
+ // ### additional note: it _can_ be that the part has been deleted before:
+ // when we're in a html frameset and the view dies first, then it will also
+ // kill the htmlpart
+ if ( m_part )
+ delete static_cast<KParts::ReadOnlyPart *>( m_part );
+ delete m_job;
+ delete m_lineParser;
+ if ( m_tempFile ) {
+ m_tempFile->setAutoDelete( true );
+ delete m_tempFile;
+ }
+ delete m_filter;
+ m_filter = 0L;
+}
+
+
+void KMultiPart::startHeader()
+{
+ m_bParsingHeader = true; // we expect a header to come first
+ m_bGotAnyHeader = false;
+ m_gzip = false;
+ // just to be sure for now
+ delete m_filter;
+ m_filter = 0L;
+}
+
+
+bool KMultiPart::openURL( const KURL &url )
+{
+ m_url = url;
+ m_lineParser->reset();
+ startHeader();
+
+ KParts::URLArgs args = m_extension->urlArgs();
+ //m_mimeType = args.serviceType;
+
+ // Hmm, args.reload is set to true when reloading, but this doesn't seem to be enough...
+ // I get "HOLD: Reusing held slave for <url>", and the old data
+
+ m_job = TDEIO::get( url, args.reload, false );
+
+ emit started( 0 /*m_job*/ ); // don't pass the job, it would interfer with our own infoMessage
+
+ connect( m_job, TQT_SIGNAL( result( TDEIO::Job * ) ),
+ this, TQT_SLOT( slotJobFinished( TDEIO::Job * ) ) );
+ connect( m_job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ),
+ this, TQT_SLOT( slotData( TDEIO::Job *, const TQByteArray & ) ) );
+
+ m_numberOfFrames = 0;
+ m_numberOfFramesSkipped = 0;
+ m_totalNumberOfFrames = 0;
+ m_qtime.start();
+ m_timer->start( 1000 ); //1s
+
+ return true;
+}
+
+// Yes, libtdenetwork's has such a parser already (MultiPart),
+// but it works on the complete string, expecting the whole data to be available....
+// The version here is asynchronous.
+void KMultiPart::slotData( TDEIO::Job *job, const TQByteArray &data )
+{
+ if (m_boundary.isNull())
+ {
+ TQString tmp = job->queryMetaData("media-boundary");
+ kdDebug() << "Got Boundary from kio-http '" << tmp << "'" << endl;
+ if ( !tmp.isEmpty() ) {
+ if (tmp.startsWith("--"))
+ m_boundary = tmp.latin1();
+ else
+ m_boundary = TQCString("--")+tmp.latin1();
+ m_boundaryLength = m_boundary.length();
+ }
+ }
+ // Append to m_currentLine until eol
+ for ( uint i = 0; i < data.size() ; ++i )
+ {
+ // Store char. Skip if '\n' and currently parsing a header.
+ m_lineParser->addChar( data[i], !m_bParsingHeader );
+ if ( m_lineParser->isLineComplete() )
+ {
+ TQByteArray lineData = m_lineParser->currentLine();
+#ifdef DEBUG_PARSING
+ kdDebug() << "lineData.size()=" << lineData.size() << endl;
+#endif
+ TQCString line( lineData.data(), lineData.size()+1 ); // deep copy
+ // 0-terminate the data, but only for the line-based tests below
+ // We want to keep the raw data in case it ends up in sendData()
+ int sz = line.size();
+ if ( sz > 0 )
+ line[sz-1] = '\0';
+#ifdef DEBUG_PARSING
+ kdDebug() << "[" << m_bParsingHeader << "] line='" << line << "'" << endl;
+#endif
+ if ( m_bParsingHeader )
+ {
+ if ( !line.isEmpty() )
+ m_bGotAnyHeader = true;
+ if ( m_boundary.isNull() )
+ {
+ if ( !line.isEmpty() ) {
+#ifdef DEBUG_PARSING
+ kdDebug() << "Boundary is " << line << endl;
+#endif
+ m_boundary = line;
+ m_boundaryLength = m_boundary.length();
+ }
+ }
+ else if ( !tqstrnicmp( line.data(), "Content-Encoding:", 17 ) )
+ {
+ TQString encoding = TQString::fromLatin1(line.data()+17).stripWhiteSpace().lower();
+ if (encoding == "gzip" || encoding == "x-gzip") {
+ m_gzip = true;
+ } else {
+ kdDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding << endl;
+ }
+ }
+ // parse Content-Type
+ else if ( !tqstrnicmp( line.data(), "Content-Type:", 13 ) )
+ {
+ Q_ASSERT( m_nextMimeType.isNull() );
+ m_nextMimeType = TQString::fromLatin1( line.data() + 14 ).stripWhiteSpace();
+ int semicolon = m_nextMimeType.find( ';' );
+ if ( semicolon != -1 )
+ m_nextMimeType = m_nextMimeType.left( semicolon );
+ kdDebug() << "m_nextMimeType=" << m_nextMimeType << endl;
+ }
+ // Empty line, end of headers (if we had any header line before)
+ else if ( line.isEmpty() && m_bGotAnyHeader )
+ {
+ m_bParsingHeader = false;
+#ifdef DEBUG_PARSING
+ kdDebug() << "end of headers" << endl;
+#endif
+ startOfData();
+ }
+ // First header (when we know it from kio_http)
+ else if ( line == m_boundary )
+ ; // nothing to do
+ else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie:
+ kdDebug() << "Ignoring header " << line << endl;
+ } else {
+ if ( !tqstrncmp( line, m_boundary, m_boundaryLength ) )
+ {
+#ifdef DEBUG_PARSING
+ kdDebug() << "boundary found!" << endl;
+ kdDebug() << "after it is " << line.data() + m_boundaryLength << endl;
+#endif
+ // Was it the very last boundary ?
+ if ( !tqstrncmp( line.data() + m_boundaryLength, "--", 2 ) )
+ {
+#ifdef DEBUG_PARSING
+ kdDebug() << "Completed!" << endl;
+#endif
+ endOfData();
+ emit completed();
+ } else
+ {
+ char nextChar = *(line.data() + m_boundaryLength);
+#ifdef DEBUG_PARSING
+ kdDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'" << endl;
+#endif
+ if ( nextChar == '\n' || nextChar == '\r' ) {
+ endOfData();
+ startHeader();
+ }
+ else {
+ // otherwise, false hit, it has trailing stuff
+ sendData( lineData );
+ }
+ }
+ } else {
+ // send to part
+ sendData( lineData );
+ }
+ }
+ m_lineParser->clearLine();
+ }
+ }
+}
+
+void KMultiPart::setPart( const TQString& mimeType )
+{
+ KXMLGUIFactory *guiFactory = factory();
+ if ( guiFactory ) // seems to be 0 when restoring from SM
+ guiFactory->removeClient( this );
+ kdDebug() << "KMultiPart::setPart " << mimeType << endl;
+ delete m_part;
+ // Try to find an appropriate viewer component
+ m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart>
+ ( m_mimeType, TQString::null, widget(), 0L, this, 0L );
+ if ( !m_part ) {
+ // TODO launch external app
+ KMessageBox::error( widget(), i18n("No handler found for %1!").arg(m_mimeType) );
+ return;
+ }
+ // By making the part a child XMLGUIClient of ours, we get its GUI merged in.
+ insertChildClient( m_part );
+ m_part->widget()->show();
+
+ connect( m_part, TQT_SIGNAL( completed() ),
+ this, TQT_SLOT( slotPartCompleted() ) );
+
+ m_isHTMLPart = ( mimeType == "text/html" );
+ KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
+
+ if ( childExtension )
+ {
+
+ // Forward signals from the part's browser extension
+ // this is very related (but not exactly like) KHTMLPart::processObjectRequest
+
+ connect( childExtension, TQT_SIGNAL( openURLNotify() ),
+ m_extension, TQT_SIGNAL( openURLNotify() ) );
+
+ connect( childExtension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
+ m_extension, TQT_SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) );
+
+ connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
+ m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
+ connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
+ m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
+
+ // Keep in sync with tdehtml_part.cpp
+ connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ),
+ m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) );
+ connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ),
+ m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) );
+ connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
+ m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
+ connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ),
+ m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
+ connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ),
+ m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
+ connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
+ m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
+
+
+ if ( m_isHTMLPart )
+ connect( childExtension, TQT_SIGNAL( infoMessage( const TQString & ) ),
+ m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) );
+ // For non-HTML we prefer to show our infoMessage ourselves.
+
+ childExtension->setBrowserInterface( m_extension->browserInterface() );
+
+ connect( childExtension, TQT_SIGNAL( enableAction( const char *, bool ) ),
+ m_extension, TQT_SIGNAL( enableAction( const char *, bool ) ) );
+ connect( childExtension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ),
+ m_extension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ) );
+ connect( childExtension, TQT_SIGNAL( setIconURL( const KURL& ) ),
+ m_extension, TQT_SIGNAL( setIconURL( const KURL& ) ) );
+ connect( childExtension, TQT_SIGNAL( loadingProgress( int ) ),
+ m_extension, TQT_SIGNAL( loadingProgress( int ) ) );
+ if ( m_isHTMLPart ) // for non-HTML we have our own
+ connect( childExtension, TQT_SIGNAL( speedProgress( int ) ),
+ m_extension, TQT_SIGNAL( speedProgress( int ) ) );
+ connect( childExtension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ),
+ m_extension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ) );
+ connect( childExtension, TQT_SIGNAL( selectionInfo( const TQString& ) ),
+ m_extension, TQT_SIGNAL( selectionInfo( const TQString& ) ) );
+ connect( childExtension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ),
+ m_extension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ) );
+ connect( childExtension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ),
+ m_extension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ) );
+ connect( childExtension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ),
+ m_extension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ) );
+ connect( childExtension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ),
+ m_extension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ) );
+ }
+
+ m_partIsLoading = false;
+ // Load the part's plugins too.
+ // ###### This is a hack. The bug is that KHTMLPart doesn't load its plugins
+ // if className != "Browser/View".
+ loadPlugins( this, m_part, m_part->instance() );
+ // Get the part's GUI to appear
+ if ( guiFactory )
+ guiFactory->addClient( this );
+}
+
+void KMultiPart::startOfData()
+{
+ kdDebug() << "KMultiPart::startOfData" << endl;
+ Q_ASSERT( !m_nextMimeType.isNull() );
+ if( m_nextMimeType.isNull() )
+ return;
+
+ if ( m_gzip )
+ {
+ m_filter = new HTTPFilterGZip;
+ connect( m_filter, TQT_SIGNAL( output( const TQByteArray& ) ), this, TQT_SLOT( reallySendData( const TQByteArray& ) ) );
+ }
+
+ if ( m_mimeType != m_nextMimeType )
+ {
+ // Need to switch parts (or create the initial one)
+ m_mimeType = m_nextMimeType;
+ setPart( m_mimeType );
+ }
+ Q_ASSERT( m_part );
+ // Pass URLArgs (e.g. reload)
+ KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
+ if ( childExtension )
+ childExtension->setURLArgs( m_extension->urlArgs() );
+
+ m_nextMimeType = TQString::null;
+ if ( m_tempFile ) {
+ m_tempFile->setAutoDelete( true );
+ delete m_tempFile;
+ m_tempFile = 0;
+ }
+ if ( m_isHTMLPart )
+ {
+ KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
+ htmlPart->begin( url() );
+ }
+ else
+ {
+ // ###### TODO use a TQByteArray and a data: URL instead
+ m_tempFile = new KTempFile;
+ }
+}
+
+void KMultiPart::sendData( const TQByteArray& line )
+{
+ if ( m_filter )
+ {
+ m_filter->slotInput( line );
+ }
+ else
+ {
+ reallySendData( line );
+ }
+}
+
+void KMultiPart::reallySendData( const TQByteArray& line )
+{
+ if ( m_isHTMLPart )
+ {
+ KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
+ htmlPart->write( line.data(), line.size() );
+ }
+ else if ( m_tempFile )
+ {
+ m_tempFile->file()->writeBlock( line.data(), line.size() );
+ }
+}
+
+void KMultiPart::endOfData()
+{
+ Q_ASSERT( m_part );
+ if ( m_isHTMLPart )
+ {
+ KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
+ htmlPart->end();
+ } else if ( m_tempFile )
+ {
+ m_tempFile->close();
+ if ( m_partIsLoading )
+ {
+ // The part is still loading the last data! Let it proceed then
+ // Otherwise we'd keep cancelling it, and nothing would ever show up...
+ kdDebug() << "KMultiPart::endOfData part isn't ready, skipping frame" << endl;
+ ++m_numberOfFramesSkipped;
+ m_tempFile->setAutoDelete( true );
+ }
+ else
+ {
+ kdDebug() << "KMultiPart::endOfData opening " << m_tempFile->name() << endl;
+ KURL url;
+ url.setPath( m_tempFile->name() );
+ m_partIsLoading = true;
+ (void) m_part->openURL( url );
+ }
+ delete m_tempFile;
+ m_tempFile = 0L;
+ }
+}
+
+void KMultiPart::slotPartCompleted()
+{
+ if ( !m_isHTMLPart )
+ {
+ Q_ASSERT( m_part );
+ // Delete temp file used by the part
+ Q_ASSERT( m_part->url().isLocalFile() );
+ kdDebug() << "slotPartCompleted deleting " << m_part->url().path() << endl;
+ (void) unlink( TQFile::encodeName( m_part->url().path() ) );
+ m_partIsLoading = false;
+ ++m_numberOfFrames;
+ // Do not emit completed from here.
+ }
+}
+
+bool KMultiPart::closeURL()
+{
+ m_timer->stop();
+ if ( m_part )
+ return m_part->closeURL();
+ return true;
+}
+
+void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * )
+{
+ // Not public!
+ //if ( m_part )
+ // m_part->guiActivateEvent( e );
+}
+
+void KMultiPart::slotJobFinished( TDEIO::Job *job )
+{
+ if ( job->error() )
+ {
+ // TODO use tdehtml's error:// scheme
+ job->showErrorDialog();
+ emit canceled( job->errorString() );
+ }
+ else
+ {
+ /*if ( m_tdehtml->view()->contentsY() == 0 )
+ {
+ KParts::URLArgs args = m_ext->urlArgs();
+ m_tdehtml->view()->setContentsPos( args.xOffset, args.yOffset );
+ }*/
+
+ emit completed();
+
+ //TQTimer::singleShot( 0, this, TQT_SLOT( updateWindowCaption() ) );
+ }
+ m_job = 0L;
+}
+
+void KMultiPart::slotProgressInfo()
+{
+ int time = m_qtime.elapsed();
+ if ( !time ) return;
+ if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped )
+ return; // No change, don't overwrite statusbar messages if any
+ //kdDebug() << m_numberOfFrames << " in " << time << " milliseconds" << endl;
+ TQString str( "%1 frames per second, %2 frames skipped per second" );
+ str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time );
+ str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time );
+ m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped;
+ //kdDebug() << str << endl;
+ emit m_extension->infoMessage( str );
+}
+
+TDEAboutData* KMultiPart::createAboutData()
+{
+ TDEAboutData* aboutData = new TDEAboutData( "tdemultipart", I18N_NOOP("KMultiPart"),
+ "0.1",
+ I18N_NOOP( "Embeddable component for multipart/mixed" ),
+ TDEAboutData::License_GPL,
+ "(c) 2001, David Faure <david@mandrakesoft.com>");
+ return aboutData;
+}
+
+#if 0
+KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name )
+ : KParts::BrowserExtension( parent, name )
+{
+ m_imgPart = parent;
+}
+
+int KMultiPartBrowserExtension::xOffset()
+{
+ return m_imgPart->doc()->view()->contentsX();
+}
+
+int KMultiPartBrowserExtension::yOffset()
+{
+ return m_imgPart->doc()->view()->contentsY();
+}
+
+void KMultiPartBrowserExtension::print()
+{
+ static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print();
+}
+
+void KMultiPartBrowserExtension::reparseConfiguration()
+{
+ static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration();
+ m_imgPart->doc()->setAutoloadImages( true );
+}
+#endif
+
+#include "tdemultipart.moc"
diff --git a/tdehtml/tdemultipart/tdemultipart.desktop b/tdehtml/tdemultipart/tdemultipart.desktop
new file mode 100644
index 000000000..d5808d928
--- /dev/null
+++ b/tdehtml/tdemultipart/tdemultipart.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Type=Service
+MimeType=multipart/mixed;multipart/x-mixed-replace
+Name=Embeddable Component for multipart/mixed
+Name[af]=Inlegbare Komponent vir multideel/gemeng
+Name[be]=Унутраны кампанент Ð´Ð»Ñ multipart/mixed
+Name[bg]=Вграден компонент за преглед на ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ multipart/mixed
+Name[bn]=multipart/mixed-à¦à¦° জনà§à¦¯ অভà§à¦¯à¦¨à§à¦¤à¦°à§€à¦£ উপাদান
+Name[bs]=Ugradiva komponenta za multipart/mixed
+Name[ca]=Component encastable per a multipart/mescla
+Name[cs]=Pohltitelné komponenty pro 'multipart/mixed'
+Name[csb]=Składowi kòmpònent dlô multipart/mixed
+Name[da]=Indlejrbar komponent for multipart/mixed
+Name[de]=Einbettungsfähige Komponente für MIME-Typ multipart/mixed
+Name[el]=Στοιχείο που μποÏεί να ενσωματωθεί για multipart/mixed
+Name[eo]=Enplantebla komponanto por plurparto/mikso
+Name[es]=Componente empotrado para multiparte/mezcla
+Name[et]=Multipart/mixed põimitav komponent
+Name[eu]=Kapsulatutako zati-anitzen/nahastuen osagaia
+Name[fa]=مؤلÙÛ€ نهÙته برای چند بخش/مخلوط
+Name[fi]=Upotettava komponentti multipart/mixed-hallintaan
+Name[fr]=Composant intégrable pour le type multipart / mixed
+Name[fy]=Yn te sluten komponint foar mulipart/mixed
+Name[ga]=Comhpháirt Inleabaithe le haghaidh multipart/mixed
+Name[gl]=Compoñente incrustábel para multpart/mixed
+Name[he]=רכיב בר־הטבעה עבור מרובה חלקי×\מעורב
+Name[hi]=मलà¥à¤Ÿà¥€à¤ªà¤¾à¤°à¥à¤Ÿ/मिकà¥à¤¸à¥à¤¡ के लिठअंतरà¥à¤¨à¤¿à¤¹à¤¿à¤¤ करने योगà¥à¤¯ घटक
+Name[hr]=Ugradiva komponenta za multipart/mixed
+Name[hu]=Beágyazható komponens a multipart/mixed adattípushoz
+Name[id]=Komponen Tersisipkan untuk multipart/mixed
+Name[is]=Ãvefjanleg eining fyrir MIME multipart/mixed
+Name[it]=Componente integrabile per multipart/mixed
+Name[ja]=マルãƒãƒ‘ート/æ··åˆ ã®åŸ‹ã‚è¾¼ã¿å¯èƒ½ãªã‚³ãƒ³ãƒãƒ¼ãƒãƒ³ãƒˆ
+Name[ka]=ჩáƒáƒ“გმáƒáƒ“ი კáƒáƒ›áƒžáƒáƒœáƒ”ნტი მრáƒáƒ•áƒáƒšáƒœáƒáƒ¬áƒ˜áƒšáƒ˜áƒáƒœáƒ˜/შერეულისთვის
+Name[kk]=multipart/mixed тіркеме үшін ендірілетін компоненті
+Name[km]=សមាសភាគ​ដែល​អាច​បង្កប់ សម្រាប់​ផ្នែកជាច្រើន/លាយ
+Name[lb]=Abettbar Komponent fir de MIME-Genre multipart/mixed
+Name[lt]=Įdedamas komponentas multipart/mixed tipui
+Name[lv]=Iegulstama komponente priekš multipart/mixed
+Name[mk]=Вгнездлива компонента за multipart/mixed
+Name[ms]=Komponen boleh serta untuk pelbagai bahagian/bercampur
+Name[nb]=Innebyggbar komponent for multipart/mixed
+Name[nds]=Inbettbor Komponent för multipart/mixed
+Name[ne]=बहà¥à¤­à¤¾à¤—/मिशà¥à¤°à¤£à¤•à¤¾ लागि समà¥à¤®à¤¿à¤²à¤¿à¤¤ गरà¥à¤¨ सकिने अवयव
+Name[nl]=Inbedbaar component voor multipart/mixed
+Name[nn]=Inkluderbar komponent for multipart/mixed
+Name[pa]=ਬਹà©à¨­à¨¾à¨—à©€/ਰਲਵੇਂ ਲਈ ਸ਼ਾਮਿਲ ਭਾਗ
+Name[pl]=Moduł składowy dla multipart/mixed
+Name[pt]=Componente Embebido para multipart/mixed
+Name[pt_BR]=Componente embutido para multipart/mixed
+Name[ro]=Componentă înglobată pentru tip MIME multipart/mixed
+Name[ru]=Ð’Ñтраиваемый компонент Ð´Ð»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹
+Name[rw]=Inyangingo ishyirwamo y'ibicebyinshi/ibivanzwe
+Name[se]=Vuojuhanláhkái oassi multipart/mixed:a várás
+Name[sk]=Vložiteľný komponent pre multipart/mixed
+Name[sl]=Vgradljiva komponenta za multipart/mixed
+Name[sr]=Уградива компонента за „multipart/mixed“
+Name[sr@Latn]=Ugradiva komponenta za „multipart/mixed“
+Name[sv]=Inbyggbar komponent för multipart/mixed
+Name[ta]=பலபà¯à®ªà®•à¯à®¤à®¿/கலகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ பகà¯à®¤à®¿à®•à¯à®•à¯à®°à®¿à®¯ உடà¯à®ªà¯Šà®¤à®¿à®¨à¯à®¤ பகà¯à®¤à®¿
+Name[te]=మలà±à°Ÿà°¿à°ªà°¾à°°à±à°Ÿà±/మికà±à°¸à±à°¡à± కొరకౠపొదిగిన అంశం
+Name[tg]=Компоненти дарунÑохт барои қиÑматҳои зиёд/омезишшуда
+Name[th]=ส่วนประà¸à¸­à¸šà¸—ี่à¸à¸±à¸‡à¸•à¸±à¸§à¹„ด้สำหรับมัลติพาร์ต/ผสม
+Name[tr]=Çok parçalı/karışık için Gömülebilir Bileşen
+Name[uk]=Вбудовна компонента Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ multipart/mixed
+Name[uz]=Multipart/mixed uchun ichiga oʻrnatib boʻladigan komponent
+Name[uz@cyrillic]=Multipart/mixed учун ичига ўрнатиб бўладиган компонент
+Name[vi]=Thành phần có khả năng nhúng cho dạng thức thư đa phần/đã trộn (multipart/mixed).
+Name[zh_CN]=å¯åµŒå…¥çš„ multipart/mixed 组件
+Name[zh_HK]=multipart/mixed çš„å¯åµŒå…¥å…ƒä»¶
+Name[zh_TW]=multipart/mixed çš„å¯åµŒå…¥å…ƒä»¶
+ServiceTypes=KParts/ReadOnlyPart
+X-TDE-Library=libtdemultipart
diff --git a/tdehtml/tdemultipart/tdemultipart.h b/tdehtml/tdemultipart/tdemultipart.h
new file mode 100644
index 000000000..e4add0816
--- /dev/null
+++ b/tdehtml/tdemultipart/tdemultipart.h
@@ -0,0 +1,118 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 David Faure <david@mandrakesoft.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.
+*/
+
+#ifndef __tdemultipart_h__
+#define __tdemultipart_h__
+
+#include <httpfilter/httpfilter.h>
+
+#include <tdeparts/part.h>
+#include <tdeparts/factory.h>
+#include <tdeparts/browserextension.h>
+#include <kaboutdata.h>
+#include <tqdatetime.h>
+
+class KHTMLPart;
+class TDEInstance;
+class KTempFile;
+class KLineParser;
+
+/**
+ * http://www.netscape.com/assist/net_sites/pushpull.html
+ */
+class KMultiPart : public KParts::ReadOnlyPart
+{
+ Q_OBJECT
+public:
+ KMultiPart( TQWidget *parentWidget, const char *widgetName,
+ TQObject *parent, const char *name, const TQStringList& );
+ virtual ~KMultiPart();
+
+ virtual bool openFile() { return false; }
+ virtual bool openURL( const KURL &url );
+
+ virtual bool closeURL();
+
+ static TDEAboutData* createAboutData();
+
+protected:
+ virtual void guiActivateEvent( KParts::GUIActivateEvent *e );
+ void setPart( const TQString& mimeType );
+
+ void startOfData();
+ void sendData( const TQByteArray& line );
+ void endOfData();
+
+private slots:
+ void reallySendData( const TQByteArray& line );
+ //void slotPopupMenu( KXMLGUIClient *cl, const TQPoint &pos, const KURL &u, const TQString &mime, mode_t mode );
+ void slotJobFinished( TDEIO::Job *job );
+ void slotData( TDEIO::Job *, const TQByteArray & );
+ //void updateWindowCaption();
+
+ void slotPartCompleted();
+
+ void startHeader();
+
+ void slotProgressInfo();
+
+private:
+ KParts::BrowserExtension* m_extension;
+ TQGuardedPtr<KParts::ReadOnlyPart> m_part;
+ bool m_isHTMLPart;
+ bool m_partIsLoading;
+ TDEIO::Job* m_job;
+ TQCString m_boundary;
+ int m_boundaryLength;
+ TQString m_mimeType; // the one handled by m_part - store the kservice instead?
+ TQString m_nextMimeType; // while parsing headers
+ KTempFile* m_tempFile;
+ KLineParser* m_lineParser;
+ bool m_bParsingHeader;
+ bool m_bGotAnyHeader;
+ bool m_gzip;
+ HTTPFilterBase *m_filter;
+ // Speed measurements
+ long m_totalNumberOfFrames;
+ long m_numberOfFrames;
+ long m_numberOfFramesSkipped;
+ TQTime m_qtime;
+ TQTimer* m_timer;
+};
+
+#if 0
+class KMultiPartBrowserExtension : public KParts::BrowserExtension
+{
+ //Q_OBJECT
+public:
+ KMultiPartBrowserExtension( KMultiPart *parent, const char *name = 0 );
+
+ virtual int xOffset();
+ virtual int yOffset();
+
+//protected slots:
+ void print();
+ void reparseConfiguration();
+
+private:
+ KMultiPart *m_imgPart;
+};
+#endif
+
+#endif
diff --git a/tdehtml/test/README b/tdehtml/test/README
new file mode 100644
index 000000000..9ab2df3c4
--- /dev/null
+++ b/tdehtml/test/README
@@ -0,0 +1,6 @@
+The contents of this directory will be moved to the toplevel directory tdehtmltests
+
+PLEASE DO NOT POST TEST CASES HERE ANY MORE
+
+
+See tdehtmltests/README
diff --git a/tdehtml/test/align.html b/tdehtml/test/align.html
new file mode 100644
index 000000000..ab663bf42
--- /dev/null
+++ b/tdehtml/test/align.html
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+ <TITLE>Left Aligned Image</TITLE>
+</HEAD>
+<BODY>
+<IMG SRC="nav_bar.gif" height=100 width=200 ALIGN=left border=1>
+The image on this page should be left aligned. Especially the list which
+follows this text should be laid out correctly. Bla bla bla
+This is just some text which you can safely ignore. This is just some
+text which you can safely ignore. This is just some text which you can
+safely ignore. This is just some text which you can safely ignore.
+<br>
+<ul>
+<li> an item
+<li> This is a very long line which really should be placed on the right
+place despite it's very long length.
+<li> another item.
+</ul>
+This is some text placed after the list
+</body>
+</html>
diff --git a/tdehtml/test/align1.html b/tdehtml/test/align1.html
new file mode 100644
index 000000000..f288b52ef
--- /dev/null
+++ b/tdehtml/test/align1.html
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+ <TITLE>Left Aligned Image</TITLE>
+</HEAD>
+<BODY>
+<IMG SRC="nav_bar.gif" height=100 width=200 ALIGN=right border=1>
+The image on this page should be left aligned. Especially the list which
+follows this text should be laid out correctly. Bla bla bla
+This is just some text which you can safely ignore. This is just some
+text which you can safely ignore. This is just some text which you can
+safely ignore. This is just some text which you can safely ignore.
+<br>
+<ul>
+<li> an item
+<li> This is a very long line which really should be placed on the right
+place despite it's very long length.
+<li> another item.
+</ul>
+This is some text placed after the list
+</body>
+</html>
diff --git a/tdehtml/test/align2.html b/tdehtml/test/align2.html
new file mode 100644
index 000000000..56f3feb70
--- /dev/null
+++ b/tdehtml/test/align2.html
@@ -0,0 +1,126 @@
+<HTML>
+<HEAD>
+ <TITLE>Align Test 2</TITLE>
+</HEAD>
+<BODY>
+<H1>Align Test 2</H1>
+This page contains regression tests for vertical alignment of images.
+Each test consist of a table with a colored background.
+Within the table an empty image is shown with a border of 1 pixel around it.
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1>
+<FONT size=7>This image has no alignment</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=top>
+<FONT size=7>This image has align=top</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=middle>
+<FONT size=7>This image has align=middle</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=bottom>
+<FONT size=7>This image has align=bottom</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1>
+<FONT size=7>This image has no alignment</FONT>
+<IMG SRC="unknown.gif" height=50 width=50 border=1>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=top>
+<FONT size=7>This image has align=top</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=middle>
+<FONT size=7>This image has align=middle</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=bottom>
+<FONT size=7>This image has align=bottom</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1>
+<FONT>This image has no alignment</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=top>
+<FONT>This image has align=top</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=middle>
+<FONT>This image has align=middle</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=10 width=50 border=1 align=bottom>
+<FONT>This image has align=bottom</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1>
+<FONT>This image has no alignment</FONT>
+<IMG SRC="unknown.gif" height=50 width=50 border=1>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=top>
+<FONT>This image has align=top</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=middle>
+<FONT>This image has align=middle</FONT>
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 100%>
+<tr><td bgcolor="0000ff">
+<IMG SRC="unknown.gif" height=150 width=50 border=1 align=bottom>
+<FONT>This image has align=bottom</FONT>
+</td></tr>
+</TABLE>
+<HR>
+</body>
+</html>
diff --git a/tdehtml/test/anchor1.html b/tdehtml/test/anchor1.html
new file mode 100644
index 000000000..4dfb26134
--- /dev/null
+++ b/tdehtml/test/anchor1.html
@@ -0,0 +1,25 @@
+<html> <head> <title>Anchor Test 1</title> </head>
+
+
+<body>
+<H1>Anchor Test 1</H1>
+This page is a regression test for anchor's.
+<P>
+<A href="#anchor1">This</a> link should jump to anchor1.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+<P>
+Note that the page may not scroll, if there are no scrollbars!
+</td>
+<td><img src="nav_bar.gif" height=200></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor1>anchor1</a>.
+
+</body>
+
+</html>
diff --git a/tdehtml/test/anchor2.html b/tdehtml/test/anchor2.html
new file mode 100644
index 000000000..4f54e83f9
--- /dev/null
+++ b/tdehtml/test/anchor2.html
@@ -0,0 +1,85 @@
+<html> <head> <title>Anchor Test 1</title> </head>
+
+
+<body>
+<H1>Anchor Test 1</H1>
+This page is a regression test for anchor's.
+<P>
+This is <a name=anchor1>anchor1</a>.
+<P>
+<A href="#anchor2">This</a> link should jump to anchor2.
+<P>
+<A href="#anchor3">This</a> link should jump to anchor3.
+<P>
+<A href="#anchor4">This</a> link should jump to anchor4.
+<P>
+<A href="#anchor5">This</a> link should jump to anchor5.
+<P>
+<A href="#anchor6">This</a> link should jump to anchor6.
+<P>
+<A href="#anchor7">This</a> link should jump to anchor7.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+</td>
+<td><img src="unknown.gif" height=100></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor2>anchor2</a>.<BR>
+Jump back to <a href="#anchor1">anchor1</a>.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+</td>
+<td><img src="unknown.gif" height=4000></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor3>anchor3</a>.<BR>
+Jump back to <a href="#anchor1">anchor1</a>.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+</td>
+<td><img src="unknown.gif" height=8000></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor4>anchor4</a>.<BR>
+Jump back to <a href="#anchor1">anchor1</a>.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+</td>
+<td><img src="unknown.gif" height=17000></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor5>anchor5</a>.<BR>
+Jump back to <a href="#anchor1">anchor1</a>.
+<P>
+<Table border=1>
+<tr>
+<td>
+This is a table to get some vertical spacing.
+</td>
+<td><img src="unknown.gif" height=33000></td>
+</tr>
+</table>
+<P>
+This is <a name=anchor6>anchor6</a>.<BR>
+Jump back to <a href="#anchor1">anchor1</a>.
+<P>
+This <b id="anchor7">bold</b> tag has the id anchor7.
+</body>
+
+</html>
diff --git a/tdehtml/test/button.html b/tdehtml/test/button.html
new file mode 100644
index 000000000..b9c3ae177
--- /dev/null
+++ b/tdehtml/test/button.html
@@ -0,0 +1,14 @@
+<html>
+<body bgcolor=white>
+text before
+<button name=button type=submit value="this should get replaced by the contents">
+some text
+<table width=200 border=1>
+<tr><td bgcolor=red>1<td bgcolor=blue>2</tr>
+<tr><td bgcolor=blue>3<td bgcolor=red>4</tr>
+</table>
+more text
+</button>
+text after text after text after text after text after text after text after text after text after text after text after text after text after text after text after text after
+</body>
+</html> \ No newline at end of file
diff --git a/tdehtml/test/color.html b/tdehtml/test/color.html
new file mode 100644
index 000000000..ff5617214
--- /dev/null
+++ b/tdehtml/test/color.html
@@ -0,0 +1,60 @@
+<HTML>
+<HEAD>
+ <TITLE>Color Test 1</TITLE>
+</HEAD>
+<BODY>
+<H1>Color Test 1</H1>
+This page contains regression tests for the parsing of colors.
+Each test consist of a table with a colored background.
+Within the table the name of the color is written in black text.
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="#0000ff">
+Blue (#0000ff)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="0000ff">
+Blue (0000ff)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="blue">
+Blue (blue)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="BLUE">
+Blue (BLUE)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="#ffff00">
+Yellow (#ffff00)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="ffff00">
+Yellow (ffff00)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="yellow">
+Yellow (yellow)
+</td></tr>
+</TABLE>
+<HR>
+<TABLE width = 150>
+<tr><td bgcolor="teal">
+Teal (teal)
+</td></tr>
+</TABLE>
+<HR>
+</body>
+</html>
diff --git a/tdehtml/test/fixed-background.html b/tdehtml/test/fixed-background.html
new file mode 100644
index 000000000..a1cdaec81
--- /dev/null
+++ b/tdehtml/test/fixed-background.html
@@ -0,0 +1,47 @@
+<html> <head> <title>Listing Test 1</title>
+<style>
+html { background-attachment: fixed;
+ background-image: url(konqi.gif);
+}
+body { color: red; }
+</style>
+</head>
+<body>
+<H1>Listing Test 1</H1>
+This is a regression test to see if the parser handles the &lt;listing&gt;
+tag correctly.<BR>
+<H2>Simple listing</H2>
+Now follows a short listing, after the listing the text
+"End of listing" should be visible.
+<listing>
+//----------------------------------------------------------------------------
+//
+// KDE HTML Widget -- Debug functions
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "tdehtml.h"
+
+#ifdef MARTINSDEBUG
+void debugM( const char *msg, ...)
+{
+ va_list ap;
+ va_start( ap, msg ); // use variable arg list
+ vfprintf( stdout, msg, ap );
+ va_end( ap );
+#else
+void debugM(const char *, ... )
+{
+#endif
+}
+</listing>
+End of listing.
+<H2>Listing with entities</H2>
+Now follows a short listing, the listing shoul read
+"a = b&amp;amp;"<BR>
+<listing>
+a = b&amp;
+</listing>
+
+</BODY>
+</HTML>
diff --git a/tdehtml/test/image.gif b/tdehtml/test/image.gif
new file mode 100644
index 000000000..ba019efb8
--- /dev/null
+++ b/tdehtml/test/image.gif
Binary files differ
diff --git a/tdehtml/test/image_map.html b/tdehtml/test/image_map.html
new file mode 100644
index 000000000..21e002382
--- /dev/null
+++ b/tdehtml/test/image_map.html
@@ -0,0 +1,24 @@
+<html> <head> <title>Image Map Test 1</title> </head>
+
+
+<body>
+<H1>Image Map Test 1</H1>
+
+The following image is a clickable map:
+<P>
+<IMG ISMAP SRC="nav_bar.gif" ALT="" BORDER=0 USEMAP="#topbar" HEIGHT=18 WIDTH=361>
+<P>
+Moving the mouse cursor over the image should show different destinations
+<P>
+
+<!-- =============== TOP IMAGE MAP =========== -->
+<MAP name="topbar">
+<AREA shape="rect" coords="90,0,120,18" href="http://www.kde.org/faq/kdefaq.html">
+<AREA shape="rect" coords="130,0,205,18" href="ftp://ftp.kde.org/pub/kde/">
+<AREA shape="rect" coords="215,0,295,18" href="http://www.kde.org/absolute_url.html">
+<AREA shape="rect" coords="305,0,355,18" href="relative_url_index.html">
+<AREA shape="default" nohref>
+</MAP>
+
+</BODY>
+</HTML>
diff --git a/tdehtml/test/java.html b/tdehtml/test/java.html
new file mode 100644
index 000000000..dfe8d698a
--- /dev/null
+++ b/tdehtml/test/java.html
@@ -0,0 +1,15 @@
+<html>
+<body>
+<table>
+<tr>
+<td width=240>
+<APPLET CODE=lake.class ID=Lake WIDTH=240 HEIGHT=630>
+ <PARAM NAME=image VALUE="konqi.gif">
+</APPLET>
+<td width=240>
+This is a small page to test html's java support. On the left you should see a picture of
+Konqi, which is mirrored on a water surface below.
+</table>
+This text should be directly beow the applet...
+</body>
+</html> \ No newline at end of file
diff --git a/tdehtml/test/jsplugins.html b/tdehtml/test/jsplugins.html
new file mode 100644
index 000000000..7af7a25f7
--- /dev/null
+++ b/tdehtml/test/jsplugins.html
@@ -0,0 +1,73 @@
+<HTML>
+<HEAD>
+<TITLE>About Plug-ins</TITLE>
+</HEAD>
+<BODY>
+<SCRIPT language="javascript">
+
+
+<!-- JavaScript to enumerate and display all installed plug-ins -->
+
+<!-- First, refresh plugins in case anything has been changed recently in prefs: -->
+<!-- (The "false" argument tells refresh not to reload or activate any plugins that would -->
+<!-- be active otherwise. In contrast, one would use "true" in the case of ASD instead of -->
+<!-- restarting) -->
+navigator.plugins.refresh(false);
+
+
+numPlugins = navigator.plugins.length;
+
+if (numPlugins > 0)
+ document.writeln("<b><font size=+3>Installed plug-ins</font></b><br>");
+else
+ document.writeln("<b><font size=+2>No plug-ins are installed.</font></b><br>");
+
+document.writeln("For more information on Netscape plug-ins, <A HREF=http://home.netscape.com/plugins/>click here</A>.<p><hr>");
+
+for (i = 0; i < numPlugins; i++)
+{
+ plugin = navigator.plugins[i];
+
+ document.write("<center><font size=+1><b>");
+ document.write(plugin.name);
+ document.writeln("</b></font></center><br>");
+
+ document.writeln("<dl><dd>File name:");
+ document.write(plugin.filename);
+ document.write("<dd><br>");
+ document.write(plugin.description);
+ document.writeln("</dl><p>");
+
+ document.writeln("<table width=100% border=2 cellpadding=5>");
+ document.writeln("<tr><th width=20%><font size=-1>Mime Type</font></th>");
+ document.writeln("<th width=50%><font size=-1>Description</font></th>");
+ document.writeln("<th width=20%><font size=-1>Suffixes</font></th>");
+ document.writeln("<th><font size=-1>Enabled</th></tr>");
+ numTypes = plugin.length;
+ for (j = 0; j < numTypes; j++)
+ {
+ mimetype = plugin[j];
+
+ if (mimetype)
+ {
+ enabled = "No";
+ enabledPlugin = mimetype.enabledPlugin;
+ if (enabledPlugin && (enabledPlugin.name == plugin.name))
+ enabled = "Yes";
+
+ document.writeln("<tr align=center>");
+ document.writeln("<td>" + mimetype.type + "</td>");
+ document.writeln("<td>" + mimetype.description + "</td>");
+ document.writeln("<td>" + mimetype.suffixes + "</td>");
+ document.writeln("<td>" + enabled + "</td>");
+ document.writeln("</tr>");
+ }
+ }
+
+ document.write("</table><p><hr><p>");
+}
+
+
+</SCRIPT>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/tdehtml/test/konqi.gif b/tdehtml/test/konqi.gif
new file mode 100644
index 000000000..b80293aa9
--- /dev/null
+++ b/tdehtml/test/konqi.gif
Binary files differ
diff --git a/tdehtml/test/lake.class b/tdehtml/test/lake.class
new file mode 100644
index 000000000..3196702b1
--- /dev/null
+++ b/tdehtml/test/lake.class
Binary files differ
diff --git a/tdehtml/test/lists.html b/tdehtml/test/lists.html
new file mode 100644
index 000000000..8f781653c
--- /dev/null
+++ b/tdehtml/test/lists.html
@@ -0,0 +1,221 @@
+<html>
+<body>
+<ul>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+
+<hr>
+In a fixed width table:
+<table width=100 border=1 bgcolor=white>
+<tr><td>
+<ul>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+</td></tr>
+</table>
+
+<hr>
+In a variable width table:
+<table border=1 bgcolor=white>
+<tr><td>
+<ul>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+</td></tr>
+</table>
+
+<hr>
+Now the same thing in a right to left context:
+
+<div dir=rtl>
+<hr>
+<ul dir=rtl>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+
+<hr>
+In a fixed width table:
+<table width=100 border=1 bgcolor=white>
+<tr><td>
+<ul>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+</td></tr>
+</table>
+
+<hr>
+In a variable width table:
+<table border=1 bgcolor=white>
+<tr><td>
+<ul>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ul>
+
+<hr>
+
+Nested lists:
+<ul>
+<li> first item
+<li> second item
+<li> a nested list
+<ul>
+<li> first nested item
+<li> second nested item
+</ul>
+<li> fourth item
+</ul>
+
+<hr>
+
+Numbered list:
+<ol>
+<li> first item
+<li> second item
+<li> third item
+<li> fourth item
+</ol>
+</td></tr>
+</table>
+</div>
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/tdehtml/test/nav_bar.gif b/tdehtml/test/nav_bar.gif
new file mode 100644
index 000000000..174348da4
--- /dev/null
+++ b/tdehtml/test/nav_bar.gif
Binary files differ
diff --git a/tdehtml/test/nbsp.html b/tdehtml/test/nbsp.html
new file mode 100644
index 000000000..7a8bde9de
--- /dev/null
+++ b/tdehtml/test/nbsp.html
@@ -0,0 +1,20 @@
+<html> <head> <title>NBSP Test</title> </head>
+
+
+<body>
+<H1>NBSP Test</H1>
+This page is a regression test to test non-breaking spaces.<BR>
+The following text contains normal and non-breaking spaces.<BR>
+After each 'a' a non-breaking space occurs. After each 'b' a
+breaking space occurs:
+<HR>
+<FONT face="lucida">
+ccccccca&nbsp;cccca&nbsp;ccccccb ccb cb ccb ccca&nbsp;ca&nbsp;a&nbsp;cb
+c4d&nbsp;&nbsp;&nbsp;&nbsp;cccc2d&nbsp;&nbsp;ccccb ccb ccc
+</FONT>
+<HR>
+
+
+</body>
+
+</html>
diff --git a/tdehtml/test/object.html b/tdehtml/test/object.html
new file mode 100644
index 000000000..91da9f575
--- /dev/null
+++ b/tdehtml/test/object.html
@@ -0,0 +1,4 @@
+<html><head></head><body>
+<object type="inode/directory" data="file:/home/" width="300" height="100">
+</body>
+</html>
diff --git a/tdehtml/test/pseudo.html b/tdehtml/test/pseudo.html
new file mode 100644
index 000000000..caba3bfee
--- /dev/null
+++ b/tdehtml/test/pseudo.html
@@ -0,0 +1,27 @@
+
+
+<html>
+<head>
+<style>
+span { background-color: blue; }
+span:hover { background-color: red; }
+div { border: 2px solid blue; }
+div:first-letter { background-color: green; float: left; font-size: 3em; margin: 3px 3px 3px 3px}
+div:first-line { background-color: red; font-size: 1em; }
+
+</style>
+</head>
+<body>
+<h1>:first-letter and :first-line</h1>
+<div>
+Hello world Hello world Hello worldHello world Hello world Hello world Hello world
+Hello world Hello world Hello worldHello world Hello world Hello world Hello world
+Hello world Hello world Hello worldHello world Hello world Hello world Hello world
+Hello world Hello world Hello worldHello world Hello world Hello world Hello world
+</div>
+<h1>:hover</h1>
+<p>
+ jee jee <span>jee</span> jee jee jee
+</p>
+</body>
+</html>
diff --git a/tdehtml/test/testpages.html b/tdehtml/test/testpages.html
new file mode 100644
index 000000000..e117a7db9
--- /dev/null
+++ b/tdehtml/test/testpages.html
@@ -0,0 +1,34 @@
+<html>
+<title>
+Links to some test pages
+</title>
+<body>
+<p>
+<a href="http://dbaron.org/dom/test/">David Baron's DOM test suite</a><br>
+Tests that work perfectly so far:
+<a href="http://dbaron.org/dom/test/one-core-html/DocumentFragment">DocumentFragment</a>,
+<a href="http://dbaron.org/dom/test/one-core-html/Document">Document</a>,
+<a href="http://dbaron.org/dom/test/one-core-html/Comment">Comment</a>,
+<a href="http://dbaron.org/dom/test/one-core-html/Node">Node</a>,
+<a href="http://dbaron.org/dom/test/one-core-html/Text">Text</a>
+
+<p>
+<a href="http://www.jeremie.com/Dev/DOM/index.jer">more jscript tests</a>
+
+<p>
+Some pages with tests from mozilla.org:
+<ul>
+<li><a href="http://komodo.mozilla.org/buster/">tests lots of pages</a>
+<li><a href="http://www.mozilla.org/quality/browser_sc.html">collection of links to test pages</a>
+</ul>
+<p>
+Some more CSS: <a href="http://haughey.com/csshorrors/">http://haughey.com/csshorrors/</a><br>
+The evil Tests: <a href="http://www.hixie.ch/tests/evil/mixed/home.html">http://www.hixie.ch/tests/evil/mixed/home.html</a>
+<p>
+The w3c CSS test suite:<a href="http://www.w3.org/Style/CSS/Test/">
+http://www.w3.org/Style/CSS/Test/</a>
+<p>
+CSS+Javascript tests: <a href="http://www.quirksmode.org">http://www.quirksmode.org</a><p>
+More evil CSS tests on <a href="http://www.endoframe.com/css/tests/">http://www.endoframe.com/css/tests/</a>
+ </body>
+</html>
diff --git a/tdehtml/test_regression.cpp b/tdehtml/test_regression.cpp
new file mode 100644
index 000000000..233ac8402
--- /dev/null
+++ b/tdehtml/test_regression.cpp
@@ -0,0 +1,1644 @@
+/**
+ * This file is part of the KDE project
+ *
+ * Copyright (C) 2001,2003 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003,2004 Stephan Kulow (coolo@kde.org)
+ * Copyright (C) 2004 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 <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <tqimage.h>
+#include <tqfile.h>
+#include "test_regression.h"
+#include <unistd.h>
+#include <stdio.h>
+
+#include "css/cssstyleselector.h"
+#include <dom_string.h>
+#include "rendering/render_style.h"
+#include "rendering/render_layer.h"
+#include "tdehtmldefaults.h"
+
+//We don't use the default fonts, though, but traditional testregression ones
+#undef HTML_DEFAULT_VIEW_FONT
+#undef HTML_DEFAULT_VIEW_FIXED_FONT
+#undef HTML_DEFAULT_VIEW_SERIF_FONT
+#undef HTML_DEFAULT_VIEW_SANSSERIF_FONT
+#undef HTML_DEFAULT_VIEW_CURSIVE_FONT
+#undef HTML_DEFAULT_VIEW_FANTASY_FONT
+#define HTML_DEFAULT_VIEW_FONT "helvetica"
+#define HTML_DEFAULT_VIEW_FIXED_FONT "courier"
+#define HTML_DEFAULT_VIEW_SERIF_FONT "times"
+#define HTML_DEFAULT_VIEW_SANSSERIF_FONT "helvetica"
+#define HTML_DEFAULT_VIEW_CURSIVE_FONT "helvetica"
+#define HTML_DEFAULT_VIEW_FANTASY_FONT "helvetica"
+
+
+#include <kaction.h>
+#include <kcmdlineargs.h>
+#include "tdehtml_factory.h"
+#include <kio/job.h>
+#include <kmainwindow.h>
+#include <ksimpleconfig.h>
+#include <kglobalsettings.h>
+
+#include <tqcolor.h>
+#include <tqcursor.h>
+#include <tqdir.h>
+#include <tqobject.h>
+#include <tqpushbutton.h>
+#include <tqscrollview.h>
+#include <tqstring.h>
+#include <tqtextstream.h>
+#include <tqvaluelist.h>
+#include <tqwidget.h>
+#include <tqfileinfo.h>
+#include <tqtimer.h>
+#include <kstatusbar.h>
+#include <tqfileinfo.h>
+
+#include "misc/decoder.h"
+#include "dom/dom2_range.h"
+#include "dom/dom_exception.h"
+#include "dom/html_document.h"
+#include "html/htmltokenizer.h"
+#include "tdehtml_part.h"
+#include "tdehtmlpart_p.h"
+#include <tdeparts/browserextension.h>
+
+#include "tdehtmlview.h"
+#include "rendering/render_replaced.h"
+#include "xml/dom_docimpl.h"
+#include "html/html_baseimpl.h"
+#include "dom/dom_doc.h"
+#include "misc/loader.h"
+#include "ecma/kjs_binding.h"
+#include "ecma/kjs_dom.h"
+#include "ecma/kjs_window.h"
+#include "ecma/kjs_binding.h"
+#include "ecma/kjs_proxy.h"
+
+using namespace tdehtml;
+using namespace DOM;
+using namespace KJS;
+
+static bool visual = false;
+static pid_t xvfb;
+
+// -------------------------------------------------------------------------
+
+PartMonitor *PartMonitor::sm_highestMonitor = NULL;
+
+PartMonitor::PartMonitor(KHTMLPart *_part)
+{
+ m_part = _part;
+ m_completed = false;
+ connect(m_part,TQT_SIGNAL(completed()),this,TQT_SLOT(partCompleted()));
+ m_timer_waits = 200;
+ m_timeout_timer = new TQTimer(this);
+}
+
+PartMonitor::~PartMonitor()
+{
+ if (this == sm_highestMonitor)
+ sm_highestMonitor = 0;
+}
+
+
+void PartMonitor::waitForCompletion()
+{
+ if (!m_completed) {
+
+ if (sm_highestMonitor)
+ return;
+
+ sm_highestMonitor = this;
+
+ kapp->enter_loop();
+
+ //connect(m_timeout_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT( timeout() ) );
+ //m_timeout_timer->stop();
+ //m_timeout_timer->start( visual ? 100 : 2, true );
+ }
+
+ TQTimer::singleShot( 0, this, TQT_SLOT( finishTimers() ) );
+ kapp->enter_loop();
+}
+
+void PartMonitor::timeout()
+{
+ kapp->exit_loop();
+}
+
+void PartMonitor::finishTimers()
+{
+ KJS::Window *w = KJS::Window::retrieveWindow( m_part );
+ --m_timer_waits;
+ if ( m_timer_waits && (w && w->winq->hasTimers()) || m_part->inProgress()) {
+ // wait a bit
+ TQTimer::singleShot( 10, this, TQT_SLOT(finishTimers() ) );
+ return;
+ }
+ kapp->exit_loop();
+}
+
+void PartMonitor::partCompleted()
+{
+ m_completed = true;
+ RenderWidget::flushWidgetResizes();
+ m_timeout_timer->stop();
+ connect(m_timeout_timer, TQT_SIGNAL(timeout()),this, TQT_SLOT( timeout() ) );
+ m_timeout_timer->start( visual ? 100 : 2, true );
+ disconnect(m_part,TQT_SIGNAL(completed()),this,TQT_SLOT(partCompleted()));
+}
+
+static void signal_handler( int )
+{
+ printf( "timeout\n" );
+ abort();
+}
+// -------------------------------------------------------------------------
+
+RegTestObject::RegTestObject(ExecState *exec, RegressionTest *_regTest)
+{
+ m_regTest = _regTest;
+ putDirect("print",new RegTestFunction(exec,m_regTest,RegTestFunction::Print,1), DontEnum);
+ putDirect("reportResult",new RegTestFunction(exec,m_regTest,RegTestFunction::ReportResult,3), DontEnum);
+ putDirect("checkOutput",new RegTestFunction(exec,m_regTest,RegTestFunction::CheckOutput,1), DontEnum);
+ // add "quit" for compatibility with the mozilla js shell
+ putDirect("quit", new RegTestFunction(exec,m_regTest,RegTestFunction::Quit,1), DontEnum );
+}
+
+RegTestFunction::RegTestFunction(ExecState* /*exec*/, RegressionTest *_regTest, int _id, int length)
+{
+ m_regTest = _regTest;
+ id = _id;
+ putDirect("length",length);
+}
+
+bool RegTestFunction::implementsCall() const
+{
+ return true;
+}
+
+Value RegTestFunction::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ Value result = Undefined();
+ if ( m_regTest->ignore_errors )
+ return result;
+
+ switch (id) {
+ case Print: {
+ UString str = args[0].toString(exec);
+ if ( str.qstring().lower().find( "failed!" ) >= 0 )
+ m_regTest->saw_failure = true;
+ TQString res = str.qstring().replace('\007', "");
+ m_regTest->m_currentOutput += res + "\n";
+ break;
+ }
+ case ReportResult: {
+ bool passed = args[0].toBoolean(exec);
+ TQString description = args[1].toString(exec).qstring();
+ if (args[1].isA(UndefinedType) || args[1].isA(NullType))
+ description = TQString::null;
+ m_regTest->reportResult(passed,description);
+ if ( !passed )
+ m_regTest->saw_failure = true;
+ break;
+ }
+ case CheckOutput: {
+ DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl*>( m_regTest->m_part->document().handle() );
+ if ( docimpl && docimpl->view() && docimpl->renderer() )
+ {
+ docimpl->updateRendering();
+ docimpl->view()->layout();
+ }
+ TQString filename = args[0].toString(exec).qstring();
+ filename = RegressionTest::curr->m_currentCategory+"/"+filename;
+ int failures = RegressionTest::NoFailure;
+ if ( m_regTest->m_genOutput ) {
+ if ( !m_regTest->reportResult( m_regTest->checkOutput(filename+"-dom"),
+ "Script-generated " + filename + "-dom") )
+ failures |= RegressionTest::DomFailure;
+ if ( !m_regTest->reportResult( m_regTest->checkOutput(filename+"-render"),
+ "Script-generated " + filename + "-render") )
+ failures |= RegressionTest::RenderFailure;
+ } else {
+ // compare with output file
+ if ( !m_regTest->reportResult( m_regTest->checkOutput(filename+"-dom"), "DOM") )
+ failures |= RegressionTest::DomFailure;
+ if ( !m_regTest->reportResult( m_regTest->checkOutput(filename+"-render"), "RENDER") )
+ failures |= RegressionTest::RenderFailure;
+ }
+ RegressionTest::curr->doFailureReport( filename, failures );
+ break;
+ }
+ case Quit:
+ m_regTest->reportResult(true,
+ "Called quit" );
+ if ( !m_regTest->saw_failure )
+ m_regTest->ignore_errors = true;
+ break;
+ }
+
+ return result;
+}
+
+// -------------------------------------------------------------------------
+
+KHTMLPartObject::KHTMLPartObject(ExecState *exec, KHTMLPart *_part)
+{
+ m_part = _part;
+ putDirect("openPage", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::OpenPage,1), DontEnum);
+ putDirect("openPageAsUrl", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::OpenPageAsUrl,1), DontEnum);
+ putDirect("begin", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::Begin,1), DontEnum);
+ putDirect("write", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::Write,1), DontEnum);
+ putDirect("end", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::End,0), DontEnum);
+ putDirect("executeScript", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::ExecuteScript,0), DontEnum);
+ putDirect("processEvents", new KHTMLPartFunction(exec,m_part,KHTMLPartFunction::ProcessEvents,0), DontEnum);
+}
+
+Value KHTMLPartObject::get(ExecState *exec, const Identifier &propertyName) const
+{
+ if (propertyName == "document")
+ return getDOMNode(exec,m_part->document());
+ else if (propertyName == "window")
+ return Object(KJS::Window::retrieveWindow(m_part));
+ else
+ return ObjectImp::get(exec,propertyName);
+}
+
+KHTMLPartFunction::KHTMLPartFunction(ExecState */*exec*/, KHTMLPart *_part, int _id, int length)
+{
+ m_part = _part;
+ id = _id;
+ putDirect("length",length);
+}
+
+bool KHTMLPartFunction::implementsCall() const
+{
+ return true;
+}
+
+Value KHTMLPartFunction::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ Value result = Undefined();
+
+ switch (id) {
+ case OpenPage: {
+ if (args[0].type() == NullType || args[0].type() == NullType) {
+ exec->setException(Error::create(exec, GeneralError,"No filename specified"));
+ return Undefined();
+ }
+
+ TQString filename = args[0].toString(exec).qstring();
+ TQString fullFilename = TQFileInfo(RegressionTest::curr->m_currentBase+"/"+filename).absFilePath();
+ KURL url;
+ url.setProtocol("file");
+ url.setPath(fullFilename);
+ PartMonitor pm(m_part);
+ m_part->openURL(url);
+ pm.waitForCompletion();
+ kapp->processEvents(60000);
+ break;
+ }
+ case OpenPageAsUrl: {
+ if (args[0].type() == NullType || args[0].type() == UndefinedType) {
+ exec->setException(Error::create(exec, GeneralError,"No filename specified"));
+ return Undefined();
+ }
+ if (args[1].type() == NullType || args[1].type() == UndefinedType) {
+ exec->setException(Error::create(exec, GeneralError,"No url specified"));
+ return Undefined();
+ }
+
+ TQString filename = args[0].toString(exec).qstring();
+ TQString url = args[1].toString(exec).qstring();
+ TQFile file(RegressionTest::curr->m_currentBase+"/"+filename);
+ if (!file.open(IO_ReadOnly)) {
+ exec->setException(Error::create(exec, GeneralError,
+ TQString("Error reading " + filename).latin1()));
+ }
+ else {
+ TQByteArray fileData;
+ TQDataStream stream(fileData,IO_WriteOnly);
+ char buf[1024];
+ int bytesread;
+ while (!file.atEnd()) {
+ bytesread = file.tqreadBlock(buf,1024);
+ stream.writeRawBytes(buf,bytesread);
+ }
+ file.close();
+ TQString contents(fileData);
+ PartMonitor pm(m_part);
+ m_part->begin(KURL( url ));
+ m_part->write(contents);
+ m_part->end();
+ pm.waitForCompletion();
+ }
+ kapp->processEvents(60000);
+ break;
+ }
+ case Begin: {
+ TQString url = args[0].toString(exec).qstring();
+ m_part->begin(KURL( url ));
+ break;
+ }
+ case Write: {
+ TQString str = args[0].toString(exec).qstring();
+ m_part->write(str);
+ break;
+ }
+ case End: {
+ m_part->end();
+ kapp->processEvents(60000);
+ break;
+ }
+ case ExecuteScript: {
+ TQString code = args[0].toString(exec).qstring();
+ Completion comp;
+ KJSProxy *proxy = m_part->jScript();
+ proxy->evaluate("",0,code,0,&comp);
+ if (comp.complType() == Throw)
+ exec->setException(comp.value());
+ kapp->processEvents(60000);
+ break;
+ }
+ case ProcessEvents: {
+ kapp->processEvents(60000);
+ break;
+ }
+ }
+
+ return result;
+}
+
+// -------------------------------------------------------------------------
+
+static KCmdLineOptions options[] =
+{
+ { "b", 0, 0 },
+ { "base <base_dir>", "Directory containing tests, basedir and output directories.", 0},
+ { "d", 0, 0 },
+ { "debug", "Do not supress debug output", 0},
+ { "g", 0, 0 } ,
+ { "genoutput", "Regenerate baseline (instead of checking)", 0 } ,
+ { "s", 0, 0 } ,
+ { "show", "Show the window while running tests", 0 } ,
+ { "t", 0, 0 } ,
+ { "test <filename>", "Only run a single test. Multiple options allowed.", 0 } ,
+ { "js", "Only run .js tests", 0 },
+ { "html", "Only run .html tests", 0},
+ { "noxvfb", "Do not use Xvfb", 0},
+ { "o", 0, 0 },
+ { "output <directory>", "Put output in <directory> instead of <base_dir>/output", 0 } ,
+ { "+[base_dir]", "Directory containing tests,basedir and output directories. Only regarded if -b is not specified.", 0 } ,
+ { "+[testcases]", "Relative path to testcase, or directory of testcases to be run (equivalent to -t).", 0 } ,
+ KCmdLineLastOption
+};
+
+static bool existsDir(TQCString dir)
+{
+ struct stat st;
+
+ return (!stat(dir.data(), &st) && S_ISDIR(st.st_mode));
+}
+
+int main(int argc, char *argv[])
+{
+ // forget about any settings
+ passwd* pw = getpwuid( getuid() );
+ if (!pw) {
+ fprintf(stderr, "dang, I don't even know who I am.\n");
+ exit(1);
+ }
+
+ TQString kh("/var/tmp/%1_non_existant");
+ kh = kh.arg( pw->pw_name );
+ setenv( "TDEHOME", kh.latin1(), 1 );
+ setenv( "LC_ALL", "C", 1 );
+ setenv( "LANG", "C", 1 );
+
+ signal( SIGALRM, signal_handler );
+
+ // workaround various Qt crashes by always enforcing a TrueColor visual
+ TQApplication::setColorSpec( TQApplication::ManyColor );
+
+ TDECmdLineArgs::init(argc, argv, "testregression", "TestRegression",
+ "Regression tester for tdehtml", "1.0");
+ TDECmdLineArgs::addCmdLineOptions(options);
+
+ TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs( );
+
+ TQCString baseDir = args->getOption("base");
+
+ if ( args->count() < 1 && baseDir.isEmpty() ) {
+ TDECmdLineArgs::usage();
+ ::exit( 1 );
+ }
+
+ int testcase_index = 0;
+ if (baseDir.isEmpty()) baseDir = args->arg(testcase_index++);
+
+ TQFileInfo bdInfo(baseDir);
+ baseDir = TQFile::encodeName(bdInfo.absFilePath());
+
+ const char *subdirs[] = {"tests", "baseline", "output", "resources"};
+ for ( int i = 0; i < 3; i++ ) {
+ TQFileInfo sourceDir(TQFile::encodeName( baseDir ) + "/" + subdirs[i]);
+ if ( !sourceDir.exists() || !sourceDir.isDir() ) {
+ fprintf(stderr,"ERROR: Source directory \"%s/%s\": no such directory.\n", (const char *)baseDir, subdirs[i]);
+ exit(1);
+ }
+ }
+
+ if (args->isSet("xvfb"))
+ {
+ TQString xvfbPath = KStandardDirs::findExe("Xvfb");
+ if ( xvfbPath.isEmpty() ) {
+ fprintf( stderr, "[test_regression] ERROR: We need Xvfb to be installed for reliable results\n" );
+ exit( 1 );
+ }
+
+ TQCString xvfbPath8 = TQFile::encodeName(xvfbPath);
+ TQStringList fpaths;
+ fpaths.append(baseDir+"/resources");
+
+ const char* const fontdirs[] = { "75dpi", "misc", "Type1" };
+ const char* const fontpaths[] = {"/usr/share/fonts/", "/usr/X11/lib/X11/fonts/",
+ "/usr/lib/X11/fonts/", "/usr/share/fonts/X11/" };
+
+ for (size_t fp=0; fp < sizeof(fontpaths)/sizeof(*fontpaths); ++fp)
+ for (size_t fd=0; fd < sizeof(fontdirs)/sizeof(*fontdirs); ++fd)
+ if (existsDir(TQCString(fontpaths[fp])+TQCString(fontdirs[fd])))
+ if (strcmp(fontdirs[fd] , "Type1"))
+ fpaths.append(TQCString(fontpaths[fp])+TQCString(fontdirs[fd])+":unscaled");
+ else
+ fpaths.append(TQCString(fontpaths[fp])+TQCString(fontdirs[fd]));
+
+ xvfb = fork();
+ if ( !xvfb ) {
+ TQCString buffer = fpaths.join(",").latin1();
+ execl( xvfbPath8.data(), xvfbPath8.data(), "-once", "-dpi", "100", "-screen", "0",
+ "1024x768x16", "-ac", "-fp", buffer.data(), ":47", (char*)NULL );
+ }
+
+ setenv( "DISPLAY", ":47", 1 );
+ }
+
+ TDEApplication a;
+ a.disableAutoDcopRegistration();
+ a.setStyle( "windows" );
+ KSimpleConfig sc1( "cryptodefaults" );
+ sc1.setGroup( "Warnings" );
+ sc1.writeEntry( "OnUnencrypted", false );
+ a.config()->setGroup( "Notification Messages" );
+ a.config()->writeEntry( "kjscupguard_alarmhandler", true );
+ a.config()->setGroup("HTML Settings");
+ a.config()->writeEntry("ReportJSErrors", false);
+ TDEConfig cfg( "tdehtmlrc" );
+ cfg.setGroup("HTML Settings");
+ cfg.writeEntry( "StandardFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT );
+ cfg.writeEntry( "FixedFont", HTML_DEFAULT_VIEW_FIXED_FONT );
+ cfg.writeEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT );
+ cfg.writeEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT );
+ cfg.writeEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT );
+ cfg.writeEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT );
+ cfg.writeEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE );
+ cfg.writeEntry( "MediumFontSize", 10 );
+ cfg.writeEntry( "Fonts", TQStringList() );
+ cfg.writeEntry( "DefaultEncoding", "" );
+ cfg.setGroup("Java/JavaScript Settings");
+ cfg.writeEntry( "WindowOpenPolicy", KHTMLSettings::KJSWindowOpenAllow);
+
+ cfg.sync();
+
+ int rv = 1;
+
+ if ( !args->isSet( "debug" ) ) {
+ KSimpleConfig dc( "kdebugrc" );
+ static int areas[] = { 1000, 6000, 6005, 6010, 6020, 6030,
+ 6031, 6035, 6036, 6040, 6041, 6045,
+ 6050, 6060, 6061, 7000, 7006, 170,
+ 171, 7101, 7002, 7019, 7027, 7014,
+ 7011, 6070, 6080, 6090, 0};
+ for ( int i = 0; areas[i]; ++i ) {
+ dc.setGroup( TQString::number( areas[i] ) );
+ dc.writeEntry( "InfoOutput", 4 );
+ }
+ dc.sync();
+
+ kdClearDebugConfig();
+ }
+
+ // create widgets
+ KHTMLFactory *fac = new KHTMLFactory();
+ KMainWindow *toplevel = new KMainWindow();
+ KHTMLPart *part = new KHTMLPart( toplevel, 0, toplevel, 0, KHTMLPart::BrowserViewGUI );
+
+ toplevel->setCentralWidget( part->widget() );
+ part->setJScriptEnabled(true);
+
+ part->executeScript(DOM::Node(), ""); // force the part to create an interpreter
+// part->setJavaEnabled(true);
+
+ if (args->isSet("show"))
+ visual = true;
+
+ a.setTopWidget(part->widget());
+ a.setMainWidget( toplevel );
+ if ( visual )
+ toplevel->show();
+
+ // we're not interested
+ toplevel->statusBar()->hide();
+
+ if (!getenv("TDE_DEBUG")) {
+ // set ulimits
+ rlimit vmem_limit = { 256*1024*1024, RLIM_INFINITY }; // 256Mb Memory should suffice
+ setrlimit(RLIMIT_AS, &vmem_limit);
+ rlimit stack_limit = { 8*1024*1024, RLIM_INFINITY }; // 8Mb Memory should suffice
+ setrlimit(RLIMIT_STACK, &stack_limit);
+ }
+
+ // run the tests
+ RegressionTest *regressionTest = new RegressionTest(part,
+ baseDir,
+ args->getOption("output"),
+ args->isSet("genoutput"),
+ !args->isSet( "html" ),
+ !args->isSet( "js" ));
+ TQObject::connect(part->browserExtension(), TQT_SIGNAL(openURLRequest(const KURL &, const KParts::URLArgs &)),
+ regressionTest, TQT_SLOT(slotOpenURL(const KURL&, const KParts::URLArgs &)));
+ TQObject::connect(part->browserExtension(), TQT_SIGNAL(resizeTopLevelWidget( int, int )),
+ regressionTest, TQT_SLOT(resizeTopLevelWidget( int, int )));
+
+ bool result = false;
+ QCStringList tests = args->getOptionList("test");
+ // merge testcases specified on command line
+ for (; testcase_index < args->count(); testcase_index++)
+ tests << args->arg(testcase_index);
+ if (tests.count() > 0)
+ for (TQValueListConstIterator<TQCString> it = tests.begin(); it != tests.end(); ++it) {
+ result = regressionTest->runTests(*it,true);
+ if (!result) break;
+ }
+ else
+ result = regressionTest->runTests();
+
+ if (result) {
+ if (args->isSet("genoutput")) {
+ printf("\nOutput generation completed.\n");
+ }
+ else {
+ printf("\nTests completed.\n");
+ printf("Total: %d\n",
+ regressionTest->m_passes_work+
+ regressionTest->m_passes_fail+
+ regressionTest->m_failures_work+
+ regressionTest->m_failures_fail+
+ regressionTest->m_errors);
+ printf("Passes: %d",regressionTest->m_passes_work);
+ if ( regressionTest->m_passes_fail )
+ printf( " (%d unexpected passes)\n", regressionTest->m_passes_fail );
+ else
+ printf( "\n" );
+ printf("Failures: %d",regressionTest->m_failures_work);
+ if ( regressionTest->m_failures_fail )
+ printf( " (%d expected failures)\n", regressionTest->m_failures_fail );
+ else
+ printf( "\n" );
+ if ( regressionTest->m_errors )
+ printf("Errors: %d\n",regressionTest->m_errors);
+
+ TQFile list( regressionTest->m_outputDir + "/links.html" );
+ list.open( IO_WriteOnly|IO_Append );
+ TQString link, cl;
+ link = TQString( "<hr>%1 failures. (%2 expected failures)" )
+ .arg(regressionTest->m_failures_work )
+ .arg( regressionTest->m_failures_fail );
+ list.tqwriteBlock( link.latin1(), link.length() );
+ list.close();
+ }
+ }
+
+ // Only return a 0 exit code if all tests were successful
+ if (regressionTest->m_failures_work == 0 && regressionTest->m_errors == 0)
+ rv = 0;
+
+ // cleanup
+ delete regressionTest;
+ delete part;
+ delete toplevel;
+ delete fac;
+
+ tdehtml::Cache::clear();
+ tdehtml::CSSStyleSelector::clear();
+ tdehtml::RenderStyle::cleanup();
+
+ kill( xvfb, SIGINT );
+
+ return rv;
+}
+
+// -------------------------------------------------------------------------
+
+RegressionTest *RegressionTest::curr = 0;
+
+RegressionTest::RegressionTest(KHTMLPart *part, const TQString &baseDir, const TQString &outputDir,
+ bool _genOutput, bool runJS, bool runHTML)
+ : TQObject(part)
+{
+ m_part = part;
+ m_baseDir = baseDir;
+ m_baseDir = m_baseDir.replace( "//", "/" );
+ if ( m_baseDir.endsWith( "/" ) )
+ m_baseDir = m_baseDir.left( m_baseDir.length() - 1 );
+ if (outputDir.isEmpty())
+ m_outputDir = m_baseDir + "/output";
+ else {
+ createMissingDirs(outputDir + "/");
+ m_outputDir = outputDir;
+ }
+ m_genOutput = _genOutput;
+ m_runJS = runJS;
+ m_runHTML = runHTML;
+ m_passes_work = m_passes_fail = 0;
+ m_failures_work = m_failures_fail = 0;
+ m_errors = 0;
+
+ ::unlink( TQFile::encodeName( m_outputDir + "/links.html" ) );
+ TQFile f( m_outputDir + "/empty.html" );
+ TQString s;
+ f.open( IO_WriteOnly | IO_Truncate );
+ s = "<html><body>Follow the white rabbit";
+ f.tqwriteBlock( s.latin1(), s.length() );
+ f.close();
+ f.setName( m_outputDir + "/index.html" );
+ f.open( IO_WriteOnly | IO_Truncate );
+ s = "<html><frameset cols=150,*><frame src=links.html><frame name=content src=empty.html>";
+ f.tqwriteBlock( s.latin1(), s.length() );
+ f.close();
+
+ m_paintBuffer = 0;
+
+ curr = this;
+}
+
+#include <tqobjectlist.h>
+
+static TQStringList readListFile( const TQString &filename )
+{
+ // Read ignore file for this directory
+ TQString ignoreFilename = filename;
+ TQFileInfo ignoreInfo(ignoreFilename);
+ TQStringList ignoreFiles;
+ if (ignoreInfo.exists()) {
+ TQFile ignoreFile(ignoreFilename);
+ if (!ignoreFile.open(IO_ReadOnly)) {
+ fprintf(stderr,"Can't open %s\n",ignoreFilename.latin1());
+ exit(1);
+ }
+ TQTextStream ignoreStream(&ignoreFile);
+ TQString line;
+ while (!(line = ignoreStream.readLine()).isNull())
+ ignoreFiles.append(line);
+ ignoreFile.close();
+ }
+ return ignoreFiles;
+}
+
+RegressionTest::~RegressionTest()
+{
+ delete m_paintBuffer;
+}
+
+bool RegressionTest::runTests(TQString relPath, bool mustExist, int known_failure)
+{
+ m_currentOutput = TQString::null;
+
+ if (!TQFile(m_baseDir + "/tests/"+relPath).exists()) {
+ fprintf(stderr,"%s: No such file or directory\n",relPath.latin1());
+ return false;
+ }
+
+ TQString fullPath = m_baseDir + "/tests/"+relPath;
+ TQFileInfo info(fullPath);
+
+ if (!info.exists() && mustExist) {
+ fprintf(stderr,"%s: No such file or directory\n",relPath.latin1());
+ return false;
+ }
+
+ if (!info.isReadable() && mustExist) {
+ fprintf(stderr,"%s: Access denied\n",relPath.latin1());
+ return false;
+ }
+
+ if (info.isDir()) {
+ TQStringList ignoreFiles = readListFile( m_baseDir + "/tests/"+relPath+"/ignore" );
+ TQStringList failureFiles = readListFile( m_baseDir + "/tests/"+relPath+"/KNOWN_FAILURES" );
+
+ // Run each test in this directory, recusively
+ TQDir sourceDir(m_baseDir + "/tests/"+relPath);
+ for (uint fileno = 0; fileno < sourceDir.count(); fileno++) {
+ TQString filename = sourceDir[fileno];
+ TQString relFilename = relPath.isEmpty() ? filename : relPath+"/"+filename;
+
+ if (filename == "." || filename == ".." || ignoreFiles.contains(filename) )
+ continue;
+ int failure_type = NoFailure;
+ if ( failureFiles.contains( filename ) )
+ failure_type |= AllFailure;
+ if ( failureFiles.contains ( filename + "-render" ) )
+ failure_type |= RenderFailure;
+ if ( failureFiles.contains ( filename + "-dump.png" ) )
+ failure_type |= PaintFailure;
+ if ( failureFiles.contains ( filename + "-dom" ) )
+ failure_type |= DomFailure;
+ runTests(relFilename, false, failure_type );
+ }
+ }
+ else if (info.isFile()) {
+
+ alarm( 400 );
+
+ tdehtml::Cache::init();
+
+ TQString relativeDir = TQFileInfo(relPath).dirPath();
+ TQString filename = info.fileName();
+ m_currentBase = m_baseDir + "/tests/"+relativeDir;
+ m_currentCategory = relativeDir;
+ m_currentTest = filename;
+ m_known_failures = known_failure;
+ if ( filename.endsWith(".html") || filename.endsWith( ".htm" ) || filename.endsWith( ".xhtml" ) || filename.endsWith( ".xml" ) ) {
+ if ( relPath.startsWith( "domts/" ) && !m_runJS )
+ return true;
+ if ( relPath.startsWith( "ecma/" ) && !m_runJS )
+ return true;
+ if ( m_runHTML )
+ testStaticFile(relPath);
+ }
+ else if (filename.endsWith(".js")) {
+ if ( m_runJS )
+ testJSFile(relPath);
+ }
+ else if (mustExist) {
+ fprintf(stderr,"%s: Not a valid test file (must be .htm(l) or .js)\n",relPath.latin1());
+ return false;
+ }
+ } else if (mustExist) {
+ fprintf(stderr,"%s: Not a regular file\n",relPath.latin1());
+ return false;
+ }
+
+ return true;
+}
+
+void RegressionTest::getPartDOMOutput( TQTextStream &outputStream, KHTMLPart* part, uint indent )
+{
+ Node node = part->document();
+ while (!node.isNull()) {
+ // process
+
+ for (uint i = 0; i < indent; i++)
+ outputStream << " ";
+ outputStream << node.nodeName().string();
+
+ switch (node.nodeType()) {
+ case Node::ELEMENT_NODE: {
+ // Sort strings to ensure consistent output
+ TQStringList attrNames;
+ NamedNodeMap attrs = node.attributes();
+ for (uint a = 0; a < attrs.length(); a++)
+ attrNames.append(attrs.item(a).nodeName().string());
+ attrNames.sort();
+
+ TQStringList::iterator it;
+ Element elem(node);
+ for (it = attrNames.begin(); it != attrNames.end(); ++it) {
+ TQString name = *it;
+ TQString value = elem.getAttribute(*it).string();
+ outputStream << " " << name << "=\"" << value << "\"";
+ }
+ if ( node.handle()->id() == ID_FRAME ) {
+ outputStream << endl;
+ TQString frameName = static_cast<DOM::HTMLFrameElementImpl *>( node.handle() )->name.string();
+ KHTMLPart* frame = part->findFrame( frameName );
+ Q_ASSERT( frame );
+ if ( frame )
+ getPartDOMOutput( outputStream, frame, indent );
+ }
+ break;
+ }
+ case Node::ATTRIBUTE_NODE:
+ // Should not be present in tree
+ assert(false);
+ break;
+ case Node::TEXT_NODE:
+ outputStream << " \"" << Text(node).data().string() << "\"";
+ break;
+ case Node::CDATA_SECTION_NODE:
+ outputStream << " \"" << CDATASection(node).data().string() << "\"";
+ break;
+ case Node::ENTITY_REFERENCE_NODE:
+ break;
+ case Node::ENTITY_NODE:
+ break;
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ break;
+ case Node::COMMENT_NODE:
+ outputStream << " \"" << Comment(node).data().string() << "\"";
+ break;
+ case Node::DOCUMENT_NODE:
+ break;
+ case Node::DOCUMENT_TYPE_NODE:
+ break;
+ case Node::DOCUMENT_FRAGMENT_NODE:
+ // Should not be present in tree
+ assert(false);
+ break;
+ case Node::NOTATION_NODE:
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ outputStream << endl;
+
+ if (!node.firstChild().isNull()) {
+ node = node.firstChild();
+ indent++;
+ }
+ else if (!node.nextSibling().isNull()) {
+ node = node.nextSibling();
+ }
+ else {
+ while (!node.isNull() && node.nextSibling().isNull()) {
+ node = node.parentNode();
+ indent--;
+ }
+ if (!node.isNull())
+ node = node.nextSibling();
+ }
+ }
+}
+
+void RegressionTest::dumpRenderTree( TQTextStream &outputStream, KHTMLPart* part )
+{
+ DOM::DocumentImpl* doc = static_cast<DocumentImpl*>( part->document().handle() );
+ if ( !doc || !doc->renderer() )
+ return;
+ doc->renderer()->layer()->dump( outputStream );
+
+ // Dump frames if any
+ // Get list of names instead of frames() to sort the list alphabetically
+ TQStringList names = part->frameNames();
+ names.sort();
+ for ( TQStringList::iterator it = names.begin(); it != names.end(); ++it ) {
+ outputStream << "FRAME: " << (*it) << "\n";
+ KHTMLPart* frame = part->findFrame( (*it) );
+ Q_ASSERT( frame );
+ if ( frame )
+ dumpRenderTree( outputStream, frame );
+ }
+}
+
+TQString RegressionTest::getPartOutput( OutputType type)
+{
+ // dump out the contents of the rendering & DOM trees
+ TQString dump;
+ TQTextStream outputStream(dump,IO_WriteOnly);
+
+ if ( type == RenderTree ) {
+ dumpRenderTree( outputStream, m_part );
+ } else {
+ assert( type == DOMTree );
+ getPartDOMOutput( outputStream, m_part, 0 );
+ }
+
+ dump.replace( m_baseDir + "/tests", TQString::fromLatin1( "REGRESSION_SRCDIR" ) );
+ return dump;
+}
+
+TQImage RegressionTest::renderToImage()
+{
+ int ew = m_part->view()->contentsWidth();
+ int eh = m_part->view()->contentsHeight();
+
+ if (ew * eh > 4000 * 4000) // don't DoS us
+ return TQImage();
+
+ TQImage img( ew, eh, 32 );
+ img.fill( 0xff0000 );
+ if (!m_paintBuffer )
+ m_paintBuffer = new TQPixmap( 512, 128, -1, TQPixmap::MemoryOptim );
+
+ for ( int py = 0; py < eh; py += 128 ) {
+ for ( int px = 0; px < ew; px += 512 ) {
+ TQPainter* tp = new TQPainter;
+ tp->begin( m_paintBuffer );
+ tp->translate( -px, -py );
+ tp->fillRect(px, py, 512, 128, Qt::magenta);
+ m_part->document().handle()->renderer()->layer()->paint( tp, TQRect( px, py, 512, 128 ) );
+ tp->end();
+ delete tp;
+
+ // now fill the chunk into our image
+ TQImage chunk = m_paintBuffer->convertToImage();
+ assert( chunk.depth() == 32 );
+ for ( int y = 0; y < 128 && py + y < eh; ++y )
+ memcpy( img.scanLine( py+y ) + px*4, chunk.scanLine( y ), kMin( 512, ew-px )*4 );
+ }
+ }
+
+ assert( img.depth() == 32 );
+ return img;
+}
+
+bool RegressionTest::imageEqual( const TQImage &lhsi, const TQImage &rhsi )
+{
+ if ( lhsi.width() != rhsi.width() || lhsi.height() != rhsi.height() ) {
+ kdDebug() << "dimensions different " << lhsi.size() << " " << rhsi.size() << endl;
+ return false;
+ }
+ int w = lhsi.width();
+ int h = lhsi.height();
+ int bytes = lhsi.bytesPerLine();
+
+ for ( int y = 0; y < h; ++y )
+ {
+ QRgb* ls = ( QRgb* ) lhsi.scanLine( y );
+ QRgb* rs = ( QRgb* ) rhsi.scanLine( y );
+ if ( memcmp( ls, rs, bytes ) ) {
+ for ( int x = 0; x < w; ++x ) {
+ QRgb l = ls[x];
+ QRgb r = rs[x];
+ if ( ( abs( tqRed( l ) - tqRed(r ) ) < 20 ) &&
+ ( abs( tqGreen( l ) - tqGreen(r ) ) < 20 ) &&
+ ( abs( tqBlue( l ) - tqBlue(r ) ) < 20 ) )
+ continue;
+ kdDebug() << "pixel (" << x << ", " << y << ") is different " << TQColor( lhsi.pixel ( x, y ) ) << " " << TQColor( rhsi.pixel ( x, y ) ) << endl;
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void RegressionTest::createLink( const TQString& test, int failures )
+{
+ createMissingDirs( m_outputDir + "/" + test + "-compare.html" );
+
+ TQFile list( m_outputDir + "/links.html" );
+ list.open( IO_WriteOnly|IO_Append );
+ TQString link;
+ link = TQString( "<a href=\"%1\" target=\"content\" title=\"%2\">" )
+ .arg( test + "-compare.html" )
+ .arg( test );
+ link += m_currentTest;
+ link += "</a> [";
+ if ( failures & DomFailure )
+ link += "D";
+ if ( failures & RenderFailure )
+ link += "R";
+ if ( failures & PaintFailure )
+ link += "P";
+ link += "]<br>\n";
+ list.tqwriteBlock( link.latin1(), link.length() );
+ list.close();
+}
+
+void RegressionTest::doJavascriptReport( const TQString &test )
+{
+ TQFile compare( m_outputDir + "/" + test + "-compare.html" );
+ if ( !compare.open( IO_WriteOnly|IO_Truncate ) )
+ kdDebug() << "failed to open " << m_outputDir + "/" + test + "-compare.html" << endl;
+ TQString cl;
+ cl = TQString( "<html><head><title>%1</title>" ).arg( test );
+ cl += "<body><tt>";
+ TQString text = "\n" + m_currentOutput;
+ text.replace( '<', "&lt;" );
+ text.replace( '>', "&gt;" );
+ text.replace( TQRegExp( "\nFAILED" ), "\n<span style='color: red'>FAILED</span>" );
+ text.replace( TQRegExp( "\nFAIL" ), "\n<span style='color: red'>FAIL</span>" );
+ text.replace( TQRegExp( "\nPASSED" ), "\n<span style='color: green'>PASSED</span>" );
+ text.replace( TQRegExp( "\nPASS" ), "\n<span style='color: green'>PASS</span>" );
+ if ( text.at( 0 ) == '\n' )
+ text = text.mid( 1, text.length() );
+ text.replace( '\n', "<br>\n" );
+ cl += text;
+ cl += "</tt></body></html>";
+ compare.tqwriteBlock( cl.latin1(), cl.length() );
+ compare.close();
+}
+
+/** returns the path in a way that is relatively reachable from base.
+ * @param base base directory (must not include trailing slash)
+ * @param path directory/file to be relatively reached by base
+ * @return path with all elements replaced by .. and concerning path elements
+ * to be relatively reachable from base.
+ */
+static TQString makeRelativePath(const TQString &base, const TQString &path)
+{
+ TQString absBase = TQFileInfo(base).absFilePath();
+ TQString absPath = TQFileInfo(path).absFilePath();
+// kdDebug() << "absPath: \"" << absPath << "\"" << endl;
+// kdDebug() << "absBase: \"" << absBase << "\"" << endl;
+
+ // walk up to common ancestor directory
+ int pos = 0;
+ do {
+ pos++;
+ int newpos = absBase.find('/', pos);
+ if (newpos == -1) newpos = absBase.length();
+ TQConstString cmpPathComp(absPath.unicode() + pos, newpos - pos);
+ TQConstString cmpBaseComp(absBase.unicode() + pos, newpos - pos);
+// kdDebug() << "cmpPathComp: \"" << cmpPathComp.string() << "\"" << endl;
+// kdDebug() << "cmpBaseComp: \"" << cmpBaseComp.string() << "\"" << endl;
+// kdDebug() << "pos: " << pos << " newpos: " << newpos << endl;
+ if (cmpPathComp.string() != cmpBaseComp.string()) { pos--; break; }
+ pos = newpos;
+ } while (pos < (int)absBase.length() && pos < (int)absPath.length());
+ int basepos = pos < (int)absBase.length() ? pos + 1 : pos;
+ int pathpos = pos < (int)absPath.length() ? pos + 1 : pos;
+
+// kdDebug() << "basepos " << basepos << " pathpos " << pathpos << endl;
+
+ TQString rel;
+ {
+ TQConstString relBase(absBase.unicode() + basepos, absBase.length() - basepos);
+ TQConstString relPath(absPath.unicode() + pathpos, absPath.length() - pathpos);
+ // generate as many .. as there are path elements in relBase
+ if (relBase.string().length() > 0) {
+ for (int i = relBase.string().contains('/'); i > 0; --i)
+ rel += "../";
+ rel += "..";
+ if (relPath.string().length() > 0) rel += "/";
+ }
+ rel += relPath.string();
+ }
+ return rel;
+}
+
+void RegressionTest::doFailureReport( const TQString& test, int failures )
+{
+ if ( failures == NoFailure ) {
+ ::unlink( TQFile::encodeName( m_outputDir + "/" + test + "-compare.html" ) );
+ return;
+ }
+
+ createLink( test, failures );
+
+ if ( failures & JSFailure ) {
+ doJavascriptReport( test );
+ return; // no support for both kind
+ }
+
+ TQFile compare( m_outputDir + "/" + test + "-compare.html" );
+
+ TQString testFile = TQFileInfo(test).fileName();
+
+ TQString renderDiff;
+ TQString domDiff;
+
+ TQString relOutputDir = makeRelativePath(m_baseDir, m_outputDir);
+
+ // are blocking reads possible with TDEProcess?
+ char pwd[PATH_MAX];
+ (void) getcwd( pwd, PATH_MAX );
+ chdir( TQFile::encodeName( m_baseDir ) );
+
+ if ( failures & RenderFailure ) {
+ renderDiff += "<pre>";
+ FILE *pipe = popen( TQString::fromLatin1( "diff -u baseline/%1-render %3/%2-render" )
+ .arg ( test, test, relOutputDir ).latin1(), "r" );
+ TQTextIStream *is = new TQTextIStream( pipe );
+ for ( int line = 0; line < 100 && !is->eof(); ++line ) {
+ TQString line = is->readLine();
+ line = line.replace( '<', "&lt;" );
+ line = line.replace( '>', "&gt;" );
+ renderDiff += line + "\n";
+ }
+ delete is;
+ pclose( pipe );
+ renderDiff += "</pre>";
+ }
+
+ if ( failures & DomFailure ) {
+ domDiff += "<pre>";
+ FILE *pipe = popen( TQString::fromLatin1( "diff -u baseline/%1-dom %3/%2-dom" )
+ .arg ( test, test, relOutputDir ).latin1(), "r" );
+ TQTextIStream *is = new TQTextIStream( pipe );
+ for ( int line = 0; line < 100 && !is->eof(); ++line ) {
+ TQString line = is->readLine();
+ line = line.replace( '<', "&lt;" );
+ line = line.replace( '>', "&gt;" );
+ domDiff += line + "\n";
+ }
+ delete is;
+ pclose( pipe );
+ domDiff += "</pre>";
+ }
+
+ chdir( pwd );
+
+ // create a relative path so that it works via web as well. ugly
+ TQString relpath = makeRelativePath(m_outputDir + "/"
+ + TQFileInfo(test).dirPath(), m_baseDir);
+
+ compare.open( IO_WriteOnly|IO_Truncate );
+ TQString cl;
+ cl = TQString( "<html><head><title>%1</title>" ).arg( test );
+ cl += TQString( "<script>\n"
+ "var pics = new Array();\n"
+ "pics[0]=new Image();\n"
+ "pics[0].src = '%1';\n"
+ "pics[1]=new Image();\n"
+ "pics[1].src = '%2';\n"
+ "var doflicker = 1;\n"
+ "var t = 1;\n"
+ "var lastb=0;\n" )
+ .arg( relpath+"/baseline/"+test+"-dump.png" )
+ .arg( testFile+"-dump.png" );
+ cl += TQString( "function toggleVisible(visible) {\n"
+ " document.getElementById('render').style.visibility= visible == 'render' ? 'visible' : 'hidden';\n"
+ " document.getElementById('image').style.visibility= visible == 'image' ? 'visible' : 'hidden';\n"
+ " document.getElementById('dom').style.visibility= visible == 'dom' ? 'visible' : 'hidden';\n"
+ "}\n"
+ "function show() { document.getElementById('image').src = pics[t].src; "
+ "document.getElementById('image').style.borderColor = t && !doflicker ? 'red' : 'gray';\n"
+ "toggleVisible('image');\n"
+ "}" );
+ cl += TQString ( "function runSlideShow(){\n"
+ " document.getElementById('image').src = pics[t].src;\n"
+ " if (doflicker)\n"
+ " t = 1 - t;\n"
+ " setTimeout('runSlideShow()', 200);\n"
+ "}\n"
+ "function m(b) { if (b == lastb) return; document.getElementById('b'+b).className='buttondown';\n"
+ " var e = document.getElementById('b'+lastb);\n"
+ " if(e) e.className='button';\n"
+ " lastb = b;\n"
+ "}\n"
+ "function showRender() { doflicker=0;toggleVisible('render')\n"
+ "}\n"
+ "function showDom() { doflicker=0;toggleVisible('dom')\n"
+ "}\n"
+ "</script>\n");
+
+ cl += TQString ("<style>\n"
+ ".buttondown { cursor: pointer; padding: 0px 20px; color: white; background-color: blue; border: inset blue 2px;}\n"
+ ".button { cursor: pointer; padding: 0px 20px; color: black; background-color: white; border: outset blue 2px;}\n"
+ ".diff { position: absolute; left: 10px; top: 100px; visibility: hidden; border: 1px black solid; background-color: white; color: black; /* width: 800; height: 600; overflow: scroll; */ }\n"
+ "</style>\n" );
+
+ if ( failures & PaintFailure )
+ cl += TQString( "<body onload=\"m(1); show(); runSlideShow();\"" );
+ else if ( failures & RenderFailure )
+ cl += TQString( "<body onload=\"m(4); toggleVisible('render');\"" );
+ else
+ cl += TQString( "<body onload=\"m(5); toggleVisible('dom');\"" );
+ cl += TQString(" text=black bgcolor=gray>\n<h1>%3</h1>\n" ).arg( test );
+ if ( failures & PaintFailure )
+ cl += TQString ( "<span id='b1' class='buttondown' onclick=\"doflicker=1;show();m(1)\">FLICKER</span>&nbsp;\n"
+ "<span id='b2' class='button' onclick=\"doflicker=0;t=0;show();m(2)\">BASE</span>&nbsp;\n"
+ "<span id='b3' class='button' onclick=\"doflicker=0;t=1;show();m(3)\">OUT</span>&nbsp;\n" );
+ if ( renderDiff.length() )
+ cl += "<span id='b4' class='button' onclick='showRender();m(4)'>R-DIFF</span>&nbsp;\n";
+ if ( domDiff.length() )
+ cl += "<span id='b5' class='button' onclick='showDom();m(5);'>D-DIFF</span>&nbsp;\n";
+ // The test file always exists - except for checkOutput called from *.js files
+ if ( TQFile::exists( m_baseDir + "/tests/"+ test ) )
+ cl += TQString( "<a class=button href=\"%1\">HTML</a>&nbsp;" )
+ .arg( relpath+"/tests/"+test );
+
+ cl += TQString( "<hr>"
+ "<img style='border: solid 5px gray' src=\"%1\" id='image'>" )
+ .arg( relpath+"/baseline/"+test+"-dump.png" );
+
+ cl += "<div id='render' class='diff'>" + renderDiff + "</div>";
+ cl += "<div id='dom' class='diff'>" + domDiff + "</div>";
+
+ cl += "</body></html>";
+ compare.tqwriteBlock( cl.latin1(), cl.length() );
+ compare.close();
+}
+
+void RegressionTest::testStaticFile(const TQString & filename)
+{
+ tqApp->mainWidget()->resize( 800, 600); // restore size
+
+ // Set arguments
+ KParts::URLArgs args;
+ if (filename.endsWith(".html") || filename.endsWith(".htm")) args.serviceType = "text/html";
+ else if (filename.endsWith(".xhtml")) args.serviceType = "application/xhtml+xml";
+ else if (filename.endsWith(".xml")) args.serviceType = "text/xml";
+ m_part->browserExtension()->setURLArgs(args);
+ // load page
+ KURL url;
+ url.setProtocol("file");
+ url.setPath(TQFileInfo(m_baseDir + "/tests/"+filename).absFilePath());
+ PartMonitor pm(m_part);
+ m_part->openURL(url);
+ pm.waitForCompletion();
+ m_part->closeURL();
+
+ if ( filename.startsWith( "domts/" ) ) {
+ TQString functionname;
+
+ KJS::Completion comp = m_part->jScriptInterpreter()->evaluate("exposeTestFunctionNames();");
+ /*
+ * Error handling
+ */
+ KJS::ExecState *exec = m_part->jScriptInterpreter()->globalExec();
+ if ( comp.complType() == ReturnValue || comp.complType() == Normal )
+ {
+ if (comp.value().isValid() && comp.value().isA(ObjectType) &&
+ (Object::dynamicCast(comp.value()).className() == "Array" ) )
+ {
+ Object argArrayObj = Object::dynamicCast(comp.value());
+ unsigned int length = argArrayObj.
+ get(exec,lengthPropertyName).
+ toUInt32(exec);
+ if ( length == 1 )
+ functionname = argArrayObj.get(exec, 0).toString(exec).qstring();
+ }
+ }
+ if ( functionname.isNull() ) {
+ kdDebug() << "DOM " << filename << " doesn't expose 1 function name - ignoring" << endl;
+ return;
+ }
+
+ KJS::Completion comp2 = m_part->jScriptInterpreter()->evaluate("setUpPage(); " + functionname + "();" );
+ bool success = ( comp2.complType() == ReturnValue || comp2.complType() == Normal );
+ TQString description = "DOMTS";
+ if ( comp2.complType() == Throw ) {
+ KJS::Value val = comp2.value();
+ KJS::Object obj = Object::dynamicCast(val);
+ if ( obj.isValid() && obj.hasProperty( exec, "jsUnitMessage" ) )
+ description = obj.get( exec, "jsUnitMessage" ).toString( exec ).qstring();
+ else
+ description = comp2.value().toString( exec ).qstring();
+ }
+ reportResult( success, description );
+
+ if (!success && !m_known_failures)
+ doFailureReport( filename, JSFailure );
+ return;
+ }
+
+ int back_known_failures = m_known_failures;
+
+ if ( m_genOutput ) {
+ if ( m_known_failures & DomFailure)
+ m_known_failures = AllFailure;
+ reportResult( checkOutput(filename+"-dom"), "DOM" );
+ if ( m_known_failures & RenderFailure )
+ m_known_failures = AllFailure;
+ reportResult( checkOutput(filename+"-render"), "RENDER" );
+ if ( m_known_failures & PaintFailure )
+ m_known_failures = AllFailure;
+ renderToImage().save(m_baseDir + "/baseline/" + filename + "-dump.png","PNG", 60);
+ printf("Generated %s\n", TQString( m_baseDir + "/baseline/" + filename + "-dump.png" ).latin1() );
+ reportResult( true, "PAINT" );
+ } else {
+ int failures = NoFailure;
+
+ // compare with output file
+ if ( m_known_failures & DomFailure)
+ m_known_failures = AllFailure;
+ if ( !reportResult( checkOutput(filename+"-dom"), "DOM" ) )
+ failures |= DomFailure;
+
+ if ( m_known_failures & RenderFailure )
+ m_known_failures = AllFailure;
+ if ( !reportResult( checkOutput(filename+"-render"), "RENDER" ) )
+ failures |= RenderFailure;
+
+ if ( m_known_failures & PaintFailure )
+ m_known_failures = AllFailure;
+ if (!reportResult( checkPaintdump(filename), "PAINT") )
+ failures |= PaintFailure;
+
+ doFailureReport(filename, failures );
+ }
+
+ m_known_failures = back_known_failures;
+}
+
+void RegressionTest::evalJS( ScriptInterpreter &interp, const TQString &filename, bool report_result )
+{
+ TQString fullSourceName = filename;
+ TQFile sourceFile(fullSourceName);
+
+ if (!sourceFile.open(IO_ReadOnly)) {
+ fprintf(stderr,"Error reading file %s\n",fullSourceName.latin1());
+ exit(1);
+ }
+
+ TQTextStream stream ( &sourceFile );
+ stream.setEncoding( TQTextStream::UnicodeUTF8 );
+ TQString code = stream.read();
+ sourceFile.close();
+
+ saw_failure = false;
+ ignore_errors = false;
+ Completion c = interp.evaluate(UString( code ) );
+
+ if ( report_result && !ignore_errors) {
+ bool expected_failure = filename.endsWith( "-n.js" );
+ if (c.complType() == Throw) {
+ TQString errmsg = c.value().toString(interp.globalExec()).qstring();
+ if ( !expected_failure ) {
+ printf( "ERROR: %s (%s)\n",filename.latin1(), errmsg.latin1());
+ m_errors++;
+ } else {
+ reportResult( true, TQString( "Expected Failure: %1" ).arg( errmsg ) );
+ }
+ } else if ( saw_failure ) {
+ if ( !expected_failure )
+ doFailureReport( m_currentCategory + "/" + m_currentTest, JSFailure );
+ reportResult( expected_failure, "saw 'failed!'" );
+ } else {
+ reportResult( !expected_failure, "passed" );
+ }
+ }
+}
+
+class GlobalImp : public ObjectImp {
+public:
+ virtual UString className() const { return "global"; }
+};
+
+void RegressionTest::testJSFile(const TQString & filename )
+{
+ tqApp->mainWidget()->resize( 800, 600); // restore size
+
+ // create interpreter
+ // note: this is different from the interpreter used by the part,
+ // it contains regression test-specific objects & functions
+ Object global(new GlobalImp());
+ tdehtml::ChildFrame frame;
+ frame.m_part = m_part;
+ ScriptInterpreter interp(global,&frame);
+ ExecState *exec = interp.globalExec();
+
+ global.put(exec, "part", Object(new KHTMLPartObject(exec,m_part)));
+ global.put(exec, "regtest", Object(new RegTestObject(exec,this)));
+ global.put(exec, "debug", Object(new RegTestFunction(exec,this,RegTestFunction::Print,1) ) );
+ global.put(exec, "print", Object(new RegTestFunction(exec,this,RegTestFunction::Print,1) ) );
+
+ TQStringList dirs = TQStringList::split( '/', filename );
+ // NOTE: the basename is of little interest here, but the last basedir change
+ // isn't taken in account
+ TQString basedir = m_baseDir + "/tests/";
+ for ( TQStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it )
+ {
+ if ( ! ::access( TQFile::encodeName( basedir + "shell.js" ), R_OK ) )
+ evalJS( interp, basedir + "shell.js", false );
+ basedir += *it + "/";
+ }
+ evalJS( interp, m_baseDir + "/tests/"+ filename, true );
+}
+
+RegressionTest::CheckResult RegressionTest::checkPaintdump(const TQString &filename)
+{
+ TQString againstFilename( filename + "-dump.png" );
+ TQString absFilename = TQFileInfo(m_baseDir + "/baseline/" + againstFilename).absFilePath();
+ if ( svnIgnored( absFilename ) ) {
+ m_known_failures = NoFailure;
+ return Ignored;
+ }
+ CheckResult result = Failure;
+
+ TQImage baseline;
+ baseline.load( absFilename, "PNG");
+ TQImage output = renderToImage();
+ if ( !imageEqual( baseline, output ) ) {
+ TQString outputFilename = m_outputDir + "/" + againstFilename;
+ createMissingDirs(outputFilename );
+
+ bool kf = false;
+ if ( m_known_failures & AllFailure )
+ kf = true;
+ else if ( m_known_failures & PaintFailure )
+ kf = true;
+ if ( kf )
+ outputFilename += "-KF";
+
+ output.save(outputFilename, "PNG", 60);
+ }
+ else {
+ ::unlink( TQFile::encodeName( m_outputDir + "/" + againstFilename ) );
+ result = Success;
+ }
+ return result;
+}
+
+RegressionTest::CheckResult RegressionTest::checkOutput(const TQString &againstFilename)
+{
+ TQString absFilename = TQFileInfo(m_baseDir + "/baseline/" + againstFilename).absFilePath();
+ if ( svnIgnored( absFilename ) ) {
+ m_known_failures = NoFailure;
+ return Ignored;
+ }
+
+ bool domOut = againstFilename.endsWith( "-dom" );
+ TQString data = getPartOutput( domOut ? DOMTree : RenderTree );
+ data.remove( char( 13 ) );
+
+ CheckResult result = Success;
+
+ // compare result to existing file
+ TQString outputFilename = TQFileInfo(m_outputDir + "/" + againstFilename).absFilePath();
+ bool kf = false;
+ if ( m_known_failures & AllFailure )
+ kf = true;
+ else if ( domOut && ( m_known_failures & DomFailure ) )
+ kf = true;
+ else if ( !domOut && ( m_known_failures & RenderFailure ) )
+ kf = true;
+ if ( kf )
+ outputFilename += "-KF";
+
+ if ( m_genOutput )
+ outputFilename = absFilename;
+
+ TQFile file(absFilename);
+ if (file.open(IO_ReadOnly)) {
+ TQTextStream stream ( &file );
+ stream.setEncoding( TQTextStream::UnicodeUTF8 );
+
+ TQString fileData = stream.read();
+
+ result = ( fileData == data ) ? Success : Failure;
+ if ( !m_genOutput && result == Success ) {
+ ::unlink( TQFile::encodeName( outputFilename ) );
+ return Success;
+ }
+ }
+
+ // generate result file
+ createMissingDirs( outputFilename );
+ TQFile file2(outputFilename);
+ if (!file2.open(IO_WriteOnly)) {
+ fprintf(stderr,"Error writing to file %s\n",outputFilename.latin1());
+ exit(1);
+ }
+
+ TQTextStream stream2(&file2);
+ stream2.setEncoding( TQTextStream::UnicodeUTF8 );
+ stream2 << data;
+ if ( m_genOutput )
+ printf("Generated %s\n", outputFilename.latin1());
+
+ return result;
+}
+
+bool RegressionTest::reportResult(CheckResult result, const TQString & description)
+{
+ if ( result == Ignored ) {
+ //printf("IGNORED: ");
+ //printDescription( description );
+ return true; // no error
+ } else
+ return reportResult( result == Success, description );
+}
+
+bool RegressionTest::reportResult(bool passed, const TQString & description)
+{
+ if (m_genOutput)
+ return true;
+
+ if (passed) {
+ if ( m_known_failures & AllFailure ) {
+ printf("PASS (unexpected!): ");
+ m_passes_fail++;
+ } else {
+ printf("PASS: ");
+ m_passes_work++;
+ }
+ }
+ else {
+ if ( m_known_failures & AllFailure ) {
+ printf("FAIL (known): ");
+ m_failures_fail++;
+ passed = true; // we knew about it
+ } else {
+ printf("FAIL: ");
+ m_failures_work++;
+ }
+ }
+
+ printDescription( description );
+ return passed;
+}
+
+void RegressionTest::printDescription(const TQString& description)
+{
+ if (!m_currentCategory.isEmpty())
+ printf("%s/", m_currentCategory.latin1());
+
+ printf("%s", m_currentTest.latin1());
+
+ if (!description.isEmpty()) {
+ TQString desc = description;
+ desc.replace( '\n', ' ' );
+ printf(" [%s]", desc.latin1());
+ }
+
+ printf("\n");
+ fflush(stdout);
+}
+
+void RegressionTest::createMissingDirs(const TQString & filename)
+{
+ TQFileInfo dif(filename);
+ TQFileInfo dirInfo( dif.dirPath() );
+ if (dirInfo.exists())
+ return;
+
+ TQStringList pathComponents;
+ TQFileInfo parentDir = dirInfo;
+ pathComponents.prepend(parentDir.absFilePath());
+ while (!parentDir.exists()) {
+ TQString parentPath = parentDir.absFilePath();
+ int slashPos = parentPath.findRev('/');
+ if (slashPos < 0)
+ break;
+ parentPath = parentPath.left(slashPos);
+ pathComponents.prepend(parentPath);
+ parentDir = TQFileInfo(parentPath);
+ }
+ for (uint pathno = 1; pathno < pathComponents.count(); pathno++) {
+ if (!TQFileInfo(pathComponents[pathno]).exists() &&
+ !TQDir(pathComponents[pathno-1]).mkdir(pathComponents[pathno])) {
+ fprintf(stderr,"Error creating directory %s\n",pathComponents[pathno].latin1());
+ exit(1);
+ }
+ }
+}
+
+void RegressionTest::slotOpenURL(const KURL &url, const KParts::URLArgs &args)
+{
+ m_part->browserExtension()->setURLArgs( args );
+
+ PartMonitor pm(m_part);
+ m_part->openURL(url);
+ pm.waitForCompletion();
+}
+
+bool RegressionTest::svnIgnored( const TQString &filename )
+{
+ TQFileInfo fi( filename );
+ TQString ignoreFilename = fi.dirPath() + "/svnignore";
+ TQFile ignoreFile(ignoreFilename);
+ if (!ignoreFile.open(IO_ReadOnly))
+ return false;
+
+ TQTextStream ignoreStream(&ignoreFile);
+ TQString line;
+ while (!(line = ignoreStream.readLine()).isNull()) {
+ if ( line == fi.fileName() )
+ return true;
+ }
+ ignoreFile.close();
+ return false;
+}
+
+void RegressionTest::resizeTopLevelWidget( int w, int h )
+{
+ tqApp->mainWidget()->resize( w, h );
+ // Since we're not visible, this doesn't have an immediate effect, TQWidget posts the event
+ TQApplication::sendPostedEvents( 0, TQEvent::Resize );
+}
+
+#include "test_regression.moc"
diff --git a/tdehtml/test_regression.h b/tdehtml/test_regression.h
new file mode 100644
index 000000000..74f56cc72
--- /dev/null
+++ b/tdehtml/test_regression.h
@@ -0,0 +1,194 @@
+/**
+ * This file is part of the KDE project
+ *
+ * Copyright (C) 2001,2003 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef TEST_REGRESSION_H
+#define TEST_REGRESSION_H
+
+#include <tdehtml_part.h>
+#include <kurl.h>
+#include <tqobject.h>
+#include <kjs/ustring.h>
+#include <kjs/object.h>
+#include <kjs/interpreter.h>
+
+class RegressionTest;
+class TQTimer;
+
+/**
+ * @internal
+ */
+class PartMonitor : public TQObject
+{
+ Q_OBJECT
+public:
+ PartMonitor(KHTMLPart *_part);
+ ~PartMonitor();
+ void waitForCompletion();
+ static PartMonitor* sm_highestMonitor;
+ bool m_completed;
+ KHTMLPart *m_part;
+ int m_timer_waits;
+ TQTimer *m_timeout_timer;
+public slots:
+ void partCompleted();
+ void timeout();
+ void finishTimers();
+};
+
+/**
+ * @internal
+ */
+class RegTestObject : public KJS::ObjectImp
+{
+public:
+ RegTestObject(KJS::ExecState *exec, RegressionTest *_regTest);
+
+private:
+ RegressionTest *m_regTest;
+};
+
+/**
+ * @internal
+ */
+class RegTestFunction : public KJS::ObjectImp
+{
+public:
+ RegTestFunction(KJS::ExecState *exec, RegressionTest *_regTest, int _id, int length);
+
+ bool implementsCall() const;
+ KJS::Value call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args);
+
+ enum { Print, ReportResult, CheckOutput, Quit };
+
+private:
+ RegressionTest *m_regTest;
+ int id;
+};
+
+/**
+ * @internal
+ */
+class KHTMLPartObject : public KJS::ObjectImp
+{
+public:
+ KHTMLPartObject(KJS::ExecState *exec, KHTMLPart *_part);
+
+ virtual KJS::Value get(KJS::ExecState *exec, const KJS::Identifier &propertyName) const;
+
+private:
+ KHTMLPart *m_part;
+};
+
+/**
+ * @internal
+ */
+class KHTMLPartFunction : public KJS::ObjectImp
+{
+public:
+ KHTMLPartFunction(KJS::ExecState *exec, KHTMLPart *_part, int _id, int length);
+
+ bool implementsCall() const;
+ KJS::Value call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args);
+
+ enum { OpenPage, OpenPageAsUrl, Begin, Write, End, ExecuteScript, ProcessEvents };
+private:
+ KHTMLPart *m_part;
+ int id;
+};
+
+namespace KJS {
+class ScriptInterpreter;
+}
+
+/**
+ * @internal
+ */
+class RegressionTest : public TQObject
+{
+ Q_OBJECT
+public:
+
+ RegressionTest(KHTMLPart *part, const TQString &baseDir, const TQString &outputDir,
+ bool _genOutput, bool runJS, bool runHTML);
+ ~RegressionTest();
+
+ enum OutputType { DOMTree, RenderTree };
+ TQString getPartOutput( OutputType type );
+ void getPartDOMOutput( TQTextStream &outputStream, KHTMLPart* part, uint indent );
+ void dumpRenderTree( TQTextStream &outputStream, KHTMLPart* part );
+ void testStaticFile(const TQString& filename);
+ void testJSFile(const TQString& filename);
+ enum CheckResult { Failure = 0, Success = 1, Ignored = 2 };
+ CheckResult checkOutput(const TQString& againstFilename);
+ CheckResult checkPaintdump( const TQString& againstFilename);
+ enum FailureType { NoFailure = 0, AllFailure = 1, RenderFailure = 2, DomFailure = 4, PaintFailure = 8, JSFailure = 16};
+ bool runTests(TQString relPath = TQString::null, bool mustExist = false, int known_failure = NoFailure);
+ bool reportResult( bool passed, const TQString & description = TQString::null );
+ bool reportResult(CheckResult result, const TQString & description = TQString::null );
+ void createMissingDirs(const TQString &path);
+
+ TQImage renderToImage();
+ bool imageEqual( const TQImage &lhs, const TQImage &rhs );
+ void createLink( const TQString& test, int failures );
+ void doJavascriptReport( const TQString &test );
+ void doFailureReport( const TQString& test, int failures );
+
+ KHTMLPart *m_part;
+ TQString m_baseDir;
+ TQString m_outputDir;
+ bool m_genOutput;
+ TQString m_currentBase;
+
+ TQString m_currentOutput;
+ TQString m_currentCategory;
+ TQString m_currentTest;
+ TQPixmap* m_paintBuffer;
+
+ bool m_getOutput;
+ bool m_runJS;
+ bool m_runHTML;
+ int m_passes_work;
+ int m_passes_fail;
+ int m_failures_work;
+ int m_failures_fail;
+ int m_errors;
+ bool saw_failure;
+ bool ignore_errors;
+ int m_known_failures;
+
+ static RegressionTest *curr;
+
+private:
+ void printDescription(const TQString& description);
+
+ static bool svnIgnored( const TQString &filename );
+
+private:
+ void evalJS( KJS::ScriptInterpreter &interp, const TQString &filename, bool report ); // used by testJS
+
+private slots:
+ void slotOpenURL(const KURL &url, const KParts::URLArgs &args);
+ void resizeTopLevelWidget( int, int );
+
+};
+
+#endif
diff --git a/tdehtml/test_regression_fontoverload.cpp b/tdehtml/test_regression_fontoverload.cpp
new file mode 100644
index 000000000..f3102b20b
--- /dev/null
+++ b/tdehtml/test_regression_fontoverload.cpp
@@ -0,0 +1,384 @@
+/**
+ * This file is part of the KDE project
+ *
+ * Copyright (C) 2003 Stephan Kulow (coolo@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 "ecma/kjs_proxy.h"
+#define QT_NO_XRANDR 1
+#define QT_NO_XFTFREETYPE 1
+#include <private/qfontengine_p.h>
+#include <tqfontdatabase.h>
+#include <tqfont.h>
+#include <tqpainter.h>
+#include "tdehtml_settings.h"
+#include <tqwidget.h>
+#include <assert.h>
+
+class QFakeFontEngine : public QFontEngineXLFD
+{
+ bool ahem;
+ int pixS;
+public:
+ QFakeFontEngine( XFontStruct *fs, const char *name, int size );
+ ~QFakeFontEngine();
+
+ int leading() const
+ {
+ if (ahem)
+ return 0;
+ else
+ return QFontEngineXLFD::leading();
+ }
+
+ void draw( TQPainter *p, int x, int y, const QTextEngine *engine, const QScriptItem *si, int textFlags )
+ {
+ //Sometimes X misrounds stuff for larger ahem, so we have to do it ourselves.
+ if (!ahem || (si->analysis.bidiLevel & 1) ) //We're fine if not ahem or bidi.
+ return QFontEngineXLFD::draw(p, x, y, engine, si, textFlags);
+
+ glyph_t* gl = engine->glyphs(si);
+ for (int pos = 0; pos < si->num_glyphs; ++pos)
+ {
+ switch (gl[pos])
+ {
+ case ' ':
+ break;
+ case 'p':
+ //Below the baseline, including it
+ p->fillRect(x, y, pixS, descent() + 1, p->pen().color());
+ break;
+ case 0xC9:
+ //Above the baseline
+ p->fillRect(x, y - ascent(), pixS, ascent(), p->pen().color());
+ break;
+ default:
+ //Whole block
+ p->fillRect(x, y - ascent(), pixS, pixS, p->pen().color());
+ }
+ x += pixS;
+ }
+ }
+
+#if 0
+ virtual glyph_metrics_t boundingBox( const glyph_t *glyphs,
+ const advance_t *advances, const qoffset_t *offsets, int numGlyphs );
+ glyph_metrics_t boundingBox( glyph_t glyph );
+
+ QFontEngine::Error stringToCMap( const TQChar *, int len, glyph_t *glyphs, advance_t *advances, int *nglyphs, bool ) const;
+
+ int ascent() const;
+ int descent() const;
+ int leading() const;
+ int maxCharWidth() const;
+ int minLeftBearing() const { return 0; }
+ int minRightBearing() const { return 0; }
+ int cmap() const;
+#endif
+ bool canRender( const TQChar *string, int len );
+};
+
+QFakeFontEngine::QFakeFontEngine( XFontStruct *fs, const char *name, int size )
+ : QFontEngineXLFD( fs, name, 0)
+{
+ pixS = size;
+ ahem = TQString::fromLatin1(name).contains("ahem");
+}
+
+QFakeFontEngine::~QFakeFontEngine()
+{
+}
+#if 0
+QFontEngine::Error QFakeFontEngine::stringToCMap( const TQChar *str, int len, glyph_t *glyphs, advance_t *advances, int *nglyphs, bool mirrored) const
+{
+ QFontEngine::Error ret = QFontEngineXLFD::stringToCMap( str, len, glyphs, advances, nglyphs, mirrored );
+
+ if ( ret != NoError )
+ return ret;
+
+ *nglyphs = len;
+
+ if ( advances ) {
+ for ( int i = 0; i < len; i++ )
+ *(advances++) = _size;
+ }
+ return NoError;
+}
+
+glyph_metrics_t QFakeFontEngine::boundingBox( const glyph_t *, const advance_t *, const qoffset_t *, int numGlyphs )
+{
+ glyph_metrics_t overall;
+ overall.x = overall.y = 0;
+ overall.width = _size*numGlyphs;
+ overall.height = _size;
+ overall.xoff = overall.width;
+ overall.yoff = 0;
+ return overall;
+}
+
+glyph_metrics_t QFakeFontEngine::boundingBox( glyph_t )
+{
+ return glyph_metrics_t( 0, _size, _size, _size, _size, 0 );
+}
+
+int QFakeFontEngine::ascent() const
+{
+ return _size;
+}
+
+int QFakeFontEngine::descent() const
+{
+ return 0;
+}
+
+int QFakeFontEngine::leading() const
+{
+ // the original uses double and creates quite random results depending
+ // on the compiler flags
+ int l = ( _size * 15 + 50) / 100;
+ // only valid on i386 without -O2 assert(l == int(tqRound(_size * 0.15)));
+ return (l > 0) ? l : 1;
+}
+
+int QFakeFontEngine::maxCharWidth() const
+{
+ return _size;
+}
+
+int QFakeFontEngine::cmap() const
+{
+ return -1;
+}
+
+#endif
+bool QFakeFontEngine::canRender( const TQChar *, int )
+{
+ return true;
+}
+
+static TQString courier_pickxlfd( int pixelsize, bool italic, bool bold )
+{
+ if ( pixelsize >= 24 )
+ pixelsize = 24;
+ else if ( pixelsize >= 18 )
+ pixelsize = 18;
+ else if ( pixelsize >= 12 )
+ pixelsize = 12;
+ else
+ pixelsize = 10;
+
+ return TQString( "-adobe-courier-%1-%2-normal--%3-*-75-75-m-*-iso10646-1" ).arg( bold ? "bold" : "medium" ).arg( italic ? "o" : "r" ).arg( pixelsize );
+}
+
+static TQString ahem_pickxlfd( int pixelsize )
+{
+ return TQString( "-misc-ahem-medium-r-normal--%1-*-100-100-c-*-iso10646-1" ).arg( pixelsize );
+}
+
+static TQString helv_pickxlfd( int pixelsize, bool italic, bool bold )
+{
+ if ( pixelsize >= 24 )
+ pixelsize = 24;
+ else if ( pixelsize >= 18 )
+ pixelsize = 18;
+ else if ( pixelsize >= 12 )
+ pixelsize = 12;
+ else
+ pixelsize = 10;
+
+ return TQString( "-adobe-helvetica-%1-%2-normal--%3-*-75-75-p-*-iso10646-1" ).arg( bold ? "bold" : "medium" ).arg( italic ? "o" : "r" ).arg( pixelsize );
+
+}
+
+KDE_EXPORT QFontEngine *
+TQFontDatabase::findFont( TQFont::Script script, const QFontPrivate *fp,
+ const QFontDef &request, int )
+{
+ TQString xlfd;
+ TQString family = request.family.lower();
+ if ( family == "adobe courier" || family == "courier" || family == "fixed" ) {
+ xlfd = courier_pickxlfd( request.pixelSize, request.italic, request.weight > 50 );
+ }
+ else if ( family == "times new roman" || family == "times" )
+ xlfd = "-adobe-times-medium-r-normal--8-80-75-75-p-44-iso10646-1";
+ else if ( family == "ahem" )
+ xlfd = ahem_pickxlfd( request.pixelSize );
+ else
+ xlfd = helv_pickxlfd( request.pixelSize, request.italic, request.weight > 50 );
+
+ QFontEngine *fe = 0;
+
+ XFontStruct *xfs;
+ xfs = XLoadQueryFont(TQPaintDevice::x11AppDisplay(), xlfd.latin1() );
+ if (!xfs) // as long as you don't do screenshots, it's maybe fine
+ tqFatal("we need some fonts. So make sure you have %s installed.", xlfd.latin1());
+
+ unsigned long value;
+ if ( !XGetFontProperty( xfs, XA_FONT, &value ) )
+ return 0;
+
+ char *n = XGetAtomName( TQPaintDevice::x11AppDisplay(), value );
+ xlfd = n;
+ if ( n )
+ XFree( n );
+
+ fe = new QFakeFontEngine( xfs, xlfd.latin1(),request.pixelSize );
+
+ // tqDebug("fe %s ascent %d descent %d minLeftBearing %d leading %d maxCharWidth %d minRightBearing %d", xlfd.latin1(), fe->ascent(), fe->descent(), fe->minLeftBearing(), fe->leading(), fe->maxCharWidth(), fe->minRightBearing());
+
+ // fe->setScale( scale );
+
+ QFontCache::Key key( request, script, fp->screen
+#if TQT_VERSION >= 0x030308
+ , fp->paintdevice
+#endif
+ );
+ QFontCache::instance->insertEngine( key, fe );
+ return fe;
+}
+
+KDE_EXPORT bool TQFontDatabase::isBitmapScalable( const TQString &,
+ const TQString &) const
+{
+ return true;
+}
+
+KDE_EXPORT bool TQFontDatabase::isSmoothlyScalable( const TQString &,
+ const TQString &) const
+{
+ return true;
+}
+
+const TQString &KHTMLSettings::availableFamilies()
+{
+ if ( !avFamilies ) {
+ avFamilies = new TQString;
+ *avFamilies = ",Adobe Courier,Arial,Comic Sans MS,Courier,Helvetica,Times,Times New Roman,Utopia,Fixed,Ahem,";
+ }
+
+ return *avFamilies;
+}
+
+bool KHTMLSettings::unfinishedImageFrame() const
+{
+ return false;
+}
+
+KDE_EXPORT int TQPaintDevice::x11AppDpiY( int )
+{
+ return 100;
+}
+
+KDE_EXPORT int TQPaintDevice::x11AppDpiX( int )
+{
+ return 100;
+}
+
+KDE_EXPORT void TQFont::insertSubstitution(const TQString &,
+ const TQString &)
+{
+}
+
+KDE_EXPORT void TQFont::insertSubstitutions(const TQString &,
+ const TQStringList &)
+{
+}
+
+#include <kprotocolinfo.h>
+bool KProtocolInfo::isKnownProtocol( const TQString& _protocol )
+{
+ return ( _protocol == "file" );
+}
+
+#include <kprotocolinfofactory.h>
+
+TQString KProtocolInfo::exec( const TQString& _protocol )
+{
+ if ( _protocol != "file" )
+ return TQString::null;
+
+ KProtocolInfo::Ptr prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
+ if ( !prot )
+ return TQString::null;
+
+ return prot->m_exec;
+}
+
+#include <dcopclient.h>
+
+bool DCOPClient::attach()
+{
+ return false;
+}
+
+bool DCOPClient::isAttached() const
+{
+ return false;
+}
+
+void DCOPClient::processSocketData( int )
+{
+}
+
+#include <tqapplication.h>
+#include <tqpalette.h>
+
+KDE_EXPORT void TQApplication::setPalette( const TQPalette &, bool ,
+ const char* )
+{
+ static bool done = false;
+ if (done) return;
+ TQString xlfd = ahem_pickxlfd(40);
+ XFontStruct *xfs;
+ xfs = XLoadQueryFont(TQPaintDevice::x11AppDisplay(), xlfd.latin1() );
+ if (!xfs) // as long as you don't do screenshots, it's maybe fine
+ tqFatal("We will need some fonts. So make sure you have %s installed.", xlfd.latin1());
+ XFreeFont(TQPaintDevice::x11AppDisplay(), xfs);
+ done = true;
+}
+
+#include <kapplication.h>
+void TDEApplication::dcopFailure( const TQString & )
+{
+ tqDebug( "TDEApplication::dcopFailure" );
+}
+
+#include <tdeparts/historyprovider.h>
+
+bool KParts::HistoryProvider::contains( const TQString& t ) const
+{
+ return ( t == "http://www.kde.org/" || t == "http://www.google.com/");
+}
+
+
+bool KJSCPUGuard::confirmTerminate()
+{
+ return false;
+}
+
+#include <ksslsettings.h>
+
+bool KSSLSettings::warnOnEnter() const { return false; }
+bool KSSLSettings::warnOnUnencrypted() const { return false; }
+bool KSSLSettings::warnOnLeave() const { return false; }
+
+#include <tdeparts/plugin.h>
+
+KParts::Plugin* KParts::Plugin::loadPlugin( TQObject * parent, const char* libname ) { return 0; }
+
diff --git a/tdehtml/testtdehtml.cpp b/tdehtml/testtdehtml.cpp
new file mode 100644
index 000000000..84ace61fe
--- /dev/null
+++ b/tdehtml/testtdehtml.cpp
@@ -0,0 +1,210 @@
+// program to test the new tdehtml implementation
+
+#include <stdlib.h>
+#include "decoder.h"
+#include "kapplication.h"
+#include "html_document.h"
+#include "htmltokenizer.h"
+// to be able to delete a static protected member pointer in kbrowser...
+// just for memory debugging
+#define protected public
+#include "tdehtml_part.h"
+#include "tdehtmlview.h"
+#undef protected
+#include "testtdehtml.h"
+#include "testtdehtml.moc"
+#include "misc/loader.h"
+#include <tqcursor.h>
+#include <dom_string.h>
+#include "dom/dom2_range.h"
+#include "dom/html_document.h"
+#include "dom/dom_exception.h"
+#include <stdio.h>
+#define protected public
+#include "tdehtml_factory.h"
+#undef protected
+#include "css/cssstyleselector.h"
+#include "html/html_imageimpl.h"
+#include "rendering/render_style.h"
+#include <kmainwindow.h>
+#include <kcmdlineargs.h>
+#include <kaction.h>
+#include "domtreeview.h"
+#include <kfiledialog.h>
+
+static KCmdLineOptions options[] = { { "+file", "url to open", 0 } , KCmdLineLastOption };
+
+int main(int argc, char *argv[])
+{
+
+ TDECmdLineArgs::init(argc, argv, "testtdehtml", "Testtdehtml",
+ "a basic web browser using the KHTML library", "1.0");
+ TDECmdLineArgs::addCmdLineOptions(options);
+
+ TDEApplication a;
+ TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs( );
+ if ( args->count() == 0 ) {
+ TDECmdLineArgs::usage();
+ ::exit( 1 );
+ }
+
+#ifndef __KDE_HAVE_GCC_VISIBILITY
+ KHTMLFactory *fac = new KHTMLFactory(true);
+#endif
+
+ KMainWindow *toplevel = new KMainWindow();
+ KHTMLPart *doc = new KHTMLPart( toplevel, 0, toplevel, 0, KHTMLPart::BrowserViewGUI );
+
+ Dummy *dummy = new Dummy( doc );
+ TQObject::connect( doc->browserExtension(), TQT_SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
+ dummy, TQT_SLOT( slotOpenURL( const KURL&, const KParts::URLArgs & ) ) );
+
+ TQObject::connect( doc, TQT_SIGNAL(completed()), dummy, TQT_SLOT(handleDone()) );
+
+ if (args->url(0).url().right(4).find(".xml", 0, false) == 0) {
+ KParts::URLArgs ags(doc->browserExtension()->urlArgs());
+ ags.serviceType = "text/xml";
+ doc->browserExtension()->setURLArgs(ags);
+ }
+
+ doc->openURL( args->url(0) );
+
+// DOMTreeView * dtv = new DOMTreeView(0, doc, "DomTreeView");
+// dtv->show();
+
+ toplevel->setCentralWidget( doc->widget() );
+ toplevel->resize( 800, 600);
+
+// dtv->resize(toplevel->width()/2, toplevel->height());
+
+ TQDomDocument d = doc->domDocument();
+ TQDomElement viewMenu = d.documentElement().firstChild().childNodes().item( 2 ).toElement();
+ TQDomElement e = d.createElement( "action" );
+ e.setAttribute( "name", "debugRenderTree" );
+ viewMenu.appendChild( e );
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "debugDOMTree" );
+ viewMenu.appendChild( e );
+
+
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "debugDoBenchmark" );
+ viewMenu.appendChild( e );
+
+ TQDomElement toolBar = d.documentElement().firstChild().nextSibling().toElement();
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "editable" );
+ toolBar.insertBefore( e, toolBar.firstChild() );
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "navigable" );
+ toolBar.insertBefore( e, toolBar.firstChild() );
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "reload" );
+ toolBar.insertBefore( e, toolBar.firstChild() );
+ e = d.createElement( "action" );
+ e.setAttribute( "name", "print" );
+ toolBar.insertBefore( e, toolBar.firstChild() );
+
+ (void)new KAction( "Reload", "reload", Qt::Key_F5, dummy, TQT_SLOT( reload() ), doc->actionCollection(), "reload" );
+ (void)new KAction( "Benchmark...", 0, 0, dummy, TQT_SLOT( doBenchmark() ), doc->actionCollection(), "debugDoBenchmark" );
+ KAction* kprint = new KAction( "Print", "print", 0, doc->browserExtension(), TQT_SLOT( print() ), doc->actionCollection(), "print" );
+ kprint->setEnabled(true);
+ KToggleAction *ta = new KToggleAction( "Navigable", "editclear", 0, doc->actionCollection(), "navigable" );
+ ta->setChecked(doc->isCaretMode());
+ TQWidget::connect(ta, TQT_SIGNAL(toggled(bool)), dummy, TQT_SLOT( toggleNavigable(bool) ));
+ ta = new KToggleAction( "Editable", "edit", 0, doc->actionCollection(), "editable" );
+ ta->setChecked(doc->isEditable());
+ TQWidget::connect(ta, TQT_SIGNAL(toggled(bool)), dummy, TQT_SLOT( toggleEditable(bool) ));
+ toplevel->guiFactory()->addClient( doc );
+
+ doc->setJScriptEnabled(true);
+ doc->setJavaEnabled(true);
+ doc->setPluginsEnabled( true );
+ doc->setURLCursor(TQCursor(Qt::PointingHandCursor));
+ a.setTopWidget(doc->widget());
+ TQWidget::connect(doc, TQT_SIGNAL(setWindowCaption(const TQString &)),
+ doc->widget()->topLevelWidget(), TQT_SLOT(setCaption(const TQString &)));
+ doc->widget()->show();
+ toplevel->show();
+ ((TQScrollView *)doc->widget())->viewport()->show();
+
+
+ int ret = a.exec();
+#ifndef __KDE_HAVE_GCC_VISIBILITY
+ fac->deref();
+#endif
+ return ret;
+}
+
+void Dummy::doBenchmark()
+{
+ TDEConfigGroup settings(TDEGlobal::config(), "bench");
+ results.clear();
+
+ TQString directory = KFileDialog::getExistingDirectory(settings.readPathEntry("path"), m_part->view(),
+ TQString::fromLatin1("Please select directory with tests"));
+
+ if (!directory.isEmpty()) {
+ settings.writePathEntry("path", directory);
+
+ TQDir dirListing(directory, "*.html");
+ for (int i = 0; i < dirListing.count(); ++i) {
+ filesToBenchmark.append(dirListing.absFilePath(dirListing[i]));
+ }
+ }
+
+ benchmarkRun = 0;
+
+ if (!filesToBenchmark.isEmpty())
+ nextRun();
+}
+
+const int COLD_RUNS = 2;
+const int HOT_RUNS = 5;
+
+void Dummy::nextRun()
+{
+ if (benchmarkRun == (COLD_RUNS + HOT_RUNS)) {
+ filesToBenchmark.remove(filesToBenchmark.begin());
+ benchmarkRun = 0;
+ }
+
+ if (!filesToBenchmark.isEmpty()) {
+ loadTimer.start();
+ m_part->openURL(filesToBenchmark[0]);
+ } else {
+ //Generate HTML for report.
+ m_part->begin();
+ m_part->write("<table border=1>");
+
+ for (TQMap<TQString, TQValueList<int> >::iterator i = results.begin(); i != results.end(); ++i) {
+ m_part->write("<tr><td>" + i.key() + "</td>");
+ TQValueList<int> timings = i.data();
+ int total = 0;
+ for (int pos = 0; pos < timings.size(); ++pos) {
+ int t = timings[pos];
+ if (pos < COLD_RUNS)
+ m_part->write(TQString::fromLatin1("<td>(Cold):") + TQString::number(t) + "</td>");
+ else {
+ total += t;
+ m_part->write(TQString::fromLatin1("<td><i>") + TQString::number(t) + "</i></td>");
+ }
+ }
+
+ m_part->write(TQString::fromLatin1("<td>Average:<b>") + TQString::number(double(total) / HOT_RUNS) + "</b></td>");
+
+ m_part->write("</tr>");
+ }
+
+ m_part->end();
+ }
+}
+
+void Dummy::handleDone()
+{
+ if (filesToBenchmark.isEmpty()) return;
+
+ results[filesToBenchmark[0]].append(loadTimer.elapsed());
+ ++benchmarkRun;
+ nextRun();
+}
diff --git a/tdehtml/testtdehtml.h b/tdehtml/testtdehtml.h
new file mode 100644
index 000000000..4fd76d044
--- /dev/null
+++ b/tdehtml/testtdehtml.h
@@ -0,0 +1,55 @@
+#ifndef TESTKHTML_H
+#define TESTKHTML_H
+
+#include <kdebug.h>
+#include <tqvaluelist.h>
+#include <tqdatetime.h>
+
+/**
+ * @internal
+ */
+class Dummy : public TQObject
+{
+ Q_OBJECT
+public:
+ Dummy( KHTMLPart *part ) : TQObject( part ) { m_part = part; };
+
+private slots:
+ void slotOpenURL( const KURL &url, const KParts::URLArgs &args )
+ {
+ m_part->browserExtension()->setURLArgs( args );
+ m_part->openURL( url );
+ }
+ void reload()
+ {
+ KParts::URLArgs args; args.reload = true;
+ m_part->browserExtension()->setURLArgs( args );
+ m_part->openURL( m_part->url() );
+ }
+
+ void toggleNavigable(bool s)
+ {
+ m_part->setCaretMode(s);
+ }
+
+ void toggleEditable(bool s)
+ {
+ kdDebug() << "editable: " << s << endl;
+ m_part->setEditable(s);
+ }
+
+ void doBenchmark();
+
+ void handleDone();
+
+private:
+ KHTMLPart *m_part;
+ TQValueList<TQString> filesToBenchmark;
+ TQMap<TQString, TQValueList<int> > results;
+ int benchmarkRun;
+ TQTime loadTimer;
+
+ void nextRun();
+};
+
+#endif
diff --git a/tdehtml/xml/CMakeLists.txt b/tdehtml/xml/CMakeLists.txt
new file mode 100644
index 000000000..904d8ba09
--- /dev/null
+++ b/tdehtml/xml/CMakeLists.txt
@@ -0,0 +1,43 @@
+#################################################
+#
+# (C) 2010 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${TQT_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}/kjs
+ ${CMAKE_BINARY_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/dcop
+ ${CMAKE_SOURCE_DIR}/tdehtml
+ ${CMAKE_SOURCE_DIR}/tdecore
+ ${CMAKE_SOURCE_DIR}/tdeui
+ ${CMAKE_SOURCE_DIR}/kio
+ ${CMAKE_SOURCE_DIR}/kio/kio
+ ${CMAKE_SOURCE_DIR}/tdewallet/client
+ ${CMAKE_SOURCE_DIR}/tdeutils
+)
+
+
+##### tdehtmlxml-static ############################
+
+set( target tdehtmlxml )
+
+set( ${target}_SRCS
+ dom_docimpl.cpp dom_nodeimpl.cpp dom_textimpl.cpp
+ dom_elementimpl.cpp dom_stringimpl.cpp dom2_rangeimpl.cpp
+ dom2_traversalimpl.cpp xml_tokenizer.cpp dom_xmlimpl.cpp
+ dom2_eventsimpl.cpp dom2_viewsimpl.cpp dom_restyler.cpp
+)
+
+tde_add_library( ${target} STATIC_PIC AUTOMOC
+ SOURCES ${${target}_SRCS}
+)
diff --git a/tdehtml/xml/Makefile.am b/tdehtml/xml/Makefile.am
new file mode 100644
index 000000000..257f63813
--- /dev/null
+++ b/tdehtml/xml/Makefile.am
@@ -0,0 +1,48 @@
+# 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 = libtdehtmlxml.la
+libtdehtmlxml_la_SOURCES = \
+ dom_docimpl.cpp dom_nodeimpl.cpp dom_textimpl.cpp \
+ dom_elementimpl.cpp dom_stringimpl.cpp dom2_rangeimpl.cpp \
+ dom2_traversalimpl.cpp xml_tokenizer.cpp dom_xmlimpl.cpp \
+ dom2_eventsimpl.cpp dom2_viewsimpl.cpp dom_restyler.cpp
+
+#libtdehtmlxml_la_LDFLAGS = -no-undefined
+libtdehtmlxml_la_METASOURCES = AUTO
+
+noinst_HEADERS = \
+ dom_docimpl.h dom_nodeimpl.h dom_textimpl.h \
+ dom_elementimpl.h dom_stringimpl.h dom2_rangeimpl.h \
+ dom2_traversalimpl.h xml_tokenizer.h dom_xmlimpl.h \
+ dom2_eventsimpl.h dom2_viewsimpl.h dom_restyler.h
+
+INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/kio -I$(top_srcdir)/dcop \
+ -I$(top_srcdir)/tdehtml -I$(top_srcdir) -I$(top_srcdir)/tdewallet/client \
+ -I$(top_srcdir)/tdeutils -I$(top_builddir)/kjs $(all_includes)
+
+SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/tdehtml
+
+## generate lib documentation
+srcdoc:
+ $(mkinstalldirs) $(SRCDOC_DEST)
+ kdoc -H -d $(SRCDOC_DEST) tdecore -lqt
+
diff --git a/tdehtml/xml/dom2_eventsimpl.cpp b/tdehtml/xml/dom2_eventsimpl.cpp
new file mode 100644
index 000000000..c0bb10f9a
--- /dev/null
+++ b/tdehtml/xml/dom2_eventsimpl.cpp
@@ -0,0 +1,969 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * (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 "dom/dom2_views.h"
+
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_stringimpl.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "rendering/render_layer.h"
+#include "tdehtmlview.h"
+
+#include <kdebug.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+EventImpl::EventImpl()
+{
+ m_type = 0;
+ m_canBubble = false;
+ m_cancelable = false;
+
+ m_propagationStopped = false;
+ m_defaultPrevented = false;
+ m_id = UNKNOWN_EVENT;
+ m_currentTarget = 0;
+ m_eventPhase = 0;
+ m_target = 0;
+ m_createTime = TQDateTime::currentDateTime();
+ m_defaultHandled = false;
+}
+
+EventImpl::EventImpl(EventId _id, bool canBubbleArg, bool cancelableArg)
+{
+ DOMString t = EventImpl::idToType(_id);
+ m_type = t.implementation();
+ if (m_type)
+ m_type->ref();
+ m_canBubble = canBubbleArg;
+ m_cancelable = cancelableArg;
+
+ m_propagationStopped = false;
+ m_defaultPrevented = false;
+ m_id = _id;
+ m_currentTarget = 0;
+ m_eventPhase = 0;
+ m_target = 0;
+ m_createTime = TQDateTime::currentDateTime();
+ m_defaultHandled = false;
+}
+
+EventImpl::~EventImpl()
+{
+ if (m_type)
+ m_type->deref();
+ if (m_target)
+ m_target->deref();
+}
+
+void EventImpl::setTarget(NodeImpl *_target)
+{
+ if (m_target)
+ m_target->deref();
+ m_target = _target;
+ if (m_target)
+ m_target->ref();
+}
+
+DOMTimeStamp EventImpl::timeStamp()
+{
+ TQDateTime epoch(TQDate(1970,1,1),TQTime(0,0));
+ // ### kjs does not yet support long long (?) so the value wraps around
+ return epoch.secsTo(m_createTime)*1000+m_createTime.time().msec();
+}
+
+void EventImpl::initEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg)
+{
+ // ### ensure this is not called after we have been dispatched (also for subclasses)
+
+ if (m_type)
+ m_type->deref();
+
+ m_type = eventTypeArg.implementation();
+ if (m_type)
+ m_type->ref();
+
+ m_id = typeToId(eventTypeArg);
+
+ m_canBubble = canBubbleArg;
+ m_cancelable = cancelableArg;
+}
+
+EventImpl::EventId EventImpl::typeToId(DOMString type)
+{
+ if (type == "DOMFocusIn")
+ return DOMFOCUSIN_EVENT;
+ else if (type == "DOMFocusOut")
+ return DOMFOCUSOUT_EVENT;
+ else if (type == "DOMActivate")
+ return DOMACTIVATE_EVENT;
+ else if (type == "click")
+ return CLICK_EVENT;
+ else if (type == "mousedown")
+ return MOUSEDOWN_EVENT;
+ else if (type == "mouseup")
+ return MOUSEUP_EVENT;
+ else if (type == "mouseover")
+ return MOUSEOVER_EVENT;
+ else if (type == "mousemove")
+ return MOUSEMOVE_EVENT;
+ else if (type == "mouseout")
+ return MOUSEOUT_EVENT;
+ else if (type == "DOMSubtreeModified")
+ return DOMSUBTREEMODIFIED_EVENT;
+ else if (type == "DOMNodeInserted")
+ return DOMNODEINSERTED_EVENT;
+ else if (type == "DOMNodeRemoved")
+ return DOMNODEREMOVED_EVENT;
+ else if (type == "DOMNodeRemovedFromDocument")
+ return DOMNODEREMOVEDFROMDOCUMENT_EVENT;
+ else if (type == "DOMNodeInsertedIntoDocument")
+ return DOMNODEINSERTEDINTODOCUMENT_EVENT;
+ else if (type == "DOMAttrModified")
+ return DOMATTRMODIFIED_EVENT;
+ else if (type == "DOMCharacterDataModified")
+ return DOMCHARACTERDATAMODIFIED_EVENT;
+ else if (type == "load")
+ return LOAD_EVENT;
+ else if (type == "unload")
+ return UNLOAD_EVENT;
+ else if (type == "abort")
+ return ABORT_EVENT;
+ else if (type == "error")
+ return ERROR_EVENT;
+ else if (type == "select")
+ return SELECT_EVENT;
+ else if (type == "change")
+ return CHANGE_EVENT;
+ else if (type == "submit")
+ return SUBMIT_EVENT;
+ else if (type == "reset")
+ return RESET_EVENT;
+ else if (type == "focus")
+ return FOCUS_EVENT;
+ else if (type == "blur")
+ return BLUR_EVENT;
+ else if (type == "resize")
+ return RESIZE_EVENT;
+ else if (type == "scroll")
+ return SCROLL_EVENT;
+ else if ( type == "keydown" )
+ return KEYDOWN_EVENT;
+ else if ( type == "keyup" )
+ return KEYUP_EVENT;
+ else if ( type == "textInput" )
+ return KEYPRESS_EVENT;
+ else if ( type == "keypress" )
+ return KEYPRESS_EVENT;
+ else if ( type == "readystatechange" )
+ return KHTML_READYSTATECHANGE_EVENT;
+ else if ( type == "dblclick" )
+ return KHTML_ECMA_DBLCLICK_EVENT;
+
+ // ignore: KHTML_CLICK_EVENT
+ return UNKNOWN_EVENT;
+}
+
+DOMString EventImpl::idToType(EventImpl::EventId id)
+{
+ switch (id) {
+ case DOMFOCUSIN_EVENT:
+ return "DOMFocusIn";
+ case DOMFOCUSOUT_EVENT:
+ return "DOMFocusOut";
+ case DOMACTIVATE_EVENT:
+ return "DOMActivate";
+ case CLICK_EVENT:
+ return "click";
+ case MOUSEDOWN_EVENT:
+ return "mousedown";
+ case MOUSEUP_EVENT:
+ return "mouseup";
+ case MOUSEOVER_EVENT:
+ return "mouseover";
+ case MOUSEMOVE_EVENT:
+ return "mousemove";
+ case MOUSEOUT_EVENT:
+ return "mouseout";
+ case DOMSUBTREEMODIFIED_EVENT:
+ return "DOMSubtreeModified";
+ case DOMNODEINSERTED_EVENT:
+ return "DOMNodeInserted";
+ case DOMNODEREMOVED_EVENT:
+ return "DOMNodeRemoved";
+ case DOMNODEREMOVEDFROMDOCUMENT_EVENT:
+ return "DOMNodeRemovedFromDocument";
+ case DOMNODEINSERTEDINTODOCUMENT_EVENT:
+ return "DOMNodeInsertedIntoDocument";
+ case DOMATTRMODIFIED_EVENT:
+ return "DOMAttrModified";
+ case DOMCHARACTERDATAMODIFIED_EVENT:
+ return "DOMCharacterDataModified";
+ case LOAD_EVENT:
+ return "load";
+ case UNLOAD_EVENT:
+ return "unload";
+ case ABORT_EVENT:
+ return "abort";
+ case ERROR_EVENT:
+ return "error";
+ case SELECT_EVENT:
+ return "select";
+ case CHANGE_EVENT:
+ return "change";
+ case SUBMIT_EVENT:
+ return "submit";
+ case RESET_EVENT:
+ return "reset";
+ case FOCUS_EVENT:
+ return "focus";
+ case BLUR_EVENT:
+ return "blur";
+ case RESIZE_EVENT:
+ return "resize";
+ case SCROLL_EVENT:
+ return "scroll";
+ case KEYDOWN_EVENT:
+ return "keydown";
+ case KEYUP_EVENT:
+ return "keyup";
+ case KEYPRESS_EVENT:
+ return "keypress"; //DOM3 ev. suggests textInput, but it's better for compat this way
+
+ //tdehtml extensions
+ case KHTML_ECMA_DBLCLICK_EVENT:
+ return "dblclick";
+ case KHTML_ECMA_CLICK_EVENT:
+ return "click";
+ case KHTML_DRAGDROP_EVENT:
+ return "tdehtml_dragdrop";
+ case KHTML_MOVE_EVENT:
+ return "tdehtml_move";
+ case KHTML_READYSTATECHANGE_EVENT:
+ return "readystatechange";
+
+ default:
+ return DOMString();
+ break;
+ }
+}
+
+bool EventImpl::isUIEvent() const
+{
+ return false;
+}
+
+bool EventImpl::isMouseEvent() const
+{
+ return false;
+}
+
+bool EventImpl::isMutationEvent() const
+{
+ return false;
+}
+
+bool EventImpl::isTextInputEvent() const
+{
+ return false;
+}
+
+bool EventImpl::isKeyboardEvent() const
+{
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+
+UIEventImpl::UIEventImpl(EventId _id, bool canBubbleArg, bool cancelableArg,
+ AbstractViewImpl *viewArg, long detailArg)
+ : EventImpl(_id,canBubbleArg,cancelableArg)
+{
+ m_view = viewArg;
+ if (m_view)
+ m_view->ref();
+ m_detail = detailArg;
+}
+
+UIEventImpl::~UIEventImpl()
+{
+ if (m_view)
+ m_view->deref();
+}
+
+void UIEventImpl::initUIEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg)
+{
+ EventImpl::initEvent(typeArg,canBubbleArg,cancelableArg);
+
+ if (m_view)
+ m_view->deref();
+
+ m_view = viewArg.handle();
+ if (m_view)
+ m_view->ref();
+ m_detail = detailArg;
+}
+
+bool UIEventImpl::isUIEvent() const
+{
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+MouseEventImpl::MouseEventImpl()
+{
+ m_screenX = 0;
+ m_screenY = 0;
+ m_clientX = 0;
+ m_clientY = 0;
+ m_pageX = 0;
+ m_pageY = 0;
+ m_ctrlKey = false;
+ m_altKey = false;
+ m_shiftKey = false;
+ m_metaKey = false;
+ m_button = 0;
+ m_relatedTarget = 0;
+ m_qevent = 0;
+ m_isDoubleClick = false;
+}
+
+MouseEventImpl::MouseEventImpl(EventId _id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ AbstractViewImpl *viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ long pageXArg,
+ long pageYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ NodeImpl *relatedTargetArg,
+ TQMouseEvent *qe,
+ bool isDoubleClick)
+ : UIEventImpl(_id,canBubbleArg,cancelableArg,viewArg,detailArg)
+{
+ m_screenX = screenXArg;
+ m_screenY = screenYArg;
+ m_clientX = clientXArg;
+ m_clientY = clientYArg;
+ m_pageX = pageXArg;
+ m_pageY = pageYArg;
+ m_ctrlKey = ctrlKeyArg;
+ m_altKey = altKeyArg;
+ m_shiftKey = shiftKeyArg;
+ m_metaKey = metaKeyArg;
+ m_button = buttonArg;
+ m_relatedTarget = relatedTargetArg;
+ if (m_relatedTarget)
+ m_relatedTarget->ref();
+ computeLayerPos();
+ m_qevent = qe;
+ m_isDoubleClick = isDoubleClick;
+}
+
+MouseEventImpl::~MouseEventImpl()
+{
+ if (m_relatedTarget)
+ m_relatedTarget->deref();
+}
+
+void MouseEventImpl::computeLayerPos()
+{
+ m_layerX = m_pageX;
+ m_layerY = m_pageY;
+
+ DocumentImpl* doc = view() ? view()->document() : 0;
+ if (doc) {
+ tdehtml::RenderObject::NodeInfo renderInfo(true, false);
+ doc->renderer()->layer()->nodeAtPoint(renderInfo, m_pageX, m_pageY);
+
+ NodeImpl *node = renderInfo.innerNonSharedNode();
+ while (node && !node->renderer())
+ node = node->parent();
+
+ if (node) {
+ node->renderer()->enclosingLayer()->updateLayerPosition();
+ for (RenderLayer* layer = node->renderer()->enclosingLayer(); layer;
+ layer = layer->parent()) {
+ m_layerX -= layer->xPos();
+ m_layerY -= layer->yPos();
+ }
+ }
+ }
+}
+
+void MouseEventImpl::initMouseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ const Node &relatedTargetArg)
+{
+ UIEventImpl::initUIEvent(typeArg,canBubbleArg,cancelableArg,viewArg,detailArg);
+
+ if (m_relatedTarget)
+ m_relatedTarget->deref();
+
+ m_screenX = screenXArg;
+ m_screenY = screenYArg;
+ m_clientX = clientXArg;
+ m_clientY = clientYArg;
+ m_pageX = clientXArg;
+ m_pageY = clientYArg;
+ KHTMLView* v;
+ if ( view() && view()->document() && ( v = view()->document()->view() ) ) {
+ m_pageX += v->contentsX();
+ m_pageY += v->contentsY();
+ }
+ m_ctrlKey = ctrlKeyArg;
+ m_altKey = altKeyArg;
+ m_shiftKey = shiftKeyArg;
+ m_metaKey = metaKeyArg;
+ m_button = buttonArg;
+ m_relatedTarget = relatedTargetArg.handle();
+ if (m_relatedTarget)
+ m_relatedTarget->ref();
+
+
+ // ### make this on-demand. its soo sloooow
+ computeLayerPos();
+ m_qevent = 0;
+}
+
+bool MouseEventImpl::isMouseEvent() const
+{
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------
+/* This class is used to do remapping between different encodings reasonably compactly */
+
+template<typename L, typename R, typename MemL>
+class IDTranslator
+{
+public:
+ struct Info {
+ MemL l;
+ R r;
+ };
+
+ IDTranslator(const Info* table) {
+ for (const Info* cursor = table; cursor->l; ++cursor) {
+ m_lToR.insert(cursor->l, cursor->r);
+ m_rToL.insert(cursor->r, cursor->l);
+ }
+ }
+
+ L toLeft(R r) {
+ TQMapIterator<R,L> i( m_rToL.find(r) );
+ if (i != m_rToL.end())
+ return *i;
+ return L();
+ }
+
+ R toRight(L l) {
+ TQMapIterator<L,R> i = m_lToR.find(l);
+ if (i != m_lToR.end())
+ return *i;
+ return R();
+ }
+
+private:
+ TQMap<L, R> m_lToR;
+ TQMap<R, L> m_rToL;
+};
+
+#define MAKE_TRANSLATOR(name,L,R,MR,table) static IDTranslator<L,R,MR>* s_##name; \
+ static IDTranslator<L,R,MR>* name() { if (!s_##name) s_##name = new IDTranslator<L,R,MR>(table); \
+ return s_##name; }
+
+//---------------------------------------------------------------------------------------------
+
+/* Mapping between special Qt keycodes and virtual DOM codes */
+IDTranslator<unsigned, unsigned, unsigned>::Info virtKeyToQtKeyTable[] =
+{
+ {KeyEventBaseImpl::DOM_VK_BACK_SPACE, Qt::Key_Backspace},
+ {KeyEventBaseImpl::DOM_VK_ENTER, Qt::Key_Enter},
+ {KeyEventBaseImpl::DOM_VK_ENTER, Qt::Key_Return},
+ {KeyEventBaseImpl::DOM_VK_NUM_LOCK, Qt::Key_NumLock},
+ {KeyEventBaseImpl::DOM_VK_RIGHT_ALT, Qt::Key_Alt},
+ {KeyEventBaseImpl::DOM_VK_LEFT_CONTROL, Qt::Key_Control},
+ {KeyEventBaseImpl::DOM_VK_LEFT_SHIFT, Qt::Key_Shift},
+ {KeyEventBaseImpl::DOM_VK_META, Qt::Key_Meta},
+ {KeyEventBaseImpl::DOM_VK_CAPS_LOCK, Qt::Key_CapsLock},
+ {KeyEventBaseImpl::DOM_VK_DELETE, Qt::Key_Delete},
+ {KeyEventBaseImpl::DOM_VK_END, Qt::Key_End},
+ {KeyEventBaseImpl::DOM_VK_ESCAPE, Qt::Key_Escape},
+ {KeyEventBaseImpl::DOM_VK_HOME, Qt::Key_Home},
+ {KeyEventBaseImpl::DOM_VK_PAUSE, Qt::Key_Pause},
+ {KeyEventBaseImpl::DOM_VK_PRINTSCREEN, Qt::Key_Print},
+ {KeyEventBaseImpl::DOM_VK_SCROLL_LOCK, Qt::Key_ScrollLock},
+ {KeyEventBaseImpl::DOM_VK_LEFT, Qt::Key_Left},
+ {KeyEventBaseImpl::DOM_VK_RIGHT, Qt::Key_Right},
+ {KeyEventBaseImpl::DOM_VK_UP, Qt::Key_Up},
+ {KeyEventBaseImpl::DOM_VK_DOWN, Qt::Key_Down},
+ {KeyEventBaseImpl::DOM_VK_PAGE_DOWN, TQt::Key_Next},
+ {KeyEventBaseImpl::DOM_VK_PAGE_UP, TQt::Key_Prior},
+ {KeyEventBaseImpl::DOM_VK_F1, Qt::Key_F1},
+ {KeyEventBaseImpl::DOM_VK_F2, Qt::Key_F2},
+ {KeyEventBaseImpl::DOM_VK_F3, Qt::Key_F3},
+ {KeyEventBaseImpl::DOM_VK_F4, Qt::Key_F4},
+ {KeyEventBaseImpl::DOM_VK_F5, Qt::Key_F5},
+ {KeyEventBaseImpl::DOM_VK_F6, Qt::Key_F6},
+ {KeyEventBaseImpl::DOM_VK_F7, Qt::Key_F7},
+ {KeyEventBaseImpl::DOM_VK_F8, Qt::Key_F8},
+ {KeyEventBaseImpl::DOM_VK_F9, Qt::Key_F9},
+ {KeyEventBaseImpl::DOM_VK_F10, Qt::Key_F10},
+ {KeyEventBaseImpl::DOM_VK_F11, Qt::Key_F11},
+ {KeyEventBaseImpl::DOM_VK_F12, Qt::Key_F12},
+ {KeyEventBaseImpl::DOM_VK_F13, Qt::Key_F13},
+ {KeyEventBaseImpl::DOM_VK_F14, Qt::Key_F14},
+ {KeyEventBaseImpl::DOM_VK_F15, Qt::Key_F15},
+ {KeyEventBaseImpl::DOM_VK_F16, Qt::Key_F16},
+ {KeyEventBaseImpl::DOM_VK_F17, Qt::Key_F17},
+ {KeyEventBaseImpl::DOM_VK_F18, Qt::Key_F18},
+ {KeyEventBaseImpl::DOM_VK_F19, Qt::Key_F19},
+ {KeyEventBaseImpl::DOM_VK_F20, Qt::Key_F20},
+ {KeyEventBaseImpl::DOM_VK_F21, Qt::Key_F21},
+ {KeyEventBaseImpl::DOM_VK_F22, Qt::Key_F22},
+ {KeyEventBaseImpl::DOM_VK_F23, Qt::Key_F23},
+ {KeyEventBaseImpl::DOM_VK_F24, Qt::Key_F24},
+ {0, 0}
+};
+
+MAKE_TRANSLATOR(virtKeyToQtKey, unsigned, unsigned, unsigned, virtKeyToQtKeyTable)
+
+KeyEventBaseImpl::KeyEventBaseImpl(EventId id, bool canBubbleArg, bool cancelableArg, AbstractViewImpl *viewArg,
+ TQKeyEvent *key) :
+ UIEventImpl(id, canBubbleArg, cancelableArg, viewArg, 0)
+{
+ m_synthetic = false;
+
+ //Here, we need to map Qt's internal info to browser-style info.
+ m_keyEvent = new TQKeyEvent(key->type(), key->key(), key->ascii(), key->state(), key->text(), key->isAutoRepeat(), key->count() );
+
+ m_detail = key->count();
+ m_keyVal = key->ascii();
+ m_virtKeyVal = virtKeyToQtKey()->toLeft(key->key());
+
+ // m_keyVal should contain the unicode value
+ // of the pressed key if available.
+ if (m_virtKeyVal == DOM_VK_UNDEFINED && !key->text().isEmpty())
+ m_keyVal = TQString(key->text()).unicode()[0];
+
+ // key->state returns enum ButtonState, which is ShiftButton, ControlButton and AltButton or'ed together.
+ m_modifier = key->state();
+}
+
+KeyEventBaseImpl::~KeyEventBaseImpl()
+{
+ delete m_keyEvent;
+}
+
+void KeyEventBaseImpl::initKeyBaseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ unsigned long keyValArg,
+ unsigned long virtKeyValArg,
+ unsigned long modifiersArg)
+{
+ m_synthetic = true;
+ delete m_keyEvent;
+ m_keyEvent = 0;
+ initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, 1);
+ m_virtKeyVal = virtKeyValArg;
+ m_keyVal = keyValArg;
+ m_modifier = modifiersArg;
+}
+
+bool KeyEventBaseImpl::checkModifier(unsigned long modifierArg)
+{
+ return ((m_modifier & modifierArg) == modifierArg);
+}
+
+void KeyEventBaseImpl::initModifier(unsigned long modifierArg,
+ bool valueArg)
+{
+ if (valueArg)
+ m_modifier |= modifierArg;
+ else
+ m_modifier &= (modifierArg ^ 0xFFFFFFFF);
+}
+
+void KeyEventBaseImpl::buildQKeyEvent() const
+{
+ delete m_keyEvent;
+
+ assert(m_synthetic);
+ //IMPORTANT: we ignore modifers on purpose.
+ //this is to prevent a website from synthesizing something
+ //like Ctrl-V or Shift-Insert and stealing contents of the user's clipboard.
+ unsigned modifiers = 0;
+
+ int key = 0;
+ int ascii = 0;
+ TQString text;
+ if (m_virtKeyVal)
+ key = virtKeyToQtKey()->toRight(m_virtKeyVal);
+ if (!key) {
+ ascii = m_keyVal; //###?
+ key = m_keyVal;
+ text = TQChar(key);
+ }
+
+ //Neuter F keys as well.
+ if (key >= Qt::Key_F1 && key <= Qt::Key_F35)
+ key = Qt::Key_ScrollLock;
+
+ m_keyEvent = new TQKeyEvent(id() == KEYUP_EVENT ? TQEvent::KeyRelease : TQEvent::KeyPress,
+ key, ascii, modifiers, text);
+}
+
+//------------------------------------------------------------------------------
+
+
+static const IDTranslator<TQCString, unsigned, const char*>::Info keyIdentifiersToVirtKeysTable[] = {
+ {"Alt", KeyEventBaseImpl::DOM_VK_LEFT_ALT},
+ {"Control", KeyEventBaseImpl::DOM_VK_LEFT_CONTROL},
+ {"Shift", KeyEventBaseImpl::DOM_VK_LEFT_SHIFT},
+ {"Meta", KeyEventBaseImpl::DOM_VK_META},
+ {"\0x08", KeyEventBaseImpl::DOM_VK_SPACE}, //1-char virt!
+ {"CapsLock", KeyEventBaseImpl::DOM_VK_CAPS_LOCK},
+ {"\x7F", KeyEventBaseImpl::DOM_VK_DELETE}, //1-char virt!
+ {"End", KeyEventBaseImpl::DOM_VK_END},
+ {"Enter", KeyEventBaseImpl::DOM_VK_ENTER},
+ {"\x1b", KeyEventBaseImpl::DOM_VK_ESCAPE}, //1-char virt!
+ {"Home", KeyEventBaseImpl::DOM_VK_HOME},
+ {"NumLock", KeyEventBaseImpl::DOM_VK_NUM_LOCK},
+ {"Pause", KeyEventBaseImpl::DOM_VK_PAUSE},
+ {"PrintScreen", KeyEventBaseImpl::DOM_VK_PRINTSCREEN},
+ {"Scroll", KeyEventBaseImpl::DOM_VK_SCROLL_LOCK},
+ {" ", KeyEventBaseImpl::DOM_VK_SPACE}, //1-char virt!
+ {"\t", KeyEventBaseImpl::DOM_VK_TAB}, //1-char virt!
+ {"Left", KeyEventBaseImpl::DOM_VK_LEFT},
+ {"Left", KeyEventBaseImpl::DOM_VK_LEFT},
+ {"Right", KeyEventBaseImpl::DOM_VK_RIGHT},
+ {"Up", KeyEventBaseImpl::DOM_VK_UP},
+ {"Down", KeyEventBaseImpl::DOM_VK_DOWN},
+ {"PageDown", KeyEventBaseImpl::DOM_VK_PAGE_DOWN},
+ {"PageUp", KeyEventBaseImpl::DOM_VK_PAGE_UP},
+ {"F1", KeyEventBaseImpl::DOM_VK_F1},
+ {"F2", KeyEventBaseImpl::DOM_VK_F2},
+ {"F3", KeyEventBaseImpl::DOM_VK_F3},
+ {"F4", KeyEventBaseImpl::DOM_VK_F4},
+ {"F5", KeyEventBaseImpl::DOM_VK_F5},
+ {"F6", KeyEventBaseImpl::DOM_VK_F6},
+ {"F7", KeyEventBaseImpl::DOM_VK_F7},
+ {"F8", KeyEventBaseImpl::DOM_VK_F8},
+ {"F9", KeyEventBaseImpl::DOM_VK_F9},
+ {"F10", KeyEventBaseImpl::DOM_VK_F10},
+ {"F11", KeyEventBaseImpl::DOM_VK_F11},
+ {"F12", KeyEventBaseImpl::DOM_VK_F12},
+ {"F13", KeyEventBaseImpl::DOM_VK_F13},
+ {"F14", KeyEventBaseImpl::DOM_VK_F14},
+ {"F15", KeyEventBaseImpl::DOM_VK_F15},
+ {"F16", KeyEventBaseImpl::DOM_VK_F16},
+ {"F17", KeyEventBaseImpl::DOM_VK_F17},
+ {"F18", KeyEventBaseImpl::DOM_VK_F18},
+ {"F19", KeyEventBaseImpl::DOM_VK_F19},
+ {"F20", KeyEventBaseImpl::DOM_VK_F20},
+ {"F21", KeyEventBaseImpl::DOM_VK_F21},
+ {"F22", KeyEventBaseImpl::DOM_VK_F22},
+ {"F23", KeyEventBaseImpl::DOM_VK_F23},
+ {"F24", KeyEventBaseImpl::DOM_VK_F24},
+ {0, 0}
+};
+
+MAKE_TRANSLATOR(keyIdentifiersToVirtKeys, TQCString, unsigned, const char*, keyIdentifiersToVirtKeysTable)
+
+/** These are the modifiers we currently support */
+static const IDTranslator<TQCString, unsigned, const char*>::Info keyModifiersToCodeTable[] = {
+ {"Alt", TQt::AltButton},
+ {"Control", TQt::ControlButton},
+ {"Shift", TQt::ShiftButton},
+ {"Meta", TQt::MetaButton},
+ {0, 0}
+};
+
+MAKE_TRANSLATOR(keyModifiersToCode, TQCString, unsigned, const char*, keyModifiersToCodeTable)
+
+KeyboardEventImpl::KeyboardEventImpl() : m_keyLocation(DOM_KEY_LOCATION_STANDARD)
+{}
+
+DOMString KeyboardEventImpl::keyIdentifier() const
+{
+ if (unsigned special = virtKeyVal())
+ if (const char* id = keyIdentifiersToVirtKeys()->toLeft(special))
+ return TQString::fromLatin1(id);
+
+ if (unsigned unicode = keyVal())
+ return TQString(TQChar(unicode));
+
+ return "Unidentified";
+}
+
+bool KeyboardEventImpl::getModifierState (const DOMString& keyIdentifierArg) const
+{
+ unsigned mask = keyModifiersToCode()->toRight(keyIdentifierArg.string().latin1());
+ return m_modifier & mask;
+}
+
+bool KeyboardEventImpl::isKeyboardEvent() const
+{
+ return true;
+}
+
+void KeyboardEventImpl::initKeyboardEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ const DOMString &keyIdentifierArg,
+ unsigned long keyLocationArg,
+ const DOMString& modifiersList)
+{
+ unsigned keyVal = 0;
+ unsigned virtKeyVal = 0;
+
+ m_keyLocation = keyLocationArg;
+
+ //Figure out the code information from the key identifier.
+ if (keyIdentifierArg.length() == 1) {
+ //Likely to be normal unicode id, unless it's one of the few
+ //special values.
+ unsigned short code = keyIdentifierArg.unicode()[0];
+ if (code > 0x20 && code != 0x7F)
+ keyVal = code;
+ }
+
+ if (!keyVal) //One of special keys, likely.
+ virtKeyVal = keyIdentifiersToVirtKeys()->toRight(keyIdentifierArg.string().latin1());
+
+ //Process modifier list.
+ TQStringList mods =
+ TQStringList::split(' ',
+ modifiersList.string().stripWhiteSpace().simplifyWhiteSpace());
+
+ unsigned modifiers = 0;
+ for (TQStringList::Iterator i = mods.begin(); i != mods.end(); ++i)
+ if (unsigned mask = keyModifiersToCode()->toRight((*i).latin1()))
+ modifiers |= mask;
+
+ initKeyBaseEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
+ keyVal, virtKeyVal, modifiers);
+}
+
+KeyboardEventImpl::KeyboardEventImpl(TQKeyEvent* key, DOM::AbstractViewImpl* view) :
+ KeyEventBaseImpl(key->type() == TQEvent::KeyRelease ? KEYUP_EVENT : KEYDOWN_EVENT, true, true, view, key)
+{
+ //Try to put something reasonable in location...
+ //we don't know direction, so guess left
+ m_keyLocation = DOM_KEY_LOCATION_STANDARD;
+ switch (m_virtKeyVal) {
+ case DOM_VK_LEFT_ALT:
+ case DOM_VK_LEFT_SHIFT:
+ case DOM_VK_LEFT_CONTROL:
+ case DOM_VK_META:
+ m_keyLocation = DOM_KEY_LOCATION_LEFT;
+ }
+}
+
+int KeyboardEventImpl::keyCode() const
+{
+ //Keycode on key events always identifies the -key- and not the input,
+ //so e.g. 'a' will get 'A'
+ if (m_virtKeyVal != DOM_VK_UNDEFINED)
+ return m_virtKeyVal;
+ else
+ return TQChar((unsigned short)m_keyVal).upper().unicode();
+}
+
+int KeyboardEventImpl::charCode() const
+{
+ //IE doesn't support charCode at all, and mozilla returns 0
+ //on key events. So return 0 here
+ return 0;
+}
+
+
+// -----------------------------------------------------------------------------
+TextEventImpl::TextEventImpl()
+{}
+
+bool TextEventImpl::isTextInputEvent() const
+{
+ return true;
+}
+
+TextEventImpl::TextEventImpl(TQKeyEvent* key, DOM::AbstractViewImpl* view) :
+ KeyEventBaseImpl(KEYPRESS_EVENT, true, true, view, key)
+{
+ m_outputString = TQString(key->text());
+}
+
+void TextEventImpl::initTextEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ const DOMString& text)
+{
+ m_outputString = text;
+
+ //See whether we can get a key out of this.
+ unsigned keyCode = 0;
+ if (text.length() == 1)
+ keyCode = text.unicode()[0].unicode();
+ initKeyBaseEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
+ keyCode, 0, 0);
+}
+
+int TextEventImpl::keyCode() const
+{
+ //Mozilla returns 0 here unless this is a non-unicode key.
+ //IE stuffs everything here, and so we try to match it..
+ if (m_keyVal)
+ return m_keyVal;
+ return m_virtKeyVal;
+}
+
+int TextEventImpl::charCode() const
+{
+ //On text events, in Mozilla charCode is 0 for non-unicode keys,
+ //and the unicode key otherwise... IE doesn't support this.
+ if (m_virtKeyVal)
+ return 0;
+ return m_keyVal;
+}
+
+
+// -----------------------------------------------------------------------------
+MutationEventImpl::MutationEventImpl()
+{
+ m_relatedNode = 0;
+ m_prevValue = 0;
+ m_newValue = 0;
+ m_attrName = 0;
+ m_attrChange = 0;
+}
+
+MutationEventImpl::MutationEventImpl(EventId _id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg)
+ : EventImpl(_id,canBubbleArg,cancelableArg)
+{
+ m_relatedNode = relatedNodeArg.handle();
+ if (m_relatedNode)
+ m_relatedNode->ref();
+ m_prevValue = prevValueArg.implementation();
+ if (m_prevValue)
+ m_prevValue->ref();
+ m_newValue = newValueArg.implementation();
+ if (m_newValue)
+ m_newValue->ref();
+ m_attrName = attrNameArg.implementation();
+ if (m_attrName)
+ m_attrName->ref();
+ m_attrChange = attrChangeArg;
+}
+
+MutationEventImpl::~MutationEventImpl()
+{
+ if (m_relatedNode)
+ m_relatedNode->deref();
+ if (m_prevValue)
+ m_prevValue->deref();
+ if (m_newValue)
+ m_newValue->deref();
+ if (m_attrName)
+ m_attrName->deref();
+}
+
+void MutationEventImpl::initMutationEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg)
+{
+ EventImpl::initEvent(typeArg,canBubbleArg,cancelableArg);
+
+ if (m_relatedNode)
+ m_relatedNode->deref();
+ if (m_prevValue)
+ m_prevValue->deref();
+ if (m_newValue)
+ m_newValue->deref();
+ if (m_attrName)
+ m_attrName->deref();
+
+ m_relatedNode = relatedNodeArg.handle();
+ if (m_relatedNode)
+ m_relatedNode->ref();
+ m_prevValue = prevValueArg.implementation();
+ if (m_prevValue)
+ m_prevValue->ref();
+ m_newValue = newValueArg.implementation();
+ if (m_newValue)
+ m_newValue->ref();
+ m_attrName = attrNameArg.implementation();
+ if (m_newValue)
+ m_newValue->ref();
+ m_attrChange = attrChangeArg;
+}
+
+bool MutationEventImpl::isMutationEvent() const
+{
+ return true;
+}
+
diff --git a/tdehtml/xml/dom2_eventsimpl.h b/tdehtml/xml/dom2_eventsimpl.h
new file mode 100644
index 000000000..5d99afbbe
--- /dev/null
+++ b/tdehtml/xml/dom2_eventsimpl.h
@@ -0,0 +1,513 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
+ * (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 _DOM_EventsImpl_h_
+#define _DOM_EventsImpl_h_
+
+#include "dom/dom2_events.h"
+#include "xml/dom2_viewsimpl.h"
+
+class KHTMLPart;
+class TQMouseEvent;
+
+namespace DOM {
+
+class AbstractViewImpl;
+class DOMStringImpl;
+class NodeImpl;
+
+// ### support user-defined events
+
+class EventImpl : public tdehtml::Shared<EventImpl>
+{
+public:
+ enum EventId {
+ UNKNOWN_EVENT = 0,
+ // UI events
+ DOMFOCUSIN_EVENT,
+ DOMFOCUSOUT_EVENT,
+ DOMACTIVATE_EVENT,
+ // Mouse events
+ CLICK_EVENT,
+ MOUSEDOWN_EVENT,
+ MOUSEUP_EVENT,
+ MOUSEOVER_EVENT,
+ MOUSEMOVE_EVENT,
+ MOUSEOUT_EVENT,
+ // Mutation events
+ DOMSUBTREEMODIFIED_EVENT,
+ DOMNODEINSERTED_EVENT,
+ DOMNODEREMOVED_EVENT,
+ DOMNODEREMOVEDFROMDOCUMENT_EVENT,
+ DOMNODEINSERTEDINTODOCUMENT_EVENT,
+ DOMATTRMODIFIED_EVENT,
+ DOMCHARACTERDATAMODIFIED_EVENT,
+ // HTML events
+ LOAD_EVENT,
+ UNLOAD_EVENT,
+ ABORT_EVENT,
+ ERROR_EVENT,
+ SELECT_EVENT,
+ CHANGE_EVENT,
+ SUBMIT_EVENT,
+ RESET_EVENT,
+ FOCUS_EVENT,
+ BLUR_EVENT,
+ RESIZE_EVENT,
+ SCROLL_EVENT,
+ // keyboard events
+ KEYDOWN_EVENT,
+ KEYUP_EVENT,
+ KEYPRESS_EVENT, //Mostly corresponds to DOM3 textInput event.
+ // tdehtml events (not part of DOM)
+ KHTML_ECMA_DBLCLICK_EVENT, // for html ondblclick
+ KHTML_ECMA_CLICK_EVENT, // for html onclick
+ KHTML_DRAGDROP_EVENT,
+ KHTML_MOVE_EVENT,
+ // XMLHttpRequest events
+ KHTML_READYSTATECHANGE_EVENT
+ };
+
+ EventImpl();
+ EventImpl(EventId _id, bool canBubbleArg, bool cancelableArg);
+ virtual ~EventImpl();
+
+ EventId id() const { return m_id; }
+
+ DOMString type() const { return m_type; }
+ NodeImpl *target() const { return m_target; }
+ void setTarget(NodeImpl *_target);
+ NodeImpl *currentTarget() const { return m_currentTarget; }
+ void setCurrentTarget(NodeImpl *_currentTarget) { m_currentTarget = _currentTarget; }
+ unsigned short eventPhase() const { return m_eventPhase; }
+ void setEventPhase(unsigned short _eventPhase) { m_eventPhase = _eventPhase; }
+ bool bubbles() const { return m_canBubble; }
+ bool cancelable() const { return m_cancelable; }
+ DOMTimeStamp timeStamp();
+ void stopPropagation(bool stop) { m_propagationStopped = stop; }
+ void preventDefault(bool prevent) { if ( m_cancelable ) m_defaultPrevented = prevent; }
+
+ void initEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg);
+
+ virtual bool isUIEvent() const;
+ virtual bool isMouseEvent() const;
+ virtual bool isMutationEvent() const;
+ virtual bool isTextInputEvent() const;
+ virtual bool isKeyboardEvent() const;
+ bool isKeyRelatedEvent() const { return isTextInputEvent() || isKeyboardEvent(); }
+
+ bool propagationStopped() const { return m_propagationStopped; }
+ bool defaultPrevented() const { return m_defaultPrevented; }
+
+ static EventId typeToId(DOMString type);
+ static DOMString idToType(EventId id);
+
+ void setDefaultHandled() { m_defaultHandled = true; }
+ bool defaultHandled() const { return m_defaultHandled; }
+
+ DOMString message() const { return m_message; }
+ void setMessage(const DOMString &_message) { m_message = _message; }
+
+protected:
+ DOMStringImpl *m_type;
+ bool m_canBubble;
+ bool m_cancelable;
+
+ bool m_propagationStopped;
+ bool m_defaultPrevented;
+ bool m_defaultHandled;
+ EventId m_id : 6;
+ unsigned short m_eventPhase : 2;
+ NodeImpl *m_currentTarget; // ref > 0 maintained externally
+ NodeImpl *m_target;
+ TQDateTime m_createTime;
+ DOMString m_message;
+};
+
+
+
+class UIEventImpl : public EventImpl
+{
+public:
+ UIEventImpl() : m_view(0), m_detail(0) {}
+ UIEventImpl(EventId _id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ AbstractViewImpl *viewArg,
+ long detailArg);
+ virtual ~UIEventImpl();
+ AbstractViewImpl *view() const { return m_view; }
+ long detail() const { return m_detail; }
+ void initUIEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg);
+ virtual bool isUIEvent() const;
+
+protected:
+ AbstractViewImpl *m_view;
+ long m_detail;
+
+};
+
+// Introduced in DOM Level 2: - internal
+class MouseEventImpl : public UIEventImpl {
+public:
+ MouseEventImpl();
+ MouseEventImpl(EventId _id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ AbstractViewImpl *viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ long pageXArg,
+ long pageYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ NodeImpl *relatedTargetArg,
+ TQMouseEvent *qe = 0,
+ bool isDoubleClick = false);
+ virtual ~MouseEventImpl();
+ long screenX() const { return m_screenX; }
+ long screenY() const { return m_screenY; }
+ long clientX() const { return m_clientX; }
+ long clientY() const { return m_clientY; }
+ long layerX() const { return m_layerX; } // non-DOM extension
+ long layerY() const { return m_layerY; } // non-DOM extension
+ long pageX() const { return m_pageX; } // non-DOM extension
+ long pageY() const { return m_pageY; } // non-DOM extension
+ bool isDoubleClick() const { return m_isDoubleClick; } // non-DOM extension
+ bool ctrlKey() const { return m_ctrlKey; }
+ bool shiftKey() const { return m_shiftKey; }
+ bool altKey() const { return m_altKey; }
+ bool metaKey() const { return m_metaKey; }
+ unsigned short button() const { return m_button; }
+ NodeImpl *relatedTarget() const { return m_relatedTarget; }
+
+ void computeLayerPos();
+
+ void initMouseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ long detailArg,
+ long screenXArg,
+ long screenYArg,
+ long clientXArg,
+ long clientYArg,
+ bool ctrlKeyArg,
+ bool altKeyArg,
+ bool shiftKeyArg,
+ bool metaKeyArg,
+ unsigned short buttonArg,
+ const Node &relatedTargetArg);
+ virtual bool isMouseEvent() const;
+
+ TQMouseEvent *qEvent() const { return m_qevent; }
+protected:
+ long m_screenX;
+ long m_screenY;
+ long m_clientX;
+ long m_clientY;
+ long m_layerX;
+ long m_layerY;
+ long m_pageX;
+ long m_pageY;
+ bool m_ctrlKey : 1;
+ bool m_altKey : 1;
+ bool m_shiftKey : 1;
+ bool m_metaKey : 1;
+ bool m_isDoubleClick : 1;
+ unsigned short m_button;
+ NodeImpl *m_relatedTarget;
+ TQMouseEvent *m_qevent;
+};
+
+
+class KeyEventBaseImpl : public UIEventImpl {
+public:
+ // VirtualKeyCode
+ enum KeyCodes {
+ DOM_VK_UNDEFINED = 0x0,
+ DOM_VK_RIGHT_ALT = 0x12,
+ DOM_VK_LEFT_ALT = 0x12,
+ DOM_VK_LEFT_CONTROL = 0x11,
+ DOM_VK_RIGHT_CONTROL = 0x11,
+ DOM_VK_LEFT_SHIFT = 0x10,
+ DOM_VK_RIGHT_SHIFT = 0x10,
+ DOM_VK_META = 0x9D,
+ DOM_VK_BACK_SPACE = 0x08,
+ DOM_VK_CAPS_LOCK = 0x14,
+ DOM_VK_DELETE = 0x7F,
+ DOM_VK_END = 0x23,
+ DOM_VK_ENTER = 0x0D,
+ DOM_VK_ESCAPE = 0x1B,
+ DOM_VK_HOME = 0x24,
+ DOM_VK_NUM_LOCK = 0x90,
+ DOM_VK_PAUSE = 0x13,
+ DOM_VK_PRINTSCREEN = 0x9A,
+ DOM_VK_SCROLL_LOCK = 0x91,
+ DOM_VK_SPACE = 0x20,
+ DOM_VK_TAB = 0x09,
+ DOM_VK_LEFT = 0x25,
+ DOM_VK_RIGHT = 0x27,
+ DOM_VK_UP = 0x26,
+ DOM_VK_DOWN = 0x28,
+ DOM_VK_PAGE_DOWN = 0x22,
+ DOM_VK_PAGE_UP = 0x21,
+ DOM_VK_F1 = 0x70,
+ DOM_VK_F2 = 0x71,
+ DOM_VK_F3 = 0x72,
+ DOM_VK_F4 = 0x73,
+ DOM_VK_F5 = 0x74,
+ DOM_VK_F6 = 0x75,
+ DOM_VK_F7 = 0x76,
+ DOM_VK_F8 = 0x77,
+ DOM_VK_F9 = 0x78,
+ DOM_VK_F10 = 0x79,
+ DOM_VK_F11 = 0x7A,
+ DOM_VK_F12 = 0x7B,
+ DOM_VK_F13 = 0xF000,
+ DOM_VK_F14 = 0xF001,
+ DOM_VK_F15 = 0xF002,
+ DOM_VK_F16 = 0xF003,
+ DOM_VK_F17 = 0xF004,
+ DOM_VK_F18 = 0xF005,
+ DOM_VK_F19 = 0xF006,
+ DOM_VK_F20 = 0xF007,
+ DOM_VK_F21 = 0xF008,
+ DOM_VK_F22 = 0xF009,
+ DOM_VK_F23 = 0xF00A,
+ DOM_VK_F24 = 0xF00B
+ };
+
+ void initKeyBaseEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ unsigned long keyVal,
+ unsigned long virtKeyVal,
+ unsigned long modifiers);
+
+ bool ctrlKey() const { return m_modifier & TQt::ControlButton; }
+ bool shiftKey() const { return m_modifier & TQt::ShiftButton; }
+ bool altKey() const { return m_modifier & TQt::AltButton; }
+ bool metaKey() const { return m_modifier & TQt::MetaButton; }
+
+ bool inputGenerated() const { return m_virtKeyVal == 0; }
+ unsigned long keyVal() const { return m_keyVal; }
+ unsigned long virtKeyVal() const { return m_virtKeyVal; }
+
+ TQKeyEvent *qKeyEvent() const { if (!m_keyEvent) buildQKeyEvent(); return m_keyEvent; }
+
+ //Legacy key stuff...
+ virtual int keyCode() const = 0;
+ virtual int charCode() const = 0;
+
+ //### KDE4: remove these 2
+ void initModifier(unsigned long modifierArg, bool valueArg);
+ bool checkModifier(unsigned long modifierArg);
+
+ ~KeyEventBaseImpl();
+
+ //Returns true if the event was synthesized by client use of DOM
+ bool isSynthetic() const { return m_synthetic; }
+protected:
+ KeyEventBaseImpl(): m_keyEvent(0), m_keyVal(0), m_virtKeyVal(0), m_modifier(0), m_synthetic(false)
+ { m_detail = 0; }
+
+ KeyEventBaseImpl(EventId id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ AbstractViewImpl *viewArg,
+ TQKeyEvent *key);
+
+
+ mutable TQKeyEvent *m_keyEvent;
+ unsigned long m_keyVal; //Unicode key value
+ unsigned long m_virtKeyVal; //Virtual key value for keys like arrows, Fn, etc.
+
+ // bitfield containing state of modifiers. not part of the dom.
+ unsigned long m_modifier;
+
+ bool m_synthetic;
+
+ void buildQKeyEvent() const; //Construct a Qt key event from m_keyVal/m_virtKeyVal
+};
+
+class TextEventImpl : public KeyEventBaseImpl {
+public:
+ TextEventImpl();
+
+ TextEventImpl(TQKeyEvent* key, DOM::AbstractViewImpl* view);
+
+ void initTextEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ const DOMString& text);
+
+ virtual bool isTextInputEvent() const;
+
+ //Legacy key stuff...
+ int keyCode() const;
+ int charCode() const;
+
+ DOMString data() const { return m_outputString; }
+private:
+ DOMString m_outputString;
+};
+
+class KeyboardEventImpl : public KeyEventBaseImpl {
+public:
+ KeyboardEventImpl();
+ KeyboardEventImpl(TQKeyEvent* key, DOM::AbstractViewImpl* view);
+
+ virtual bool isKeyboardEvent() const;
+
+ enum KeyLocation {
+ DOM_KEY_LOCATION_STANDARD = 0x00,
+ DOM_KEY_LOCATION_LEFT = 0x01,
+ DOM_KEY_LOCATION_RIGHT = 0x02,
+ DOM_KEY_LOCATION_NUMPAD = 0x03
+ };
+
+ //Legacy key stuff...
+ int keyCode() const;
+ int charCode() const;
+
+ DOMString keyIdentifier() const;
+ unsigned long keyLocation() const { return m_keyLocation; }
+
+ bool getModifierState(const DOMString& keyIdentifierArg) const;
+
+ void initKeyboardEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ const DOMString &keyIdentifierArg,
+ unsigned long keyLocationArg,
+ const DOMString& modifiersList);
+
+ //### KDE4: remove this, it's only for compatibility with
+ //the old TextEvent wrapper
+ void initKeyboardEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const AbstractView &viewArg,
+ unsigned long keyVal,
+ unsigned long virtKeyVal,
+ unsigned long modifiers,
+ unsigned long keyLocationArg) {
+ initKeyBaseEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
+ keyVal, virtKeyVal, modifiers);
+ m_keyLocation = keyLocationArg;
+ }
+private:
+ unsigned long m_keyLocation;
+};
+
+
+
+class MutationEventImpl : public EventImpl {
+// ### fire these during parsing (if necessary)
+public:
+ MutationEventImpl();
+ MutationEventImpl(EventId _id,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg);
+ ~MutationEventImpl();
+
+ Node relatedNode() const { return m_relatedNode; }
+ DOMString prevValue() const { return m_prevValue; }
+ DOMString newValue() const { return m_newValue; }
+ DOMString attrName() const { return m_attrName; }
+ unsigned short attrChange() const { return m_attrChange; }
+ void initMutationEvent(const DOMString &typeArg,
+ bool canBubbleArg,
+ bool cancelableArg,
+ const Node &relatedNodeArg,
+ const DOMString &prevValueArg,
+ const DOMString &newValueArg,
+ const DOMString &attrNameArg,
+ unsigned short attrChangeArg);
+ virtual bool isMutationEvent() const;
+protected:
+ NodeImpl *m_relatedNode;
+ DOMStringImpl *m_prevValue;
+ DOMStringImpl *m_newValue;
+ DOMStringImpl *m_attrName;
+ unsigned short m_attrChange;
+};
+
+
+class RegisteredEventListener {
+public:
+ RegisteredEventListener() : id(EventImpl::EventId(0)), useCapture(false), listener(0) {}
+
+ RegisteredEventListener(EventImpl::EventId _id, EventListener *_listener, bool _useCapture)
+ : id(_id), useCapture(_useCapture), listener(_listener) { if (listener) listener->ref(); }
+
+ ~RegisteredEventListener() { if (listener) listener->deref(); listener = 0; }
+
+ bool operator==(const RegisteredEventListener &other) const
+ { return id == other.id && listener == other.listener && useCapture == other.useCapture; }
+
+
+ EventImpl::EventId id : 6;
+ bool useCapture;
+ EventListener *listener;
+
+ RegisteredEventListener( const RegisteredEventListener &other ) :
+ id(other.id), useCapture(other.useCapture), listener(other.listener)
+ { if (listener) listener->ref(); }
+
+ RegisteredEventListener & operator=( const RegisteredEventListener &other ) {
+ id = other.id;
+ useCapture = other.useCapture;
+ if (other.listener)
+ other.listener->ref();
+ if (listener)
+ listener->deref();
+ listener = other.listener;
+ return *this;
+ }
+};
+
+
+
+} //namespace
+#endif
diff --git a/tdehtml/xml/dom2_rangeimpl.cpp b/tdehtml/xml/dom2_rangeimpl.cpp
new file mode 100644
index 000000000..b160ce23f
--- /dev/null
+++ b/tdehtml/xml/dom2_rangeimpl.cpp
@@ -0,0 +1,1640 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2001-2003 Dirk Mueller (mueller@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (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.
+ */
+
+#include "dom/dom_exception.h"
+#include "dom_docimpl.h"
+#include "dom2_rangeimpl.h"
+#include "dom_textimpl.h"
+#include "dom_xmlimpl.h"
+#include "html/html_elementimpl.h"
+#include "misc/htmltags.h"
+
+using namespace DOM;
+
+
+RangeImpl::RangeImpl(DocumentImpl *_ownerDocument)
+{
+ m_ownerDocument = _ownerDocument;
+ m_ownerDocument->ref();
+ m_startContainer = _ownerDocument;
+ m_startContainer->ref();
+ m_endContainer = _ownerDocument;
+ m_endContainer->ref();
+ m_startOffset = 0;
+ m_endOffset = 0;
+ m_detached = false;
+}
+
+RangeImpl::RangeImpl(DocumentImpl *_ownerDocument,
+ NodeImpl *_startContainer, long _startOffset,
+ NodeImpl *_endContainer, long _endOffset)
+{
+ m_ownerDocument = _ownerDocument;
+ m_ownerDocument->ref();
+ m_startContainer = _startContainer;
+ m_startContainer->ref();
+ m_startOffset = _startOffset;
+ m_endContainer = _endContainer;
+ m_endContainer->ref();
+ m_endOffset = _endOffset;
+ m_detached = false;
+}
+
+RangeImpl::~RangeImpl()
+{
+ m_ownerDocument->deref();
+ int exceptioncode = 0;
+ if (!m_detached)
+ detach(exceptioncode);
+}
+
+NodeImpl *RangeImpl::startContainer(int &exceptioncode) const
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return m_startContainer;
+}
+
+long RangeImpl::startOffset(int &exceptioncode) const
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return m_startOffset;
+}
+
+NodeImpl *RangeImpl::endContainer(int &exceptioncode) const
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return m_endContainer;
+}
+
+long RangeImpl::endOffset(int &exceptioncode) const
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return m_endOffset;
+}
+
+NodeImpl *RangeImpl::commonAncestorContainer(int &exceptioncode)
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ NodeImpl *com = commonAncestorContainer(m_startContainer,m_endContainer);
+ if (!com) // should never happen
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return com;
+}
+
+NodeImpl *RangeImpl::commonAncestorContainer(NodeImpl *containerA, NodeImpl *containerB)
+{
+ NodeImpl *parentStart;
+
+ for (parentStart = containerA; parentStart; parentStart = parentStart->parentNode()) {
+ NodeImpl *parentEnd = containerB;
+ while( parentEnd && (parentStart != parentEnd) )
+ parentEnd = parentEnd->parentNode();
+
+ if(parentStart == parentEnd) break;
+ }
+
+ return parentStart;
+}
+
+bool RangeImpl::collapsed(int &exceptioncode) const
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return (m_startContainer == m_endContainer && m_startOffset == m_endOffset);
+}
+
+void RangeImpl::setStart( NodeImpl *refNode, long offset, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeWOffset( refNode, offset, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setStartContainer(refNode);
+ m_startOffset = offset;
+
+ // check if different root container
+ NodeImpl *endRootContainer = m_endContainer;
+ while (endRootContainer->parentNode())
+ endRootContainer = endRootContainer->parentNode();
+ NodeImpl *startRootContainer = m_startContainer;
+ while (startRootContainer->parentNode())
+ startRootContainer = startRootContainer->parentNode();
+ if (startRootContainer != endRootContainer)
+ collapse(true,exceptioncode);
+ // check if new start after end
+ else if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)
+ collapse(true,exceptioncode);
+}
+
+void RangeImpl::setEnd( NodeImpl *refNode, long offset, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeWOffset( refNode, offset, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setEndContainer(refNode);
+ m_endOffset = offset;
+
+ // check if different root container
+ NodeImpl *endRootContainer = m_endContainer;
+ while (endRootContainer->parentNode())
+ endRootContainer = endRootContainer->parentNode();
+ NodeImpl *startRootContainer = m_startContainer;
+ while (startRootContainer->parentNode())
+ startRootContainer = startRootContainer->parentNode();
+ if (startRootContainer != endRootContainer)
+ collapse(false,exceptioncode);
+ // check if new end before start
+ if (compareBoundaryPoints(m_startContainer,m_startOffset,m_endContainer,m_endOffset) > 0)
+ collapse(false,exceptioncode);
+}
+
+void RangeImpl::collapse( bool toStart, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if( toStart ) // collapse to start
+ {
+ setEndContainer(m_startContainer);
+ m_endOffset = m_startOffset;
+ }
+ else // collapse to end
+ {
+ setStartContainer(m_endContainer);
+ m_startOffset = m_endOffset;
+ }
+}
+
+short RangeImpl::compareBoundaryPoints( Range::CompareHow how, RangeImpl *sourceRange, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ if (!sourceRange) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+ }
+
+ NodeImpl *thisCont = commonAncestorContainer(exceptioncode);
+ NodeImpl *sourceCont = sourceRange->commonAncestorContainer(exceptioncode);
+ if (exceptioncode)
+ return 0;
+
+ if (thisCont->getDocument() != sourceCont->getDocument()) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return 0;
+ }
+
+ NodeImpl *thisTop = thisCont;
+ NodeImpl *sourceTop = sourceCont;
+ while (thisTop->parentNode())
+ thisTop = thisTop->parentNode();
+ while (sourceTop->parentNode())
+ sourceTop = sourceTop->parentNode();
+ if (thisTop != sourceTop) { // in different DocumentFragments
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return 0;
+ }
+
+ switch(how)
+ {
+ case Range::START_TO_START:
+ return compareBoundaryPoints( m_startContainer, m_startOffset,
+ sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );
+ break;
+ case Range::START_TO_END:
+ return compareBoundaryPoints( m_startContainer, m_startOffset,
+ sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );
+ break;
+ case Range::END_TO_END:
+ return compareBoundaryPoints( m_endContainer, m_endOffset,
+ sourceRange->endContainer(exceptioncode), sourceRange->endOffset(exceptioncode) );
+ break;
+ case Range::END_TO_START:
+ return compareBoundaryPoints( m_endContainer, m_endOffset,
+ sourceRange->startContainer(exceptioncode), sourceRange->startOffset(exceptioncode) );
+ break;
+ default:
+ exceptioncode = DOMException::SYNTAX_ERR;
+ return 0;
+ }
+}
+
+short RangeImpl::compareBoundaryPoints( NodeImpl *containerA, long offsetA, NodeImpl *containerB, long offsetB )
+{
+ // see DOM2 traversal & range section 2.5
+
+ // case 1: both points have the same container
+ if( containerA == containerB )
+ {
+ if( offsetA == offsetB ) return 0; // A is equal to B
+ if( offsetA < offsetB ) return -1; // A is before B
+ else return 1; // A is after B
+ }
+
+ // case 2: node C (container B or an ancestor) is a child node of A
+ NodeImpl *c = containerB;
+ while (c && c->parentNode() != containerA)
+ c = c->parentNode();
+ if (c) {
+ int offsetC = 0;
+ NodeImpl* n = containerA->firstChild();
+ while (n != c) {
+ offsetC++;
+ n = n->nextSibling();
+ }
+
+ if( offsetA <= offsetC ) return -1; // A is before B
+ else return 1; // A is after B
+ }
+
+ // case 3: node C (container A or an ancestor) is a child node of B
+ c = containerA;
+ while (c && c->parentNode() != containerB)
+ c = c->parentNode();
+ if (c) {
+ int offsetC = 0;
+ NodeImpl* n = containerB->firstChild();
+ while (n != c) {
+ offsetC++;
+ n = n->nextSibling();
+ }
+
+ if( offsetC < offsetB ) return -1; // A is before B
+ else return 1; // A is after B
+ }
+
+ // case 4: containers A & B are siblings, or children of siblings
+ // ### we need to do a traversal here instead
+ NodeImpl *cmnRoot = commonAncestorContainer(containerA,containerB);
+ if (!cmnRoot) return -1; // Whatever...
+ NodeImpl *childA = containerA;
+ while (childA->parentNode() != cmnRoot)
+ childA = childA->parentNode();
+ NodeImpl *childB = containerB;
+ while (childB->parentNode() != cmnRoot)
+ childB = childB->parentNode();
+
+ NodeImpl *n = cmnRoot->firstChild();
+ int i = 0;
+ int childAOffset = -1;
+ int childBOffset = -1;
+ while (childAOffset < 0 || childBOffset < 0) {
+ if (n == childA)
+ childAOffset = i;
+ if (n == childB)
+ childBOffset = i;
+ n = n->nextSibling();
+ i++;
+ }
+
+ if( childAOffset == childBOffset ) return 0; // A is equal to B
+ if( childAOffset < childBOffset ) return -1; // A is before B
+ else return 1; // A is after B
+}
+
+bool RangeImpl::boundaryPointsValid( )
+{
+ short valid = compareBoundaryPoints( m_startContainer, m_startOffset,
+ m_endContainer, m_endOffset );
+ if( valid == 1 ) return false;
+ else return true;
+
+}
+
+void RangeImpl::deleteContents( int &exceptioncode ) {
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ checkDeleteExtract(exceptioncode);
+ if (exceptioncode)
+ return;
+
+ processContents(DELETE_CONTENTS,exceptioncode);
+}
+
+DocumentFragmentImpl *RangeImpl::processContents ( ActionType action, int &exceptioncode )
+{
+ // ### when mutation events are implemented, we will have to take into account
+ // situations where the tree is being transformed while we delete - ugh!
+
+ // ### perhaps disable node deletion notification for this range while we do this?
+
+ if (collapsed(exceptioncode))
+ return 0;
+ if (exceptioncode)
+ return 0;
+
+ NodeImpl *cmnRoot = commonAncestorContainer(exceptioncode);
+ if (exceptioncode)
+ return 0;
+
+ // what is the highest node that partially selects the start of the range?
+ NodeImpl *partialStart = 0;
+ if (m_startContainer != cmnRoot) {
+ partialStart = m_startContainer;
+ while (partialStart->parentNode() != cmnRoot)
+ partialStart = partialStart->parentNode();
+ }
+
+ // what is the highest node that partially selects the end of the range?
+ NodeImpl *partialEnd = 0;
+ if (m_endContainer != cmnRoot) {
+ partialEnd = m_endContainer;
+ while (partialEnd->parentNode() != cmnRoot)
+ partialEnd = partialEnd->parentNode();
+ }
+
+ DocumentFragmentImpl *fragment = 0;
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
+ fragment = new DocumentFragmentImpl(m_ownerDocument);
+
+ // Simple case: the start and end containers are the same. We just grab
+ // everything >= start offset and < end offset
+ if (m_startContainer == m_endContainer) {
+ if(m_startContainer->nodeType() == Node::TEXT_NODE ||
+ m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
+ m_startContainer->nodeType() == Node::COMMENT_NODE) {
+
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
+ c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_endOffset,exceptioncode);
+ c->deleteData(0,m_startOffset,exceptioncode);
+ fragment->appendChild(c,exceptioncode);
+ }
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
+ static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(m_startOffset,m_endOffset-m_startOffset,exceptioncode);
+ }
+ else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
+ // ### operate just on data ?
+ }
+ else {
+ NodeImpl *n = m_startContainer->firstChild();
+ unsigned long i;
+ for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
+ n = n->nextSibling();
+ while (n && i < m_endOffset) { // delete until m_endOffset
+ NodeImpl *next = n->nextSibling();
+ if (action == EXTRACT_CONTENTS)
+ fragment->appendChild(n,exceptioncode); // will remove n from its parent
+ else if (action == CLONE_CONTENTS)
+ fragment->appendChild(n->cloneNode(true),exceptioncode);
+ else
+ m_startContainer->removeChild(n,exceptioncode);
+ n = next;
+ i++;
+ }
+ }
+ collapse(true,exceptioncode);
+ return fragment;
+ }
+
+ // Complex case: Start and end containers are different.
+ // There are three possiblities here:
+ // 1. Start container == cmnRoot (End container must be a descendant)
+ // 2. End container == cmnRoot (Start container must be a descendant)
+ // 3. Neither is cmnRoot, they are both descendants
+ //
+ // In case 3, we grab everything after the start (up until a direct child
+ // of cmnRoot) into leftContents, and everything before the end (up until
+ // a direct child of cmnRoot) into rightContents. Then we process all
+ // cmnRoot children between leftContents and rightContents
+ //
+ // In case 1 or 2, we skip either processing of leftContents or rightContents,
+ // in which case the last lot of nodes either goes from the first or last
+ // child of cmnRoot.
+ //
+ // These are deleted, cloned, or extracted (i.e. both) depending on action.
+
+ NodeImpl *leftContents = 0;
+ if (m_startContainer != cmnRoot) {
+ // process the left-hand side of the range, up until the last ancestor of
+ // m_startContainer before cmnRoot
+ if(m_startContainer->nodeType() == Node::TEXT_NODE ||
+ m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ||
+ m_startContainer->nodeType() == Node::COMMENT_NODE) {
+
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true));
+ c->deleteData(0,m_startOffset,exceptioncode);
+ leftContents = c;
+ }
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
+ static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(
+ m_startOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_startOffset,exceptioncode);
+ }
+ else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
+ // ### operate just on data ?
+ // leftContents = ...
+ }
+ else {
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
+ leftContents = m_startContainer->cloneNode(false);
+ NodeImpl *n = m_startContainer->firstChild();
+ unsigned long i;
+ for(i = 0; i < m_startOffset; i++) // skip until m_startOffset
+ n = n->nextSibling();
+ while (n) { // process until end
+ NodeImpl *next = n->nextSibling();
+ if (action == EXTRACT_CONTENTS)
+ leftContents->appendChild(n,exceptioncode); // will remove n from m_startContainer
+ else if (action == CLONE_CONTENTS)
+ leftContents->appendChild(n->cloneNode(true),exceptioncode);
+ else
+ m_startContainer->removeChild(n,exceptioncode);
+ n = next;
+ }
+ }
+
+ NodeImpl *leftParent = m_startContainer->parentNode();
+ NodeImpl *n = m_startContainer->nextSibling();
+ for (; leftParent != cmnRoot; leftParent = leftParent->parentNode()) {
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ NodeImpl *leftContentsParent = leftParent->cloneNode(false);
+ leftContentsParent->appendChild(leftContents,exceptioncode);
+ leftContents = leftContentsParent;
+ }
+
+ NodeImpl *next;
+ for (; n; n = next ) {
+ next = n->nextSibling();
+ if (action == EXTRACT_CONTENTS)
+ leftContents->appendChild(n,exceptioncode); // will remove n from leftParent
+ else if (action == CLONE_CONTENTS)
+ leftContents->appendChild(n->cloneNode(true),exceptioncode);
+ else
+ leftParent->removeChild(n,exceptioncode);
+ }
+ n = leftParent->nextSibling();
+ }
+ }
+
+ NodeImpl *rightContents = 0;
+ if (m_endContainer != cmnRoot) {
+ // delete the right-hand side of the range, up until the last ancestor of
+ // m_endContainer before cmnRoot
+ if(m_endContainer->nodeType() == Node::TEXT_NODE ||
+ m_endContainer->nodeType() == Node::CDATA_SECTION_NODE ||
+ m_endContainer->nodeType() == Node::COMMENT_NODE) {
+
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_endContainer->cloneNode(true));
+ c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_endContainer)->length()-m_endOffset,exceptioncode);
+ rightContents = c;
+ }
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
+ static_cast<CharacterDataImpl*>(m_endContainer)->deleteData(0,m_endOffset,exceptioncode);
+ }
+ else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
+ // ### operate just on data ?
+ // rightContents = ...
+ }
+ else {
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
+ rightContents = m_endContainer->cloneNode(false);
+ NodeImpl *n = m_endContainer->firstChild();
+ unsigned long i;
+ for(i = 0; i+1 < m_endOffset; i++) // skip to m_endOffset
+ n = n->nextSibling();
+ NodeImpl *prev;
+ for (; n; n = prev ) {
+ prev = n->previousSibling();
+ if (action == EXTRACT_CONTENTS)
+ rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
+ else if (action == CLONE_CONTENTS)
+ rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
+ else
+ m_endContainer->removeChild(n,exceptioncode);
+ }
+ }
+
+ NodeImpl *rightParent = m_endContainer->parentNode();
+ NodeImpl *n = m_endContainer->previousSibling();
+ for (; rightParent != cmnRoot; rightParent = rightParent->parentNode()) {
+ if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {
+ NodeImpl *rightContentsParent = rightParent->cloneNode(false);
+ rightContentsParent->appendChild(rightContents,exceptioncode);
+ rightContents = rightContentsParent;
+ }
+
+ NodeImpl *prev;
+ for (; n; n = prev ) {
+ prev = n->previousSibling();
+ if (action == EXTRACT_CONTENTS)
+ rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from its parent
+ else if (action == CLONE_CONTENTS)
+ rightContents->insertBefore(n->cloneNode(true),rightContents->firstChild(),exceptioncode);
+ else
+ rightParent->removeChild(n,exceptioncode);
+
+ }
+ n = rightParent->previousSibling();
+ }
+ }
+
+ // delete all children of cmnRoot between the start and end container
+
+ NodeImpl *processStart; // child of cmnRooot
+ if (m_startContainer == cmnRoot) {
+ unsigned long i;
+ processStart = m_startContainer->firstChild();
+ for (i = 0; i < m_startOffset; i++)
+ processStart = processStart->nextSibling();
+ }
+ else {
+ processStart = m_startContainer;
+ while (processStart->parentNode() != cmnRoot)
+ processStart = processStart->parentNode();
+ processStart = processStart->nextSibling();
+ }
+ NodeImpl *processEnd; // child of cmnRooot
+ if (m_endContainer == cmnRoot) {
+ unsigned long i;
+ processEnd = m_endContainer->firstChild();
+ for (i = 0; i < m_endOffset; i++)
+ processEnd = processEnd->nextSibling();
+ }
+ else {
+ processEnd = m_endContainer;
+ while (processEnd->parentNode() != cmnRoot)
+ processEnd = processEnd->parentNode();
+ }
+
+ // Now add leftContents, stuff in between, and rightContents to the fragment
+ // (or just delete the stuff in between)
+
+ if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents)
+ fragment->appendChild(leftContents,exceptioncode);
+
+ NodeImpl *next;
+ NodeImpl *n;
+ if (processStart) {
+ for (n = processStart; n && n != processEnd; n = next) {
+ next = n->nextSibling();
+
+ if (action == EXTRACT_CONTENTS)
+ fragment->appendChild(n,exceptioncode); // will remove from cmnRoot
+ else if (action == CLONE_CONTENTS)
+ fragment->appendChild(n->cloneNode(true),exceptioncode);
+ else
+ cmnRoot->removeChild(n,exceptioncode);
+ }
+ }
+
+ if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)
+ fragment->appendChild(rightContents,exceptioncode);
+
+ // collapse to the proper position - see spec section 2.6
+ if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
+ if (!partialStart && !partialEnd)
+ collapse(true,exceptioncode);
+ else if (partialStart) {
+ setStartContainer(partialStart->parentNode());
+ setEndContainer(partialStart->parentNode());
+ m_startOffset = m_endOffset = partialStart->nodeIndex()+1;
+ }
+ else if (partialEnd) {
+ setStartContainer(partialEnd->parentNode());
+ setEndContainer(partialEnd->parentNode());
+ m_startOffset = m_endOffset = partialEnd->nodeIndex();
+ }
+ }
+ return fragment;
+}
+
+
+DocumentFragmentImpl *RangeImpl::extractContents( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ checkDeleteExtract(exceptioncode);
+ if (exceptioncode)
+ return 0;
+
+ return processContents(EXTRACT_CONTENTS,exceptioncode);
+}
+
+DocumentFragmentImpl *RangeImpl::cloneContents( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return processContents(CLONE_CONTENTS,exceptioncode);
+}
+
+void RangeImpl::insertNode( NodeImpl *newNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
+ // the Range is read-only.
+ NodeImpl *n = m_startContainer;
+ while (n && !n->isReadOnly())
+ n = n->parentNode();
+ if (n) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ n = m_endContainer;
+ while (n && !n->isReadOnly())
+ n = n->parentNode();
+ if (n) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
+ // not created from the same document.
+ if (newNode->getDocument() != m_startContainer->getDocument()) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+
+ // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
+ // does not allow children of the type of newNode or if newNode is an ancestor of the container.
+
+ // an extra one here - if a text node is going to split, it must have a parent to insert into
+ if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+
+ // In the case where the container is a text node, we check against the container's parent, because
+ // text nodes get split up upon insertion.
+ NodeImpl *checkAgainst;
+ if (m_startContainer->nodeType() == Node::TEXT_NODE)
+ checkAgainst = m_startContainer->parentNode();
+ else
+ checkAgainst = m_startContainer;
+
+ if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
+ // check each child node, not the DocumentFragment itself
+ NodeImpl *c;
+ for (c = newNode->firstChild(); c; c = c->nextSibling()) {
+ if (!checkAgainst->childTypeAllowed(c->nodeType())) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+ }
+ else {
+ if (!checkAgainst->childTypeAllowed(newNode->nodeType())) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+
+ for (n = m_startContainer; n; n = n->parentNode()) {
+ if (n == newNode) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+
+ // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node.
+ if( newNode->nodeType() == Node::ATTRIBUTE_NODE ||
+ newNode->nodeType() == Node::ENTITY_NODE ||
+ newNode->nodeType() == Node::NOTATION_NODE ||
+ newNode->nodeType() == Node::DOCUMENT_NODE) {
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+
+ if( m_startContainer->nodeType() == Node::TEXT_NODE ||
+ m_startContainer->nodeType() == Node::CDATA_SECTION_NODE )
+ {
+ TextImpl *newText = static_cast<TextImpl*>(m_startContainer)->splitText(m_startOffset,exceptioncode);
+ if (exceptioncode)
+ return;
+ m_startContainer->parentNode()->insertBefore( newNode, newText, exceptioncode );
+ }
+ else {
+ m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), exceptioncode );
+ }
+}
+
+DOMString RangeImpl::toString( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return DOMString();
+ }
+
+ DOMString text = "";
+ NodeImpl *n = m_startContainer;
+
+ /* This function converts a dom range to the plain text string that the user would see in this
+ * portion of rendered html.
+ *
+ * There are several ways ranges can be used.
+ *
+ * The simplest is the start and endContainer is a text node. The start and end offset is the
+ * number of characters into the text to remove/truncate.
+ *
+ * The next case is the start and endContainer is, well, a container, such a P tag or DIV tag.
+ * In this case the start and end offset is the number of children into the container to start
+ * from and end at.
+ *
+ * The other cases are different arrangements of the first two.
+ *
+ * psuedo code:
+ *
+ * if start container is not text:
+ * count through the children to find where we start (m_startOffset children)
+ *
+ * loop from the start position:
+ * if the current node is text, add the text to our variable 'text', truncating/removing if at the end/start.
+ *
+ * if the node has children, step to the first child.
+ * if the node has no children but does have siblings, step to the next sibling
+ * until we find a sibling, go to next the parent but:
+ * make sure this sibling isn't past the end of where we are supposed to go. (position > endOffset and the parent is the endContainer)
+ *
+ */
+
+
+ if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)
+ return text;
+
+
+ if(n->firstChild()) {
+ n = n->firstChild();
+ int current_offset = m_startOffset;
+ while(current_offset-- && n) {
+ n = n->nextSibling();
+ }
+ }
+
+ while(n) {
+ if(n->nodeType() == DOM::Node::TEXT_NODE ||
+ n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
+
+ DOMString str;
+ str = static_cast<TextImpl *>(n)->string();
+ if( n == m_endContainer || n == m_startContainer)
+ str = str.copy(); //copy if we are going to modify.
+
+ if (n == m_endContainer)
+ str.truncate(m_endOffset);
+ if (n == m_startContainer)
+ str.remove(0,m_startOffset);
+ text += str;
+ if (n == m_endContainer)
+ break;
+ }
+
+
+ NodeImpl *next = n->firstChild();
+ if(!next)
+ next = n->nextSibling();
+
+ while( !next && n->parentNode() ) {
+ if (n == m_endContainer) return text;
+ n = n->parentNode();
+ if (n == m_endContainer) return text;
+ next = n->nextSibling();
+ }
+
+ if(n->parentNode() == m_endContainer) {
+ if(!next) break;
+ unsigned long current_offset = 0;
+ NodeImpl *it = n;
+ while((it = it->previousSibling())) ++current_offset;
+ if(current_offset >= m_endOffset) {
+ break;
+ }
+ }
+
+ n = next;
+ }
+ return text;
+}
+
+DOMString RangeImpl::toHTML( int &exceptioncode )
+{
+ bool hasHtmlTag = false;
+ bool hasBodyTag = false;
+ //FIXME: What is this section of code below exactly? Do I want it here?
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return DOMString();
+ }
+ DOMString text = "";
+ NodeImpl *n = m_startContainer;
+ int num_tables=0;
+ bool in_li = false; //whether we have an li in the text, without an ol/ul
+ int depth_difference = 0;
+ int lowest_depth_difference = 0;
+
+ if( m_startContainer == m_endContainer && m_startOffset >= m_endOffset)
+ return text;
+
+ while(n) {
+ /* First, we could have an tag <tagname key=value>otherstuff</tagname> */
+ if(n->nodeType() == DOM::Node::ELEMENT_NODE) {
+ int elementId = static_cast<ElementImpl *>(n)->id();
+ if(elementId == ID_TABLE) num_tables++;
+ if(elementId == ID_BODY) hasBodyTag = true;
+ if(elementId == ID_HTML) hasHtmlTag = true;
+ if(elementId == ID_LI) in_li=true;
+ if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables++;
+ if(!( !n->hasChildNodes() && (elementId == ID_H1 || elementId == ID_H2 || elementId == ID_H3 || elementId == ID_H4 || elementId ==ID_H5))) { //Don't add <h1/> etc. Just skip these nodes just to make the output html a bit nicer.
+ text += static_cast<ElementImpl *>(n)->openTagStartToString(true /*safely expand img urls*/); // adds "<tagname key=value"
+ if(n->hasChildNodes()) {
+ depth_difference++;
+ text += ">";
+ } else {
+ text += "/>";
+ }
+ }
+ } else
+ if(n->nodeType() == DOM::Node::TEXT_NODE ||
+ n->nodeType() == DOM::Node::CDATA_SECTION_NODE) {
+ if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += "<![CDATA[ ";
+ long long startOffset = (n == m_startContainer)?(long long)m_startOffset:-1;
+ long long endOffset = (n == m_endContainer)?(long long) m_endOffset:-1;
+ text += static_cast<TextImpl *>(n)->toString(startOffset, endOffset); //Note this should always work since CDataImpl inherits TextImpl
+ if(n->nodeType() == DOM::Node::CDATA_SECTION_NODE) text += " ]]>";
+ if(n == m_endContainer) {
+ break;
+ }
+ }
+ if(n->parentNode() == m_endContainer && !n->nextSibling()) {
+ break;
+ }
+
+ //if (n == m_endContainer) break;
+ NodeImpl *next = n->firstChild();
+ if(next) {
+ if(n == m_startContainer) {
+ //This is the start of our selection, so we have to move to where we have started selecting.
+ //For example, if 'n' is "hello <img src='hello.png'> how are you? <img src='goodbye.png'>"
+ //then this has four children. If our selection started on the image, then we need to start from there.
+ unsigned long current_offset = 0;
+ while(current_offset < m_startOffset && next) {
+ next = next->nextSibling();
+ ++current_offset;
+ }
+ }
+ } else {
+ next = n->nextSibling();
+
+ if(n->parentNode() == m_endContainer) {
+ unsigned long current_offset = 1;
+ NodeImpl *it = n;
+ while((it = it->previousSibling())) ++current_offset;
+
+ if(current_offset >= m_endOffset) {
+ break;
+ }
+ }
+ }
+
+ while( !next && n->parentNode() ) {
+ n = n->parentNode();
+ if(n->nodeType() == DOM::Node::ELEMENT_NODE) {
+ text += "</";
+ text += static_cast<ElementImpl *>(n)->tagName();
+ int elementId = static_cast<ElementImpl *>(n)->id();
+ if(elementId == ID_TABLE) num_tables--;
+ depth_difference--;
+ if(lowest_depth_difference > depth_difference) lowest_depth_difference=depth_difference;
+ if(num_tables==0 && ( elementId == ID_TD || elementId == ID_TR || elementId == ID_TH || elementId == ID_TBODY || elementId == ID_TFOOT || elementId == ID_THEAD)) num_tables--;
+ if(elementId == ID_OL || elementId == ID_UL) in_li=false;
+ text += ">";
+ }
+ next = n->nextSibling();
+ }
+ n = next;
+ }
+
+ //We have the html in the selection. But now we need to properly add the opening and closing tags.
+ //For example say we have: "Hello <b>Mr. John</b> How are you?" and we select "John" or even
+ //"John</b> How" and copy. We want to return "<b>John</b>" and "<b>John</b> How" respectively
+
+ //To do this, we need to go up the tree from the start, and prepend those tags.
+ //Imagine our selection was this:
+ //
+ // hello</b></p><p>there
+ //
+ // The difference in depths between the start and end is -1, and the lowest depth
+ // difference from the starting point is -2
+ //
+ // So from the start of the selection, we want to go down to the lowest_depth_difference
+ // and prepend those tags. (<p><b>)
+ //
+ // From the end of the selection, we want to also go down to the lowest_depth_difference.
+ // We know the depth of the end of the selection - i.e. depth_difference.
+ //
+ //
+ n = m_startContainer;
+ int startdepth = 0; //by definition - we are counting from zero.
+ while((n = n->parentNode()) && startdepth>lowest_depth_difference) {
+ if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
+ switch (static_cast<ElementImpl *>(n)->id()) {
+ case ID_TABLE:
+ num_tables--;
+ break;
+ case ID_BODY:
+ hasBodyTag = true;
+ break;
+ case ID_HTML:
+ hasHtmlTag = true;
+ break;
+ case ID_LI:
+ in_li = true;
+ break;
+ }
+ text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text; // prepends "<tagname key=value>"
+ }
+ startdepth--;
+ }
+ n = m_endContainer;
+ while( depth_difference>lowest_depth_difference && (n = n->parentNode())) {
+ if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
+ switch (static_cast<ElementImpl *>(n)->id()) {
+ case ID_TABLE:
+ num_tables++;
+ break;
+ case ID_OL:
+ case ID_UL:
+ in_li=false;
+ break;
+ }
+ text += "</";
+ text += static_cast<ElementImpl *>(n)->tagName();
+ text += ">";
+ }
+ depth_difference--;
+ }
+
+ // Now our text string is the same depth on both sides, with nothing lower (in other words all the
+ // tags in it match up.) This also means that the end value for n in the first loop is a sibling of the
+ // end value for n in the second loop.
+ //
+ // We now need to go down the tree, and for certain tags, add them in on both ends of the text.
+ // For example, if have: "<b>hello</b>" and we select "ll", then we want to go down the tree and
+ // add "<b>" and "</b>" to it, to produce "<b>ll</b>".
+ //
+ // I just guessed at which tags you'd want to keep (bold, italic etc) and which you wouldn't (tables etc).
+ // It's just wild guessing. feel free to change.
+ //
+ // Note we can carry on with the value of n
+ if(n) {
+ while((n = n->parentNode())) {
+ if(n->nodeType() == DOM::Node::ELEMENT_NODE) { //This should always be true.. right?
+ int elementId = static_cast<ElementImpl *>(n)->id();
+ switch (elementId) {
+ case ID_TABLE:
+ case ID_TD:
+ case ID_TR:
+ case ID_TH:
+ case ID_TBODY:
+ case ID_TFOOT:
+ case ID_THEAD:
+ if(num_tables>0) {
+ if(elementId == ID_TABLE) num_tables--;
+ text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
+ text += "</";
+ text += static_cast<ElementImpl *>(n)->tagName();
+ text += ">";
+
+ }
+ break;
+
+ case ID_LI:
+ if(!in_li) break;
+ text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
+ text += "</";
+ text += static_cast<ElementImpl *>(n)->tagName();
+ text += ">";
+ break;
+
+ case ID_UL:
+ case ID_OL:
+ if(!in_li) break;
+ in_li = false;
+ case ID_B:
+ case ID_I:
+ case ID_U:
+ case ID_FONT:
+ case ID_S:
+ case ID_STRONG:
+ case ID_STRIKE:
+ case ID_DEL:
+ case ID_A:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ //should small, etc be here? so hard to decide. this is such a hack :(
+ //There's probably tons of others you'd want here.
+ text = static_cast<ElementImpl *>(n)->openTagStartToString(true /*expand img urls*/)+">" +text;
+ text += "</";
+ text += static_cast<ElementImpl *>(n)->tagName();
+ text += ">";
+ break;
+ }
+ }
+ }
+ }
+
+
+ if(!hasBodyTag) text = DOMString("<body>") + text + "</body>";
+ else if(!hasHtmlTag) {
+ text = DOMString("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+ "<head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
+ "<meta name=\"Generator\" content=\"KHTML, the KDE Web Page Viewer\" />\n"
+ "</head>\n") +
+ text +
+ "</html>";
+ }
+ text = DOMString("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n") + text;
+
+ return text;
+
+}
+
+DocumentFragment RangeImpl::createContextualFragment ( const DOMString &html, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return DocumentFragment();
+ }
+
+ if (! m_startContainer->isHTMLElement()) {
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+ return DocumentFragment();
+ }
+
+ HTMLElementImpl *e = static_cast<HTMLElementImpl *>(m_startContainer);
+ DocumentFragment fragment = e->createContextualFragment(html);
+ if (fragment.isNull()) {
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+ return DocumentFragment();
+ }
+
+ return fragment;
+}
+
+
+void RangeImpl::detach( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (m_startContainer)
+ m_startContainer->deref();
+ m_startContainer = 0;
+ if (m_endContainer)
+ m_endContainer->deref();
+ m_endContainer = 0;
+ m_detached = true;
+}
+
+bool RangeImpl::isDetached() const
+{
+ return m_detached;
+}
+
+void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const
+{
+ if( offset < 0 ) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ }
+
+ switch (n->nodeType()) {
+ case Node::ENTITY_NODE:
+ case Node::NOTATION_NODE:
+ case Node::DOCUMENT_TYPE_NODE:
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ break;
+ case Node::TEXT_NODE:
+ case Node::COMMENT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ if ( (unsigned long)offset > static_cast<CharacterDataImpl*>(n)->length() )
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ break;
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ // ### are we supposed to check with just data or the whole contents?
+ if ( (unsigned long)offset > static_cast<ProcessingInstructionImpl*>(n)->data().length() )
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ break;
+ default:
+ if ( (unsigned long)offset > n->childNodeCount() )
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ break;
+ }
+}
+
+void RangeImpl::checkNodeBA( NodeImpl *n, int &exceptioncode ) const
+{
+ // INVALID_NODE_TYPE_ERR: Raised if the root container of refNode is not an
+ // Attr, Document or DocumentFragment node or if refNode is a Document,
+ // DocumentFragment, Attr, Entity, or Notation node.
+ NodeImpl *root = n;
+ while (root->parentNode())
+ root = root->parentNode();
+ if (!(root->nodeType() == Node::ATTRIBUTE_NODE ||
+ root->nodeType() == Node::DOCUMENT_NODE ||
+ root->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)) {
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+
+ if( n->nodeType() == Node::DOCUMENT_NODE ||
+ n->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
+ n->nodeType() == Node::ATTRIBUTE_NODE ||
+ n->nodeType() == Node::ENTITY_NODE ||
+ n->nodeType() == Node::NOTATION_NODE )
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+
+}
+
+RangeImpl *RangeImpl::cloneRange(int &exceptioncode)
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ return new RangeImpl(m_ownerDocument,m_startContainer,m_startOffset,m_endContainer,m_endOffset);
+}
+
+void RangeImpl::setStartAfter( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeBA( refNode, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setStart( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
+}
+
+void RangeImpl::setEndBefore( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeBA( refNode, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setEnd( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
+}
+
+void RangeImpl::setEndAfter( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeBA( refNode, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setEnd( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
+
+}
+
+void RangeImpl::selectNode( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ // INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
+ // DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
+ // node.
+ NodeImpl *anc;
+ for (anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
+ if (anc->nodeType() == Node::ENTITY_NODE ||
+ anc->nodeType() == Node::NOTATION_NODE ||
+ anc->nodeType() == Node::DOCUMENT_TYPE_NODE) {
+
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+ }
+
+ if (refNode->nodeType() == Node::DOCUMENT_NODE ||
+ refNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
+ refNode->nodeType() == Node::ATTRIBUTE_NODE ||
+ refNode->nodeType() == Node::ENTITY_NODE ||
+ refNode->nodeType() == Node::NOTATION_NODE) {
+
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+
+ setStartBefore( refNode, exceptioncode );
+ if (exceptioncode)
+ return;
+ setEndAfter( refNode, exceptioncode );
+}
+
+void RangeImpl::selectNodeContents( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ // INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
+ // or DocumentType node.
+ NodeImpl *n;
+ for (n = refNode; n; n = n->parentNode()) {
+ if (n->nodeType() == Node::ENTITY_NODE ||
+ n->nodeType() == Node::NOTATION_NODE ||
+ n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
+
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+ }
+
+ setStartContainer(refNode);
+ m_startOffset = 0;
+ setEndContainer(refNode);
+ m_endOffset = refNode->childNodeCount();
+}
+
+void RangeImpl::surroundContents( NodeImpl *newParent, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if( !newParent ) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ // INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
+ // Document, or DocumentFragment node.
+ if( newParent->nodeType() == Node::ATTRIBUTE_NODE ||
+ newParent->nodeType() == Node::ENTITY_NODE ||
+ newParent->nodeType() == Node::NOTATION_NODE ||
+ newParent->nodeType() == Node::DOCUMENT_TYPE_NODE ||
+ newParent->nodeType() == Node::DOCUMENT_NODE ||
+ newParent->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
+ exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
+ // the Range is read-only.
+ if (readOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ NodeImpl *n = m_startContainer;
+ while (n && !n->isReadOnly())
+ n = n->parentNode();
+ if (n) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ n = m_endContainer;
+ while (n && !n->isReadOnly())
+ n = n->parentNode();
+ if (n) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
+ // not created from the same document.
+ if (newParent->getDocument() != m_startContainer->getDocument()) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
+ // does not allow children of the type of newParent or if newParent is an ancestor of the container
+ // or if node would end up with a child node of a type not allowed by the type of node.
+ if (!m_startContainer->childTypeAllowed(newParent->nodeType())) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+
+ for (n = m_startContainer; n; n = n->parentNode()) {
+ if (n == newParent) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+
+ // ### check if node would end up with a child node of a type not allowed by the type of node
+
+ // BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text node.
+ if (m_startContainer->nodeType() != Node::TEXT_NODE &&
+ m_startContainer->nodeType() != Node::COMMENT_NODE &&
+ m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
+ m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
+
+ if (m_startOffset > 0 && m_startOffset < m_startContainer->childNodeCount()) {
+ exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+ }
+
+ if (m_endContainer->nodeType() != Node::TEXT_NODE &&
+ m_endContainer->nodeType() != Node::COMMENT_NODE &&
+ m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
+ m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
+
+ if (m_endOffset > 0 && m_endOffset < m_endContainer->childNodeCount()) {
+ exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
+ return;
+ }
+ }
+
+ while (newParent->firstChild()) {
+ newParent->removeChild(newParent->firstChild(),exceptioncode);
+ if (exceptioncode)
+ return;
+ }
+ DocumentFragmentImpl *fragment = extractContents(exceptioncode);
+ if (exceptioncode)
+ return;
+ insertNode( newParent, exceptioncode );
+ if (exceptioncode)
+ return;
+ newParent->appendChild( fragment, exceptioncode );
+ if (exceptioncode)
+ return;
+ selectNode( newParent, exceptioncode );
+}
+
+void RangeImpl::setStartBefore( NodeImpl *refNode, int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return;
+ }
+
+ if (!refNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ if (refNode->getDocument() != m_ownerDocument) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ checkNodeBA( refNode, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ setStart( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
+}
+
+void RangeImpl::setStartContainer(NodeImpl *_startContainer)
+{
+ if (m_startContainer == _startContainer)
+ return;
+
+ if (m_startContainer)
+ m_startContainer->deref();
+ m_startContainer = _startContainer;
+ if (m_startContainer)
+ m_startContainer->ref();
+}
+
+void RangeImpl::setEndContainer(NodeImpl *_endContainer)
+{
+ if (m_endContainer == _endContainer)
+ return;
+
+ if (m_endContainer)
+ m_endContainer->deref();
+ m_endContainer = _endContainer;
+ if (m_endContainer)
+ m_endContainer->ref();
+}
+
+void RangeImpl::checkDeleteExtract(int &exceptioncode) {
+
+ NodeImpl *start;
+ if (m_startContainer->nodeType() != Node::TEXT_NODE &&
+ m_startContainer->nodeType() != Node::CDATA_SECTION_NODE &&
+ m_startContainer->nodeType() != Node::COMMENT_NODE &&
+ m_startContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
+
+ start = m_startContainer->childNode(m_startOffset);
+ if (!start) {
+ if (m_startContainer->lastChild())
+ start = m_startContainer->lastChild()->traverseNextNode();
+ else
+ start = m_startContainer->traverseNextNode();
+ }
+ }
+ else
+ start = m_startContainer;
+
+ NodeImpl *end;
+ if (m_endContainer->nodeType() != Node::TEXT_NODE &&
+ m_endContainer->nodeType() != Node::CDATA_SECTION_NODE &&
+ m_endContainer->nodeType() != Node::COMMENT_NODE &&
+ m_endContainer->nodeType() != Node::PROCESSING_INSTRUCTION_NODE) {
+
+ end = m_endContainer->childNode(m_endOffset);
+ if (!end) {
+ if (m_endContainer->lastChild())
+ end = m_endContainer->lastChild()->traverseNextNode();
+ else
+ end = m_endContainer->traverseNextNode();
+ }
+ }
+ else
+ end = m_endContainer;
+
+ NodeImpl *n;
+ for (n = start; n != end; n = n->traverseNextNode()) {
+ if (n->isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+ if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { // ### is this for only directly under the DF, or anywhere?
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+
+ if (containedByReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+}
+
+
+bool RangeImpl::containedByReadOnly() {
+ NodeImpl *n;
+ for (n = m_startContainer; n; n = n->parentNode()) {
+ if (n->isReadOnly())
+ return true;
+ }
+ for (n = m_endContainer; n; n = n->parentNode()) {
+ if (n->isReadOnly())
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+
+
+
diff --git a/tdehtml/xml/dom2_rangeimpl.h b/tdehtml/xml/dom2_rangeimpl.h
new file mode 100644
index 000000000..9cf7a3b23
--- /dev/null
+++ b/tdehtml/xml/dom2_rangeimpl.h
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _DOM2_RangeImpl_h_
+#define _DOM2_RangeImpl_h_
+
+#include "dom/dom2_range.h"
+#include "misc/shared.h"
+
+namespace DOM {
+
+class RangeImpl : public tdehtml::Shared<RangeImpl>
+{
+ friend class DocumentImpl;
+public:
+ RangeImpl(DocumentImpl *_ownerDocument);
+ RangeImpl(DocumentImpl *_ownerDocument,
+ NodeImpl *_startContainer, long _startOffset,
+ NodeImpl *_endContainer, long _endOffset);
+
+ ~RangeImpl();
+
+ NodeImpl *startContainer(int &exceptioncode) const;
+ long startOffset(int &exceptioncode) const;
+ NodeImpl *endContainer(int &exceptioncode) const;
+ long endOffset(int &exceptioncode) const;
+ bool collapsed(int &exceptioncode) const;
+
+ NodeImpl *commonAncestorContainer(int &exceptioncode);
+ static NodeImpl *commonAncestorContainer(NodeImpl *containerA, NodeImpl *containerB);
+ void setStart ( NodeImpl *refNode, long offset, int &exceptioncode );
+ void setEnd ( NodeImpl *refNode, long offset, int &exceptioncode );
+ void collapse ( bool toStart, int &exceptioncode );
+ short compareBoundaryPoints ( Range::CompareHow how, RangeImpl *sourceRange, int &exceptioncode );
+ static short compareBoundaryPoints ( NodeImpl *containerA, long offsetA, NodeImpl *containerB, long offsetB );
+ bool boundaryPointsValid ( );
+ void deleteContents ( int &exceptioncode );
+ DocumentFragmentImpl *extractContents ( int &exceptioncode );
+ DocumentFragmentImpl *cloneContents ( int &exceptioncode );
+ void insertNode( NodeImpl *newNode, int &exceptioncode );
+ DOMString toString ( int &exceptioncode );
+ /** Converts the selection to HTML. The returned string will have matching
+ * tags, and all td, tr, etc tags will be inside a table tag. CSS is not
+ * used at this stage - This needs to be fixed.
+ *
+ * This is guaranteed to produce an xml valid snippet, no matter how crappy the input
+ * html page is. It will have html and body tags.
+ *
+ * Any urls in images or links will be expanded to full urls <em>with passwords stripped</em>
+ * for security reasons.
+ *
+ * Note: Originally this function didn't have the exceptioncode argument. I added it
+ * since all the other functions do. If this is correct, please remove this comment.
+ *
+ * @param exceptioncode This will be set if m_detached is true.
+ * @return A string with html tags for this range.
+ *
+ * @since 3.4
+ */
+ DOMString toHTML ( int &exceptioncode );
+
+ DocumentFragment createContextualFragment ( const DOMString &html, int &exceptioncode );
+
+ void detach ( int &exceptioncode );
+ bool isDetached() const;
+ RangeImpl *cloneRange(int &exceptioncode);
+
+ void setStartAfter( NodeImpl *refNode, int &exceptioncode );
+ void setEndBefore( NodeImpl *refNode, int &exceptioncode );
+ void setEndAfter( NodeImpl *refNode, int &exceptioncode );
+ void selectNode( NodeImpl *refNode, int &exceptioncode );
+ void selectNodeContents( NodeImpl *refNode, int &exceptioncode );
+ void surroundContents( NodeImpl *newParent, int &exceptioncode );
+ void setStartBefore( NodeImpl *refNode, int &exceptioncode );
+
+ enum ActionType {
+ DELETE_CONTENTS,
+ EXTRACT_CONTENTS,
+ CLONE_CONTENTS
+ };
+ DocumentFragmentImpl *processContents ( ActionType action, int &exceptioncode );
+
+ bool readOnly() { return false; }
+
+protected:
+ DocumentImpl *m_ownerDocument;
+ NodeImpl *m_startContainer;
+ unsigned long m_startOffset;
+ NodeImpl *m_endContainer;
+ unsigned long m_endOffset;
+ bool m_detached;
+
+private:
+ void checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const;
+ void checkNodeBA( NodeImpl *n, int &exceptioncode ) const;
+ void setStartContainer(NodeImpl *_startContainer);
+ void setEndContainer(NodeImpl *_endContainer);
+ void checkDeleteExtract(int &exceptioncode);
+ bool containedByReadOnly();
+};
+
+} // namespace
+
+#endif
+
diff --git a/tdehtml/xml/dom2_traversalimpl.cpp b/tdehtml/xml/dom2_traversalimpl.cpp
new file mode 100644
index 000000000..2abdadead
--- /dev/null
+++ b/tdehtml/xml/dom2_traversalimpl.cpp
@@ -0,0 +1,667 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ */
+
+#include "dom/dom_exception.h"
+#include "xml/dom_docimpl.h"
+
+using namespace DOM;
+
+NodeIteratorImpl::NodeIteratorImpl(NodeImpl *_root, unsigned long _whatToShow,
+ NodeFilter _filter, bool _entityReferenceExpansion)
+{
+ m_root = _root;
+ m_whatToShow = _whatToShow;
+ m_filter = _filter;
+ m_expandEntityReferences = _entityReferenceExpansion;
+
+ m_referenceNode = _root;
+ m_inFront = false;
+
+ m_doc = m_root->getDocument();
+ m_doc->attachNodeIterator(this);
+ m_doc->ref();
+
+ m_detached = false;
+}
+
+NodeIteratorImpl::~NodeIteratorImpl()
+{
+ m_doc->detachNodeIterator(this);
+ m_doc->deref();
+}
+
+NodeImpl *NodeIteratorImpl::root()
+{
+ return m_root;
+}
+
+unsigned long NodeIteratorImpl::whatToShow()
+{
+ return m_whatToShow;
+}
+
+NodeFilter NodeIteratorImpl::filter()
+{
+ return m_filter;
+}
+
+bool NodeIteratorImpl::expandEntityReferences()
+{
+ return m_expandEntityReferences;
+}
+
+NodeImpl *NodeIteratorImpl::nextNode( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ if (!m_referenceNode) {
+ m_inFront = true;
+ return 0;
+ }
+
+ if (!m_inFront) {
+ m_inFront = true;
+ if (isAccepted(m_referenceNode) == NodeFilter::FILTER_ACCEPT)
+ return m_referenceNode;
+ }
+
+ NodeImpl *_tempCurrent = getNextNode(m_referenceNode);
+ while( _tempCurrent ) {
+ m_referenceNode = _tempCurrent;
+ if(isAccepted(_tempCurrent) == NodeFilter::FILTER_ACCEPT)
+ return m_referenceNode;
+ _tempCurrent = getNextNode(_tempCurrent);
+ }
+
+ return 0;
+}
+
+NodeImpl *NodeIteratorImpl::getNextNode(NodeImpl *n)
+{
+ /* 1. my first child
+ * 2. my next sibling
+ * 3. my parents sibling, or their parents sibling (loop)
+ * 4. not found
+ */
+
+ if( !n )
+ return 0;
+
+ if( n->hasChildNodes() )
+ return n->firstChild();
+
+ if( m_root == n)
+ return 0;
+
+ if( n->nextSibling() )
+ return n->nextSibling();
+
+ NodeImpl *parent = n->parentNode();
+ while( parent )
+ {
+ if( m_root == parent )
+ return 0;
+
+ n = parent->nextSibling();
+ if( n )
+ return n;
+
+ parent = parent->parentNode();
+ }
+ return 0;
+}
+
+NodeImpl *NodeIteratorImpl::previousNode( int &exceptioncode )
+{
+ if (m_detached) {
+ exceptioncode = DOMException::INVALID_STATE_ERR;
+ return 0;
+ }
+
+ if (!m_referenceNode) {
+ m_inFront = false;
+ return 0;
+ }
+
+ if (m_inFront) {
+ m_inFront = false;
+ if (isAccepted(m_referenceNode) == NodeFilter::FILTER_ACCEPT)
+ return m_referenceNode;
+ }
+
+ NodeImpl *_tempCurrent = getPreviousNode(m_referenceNode);
+ while( _tempCurrent ) {
+ m_referenceNode = _tempCurrent;
+ if(isAccepted(_tempCurrent) == NodeFilter::FILTER_ACCEPT)
+ return m_referenceNode;
+ _tempCurrent = getPreviousNode(_tempCurrent);
+ }
+
+ return 0;
+}
+
+NodeImpl *NodeIteratorImpl::getPreviousNode(NodeImpl *n)
+{
+/* 1. my previous sibling.lastchild
+ * 2. my previous sibling
+ * 3. my parent
+ */
+ NodeImpl *_tempCurrent;
+
+ if( !n || m_root == n )
+ return 0;
+
+ _tempCurrent = n->previousSibling();
+ if( _tempCurrent )
+ {
+ if( _tempCurrent->lastChild() )
+ {
+ while( _tempCurrent->lastChild() )
+ _tempCurrent = _tempCurrent->lastChild();
+ return _tempCurrent;
+ }
+ else
+ return _tempCurrent;
+ }
+
+ return n->parentNode();
+
+}
+
+void NodeIteratorImpl::detach(int &/*exceptioncode*/)
+{
+ m_doc->detachNodeIterator(this);
+ m_detached = true;
+}
+
+
+void NodeIteratorImpl::notifyBeforeNodeRemoval(NodeImpl *removed)
+{
+ // make sure the deleted node is with the root (but not the root itself)
+ if (removed == m_root)
+ return;
+
+ NodeImpl *maybeRoot = removed->parentNode();
+ while (maybeRoot && maybeRoot != m_root)
+ maybeRoot = maybeRoot->parentNode();
+ if (!maybeRoot)
+ return;
+
+ // did I get deleted, or one of my parents?
+ NodeImpl *_tempDeleted = m_referenceNode;
+ while( _tempDeleted && _tempDeleted != removed)
+ _tempDeleted = _tempDeleted->parentNode();
+
+ if( !_tempDeleted ) // someone that didn't consern me got deleted
+ return;
+
+ if( !m_inFront)
+ {
+ NodeImpl *_next = getNextNode(_tempDeleted);
+ if( _next )
+ m_referenceNode = _next;
+ else
+ {
+ // deleted node was at end of list
+ m_inFront = true;
+ m_referenceNode = getPreviousNode(_tempDeleted);
+ }
+ }
+ else {
+ NodeImpl *_prev = getPreviousNode(_tempDeleted);
+ if ( _prev )
+ m_referenceNode = _prev;
+ else
+ {
+ // deleted node was at start of list
+ m_inFront = false;
+ m_referenceNode = getNextNode(_tempDeleted);
+ }
+ }
+
+}
+
+short NodeIteratorImpl::isAccepted(NodeImpl *n)
+{
+ // if XML is implemented we have to check expandEntityRerefences in this function
+ if( ( ( 1 << ( n->nodeType()-1 ) ) & m_whatToShow) != 0 )
+ {
+ if(!m_filter.isNull())
+ return m_filter.acceptNode(n);
+ else
+ return NodeFilter::FILTER_ACCEPT;
+ }
+ return NodeFilter::FILTER_SKIP;
+}
+
+// --------------------------------------------------------------
+
+
+NodeFilterImpl::NodeFilterImpl()
+{
+ m_customNodeFilter = 0;
+}
+
+NodeFilterImpl::~NodeFilterImpl()
+{
+ if (m_customNodeFilter)
+ m_customNodeFilter->deref();
+}
+
+short NodeFilterImpl::acceptNode(const Node &n)
+{
+ if (m_customNodeFilter)
+ return m_customNodeFilter->acceptNode(n);
+ else
+ return NodeFilter::FILTER_ACCEPT;
+}
+
+void NodeFilterImpl::setCustomNodeFilter(CustomNodeFilter *custom)
+{
+ m_customNodeFilter = custom;
+ if (m_customNodeFilter)
+ m_customNodeFilter->ref();
+}
+
+CustomNodeFilter *NodeFilterImpl::customNodeFilter()
+{
+ return m_customNodeFilter;
+}
+
+// --------------------------------------------------------------
+
+TreeWalkerImpl::TreeWalkerImpl(NodeImpl *n, long _whatToShow, NodeFilterImpl *f,
+ bool entityReferenceExpansion)
+{
+ m_currentNode = n;
+ m_rootNode = n;
+ m_whatToShow = _whatToShow;
+ m_filter = f;
+ if ( m_filter )
+ m_filter->ref();
+ m_expandEntityReferences = entityReferenceExpansion;
+ m_doc = m_rootNode->getDocument();
+ m_doc->ref();
+}
+
+TreeWalkerImpl::~TreeWalkerImpl()
+{
+ m_doc->deref();
+ if ( m_filter )
+ m_filter->deref();
+}
+
+NodeImpl *TreeWalkerImpl::getRoot() const
+{
+ return m_rootNode;
+}
+
+unsigned long TreeWalkerImpl::getWhatToShow() const
+{
+ return m_whatToShow;
+}
+
+NodeFilterImpl *TreeWalkerImpl::getFilter() const
+{
+ return m_filter;
+}
+
+bool TreeWalkerImpl::getExpandEntityReferences() const
+{
+ return m_expandEntityReferences;
+}
+
+NodeImpl *TreeWalkerImpl::getCurrentNode() const
+{
+ return m_currentNode;
+}
+
+void TreeWalkerImpl::setWhatToShow(long _whatToShow)
+{
+ // do some testing wether this is an accepted value
+ m_whatToShow = _whatToShow;
+}
+
+void TreeWalkerImpl::setFilter(NodeFilterImpl *_filter)
+{
+ m_filter->deref();
+ m_filter = _filter;
+ if ( m_filter )
+ m_filter->ref();
+}
+
+void TreeWalkerImpl::setExpandEntityReferences(bool value)
+{
+ m_expandEntityReferences = value;
+}
+
+void TreeWalkerImpl::setCurrentNode( NodeImpl *n )
+{
+ if ( n )
+ {
+ //m_rootNode = n;
+ m_currentNode = n;
+ }
+// else
+// throw( DOMException::NOT_SUPPORTED_ERR );
+}
+
+NodeImpl *TreeWalkerImpl::parentNode( )
+{
+ NodeImpl *n = getParentNode( m_currentNode );
+ if ( n )
+ m_currentNode = n;
+ return n;
+}
+
+
+NodeImpl *TreeWalkerImpl::firstChild( )
+{
+ NodeImpl *n = getFirstChild( m_currentNode );
+ if ( n )
+ m_currentNode = n;
+ return n;
+}
+
+
+NodeImpl *TreeWalkerImpl::lastChild( )
+{
+ NodeImpl *n = getLastChild(m_currentNode);
+ if( n )
+ m_currentNode = n;
+ return n;
+}
+
+NodeImpl *TreeWalkerImpl::previousSibling( )
+{
+ NodeImpl *n = getPreviousSibling( m_currentNode );
+ if( n )
+ m_currentNode = n;
+ return n;
+}
+
+NodeImpl *TreeWalkerImpl::nextSibling( )
+{
+ NodeImpl *n = getNextSibling( m_currentNode );
+ if( n )
+ m_currentNode = n;
+ return n;
+}
+
+NodeImpl *TreeWalkerImpl::previousNode( )
+{
+/* 1. my previous sibling.lastchild
+ * 2. my previous sibling
+ * 3. my parent
+ */
+
+ NodeImpl *n = getPreviousSibling( m_currentNode );
+ if( !n )
+ {
+ n = getParentNode( m_currentNode );
+ if( n ) //parent
+ {
+ m_currentNode = n;
+ return m_currentNode;
+ }
+ else // parent failed.. no previous node
+ return 0;
+ }
+
+ NodeImpl *child = getLastChild( n );
+ if( child ) // previous siblings last child
+ {
+ m_currentNode = child;
+ return m_currentNode;
+ }
+ else // previous sibling
+ {
+ m_currentNode = n;
+ return m_currentNode;
+ }
+ return 0; // should never get here!
+}
+
+NodeImpl *TreeWalkerImpl::nextNode( )
+{
+/* 1. my first child
+ * 2. my next sibling
+ * 3. my parents sibling, or their parents sibling (loop)
+ * 4. not found
+ */
+
+ NodeImpl *n = getFirstChild( m_currentNode );
+ if( n ) // my first child
+ {
+ m_currentNode = n;
+ return n;
+ }
+
+ n = getNextSibling( m_currentNode ); // my next sibling
+ if( n )
+ {
+ m_currentNode = n;
+ return m_currentNode;
+ }
+ NodeImpl *parent = getParentNode( m_currentNode );
+ while( parent ) // parents sibling
+ {
+ n = getNextSibling( parent );
+ if( n )
+ {
+ m_currentNode = n;
+ return m_currentNode;
+ }
+ else
+ parent = getParentNode( parent );
+ }
+ return 0;
+}
+
+short TreeWalkerImpl::isAccepted(NodeImpl *n)
+{
+ // if XML is implemented we have to check expandEntityRerefences in this function
+ if( ( ( 1 << ( n->nodeType()-1 ) ) & m_whatToShow) != 0 )
+ {
+ if(m_filter)
+ return m_filter->acceptNode(n);
+ else
+ return NodeFilter::FILTER_ACCEPT;
+ }
+ return NodeFilter::FILTER_SKIP;
+}
+
+NodeImpl *TreeWalkerImpl::getParentNode(NodeImpl *n)
+{
+ short _result = NodeFilter::FILTER_ACCEPT;
+
+ if( n == m_rootNode /*|| !n*/ )
+ return 0;
+
+ NodeImpl *_tempCurrent = n->parentNode();
+
+ if( !_tempCurrent )
+ return 0;
+
+ _result = isAccepted( _tempCurrent );
+ if ( _result == NodeFilter::FILTER_ACCEPT )
+ return _tempCurrent; // match found
+
+ return getParentNode( _tempCurrent );
+}
+
+NodeImpl *TreeWalkerImpl::getFirstChild(NodeImpl *n)
+{
+ short _result;
+
+ if( !n || !n->firstChild() )
+ return 0;
+ n = n->firstChild();
+
+ _result = isAccepted( n );
+
+ switch( _result )
+ {
+ case NodeFilter::FILTER_ACCEPT:
+ return n;
+ break;
+ case NodeFilter::FILTER_SKIP:
+ if( n->hasChildNodes() )
+ return getFirstChild( n );
+ else
+ return getNextSibling( n );
+ break;
+
+ case NodeFilter::FILTER_REJECT:
+ return getNextSibling( n );
+ break;
+ }
+ return 0; // should never get here!
+}
+
+NodeImpl *TreeWalkerImpl::getLastChild(NodeImpl *n)
+{
+ short _result;
+
+ if( !n || !n->lastChild() )
+ return 0;
+ n = n->lastChild();
+ _result = isAccepted( n );
+
+ switch( _result )
+ {
+ case NodeFilter::FILTER_ACCEPT:
+ return n;
+ break;
+
+ case NodeFilter::FILTER_SKIP:
+ if( n->hasChildNodes() )
+ return getLastChild( n );
+ else
+ return getPreviousSibling( n );
+ break;
+
+ case NodeFilter::FILTER_REJECT:
+ return getPreviousSibling( n );
+ break;
+ }
+ return 0;
+}
+
+NodeImpl *TreeWalkerImpl::getPreviousSibling(NodeImpl *n)
+{
+ short _result;
+ NodeImpl *_tempCurrent;
+
+ if( !n )
+ return 0;
+ //first the cases if we have a previousSibling
+ _tempCurrent = n->previousSibling();
+ if( _tempCurrent )
+ {
+ _result = isAccepted( _tempCurrent );
+ switch ( _result )
+ {
+ case NodeFilter::FILTER_ACCEPT:
+ return _tempCurrent;
+ break;
+
+ case NodeFilter::FILTER_SKIP:
+ {
+ NodeImpl *nskip = getLastChild( _tempCurrent );
+ if( nskip )
+ return nskip;
+ return getPreviousSibling( _tempCurrent );
+ break;
+ }
+
+ case NodeFilter::FILTER_REJECT:
+ return getPreviousSibling( _tempCurrent );
+ break;
+ }
+ }
+ // now the case if we don't have previous sibling
+ else
+ {
+ _tempCurrent = n->parentNode();
+ if( !_tempCurrent || _tempCurrent == m_rootNode)
+ return 0;
+ _result = isAccepted( _tempCurrent );
+ if ( _result == NodeFilter::FILTER_SKIP )
+ return getPreviousSibling( _tempCurrent );
+
+ return 0;
+
+ }
+ return 0; // should never get here!
+}
+
+NodeImpl *TreeWalkerImpl::getNextSibling(NodeImpl *n)
+{
+ NodeImpl *_tempCurrent = 0;
+ short _result;
+
+ if( !n )
+ return 0;
+
+ _tempCurrent = n->nextSibling();
+ if( _tempCurrent )
+ {
+ _result = isAccepted( _tempCurrent );
+ switch ( _result )
+ {
+ case NodeFilter::FILTER_ACCEPT:
+ return _tempCurrent;
+ break;
+
+ case NodeFilter::FILTER_SKIP:
+ {
+ NodeImpl *nskip = getFirstChild( _tempCurrent );
+ if( nskip )
+ return nskip;
+ return getNextSibling( _tempCurrent );
+ break;
+ }
+
+ case NodeFilter::FILTER_REJECT:
+ return getNextSibling( _tempCurrent );
+ break;
+ }
+ }
+ else
+ {
+ _tempCurrent = n->parentNode();
+ if( !_tempCurrent || _tempCurrent == m_rootNode)
+ return 0;
+ _result = isAccepted( _tempCurrent );
+ if( _result == NodeFilter::FILTER_SKIP )
+ return getNextSibling( _tempCurrent );
+
+ return 0;
+ }
+ return 0;
+}
+
diff --git a/tdehtml/xml/dom2_traversalimpl.h b/tdehtml/xml/dom2_traversalimpl.h
new file mode 100644
index 000000000..43800c4aa
--- /dev/null
+++ b/tdehtml/xml/dom2_traversalimpl.h
@@ -0,0 +1,196 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _DOM2_TraversalImpl_h_
+#define _DOM2_TraversalImpl_h_
+
+#include "dom/dom_node.h"
+#include "dom/dom_misc.h"
+#include "misc/shared.h"
+#include "dom/dom2_traversal.h"
+
+namespace DOM {
+
+class NodeImpl;
+class DocumentImpl;
+
+class NodeIteratorImpl : public tdehtml::Shared<NodeIteratorImpl>
+{
+public:
+ NodeIteratorImpl(NodeImpl *_root, unsigned long _whatToShow, NodeFilter _filter, bool _entityReferenceExpansion);
+ ~NodeIteratorImpl();
+
+
+ NodeImpl *root();
+ unsigned long whatToShow();
+ NodeFilter filter();
+ bool expandEntityReferences();
+
+ NodeImpl *nextNode(int &exceptioncode);
+ NodeImpl *previousNode(int &exceptioncode);
+ void detach(int &exceptioncode);
+
+
+ /**
+ * This function has to be called if you delete a node from the
+ * document tree and you want the Iterator to react if there
+ * are any changes concerning it.
+ */
+ void notifyBeforeNodeRemoval(NodeImpl *removed);
+
+ short isAccepted(NodeImpl *n);
+ NodeImpl *getNextNode(NodeImpl *n);
+ NodeImpl *getPreviousNode(NodeImpl *n);
+protected:
+ NodeImpl *m_root;
+ long m_whatToShow;
+ NodeFilter m_filter;
+ bool m_expandEntityReferences;
+
+ bool m_inFront;
+ NodeImpl *m_referenceNode;
+ bool m_detached;
+ DocumentImpl *m_doc;
+};
+
+class NodeFilterImpl : public tdehtml::Shared<NodeFilterImpl>
+{
+public:
+ NodeFilterImpl();
+ ~NodeFilterImpl();
+
+ short acceptNode(const Node &n);
+
+ void setCustomNodeFilter(CustomNodeFilter *custom);
+ CustomNodeFilter *customNodeFilter();
+protected:
+ CustomNodeFilter *m_customNodeFilter;
+
+};
+
+class TreeWalkerImpl : public tdehtml::Shared<TreeWalkerImpl>
+{
+public:
+ TreeWalkerImpl();
+ TreeWalkerImpl(const TreeWalkerImpl &other);
+ TreeWalkerImpl(NodeImpl *n, NodeFilter f);
+ TreeWalkerImpl(NodeImpl *n, long _whatToShow, NodeFilterImpl *f,
+ bool entityReferenceExpansion);
+ TreeWalkerImpl & operator = (const TreeWalkerImpl &other);
+
+
+ ~TreeWalkerImpl();
+
+ NodeImpl *getRoot() const;
+
+ unsigned long getWhatToShow() const;
+
+ NodeFilterImpl *getFilter() const;
+
+ bool getExpandEntityReferences() const;
+
+ NodeImpl *getCurrentNode() const;
+
+ void setCurrentNode( NodeImpl *_currentNode);
+
+ NodeImpl *parentNode();
+
+ NodeImpl *firstChild();
+
+ NodeImpl *lastChild ();
+
+ NodeImpl *previousSibling ();
+
+ NodeImpl *nextSibling();
+
+ NodeImpl *previousNode();
+
+ NodeImpl *nextNode();
+
+
+ /**
+ * Sets which node types are to be presented via the TreeWalker
+ */
+ void setWhatToShow(long _whatToShow);
+ void setFilter(NodeFilterImpl *_filter);
+ void setExpandEntityReferences(bool value);
+
+ NodeImpl *getParentNode(NodeImpl *n);
+ NodeImpl *getFirstChild(NodeImpl *n);
+ NodeImpl *getLastChild(NodeImpl *n);
+ NodeImpl *getPreviousSibling(NodeImpl *n);
+ NodeImpl *getNextSibling(NodeImpl *n);
+
+ short isAccepted(NodeImpl *n);
+
+protected:
+ /**
+ * This attribute determines which node types are presented via
+ * the TreeWalker.
+ *
+ */
+ long m_whatToShow;
+
+ /**
+ * The filter used to screen nodes.
+ *
+ */
+ NodeFilterImpl *m_filter;
+
+ /**
+ * The value of this flag determines whether entity reference
+ * nodes are expanded. To produce a view of the document that has
+ * entity references expanded and does not expose the entity
+ * reference node itself, use the whatToShow flags to hide the
+ * entity reference node and set expandEntityReferences to true
+ * when creating the iterator. To produce a view of the document
+ * that has entity reference nodes but no entity expansion, use
+ * the whatToShow flags to show the entity reference node and set
+ * expandEntityReferences to true.
+ *
+ * This is not implemented (always true)
+ */
+ bool m_expandEntityReferences;
+
+ /**
+ * The current node.
+ *
+ * The value must not be null. Attempting to set it to null will
+ * raise a NOT_SUPPORTED_ERR exception. When setting a node, the
+ * whatToShow flags and any Filter associated with the TreeWalker
+ * are not checked. The currentNode may be set to any Node of any
+ * type.
+ *
+ */
+ NodeImpl *m_currentNode;
+
+ NodeImpl *m_rootNode;
+ DocumentImpl *m_doc;
+};
+
+
+} // namespace
+
+#endif
+
diff --git a/tdehtml/xml/dom2_viewsimpl.cpp b/tdehtml/xml/dom2_viewsimpl.cpp
new file mode 100644
index 000000000..217184aa1
--- /dev/null
+++ b/tdehtml/xml/dom2_viewsimpl.cpp
@@ -0,0 +1,50 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#include "dom2_viewsimpl.h"
+#include "dom_elementimpl.h"
+#include "dom_docimpl.h"
+#include "css/css_renderstyledeclarationimpl.h"
+#include "css/cssproperties.h"
+#include "css/css_stylesheetimpl.h"
+
+using namespace tdehtml;
+using namespace DOM;
+
+AbstractViewImpl::AbstractViewImpl(DocumentImpl *_document)
+{
+ m_document = _document;
+}
+
+AbstractViewImpl::~AbstractViewImpl()
+{
+}
+
+CSSStyleDeclarationImpl *AbstractViewImpl::getComputedStyle(ElementImpl* elt, DOMStringImpl* /*pseudoElt*/)
+{
+ if (!elt)
+ return 0;
+
+ CSSStyleDeclarationImpl* style = new RenderStyleDeclarationImpl( elt );
+ return style;
+}
+
diff --git a/tdehtml/xml/dom2_viewsimpl.h b/tdehtml/xml/dom2_viewsimpl.h
new file mode 100644
index 000000000..e82685244
--- /dev/null
+++ b/tdehtml/xml/dom2_viewsimpl.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * (C) 2001 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _DOM_ViewsImpl_h_
+#define _DOM_ViewsImpl_h_
+
+#include "dom/dom_misc.h"
+#include "css/css_valueimpl.h"
+#include "misc/shared.h"
+
+namespace DOM {
+
+class DocumentImpl;
+class CSSStyleDeclarationImpl;
+class ElementImpl;
+class DOMStringImpl;
+
+// Introduced in DOM Level 2:
+class AbstractViewImpl : public tdehtml::Shared<AbstractViewImpl>
+{
+public:
+ AbstractViewImpl(DocumentImpl *_document);
+ ~AbstractViewImpl();
+ DocumentImpl *document() const { return m_document; }
+ CSSStyleDeclarationImpl *getComputedStyle(ElementImpl *elt, DOMStringImpl *pseudoElt);
+protected:
+ DocumentImpl *m_document;
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/xml/dom_docimpl.cpp b/tdehtml/xml/dom_docimpl.cpp
new file mode 100644
index 000000000..3ab639867
--- /dev/null
+++ b/tdehtml/xml/dom_docimpl.cpp
@@ -0,0 +1,2892 @@
+/**
+ * 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-2006 Apple Computer, Inc.
+ * (C) 2006 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.
+ */
+
+#include "dom/dom_exception.h"
+
+#include "xml/dom_textimpl.h"
+#include "xml/dom_xmlimpl.h"
+#include "xml/dom2_rangeimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/xml_tokenizer.h"
+#include "html/htmltokenizer.h"
+#include "xml/dom_restyler.h"
+
+#include "css/csshelper.h"
+#include "css/cssstyleselector.h"
+#include "css/css_stylesheetimpl.h"
+#include "misc/htmlhashes.h"
+#include "misc/helper.h"
+#include "misc/seed.h"
+#include "misc/loader.h"
+#include "ecma/kjs_proxy.h"
+#include "ecma/kjs_binding.h"
+
+#include <tqptrstack.h>
+#include <tqpaintdevicemetrics.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kstaticdeleter.h>
+
+#include "rendering/counter_tree.h"
+#include "rendering/render_canvas.h"
+#include "rendering/render_replaced.h"
+#include "rendering/render_arena.h"
+#include "rendering/render_layer.h"
+#include "rendering/render_frames.h"
+#include "rendering/render_image.h"
+
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+
+#include <kglobalsettings.h>
+#include <kstringhandler.h>
+#include <krfcdate.h>
+#include "tdehtml_settings.h"
+#include "tdehtmlpart_p.h"
+
+#include "html/html_baseimpl.h"
+#include "html/html_blockimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/html_formimpl.h"
+#include "html/html_headimpl.h"
+#include "html/html_imageimpl.h"
+#include "html/html_listimpl.h"
+#include "html/html_miscimpl.h"
+#include "html/html_tableimpl.h"
+#include "html/html_objectimpl.h"
+
+#include <kapplication.h>
+#include <kio/job.h>
+
+#include <stdlib.h>
+#include "dom_docimpl.h"
+
+using namespace DOM;
+using namespace tdehtml;
+
+// ------------------------------------------------------------------------
+
+DOMImplementationImpl *DOMImplementationImpl::m_instance = 0;
+
+DOMImplementationImpl::DOMImplementationImpl()
+{
+}
+
+DOMImplementationImpl::~DOMImplementationImpl()
+{
+}
+
+bool DOMImplementationImpl::hasFeature ( const DOMString &feature, const DOMString &version )
+{
+ // ### update when we (fully) support the relevant features
+ TQString lower = feature.string().lower();
+ if ((lower == "html" || lower == "xml") &&
+ (version.isEmpty() || version == "1.0" || version == "2.0" || version == "null"))
+ return true;
+
+ // ## Do we support Core Level 3 ?
+ if ((lower == "core" ) &&
+ (version.isEmpty() || version == "2.0" || version == "null"))
+ return true;
+
+ if ((lower == "events" || lower == "uievents" ||
+ lower == "mouseevents" || lower == "mutationevents" ||
+ lower == "htmlevents" || lower == "textevents" ) &&
+ (version.isEmpty() || version == "2.0" || version == "3.0" || version == "null"))
+ return true;
+ return false;
+}
+
+DocumentTypeImpl *DOMImplementationImpl::createDocumentType( const DOMString &qualifiedName, const DOMString &publicId,
+ const DOMString &systemId, int &exceptioncode )
+{
+ // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
+ if (qualifiedName.isNull()) {
+ exceptioncode = DOMException::NAMESPACE_ERR;
+ return 0;
+ }
+
+ // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
+ if (!Element::tdehtmlValidQualifiedName(qualifiedName)) {
+ exceptioncode = DOMException::INVALID_CHARACTER_ERR;
+ return 0;
+ }
+
+ // NAMESPACE_ERR: Raised if the qualifiedName is malformed.
+ // Added special case for the empty string, which seems to be a common pre-DOM2 misuse
+ if (!qualifiedName.isEmpty() && Element::tdehtmlMalformedQualifiedName(qualifiedName)) {
+ exceptioncode = DOMException::NAMESPACE_ERR;
+ return 0;
+ }
+
+ return new DocumentTypeImpl(this,0,qualifiedName,publicId,systemId);
+}
+
+DOMImplementationImpl* DOMImplementationImpl::getInterface(const DOMString& /*feature*/) const
+{
+ // ###
+ return 0;
+}
+
+DocumentImpl *DOMImplementationImpl::createDocument( const DOMString &namespaceURI, const DOMString &qualifiedName,
+ const DocumentType &doctype, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ if (!checkQualifiedName(qualifiedName, namespaceURI, 0, true/*nameCanBeNull*/,
+ true /*nameCanBeEmpty, see #61650*/, &exceptioncode) )
+ return 0;
+
+ DocumentTypeImpl *dtype = static_cast<DocumentTypeImpl*>(doctype.handle());
+ // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
+ // created from a different implementation.
+ if (dtype && (dtype->getDocument() || dtype->implementation() != this)) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return 0;
+ }
+
+ // ### this is completely broken.. without a view it will not work (Dirk)
+ DocumentImpl *doc = new DocumentImpl(this, 0);
+
+ // now get the interesting parts of the doctype
+ // ### create new one if not there (currently always there)
+ if (doc->doctype() && dtype)
+ doc->doctype()->copyFrom(*dtype);
+
+ // the document must be created empty if all parameters are null
+ // (or empty for qName/nsURI as a tolerance) - see DOM 3 Core.
+ if (dtype || !qualifiedName.isEmpty() || !namespaceURI.isEmpty()) {
+ ElementImpl *element = doc->createElementNS(namespaceURI,qualifiedName);
+ doc->appendChild(element,exceptioncode);
+ if (exceptioncode) {
+ delete element;
+ delete doc;
+ return 0;
+ }
+ }
+ return doc;
+}
+
+CSSStyleSheetImpl *DOMImplementationImpl::createCSSStyleSheet(DOMStringImpl* /*title*/, DOMStringImpl *media,
+ int &/*exceptioncode*/)
+{
+ // ### TODO : title should be set, and media could have wrong syntax, in which case we should
+ // generate an exception.
+ CSSStyleSheetImpl *parent = 0L;
+ CSSStyleSheetImpl *sheet = new CSSStyleSheetImpl(parent, DOMString());
+ sheet->setMedia(new MediaListImpl(sheet, media));
+ return sheet;
+}
+
+DocumentImpl *DOMImplementationImpl::createDocument( KHTMLView *v )
+{
+ return new DocumentImpl(this, v);
+}
+
+HTMLDocumentImpl *DOMImplementationImpl::createHTMLDocument( KHTMLView *v )
+{
+ return new HTMLDocumentImpl(this, v);
+}
+
+DOMImplementationImpl *DOMImplementationImpl::instance()
+{
+ if (!m_instance) {
+ m_instance = new DOMImplementationImpl();
+ m_instance->ref();
+ }
+
+ return m_instance;
+}
+
+// ------------------------------------------------------------------------
+
+
+ElementMappingCache::ElementMappingCache():m_dict(257)
+{
+ m_dict.setAutoDelete(true);
+}
+
+void ElementMappingCache::add(const TQString& id, ElementImpl* nd)
+{
+ if (id.isEmpty()) return;
+
+ ItemInfo* info = m_dict.find(id);
+ if (info)
+ {
+ info->ref++;
+ info->nd = 0; //Now ambigous
+ }
+ else
+ {
+ ItemInfo* info = new ItemInfo();
+ info->ref = 1;
+ info->nd = nd;
+ m_dict.insert(id, info);
+ }
+}
+
+void ElementMappingCache::set(const TQString& id, ElementImpl* nd)
+{
+ if (id.isEmpty()) return;
+
+ ItemInfo* info = m_dict.find(id);
+ info->nd = nd;
+}
+
+void ElementMappingCache::remove(const TQString& id, ElementImpl* nd)
+{
+ if (id.isEmpty()) return;
+
+ ItemInfo* info = m_dict.find(id);
+ info->ref--;
+ if (info->ref == 0)
+ {
+ m_dict.take(id);
+ delete info;
+ }
+ else
+ {
+ if (info->nd == nd)
+ info->nd = 0;
+ }
+}
+
+bool ElementMappingCache::contains(const TQString& id)
+{
+ if (id.isEmpty()) return false;
+ return m_dict.find(id);
+}
+
+ElementMappingCache::ItemInfo* ElementMappingCache::get(const TQString& id)
+{
+ if (id.isEmpty()) return 0;
+ return m_dict.find(id);
+}
+
+static KStaticDeleter< TQPtrList<DocumentImpl> > s_changedDocumentsDeleter;
+TQPtrList<DocumentImpl> * DocumentImpl::changedDocuments;
+
+// KHTMLView might be 0
+DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
+ : NodeBaseImpl( 0 ), m_domtree_version(0), m_counterDict(257),
+ m_imageLoadEventTimer(0)
+{
+ m_document.resetSkippingRef(this); //Make getDocument return us..
+ m_selfOnlyRefCount = 0;
+
+ m_paintDeviceMetrics = 0;
+ m_paintDevice = 0;
+ m_decoderMibEnum = 0;
+ m_textColor = Qt::black;
+
+ m_view = v;
+ m_renderArena.reset();
+
+ KHTMLFactory::ref();
+
+ if ( v ) {
+ m_docLoader = new DocLoader(v->part(), this );
+ setPaintDevice( TQT_TQPAINTDEVICE(m_view) );
+ }
+ else
+ m_docLoader = new DocLoader( 0, this );
+
+ visuallyOrdered = false;
+ m_bParsing = false;
+ m_docChanged = false;
+ m_elemSheet = 0;
+ m_tokenizer = 0;
+
+ // ### this should be created during parsing a <!DOCTYPE>
+ // not during construction. Not sure who added that and why (Dirk)
+ m_doctype = new DocumentTypeImpl(_implementation, getDocument(),
+ DOMString() /* qualifiedName */,
+ DOMString() /* publicId */,
+ DOMString() /* systemId */);
+ m_doctype->ref();
+
+ m_implementation = _implementation;
+ m_implementation->ref();
+ pMode = Strict;
+ hMode = XHtml;
+ m_textColor = "#000000";
+ m_attrMap = new IdNameMapping(ATTR_LAST_ATTR+1);
+ m_elementMap = new IdNameMapping(ID_LAST_TAG+1);
+ m_namespaceMap = new IdNameMapping(1);
+ TQString xhtml(XHTML_NAMESPACE);
+ m_namespaceMap->names.insert(emptyNamespace, new DOMStringImpl(""));
+ m_namespaceMap->names.insert(xhtmlNamespace, new DOMStringImpl(xhtml.unicode(), xhtml.length()));
+ m_namespaceMap->names[emptyNamespace]->ref();
+ m_namespaceMap->names[xhtmlNamespace]->ref();
+ m_namespaceMap->count+=2;
+ m_focusNode = 0;
+ m_hoverNode = 0;
+ m_activeNode = 0;
+ m_defaultView = new AbstractViewImpl(this);
+ m_defaultView->ref();
+ m_listenerTypes = 0;
+ m_styleSheets = new StyleSheetListImpl;
+ m_styleSheets->ref();
+ m_addedStyleSheets = 0;
+ m_inDocument = true;
+ m_styleSelectorDirty = false;
+ m_styleSelector = 0;
+ m_counterDict.setAutoDelete(true);
+
+ m_inStyleRecalc = false;
+ m_pendingStylesheets = 0;
+ m_ignorePendingStylesheets = false;
+ m_async = true;
+ m_hadLoadError = false;
+ m_docLoading = false;
+ m_inSyncLoad = false;
+ m_loadingXMLDoc = 0;
+ m_cssTarget = 0;
+ m_dynamicDomRestyler = new tdehtml::DynamicDomRestyler();
+}
+
+void DocumentImpl::removedLastRef()
+{
+ if (m_selfOnlyRefCount) {
+ /* In this case, the only references to us are from children,
+ so we have a cycle. We'll try to break it by disconnecting the
+ children from us; this sucks/is wrong, but it's pretty much
+ the best we can do without tracing.
+
+ Of course, if dumping the children causes the refcount from them to
+ drop to 0 we can get killed right here, so better hold
+ a temporary reference, too
+ */
+ DocPtr<DocumentImpl> guard(this);
+
+ // we must make sure not to be retaining any of our children through
+ // these extra pointers or we will create a reference cycle
+ if (m_doctype) {
+ m_doctype->deref();
+ m_doctype = 0;
+ }
+
+ if (m_cssTarget) {
+ m_cssTarget->deref();
+ m_cssTarget = 0;
+ }
+
+ if (m_focusNode) {
+ m_focusNode->deref();
+ m_focusNode = 0;
+ }
+
+ if (m_hoverNode) {
+ m_hoverNode->deref();
+ m_hoverNode = 0;
+ }
+
+ if (m_activeNode) {
+ m_activeNode->deref();
+ m_activeNode = 0;
+ }
+
+ removeChildren();
+
+ delete m_tokenizer;
+ m_tokenizer = 0;
+ } else {
+ delete this;
+ }
+}
+
+DocumentImpl::~DocumentImpl()
+{
+ //Important: if you need to remove stuff here,
+ //you may also have to fix removedLastRef() above - M.O.
+ assert( !m_render );
+
+ TQIntDictIterator<NodeListImpl::Cache> it(m_nodeListCache);
+ for (; it.current(); ++it)
+ it.current()->deref();
+
+ if (m_loadingXMLDoc)
+ m_loadingXMLDoc->deref(this);
+ if (changedDocuments && m_docChanged)
+ changedDocuments->remove(this);
+ delete m_tokenizer;
+ m_document.resetSkippingRef(0);
+ delete m_styleSelector;
+ delete m_docLoader;
+ if (m_elemSheet ) m_elemSheet->deref();
+ if (m_doctype)
+ m_doctype->deref();
+ m_implementation->deref();
+ delete m_paintDeviceMetrics;
+ delete m_elementMap;
+ delete m_attrMap;
+ delete m_namespaceMap;
+ delete m_dynamicDomRestyler;
+ m_defaultView->deref();
+ m_styleSheets->deref();
+ if (m_addedStyleSheets)
+ m_addedStyleSheets->deref();
+ if (m_cssTarget)
+ m_cssTarget->deref();
+ if (m_focusNode)
+ m_focusNode->deref();
+ if ( m_hoverNode )
+ m_hoverNode->deref();
+ if (m_activeNode)
+ m_activeNode->deref();
+
+ m_renderArena.reset();
+
+ KHTMLFactory::deref();
+}
+
+
+DocumentTypeImpl *DocumentImpl::doctype() const
+{
+ return m_doctype;
+}
+
+DOMImplementationImpl *DocumentImpl::implementation() const
+{
+ return m_implementation;
+}
+
+ElementImpl *DocumentImpl::documentElement() const
+{
+ NodeImpl *n = firstChild();
+ while (n && n->nodeType() != Node::ELEMENT_NODE)
+ n = n->nextSibling();
+ return static_cast<ElementImpl*>(n);
+}
+
+ElementImpl *DocumentImpl::createElement( const DOMString &name, int* pExceptioncode )
+{
+ Id id = getId( NodeImpl::ElementId, name.implementation(),
+ false /* allocate */, false /*HTMLDocumentImpl::createElement looked for HTML elements already*/,
+ pExceptioncode);
+ if ( pExceptioncode && *pExceptioncode )
+ return 0;
+
+ XMLElementImpl* e = new XMLElementImpl( getDocument(), id );
+ e->setHTMLCompat( htmlMode() != XHtml ); // Not a real HTML element, but inside an html-compat doc all tags are uppercase.
+ return e;
+}
+
+AttrImpl *DocumentImpl::createAttribute( const DOMString &tagName, int* pExceptioncode )
+{
+ Id id = getId( NodeImpl::AttributeId, tagName.implementation(),
+ false /* allocate */, isHTMLDocument(), pExceptioncode);
+ if ( pExceptioncode && *pExceptioncode )
+ return 0;
+ AttrImpl* attr = new AttrImpl( 0, getDocument(), id, DOMString("").implementation());
+ attr->setHTMLCompat( htmlMode() != XHtml );
+ return attr;
+}
+
+DocumentFragmentImpl *DocumentImpl::createDocumentFragment( )
+{
+ return new DocumentFragmentImpl( docPtr() );
+}
+
+CommentImpl *DocumentImpl::createComment ( DOMStringImpl* data )
+{
+ return new CommentImpl( docPtr(), data );
+}
+
+CDATASectionImpl *DocumentImpl::createCDATASection ( DOMStringImpl* data )
+{
+ return new CDATASectionImpl( docPtr(), data );
+}
+
+ProcessingInstructionImpl *DocumentImpl::createProcessingInstruction ( const DOMString &target, DOMStringImpl* data )
+{
+ return new ProcessingInstructionImpl( docPtr(),target,data);
+}
+
+EntityReferenceImpl *DocumentImpl::createEntityReference ( const DOMString &name )
+{
+ return new EntityReferenceImpl(docPtr(), name.implementation());
+}
+
+NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
+{
+ NodeImpl *result = 0;
+
+ // Not mentioned in spec: throw NOT_FOUND_ERR if evt is null
+ if (!importedNode) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+ }
+
+ if(importedNode->nodeType() == Node::ELEMENT_NODE)
+ {
+ // Why not use cloneNode?
+ ElementImpl *otherElem = static_cast<ElementImpl*>(importedNode);
+ NamedAttrMapImpl *otherMap = static_cast<ElementImpl *>(importedNode)->attributes(true);
+
+ ElementImpl *tempElementImpl;
+ if (!importedNode->localName().isNull())
+ tempElementImpl = createElementNS(otherElem->namespaceURI(),otherElem->nodeName());
+ else
+ tempElementImpl = createElement(otherElem->nodeName());
+ result = tempElementImpl;
+
+
+ if(otherMap) {
+ for(unsigned long i = 0; i < otherMap->length(); i++)
+ {
+ AttrImpl *otherAttr = otherMap->attrAt(i)->createAttr(otherElem,otherElem->docPtr());
+
+ if (!otherAttr->localName().isNull()) {
+ // attr was created via createElementNS()
+ tempElementImpl->setAttributeNS(otherAttr->namespaceURI(),
+ otherAttr->name(),
+ otherAttr->nodeValue(),
+ exceptioncode);
+ }
+ else {
+ // attr was created via createElement()
+ tempElementImpl->setAttribute(otherAttr->id(),
+ otherAttr->nodeValue(),
+ otherAttr->name(),
+ exceptioncode);
+ }
+
+ if(exceptioncode != 0)
+ break; // ### properly cleanup here
+ }
+ }
+ }
+ else if(importedNode->nodeType() == Node::TEXT_NODE)
+ {
+ result = createTextNode(static_cast<TextImpl*>(importedNode)->string());
+ deep = false;
+ }
+ else if(importedNode->nodeType() == Node::CDATA_SECTION_NODE)
+ {
+ result = createCDATASection(static_cast<CDATASectionImpl*>(importedNode)->string());
+ deep = false;
+ }
+ else if(importedNode->nodeType() == Node::ENTITY_REFERENCE_NODE)
+ result = createEntityReference(importedNode->nodeName());
+ else if(importedNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
+ {
+ result = createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue().implementation());
+ deep = false;
+ }
+ else if(importedNode->nodeType() == Node::COMMENT_NODE)
+ {
+ result = createComment(static_cast<CommentImpl*>(importedNode)->string());
+ deep = false;
+ }
+ else if (importedNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
+ result = createDocumentFragment();
+ else
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+
+ //### FIXME: This should handle Attributes, and a few other things
+
+ if(deep && result)
+ {
+ for(Node n = importedNode->firstChild(); !n.isNull(); n = n.nextSibling())
+ result->appendChild(importNode(n.handle(), true, exceptioncode), exceptioncode);
+ }
+
+ return result;
+}
+
+ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName, int* pExceptioncode )
+{
+ ElementImpl *e = 0;
+ int colonPos = -2;
+ // check NAMESPACE_ERR/INVALID_CHARACTER_ERR
+ if (pExceptioncode && !checkQualifiedName(_qualifiedName, _namespaceURI, &colonPos,
+ false/*nameCanBeNull*/, false/*nameCanBeEmpty*/,
+ pExceptioncode))
+ return 0;
+ DOMString prefix, localName;
+ splitPrefixLocalName(_qualifiedName.implementation(), prefix, localName, colonPos);
+
+ if ((isHTMLDocument() && _namespaceURI.isNull()) ||
+ (strcasecmp(_namespaceURI, XHTML_NAMESPACE) == 0 && localName == localName.lower())) {
+ e = createHTMLElement(localName);
+ if (e) {
+ int _exceptioncode = 0;
+ if (!prefix.isNull())
+ e->setPrefix(prefix, _exceptioncode);
+ if ( _exceptioncode ) {
+ if ( pExceptioncode ) *pExceptioncode = _exceptioncode;
+ delete e;
+ return 0;
+ }
+ e->setHTMLCompat( _namespaceURI.isNull() && htmlMode() != XHtml );
+ }
+ }
+ if (!e) {
+ Id id = getId(NodeImpl::ElementId, _namespaceURI.implementation(), prefix.implementation(),
+ localName.implementation(), false, false /*HTML already looked up*/);
+ e = new XMLElementImpl( getDocument(), id, prefix.implementation() );
+ }
+
+ return e;
+}
+
+AttrImpl *DocumentImpl::createAttributeNS( const DOMString &_namespaceURI,
+ const DOMString &_qualifiedName, int* pExceptioncode)
+{
+ int colonPos = -2;
+ // check NAMESPACE_ERR/INVALID_CHARACTER_ERR
+ if (pExceptioncode && !checkQualifiedName(_qualifiedName, _namespaceURI, &colonPos,
+ false/*nameCanBeNull*/, false/*nameCanBeEmpty*/,
+ pExceptioncode))
+ return 0;
+ DOMString prefix, localName;
+ splitPrefixLocalName(_qualifiedName.implementation(), prefix, localName, colonPos);
+ Id id = getId(NodeImpl::AttributeId, _namespaceURI.implementation(), prefix.implementation(),
+ localName.implementation(), false, true /*lookupHTML*/);
+ AttrImpl* attr = new AttrImpl(0, getDocument(), id, DOMString("").implementation(),
+ prefix.implementation());
+ attr->setHTMLCompat( _namespaceURI.isNull() && htmlMode() != XHtml );
+ return attr;
+}
+
+ElementImpl *DocumentImpl::getElementById( const DOMString &elementId ) const
+{
+ TQString stringKey = elementId.string();
+
+ ElementMappingCache::ItemInfo* info = m_getElementByIdCache.get(stringKey);
+
+ if (!info)
+ return 0;
+
+ //See if cache has an unambiguous answer.
+ if (info->nd)
+ return info->nd;
+
+ //Now we actually have to walk.
+ TQPtrStack<NodeImpl> nodeStack;
+ NodeImpl *current = _first;
+
+ while(1)
+ {
+ if(!current)
+ {
+ if(nodeStack.isEmpty()) break;
+ current = nodeStack.pop();
+ current = current->nextSibling();
+ }
+ else
+ {
+ if(current->isElementNode())
+ {
+ ElementImpl *e = static_cast<ElementImpl *>(current);
+ if(e->getAttribute(ATTR_ID) == elementId) {
+ info->nd = e;
+ return e;
+ }
+ }
+
+ NodeImpl *child = current->firstChild();
+ if(child)
+ {
+ nodeStack.push(current);
+ current = child;
+ }
+ else
+ {
+ current = current->nextSibling();
+ }
+ }
+ }
+
+ assert(0); //If there is no item with such an ID, we should never get here
+
+ //kdDebug() << "WARNING: *DocumentImpl::getElementById not found " << elementId.string() << endl;
+
+ return 0;
+}
+
+void DocumentImpl::setTitle(const DOMString& _title)
+{
+ if (_title == m_title && !m_title.isNull()) return;
+
+ m_title = _title;
+
+ TQString titleStr = m_title.string();
+ for (unsigned int i = 0; i < titleStr.length(); ++i)
+ if (titleStr[i] < ' ')
+ titleStr[i] = ' ';
+ titleStr = titleStr.simplifyWhiteSpace();
+ titleStr.compose();
+ if ( view() && !view()->part()->parentPart() ) {
+ if (titleStr.isNull() || titleStr.isEmpty()) {
+ // empty title... set window caption as the URL
+ KURL url = m_url;
+ url.setRef(TQString::null);
+ url.setQuery(TQString::null);
+ titleStr = url.prettyURL();
+ }
+
+ emit view()->part()->setWindowCaption( KStringHandler::csqueeze( titleStr, 128 ) );
+ }
+}
+
+DOMString DocumentImpl::nodeName() const
+{
+ return "#document";
+}
+
+unsigned short DocumentImpl::nodeType() const
+{
+ return Node::DOCUMENT_NODE;
+}
+
+DOMStringImpl* DocumentImpl::textContent() const
+{
+ return 0;
+}
+
+void DocumentImpl::setTextContent( const DOMString&, int& )
+{}
+
+ElementImpl *DocumentImpl::createHTMLElement( const DOMString &name )
+{
+ uint id = tdehtml::getTagID( name.string().lower().latin1(), name.string().length() );
+// id = makeId(xhtmlNamespace, id);
+
+ ElementImpl *n = 0;
+ switch(id)
+ {
+ case ID_HTML:
+ n = new HTMLHtmlElementImpl(docPtr());
+ break;
+ case ID_HEAD:
+ n = new HTMLHeadElementImpl(docPtr());
+ break;
+ case ID_BODY:
+ n = new HTMLBodyElementImpl(docPtr());
+ break;
+
+// head elements
+ case ID_BASE:
+ n = new HTMLBaseElementImpl(docPtr());
+ break;
+ case ID_LINK:
+ n = new HTMLLinkElementImpl(docPtr());
+ break;
+ case ID_META:
+ n = new HTMLMetaElementImpl(docPtr());
+ break;
+ case ID_STYLE:
+ n = new HTMLStyleElementImpl(docPtr());
+ break;
+ case ID_TITLE:
+ n = new HTMLTitleElementImpl(docPtr());
+ break;
+
+// frames
+ case ID_FRAME:
+ n = new HTMLFrameElementImpl(docPtr());
+ break;
+ case ID_FRAMESET:
+ n = new HTMLFrameSetElementImpl(docPtr());
+ break;
+ case ID_IFRAME:
+ n = new HTMLIFrameElementImpl(docPtr());
+ break;
+
+// form elements
+// ### FIXME: we need a way to set form dependency after we have made the form elements
+ case ID_FORM:
+ n = new HTMLFormElementImpl(docPtr(), false);
+ break;
+ case ID_BUTTON:
+ n = new HTMLButtonElementImpl(docPtr());
+ break;
+ case ID_FIELDSET:
+ n = new HTMLFieldSetElementImpl(docPtr());
+ break;
+ case ID_INPUT:
+ n = new HTMLInputElementImpl(docPtr());
+ break;
+ case ID_ISINDEX:
+ n = new HTMLIsIndexElementImpl(docPtr());
+ break;
+ case ID_LABEL:
+ n = new HTMLLabelElementImpl(docPtr());
+ break;
+ case ID_LEGEND:
+ n = new HTMLLegendElementImpl(docPtr());
+ break;
+ case ID_OPTGROUP:
+ n = new HTMLOptGroupElementImpl(docPtr());
+ break;
+ case ID_OPTION:
+ n = new HTMLOptionElementImpl(docPtr());
+ break;
+ case ID_SELECT:
+ n = new HTMLSelectElementImpl(docPtr());
+ break;
+ case ID_TEXTAREA:
+ n = new HTMLTextAreaElementImpl(docPtr());
+ break;
+
+// lists
+ case ID_DL:
+ n = new HTMLDListElementImpl(docPtr());
+ break;
+ case ID_DD:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+ case ID_DT:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+ case ID_UL:
+ n = new HTMLUListElementImpl(docPtr());
+ break;
+ case ID_OL:
+ n = new HTMLOListElementImpl(docPtr());
+ break;
+ case ID_DIR:
+ n = new HTMLDirectoryElementImpl(docPtr());
+ break;
+ case ID_MENU:
+ n = new HTMLMenuElementImpl(docPtr());
+ break;
+ case ID_LI:
+ n = new HTMLLIElementImpl(docPtr());
+ break;
+
+// formatting elements (block)
+ case ID_DIV:
+ case ID_P:
+ n = new HTMLDivElementImpl( docPtr(), id );
+ break;
+ case ID_BLOCKQUOTE:
+ case ID_H1:
+ case ID_H2:
+ case ID_H3:
+ case ID_H4:
+ case ID_H5:
+ case ID_H6:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+ case ID_HR:
+ n = new HTMLHRElementImpl(docPtr());
+ break;
+ case ID_PLAINTEXT:
+ case ID_XMP:
+ case ID_PRE:
+ n = new HTMLPreElementImpl(docPtr(), id);
+ break;
+
+// font stuff
+ case ID_BASEFONT:
+ n = new HTMLBaseFontElementImpl(docPtr());
+ break;
+ case ID_FONT:
+ n = new HTMLFontElementImpl(docPtr());
+ break;
+
+// ins/del
+ case ID_DEL:
+ case ID_INS:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+
+// anchor
+ case ID_A:
+ n = new HTMLAnchorElementImpl(docPtr());
+ break;
+
+// images
+ case ID_IMG:
+ n = new HTMLImageElementImpl(docPtr());
+ break;
+ case ID_MAP:
+ n = new HTMLMapElementImpl(docPtr());
+ /*n = map;*/
+ break;
+ case ID_AREA:
+ n = new HTMLAreaElementImpl(docPtr());
+ break;
+
+// objects, applets and scripts
+ case ID_APPLET:
+ n = new HTMLAppletElementImpl(docPtr());
+ break;
+ case ID_OBJECT:
+ n = new HTMLObjectElementImpl(docPtr());
+ break;
+ case ID_EMBED:
+ n = new HTMLEmbedElementImpl(docPtr());
+ break;
+ case ID_PARAM:
+ n = new HTMLParamElementImpl(docPtr());
+ break;
+ case ID_SCRIPT:
+ n = new HTMLScriptElementImpl(docPtr());
+ break;
+
+// tables
+ case ID_TABLE:
+ n = new HTMLTableElementImpl(docPtr());
+ break;
+ case ID_CAPTION:
+ n = new HTMLTableCaptionElementImpl(docPtr());
+ break;
+ case ID_COLGROUP:
+ case ID_COL:
+ n = new HTMLTableColElementImpl(docPtr(), id);
+ break;
+ case ID_TR:
+ n = new HTMLTableRowElementImpl(docPtr());
+ break;
+ case ID_TD:
+ case ID_TH:
+ n = new HTMLTableCellElementImpl(docPtr(), id);
+ break;
+ case ID_THEAD:
+ case ID_TBODY:
+ case ID_TFOOT:
+ n = new HTMLTableSectionElementImpl(docPtr(), id, false);
+ break;
+
+// inline elements
+ case ID_BR:
+ n = new HTMLBRElementImpl(docPtr());
+ break;
+ case ID_Q:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+
+// elements with no special representation in the DOM
+
+// block:
+ case ID_ADDRESS:
+ case ID_CENTER:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ 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_NOBR:
+ case ID_WBR:
+ case ID_BDO:
+ case ID_NOFRAMES:
+ n = new HTMLGenericElementImpl(docPtr(), id);
+ break;
+
+ case ID_MARQUEE:
+ n = new HTMLMarqueeElementImpl(docPtr());
+ break;
+// text
+ case ID_TEXT:
+ kdDebug( 6020 ) << "Use document->createTextNode()" << endl;
+ break;
+
+ default:
+ break;
+ }
+ return n;
+}
+
+TQString DocumentImpl::nextState()
+{
+ TQString state;
+ if (!m_state.isEmpty())
+ {
+ state = m_state.first();
+ m_state.remove(m_state.begin());
+ }
+ return state;
+}
+
+TQStringList DocumentImpl::docState()
+{
+ TQStringList s;
+ for (TQPtrListIterator<NodeImpl> it(m_maintainsState); it.current(); ++it)
+ s.append(it.current()->state());
+
+ return s;
+}
+
+bool DocumentImpl::unsubmittedFormChanges()
+{
+ for (TQPtrListIterator<NodeImpl> it(m_maintainsState); it.current(); ++it)
+ if (it.current()->state().right(1)=="M")
+ return true;
+
+ return false;
+}
+
+RangeImpl *DocumentImpl::createRange()
+{
+ return new RangeImpl( docPtr() );
+}
+
+NodeIteratorImpl *DocumentImpl::createNodeIterator(NodeImpl *root, unsigned long whatToShow,
+ NodeFilter &filter, bool entityReferenceExpansion,
+ int &exceptioncode)
+{
+ if (!root) {
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+ return 0;
+ }
+
+ return new NodeIteratorImpl(root,whatToShow,filter,entityReferenceExpansion);
+}
+
+TreeWalkerImpl *DocumentImpl::createTreeWalker(NodeImpl *root, unsigned long whatToShow, NodeFilterImpl *filter,
+ bool entityReferenceExpansion, int &exceptioncode)
+{
+ if (!root) {
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+ return 0;
+ }
+
+ return new TreeWalkerImpl( root, whatToShow, filter, entityReferenceExpansion );
+}
+
+void DocumentImpl::setDocumentChanged(bool b)
+{
+ if (!changedDocuments)
+ changedDocuments = s_changedDocumentsDeleter.setObject( changedDocuments, new TQPtrList<DocumentImpl>() );
+
+ if (b && !m_docChanged)
+ changedDocuments->append(this);
+ else if (!b && m_docChanged)
+ changedDocuments->remove(this);
+ m_docChanged = b;
+}
+
+void DocumentImpl::recalcStyle( StyleChange change )
+{
+// tqDebug("recalcStyle(%p)", this);
+// TQTime qt;
+// qt.start();
+ if (m_inStyleRecalc)
+ return; // Guard against re-entrancy. -dwh
+
+ m_inStyleRecalc = true;
+
+ if( !m_render ) goto bail_out;
+
+ if ( change == Force ) {
+ RenderStyle* oldStyle = m_render->style();
+ if ( oldStyle ) oldStyle->ref();
+ RenderStyle* _style = new RenderStyle();
+ _style->setDisplay(BLOCK);
+ _style->setVisuallyOrdered( visuallyOrdered );
+ // ### make the font stuff _really_ work!!!!
+
+ tdehtml::FontDef fontDef;
+ TQFont f = TDEGlobalSettings::generalFont();
+ fontDef.family = f.family();
+ fontDef.italic = f.italic();
+ fontDef.weight = f.weight();
+ if (m_view) {
+ const KHTMLSettings *settings = m_view->part()->settings();
+ TQString stdfont = settings->stdFontName();
+ if ( !stdfont.isEmpty() )
+ fontDef.family = stdfont;
+
+ fontDef.size = m_styleSelector->fontSizes()[3];
+ }
+
+ //kdDebug() << "DocumentImpl::attach: setting to charset " << settings->charset() << endl;
+ _style->setFontDef(fontDef);
+ _style->htmlFont().update( paintDeviceMetrics() );
+ if ( inCompatMode() )
+ _style->setHtmlHacks(true); // enable html specific rendering tricks
+
+ StyleChange ch = diff( _style, oldStyle );
+ if(m_render && ch != NoChange)
+ m_render->setStyle(_style);
+ else
+ delete _style;
+ if ( change != Force )
+ change = ch;
+
+ if (oldStyle)
+ oldStyle->deref();
+ }
+
+ NodeImpl *n;
+ for (n = _first; n; n = n->nextSibling())
+ if ( change>= Inherit || n->hasChangedChild() || n->changed() )
+ n->recalcStyle( change );
+ //kdDebug( 6020 ) << "TIME: recalcStyle() dt=" << qt.elapsed() << endl;
+
+ if (changed() && m_view)
+ m_view->layout();
+
+bail_out:
+ setChanged( false );
+ setHasChangedChild( false );
+ setDocumentChanged( false );
+
+ m_inStyleRecalc = false;
+}
+
+void DocumentImpl::updateRendering()
+{
+ if (!hasChangedChild()) return;
+
+// TQTime time;
+// time.start();
+// kdDebug() << "UPDATERENDERING: "<<endl;
+
+ StyleChange change = NoChange;
+#if 0
+ if ( m_styleSelectorDirty ) {
+ recalcStyleSelector();
+ change = Force;
+ }
+#endif
+ recalcStyle( change );
+
+// kdDebug() << "UPDATERENDERING time used="<<time.elapsed()<<endl;
+}
+
+void DocumentImpl::updateDocumentsRendering()
+{
+ if (!changedDocuments)
+ return;
+
+ while ( !changedDocuments->isEmpty() ) {
+ changedDocuments->first();
+ DocumentImpl* it = changedDocuments->take();
+ if (it->isDocumentChanged())
+ it->updateRendering();
+ }
+}
+
+void DocumentImpl::updateLayout()
+{
+ bool oldIgnore = m_ignorePendingStylesheets;
+
+ if (!haveStylesheetsLoaded()) {
+ m_ignorePendingStylesheets = true;
+ updateStyleSelector();
+ }
+
+ updateRendering();
+
+ // Only do a layout if changes have occurred that make it necessary.
+ if (m_view && renderer() && renderer()->needsLayout())
+ m_view->layout();
+
+ m_ignorePendingStylesheets = oldIgnore;
+}
+
+void DocumentImpl::attach()
+{
+ assert(!attached());
+
+ if ( m_view )
+ setPaintDevice( TQT_TQPAINTDEVICE(m_view) );
+
+ if (!m_renderArena)
+ m_renderArena.reset(new RenderArena());
+
+ // Create the rendering tree
+ assert(!m_styleSelector);
+ m_styleSelector = new CSSStyleSelector( this, m_usersheet, m_styleSheets, m_url,
+ !inCompatMode() );
+ m_render = new (m_renderArena.get()) RenderCanvas(this, m_view);
+ m_styleSelector->computeFontSizes(paintDeviceMetrics(), m_view ? m_view->part()->zoomFactor() : 100);
+ recalcStyle( Force );
+
+ RenderObject* render = m_render;
+ m_render = 0;
+
+ NodeBaseImpl::attach();
+ m_render = render;
+}
+
+void DocumentImpl::detach()
+{
+ RenderObject* render = m_render;
+
+ // indicate destruction mode, i.e. attached() but m_render == 0
+ m_render = 0;
+
+ delete m_tokenizer;
+ m_tokenizer = 0;
+
+ // Empty out these lists as a performance optimization
+ m_imageLoadEventDispatchSoonList.clear();
+ m_imageLoadEventDispatchingList.clear();
+ NodeBaseImpl::detach();
+
+ if ( render )
+ render->detach();
+
+ m_view = 0;
+
+ m_renderArena.reset();
+}
+
+void DocumentImpl::setVisuallyOrdered()
+{
+ visuallyOrdered = true;
+ if (m_render)
+ m_render->style()->setVisuallyOrdered(true);
+}
+
+void DocumentImpl::setSelection(NodeImpl* s, int sp, NodeImpl* e, int ep)
+{
+ if ( m_render )
+ static_cast<RenderCanvas*>(m_render)->setSelection(s->renderer(),sp,e->renderer(),ep);
+}
+
+void DocumentImpl::clearSelection()
+{
+ if ( m_render )
+ static_cast<RenderCanvas*>(m_render)->clearSelection();
+}
+
+tdehtml::Tokenizer *DocumentImpl::createTokenizer()
+{
+ return new tdehtml::XMLTokenizer(docPtr(),m_view);
+}
+
+void DocumentImpl::setPaintDevice( TQPaintDevice *dev )
+{
+ if (m_paintDevice != dev) {
+ m_paintDevice = dev;
+ delete m_paintDeviceMetrics;
+ m_paintDeviceMetrics = new TQPaintDeviceMetrics( dev );
+ }
+}
+
+void DocumentImpl::open( bool clearEventListeners )
+{
+ if (parsing()) return;
+
+ if (m_tokenizer)
+ close();
+
+ delete m_tokenizer;
+ m_tokenizer = 0;
+
+ KHTMLView* view = m_view;
+ bool was_attached = attached();
+ if ( was_attached )
+ detach();
+
+ removeChildren();
+ delete m_styleSelector;
+ m_styleSelector = 0;
+ m_view = view;
+ if ( was_attached )
+ attach();
+
+ if (clearEventListeners)
+ m_windowEventListeners.clear();
+
+ m_tokenizer = createTokenizer();
+ m_decoderMibEnum = 0;
+ connect(m_tokenizer,TQT_SIGNAL(finishedParsing()),this,TQT_SIGNAL(finishedParsing()));
+ m_tokenizer->begin();
+}
+
+HTMLElementImpl* DocumentImpl::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 DocumentImpl::close( )
+{
+ if (parsing() || !m_tokenizer) return;
+
+ if ( m_render )
+ m_render->close();
+
+ // on an explicit document.close(), the tokenizer might still be waiting on scripts,
+ // and in that case we don't want to destroy it because that will prevent the
+ // scripts from getting processed.
+ if (m_tokenizer && !m_tokenizer->isWaitingForScripts() && !m_tokenizer->isExecutingScript()) {
+ delete m_tokenizer;
+ m_tokenizer = 0;
+ }
+
+ if (m_view)
+ m_view->part()->checkEmitLoadEvent();
+}
+
+void DocumentImpl::write( const DOMString &text )
+{
+ write(text.string());
+}
+
+void DocumentImpl::write( const TQString &text )
+{
+ if (!m_tokenizer) {
+ open();
+ if (m_view)
+ m_view->part()->resetFromScript();
+ m_tokenizer->setAutoClose();
+ write(TQString::fromLatin1("<html>"));
+ }
+ m_tokenizer->write(text, false);
+}
+
+void DocumentImpl::writeln( const DOMString &text )
+{
+ write(text);
+ write(DOMString("\n"));
+}
+
+void DocumentImpl::finishParsing ( )
+{
+ if(m_tokenizer)
+ m_tokenizer->finish();
+}
+
+void DocumentImpl::setUserStyleSheet( const TQString& sheet )
+{
+ if ( m_usersheet != sheet ) {
+ m_usersheet = sheet;
+ updateStyleSelector();
+ }
+}
+
+CSSStyleSheetImpl* DocumentImpl::elementSheet()
+{
+ if (!m_elemSheet) {
+ m_elemSheet = new CSSStyleSheetImpl(this, baseURL().url() );
+ m_elemSheet->ref();
+ }
+ return m_elemSheet;
+}
+
+void DocumentImpl::determineParseMode( const TQString &/*str*/ )
+{
+ // For XML documents, use strict parse mode
+ pMode = Strict;
+ hMode = XHtml;
+ kdDebug(6020) << " using strict parseMode" << endl;
+}
+
+NodeImpl *DocumentImpl::nextFocusNode(NodeImpl *fromNode)
+{
+ unsigned short fromTabIndex;
+
+ if (!fromNode) {
+ // No starting node supplied; begin with the top of the document
+ NodeImpl *n;
+
+ int lowestTabIndex = 65535;
+ for (n = this; n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable()) {
+ if ((n->tabIndex() > 0) && (n->tabIndex() < lowestTabIndex))
+ lowestTabIndex = n->tabIndex();
+ }
+ }
+
+ if (lowestTabIndex == 65535)
+ lowestTabIndex = 0;
+
+ // Go to the first node in the document that has the desired tab index
+ for (n = this; n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == lowestTabIndex))
+ return n;
+ }
+
+ return 0;
+ }
+ else {
+ fromTabIndex = fromNode->tabIndex();
+ }
+
+ if (fromTabIndex == 0) {
+ // Just need to find the next selectable node after fromNode (in document order) that doesn't have a tab index
+ NodeImpl *n = fromNode->traverseNextNode();
+ while (n && !(n->isTabFocusable() && n->tabIndex() == 0))
+ n = n->traverseNextNode();
+ return n;
+ }
+ else {
+ // Find the lowest tab index out of all the nodes except fromNode, that is greater than or equal to fromNode's
+ // tab index. For nodes with the same tab index as fromNode, we are only interested in those that come after
+ // fromNode in document order.
+ // If we don't find a suitable tab index, the next focus node will be one with a tab index of 0.
+ unsigned short lowestSuitableTabIndex = 65535;
+ NodeImpl *n;
+
+ bool reachedFromNode = false;
+ for (n = this; n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() &&
+ ((reachedFromNode && (n->tabIndex() >= fromTabIndex)) ||
+ (!reachedFromNode && (n->tabIndex() > fromTabIndex))) &&
+ (n->tabIndex() < lowestSuitableTabIndex) &&
+ (n != fromNode)) {
+
+ // We found a selectable node with a tab index at least as high as fromNode's. Keep searching though,
+ // as there may be another node which has a lower tab index but is still suitable for use.
+ lowestSuitableTabIndex = n->tabIndex();
+ }
+
+ if (n == fromNode)
+ reachedFromNode = true;
+ }
+
+ if (lowestSuitableTabIndex == 65535) {
+ // No next node with a tab index -> just take first node with tab index of 0
+ NodeImpl *n = this;
+ while (n && !(n->isTabFocusable() && n->tabIndex() == 0))
+ n = n->traverseNextNode();
+ return n;
+ }
+
+ // Search forwards from fromNode
+ for (n = fromNode->traverseNextNode(); n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == lowestSuitableTabIndex))
+ return n;
+ }
+
+ // The next node isn't after fromNode, start from the beginning of the document
+ for (n = this; n != fromNode; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == lowestSuitableTabIndex))
+ return n;
+ }
+
+ assert(false); // should never get here
+ return 0;
+ }
+}
+
+NodeImpl *DocumentImpl::previousFocusNode(NodeImpl *fromNode)
+{
+ NodeImpl *lastNode = this;
+ while (lastNode->lastChild())
+ lastNode = lastNode->lastChild();
+
+ if (!fromNode) {
+ // No starting node supplied; begin with the very last node in the document
+ NodeImpl *n;
+
+ int highestTabIndex = 0;
+ for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
+ if (n->isTabFocusable()) {
+ if (n->tabIndex() == 0)
+ return n;
+ else if (n->tabIndex() > highestTabIndex)
+ highestTabIndex = n->tabIndex();
+ }
+ }
+
+ // No node with a tab index of 0; just go to the last node with the highest tab index
+ for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == highestTabIndex))
+ return n;
+ }
+
+ return 0;
+ }
+ else {
+ unsigned short fromTabIndex = fromNode->tabIndex();
+
+ if (fromTabIndex == 0) {
+ // Find the previous selectable node before fromNode (in document order) that doesn't have a tab index
+ NodeImpl *n = fromNode->traversePreviousNode();
+ while (n && !(n->isTabFocusable() && n->tabIndex() == 0))
+ n = n->traversePreviousNode();
+ if (n)
+ return n;
+
+ // No previous nodes with a 0 tab index, go to the last node in the document that has the highest tab index
+ int highestTabIndex = 0;
+ for (n = this; n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() > highestTabIndex))
+ highestTabIndex = n->tabIndex();
+ }
+
+ if (highestTabIndex == 0)
+ return 0;
+
+ for (n = lastNode; n != 0; n = n->traversePreviousNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == highestTabIndex))
+ return n;
+ }
+
+ assert(false); // should never get here
+ return 0;
+ }
+ else {
+ // Find the lowest tab index out of all the nodes except fromNode, that is less than or equal to fromNode's
+ // tab index. For nodes with the same tab index as fromNode, we are only interested in those before
+ // fromNode.
+ // If we don't find a suitable tab index, then there will be no previous focus node.
+ unsigned short highestSuitableTabIndex = 0;
+ NodeImpl *n;
+
+ bool reachedFromNode = false;
+ for (n = this; n != 0; n = n->traverseNextNode()) {
+ if (n->isTabFocusable() &&
+ ((!reachedFromNode && (n->tabIndex() <= fromTabIndex)) ||
+ (reachedFromNode && (n->tabIndex() < fromTabIndex))) &&
+ (n->tabIndex() > highestSuitableTabIndex) &&
+ (n != fromNode)) {
+
+ // We found a selectable node with a tab index no higher than fromNode's. Keep searching though, as
+ // there may be another node which has a higher tab index but is still suitable for use.
+ highestSuitableTabIndex = n->tabIndex();
+ }
+
+ if (n == fromNode)
+ reachedFromNode = true;
+ }
+
+ if (highestSuitableTabIndex == 0) {
+ // No previous node with a tab index. Since the order specified by HTML is nodes with tab index > 0
+ // first, this means that there is no previous node.
+ return 0;
+ }
+
+ // Search backwards from fromNode
+ for (n = fromNode->traversePreviousNode(); n != 0; n = n->traversePreviousNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == highestSuitableTabIndex))
+ return n;
+ }
+ // The previous node isn't before fromNode, start from the end of the document
+ for (n = lastNode; n != fromNode; n = n->traversePreviousNode()) {
+ if (n->isTabFocusable() && (n->tabIndex() == highestSuitableTabIndex))
+ return n;
+ }
+
+ assert(false); // should never get here
+ return 0;
+ }
+ }
+}
+
+ElementImpl* DocumentImpl::findAccessKeyElement(TQChar c)
+{
+ c = c.upper();
+ for( NodeImpl* n = this;
+ n != NULL;
+ n = n->traverseNextNode()) {
+ if( n->isElementNode()) {
+ ElementImpl* en = static_cast< ElementImpl* >( n );
+ DOMString s = en->getAttribute( ATTR_ACCESSKEY );
+ if( s.length() == 1
+ && s[ 0 ].upper() == c )
+ return en;
+ }
+ }
+ return NULL;
+}
+
+int DocumentImpl::nodeAbsIndex(NodeImpl *node)
+{
+ assert(node->getDocument() == this);
+
+ int absIndex = 0;
+ for (NodeImpl *n = node; n && n != this; n = n->traversePreviousNode())
+ absIndex++;
+ return absIndex;
+}
+
+NodeImpl *DocumentImpl::nodeWithAbsIndex(int absIndex)
+{
+ NodeImpl *n = this;
+ for (int i = 0; n && (i < absIndex); i++) {
+ n = n->traverseNextNode();
+ }
+ return n;
+}
+
+void DocumentImpl::processHttpEquiv(const DOMString &equiv, const DOMString &content)
+{
+ assert(!equiv.isNull() && !content.isNull());
+
+ KHTMLView *v = getDocument()->view();
+
+ if(strcasecmp(equiv, "refresh") == 0 && v && v->part()->metaRefreshEnabled())
+ {
+ // get delay and url
+ TQString str = content.string().stripWhiteSpace();
+ int pos = str.find(TQRegExp("[;,]"));
+ if ( pos == -1 )
+ pos = str.find(TQRegExp("[ \t]"));
+
+ bool ok = false;
+ int delay = kMax( 0, content.implementation()->toInt(&ok) );
+ if ( !ok && str.length() && str[0] == '.' )
+ ok = true;
+
+ if (pos == -1) // There can be no url (David)
+ {
+ if(ok)
+ v->part()->scheduleRedirection(delay, v->part()->url().url() );
+ } else {
+ pos++;
+ while(pos < (int)str.length() && str[pos].isSpace()) pos++;
+ str = str.mid(pos);
+ if(str.find("url", 0, false ) == 0) str = str.mid(3);
+ str = str.stripWhiteSpace();
+ if ( str.length() && str[0] == '=' ) str = str.mid( 1 ).stripWhiteSpace();
+ while(str.length() &&
+ (str[str.length()-1] == ';' || str[str.length()-1] == ','))
+ str.setLength(str.length()-1);
+ str = parseURL( DOMString(str) ).string();
+ TQString newURL = getDocument()->completeURL( str );
+ if ( ok )
+ v->part()->scheduleRedirection(delay, getDocument()->completeURL( str ), delay < 2 || newURL == URL().url());
+ }
+ }
+ else if(strcasecmp(equiv, "expires") == 0)
+ {
+ bool relative = false;
+ TQString str = content.string().stripWhiteSpace();
+ time_t expire_date = KRFCDate::parseDate(str);
+ if (!expire_date)
+ {
+ expire_date = str.toULong();
+ relative = true;
+ }
+ if (!expire_date)
+ expire_date = 1; // expire now
+ if (m_docLoader)
+ m_docLoader->setExpireDate(expire_date, relative);
+ }
+ else if(v && (strcasecmp(equiv, "pragma") == 0 || strcasecmp(equiv, "cache-control") == 0))
+ {
+ TQString str = content.string().lower().stripWhiteSpace();
+ KURL url = v->part()->url();
+ if ((str == "no-cache") && url.protocol().startsWith("http"))
+ {
+ TDEIO::http_update_cache(url, true, 0);
+ }
+ }
+ else if( (strcasecmp(equiv, "set-cookie") == 0))
+ {
+ // ### make setCookie work on XML documents too; e.g. in case of <html:meta .....>
+ HTMLDocumentImpl *d = static_cast<HTMLDocumentImpl *>(this);
+ d->setCookie(content);
+ }
+ else if (strcasecmp(equiv, "default-style") == 0) {
+ // HTML 4.0 14.3.2
+ // http://www.hixie.ch/tests/evil/css/import/main/preferred.html
+ m_preferredStylesheetSet = content;
+ updateStyleSelector();
+ }
+ else if (strcasecmp(equiv, "content-language") == 0) {
+ m_contentLanguage = content.string();
+ }
+}
+
+bool DocumentImpl::prepareMouseEvent( bool readonly, int _x, int _y, MouseEvent *ev )
+{
+ if ( m_render ) {
+ assert(m_render->isCanvas());
+ RenderObject::NodeInfo renderInfo(readonly, ev->type == MousePress);
+ bool isInside = m_render->layer()->nodeAtPoint(renderInfo, _x, _y);
+ ev->innerNode = renderInfo.innerNode();
+ ev->innerNonSharedNode = renderInfo.innerNonSharedNode();
+
+ if (renderInfo.URLElement()) {
+ assert(renderInfo.URLElement()->isElementNode());
+ //tqDebug("urlnode: %s (%d)", getTagName(renderInfo.URLElement()->id()).string().latin1(), renderInfo.URLElement()->id());
+
+ ElementImpl* e = static_cast<ElementImpl*>(renderInfo.URLElement());
+ DOMString href = tdehtml::parseURL(e->getAttribute(ATTR_HREF));
+ DOMString target = e->getAttribute(ATTR_TARGET);
+
+ if (!target.isNull() && !href.isNull()) {
+ ev->target = target;
+ ev->url = href;
+ }
+ else
+ ev->url = href;
+ }
+
+ if (!readonly)
+ updateRendering();
+
+ return isInside;
+ }
+
+
+ return false;
+}
+
+
+// DOM Section 1.1.1
+bool DocumentImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::ATTRIBUTE_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::DOCUMENT_FRAGMENT_NODE:
+ case Node::DOCUMENT_NODE:
+ case Node::ENTITY_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ case Node::NOTATION_NODE:
+ case Node::TEXT_NODE:
+// case Node::XPATH_NAMESPACE_NODE:
+ return false;
+ case Node::COMMENT_NODE:
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ return true;
+ case Node::DOCUMENT_TYPE_NODE:
+ case Node::ELEMENT_NODE:
+ // Documents may contain no more than one of each of these.
+ // (One Element and one DocumentType.)
+ for (NodeImpl* c = firstChild(); c; c = c->nextSibling())
+ if (c->nodeType() == type)
+ return false;
+ return true;
+ }
+ return false;
+}
+
+NodeImpl *DocumentImpl::cloneNode ( bool /*deep*/ )
+{
+ // Spec says cloning Document nodes is "implementation dependent"
+ // so we do not support it...
+ return 0;
+}
+
+
+typedef const char* (*NameLookupFunction)(unsigned short id);
+typedef int (*IdLookupFunction)(const char *tagStr, int len);
+
+NodeImpl::Id DocumentImpl::getId( NodeImpl::IdType _type, DOMStringImpl* _nsURI, DOMStringImpl *_prefix,
+ DOMStringImpl *_name, bool readonly, bool /*lookupHTML*/, int *pExceptioncode)
+{
+ /*kdDebug() << "DocumentImpl::getId( type: " << _type << ", uri: " << DOMString(_nsURI).string()
+ << ", prefix: " << DOMString(_prefix).string() << ", name: " << DOMString(_name).string()
+ << ", readonly: " << readonly
+ << ", lookupHTML: " << lookupHTML
+ << ", exceptions: " << (pExceptioncode ? "yes" : "no")
+ << " )" << endl;*/
+
+ if(!_name) return 0;
+ IdNameMapping *map;
+ IdLookupFunction lookup;
+
+ switch (_type) {
+ case NodeImpl::ElementId:
+ map = m_elementMap;
+ lookup = getTagID;
+ break;
+ case NodeImpl::AttributeId:
+ map = m_attrMap;
+ lookup = getAttrID;
+ break;
+ case NodeImpl::NamespaceId:
+ if( strcasecmp(_name, XHTML_NAMESPACE) == 0)
+ return xhtmlNamespace;
+ if( _name->l == 0)
+ return emptyNamespace;
+ // defaultNamespace handled by "if (!_name) return 0"
+ map = m_namespaceMap;
+ lookup = 0;
+ break;
+ default:
+ return 0;
+ }
+ // Names and attributes with ""
+ if (_name->l == 0) return 0;
+
+ NodeImpl::Id id, nsid = 0;
+ TQConstString n(_name->s, _name->l);
+ bool cs = true; // case sensitive
+ if (_type != NodeImpl::NamespaceId) {
+ if (_nsURI)
+ nsid = getId( NodeImpl::NamespaceId, 0, 0, _nsURI, false, false, 0 ) << 16;
+
+ // Each document maintains a mapping of tag name -> id for every tag name encountered
+ // in the document.
+ cs = (htmlMode() == XHtml) || (_nsURI && _type != NodeImpl::AttributeId);
+
+ // First see if it's a HTML element name
+ // xhtml is lower case - case sensitive, easy to implement
+ if ( cs && (id = lookup(n.string().ascii(), _name->l)) ) {
+ map->addAlias(_prefix, _name, cs, id);
+ return nsid + id;
+ }
+ // compatibility: upper case - case insensitive
+ if ( !cs && (id = lookup(n.string().lower().ascii(), _name->l )) ) {
+ map->addAlias(_prefix, _name, cs, id);
+ return nsid + id;
+ }
+ }
+
+ // Look in the names array for the name
+ // compatibility mode has to lookup upper case
+ TQString name = cs ? n.string() : n.string().upper();
+
+ if (!_nsURI) {
+ id = (NodeImpl::Id)(long) map->ids.find( name );
+ if (!id && _type != NodeImpl::NamespaceId) {
+ id = (NodeImpl::Id)(long) map->ids.find( "aliases: " + name );
+ }
+ } else {
+ id = (NodeImpl::Id)(long) map->ids.find( name );
+ if (!readonly && id && _prefix && _prefix->l) {
+ // we were called in registration mode... check if the alias exists
+ TQConstString px( _prefix->s, _prefix->l );
+ TQString qn("aliases: " + (cs ? px.string() : px.string().upper()) + ":" + name);
+ if (!map->ids.find( qn )) {
+ map->ids.insert( qn, (void*)id );
+ }
+ }
+ }
+
+ if (id) return nsid + id;
+
+ // unknown
+ if (readonly) return 0;
+
+ if ( pExceptioncode && _type != NodeImpl::NamespaceId && !Element::tdehtmlValidQualifiedName(_name)) {
+ *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
+ return 0;
+ }
+
+ // Name not found, so let's add it
+ NodeImpl::Id cid = map->count++ + map->idStart;
+ map->names.insert( cid, _name );
+ _name->ref();
+
+ map->ids.insert( name, (void*)cid );
+
+ // and register an alias if needed for DOM1 methods compatibility
+ map->addAlias(_prefix, _name, cs, cid);
+
+ return nsid + cid;
+ }
+
+NodeImpl::Id DocumentImpl::getId( NodeImpl::IdType _type, DOMStringImpl *_nodeName, bool readonly, bool lookupHTML, int *pExceptioncode)
+{
+ return getId(_type, 0, 0, _nodeName, readonly, lookupHTML, pExceptioncode);
+}
+
+DOMString DocumentImpl::getName( NodeImpl::IdType _type, NodeImpl::Id _id ) const
+{
+ IdNameMapping *map;
+ NameLookupFunction lookup;
+ bool hasNS = (namespacePart(_id) != defaultNamespace);
+ switch (_type) {
+ case NodeImpl::ElementId:
+ map = m_elementMap;
+ lookup = getTagName;
+ break;
+ case NodeImpl::AttributeId:
+ map = m_attrMap;
+ lookup = getAttrName;
+ break;
+ case NodeImpl::NamespaceId:
+ if( _id == xhtmlNamespace )
+ return XHTML_NAMESPACE;
+ else
+ if( _id == emptyNamespace )
+ return DOMString("");
+ else
+ if ( _id == defaultNamespace )
+ return DOMString();
+ map = m_namespaceMap;
+ lookup = 0;
+ break;
+ default:
+ return DOMString();;
+ }
+ _id = localNamePart(_id) ;
+ if (_id >= map->idStart) {
+ return map->names[_id];
+ }
+ else if (lookup) {
+ // ### put them in a cache
+ if (hasNS)
+ return DOMString(lookup(_id)).lower();
+ else
+ return lookup(_id);
+ } else
+ return DOMString();
+}
+
+// This method is called whenever a top-level stylesheet has finished loading.
+void DocumentImpl::styleSheetLoaded()
+{
+ // Make sure we knew this sheet was pending, and that our count isn't out of sync.
+ assert(m_pendingStylesheets > 0);
+
+ m_pendingStylesheets--;
+ updateStyleSelector();
+}
+
+DOMString DocumentImpl::selectedStylesheetSet() const
+{
+ if (!view()) return DOMString();
+
+ return view()->part()->d->m_sheetUsed;
+}
+
+void DocumentImpl::setSelectedStylesheetSet(const DOMString& s)
+{
+ // this code is evil
+ if (view() && view()->part()->d->m_sheetUsed != s.string()) {
+ view()->part()->d->m_sheetUsed = s.string();
+ updateStyleSelector();
+ }
+}
+
+void DocumentImpl::addStyleSheet(StyleSheetImpl *sheet, int *exceptioncode)
+{
+ int excode = 0;
+
+ if (!m_addedStyleSheets) {
+ m_addedStyleSheets = new StyleSheetListImpl;
+ m_addedStyleSheets->ref();
+ }
+
+ m_addedStyleSheets->add(sheet);
+ if (sheet->isCSSStyleSheet()) updateStyleSelector();
+
+ if (exceptioncode) *exceptioncode = excode;
+}
+
+void DocumentImpl::removeStyleSheet(StyleSheetImpl *sheet, int *exceptioncode)
+{
+ int excode = 0;
+ bool removed = false;
+ bool is_css = sheet->isCSSStyleSheet();
+
+ if (m_addedStyleSheets) {
+ bool in_main_list = !sheet->hasOneRef();
+ removed = m_addedStyleSheets->styleSheets.removeRef(sheet);
+ sheet->deref();
+
+ if (m_addedStyleSheets->styleSheets.count() == 0) {
+ bool reset = m_addedStyleSheets->hasOneRef();
+ m_addedStyleSheets->deref();
+ if (reset) m_addedStyleSheets = 0;
+ }
+
+ // remove from main list, too
+ if (in_main_list) m_styleSheets->remove(sheet);
+ }
+
+ if (removed) {
+ if (is_css) updateStyleSelector();
+ } else
+ excode = DOMException::NOT_FOUND_ERR;
+
+ if (exceptioncode) *exceptioncode = excode;
+}
+
+void DocumentImpl::updateStyleSelector(bool shallow)
+{
+// kdDebug() << "PENDING " << m_pendingStylesheets << endl;
+
+ // Don't bother updating, since we haven't loaded all our style info yet.
+ if (m_pendingStylesheets > 0)
+ return;
+
+ if (shallow)
+ rebuildStyleSelector();
+ else
+ recalcStyleSelector();
+ recalcStyle(Force);
+#if 0
+
+ m_styleSelectorDirty = true;
+#endif
+ if ( renderer() )
+ renderer()->setNeedsLayoutAndMinMaxRecalc();
+}
+
+void DocumentImpl::recalcStyleSelector()
+{
+ if ( !m_render || !attached() ) return;
+
+ assert(m_pendingStylesheets==0);
+
+ TQPtrList<StyleSheetImpl> oldStyleSheets = m_styleSheets->styleSheets;
+ m_styleSheets->styleSheets.clear();
+ TQString sheetUsed = view() ? view()->part()->d->m_sheetUsed.replace("&&", "&") : TQString();
+ bool autoselect = sheetUsed.isEmpty();
+ if (autoselect && !m_preferredStylesheetSet.isEmpty())
+ sheetUsed = m_preferredStylesheetSet.string();
+ NodeImpl *n;
+ for (int i=0 ; i<2 ; i++) {
+ m_availableSheets.clear();
+ m_availableSheets << i18n("Basic Page Style");
+ bool canResetSheet = false;
+
+ for (n = this; n; n = n->traverseNextNode()) {
+ StyleSheetImpl *sheet = 0;
+
+ if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
+ {
+ // Processing instruction (XML documents only)
+ ProcessingInstructionImpl* pi = static_cast<ProcessingInstructionImpl*>(n);
+ sheet = pi->sheet();
+ if (!sheet && !pi->localHref().isEmpty())
+ {
+ // Processing instruction with reference to an element in this document - e.g.
+ // <?xml-stylesheet href="#mystyle">, with the element
+ // <foo id="mystyle">heading { color: red; }</foo> at some location in
+ // the document
+ ElementImpl* elem = getElementById(pi->localHref());
+ if (elem) {
+ DOMString sheetText("");
+ NodeImpl *c;
+ for (c = elem->firstChild(); c; c = c->nextSibling()) {
+ if (c->nodeType() == Node::TEXT_NODE || c->nodeType() == Node::CDATA_SECTION_NODE)
+ sheetText += c->nodeValue();
+ }
+
+ CSSStyleSheetImpl *cssSheet = new CSSStyleSheetImpl(this);
+ cssSheet->parseString(sheetText);
+ pi->setStyleSheet(cssSheet);
+ sheet = cssSheet;
+ }
+ }
+
+ }
+ else if (n->isHTMLElement() && ( n->id() == ID_LINK || n->id() == ID_STYLE) ) {
+ TQString title;
+ if ( n->id() == ID_LINK ) {
+ HTMLLinkElementImpl* l = static_cast<HTMLLinkElementImpl*>(n);
+ if (l->isCSSStyleSheet()) {
+ sheet = l->sheet();
+
+ if (sheet || l->isLoading() || l->isAlternate() )
+ title = l->getAttribute(ATTR_TITLE).string();
+
+ if ((autoselect || title != sheetUsed) && l->isDisabled()) {
+ sheet = 0;
+ } else if (!title.isEmpty() && !l->isAlternate() && sheetUsed.isEmpty()) {
+ sheetUsed = title;
+ l->setDisabled(false);
+ }
+ }
+ }
+ else {
+ // <STYLE> element
+ HTMLStyleElementImpl* s = static_cast<HTMLStyleElementImpl*>(n);
+ if (!s->isLoading()) {
+ sheet = s->sheet();
+ if (sheet) title = s->getAttribute(ATTR_TITLE).string();
+ }
+ if (!title.isEmpty() && sheetUsed.isEmpty())
+ sheetUsed = title;
+ }
+
+ if ( !title.isEmpty() ) {
+ if ( title != sheetUsed )
+ sheet = 0; // don't use it
+
+ title = title.replace('&', "&&");
+
+ if ( !m_availableSheets.contains( title ) )
+ m_availableSheets.append( title );
+ }
+ }
+ else if (n->isHTMLElement() && n->id() == ID_BODY) {
+ // <BODY> element (doesn't contain styles as such but vlink="..." and friends
+ // are treated as style declarations)
+ sheet = static_cast<HTMLBodyElementImpl*>(n)->sheet();
+ }
+
+ if (sheet) {
+ sheet->ref();
+ m_styleSheets->styleSheets.append(sheet);
+ }
+
+ // For HTML documents, stylesheets are not allowed within/after the <BODY> tag. So we
+ // can stop searching here.
+ if (isHTMLDocument() && n->id() == ID_BODY) {
+ canResetSheet = !canResetSheet;
+ break;
+ }
+ }
+
+ // we're done if we don't select an alternative sheet
+ // or we found the sheet we selected
+ if (sheetUsed.isEmpty() ||
+ (!canResetSheet && tokenizer()) ||
+ m_availableSheets.contains(sheetUsed)) {
+ break;
+ }
+
+ // the alternative sheet we used doesn't exist anymore
+ // so try from scratch again
+ if (view())
+ view()->part()->d->m_sheetUsed = TQString::null;
+ if (!m_preferredStylesheetSet.isEmpty() && !(sheetUsed == m_preferredStylesheetSet))
+ sheetUsed = m_preferredStylesheetSet.string();
+ else
+ sheetUsed = TQString::null;
+ autoselect = true;
+ }
+
+ // Include programmatically added style sheets
+ if (m_addedStyleSheets) {
+ TQPtrListIterator<StyleSheetImpl> it = m_addedStyleSheets->styleSheets;
+ for (; *it; ++it) {
+ if ((*it)->isCSSStyleSheet() && !(*it)->disabled())
+ m_styleSheets->add(*it);
+ }
+ }
+
+ // De-reference all the stylesheets in the old list
+ TQPtrListIterator<StyleSheetImpl> it(oldStyleSheets);
+ for (; it.current(); ++it)
+ it.current()->deref();
+
+ rebuildStyleSelector();
+}
+
+void DocumentImpl::rebuildStyleSelector()
+{
+ // Create a new style selector
+ delete m_styleSelector;
+ TQString usersheet = m_usersheet;
+ if ( m_view && m_view->mediaType() == "print" )
+ usersheet += m_printSheet;
+ m_styleSelector = new CSSStyleSelector( this, usersheet, m_styleSheets, m_url,
+ !inCompatMode() );
+
+ m_styleSelectorDirty = false;
+}
+
+void DocumentImpl::setHoverNode(NodeImpl *newHoverNode)
+{
+ NodeImpl* oldHoverNode = m_hoverNode;
+ if (newHoverNode ) newHoverNode->ref();
+ m_hoverNode = newHoverNode;
+ if ( oldHoverNode ) oldHoverNode->deref();
+}
+
+void DocumentImpl::setActiveNode(NodeImpl* newActiveNode)
+{
+ NodeImpl* oldActiveNode = m_activeNode;
+ if (newActiveNode ) newActiveNode->ref();
+ m_activeNode = newActiveNode;
+ if ( oldActiveNode ) oldActiveNode->deref();
+}
+
+void DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
+{
+ // don't process focus changes while detaching
+ if( !m_render ) return;
+
+ // We do want to blur if a widget is being detached,
+ // but we don't want to emit events since that
+ // triggers updateLayout() and may recurse detach()
+ bool widgetDetach = m_focusNode && m_focusNode != this &&
+ m_focusNode->renderer() && !m_focusNode->renderer()->parent();
+
+ // Make sure newFocusNode is actually in this document
+ if (newFocusNode && (newFocusNode->getDocument() != this))
+ return;
+
+ if (m_focusNode != newFocusNode) {
+ NodeImpl *oldFocusNode = m_focusNode;
+ // Set focus on the new node
+ m_focusNode = newFocusNode;
+ // Remove focus from the existing focus node (if any)
+ if (oldFocusNode) {
+ if (oldFocusNode->active())
+ oldFocusNode->setActive(false);
+
+ oldFocusNode->setFocus(false);
+
+ if (!widgetDetach) {
+ oldFocusNode->dispatchHTMLEvent(EventImpl::BLUR_EVENT,false,false);
+ oldFocusNode->dispatchUIEvent(EventImpl::DOMFOCUSOUT_EVENT);
+ }
+ if ((oldFocusNode == this) && oldFocusNode->hasOneRef()) {
+ oldFocusNode->deref(); // deletes this
+ return;
+ }
+ else {
+ oldFocusNode->deref();
+ }
+ }
+
+ if (m_focusNode) {
+ m_focusNode->ref();
+ m_focusNode->dispatchHTMLEvent(EventImpl::FOCUS_EVENT,false,false);
+ if (m_focusNode != newFocusNode) return;
+ m_focusNode->dispatchUIEvent(EventImpl::DOMFOCUSIN_EVENT);
+ if (m_focusNode != newFocusNode) return;
+ m_focusNode->setFocus();
+ if (m_focusNode != newFocusNode) return;
+
+ // eww, I suck. set the qt focus correctly
+ // ### find a better place in the code for this
+ if (view()) {
+ if (!m_focusNode->renderer() || !m_focusNode->renderer()->isWidget())
+ view()->setFocus();
+ else if (static_cast<RenderWidget*>(m_focusNode->renderer())->widget())
+ {
+ if (view()->isVisible())
+ static_cast<RenderWidget*>(m_focusNode->renderer())->widget()->setFocus();
+ }
+ }
+ } else {
+ //We're blurring. Better clear the Qt focus/give it to the view...
+ if (view())
+ view()->setFocus();
+ }
+
+ if (!widgetDetach)
+ updateRendering();
+ }
+}
+
+void DocumentImpl::setCSSTarget(NodeImpl* n)
+{
+ if (n == m_cssTarget)
+ return;
+
+ if (m_cssTarget) {
+ m_cssTarget->setChanged();
+ m_cssTarget->deref();
+ }
+ m_cssTarget = n;
+ if (n) {
+ n->setChanged();
+ n->ref();
+ }
+}
+
+void DocumentImpl::attachNodeIterator(NodeIteratorImpl *ni)
+{
+ m_nodeIterators.append(ni);
+}
+
+void DocumentImpl::detachNodeIterator(NodeIteratorImpl *ni)
+{
+ m_nodeIterators.remove(ni);
+}
+
+void DocumentImpl::notifyBeforeNodeRemoval(NodeImpl *n)
+{
+ TQPtrListIterator<NodeIteratorImpl> it(m_nodeIterators);
+ for (; it.current(); ++it)
+ it.current()->notifyBeforeNodeRemoval(n);
+}
+
+bool DocumentImpl::isURLAllowed(const TQString& url) const
+{
+ KHTMLPart *thisPart = part();
+
+ KURL newURL(completeURL(url));
+ newURL.setRef(TQString::null);
+
+ if (KHTMLFactory::defaultHTMLSettings()->isAdFiltered( newURL.url() ))
+ return false;
+
+ // Prohibit non-file URLs if we are asked to.
+ if (!thisPart || thisPart->onlyLocalReferences() && newURL.protocol() != "file" && newURL.protocol() != "data")
+ return false;
+
+ // do we allow this suburl ?
+ if ( !kapp || (newURL.protocol() != "javascript" && !kapp->authorizeURLAction("redirect", thisPart->url(), newURL)) )
+ return false;
+
+ // We allow one level of self-reference because some sites depend on that.
+ // But we don't allow more than one.
+ bool foundSelfReference = false;
+ for (KHTMLPart *part = thisPart; part; part = part->parentPart()) {
+ KURL partURL = part->url();
+ partURL.setRef(TQString::null);
+ if (partURL == newURL) {
+ if (foundSelfReference)
+ return false;
+ foundSelfReference = true;
+ }
+ }
+
+ return true;
+}
+
+void DocumentImpl::setDesignMode(bool b)
+{
+ if (part())
+ part()->setEditable(b);
+}
+
+bool DocumentImpl::designMode() const
+{
+ return part() ? part()->isEditable() : false;
+}
+
+EventImpl *DocumentImpl::createEvent(const DOMString &eventType, int &exceptioncode)
+{
+ if (eventType == "UIEvents" || eventType == "UIEvent")
+ return new UIEventImpl();
+ else if (eventType == "MouseEvents" || eventType == "MouseEvent")
+ return new MouseEventImpl();
+ else if (eventType == "TextEvent")
+ return new TextEventImpl();
+ else if (eventType == "KeyboardEvent")
+ return new KeyboardEventImpl();
+ else if (eventType == "MutationEvents" || eventType == "MutationEvent")
+ return new MutationEventImpl();
+ else if (eventType == "HTMLEvents" || eventType == "Events" ||
+ eventType == "HTMLEvent" || eventType == "Event")
+ return new EventImpl();
+ else {
+ exceptioncode = DOMException::NOT_SUPPORTED_ERR;
+ return 0;
+ }
+}
+
+CSSStyleDeclarationImpl *DocumentImpl::getOverrideStyle(ElementImpl* /*elt*/, DOMStringImpl* /*pseudoElt*/)
+{
+ return 0; // ###
+}
+
+void DocumentImpl::abort()
+{
+ if (m_inSyncLoad) {
+ m_inSyncLoad = false;
+ kapp->exit_loop();
+ }
+
+ if (m_loadingXMLDoc)
+ m_loadingXMLDoc->deref(this);
+ m_loadingXMLDoc = 0;
+}
+
+void DocumentImpl::load(const DOMString &uri)
+{
+ if (m_inSyncLoad) {
+ m_inSyncLoad = false;
+ kapp->exit_loop();
+ }
+
+ m_hadLoadError = false;
+ if (m_loadingXMLDoc)
+ m_loadingXMLDoc->deref(this);
+
+ // Use the document loader to retrieve the XML file. We use CachedCSSStyleSheet because
+ // this is an easy way to retrieve an arbitrary text file... it is not specific to
+ // stylesheets.
+
+ // ### Note: By loading the XML document this way we do not get the proper decoding
+ // of the data retrieved from the server based on the character set, as happens with
+ // HTML files. Need to look into a way of using the decoder in CachedCSSStyleSheet.
+ m_docLoading = true;
+ m_loadingXMLDoc = m_docLoader->requestStyleSheet(uri.string(),TQString(),"text/xml");
+
+ if (!m_loadingXMLDoc) {
+ m_docLoading = false;
+ return;
+ }
+
+ m_loadingXMLDoc->ref(this);
+
+ if (!m_async && m_docLoading) {
+ m_inSyncLoad = true;
+ kapp->enter_loop();
+ }
+}
+
+void DocumentImpl::loadXML(const DOMString &source)
+{
+ open(false);
+ write(source);
+ finishParsing();
+ close();
+ dispatchHTMLEvent(EventImpl::LOAD_EVENT,false,false);
+}
+
+void DocumentImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset)
+{
+ if (!m_hadLoadError) {
+ m_url = url.string();
+ loadXML(sheet);
+ }
+
+ m_docLoading = false;
+ if (m_inSyncLoad) {
+ m_inSyncLoad = false;
+ kapp->exit_loop();
+ }
+
+ assert(m_loadingXMLDoc != 0);
+ m_loadingXMLDoc->deref(this);
+ m_loadingXMLDoc = 0;
+}
+
+void DocumentImpl::error(int err, const TQString &text)
+{
+ m_docLoading = false;
+ if (m_inSyncLoad) {
+ m_inSyncLoad = false;
+ kapp->exit_loop();
+ }
+
+ m_hadLoadError = true;
+
+ int exceptioncode = 0;
+ EventImpl *evt = new EventImpl(EventImpl::ERROR_EVENT,false,false);
+ if (err != 0)
+ evt->setMessage(TDEIO::buildErrorString(err,text));
+ else
+ evt->setMessage(text);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+
+ assert(m_loadingXMLDoc != 0);
+ m_loadingXMLDoc->deref(this);
+ m_loadingXMLDoc = 0;
+}
+
+void DocumentImpl::defaultEventHandler(EventImpl *evt)
+{
+ // if any html event listeners are registered on the window, then dispatch them here
+ if (!m_windowEventListeners.listeners || evt->propagationStopped())
+ return;
+
+ TQValueList<RegisteredEventListener>::iterator it;
+
+ //Grab a copy in case of clear
+ TQValueList<RegisteredEventListener> listeners = *m_windowEventListeners.listeners;
+ Event ev(evt);
+ for (it = listeners.begin(); it != listeners.end(); ++it) {
+ //Check to make sure it didn't get removed. KDE4: use Java-style iterators
+ if (!m_windowEventListeners.stillContainsListener(*it))
+ continue;
+
+ if ((*it).id == evt->id()) {
+ // currentTarget must be 0 in tdehtml for kjs_events to set "this" correctly.
+ // (this is how we identify events dispatched to the window, like window.onmousedown)
+ // ## currentTarget is unimplemented in IE, and is "window" in Mozilla (how? not a DOM node)
+ evt->setCurrentTarget(0);
+ (*it).listener->handleEvent(ev);
+ }
+ }
+}
+
+void DocumentImpl::setHTMLWindowEventListener(int id, EventListener *listener)
+{
+ m_windowEventListeners.setHTMLEventListener(id, listener);
+}
+
+EventListener *DocumentImpl::getHTMLWindowEventListener(int id)
+{
+ return m_windowEventListeners.getHTMLEventListener(id);
+}
+
+void DocumentImpl::addWindowEventListener(int id, EventListener *listener, const bool useCapture)
+{
+ m_windowEventListeners.addEventListener(id, listener, useCapture);
+}
+
+void DocumentImpl::removeWindowEventListener(int id, EventListener *listener, bool useCapture)
+{
+ m_windowEventListeners.removeEventListener(id, listener, useCapture);
+}
+
+bool DocumentImpl::hasWindowEventListener(int id)
+{
+ return m_windowEventListeners.hasEventListener(id);
+}
+
+EventListener *DocumentImpl::createHTMLEventListener(const TQString& code, const TQString& name, NodeImpl* node)
+{
+ return part() ? part()->createHTMLEventListener(code, name, node) : 0;
+}
+
+void DocumentImpl::dispatchImageLoadEventSoon(HTMLImageElementImpl *image)
+{
+ m_imageLoadEventDispatchSoonList.append(image);
+ if (!m_imageLoadEventTimer) {
+ m_imageLoadEventTimer = startTimer(0);
+ }
+}
+
+void DocumentImpl::removeImage(HTMLImageElementImpl *image)
+{
+ // Remove instances of this image from both lists.
+ // Use loops because we allow multiple instances to get into the lists.
+ while (m_imageLoadEventDispatchSoonList.removeRef(image)) { }
+ while (m_imageLoadEventDispatchingList.removeRef(image)) { }
+ if (m_imageLoadEventDispatchSoonList.isEmpty() && m_imageLoadEventTimer) {
+ killTimer(m_imageLoadEventTimer);
+ m_imageLoadEventTimer = 0;
+ }
+}
+
+void DocumentImpl::dispatchImageLoadEventsNow()
+{
+ // need to avoid re-entering this function; if new dispatches are
+ // scheduled before the parent finishes processing the list, they
+ // will set a timer and eventually be processed
+ if (!m_imageLoadEventDispatchingList.isEmpty()) {
+ return;
+ }
+
+ if (m_imageLoadEventTimer) {
+ killTimer(m_imageLoadEventTimer);
+ m_imageLoadEventTimer = 0;
+ }
+
+ m_imageLoadEventDispatchingList = m_imageLoadEventDispatchSoonList;
+ m_imageLoadEventDispatchSoonList.clear();
+ for (TQPtrListIterator<HTMLImageElementImpl> it(m_imageLoadEventDispatchingList); it.current(); ) {
+ HTMLImageElementImpl* image = it.current();
+ // Must advance iterator *before* dispatching call.
+ // Otherwise, it might be advanced automatically if dispatching the call had a side effect
+ // of destroying the current HTMLImageElementImpl, and then we would advance past the *next*
+ // item, missing one altogether.
+ ++it;
+ image->dispatchLoadEvent();
+ }
+ m_imageLoadEventDispatchingList.clear();
+}
+
+void DocumentImpl::timerEvent(TQTimerEvent *)
+{
+ dispatchImageLoadEventsNow();
+}
+
+void DocumentImpl::setDecoderCodec(const TQTextCodec *codec)
+{
+ m_decoderMibEnum = codec->mibEnum();
+}
+
+ElementImpl *DocumentImpl::ownerElement() const
+{
+ KHTMLPart *childPart = part();
+ if (!childPart)
+ return 0;
+ ChildFrame *childFrame = childPart->d->m_frame;
+ if (!childFrame)
+ return 0;
+ RenderPart *renderPart = childFrame->m_frame;
+ if (!renderPart)
+ return 0;
+ return static_cast<ElementImpl *>(renderPart->element());
+}
+
+DOMString DocumentImpl::domain() const
+{
+ if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and space)
+ m_domain = URL().host(); // Initially set to the host
+ return m_domain;
+}
+
+void DocumentImpl::setDomain(const DOMString &newDomain)
+{
+ if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and space)
+ m_domain = URL().host().lower(); // Initially set to the host
+
+ if ( m_domain.isEmpty() /*&& part() && part()->openedByJS()*/ )
+ m_domain = newDomain.lower();
+
+ // Both NS and IE specify that changing the domain is only allowed when
+ // the new domain is a suffix of the old domain.
+ int oldLength = m_domain.length();
+ int newLength = newDomain.length();
+ if ( newLength < oldLength ) // e.g. newDomain=kde.org (7) and m_domain=www.kde.org (11)
+ {
+ DOMString test = m_domain.copy();
+ DOMString reference = newDomain.lower();
+ if ( test[oldLength - newLength - 1] == '.' ) // Check that it's a subdomain, not e.g. "de.org"
+ {
+ test.remove( 0, oldLength - newLength ); // now test is "kde.org" from m_domain
+ if ( test == reference ) // and we check that it's the same thing as newDomain
+ m_domain = reference;
+ }
+ }
+}
+
+DOMString DocumentImpl::toString() const
+{
+ DOMString result;
+
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ result += child->toString();
+ }
+
+ return result;
+}
+
+
+KHTMLPart* DOM::DocumentImpl::part() const
+{
+ // ### TODO: make this independent from a KHTMLView one day.
+ return view() ? view()->part() : 0;
+}
+
+NodeListImpl::Cache* DOM::DocumentImpl::acquireCachedNodeListInfo(
+ NodeListImpl::CacheFactory* factory, NodeImpl* base, int type)
+{
+ //### might want to flush the dict when the version number
+ //changes
+ NodeListImpl::CacheKey key(base, type);
+
+ //Check to see if we have this sort of item cached.
+ NodeListImpl::Cache* cached =
+ (type == NodeListImpl::UNCACHEABLE) ? 0 : m_nodeListCache.find(key.hash());
+
+ if (cached) {
+ if (cached->key == key) {
+ cached->ref(); //Add the nodelist's reference
+ return cached;
+ } else {
+ //Conflict. Drop our reference to the old item.
+ cached->deref();
+ }
+ }
+
+ //Nothing to reuse, make a new item.
+ NodeListImpl::Cache* newInfo = factory();
+ newInfo->key = key;
+ newInfo->clear(this);
+ newInfo->ref(); //Add the nodelist's reference
+
+ if (type != NodeListImpl::UNCACHEABLE) {
+ newInfo->ref(); //Add the cache's reference
+ m_nodeListCache.replace(key.hash(), newInfo);
+ }
+
+ return newInfo;
+}
+
+void DOM::DocumentImpl::releaseCachedNodeListInfo(NodeListImpl::Cache* entry)
+{
+ entry->deref();
+}
+
+// ----------------------------------------------------------------------------
+
+DocumentFragmentImpl::DocumentFragmentImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
+{
+}
+
+DocumentFragmentImpl::DocumentFragmentImpl(const DocumentFragmentImpl &other)
+ : NodeBaseImpl(other)
+{
+}
+
+DOMString DocumentFragmentImpl::nodeName() const
+{
+ return "#document-fragment";
+}
+
+unsigned short DocumentFragmentImpl::nodeType() const
+{
+ return Node::DOCUMENT_FRAGMENT_NODE;
+}
+
+// DOM Section 1.1.1
+bool DocumentFragmentImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::ELEMENT_NODE:
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ case Node::COMMENT_NODE:
+ case Node::TEXT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+DOMString DocumentFragmentImpl::toString() const
+{
+ DOMString result;
+
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ result += child->toString();
+ }
+
+ return result;
+}
+
+NodeImpl *DocumentFragmentImpl::cloneNode ( bool deep )
+{
+ DocumentFragmentImpl *clone = new DocumentFragmentImpl( docPtr() );
+ if (deep)
+ cloneChildNodes(clone);
+ return clone;
+}
+
+
+// ----------------------------------------------------------------------------
+
+DocumentTypeImpl::DocumentTypeImpl(DOMImplementationImpl *implementation, DocumentImpl *doc,
+ const DOMString &qualifiedName, const DOMString &publicId,
+ const DOMString &systemId)
+ : NodeImpl(doc), m_implementation(implementation),
+ m_qualifiedName(qualifiedName), m_publicId(publicId), m_systemId(systemId)
+{
+ m_implementation->ref();
+
+ m_entities = 0;
+ m_notations = 0;
+
+ // if doc is 0, it is not attached to a document and / or
+ // therefore does not provide entities or notations. (DOM Level 3)
+}
+
+DocumentTypeImpl::~DocumentTypeImpl()
+{
+ m_implementation->deref();
+ if (m_entities)
+ m_entities->deref();
+ if (m_notations)
+ m_notations->deref();
+}
+
+void DocumentTypeImpl::copyFrom(const DocumentTypeImpl& other)
+{
+ m_qualifiedName = other.m_qualifiedName;
+ m_publicId = other.m_publicId;
+ m_systemId = other.m_systemId;
+ m_subset = other.m_subset;
+}
+
+DOMString DocumentTypeImpl::toString() const
+{
+ DOMString result = "<!DOCTYPE";
+ result += m_qualifiedName;
+ if (!m_publicId.isEmpty()) {
+ result += " PUBLIC \"";
+ result += m_publicId;
+ result += "\" \"";
+ result += m_systemId;
+ result += "\"";
+ } else if (!m_systemId.isEmpty()) {
+ result += " SYSTEM \"";
+ result += m_systemId;
+ result += "\"";
+ }
+
+ if (!m_subset.isEmpty()) {
+ result += " [";
+ result += m_subset;
+ result += "]";
+ }
+
+ result += ">";
+
+ return result;
+}
+
+DOMString DocumentTypeImpl::nodeName() const
+{
+ return name();
+}
+
+unsigned short DocumentTypeImpl::nodeType() const
+{
+ return Node::DOCUMENT_TYPE_NODE;
+}
+
+// DOM Section 1.1.1
+bool DocumentTypeImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+NodeImpl *DocumentTypeImpl::cloneNode ( bool /*deep*/ )
+{
+ // Spec says cloning Document nodes is "implementation dependent"
+ // so we do not support it...
+ return 0;
+}
+
+DOMStringImpl* DocumentTypeImpl::textContent() const
+{
+ return 0;
+}
+
+void DocumentTypeImpl::setTextContent( const DOMString&, int& )
+{}
+
+NamedNodeMapImpl * DocumentTypeImpl::entities() const
+{
+ if ( !m_entities ) {
+ m_entities = new GenericRONamedNodeMapImpl( docPtr() );
+ m_entities->ref();
+ }
+ return m_entities;
+}
+
+NamedNodeMapImpl * DocumentTypeImpl::notations() const
+{
+ if ( !m_notations ) {
+ m_notations = new GenericRONamedNodeMapImpl( docPtr() );
+ m_notations->ref();
+ }
+ return m_notations;
+}
+
+#include "dom_docimpl.moc"
diff --git a/tdehtml/xml/dom_docimpl.h b/tdehtml/xml/dom_docimpl.h
new file mode 100644
index 000000000..18b164643
--- /dev/null
+++ b/tdehtml/xml/dom_docimpl.h
@@ -0,0 +1,763 @@
+/*
+ * 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.
+ * (C) 2006 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.
+ *
+ */
+
+#ifndef _DOM_DocumentImpl_h_
+#define _DOM_DocumentImpl_h_
+
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_traversalimpl.h"
+#include "misc/shared.h"
+#include "misc/loader.h"
+#include "misc/seed.h"
+
+#include <tqstringlist.h>
+#include <tqptrlist.h>
+#include <tqobject.h>
+#include <tqintcache.h>
+#include <tqintdict.h>
+#include <tqdict.h>
+#include <tqmap.h>
+
+#include <kurl.h>
+
+class TQPaintDevice;
+class TQTextCodec;
+class TQPaintDeviceMetrics;
+class KHTMLView;
+
+namespace tdehtml {
+ class Tokenizer;
+ class CSSStyleSelector;
+ class DocLoader;
+ class CSSStyleSelectorList;
+ class RenderArena;
+ class RenderObject;
+ class CounterNode;
+ class CachedObject;
+ class CachedCSSStyleSheet;
+ class DynamicDomRestyler;
+}
+
+namespace DOM {
+
+ class AbstractViewImpl;
+ class AttrImpl;
+ class CDATASectionImpl;
+ class CSSStyleSheetImpl;
+ class CommentImpl;
+ class DocumentFragmentImpl;
+ class DocumentImpl;
+ class DocumentType;
+ class DocumentTypeImpl;
+ class ElementImpl;
+ class EntityReferenceImpl;
+ class EventImpl;
+ class EventListener;
+ class GenericRONamedNodeMapImpl;
+ class HTMLDocumentImpl;
+ class HTMLElementImpl;
+ class HTMLImageElementImpl;
+ class NodeFilter;
+ class NodeFilterImpl;
+ class NodeIteratorImpl;
+ class NodeListImpl;
+ class ProcessingInstructionImpl;
+ class RangeImpl;
+ class RegisteredEventListener;
+ class StyleSheetImpl;
+ class StyleSheetListImpl;
+ class TextImpl;
+ class TreeWalkerImpl;
+
+class DOMImplementationImpl : public tdehtml::Shared<DOMImplementationImpl>
+{
+public:
+ DOMImplementationImpl();
+ ~DOMImplementationImpl();
+
+ // DOM methods & attributes for DOMImplementation
+ bool hasFeature ( const DOMString &feature, const DOMString &version );
+ DocumentTypeImpl *createDocumentType( const DOMString &qualifiedName, const DOMString &publicId,
+ const DOMString &systemId, int &exceptioncode );
+ DocumentImpl *createDocument( const DOMString &namespaceURI, const DOMString &qualifiedName,
+ const DocumentType &doctype, int &exceptioncode );
+
+ DOMImplementationImpl* getInterface(const DOMString& feature) const;
+
+ // From the DOMImplementationCSS interface
+ CSSStyleSheetImpl *createCSSStyleSheet(DOMStringImpl *title, DOMStringImpl *media, int &exceptioncode);
+
+ // From the HTMLDOMImplementation interface
+ HTMLDocumentImpl* createHTMLDocument( const DOMString& title);
+
+ // Other methods (not part of DOM)
+ DocumentImpl *createDocument( KHTMLView *v = 0 );
+ HTMLDocumentImpl *createHTMLDocument( KHTMLView *v = 0 );
+
+ // Returns the static instance of this class - only one instance of this class should
+ // ever be present, and is used as a factory method for creating DocumentImpl objects
+ static DOMImplementationImpl *instance();
+
+protected:
+ static DOMImplementationImpl *m_instance;
+};
+
+/**
+ * @internal A cache of element name (or id) to pointer
+ * ### KDE4, QHash: better to store values here
+ */
+class ElementMappingCache
+{
+public:
+ /**
+ For each name, we hold a reference count, and a
+ pointer. If the item is in the table, which implies
+ reference count is > 1, the name is a valid key.
+ If the pointer is non-null, it points to the appropriate
+ mapping
+ */
+ struct ItemInfo
+ {
+ int ref;
+ ElementImpl* nd;
+ };
+
+ ElementMappingCache();
+
+ /**
+ Add a pointer as just one of candidates, not neccesserily the proper one
+ */
+ void add(const TQString& id, ElementImpl* nd);
+
+ /**
+ Set the pointer as the definite mapping; it must have already been added
+ */
+ void set(const TQString& id, ElementImpl* nd);
+
+ /**
+ Remove the item; it must have already been added.
+ */
+ void remove(const TQString& id, ElementImpl* nd);
+
+ /**
+ Returns true if the item exists
+ */
+ bool contains(const TQString& id);
+
+ /**
+ Returns the information for the given ID
+ */
+ ItemInfo* get(const TQString& id);
+private:
+ TQDict<ItemInfo> m_dict;
+};
+
+
+/**
+ * @internal
+ */
+class DocumentImpl : public TQObject, private tdehtml::CachedObjectClient, public NodeBaseImpl
+{
+ Q_OBJECT
+public:
+ DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v);
+ ~DocumentImpl();
+
+ // DOM methods & attributes for Document
+
+ DocumentTypeImpl *doctype() const;
+
+ DOMImplementationImpl *implementation() const;
+ ElementImpl *documentElement() const;
+ virtual ElementImpl *createElement ( const DOMString &tagName, int* pExceptioncode = 0 );
+ virtual AttrImpl *createAttribute( const DOMString &tagName, int* pExceptioncode = 0 );
+ DocumentFragmentImpl *createDocumentFragment ();
+ TextImpl *createTextNode ( DOMStringImpl* data ) { return new TextImpl( docPtr(), data); }
+ TextImpl *createTextNode ( const TQString& data )
+ { return createTextNode(new DOMStringImpl(data.unicode(), data.length())); }
+ CommentImpl *createComment ( DOMStringImpl* data );
+ CDATASectionImpl *createCDATASection ( DOMStringImpl* data );
+ ProcessingInstructionImpl *createProcessingInstruction ( const DOMString &target, DOMStringImpl* data );
+ EntityReferenceImpl *createEntityReference ( const DOMString &name );
+ NodeImpl *importNode( NodeImpl *importedNode, bool deep, int &exceptioncode );
+ virtual ElementImpl *createElementNS ( const DOMString &_namespaceURI, const DOMString &_qualifiedName,
+ int* pExceptioncode = 0 );
+ virtual AttrImpl *createAttributeNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName,
+ int* pExceptioncode = 0 );
+ ElementImpl *getElementById ( const DOMString &elementId ) const;
+
+ // Actually part of HTMLDocument, but used for giving XML documents a window title as well
+ DOMString title() const { return m_title; }
+ void setTitle(const DOMString& _title);
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+
+ virtual DOMStringImpl* textContent() const;
+ virtual void setTextContent( const DOMString &text, int& exceptioncode );
+
+ // Other methods (not part of DOM)
+ virtual bool isDocumentNode() const { return true; }
+ virtual bool isHTMLDocument() const { return false; }
+
+ virtual ElementImpl *createHTMLElement ( const DOMString &tagName );
+
+ tdehtml::CSSStyleSelector *styleSelector() { return m_styleSelector; }
+
+ /**
+ * Updates the pending sheet count and then calls updateStyleSelector.
+ */
+ void styleSheetLoaded();
+
+ /**
+ * This method returns true if all top-level stylesheets have loaded (including
+ * any \@imports that they may be loading).
+ */
+ bool haveStylesheetsLoaded() { return m_pendingStylesheets <= 0 || m_ignorePendingStylesheets; }
+
+ /**
+ * Increments the number of pending sheets. The \<link\> elements
+ * invoke this to add themselves to the loading list.
+ */
+ void addPendingSheet() { m_pendingStylesheets++; }
+
+ /**
+ * Returns true if the document has pending stylesheets
+ * loading.
+ */
+ bool hasPendingSheets() const { return m_pendingStylesheets; }
+
+ /**
+ * Called when one or more stylesheets in the document may have been added, removed or changed.
+ *
+ * Creates a new style selector and assign it to this document. This is done by iterating through all nodes in
+ * document (or those before \<BODY\> in a HTML document), searching for stylesheets. Stylesheets can be contained in
+ * \<LINK\>, \<STYLE\> or \<BODY\> elements, as well as processing instructions (XML documents only). A list is
+ * constructed from these which is used to create the a new style selector which collates all of the stylesheets
+ * found and is used to calculate the derived styles for all rendering objects.
+ *
+ * @param shallow If the stylesheet list for the document is unchanged, with only added or removed rules
+ * in existing sheets, then set this argument to true for efficiency.
+ */
+ void updateStyleSelector(bool shallow=false);
+
+ void recalcStyleSelector();
+ void rebuildStyleSelector();
+
+ TQString nextState();
+
+ // Query all registered elements for their state
+ TQStringList docState();
+ bool unsubmittedFormChanges();
+ void registerMaintainsState(NodeImpl* e) { m_maintainsState.append(e); }
+ void deregisterMaintainsState(NodeImpl* e) { m_maintainsState.removeRef(e); }
+
+ // Set the state the document should restore to
+ void setRestoreState( const TQStringList &s) { m_state = s; }
+
+ KHTMLView *view() const { return m_view; }
+ KHTMLPart* part() const;
+
+ RangeImpl *createRange();
+
+ NodeIteratorImpl *createNodeIterator(NodeImpl *root, unsigned long whatToShow,
+ NodeFilter &filter, bool entityReferenceExpansion, int &exceptioncode);
+
+ TreeWalkerImpl *createTreeWalker(NodeImpl *root, unsigned long whatToShow, NodeFilterImpl *filter,
+ bool entityReferenceExpansion, int &exceptioncode);
+
+ virtual void recalcStyle( StyleChange = NoChange );
+ static TQPtrList<DocumentImpl> * changedDocuments;
+ virtual void updateRendering();
+ void updateLayout();
+ static void updateDocumentsRendering();
+ tdehtml::DocLoader *docLoader() { return m_docLoader; }
+
+ virtual void attach();
+ virtual void detach();
+
+ tdehtml::RenderArena* renderArena() { return m_renderArena.get(); }
+
+ // to get visually ordered hebrew and arabic pages right
+ void setVisuallyOrdered();
+ // to get URL decoding right
+ void setDecoderCodec(const TQTextCodec *codec);
+
+ void setSelection(NodeImpl* s, int sp, NodeImpl* e, int ep);
+ void clearSelection();
+
+ void open ( bool clearEventListeners = true );
+ virtual void close ( );
+ void write ( const DOMString &text );
+ void write ( const TQString &text );
+ void writeln ( const DOMString &text );
+ void finishParsing ( );
+
+ KURL URL() const { return m_url; }
+ void setURL(const TQString& url) { m_url = url; }
+
+ KURL baseURL() const { return m_baseURL.isEmpty() ? m_url : m_baseURL; }
+ void setBaseURL(const KURL& baseURL) { m_baseURL = baseURL; }
+
+ TQString baseTarget() const { return m_baseTarget; }
+ void setBaseTarget(const TQString& baseTarget) { m_baseTarget = baseTarget; }
+
+ TQString completeURL(const TQString& url) const { return KURL(baseURL(),url,m_decoderMibEnum).url(); };
+ DOMString canonURL(const DOMString& url) const { return url.isEmpty() ? url : completeURL(url.string()); }
+
+ void setUserStyleSheet(const TQString& sheet);
+ TQString userStyleSheet() const { return m_usersheet; }
+ void setPrintStyleSheet(const TQString& sheet) { m_printSheet = sheet; }
+ TQString printStyleSheet() const { return m_printSheet; }
+
+ CSSStyleSheetImpl* elementSheet();
+ virtual tdehtml::Tokenizer *createTokenizer();
+ tdehtml::Tokenizer *tokenizer() { return m_tokenizer; }
+
+ TQPaintDeviceMetrics *paintDeviceMetrics() { return m_paintDeviceMetrics; }
+ TQPaintDevice *paintDevice() const { return m_paintDevice; }
+ void setPaintDevice( TQPaintDevice *dev );
+
+ enum HTMLMode {
+ Html3 = 0,
+ Html4 = 1,
+ XHtml = 2
+ };
+
+ enum ParseMode {
+ Unknown,
+ Compat,
+ Transitional,
+ Strict
+ };
+ virtual void determineParseMode( const TQString &str );
+ void setParseMode( ParseMode m ) { pMode = m; }
+ ParseMode parseMode() const { return pMode; }
+
+ bool inCompatMode() const { return pMode == Compat; }
+ bool inTransitionalMode() const { return pMode == Transitional; }
+ bool inStrictMode() const { return pMode == Strict; }
+
+ //void setHTMLMode( HTMLMode m ) { hMode = m; }
+ HTMLMode htmlMode() const { return hMode; }
+
+ void setParsing(bool b) { m_bParsing = b; }
+ bool parsing() const { return m_bParsing; }
+
+ void setTextColor( TQColor color ) { m_textColor = color; }
+ TQColor textColor() const { return m_textColor; }
+
+ void setDesignMode(bool b);
+ bool designMode() const;
+
+ // internal
+ bool prepareMouseEvent( bool readonly, int x, int y, MouseEvent *ev );
+
+ virtual bool childTypeAllowed( unsigned short nodeType );
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ NodeImpl::Id getId( NodeImpl::IdType _type, DOMStringImpl* _nsURI, DOMStringImpl *_localName,
+ DOMStringImpl *_prefix, bool readonly, bool lookupHTML, int *pExceptioncode = 0);
+ NodeImpl::Id getId( NodeImpl::IdType _type, DOMStringImpl *_nodeName, bool readonly, bool lookupHTML,
+ int *pExceptioncode = 0);
+ DOMString getName( NodeImpl::IdType _type, NodeImpl::Id _id ) const;
+
+ StyleSheetListImpl* styleSheets() { return m_styleSheets; };
+
+ DOMString preferredStylesheetSet() const { return m_preferredStylesheetSet; }
+ DOMString selectedStylesheetSet() const;
+ void setSelectedStylesheetSet(const DOMString&);
+ void setPreferredStylesheetSet(const DOMString& s) { m_preferredStylesheetSet = s; }
+
+ void addStyleSheet(StyleSheetImpl *, int *exceptioncode = 0);
+ void removeStyleSheet(StyleSheetImpl *, int *exceptioncode = 0);
+
+ TQStringList availableStyleSheets() const { return m_availableSheets; }
+
+ NodeImpl* hoverNode() const { return m_hoverNode; }
+ void setHoverNode(NodeImpl *newHoverNode);
+ NodeImpl *focusNode() const { return m_focusNode; }
+ void setFocusNode(NodeImpl *newFocusNode);
+ NodeImpl* activeNode() const { return m_activeNode; }
+ void setActiveNode(NodeImpl *newActiveNode);
+
+ // Updates for :target (CSS3 selector).
+ void setCSSTarget(NodeImpl* n);
+ NodeImpl* getCSSTarget() { return m_cssTarget; }
+
+ bool isDocumentChanged() { return m_docChanged; }
+ virtual void setDocumentChanged(bool = true);
+ void attachNodeIterator(NodeIteratorImpl *ni);
+ void detachNodeIterator(NodeIteratorImpl *ni);
+ void notifyBeforeNodeRemoval(NodeImpl *n);
+ AbstractViewImpl *defaultView() const { return m_defaultView; }
+ EventImpl *createEvent(const DOMString &eventType, int &exceptioncode);
+
+ // keep track of what types of event listeners are registered, so we don't
+ // dispatch events unnecessarily
+ enum ListenerType {
+ DOMSUBTREEMODIFIED_LISTENER = 0x01,
+ DOMNODEINSERTED_LISTENER = 0x02,
+ DOMNODEREMOVED_LISTENER = 0x04,
+ DOMNODEREMOVEDFROMDOCUMENT_LISTENER = 0x08,
+ DOMNODEINSERTEDINTODOCUMENT_LISTENER = 0x10,
+ DOMATTRMODIFIED_LISTENER = 0x20,
+ DOMCHARACTERDATAMODIFIED_LISTENER = 0x40
+ };
+
+ bool hasListenerType(ListenerType listenerType) const { return (m_listenerTypes & listenerType); }
+ void addListenerType(ListenerType listenerType) { m_listenerTypes = m_listenerTypes | listenerType; }
+
+ CSSStyleDeclarationImpl *getOverrideStyle(ElementImpl *elt, DOMStringImpl *pseudoElt);
+
+ bool async() const { return m_async; }
+ void setAsync(bool b) { m_async = b; }
+ void abort();
+ void load(const DOMString &uri);
+ void loadXML(const DOMString &source);
+ // from cachedObjectClient
+ void setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset);
+ void error(int err, const TQString &text);
+
+ typedef TQMap<TQString, ProcessingInstructionImpl*> LocalStyleRefs;
+ LocalStyleRefs* localStyleRefs() { return &m_localStyleRefs; }
+
+ virtual void defaultEventHandler(EventImpl *evt);
+ virtual void setHTMLWindowEventListener(int id, EventListener *listener);
+ EventListener *getHTMLWindowEventListener(int id);
+ EventListener *createHTMLEventListener(const TQString& code, const TQString& name, NodeImpl* node);
+
+ void addWindowEventListener(int id, EventListener *listener, const bool useCapture);
+ void removeWindowEventListener(int id, EventListener *listener, bool useCapture);
+ bool hasWindowEventListener(int id);
+
+ EventListener *createHTMLEventListener(TQString code);
+
+ /**
+ * Searches through the document, starting from fromNode, for the next selectable element that comes after fromNode.
+ * The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab indexes
+ * first (from lowest to highest), and then elements without tab indexes (in document order).
+ *
+ * @param fromNode The node from which to start searching. The node after this will be focused. May be null.
+ *
+ * @return The focus node that comes after fromNode
+ *
+ * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
+ */
+ NodeImpl *nextFocusNode(NodeImpl *fromNode);
+
+ /**
+ * Searches through the document, starting from fromNode, for the previous selectable element (that comes _before_)
+ * fromNode. The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab
+ * indexes first (from lowest to highest), and then elements without tab indexes (in document order).
+ *
+ * @param fromNode The node from which to start searching. The node before this will be focused. May be null.
+ *
+ * @return The focus node that comes before fromNode
+ *
+ * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
+ */
+ NodeImpl *previousFocusNode(NodeImpl *fromNode);
+
+ ElementImpl* findAccessKeyElement(TQChar c);
+
+ int nodeAbsIndex(NodeImpl *node);
+ NodeImpl *nodeWithAbsIndex(int absIndex);
+
+ /**
+ * Handles a HTTP header equivalent set by a meta tag using <meta http-equiv="..." content="...">. This is called
+ * when a meta tag is encountered during document parsing, and also when a script dynamically changes or adds a meta
+ * tag. This enables scripts to use meta tags to perform refreshes and set expiry dates in addition to them being
+ * specified in a HTML file.
+ *
+ * @param equiv The http header name (value of the meta tag's "equiv" attribute)
+ * @param content The header value (value of the meta tag's "content" attribute)
+ */
+ void processHttpEquiv(const DOMString &equiv, const DOMString &content);
+
+ void dispatchImageLoadEventSoon(HTMLImageElementImpl *);
+ void dispatchImageLoadEventsNow();
+ void removeImage(HTMLImageElementImpl *);
+ virtual void timerEvent(TQTimerEvent *);
+
+ // Returns the owning element in the parent document.
+ // Returns 0 if this is the top level document.
+ ElementImpl *ownerElement() const;
+
+ DOMString domain() const;
+ void setDomain( const DOMString &newDomain ); // not part of the DOM
+
+ bool isURLAllowed(const TQString& url) const;
+
+ HTMLElementImpl* body();
+
+ DOMString toString() const;
+
+ void incDOMTreeVersion() { ++m_domtree_version; }
+ unsigned int domTreeVersion() const { return m_domtree_version; }
+
+ TQDict<tdehtml::CounterNode>* counters(const tdehtml::RenderObject* o) { return m_counterDict[(void*)o]; }
+ void setCounters(const tdehtml::RenderObject* o, TQDict<tdehtml::CounterNode> *dict) { m_counterDict.insert((void*)o, dict);}
+ void removeCounters(const tdehtml::RenderObject* o) { m_counterDict.remove((void*)o); }
+
+
+ ElementMappingCache& underDocNamedCache() {
+ return m_underDocNamedCache;
+ }
+
+ NodeListImpl::Cache* acquireCachedNodeListInfo(NodeListImpl::CacheFactory* fact,
+ NodeImpl* base, int type);
+ void releaseCachedNodeListInfo(NodeListImpl::Cache* cache);
+
+ ElementMappingCache& getElementByIdCache() const {
+ return m_getElementByIdCache;
+ }
+
+ TQString contentLanguage() const { return m_contentLanguage; }
+ void setContentLanguage(const TQString& cl) { m_contentLanguage = cl; }
+
+ tdehtml::DynamicDomRestyler& dynamicDomRestyler() { return *m_dynamicDomRestyler; }
+ const tdehtml::DynamicDomRestyler& dynamicDomRestyler() const { return *m_dynamicDomRestyler; }
+
+signals:
+ void finishedParsing();
+
+protected:
+ tdehtml::CSSStyleSelector *m_styleSelector;
+ KHTMLView *m_view;
+ TQStringList m_state;
+
+ tdehtml::DocLoader *m_docLoader;
+ tdehtml::Tokenizer *m_tokenizer;
+ KURL m_url;
+ KURL m_baseURL;
+ TQString m_baseTarget;
+
+ DocumentTypeImpl *m_doctype;
+ DOMImplementationImpl *m_implementation;
+
+ TQString m_usersheet;
+ TQString m_printSheet;
+ TQStringList m_availableSheets;
+
+ TQString m_contentLanguage;
+
+ // Track the number of currently loading top-level stylesheets. Sheets
+ // loaded using the @import directive are not included in this count.
+ // We use this count of pending sheets to detect when we can begin attaching
+ // elements.
+ int m_pendingStylesheets;
+ bool m_ignorePendingStylesheets;
+
+ CSSStyleSheetImpl *m_elemSheet;
+
+ TQPaintDevice *m_paintDevice;
+ TQPaintDeviceMetrics *m_paintDeviceMetrics;
+ ParseMode pMode;
+ HTMLMode hMode;
+
+ TQColor m_textColor;
+ NodeImpl *m_hoverNode;
+ NodeImpl *m_focusNode;
+ NodeImpl *m_activeNode;
+ NodeImpl *m_cssTarget;
+
+ unsigned int m_domtree_version;
+
+ struct IdNameMapping {
+ IdNameMapping(unsigned short _start)
+ : idStart(_start), count(0) {}
+ ~IdNameMapping() {
+ TQIntDictIterator<DOM::DOMStringImpl> it(names);
+ for (; it.current() ; ++it)
+ it.current()->deref();
+ }
+ unsigned short idStart;
+ unsigned short count;
+ TQIntDict<DOM::DOMStringImpl> names;
+ TQDict<void> ids;
+
+ void expandIfNeeded() {
+ if (ids.size() <= ids.count() && ids.size() != tdehtml_MaxSeed)
+ ids.resize( tdehtml::nextSeed(ids.count()) );
+ if (names.size() <= names.count() && names.size() != tdehtml_MaxSeed)
+ names.resize( tdehtml::nextSeed(names.count()) );
+ }
+
+ void addAlias(DOMStringImpl* _prefix, DOMStringImpl* _name, bool cs, NodeImpl::Id id) {
+ if(_prefix && _prefix->l) {
+ TQConstString n(_name->s, _name->l);
+ TQConstString px( _prefix->s, _prefix->l );
+ TQString name = cs ? n.string() : n.string().upper();
+ TQString qn("aliases: " + (cs ? px.string() : px.string().upper()) + ":" + name);
+ if (!ids.find( qn )) {
+ ids.insert( qn, (void*)id );
+ }
+ }
+ expandIfNeeded();
+ }
+
+ };
+
+ IdNameMapping *m_attrMap;
+ IdNameMapping *m_elementMap;
+ IdNameMapping *m_namespaceMap;
+
+ TQPtrList<NodeIteratorImpl> m_nodeIterators;
+ AbstractViewImpl *m_defaultView;
+
+ unsigned short m_listenerTypes;
+ StyleSheetListImpl* m_styleSheets;
+ StyleSheetListImpl *m_addedStyleSheets; // programmatically added style sheets
+ LocalStyleRefs m_localStyleRefs; // references to inlined style elements
+ RegisteredListenerList m_windowEventListeners;
+ TQPtrList<NodeImpl> m_maintainsState;
+
+ // ### evaluate for placement in RenderStyle
+ TQPtrDict<TQDict<tdehtml::CounterNode> > m_counterDict;
+
+ tdehtml::DynamicDomRestyler *m_dynamicDomRestyler;
+
+ bool visuallyOrdered;
+ bool m_bParsing;
+ bool m_docChanged;
+ bool m_styleSelectorDirty;
+ bool m_inStyleRecalc;
+ bool m_async;
+ bool m_hadLoadError;
+ bool m_docLoading;
+ bool m_inSyncLoad;
+
+ DOMString m_title;
+ DOMString m_preferredStylesheetSet;
+ tdehtml::CachedCSSStyleSheet *m_loadingXMLDoc;
+
+ int m_decoderMibEnum;
+
+ //Forms, images, etc., must be quickly accessible via document.name.
+ ElementMappingCache m_underDocNamedCache;
+
+ //Cache for nodelists and collections.
+ TQIntDict<NodeListImpl::Cache> m_nodeListCache;
+
+ TQPtrList<HTMLImageElementImpl> m_imageLoadEventDispatchSoonList;
+ TQPtrList<HTMLImageElementImpl> m_imageLoadEventDispatchingList;
+ int m_imageLoadEventTimer;
+
+ //Cache for getElementById
+ mutable ElementMappingCache m_getElementByIdCache;
+
+ tdehtml::SharedPtr<tdehtml::RenderArena> m_renderArena;
+private:
+ mutable DOMString m_domain;
+ int m_selfOnlyRefCount;
+public:
+ // Nodes belonging to this document hold "self-only" references -
+ // these are enough to keep the document from being destroyed, but
+ // not enough to keep it from removing its children. This allows a
+ // node that outlives its document to still have a valid document
+ // pointer without introducing reference cycles
+
+ void selfOnlyRef() { ++m_selfOnlyRefCount; }
+ void selfOnlyDeref() {
+ --m_selfOnlyRefCount;
+ if (!m_selfOnlyRefCount && !refCount())
+ delete this;
+ }
+
+ // This is called when our last outside reference dies
+ virtual void removedLastRef();
+};
+
+class DocumentFragmentImpl : public NodeBaseImpl
+{
+public:
+ DocumentFragmentImpl(DocumentImpl *doc);
+ DocumentFragmentImpl(const DocumentFragmentImpl &other);
+
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+ virtual bool childTypeAllowed( unsigned short type );
+
+ virtual DOMString toString() const;
+};
+
+
+class DocumentTypeImpl : public NodeImpl
+{
+public:
+ DocumentTypeImpl(DOMImplementationImpl *_implementation, DocumentImpl *doc,
+ const DOMString &qualifiedName, const DOMString &publicId,
+ const DOMString &systemId);
+ ~DocumentTypeImpl();
+
+ // DOM methods & attributes for DocumentType
+ NamedNodeMapImpl *entities() const;
+ NamedNodeMapImpl *notations() const;
+
+ DOMString name() const { return m_qualifiedName; }
+ DOMString publicId() const { return m_publicId; }
+ DOMString systemId() const { return m_systemId; }
+ DOMString internalSubset() const { return m_subset; }
+
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual bool childTypeAllowed( unsigned short type );
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ virtual DOMStringImpl* textContent() const;
+ virtual void setTextContent( const DOMString &text, int& exceptioncode );
+
+ // Other methods (not part of DOM)
+ void setName(const DOMString& n) { m_qualifiedName = n; }
+ void setPublicId(const DOMString& publicId) { m_publicId = publicId; }
+ void setSystemId(const DOMString& systemId) { m_systemId = systemId; }
+ DOMImplementationImpl *implementation() const { return m_implementation; }
+ void copyFrom(const DocumentTypeImpl&);
+
+ virtual DOMString toString() const;
+
+protected:
+ DOMImplementationImpl *m_implementation;
+ mutable NamedNodeMapImpl* m_entities;
+ mutable NamedNodeMapImpl* m_notations;
+
+ DOMString m_qualifiedName;
+ DOMString m_publicId;
+ DOMString m_systemId;
+ DOMString m_subset;
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/xml/dom_elementimpl.cpp b/tdehtml/xml/dom_elementimpl.cpp
new file mode 100644
index 000000000..75ed41dfc
--- /dev/null
+++ b/tdehtml/xml/dom_elementimpl.cpp
@@ -0,0 +1,1301 @@
+/**
+ * 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 Peter Kelly (pmk@post.com)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2006 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 EVENT_DEBUG
+#include "dom/dom_exception.h"
+#include "dom/dom_node.h"
+#include "dom/html_image.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_restyler.h"
+
+#include "html/dtd.h"
+#include "html/htmlparser.h"
+#include "html/html_imageimpl.h"
+
+#include "rendering/render_canvas.h"
+#include "misc/htmlhashes.h"
+#include "css/css_valueimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/cssstyleselector.h"
+#include "css/cssvalues.h"
+#include "css/cssproperties.h"
+#include "xml/dom_xmlimpl.h"
+
+#include <tqtextstream.h>
+#include <kdebug.h>
+#include <stdlib.h>
+
+// ### support default attributes
+// ### dispatch mutation events
+// ### check for INVALID_CHARACTER_ERR where appropriate
+
+using namespace DOM;
+using namespace tdehtml;
+
+AttrImpl::AttrImpl(ElementImpl* element, DocumentImpl* docPtr, NodeImpl::Id attrId,
+ DOMStringImpl *value, DOMStringImpl *prefix)
+ : NodeBaseImpl(docPtr),
+ m_element(element),
+ m_attrId(attrId)
+{
+ m_value = value;
+ m_value->ref();
+
+ m_prefix = prefix;
+ if (m_prefix)
+ m_prefix->ref();
+ m_specified = true; // we don't yet support default attributes
+}
+
+AttrImpl::~AttrImpl()
+{
+ m_value->deref();
+ if (m_prefix)
+ m_prefix->deref();
+}
+
+DOMString AttrImpl::nodeName() const
+{
+ return name();
+}
+
+unsigned short AttrImpl::nodeType() const
+{
+ return Node::ATTRIBUTE_NODE;
+}
+
+DOMString AttrImpl::prefix() const
+{
+ return m_prefix;
+}
+
+void AttrImpl::setPrefix(const DOMString &_prefix, int &exceptioncode )
+{
+ checkSetPrefix(_prefix, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ if (m_prefix == _prefix.implementation())
+ return;
+
+ if (m_prefix)
+ m_prefix->deref();
+ m_prefix = _prefix.implementation();
+ if (m_prefix)
+ m_prefix->ref();
+}
+
+DOMString AttrImpl::namespaceURI() const
+{
+ if (m_htmlCompat)
+ return DOMString();
+ return getDocument()->getName(NamespaceId, m_attrId >> 16);
+}
+
+DOMString AttrImpl::localName() const
+{
+ if (m_htmlCompat)
+ return DOMString();
+ return getDocument()->getName(AttributeId, m_attrId);
+}
+
+DOMString AttrImpl::nodeValue() const
+{
+ return m_value;
+}
+
+DOMString AttrImpl::name() const
+{
+ DOMString n = getDocument()->getName(AttributeId, m_attrId);
+
+ // compat mode always return attribute names in lowercase.
+ // that's not formally in the specification, but common
+ // practice - a w3c erratum to DOM L2 is pending.
+ if (m_htmlCompat)
+ n = n.lower();
+
+ if (m_prefix && m_prefix->l)
+ return DOMString(m_prefix) + ":" + n;
+
+ return n;
+}
+
+void AttrImpl::setValue( const DOMString &v, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // ### according to the DOM docs, we should create an unparsed Text child
+ // node here
+ // do not interprete entities in the string, its literal!
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // ### what to do on 0 ?
+ if (v.isNull()) {
+ exceptioncode = DOMException::DOMSTRING_SIZE_ERR;
+ return;
+ }
+
+ if (m_value == v.implementation())
+ return;
+
+ if (m_element && m_attrId == ATTR_ID)
+ m_element->updateId(m_value, v.implementation());
+
+ m_value->deref();
+ m_value = v.implementation();
+ m_value->ref();
+
+ if (m_element) {
+ m_element->parseAttribute(m_attrId,m_value);
+ m_element->attributeChanged(m_attrId);
+ }
+}
+
+void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode )
+{
+ exceptioncode = 0;
+ // NO_MODIFICATION_ALLOWED_ERR: taken care of by setValue()
+ setValue(v, exceptioncode);
+}
+
+NodeImpl *AttrImpl::cloneNode ( bool /*deep*/)
+{
+ AttrImpl* attr = new AttrImpl(0, docPtr(), m_attrId, m_value, m_prefix);
+ attr->setHTMLCompat(m_htmlCompat);
+ return attr;
+}
+
+// DOM Section 1.1.1
+bool AttrImpl::childAllowed( NodeImpl *newChild )
+{
+ if(!newChild)
+ return false;
+
+ return childTypeAllowed(newChild->nodeType());
+}
+
+bool AttrImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::TEXT_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+DOMString AttrImpl::toString() const
+{
+ DOMString result;
+
+ result += nodeName();
+
+ // FIXME: substitute entities for any instances of " or ' --
+ // maybe easier to just use text value and ignore existing
+ // entity refs?
+
+ if ( firstChild() ) {
+ result += "=\"";
+
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ result += child->toString();
+ }
+
+ result += "\"";
+ } else if ( !nodeValue().isEmpty() ){
+ //remove the else once the AttributeImpl changes are merged
+ result += "=\"";
+ result += nodeValue();
+ result += "\"";
+ }
+
+ return result;
+}
+
+void AttrImpl::setElement(ElementImpl *element)
+{
+ m_element = element;
+}
+
+// Strictly speaking, these two methods should not be needed, but
+// we can't fully deal with the mess that are DOM attributes right..
+DOMStringImpl* AttrImpl::textContent() const
+{
+ if (m_value)
+ return new DOMStringImpl(m_value->s, m_value->l);
+ else
+ return 0;
+}
+
+void AttrImpl::setTextContent( const DOMString &text, int& exceptioncode )
+{
+ setValue(text, exceptioncode);
+}
+
+// -------------------------------------------------------------------------
+
+void AttributeImpl::setValue(DOMStringImpl *value, ElementImpl *element)
+{
+ assert(value);
+ if (m_attrId) {
+ if (m_data.value == value)
+ return;
+
+ if (element && m_attrId == ATTR_ID)
+ element->updateId(m_data.value, value);
+
+ m_data.value->deref();
+ m_data.value = value;
+ m_data.value->ref();
+
+ if (element) {
+ element->parseAttribute(this);
+ element->attributeChanged(m_attrId);
+ }
+ }
+ else {
+ int exceptioncode = 0;
+ m_data.attr->setValue(value,exceptioncode);
+ // AttrImpl::setValue() calls parseAttribute()
+ }
+}
+
+AttrImpl *AttributeImpl::createAttr(ElementImpl *element, DocumentImpl *docPtr)
+{
+ if (m_attrId) {
+ AttrImpl *attr = new AttrImpl(element,docPtr,m_attrId,m_data.value);
+ if (!attr) return 0;
+ attr->setHTMLCompat( docPtr->htmlMode() != DocumentImpl::XHtml );
+ m_data.value->deref();
+ m_data.attr = attr;
+ m_data.attr->ref();
+ m_attrId = 0; /* "has implementation" flag */
+ }
+
+ return m_data.attr;
+}
+
+void AttributeImpl::free()
+{
+ if (m_attrId) {
+ m_data.value->deref();
+ }
+ else {
+ m_data.attr->setElement(0);
+ m_data.attr->deref();
+ }
+}
+
+// -------------------------------------------------------------------------
+
+ElementImpl::ElementImpl(DocumentImpl *doc)
+ : NodeBaseImpl(doc)
+{
+ namedAttrMap = 0;
+ m_styleDecls = 0;
+ m_prefix = 0;
+}
+
+ElementImpl::~ElementImpl()
+{
+ if(namedAttrMap) {
+ namedAttrMap->detachFromElement();
+ namedAttrMap->deref();
+ }
+
+ if (m_styleDecls) {
+ m_styleDecls->setNode(0);
+ m_styleDecls->setParent(0);
+ m_styleDecls->deref();
+ }
+
+ if (m_prefix)
+ m_prefix->deref();
+}
+
+unsigned short ElementImpl::nodeType() const
+{
+ return Node::ELEMENT_NODE;
+}
+
+DOMStringImpl* ElementImpl::getAttributeImpl( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName) const
+{
+ if (!namedAttrMap)
+ return 0;
+
+ DOMStringImpl *value = namedAttrMap->getValue(id, nsAware, qName);
+ if (value)
+ return value;
+
+ // then search in default attr in case it is not yet set
+ NamedAttrMapImpl* dm = defaultMap();
+ value = dm ? dm->getValue(id, nsAware, qName) : 0;
+ if (value)
+ return value;
+
+ return 0;
+}
+
+DOMString ElementImpl::getAttribute( NodeImpl::Id id, bool nsAware, const DOMString& qName) const
+{
+ return DOMString(getAttributeImpl(id, nsAware, qName.implementation()));
+}
+
+void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value, const DOMString& qName, int &exceptioncode)
+{
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+ attributes()->setValue(id, value.implementation(), (qName.isEmpty() ? 0: qName.implementation()));
+}
+
+void ElementImpl::setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName,
+ const DOMString &value, int &exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+ int colonPos;
+ if (!DOM::checkQualifiedName(qualifiedName, namespaceURI, &colonPos,
+ false/*nameCanBeNull*/, false/*nameCanBeEmpty*/,
+ &exceptioncode))
+ return;
+ DOMString prefix, localName;
+ splitPrefixLocalName(qualifiedName.implementation(), prefix, localName, colonPos);
+ NodeImpl::Id id = getDocument()->getId(AttributeId, namespaceURI.implementation(),
+ prefix.implementation(), localName.implementation(), false, true /*lookupHTML*/);
+ attributes()->setValue(id, value.implementation(), 0, prefix.implementation(),
+ true /*nsAware*/, !namespaceURI.isNull() /*hasNS*/);
+}
+
+void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value)
+{
+ int exceptioncode = 0;
+ setAttribute(id,value,DOMString(),exceptioncode);
+}
+
+void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
+{
+ // If setting the whole map changes the id attribute, we need to
+ // call updateId.
+ DOMStringImpl *oldId = namedAttrMap ? namedAttrMap->getValue(ATTR_ID) : 0;
+ DOMStringImpl *newId = list ? list->getValue(ATTR_ID) : 0;
+
+ if (oldId || newId) {
+ updateId(oldId, newId);
+ }
+
+ if (namedAttrMap) {
+ namedAttrMap->detachFromElement();
+ namedAttrMap->deref();
+ }
+
+ namedAttrMap = list;
+
+ if (namedAttrMap) {
+ namedAttrMap->ref();
+ assert(namedAttrMap->m_element == 0);
+ namedAttrMap->setElement(this);
+ unsigned long len = namedAttrMap->length();
+ for (unsigned long i = 0; i < len; i++) {
+ parseAttribute(&namedAttrMap->m_attrs[i]);
+ attributeChanged(namedAttrMap->m_attrs[i].id());
+ }
+ }
+}
+
+NodeImpl *ElementImpl::cloneNode(bool deep)
+{
+ ElementImpl *clone;
+ if ( !localName().isNull() )
+ clone = getDocument()->createElementNS( namespaceURI(), nodeName() );
+ else
+ clone = getDocument()->createElement( nodeName() );
+ if (!clone) return 0;
+ finishCloneNode( clone, deep );
+ return clone;
+}
+
+void ElementImpl::finishCloneNode( ElementImpl* clone, bool deep )
+{
+ // clone attributes
+ if (namedAttrMap)
+ clone->attributes()->copyAttributes(namedAttrMap);
+
+ // clone individual style rules
+ if (m_styleDecls)
+ *(clone->styleRules()) = *m_styleDecls;
+
+ if (deep)
+ cloneChildNodes(clone);
+}
+
+DOMString ElementImpl::nodeName() const
+{
+ return tagName();
+}
+
+DOMString ElementImpl::namespaceURI() const
+{
+ if (m_htmlCompat)
+ return DOMString();
+ return getDocument()->getName(NamespaceId, id() >> 16);
+}
+
+DOMString ElementImpl::prefix() const
+{
+ return m_prefix;
+}
+
+void ElementImpl::setPrefix( const DOMString &_prefix, int &exceptioncode )
+{
+ checkSetPrefix(_prefix, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ if (m_prefix == _prefix.implementation())
+ return;
+
+ if (m_prefix)
+ m_prefix->deref();
+ m_prefix = _prefix.implementation();
+ if (m_prefix)
+ m_prefix->ref();
+}
+
+void ElementImpl::createAttributeMap() const
+{
+ namedAttrMap = new NamedAttrMapImpl(const_cast<ElementImpl*>(this));
+ namedAttrMap->ref();
+}
+
+NamedAttrMapImpl* ElementImpl::defaultMap() const
+{
+ return 0;
+}
+
+RenderStyle *ElementImpl::styleForRenderer(RenderObject * /*parentRenderer*/)
+{
+ return getDocument()->styleSelector()->styleForElement(this);
+}
+
+RenderObject *ElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
+{
+ if (getDocument()->documentElement() == this && style->display() == NONE) {
+ // Ignore display: none on root elements. Force a display of block in that case.
+ RenderBlock* result = new (arena) RenderBlock(this);
+ if (result) result->setStyle(style);
+ return result;
+ }
+ return RenderObject::createObject(this, style);
+}
+
+void ElementImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render);
+ assert(parentNode());
+
+#if SPEED_DEBUG < 1
+ createRendererIfNeeded();
+#endif
+
+ NodeBaseImpl::attach();
+}
+
+void ElementImpl::close()
+{
+ NodeImpl::close();
+
+ // Trigger all the addChild changes as one large dynamic appendChildren change
+ if (attached())
+ backwardsStructureChanged();
+}
+
+void ElementImpl::detach()
+{
+ getDocument()->dynamicDomRestyler().resetDependencies(this);
+
+ NodeBaseImpl::detach();
+}
+
+void ElementImpl::structureChanged()
+{
+ NodeBaseImpl::structureChanged();
+
+ if (!getDocument()->renderer())
+ return; // the document is about to be destroyed
+
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, StructuralDependency);
+ // In theory BackwardsStructurualDependencies are indifferent to prepend,
+ // but it's too rare to optimize.
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, BackwardsStructuralDependency);
+}
+
+void ElementImpl::backwardsStructureChanged()
+{
+ NodeBaseImpl::backwardsStructureChanged();
+
+ if (!getDocument()->renderer())
+ return; // the document is about to be destroyed
+
+ // Most selectors are not affected by append. Fire the few that are.
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, BackwardsStructuralDependency);
+}
+
+void ElementImpl::attributeChanged(NodeImpl::Id id)
+{
+ if (!getDocument()->renderer())
+ return; // the document is about to be destroyed
+
+#if 0 // one-one dependencies for attributes disabled
+ getDocument()->dynamicDomRestyler().restyleDepedent(this, AttributeDependency);
+#endif
+ if (getDocument()->dynamicDomRestyler().checkDependency(id, PersonalDependency))
+ setChanged(true);
+ if (getDocument()->dynamicDomRestyler().checkDependency(id, AncestorDependency))
+ setChangedAscendentAttribute(true);
+ if (getDocument()->dynamicDomRestyler().checkDependency(id, PredecessorDependency) && parent())
+ // Any element that dependt on a predecessors attribute, also depend structurally on parent
+ parent()->structureChanged();
+}
+
+void ElementImpl::recalcStyle( StyleChange change )
+{
+ // ### should go away and be done in renderobject
+ RenderStyle* _style = m_render ? m_render->style() : 0;
+ bool hasParentRenderer = parent() ? parent()->attached() : false;
+
+#if 0
+ const char* debug;
+ switch(change) {
+ case NoChange: debug = "NoChange";
+ break;
+ case NoInherit: debug= "NoInherit";
+ break;
+ case Inherit: debug = "Inherit";
+ break;
+ case Force: debug = "Force";
+ break;
+ }
+ tqDebug("recalcStyle(%d: %s, changed: %d)[%p: %s]", change, debug, changed(), this, tagName().string().latin1());
+#endif
+ if ( hasParentRenderer && (change >= Inherit || changed()) ) {
+ RenderStyle *newStyle = getDocument()->styleSelector()->styleForElement(this);
+ newStyle->ref();
+ StyleChange ch = diff( _style, newStyle );
+ if (ch == Detach) {
+ if (attached()) detach();
+ // ### Suboptimal. Style gets calculated again.
+ attach();
+ // attach recalulates the style for all children. No need to do it twice.
+ setChanged( false );
+ setHasChangedChild( false );
+ newStyle->deref();
+ return;
+ }
+ else if (ch != NoChange) {
+ if( m_render && newStyle ) {
+ m_render->setStyle(newStyle);
+ }
+ }
+ newStyle->deref();
+
+ if ( change != Force)
+ change = ch;
+ }
+ // If a changed attribute has ancestor dependencies, restyle all children
+ if (changedAscendentAttribute()) {
+ change = Force;
+ setChangedAscendentAttribute(false);
+ }
+
+ NodeImpl *n;
+ for (n = _first; n; n = n->nextSibling()) {
+ if ( change >= Inherit || n->isTextNode() ||
+ n->hasChangedChild() || n->changed() ) {
+ //tqDebug(" (%p) calling recalcStyle on child %p/%s, change=%d", this, n, n->isElementNode() ? ((ElementImpl *)n)->tagName().string().latin1() : n->isTextNode() ? "text" : "unknown", change );
+ n->recalcStyle( change );
+ }
+ }
+
+ setChanged( false );
+ setHasChangedChild( false );
+}
+
+bool ElementImpl::isFocusable() const
+{
+ // Only make editable elements selectable if its parent element
+ // is not editable. FIXME: this is not 100% right as non-editable elements
+ // within editable elements are focusable too.
+ return contentEditable() && !(parentNode() && parentNode()->contentEditable());
+}
+
+// DOM Section 1.1.1
+bool ElementImpl::childAllowed( NodeImpl *newChild )
+{
+ if (!childTypeAllowed(newChild->nodeType()))
+ return false;
+
+ // ### check xml element allowedness according to DTD
+
+ // If either this node or the other node is an XML element node, allow regardless (we don't do DTD checks for XML
+ // yet)
+ if (isXMLElementNode() || newChild->isXMLElementNode())
+ return true;
+ else
+ return checkChild(id(), newChild->id(), !getDocument()->inCompatMode());
+}
+
+bool ElementImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::ELEMENT_NODE:
+ case Node::TEXT_NODE:
+ case Node::COMMENT_NODE:
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+void ElementImpl::scrollIntoView(bool /*alignToTop*/)
+{
+ // ###
+ kdWarning() << "non-standard scrollIntoView() not implemented" << endl;
+}
+
+void ElementImpl::createDecl( )
+{
+ m_styleDecls = new CSSStyleDeclarationImpl(0);
+ m_styleDecls->ref();
+ m_styleDecls->setParent(getDocument()->elementSheet());
+ m_styleDecls->setNode(this);
+ m_styleDecls->setStrictParsing( !getDocument()->inCompatMode() );
+}
+
+void ElementImpl::dispatchAttrRemovalEvent(NodeImpl::Id /*id*/, DOMStringImpl * /*value*/)
+{
+ // ### enable this stuff again
+ if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
+ return;
+ //int exceptioncode = 0;
+ //dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
+ //attr->value(), getDocument()->attrName(attr->id()),MutationEvent::REMOVAL),exceptioncode);
+}
+
+void ElementImpl::dispatchAttrAdditionEvent(NodeImpl::Id /*id*/, DOMStringImpl * /*value*/)
+{
+ // ### enable this stuff again
+ if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
+ return;
+ //int exceptioncode = 0;
+ //dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
+ //attr->value(),getDocument()->attrName(attr->id()),MutationEvent::ADDITION),exceptioncode);
+}
+
+void ElementImpl::updateId(DOMStringImpl* oldId, DOMStringImpl* newId)
+{
+ if (!inDocument())
+ return;
+
+ if (oldId && oldId->l)
+ removeId(DOMString(oldId).string());
+
+ if (newId && newId->l)
+ addId(DOMString(newId).string());
+}
+
+void ElementImpl::removeId(const TQString& id)
+{
+ getDocument()->getElementByIdCache().remove(id, this);
+}
+
+void ElementImpl::addId(const TQString& id)
+{
+ getDocument()->getElementByIdCache().add(id, this);
+}
+
+void ElementImpl::insertedIntoDocument()
+{
+ // need to do superclass processing first so inDocument() is true
+ // by the time we reach updateId
+ NodeBaseImpl::insertedIntoDocument();
+
+ if (hasID()) {
+ DOMString id = getAttribute(ATTR_ID);
+ updateId(0, id.implementation());
+ }
+}
+
+void ElementImpl::removedFromDocument()
+{
+ if (hasID()) {
+ DOMString id = getAttribute(ATTR_ID);
+ updateId(id.implementation(), 0);
+ }
+
+ NodeBaseImpl::removedFromDocument();
+}
+
+DOMString ElementImpl::openTagStartToString(bool expandurls) const
+{
+ DOMString result = DOMString("<") + tagName();
+
+ NamedAttrMapImpl *attrMap = attributes(true);
+
+ if (attrMap) {
+ unsigned long numAttrs = attrMap->length();
+ for (unsigned long i = 0; i < numAttrs; i++) {
+ result += " ";
+
+ AttributeImpl *attribute = attrMap->attrAt(i);
+ AttrImpl *attr = attribute->attr();
+
+ if (attr) {
+ result += attr->toString();
+ } else {
+ result += getDocument()->getName( NodeImpl::AttributeId, attribute->id());
+ if (!attribute->value().isNull()) {
+ result += "=\"";
+ // FIXME: substitute entities for any instances of " or '
+ // Expand out all urls, i.e. the src and href attributes
+ if(expandurls && ( attribute->id() == ATTR_SRC || attribute->id() == ATTR_HREF))
+ if(getDocument()) {
+ //We need to sanitize the urls - strip out the passwords.
+ //FIXME: are src= and href= the only places that might have a password and need to be sanitized?
+ KURL safeURL(getDocument()->completeURL(attribute->value().string()));
+ safeURL.setPass(TQString::null);
+ result += safeURL.htmlURL();
+ }
+ else {
+ kdWarning() << "getDocument() returned false";
+ result += attribute->value();
+ }
+ else
+ result += attribute->value();
+ result += "\"";
+ }
+ }
+ }
+ }
+
+ return result;
+}
+DOMString ElementImpl::selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const
+{
+ DOMString result = openTagStartToString();
+
+ if (hasChildNodes()) {
+ result += ">";
+
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ result += child->selectionToString(selectionStart, selectionEnd, startOffset, endOffset, found); // this might set found to true
+ if(child == selectionEnd)
+ found = true;
+ if(found) break;
+ }
+
+ result += "</";
+ result += tagName();
+ result += ">";
+ } else {
+ result += " />";
+ }
+
+ return result;
+}
+
+DOMString ElementImpl::toString() const
+{
+ TQString result = openTagStartToString().string(); //Accumulate in TQString, since DOMString can't append well.
+
+ if (hasChildNodes()) {
+ result += ">";
+
+ for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+ DOMString kid = child->toString();
+ result += TQConstString(kid.unicode(), kid.length()).string();
+ }
+
+ result += "</";
+ result += tagName().string();
+ result += ">";
+ } else if (result.length() == 1) {
+ // ensure we dont get results like < /> can happen when serialize document
+ result = "";
+ } else {
+ result += " />";
+ }
+
+ return result;
+}
+
+bool ElementImpl::contentEditable() const {
+#if 0
+ DOM::CSSPrimitiveValueImpl *val = static_cast<DOM::CSSPrimitiveValueImpl *>
+ (const_cast<ElementImpl *>(this)->styleRules()
+ ->getPropertyCSSValue(CSS_PROP__KONQ_USER_INPUT));
+// kdDebug() << "val" << val << endl;
+ return val ? val->getIdent() == CSS_VAL_ENABLED : false;
+#endif
+ return NodeImpl::contentEditable();
+}
+
+void ElementImpl::setContentEditable(bool enabled) {
+ // FIXME: the approach is flawed, better use an enum instead of bool
+ int value;
+ if (enabled)
+ value = CSS_VAL_ENABLED;
+ else {
+ // Intelligently use "none" or "disabled", depending on the type of
+ // element
+ // FIXME: intelligence not impl'd yet
+ value = CSS_VAL_NONE;
+
+ // FIXME: reset caret if it is in this node or a child
+ }/*end if*/
+ // FIXME: use addCSSProperty when I get permission to move it here
+// kdDebug(6000) << "CSS_PROP__KHTML_USER_INPUT: "<< value << endl;
+ styleRules()->setProperty(CSS_PROP__KHTML_USER_INPUT, value, false, true);
+ setChanged();
+
+}
+
+// -------------------------------------------------------------------------
+
+XMLElementImpl::XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id)
+ : ElementImpl(doc)
+{
+ // Called from createElement(). In this case localName, prefix, and namespaceURI all need to be null.
+ m_id = id;
+}
+
+XMLElementImpl::XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id, DOMStringImpl *_prefix)
+ : ElementImpl(doc)
+{
+ // Called from createElementNS()
+ m_id = id;
+
+ m_prefix = _prefix;
+ if (m_prefix)
+ m_prefix->ref();
+}
+
+XMLElementImpl::~XMLElementImpl()
+{
+}
+
+DOMString XMLElementImpl::localName() const
+{
+ if ( m_htmlCompat )
+ return DOMString(); // was created with non-namespace-aware createElement()
+ return getDocument()->getName(ElementId, m_id);
+}
+
+DOMString XMLElementImpl::tagName() const
+{
+ DOMString tn = getDocument()->getName(ElementId, id());
+ if (m_htmlCompat)
+ tn = tn.upper();
+
+ if (m_prefix)
+ return DOMString(m_prefix) + ":" + tn;
+
+ return tn;
+}
+
+NodeImpl *XMLElementImpl::cloneNode ( bool deep )
+{
+ XMLElementImpl *clone = new XMLElementImpl(docPtr(), id(), m_prefix);
+ finishCloneNode( clone, deep );
+ return clone;
+}
+
+// -------------------------------------------------------------------------
+
+NamedAttrMapImpl::NamedAttrMapImpl(ElementImpl *element)
+ : m_element(element),
+ m_attrs(0),
+ m_attrCount(0)
+{
+}
+
+NamedAttrMapImpl::~NamedAttrMapImpl()
+{
+ for (unsigned long i = 0; i < m_attrCount; i++)
+ m_attrs[i].free();
+ free(m_attrs);
+}
+
+NodeImpl *NamedAttrMapImpl::getNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName ) const
+{
+ if (!m_element)
+ return 0;
+ unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
+ id = (id & mask);
+
+ for (unsigned long i = 0; i < m_attrCount; i++) {
+ if ((m_attrs[i].id() & mask) == id) {
+ // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
+ if (qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) &&
+ strcasecmp(m_attrs[i].name(), DOMString(qName)))
+ continue;
+ return m_attrs[i].createAttr(m_element,m_element->docPtr());
+ }
+ }
+
+ return 0;
+}
+
+Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode )
+{
+ if (!m_element) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+ }
+ unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
+ id = (id & mask);
+
+ for (unsigned long i = 0; i < m_attrCount; i++) {
+ if ((m_attrs[i].id() & mask) == id) {
+ // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
+ if (qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) &&
+ strcasecmp(m_attrs[i].name(), DOMString(qName)))
+ continue;
+ id = m_attrs[i].id();
+ if (id == ATTR_ID)
+ m_element->updateId(m_attrs[i].val(), 0);
+ Node removed(m_attrs[i].createAttr(m_element,m_element->docPtr()));
+ m_attrs[i].free();
+ memmove(m_attrs+i,m_attrs+i+1,(m_attrCount-i-1)*sizeof(AttributeImpl));
+ m_attrCount--;
+ m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
+ m_element->parseAttribute(id,0);
+ m_element->attributeChanged(id);
+ return removed;
+ }
+ }
+
+ // NOT_FOUND_ERR: Raised if there is no node with the specified namespaceURI
+ // and localName in this map.
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+}
+
+Node NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode )
+{
+ if (!m_element) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+ }
+
+ // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
+ if (arg->getDocument() != m_element->getDocument()) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return 0;
+ }
+
+ // HIERARCHY_REQUEST_ERR: Raised if an attempt is made to add a node doesn't belong in this NamedNodeMap
+ if (!arg->isAttributeNode()) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return 0;
+ }
+ AttrImpl *attr = static_cast<AttrImpl*>(arg);
+
+ // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
+ // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
+ if (attr->ownerElement() && attr->ownerElement() != m_element) {
+ exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
+ return 0;
+ }
+
+ if (attr->ownerElement() == m_element) {
+ // Already have this attribute.
+ // DOMTS core-1 test "hc_elementreplaceattributewithself" says we should return it.
+ return attr;
+ }
+ unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
+ NodeImpl::Id id = (attr->id() & mask);
+
+ for (unsigned long i = 0; i < m_attrCount; i++) {
+ if ((m_attrs[i].id() & mask) == id) {
+ // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
+ if (qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) &&
+ strcasecmp(m_attrs[i].name(), DOMString(qName)))
+ continue;
+ // Attribute exists; replace it
+ if (id == ATTR_ID)
+ m_element->updateId(m_attrs[i].val(), attr->val());
+
+ Node replaced = m_attrs[i].createAttr(m_element,m_element->docPtr());
+ m_attrs[i].free();
+ m_attrs[i].m_attrId = 0; /* "has implementation" flag */
+ m_attrs[i].m_data.attr = attr;
+ m_attrs[i].m_data.attr->ref();
+ attr->setElement(m_element);
+ m_element->parseAttribute(&m_attrs[i]);
+ m_element->attributeChanged(m_attrs[i].id());
+ // ### dispatch mutation events
+ return replaced;
+ }
+ }
+
+ // No existing attribute; add to list
+ m_attrCount++;
+ m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
+ m_attrs[m_attrCount-1].m_attrId = 0; /* "has implementation" flag */
+ m_attrs[m_attrCount-1].m_data.attr = attr;
+ m_attrs[m_attrCount-1].m_data.attr->ref();
+ attr->setElement(m_element);
+ if (id == ATTR_ID)
+ m_element->updateId(0, attr->val());
+ m_element->parseAttribute(&m_attrs[m_attrCount-1]);
+ m_element->attributeChanged(m_attrs[m_attrCount-1].id());
+ // ### dispatch mutation events
+
+ return 0;
+}
+
+NodeImpl *NamedAttrMapImpl::item ( unsigned long index ) const
+{
+ if (!m_element)
+ return 0;
+
+ if (index >= m_attrCount)
+ return 0;
+ else
+ return m_attrs[index].createAttr(m_element,m_element->docPtr());
+}
+
+unsigned long NamedAttrMapImpl::length( ) const
+{
+ if (!m_element)
+ return 0;
+
+ return m_attrCount;
+}
+
+NodeImpl::Id NamedAttrMapImpl::idAt(unsigned long index) const
+{
+ assert(index <= m_attrCount);
+ return m_attrs[index].id();
+}
+
+DOMStringImpl *NamedAttrMapImpl::valueAt(unsigned long index) const
+{
+ assert(index <= m_attrCount);
+ return m_attrs[index].val();
+}
+
+DOMStringImpl *NamedAttrMapImpl::getValue(NodeImpl::Id id, bool nsAware, DOMStringImpl* qName) const
+{
+ unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
+ id = (id & mask);
+ for (unsigned long i = 0; i < m_attrCount; i++)
+ if ((m_attrs[i].id() & mask) == id) {
+ // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
+ if (qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) &&
+ strcasecmp(m_attrs[i].name(), qName))
+ continue;
+ return m_attrs[i].val();
+ }
+ return 0;
+}
+
+void NamedAttrMapImpl::setValue(NodeImpl::Id id, DOMStringImpl *value, DOMStringImpl* qName,
+ DOMStringImpl *prefix, bool nsAware, bool hasNS)
+{
+ assert( !(qName && nsAware) );
+ if (!id) return;
+ // Passing in a null value here causes the attribute to be removed. This is a tdehtml extension
+ // (the spec does not specify what to do in this situation).
+ int exceptioncode = 0;
+ if (!value) {
+ removeNamedItem(id, nsAware, qName, exceptioncode);
+ return;
+ }
+ unsigned int mask = nsAware ? ~0L : NodeImpl_IdLocalMask;
+ NodeImpl::Id mid = (id & mask);
+
+ // Check for an existing attribute.
+ for (unsigned long i = 0; i < m_attrCount; i++) {
+ if ((m_attrs[i].id() & mask) == mid) {
+ // if we are called with a qualified name, filter out NS-aware elements with non-matching name.
+ if (qName && (namespacePart(m_attrs[i].id()) != defaultNamespace) &&
+ strcasecmp(m_attrs[i].name(), DOMString(qName)))
+ continue;
+ if (prefix)
+ m_attrs[i].attr()->setPrefix(prefix,exceptioncode);
+ m_attrs[i].setValue(value,m_element);
+ // ### dispatch mutation events
+ return;
+ }
+ }
+
+ // No existing matching attribute; add a new one
+ m_attrCount++;
+ m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
+ if (!nsAware) {
+ // Called from setAttribute()... we only have a name
+ m_attrs[m_attrCount-1].m_attrId = id;
+ m_attrs[m_attrCount-1].m_data.value = value;
+ m_attrs[m_attrCount-1].m_data.value->ref();
+ }
+ else {
+ // Called from setAttributeNS()... need to create a full AttrImpl here
+ if(!m_element)
+ return;
+ m_attrs[m_attrCount-1].m_data.attr = new AttrImpl(m_element,m_element->docPtr(),
+ id,
+ value,
+ prefix);
+ m_attrs[m_attrCount-1].m_attrId = 0; /* "has implementation" flag */
+ m_attrs[m_attrCount-1].m_data.attr->ref();
+ m_attrs[m_attrCount-1].m_data.attr->setHTMLCompat( !hasNS &&
+ m_element->getDocument()->htmlMode() != DocumentImpl::XHtml );
+ }
+ if (m_element) {
+ if (id == ATTR_ID)
+ m_element->updateId(0, value);
+ m_element->parseAttribute(&m_attrs[m_attrCount-1]);
+ m_element->attributeChanged(m_attrs[m_attrCount-1].id());
+ }
+ // ### dispatch mutation events
+}
+
+Attr NamedAttrMapImpl::removeAttr(AttrImpl *attr)
+{
+ for (unsigned long i = 0; i < m_attrCount; i++) {
+ if (m_attrs[i].attr() == attr) {
+ NodeImpl::Id id = m_attrs[i].id();
+ if (id == ATTR_ID)
+ m_element->updateId(attr->val(), 0);
+ Node removed(m_attrs[i].createAttr(m_element,m_element->docPtr()));
+ m_attrs[i].free();
+ memmove(m_attrs+i,m_attrs+i+1,(m_attrCount-i-1)*sizeof(AttributeImpl));
+ m_attrCount--;
+ m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
+ m_element->parseAttribute(id,0);
+ m_element->attributeChanged(id);
+ // ### dispatch mutation events
+ return removed;
+ }
+ }
+
+ return 0;
+}
+
+NodeImpl::Id NamedAttrMapImpl::mapId(DOMStringImpl* namespaceURI,
+ DOMStringImpl* localName, bool readonly)
+{
+ if (!m_element)
+ return 0;
+
+ return m_element->getDocument()->getId(NodeImpl::AttributeId, namespaceURI, 0, localName, readonly,
+ true /*lookupHTML*/);
+}
+
+void NamedAttrMapImpl::copyAttributes(NamedAttrMapImpl *other)
+{
+ assert(m_element);
+ unsigned long i;
+ for (i = 0; i < m_attrCount; i++) {
+ if (m_attrs[i].id() == ATTR_ID)
+ m_element->updateId(m_attrs[i].val(), 0);
+ m_attrs[i].free();
+ }
+ m_attrCount = other->m_attrCount;
+ m_attrs = (AttributeImpl*)realloc(m_attrs,m_attrCount*sizeof(AttributeImpl));
+ for (i = 0; i < m_attrCount; i++) {
+ m_attrs[i].m_attrId = other->m_attrs[i].m_attrId;
+ if (m_attrs[i].m_attrId) {
+ m_attrs[i].m_data.value = other->m_attrs[i].m_data.value;
+ m_attrs[i].m_data.value->ref();
+ }
+ else {
+ m_attrs[i].m_data.attr = static_cast<AttrImpl*>(other->m_attrs[i].m_data.attr->cloneNode(true));
+ m_attrs[i].m_data.attr->ref();
+ m_attrs[i].m_data.attr->setElement(m_element);
+ }
+ if (m_attrs[i].id() == ATTR_ID)
+ m_element->updateId(0, m_attrs[i].val());
+ m_element->parseAttribute(&m_attrs[i]);
+ m_element->attributeChanged(m_attrs[i].id());
+ }
+}
+
+void NamedAttrMapImpl::setElement(ElementImpl *element)
+{
+ assert(!m_element);
+ m_element = element;
+
+ for (unsigned long i = 0; i < m_attrCount; i++)
+ if (m_attrs[i].attr())
+ m_attrs[i].attr()->setElement(element);
+}
+
+void NamedAttrMapImpl::detachFromElement()
+{
+ // This makes the map invalid; nothing can really be done with it now since it's not
+ // associated with an element. But we have to keep it around in memory in case there
+ // are still references to it.
+ m_element = 0;
+ for (unsigned long i = 0; i < m_attrCount; i++)
+ m_attrs[i].free();
+ free(m_attrs);
+ m_attrs = 0;
+ m_attrCount = 0;
+}
diff --git a/tdehtml/xml/dom_elementimpl.h b/tdehtml/xml/dom_elementimpl.h
new file mode 100644
index 000000000..e528d7e24
--- /dev/null
+++ b/tdehtml/xml/dom_elementimpl.h
@@ -0,0 +1,392 @@
+/*
+ * 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 Peter Kelly (pmk@post.com)
+ * (C) 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.
+ *
+ */
+#ifndef _DOM_ELEMENTImpl_h_
+#define _DOM_ELEMENTImpl_h_
+
+#include "dom_nodeimpl.h"
+#include "dom/dom_exception.h"
+#include "dom/dom_element.h"
+#include "xml/dom_stringimpl.h"
+#include "misc/shared.h"
+
+namespace tdehtml {
+ class CSSStyleSelector;
+}
+
+namespace DOM {
+
+class ElementImpl;
+class DocumentImpl;
+class NamedAttrMapImpl;
+
+// Attr can have Text and EntityReference children
+// therefore it has to be a fullblown Node. The plan
+// is to dynamically allocate a textchild and store the
+// resulting nodevalue in the AttributeImpl upon
+// destruction. however, this is not yet implemented.
+class AttrImpl : public NodeBaseImpl
+{
+ friend class ElementImpl;
+ friend class NamedAttrMapImpl;
+
+public:
+ AttrImpl(ElementImpl* element, DocumentImpl* docPtr, NodeImpl::Id attrId,
+ DOMStringImpl *value, DOMStringImpl *prefix = 0);
+ ~AttrImpl();
+
+private:
+ AttrImpl(const AttrImpl &other);
+ AttrImpl &operator = (const AttrImpl &other);
+public:
+
+ // DOM methods & attributes for Attr
+ bool specified() const { return m_specified; }
+ ElementImpl* ownerElement() const { return m_element; }
+ void setOwnerElement( ElementImpl* impl ) { m_element = impl; }
+ DOMString name() const;
+
+ //DOMString value() const;
+ void setValue( const DOMString &v, int &exceptioncode );
+
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual DOMString prefix() const;
+ virtual void setPrefix(const DOMString &_prefix, int &exceptioncode );
+ virtual DOMString namespaceURI() const;
+ virtual DOMString localName() const;
+
+ virtual DOMString nodeValue() const;
+ virtual void setNodeValue( const DOMString &, int &exceptioncode );
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ virtual DOMStringImpl* textContent() const;
+ virtual void setTextContent( const DOMString &text, int& exceptioncode );
+
+
+ // Other methods (not part of DOM)
+ virtual bool isAttributeNode() const { return true; }
+ virtual bool childAllowed( NodeImpl *newChild );
+ virtual bool childTypeAllowed( unsigned short type );
+ virtual NodeImpl::Id id() const { return m_attrId; }
+
+ virtual DOMString toString() const;
+
+ void setElement(ElementImpl *element);
+ DOMStringImpl *val() { return m_value; }
+
+protected:
+ ElementImpl *m_element;
+ NodeImpl::Id m_attrId;
+ DOMStringImpl *m_value;
+ DOMStringImpl *m_prefix;
+ DOMStringImpl *m_localName;
+};
+
+// Mini version of AttrImpl internal to NamedAttrMapImpl.
+// Stores either the id and value of an attribute
+// (in the case of m_attrId != 0), or a pointer to an AttrImpl (if m_attrId == 0)
+// The latter case only happens when the Attr node is requested by some DOM
+// code or is an XML attribute.
+// In most cases the id and value is all we need to store, which is more
+// memory efficient.
+struct AttributeImpl
+{
+ NodeImpl::Id id() const { return m_attrId ? m_attrId : m_data.attr->id(); }
+ DOMStringImpl *val() const { return m_attrId ? m_data.value : m_data.attr->val(); }
+ DOMString value() const { return val(); }
+ AttrImpl *attr() const { return m_attrId ? 0 : m_data.attr; }
+ DOMString namespaceURI() { return m_attrId ? DOMString() : m_data.attr->namespaceURI(); }
+ DOMString prefix() { return m_attrId ? DOMString() : m_data.attr->prefix(); }
+ DOMString localName() { return m_attrId ? DOMString() : m_data.attr->localName(); }
+ DOMString name() { return m_attrId ? DOMString() : m_data.attr->name(); }
+
+ void setValue(DOMStringImpl *value, ElementImpl *element);
+ AttrImpl *createAttr(ElementImpl *element, DocumentImpl *docPtr);
+ void free();
+
+ NodeImpl::Id m_attrId;
+ union {
+ DOMStringImpl *value;
+ AttrImpl *attr;
+ } m_data;
+};
+
+class ElementImpl : public NodeBaseImpl
+{
+ friend class DocumentImpl;
+ friend class NamedAttrMapImpl;
+ friend class AttrImpl;
+ friend class NodeImpl;
+ friend class tdehtml::CSSStyleSelector;
+public:
+ ElementImpl(DocumentImpl *doc);
+ ~ElementImpl();
+
+ DOMString getAttribute( NodeImpl::Id id, bool nsAware = 0, const DOMString& qName = DOMString() ) const;
+ DOMStringImpl* getAttributeImpl( NodeImpl::Id id, bool nsAware = 0, DOMStringImpl* qName = 0 ) const;
+ void setAttribute( NodeImpl::Id id, const DOMString &value, const DOMString &qName,
+ int &exceptioncode );
+ void setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName,
+ const DOMString& value, int &exceptioncode );
+ virtual DOMString prefix() const;
+ void setPrefix(const DOMString &_prefix, int &exceptioncode );
+ virtual DOMString namespaceURI() const;
+
+ // DOM methods overridden from parent classes
+ virtual DOMString tagName() const = 0;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+ virtual DOMString nodeName() const;
+ virtual NodeImpl::Id id() const = 0;
+ virtual bool isElementNode() const { return true; }
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+
+ // convenience methods which ignore exceptions
+ void setAttribute (NodeImpl::Id id, const DOMString &value);
+
+ NamedAttrMapImpl* attributes(bool readonly = false) const
+ {
+ if (!readonly && !namedAttrMap) createAttributeMap();
+ return namedAttrMap;
+ }
+
+ //This is always called, whenever an attribute changed
+ virtual void parseAttribute(AttributeImpl *) {}
+ void parseAttribute(NodeImpl::Id attrId, DOMStringImpl *value) {
+ AttributeImpl aimpl;
+ aimpl.m_attrId = attrId;
+ aimpl.m_data.value = value;
+ parseAttribute(&aimpl);
+ }
+
+ // not part of the DOM
+ void setAttributeMap ( NamedAttrMapImpl* list );
+
+ // State of the element.
+ virtual TQString state() { return TQString::null; }
+
+ virtual void attach();
+ virtual void close();
+ virtual void detach();
+ virtual void structureChanged();
+ virtual void backwardsStructureChanged();
+ virtual void attributeChanged(NodeImpl::Id attrId);
+
+ virtual tdehtml::RenderStyle *styleForRenderer(tdehtml::RenderObject *parent);
+ virtual tdehtml::RenderObject *createRenderer(tdehtml::RenderArena *, tdehtml::RenderStyle *);
+ virtual void recalcStyle( StyleChange = NoChange );
+
+ virtual void mouseEventHandler( MouseEvent* /*ev*/, bool /*inside*/ ) {}
+ virtual bool isFocusable() const;
+ virtual bool childAllowed( NodeImpl *newChild );
+ virtual bool childTypeAllowed( unsigned short type );
+
+ DOM::CSSStyleDeclarationImpl *styleRules() {
+ if (!m_styleDecls) createDecl();
+ return m_styleDecls;
+ }
+
+ void dispatchAttrRemovalEvent(NodeImpl::Id id, DOMStringImpl *value);
+ void dispatchAttrAdditionEvent(NodeImpl::Id id, DOMStringImpl *value);
+
+ virtual DOMString toString() const;
+ virtual DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const;
+
+ virtual bool contentEditable() const;
+ void setContentEditable(bool enabled);
+
+ void scrollIntoView(bool alignToTop);
+
+ /** Returns the opening tag and properties.
+ * Examples: '<b', '<img alt="hello" src="image.png"
+ *
+ * For security reasons, passwords are stripped out of all src= and
+ * href= tags if expandurls is turned on.
+ *
+ * @param expandurls If this is set then in the above example, it would give
+ * src="http://website.com/image.png". Note that the password
+ * is stripped out of the url.
+ *
+ * DOM::RangeImpl uses this which is why it is public.
+ */
+ DOMString openTagStartToString(bool expandurls = false) const;
+
+ void updateId(DOMStringImpl* oldId, DOMStringImpl* newId);
+ //Called when mapping from id to this node in document should be removed
+ virtual void removeId(const TQString& id);
+ //Called when mapping from id to this node in document should be added
+ virtual void addId (const TQString& id);
+
+protected:
+ void createAttributeMap() const;
+ void createDecl();
+ void finishCloneNode( ElementImpl *clone, bool deep );
+
+private:
+ // map of default attributes. derived element classes are responsible
+ // for setting this according to the corresponding element description
+ // in the DTD
+ virtual NamedAttrMapImpl* defaultMap() const;
+
+protected: // member variables
+ mutable NamedAttrMapImpl *namedAttrMap;
+
+ DOM::CSSStyleDeclarationImpl *m_styleDecls;
+ DOMStringImpl *m_prefix;
+};
+
+
+class XMLElementImpl : public ElementImpl
+{
+
+public:
+ XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id);
+ XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id, DOMStringImpl *_qualifiedName);
+ ~XMLElementImpl();
+
+ // DOM methods overridden from parent classes
+ virtual DOMString tagName() const;
+ virtual DOMString localName() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+ virtual bool isXMLElementNode() const { return true; }
+ virtual Id id() const { return m_id; }
+
+protected:
+ Id m_id;
+};
+
+// the map of attributes of an element
+class NamedAttrMapImpl : public NamedNodeMapImpl
+{
+ friend class ElementImpl;
+public:
+ NamedAttrMapImpl(ElementImpl *element);
+ virtual ~NamedAttrMapImpl();
+
+ // DOM methods & attributes for NamedNodeMap
+ virtual NodeImpl *getNamedItem ( NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0 ) const;
+ virtual Node removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode );
+ virtual Node setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode );
+
+ virtual NodeImpl *item ( unsigned long index ) const;
+ virtual unsigned long length( ) const;
+
+ // Other methods (not part of DOM)
+ virtual bool isReadOnly() { return false; }
+
+ AttributeImpl *attrAt(unsigned long index) const { return &m_attrs[index]; }
+ // ### replace idAt and getValueAt with attrAt
+ NodeImpl::Id idAt(unsigned long index) const;
+ DOMStringImpl *valueAt(unsigned long index) const;
+ DOMStringImpl *getValue(NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0) const;
+ void setValue(NodeImpl::Id id, DOMStringImpl *value, DOMStringImpl* qName = 0,
+ DOMStringImpl *prefix = 0, bool nsAware = false, bool hasNS = false);
+ Attr removeAttr(AttrImpl *attr);
+ NodeImpl::Id mapId(DOMStringImpl* namespaceURI, DOMStringImpl* localName, bool readonly);
+ void copyAttributes(NamedAttrMapImpl *other);
+ void setElement(ElementImpl *element);
+ void detachFromElement();
+
+protected:
+ ElementImpl *m_element;
+ AttributeImpl *m_attrs;
+ unsigned long m_attrCount;
+};
+
+// ------------ inline DOM helper functions ---------------
+
+inline bool checkQualifiedName(const DOMString &qualifiedName, const DOMString &namespaceURI, int *colonPos,
+ bool nameCanBeNull, bool nameCanBeEmpty, int *pExceptioncode)
+{
+
+ // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
+ if (!nameCanBeNull && qualifiedName.isNull()) {
+ if (pExceptioncode)
+ *pExceptioncode = DOMException::NAMESPACE_ERR;
+ return false;
+ }
+
+ // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
+ if (!qualifiedName.isNull() && !Element::tdehtmlValidQualifiedName(qualifiedName)
+ && ( !qualifiedName.isEmpty() || !nameCanBeEmpty ) ) {
+ if (pExceptioncode)
+ *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
+ return false;
+ }
+
+ // NAMESPACE_ERR:
+ // - Raised if the qualifiedName is malformed,
+ // - if the qualifiedName has a prefix and the namespaceURI is null, or
+ // - if the qualifiedName is null and the namespaceURI is different from null
+ // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different
+ // from "http://www.w3.org/XML/1998/namespace" [Namespaces].
+ int colonpos = -1;
+ uint i;
+ DOMStringImpl *qname = qualifiedName.implementation();
+ for (i = 0 ; i < qname->l ; i++) {
+ if ((*qname)[i] == ':') {
+ colonpos = i;
+ break;
+ }
+ }
+
+ if (!qualifiedName.isNull() && Element::tdehtmlMalformedQualifiedName(qualifiedName) ||
+ (colonpos >= 0 && namespaceURI.isNull()) ||
+ (qualifiedName.isNull() && !namespaceURI.isNull()) ||
+ (colonpos == 3 && qualifiedName[0] == 'x' && qualifiedName[1] == 'm' && qualifiedName[2] == 'l' &&
+ namespaceURI != "http://www.w3.org/XML/1998/namespace")) {
+ if (pExceptioncode)
+ *pExceptioncode = DOMException::NAMESPACE_ERR;
+ return false;
+ }
+ if(colonPos)
+ *colonPos = colonpos;
+ return true;
+}
+
+inline void splitPrefixLocalName(DOMStringImpl *qualifiedName, DOMString &prefix, DOMString &localName, int colonPos = -2)
+{
+ if (colonPos == -2)
+ for (uint i = 0 ; i < qualifiedName->l ; ++i)
+ if (qualifiedName->s[i] == ':') {
+ colonPos = i;
+ break;
+ }
+ if (colonPos >= 0) {
+ prefix = qualifiedName->copy();
+ localName = prefix.split(colonPos+1);
+ prefix.implementation()->truncate(colonPos);
+ } else
+ localName = qualifiedName->copy();
+}
+
+} //namespace
+
+#endif
diff --git a/tdehtml/xml/dom_nodeimpl.cpp b/tdehtml/xml/dom_nodeimpl.cpp
new file mode 100644
index 000000000..251cb1444
--- /dev/null
+++ b/tdehtml/xml/dom_nodeimpl.cpp
@@ -0,0 +1,2068 @@
+/*
+ * 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) 2003-2006 Apple Computer, Inc.
+ * (C) 2006 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.
+ */
+
+#include "dom/dom_exception.h"
+#include "misc/htmlattrs.h"
+#include "misc/htmltags.h"
+#include "xml/dom_elementimpl.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_restyler.h"
+
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include "rendering/render_text.h"
+#include "rendering/render_flow.h"
+#include "rendering/render_line.h"
+
+#include "ecma/kjs_proxy.h"
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include "dom_nodeimpl.h"
+
+// from tdehtml_caret_p.h
+namespace tdehtml {
+void /*KDE_NO_EXPORT*/ mapDOMPosToRenderPos(DOM::NodeImpl *node, long offset,
+ tdehtml::RenderObject *&r, long &r_ofs, bool &outside, bool &outsideEnd);
+}
+
+using namespace DOM;
+using namespace tdehtml;
+
+NodeImpl::NodeImpl(DocumentImpl *doc)
+ : m_document(doc),
+ m_previous(0),
+ m_next(0),
+ m_render(0),
+ m_tabIndex( 0 ),
+ m_hasId( false ),
+ m_attached(false),
+ m_closed(false),
+ m_changed( false ),
+ m_hasChangedChild( false ),
+ m_changedAscendentAttribute( false ),
+ m_inDocument( false ),
+ m_hasAnchor( false ),
+ m_specified( false ),
+ m_hovered( false ),
+ m_focused( false ),
+ m_active( false ),
+ m_implicit( false ),
+ m_htmlCompat( false ),
+ m_hasClassList( false ),
+ m_hasClass( false )
+{
+}
+
+NodeImpl::~NodeImpl()
+{
+ if (m_render)
+ detach();
+ if (m_previous)
+ m_previous->setNextSibling(0);
+ if (m_next)
+ m_next->setPreviousSibling(0);
+}
+
+DOMString NodeImpl::nodeValue() const
+{
+ return DOMString();
+}
+
+void NodeImpl::setNodeValue( const DOMString &/*_nodeValue*/, int &/*exceptioncode*/ )
+{
+ // by default nodeValue is null, so setting it has no effect
+ // don't throw NO_MODIFICATION_ALLOWED_ERR from here, DOMTS-Core-Level1's hc_nodevalue03
+ // (createEntityReference().setNodeValue())) says it would be wrong.
+ // This must be done by subclasses instead.
+}
+
+DOMString NodeImpl::nodeName() const
+{
+ return DOMString();
+}
+
+unsigned short NodeImpl::nodeType() const
+{
+ return 0;
+}
+
+NodeListImpl *NodeImpl::childNodes()
+{
+ return new ChildNodeListImpl(this);
+}
+
+NodeImpl *NodeImpl::firstChild() const
+{
+ return 0;
+}
+
+NodeImpl *NodeImpl::lastChild() const
+{
+ return 0;
+}
+
+NodeImpl *NodeImpl::insertBefore( NodeImpl *, NodeImpl *, int &exceptioncode )
+{
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return 0;
+}
+
+void NodeImpl::replaceChild( NodeImpl *, NodeImpl *, int &exceptioncode )
+{
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+}
+
+void NodeImpl::removeChild( NodeImpl *, int &exceptioncode )
+{
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+}
+
+NodeImpl *NodeImpl::appendChild( NodeImpl *, int &exceptioncode )
+{
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return 0;
+}
+
+bool NodeImpl::hasChildNodes( ) const
+{
+ return false;
+}
+
+void NodeImpl::normalize ()
+{
+ // ### normalize attributes? (when we store attributes using child nodes)
+ int exceptioncode = 0;
+ NodeImpl *child = firstChild();
+
+ // Recursively go through the subtree beneath us, normalizing all nodes. In the case
+ // where there are two adjacent text nodes, they are merged together
+ while (child) {
+ NodeImpl *nextChild = child->nextSibling();
+
+ if (nextChild && child->nodeType() == Node::TEXT_NODE && nextChild->nodeType() == Node::TEXT_NODE) {
+ // Current child and the next one are both text nodes... merge them
+ TextImpl *currentText = static_cast<TextImpl*>(child);
+ TextImpl *nextText = static_cast<TextImpl*>(nextChild);
+
+ currentText->appendData(nextText->data(),exceptioncode);
+ if (exceptioncode)
+ return;
+
+ removeChild(nextChild,exceptioncode);
+ if (exceptioncode)
+ return;
+ }
+ else {
+ child->normalize();
+ child = nextChild;
+ }
+ }
+}
+
+DOMString NodeImpl::prefix() const
+{
+ // For nodes other than elements and attributes, the prefix is always null
+ return DOMString();
+}
+
+DOMString NodeImpl::namespaceURI() const
+{
+ return DOMString();
+}
+
+void NodeImpl::setPrefix(const DOMString &/*_prefix*/, int &exceptioncode )
+{
+ // The spec says that for nodes other than elements and attributes, prefix is always null.
+ // It does not say what to do when the user tries to set the prefix on another type of
+ // node, however mozilla throws a NAMESPACE_ERR exception
+ exceptioncode = DOMException::NAMESPACE_ERR;
+}
+
+DOMString NodeImpl::localName() const
+{
+ return DOMString();
+}
+
+void NodeImpl::setFirstChild(NodeImpl *)
+{
+}
+
+void NodeImpl::setLastChild(NodeImpl *)
+{
+}
+
+NodeImpl *NodeImpl::addChild(NodeImpl *)
+{
+ return 0;
+}
+
+void NodeImpl::getCaret(int offset, bool override, int &_x, int &_y, int &width, int &height)
+{
+ if (m_render) {
+ RenderObject *r;
+ long r_ofs;
+ bool outside, outsideEnd;
+#if 0
+kdDebug(6200) << "getCaret: node " << this << " " << nodeName().string() << " offset: " << offset << endl;
+#endif
+ mapDOMPosToRenderPos(this, offset, r, r_ofs, outside, outsideEnd);
+#if 0
+kdDebug(6200) << "getCaret: r " << r << " " << (r?r->renderName():TQString::null) << " r_ofs: " << r_ofs << " outside " << outside << " outsideEnd " << outsideEnd << endl;
+#endif
+ if (r) {
+ r->caretPos(r_ofs, override*RenderObject::CFOverride
+ + outside*RenderObject::CFOutside
+ + outsideEnd*RenderObject::CFOutsideEnd, _x, _y, width, height);
+ } else
+ _x = _y = height = -1, width = 1;
+ } else _x = _y = height = -1, width = 1;
+}
+
+TQRect NodeImpl::getRect() const
+{
+ int _x, _y;
+ if(m_render && m_render->absolutePosition(_x, _y))
+ return TQRect( _x + m_render->inlineXPos(), _y + m_render->inlineYPos(),
+ m_render->width(), m_render->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra() );
+
+ return TQRect();
+}
+
+void NodeImpl::setChanged(bool b)
+{
+ if (b && !attached()) // changed compared to what?
+ return;
+
+ m_changed = b;
+ if ( b ) {
+ NodeImpl *p = parentNode();
+ while ( p ) {
+ p->setHasChangedChild( true );
+ p = p->parentNode();
+ }
+ getDocument()->setDocumentChanged();
+ }
+}
+
+bool NodeImpl::isInline() const
+{
+ if (m_render) return m_render->style()->display() == tdehtml::INLINE;
+ return !isElementNode();
+}
+
+
+unsigned long NodeImpl::nodeIndex() const
+{
+ NodeImpl *_tempNode = previousSibling();
+ unsigned long count=0;
+ for( count=0; _tempNode; count++ )
+ _tempNode = _tempNode->previousSibling();
+ return count;
+}
+
+void NodeImpl::addEventListener(int id, EventListener *listener, const bool useCapture)
+{
+ switch (id) {
+ case EventImpl::DOMSUBTREEMODIFIED_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
+ break;
+ case EventImpl::DOMNODEINSERTED_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER);
+ break;
+ case EventImpl::DOMNODEREMOVED_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER);
+ break;
+ case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
+ break;
+ case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
+ break;
+ case EventImpl::DOMATTRMODIFIED_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER);
+ break;
+ case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
+ getDocument()->addListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
+ break;
+ default:
+ break;
+ }
+
+ m_regdListeners.addEventListener(id, listener, useCapture);
+}
+
+void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
+{
+ m_regdListeners.removeEventListener(id, listener, useCapture);
+}
+
+void NodeImpl::setHTMLEventListener(int id, EventListener *listener)
+{
+ m_regdListeners.setHTMLEventListener(id, listener);
+}
+
+EventListener *NodeImpl::getHTMLEventListener(int id)
+{
+ return m_regdListeners.getHTMLEventListener(id);
+}
+
+void NodeImpl::dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent)
+{
+ evt->setTarget(this);
+
+ // Since event handling code could cause this object to be deleted, grab a reference to the view now
+ KHTMLView *view = getDocument()->view();
+
+ dispatchGenericEvent( evt, exceptioncode );
+
+ // If tempEvent is true, this means that the DOM implementation will not be storing a reference to the event, i.e.
+ // there is no way to retrieve it from javascript if a script does not already have a reference to it in a variable.
+ // So there is no need for the interpreter to keep the event in its cache
+ if (tempEvent && view && view->part() && view->part()->jScript())
+ view->part()->jScript()->finishedWithEvent(evt);
+}
+
+void NodeImpl::dispatchGenericEvent( EventImpl *evt, int &/*exceptioncode */)
+{
+ // ### check that type specified
+
+ // work out what nodes to send event to
+ TQPtrList<NodeImpl> nodeChain;
+ NodeImpl *n;
+ for (n = this; n; n = n->parentNode()) {
+ n->ref();
+ nodeChain.prepend(n);
+ }
+
+ // trigger any capturing event handlers on our way down
+ evt->setEventPhase(Event::CAPTURING_PHASE);
+ TQPtrListIterator<NodeImpl> it(nodeChain);
+ for (; it.current() && it.current() != this && !evt->propagationStopped(); ++it) {
+ evt->setCurrentTarget(it.current());
+ it.current()->handleLocalEvents(evt,true);
+ }
+
+ // dispatch to the actual target node
+ it.toLast();
+ NodeImpl* propagationSentinel = 0;
+ if (!evt->propagationStopped()) {
+ evt->setEventPhase(Event::AT_TARGET);
+ evt->setCurrentTarget(it.current());
+ it.current()->handleLocalEvents(evt, true);
+ if (!evt->propagationStopped())
+ it.current()->handleLocalEvents(evt,false);
+ else
+ propagationSentinel = it.current();
+ }
+ --it;
+
+ if (evt->bubbles()) {
+ evt->setEventPhase(Event::BUBBLING_PHASE);
+ for (; it.current() && !evt->propagationStopped(); --it) {
+ if (evt->propagationStopped()) propagationSentinel = it.current();
+ evt->setCurrentTarget(it.current());
+ it.current()->handleLocalEvents(evt,false);
+ }
+
+ // now we call all default event handlers (this is not part of DOM - it is internal to tdehtml)
+ evt->setCurrentTarget(0);
+ evt->setEventPhase(0); // I guess this is correct, the spec does not seem to say
+ for (it.toLast(); it.current() && it.current() != propagationSentinel &&
+ !evt->defaultPrevented() && !evt->defaultHandled(); --it)
+ it.current()->defaultEventHandler(evt);
+
+ if (evt->id() == EventImpl::CLICK_EVENT && !evt->defaultPrevented() &&
+ static_cast<MouseEventImpl*>( evt )->button() == 0) // LMB click
+ dispatchUIEvent(EventImpl::DOMACTIVATE_EVENT, static_cast<UIEventImpl*>(evt)->detail());
+ }
+
+ // copy this over into a local variable, as the following deref() calls might cause this to be deleted.
+ DocumentImpl *doc = m_document.get();
+ doc->ref();
+
+ // deref all nodes in chain
+ it.toFirst();
+ for (; it.current(); ++it)
+ it.current()->deref(); // this may delete us
+
+ DocumentImpl::updateDocumentsRendering();
+ doc->deref();
+}
+
+bool NodeImpl::dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg)
+{
+ int exceptioncode = 0;
+ EventImpl* const evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode,true);
+ bool ret = !evt->defaultPrevented();
+ evt->deref();
+ return ret;
+}
+
+void NodeImpl::dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg)
+{
+ int exceptioncode = 0;
+ EventImpl* const evt = new EventImpl(static_cast<EventImpl::EventId>(_id),canBubbleArg,cancelableArg);
+ evt->setTarget( 0 );
+ evt->ref();
+ DocumentImpl *doc = getDocument();
+ doc->ref();
+ dispatchGenericEvent( evt, exceptioncode );
+ if (!evt->defaultPrevented() && doc)
+ doc->defaultEventHandler(evt);
+
+ if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && doc) {
+ // For onload events, send them to the enclosing frame only.
+ // This is a DOM extension and is independent of bubbling/capturing rules of
+ // the DOM. You send the event only to the enclosing frame. It does not
+ // bubble through the parent document.
+ DOM::ElementImpl* elt = doc->ownerElement();
+ if (elt && (elt->getDocument()->domain().isNull() ||
+ elt->getDocument()->domain() == doc->domain())) {
+ // We also do a security check, since we don't want to allow the enclosing
+ // iframe to see loads of child documents in other domains.
+ evt->setCurrentTarget(elt);
+
+ // Capturing first.
+ elt->handleLocalEvents(evt,true);
+
+ // Bubbling second.
+ if (!evt->propagationStopped())
+ elt->handleLocalEvents(evt,false);
+ }
+ }
+
+ doc->deref();
+ evt->deref();
+}
+
+void NodeImpl::dispatchMouseEvent(TQMouseEvent *_mouse, int overrideId, int overrideDetail)
+{
+ bool cancelable = true;
+ int detail = overrideDetail; // defaults to 0
+ EventImpl::EventId evtId = EventImpl::UNKNOWN_EVENT;
+ if (overrideId) {
+ evtId = static_cast<EventImpl::EventId>(overrideId);
+ }
+ else {
+ switch (_mouse->type()) {
+ case TQEvent::MouseButtonPress:
+ evtId = EventImpl::MOUSEDOWN_EVENT;
+ break;
+ case TQEvent::MouseButtonRelease:
+ evtId = EventImpl::MOUSEUP_EVENT;
+ break;
+ case TQEvent::MouseButtonDblClick:
+ evtId = EventImpl::CLICK_EVENT;
+ detail = 1; // ### support for multiple double clicks
+ break;
+ case TQEvent::MouseMove:
+ evtId = EventImpl::MOUSEMOVE_EVENT;
+ cancelable = false;
+ break;
+ default:
+ break;
+ }
+ }
+ if (evtId == EventImpl::UNKNOWN_EVENT)
+ return; // shouldn't happen
+
+
+ int exceptioncode = 0;
+ int pageX = _mouse->x();
+ int pageY = _mouse->y();
+ int clientX = pageX;
+ int clientY = pageY;
+ if ( getDocument()->view() )
+ getDocument()->view()->viewportToContents( clientX, clientY, pageX, pageY );
+
+ int screenX = _mouse->globalX();
+ int screenY = _mouse->globalY();
+
+ int button = -1;
+ switch (_mouse->button()) {
+ case Qt::LeftButton:
+ button = 0;
+ break;
+ case Qt::MidButton:
+ button = 1;
+ break;
+ case Qt::RightButton:
+ button = 2;
+ break;
+ default:
+ break;
+ }
+ bool ctrlKey = (_mouse->state() & TQt::ControlButton);
+ bool altKey = (_mouse->state() & TQt::AltButton);
+ bool shiftKey = (_mouse->state() & TQt::ShiftButton);
+ bool metaKey = false; // ### qt support?
+
+ EventImpl* const evt = new MouseEventImpl(evtId,true,cancelable,getDocument()->defaultView(),
+ detail,screenX,screenY,clientX,clientY,pageX,pageY,ctrlKey,altKey,shiftKey,metaKey,
+ button,0);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+}
+
+void NodeImpl::dispatchUIEvent(int _id, int detail)
+{
+ assert (!( (_id != EventImpl::DOMFOCUSIN_EVENT &&
+ _id != EventImpl::DOMFOCUSOUT_EVENT &&
+ _id != EventImpl::DOMACTIVATE_EVENT)));
+
+ bool cancelable = false;
+ if (_id == EventImpl::DOMACTIVATE_EVENT)
+ cancelable = true;
+
+ int exceptioncode = 0;
+ UIEventImpl* const evt = new UIEventImpl(static_cast<EventImpl::EventId>(_id),true,
+ cancelable,getDocument()->defaultView(),detail);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+}
+
+void NodeImpl::dispatchSubtreeModifiedEvent()
+{
+ childrenChanged();
+ getDocument()->incDOMTreeVersion();
+ if (!getDocument()->hasListenerType(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER))
+ return;
+ int exceptioncode = 0;
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMSUBTREEMODIFIED_EVENT,true,
+ false,0,DOMString(),DOMString(),DOMString(),0);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+}
+
+bool NodeImpl::dispatchKeyEvent(TQKeyEvent *key, bool keypress)
+{
+ int exceptioncode = 0;
+ //kdDebug(6010) << "DOM::NodeImpl: dispatching keyboard event" << endl;
+ EventImpl* keyEventImpl;
+ if (keypress)
+ keyEventImpl = new TextEventImpl(key, getDocument()->defaultView());
+ else
+ keyEventImpl = new KeyboardEventImpl(key, getDocument()->defaultView());
+ keyEventImpl->ref();
+ dispatchEvent(keyEventImpl,exceptioncode,true);
+ bool r = keyEventImpl->defaultHandled() || keyEventImpl->defaultPrevented();
+ keyEventImpl->deref();
+ return r;
+}
+
+void NodeImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
+{
+ if (!m_regdListeners.listeners)
+ return;
+
+ Event ev = evt;
+ // removeEventListener (e.g. called from a JS event listener) might
+ // invalidate the item after the current iterator (which "it" is pointing to).
+ // So we make a copy of the list.
+ TQValueList<RegisteredEventListener> listeners = *m_regdListeners.listeners;
+ TQValueList<RegisteredEventListener>::iterator it;
+ for (it = listeners.begin(); it != listeners.end(); ++it) {
+ //Check whether this got removed...KDE4: use Java-style iterators
+ if (!m_regdListeners.stillContainsListener(*it))
+ continue;
+
+ RegisteredEventListener& current = (*it);
+ if (current.id == evt->id() && current.useCapture == useCapture)
+ current.listener->handleEvent(ev);
+
+ // ECMA legacy hack
+ if (current.useCapture == useCapture && evt->id() == EventImpl::CLICK_EVENT) {
+ MouseEventImpl* me = static_cast<MouseEventImpl*>(evt);
+ if (me->button() == 0) {
+ // To find whether to call onclick or ondblclick, we can't
+ // * use me->detail(), it's 2 when clicking twice w/o moving, even very slowly
+ // * use me->qEvent(), it's not available when using initMouseEvent/dispatchEvent
+ // So we currently store a bool in MouseEventImpl. If anyone needs to trigger
+ // dblclicks from the DOM API, we'll need a timer here (well in the doc).
+ if ( ( !me->isDoubleClick() && current.id == EventImpl::KHTML_ECMA_CLICK_EVENT) ||
+ ( me->isDoubleClick() && current.id == EventImpl::KHTML_ECMA_DBLCLICK_EVENT) )
+ current.listener->handleEvent(ev);
+ }
+ }
+ }
+}
+
+void NodeImpl::defaultEventHandler(EventImpl *)
+{
+}
+
+unsigned long NodeImpl::childNodeCount()
+{
+ return 0;
+}
+
+NodeImpl *NodeImpl::childNode(unsigned long /*index*/)
+{
+ return 0;
+}
+
+NodeImpl *NodeImpl::traverseNextNode(NodeImpl *stayWithin) const
+{
+ if (firstChild() || stayWithin == this)
+ return firstChild();
+ else if (nextSibling())
+ return nextSibling();
+ else {
+ const NodeImpl *n = this;
+ while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
+ n = n->parentNode();
+ if (n)
+ return n->nextSibling();
+ }
+ return 0;
+}
+
+NodeImpl *NodeImpl::traversePreviousNode() const
+{
+ if (previousSibling()) {
+ NodeImpl *n = previousSibling();
+ while (n->lastChild())
+ n = n->lastChild();
+ return n;
+ }
+ else if (parentNode()) {
+ return parentNode();
+ }
+ else {
+ return 0;
+ }
+}
+
+void NodeImpl::checkSetPrefix(const DOMString &_prefix, int &exceptioncode)
+{
+ // Perform error checking as required by spec for setting Node.prefix. Used by
+ // ElementImpl::setPrefix() and AttrImpl::setPrefix()
+
+ // INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
+ if (!Element::tdehtmlValidPrefix(_prefix)) {
+ exceptioncode = DOMException::INVALID_CHARACTER_ERR;
+ return;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // NAMESPACE_ERR: - Raised if the specified prefix is malformed
+ // - if the namespaceURI of this node is null,
+ // - if the specified prefix is "xml" and the namespaceURI of this node is different from
+ // "http://www.w3.org/XML/1998/namespace",
+ // - if this node is an attribute and the specified prefix is "xmlns" and
+ // the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
+ // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
+ if (Element::tdehtmlMalformedPrefix(_prefix) || (namespacePart(id()) == defaultNamespace && id() > ID_LAST_TAG) ||
+ (_prefix == "xml" && namespaceURI() != "http://www.w3.org/XML/1998/namespace")) {
+ exceptioncode = DOMException::NAMESPACE_ERR;
+ return;
+ }
+}
+
+void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
+{
+ // Perform error checking as required by spec for adding a new child. Used by
+ // appendChild(), replaceChild() and insertBefore()
+
+ // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
+ if (!newChild) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
+ // created this node.
+ // We assume that if newChild is a DocumentFragment, all children are created from the same document
+ // as the fragment itself (otherwise they could not have been added as children)
+ if (newChild->getDocument() != getDocument()) {
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return;
+ }
+
+ // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
+ // newChild node, or if the node to append is one of this node's ancestors.
+
+ // check for ancestor/same node
+ if (isAncestor(newChild)) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+
+ // check node allowed
+ if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
+ // newChild is a DocumentFragment... check all its children instead of newChild itself
+ NodeImpl *child;
+ for (child = newChild->firstChild(); child; child = child->nextSibling()) {
+ if (!childTypeAllowed(child->nodeType())) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+ }
+ else {
+ // newChild is not a DocumentFragment... check if it's allowed directly
+ if(!childTypeAllowed(newChild->nodeType())) {
+ exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
+ return;
+ }
+ }
+}
+
+bool NodeImpl::isAncestor( NodeImpl *other )
+{
+ // Return true if other is the same as this node or an ancestor of it, otherwise false
+ NodeImpl *n;
+ for (n = this; n; n = n->parentNode()) {
+ if (n == other)
+ return true;
+ }
+ return false;
+}
+
+bool NodeImpl::childAllowed( NodeImpl *newChild )
+{
+ return childTypeAllowed(newChild->nodeType());
+}
+
+NodeImpl::StyleChange NodeImpl::diff( tdehtml::RenderStyle *s1, tdehtml::RenderStyle *s2 )
+{
+ // This method won't work when a style contains noninherited properties with "inherit" value.
+ StyleChange ch = NoInherit;
+
+ EDisplay display1 = s1 ? s1->display() : NONE;
+ EDisplay display2 = s2 ? s2->display() : NONE;
+ EPosition position1 = s1 ? s1->position() : STATIC;
+ EPosition position2 = s2 ? s2->position() : STATIC;
+
+ if (display1 != display2 || position1 != position2)
+ ch = Detach;
+ else if ( !s1 || !s2 )
+ ch = Inherit;
+ else if ( *s1 == *s2 )
+ ch = NoChange;
+ else if (s1->useNormalContent() != s2->useNormalContent())
+ ch = Detach; // when we add generated content all children must be detached
+ else if ( s1->inheritedNotEqual( s2 ) )
+ ch = Inherit;
+
+ // Because the first-letter implementation is so f..ked up, the easiest way
+ // to update first-letter is to remove the entire node and readd it.
+ if (ch < Detach && pseudoDiff(s1, s2, tdehtml::RenderStyle::FIRST_LETTER))
+ ch = Detach;
+ // If the other pseudoStyles have changed, we want to return NoInherit
+ if (ch == NoChange && pseudoDiff(s1, s2, tdehtml::RenderStyle::BEFORE))
+ ch = NoInherit;
+ if (ch == NoChange && pseudoDiff(s1, s2, tdehtml::RenderStyle::AFTER))
+ ch = NoInherit;
+ if (ch == NoChange && pseudoDiff(s1, s2, tdehtml::RenderStyle::MARKER))
+ ch = NoInherit;
+ if (ch == NoChange && pseudoDiff(s1, s2, tdehtml::RenderStyle::SELECTION))
+ ch = NoInherit;
+ if (ch == NoChange && pseudoDiff(s1, s2, tdehtml::RenderStyle::FIRST_LINE))
+ ch = NoInherit;
+
+ return ch;
+}
+
+bool NodeImpl::pseudoDiff( tdehtml::RenderStyle *s1, tdehtml::RenderStyle *s2, unsigned int pid)
+{
+ tdehtml::RenderStyle *ps1 = s1 ? s1->getPseudoStyle((tdehtml::RenderStyle::PseudoId)pid) : 0;
+ tdehtml::RenderStyle *ps2 = s2 ? s2->getPseudoStyle((tdehtml::RenderStyle::PseudoId)pid) : 0;
+
+ if (ps1 == ps2)
+ return false;
+ else
+ if (ps1 && ps2) {
+ if (*ps1 == *ps2)
+ return false;
+ else
+ return true;
+ }
+ else
+ return true;
+}
+
+void NodeImpl::close()
+{
+ if (m_render) m_render->close();
+ m_closed = true;
+}
+
+void NodeImpl::attach()
+{
+ assert(!attached());
+ assert(!m_render || (m_render->style() && m_render->parent()));
+ if (m_render) // set states to match node
+ {
+ if (closed()) m_render->close();
+ if (hovered()) m_render->setMouseInside();
+ }
+ getDocument()->incDOMTreeVersion();
+ m_attached = true;
+}
+
+void NodeImpl::detach()
+{
+// assert(m_attached);
+
+ if ( m_render )
+ m_render->detach();
+
+ m_render = 0;
+ getDocument()->incDOMTreeVersion();
+ m_attached = false;
+}
+
+bool NodeImpl::maintainsState()
+{
+ return false;
+}
+
+TQString NodeImpl::state()
+{
+ return TQString::null;
+}
+
+void NodeImpl::restoreState(const TQString &/*state*/)
+{
+}
+
+void NodeImpl::insertedIntoDocument()
+{
+ setInDocument(true);
+}
+
+void NodeImpl::removedFromDocument()
+{
+ setInDocument(false);
+}
+
+void NodeImpl::childrenChanged()
+{
+ if (parentNode())
+ parentNode()->childrenChanged();
+}
+
+bool NodeImpl::isReadOnly()
+{
+ // Entity & Entity Reference nodes and their descendants are read-only
+ NodeImpl *n = this;
+ while (n) {
+ if (n->nodeType() == Node::ENTITY_NODE ||
+ n->nodeType() == Node::ENTITY_REFERENCE_NODE)
+ return true;
+ n = n->parentNode();
+ }
+ return false;
+}
+
+RenderObject * NodeImpl::previousRenderer()
+{
+ for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
+ if (n->renderer())
+ return n->renderer();
+ }
+ return 0;
+}
+
+RenderObject * NodeImpl::nextRenderer()
+{
+ for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
+ if (n->renderer())
+ return n->renderer();
+ }
+ return 0;
+}
+
+void NodeImpl::createRendererIfNeeded()
+{
+#ifdef APPLE_CHANGES
+ if (!getDocument()->shouldCreateRenderers())
+ return;
+#endif
+
+ assert(!m_render);
+
+ NodeImpl *parent = parentNode();
+ assert(parent);
+
+ RenderObject *parentRenderer = parent->renderer();
+ if (parentRenderer && parentRenderer->childAllowed()) {
+ RenderStyle *style = styleForRenderer(parentRenderer);
+ style->ref();
+ if (rendererIsNeeded(style)) {
+ m_render = createRenderer(getDocument()->renderArena(), style);
+ m_render->setStyle(style);
+ parentRenderer->addChild(m_render, nextRenderer());
+ }
+ style->deref();
+ }
+}
+
+RenderStyle *NodeImpl::styleForRenderer(RenderObject *parent)
+{
+ return parent->style();
+}
+
+bool NodeImpl::rendererIsNeeded(RenderStyle *style)
+{
+ return (getDocument()->documentElement() == this) || (style->display() != NONE);
+}
+
+RenderObject *NodeImpl::createRenderer(RenderArena* /*arena*/, RenderStyle* /*style*/)
+{
+ assert(false);
+ return 0;
+}
+
+bool NodeImpl::contentEditable() const
+{
+ RenderObject *r = renderer();
+ if (!r || !r->style()) return false;
+ return r->style()->userInput() == UI_ENABLED;
+}
+
+long NodeImpl::minOffset() const
+{
+ // Arrgh! You'd think *every* offset starts at zero, but loo,
+ // therefore we need this method
+ return renderer() ? renderer()->minOffset() : 0;
+}
+
+long NodeImpl::maxOffset() const
+{
+ return const_cast<NodeImpl *>(this)->childNodeCount();
+// return renderer() ? renderer()->maxOffset() : 1;
+}
+
+DOMStringImpl* NodeImpl::textContent() const
+{
+ TQString out;
+ for (NodeImpl *child = firstChild(); child != 0; child = child->nextSibling()) {
+ short type = child->nodeType();
+ if (type != Node::COMMENT_NODE && type != Node::PROCESSING_INSTRUCTION_NODE) {
+ DOMStringImpl* kidText = child->textContent();
+ if (kidText)
+ out += TQConstString(kidText->s, kidText->l).string();
+ delete kidText;
+ }
+ }
+ return new DOMStringImpl(out.unicode(), out.length());
+}
+
+//-------------------------------------------------------------------------
+
+NodeBaseImpl::~NodeBaseImpl()
+{
+ //kdDebug( 6020 ) << "NodeBaseImpl destructor" << endl;
+ // we have to tell all children, that the parent has died...
+ NodeImpl *n;
+ NodeImpl *next;
+
+ for( n = _first; n != 0; n = next ) {
+ next = n->nextSibling();
+ n->setPreviousSibling(0);
+ n->setNextSibling(0);
+ n->setParent(0);
+ if ( !n->refCount() )
+ delete n;
+ }
+}
+
+
+NodeImpl *NodeBaseImpl::firstChild() const
+{
+ return _first;
+}
+
+NodeImpl *NodeBaseImpl::lastChild() const
+{
+ return _last;
+}
+
+NodeImpl *NodeBaseImpl::insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // insertBefore(...,null) is equivalent to appendChild()
+ if(!refChild)
+ return appendChild(newChild, exceptioncode);
+
+ // Make sure adding the new child is ok
+ checkAddChild(newChild, exceptioncode);
+ if (exceptioncode)
+ return 0;
+
+ // NOT_FOUND_ERR: Raised if refChild is not a child of this node
+ if (refChild->parentNode() != this) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return 0;
+ }
+
+ bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
+
+ // If newChild is a DocumentFragment with no children.... there's nothing to do.
+ // Just return the document fragment
+ if (isFragment && !newChild->firstChild())
+ return newChild;
+
+ // Now actually add the child(ren)
+ NodeImpl *nextChild;
+ NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
+
+ NodeImpl *prev = refChild->previousSibling();
+ if ( prev == newChild || refChild == newChild ) // nothing to do
+ return newChild;
+
+ while (child) {
+ nextChild = isFragment ? child->nextSibling() : 0;
+
+ // If child is already present in the tree, first remove it
+ NodeImpl *newParent = child->parentNode();
+
+ //...guard it in case we need to move it..
+ SharedPtr<NodeImpl> guard(child);
+
+ if(newParent)
+ newParent->removeChild( child, exceptioncode );
+ if ( exceptioncode )
+ return 0;
+
+ // Add child in the correct position
+ if (prev)
+ prev->setNextSibling(child);
+ else
+ _first = child;
+ refChild->setPreviousSibling(child);
+ child->setParent(this);
+ child->setPreviousSibling(prev);
+ child->setNextSibling(refChild);
+
+ // Add child to the rendering tree
+ // ### should we detach() it first if it's already attached?
+ if (attached() && !child->attached())
+ child->attach();
+
+ // Dispatch the mutation events
+ dispatchChildInsertedEvents(child,exceptioncode);
+
+ prev = child;
+ child = nextChild;
+ }
+
+ structureChanged();
+
+ // ### set style in case it's attached
+ dispatchSubtreeModifiedEvent();
+ return newChild;
+}
+
+void NodeBaseImpl::replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ if ( oldChild == newChild ) // nothing to do
+ return;
+
+ // Make sure adding the new child is ok
+ checkAddChild(newChild, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
+ if (!oldChild || oldChild->parentNode() != this) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
+ NodeImpl *nextChild;
+ NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
+
+
+ // Remove the old child
+ NodeImpl *prev = oldChild->previousSibling();
+ NodeImpl *next = oldChild->nextSibling();
+
+ removeChild(oldChild, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ // Add the new child(ren)
+ while (child) {
+ nextChild = isFragment ? child->nextSibling() : 0;
+
+ // If child is already present in the tree, first remove it
+ NodeImpl *newParent = child->parentNode();
+ if ( child == next )
+ next = child->nextSibling();
+ if ( child == prev )
+ prev = child->previousSibling();
+ //...guard it in case we need to move it..
+ SharedPtr<NodeImpl> guard(child);
+ if(newParent)
+ newParent->removeChild( child, exceptioncode );
+ if (exceptioncode)
+ return;
+
+ // Add child in the correct position
+ if (prev) prev->setNextSibling(child);
+ if (next) next->setPreviousSibling(child);
+ if(!prev) _first = child;
+ if(!next) _last = child;
+ child->setParent(this);
+ child->setPreviousSibling(prev);
+ child->setNextSibling(next);
+
+ // Add child to the rendering tree
+ // ### should we detach() it first if it's already attached?
+ if (attached() && !child->attached())
+ child->attach();
+
+ // Dispatch the mutation events
+ dispatchChildInsertedEvents(child,exceptioncode);
+
+ prev = child;
+ child = nextChild;
+ }
+
+ structureChanged();
+
+ // ### set style in case it's attached
+ dispatchSubtreeModifiedEvent();
+ return;
+}
+
+void NodeBaseImpl::removeChild ( NodeImpl *oldChild, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ // NOT_FOUND_ERR: Raised if oldChild is not a child of this node.
+ if (!oldChild || oldChild->parentNode() != this) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return;
+ }
+
+ dispatchChildRemovalEvents(oldChild,exceptioncode);
+ if (exceptioncode)
+ return;
+
+ SharedPtr<NodeImpl> memManage(oldChild); //Make sure to free if needed
+
+ // Remove from rendering tree
+ if (oldChild->attached())
+ oldChild->detach();
+
+ // Remove the child
+ NodeImpl *prev, *next;
+ prev = oldChild->previousSibling();
+ next = oldChild->nextSibling();
+
+ if(next) next->setPreviousSibling(prev);
+ if(prev) prev->setNextSibling(next);
+ if(_first == oldChild) _first = next;
+ if(_last == oldChild) _last = prev;
+
+ oldChild->setPreviousSibling(0);
+ oldChild->setNextSibling(0);
+ oldChild->setParent(0);
+
+ structureChanged();
+
+ // Dispatch post-removal mutation events
+ dispatchSubtreeModifiedEvent();
+
+ NodeImpl *p = this;
+ while (p->parentNode())
+ p = p->parentNode();
+ if (p->nodeType() == Node::DOCUMENT_NODE) {
+ for (NodeImpl *c = oldChild; c; c = c->traverseNextNode(oldChild))
+ c->removedFromDocument();
+ }
+}
+
+void NodeBaseImpl::removeChildren()
+{
+ bool inDoc = inDocument();
+ NodeImpl *n, *next;
+ for( n = _first, _first = 0; n; n = next )
+ {
+ next = n->nextSibling();
+ if (n->attached())
+ n->detach();
+ n->setPreviousSibling(0);
+ n->setNextSibling(0);
+ n->setParent(0);
+
+ if ( inDoc )
+ for ( NodeImpl* c = n; c; c = c->traverseNextNode( n ) )
+ c->removedFromDocument();
+
+ if( !n->refCount() )
+ delete n;
+ }
+ _last = 0;
+}
+
+
+NodeImpl *NodeBaseImpl::appendChild ( NodeImpl *newChild, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // Make sure adding the new child is ok
+ checkAddChild(newChild, exceptioncode);
+ if (exceptioncode)
+ return 0;
+
+ if ( newChild == _last ) // nothing to do
+ return newChild;
+
+ bool isFragment = newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE;
+
+ // If newChild is a DocumentFragment with no children.... there's nothing to do.
+ // Just return the document fragment
+ if (isFragment && !newChild->firstChild())
+ return newChild;
+
+ // Now actually add the child(ren)
+ NodeImpl *nextChild;
+ NodeImpl *child = isFragment ? newChild->firstChild() : newChild;
+
+ while (child) {
+ nextChild = isFragment ? child->nextSibling() : 0;
+
+ // If child is already present in the tree, first remove it
+ NodeImpl *oldParent = child->parentNode();
+ SharedPtr<NodeImpl> guard(child); //Guard in case we move it
+ if(oldParent) {
+ oldParent->removeChild( child, exceptioncode );
+ if (exceptioncode)
+ return 0;
+ }
+
+ // Append child to the end of the list
+ child->setParent(this);
+
+ if(_last)
+ {
+ child->setPreviousSibling(_last);
+ _last->setNextSibling(child);
+ _last = child;
+ }
+ else
+ {
+ _first = _last = child;
+ }
+
+ // Add child to the rendering tree
+ // ### should we detach() it first if it's already attached?
+ if (attached() && !child->attached())
+ child->attach();
+
+ // Dispatch the mutation events
+ dispatchChildInsertedEvents(child,exceptioncode);
+
+ child = nextChild;
+ }
+
+ backwardsStructureChanged();
+
+ // ### set style in case it's attached
+ dispatchSubtreeModifiedEvent();
+ return newChild;
+}
+
+bool NodeBaseImpl::hasChildNodes ( ) const
+{
+ return _first != 0;
+}
+
+// not part of the DOM
+void NodeBaseImpl::setFirstChild(NodeImpl *child)
+{
+ _first = child;
+}
+
+void NodeBaseImpl::setLastChild(NodeImpl *child)
+{
+ _last = child;
+}
+
+// check for same source document:
+bool NodeBaseImpl::checkSameDocument( NodeImpl *newChild, int &exceptioncode )
+{
+ exceptioncode = 0;
+ DocumentImpl *ownerDocThis = getDocument();
+ DocumentImpl *ownerDocNew = newChild->getDocument();
+ if(ownerDocThis != ownerDocNew) {
+ kdDebug(6010)<< "not same document, newChild = " << newChild << "document = " << getDocument() << endl;
+ exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+ return true;
+ }
+ return false;
+}
+
+// check for being child:
+bool NodeBaseImpl::checkIsChild( NodeImpl *oldChild, int &exceptioncode )
+{
+ if(!oldChild || oldChild->parentNode() != this) {
+ exceptioncode = DOMException::NOT_FOUND_ERR;
+ return true;
+ }
+ return false;
+}
+
+NodeImpl *NodeBaseImpl::addChild(NodeImpl *newChild)
+{
+ // do not add applyChanges here! This function is only used during parsing
+
+ // short check for consistency with DTD
+ if(getDocument()->isHTMLDocument() && !childAllowed(newChild))
+ {
+ //kdDebug( 6020 ) << "AddChild failed! id=" << id() << ", child->id=" << newChild->id() << endl;
+ return 0;
+ }
+
+ // just add it...
+ newChild->setParent(this);
+
+ if(_last)
+ {
+ newChild->setPreviousSibling(_last);
+ _last->setNextSibling(newChild);
+ _last = newChild;
+ }
+ else
+ {
+ _first = _last = newChild;
+ }
+
+ if (inDocument())
+ newChild->insertedIntoDocument();
+ childrenChanged();
+
+ if(newChild->nodeType() == Node::ELEMENT_NODE)
+ return newChild;
+ return this;
+}
+
+void NodeBaseImpl::attach()
+{
+ NodeImpl *child = _first;
+ while(child != 0)
+ {
+ child->attach();
+ child = child->nextSibling();
+ }
+ NodeImpl::attach();
+}
+
+void NodeBaseImpl::detach()
+{
+ NodeImpl *child = _first;
+ while(child != 0)
+ {
+ NodeImpl* prev = child;
+ child = child->nextSibling();
+ prev->detach();
+ }
+ NodeImpl::detach();
+}
+
+void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
+{
+ int exceptioncode = 0;
+ NodeImpl *n;
+ for(n = firstChild(); n && !exceptioncode; n = n->nextSibling())
+ {
+ clone->appendChild(n->cloneNode(true),exceptioncode);
+ }
+}
+
+// I don't like this way of implementing the method, but I didn't find any
+// other way. Lars
+bool NodeBaseImpl::getUpperLeftCorner(int &xPos, int &yPos) const
+{
+ if (!m_render)
+ return false;
+ RenderObject *o = m_render;
+ xPos = yPos = 0;
+ if ( !o->isInline() || o->isReplaced() ) {
+ o->absolutePosition( xPos, yPos );
+ return true;
+ }
+
+ // find the next text/image child, to get a position
+ while(o) {
+ if(o->firstChild())
+ o = o->firstChild();
+ else if(o->nextSibling())
+ o = o->nextSibling();
+ else {
+ RenderObject *next = 0;
+ while(!next) {
+ o = o->parent();
+ if(!o) return false;
+ next = o->nextSibling();
+ }
+ o = next;
+ }
+ if((o->isText() && !o->isBR()) || o->isReplaced()) {
+ o->container()->absolutePosition( xPos, yPos );
+ if (o->isText()) {
+ xPos += o->inlineXPos();
+ yPos += o->inlineYPos();
+ } else {
+ xPos += o->xPos();
+ yPos += o->yPos();
+ }
+ return true;
+ }
+ }
+ return true;
+}
+
+bool NodeBaseImpl::getLowerRightCorner(int &xPos, int &yPos) const
+{
+ if (!m_render)
+ return false;
+
+ RenderObject *o = m_render;
+ xPos = yPos = 0;
+ if (!o->isInline() || o->isReplaced())
+ {
+ o->absolutePosition( xPos, yPos );
+ xPos += o->width();
+ yPos += o->height() + o->borderTopExtra() + o->borderBottomExtra();
+ return true;
+ }
+ // find the last text/image child, to get a position
+ while(o) {
+ if(o->lastChild())
+ o = o->lastChild();
+ else if(o->previousSibling())
+ o = o->previousSibling();
+ else {
+ RenderObject *prev = 0;
+ while(!prev) {
+ o = o->parent();
+ if(!o) return false;
+ prev = o->previousSibling();
+ }
+ o = prev;
+ }
+ if((o->isText() && !o->isBR()) || o->isReplaced()) {
+ o->container()->absolutePosition(xPos, yPos);
+ if (o->isText()) {
+ xPos += o->inlineXPos() + o->width();
+ yPos += o->inlineYPos() + o->height();
+ } else {
+ xPos += o->xPos() + o->width();
+ yPos += o->yPos() + o->height();
+ }
+ return true;
+ }
+ }
+ return true;
+}
+
+void NodeBaseImpl::setFocus(bool received)
+{
+ if (m_focused == received) return;
+
+ NodeImpl::setFocus(received);
+
+ // note that we need to recalc the style
+ setChanged(); // *:focus is a default style, so we just assume personal dependency
+ if (isElementNode()) {
+ getDocument()->dynamicDomRestyler().restyleDepedent(static_cast<ElementImpl*>(this), OtherStateDependency);
+ }
+}
+
+void NodeBaseImpl::setActive(bool down)
+{
+ if (down == active()) return;
+
+ NodeImpl::setActive(down);
+
+ // note that we need to recalc the style
+ if (isElementNode())
+ getDocument()->dynamicDomRestyler().restyleDepedent(static_cast<ElementImpl*>(this), ActiveDependency);
+}
+
+void NodeBaseImpl::setHovered(bool hover)
+{
+ if (hover == hovered()) return;
+
+ NodeImpl::setHovered(hover);
+
+ // note that we need to recalc the style
+ if (isElementNode())
+ getDocument()->dynamicDomRestyler().restyleDepedent(static_cast<ElementImpl*>(this), HoverDependency);
+}
+
+unsigned long NodeBaseImpl::childNodeCount()
+{
+ unsigned long count = 0;
+ NodeImpl *n;
+ for (n = firstChild(); n; n = n->nextSibling())
+ count++;
+ return count;
+}
+
+NodeImpl *NodeBaseImpl::childNode(unsigned long index)
+{
+ unsigned long i;
+ NodeImpl *n = firstChild();
+ for (i = 0; n && i < index; i++)
+ n = n->nextSibling();
+ return n;
+}
+
+void NodeBaseImpl::dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode )
+{
+ if (getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTED_LISTENER)) {
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTED_EVENT,true,false,this,DOMString(),DOMString(),DOMString(),0);
+ evt->ref();
+ child->dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+ if (exceptioncode)
+ return;
+ }
+
+ // dispatch the DOMNodeInsertedIntoDocument event to all descendants
+ bool hasInsertedListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
+ NodeImpl *p = this;
+ while (p->parentNode())
+ p = p->parentNode();
+ if (p->nodeType() == Node::DOCUMENT_NODE) {
+ for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
+ c->insertedIntoDocument();
+
+ if (hasInsertedListeners) {
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT,false,false,0,DOMString(),DOMString(),DOMString(),0);
+ evt->ref();
+ c->dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+ if (exceptioncode)
+ return;
+ }
+ }
+ }
+}
+
+void NodeBaseImpl::dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode )
+{
+ // Dispatch pre-removal mutation events
+ getDocument()->notifyBeforeNodeRemoval(child); // ### use events instead
+ if (getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVED_LISTENER)) {
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVED_EVENT,true,false,this,DOMString(),DOMString(),DOMString(),0);
+ evt->ref();
+ child->dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+ if (exceptioncode)
+ return;
+ }
+
+ bool hasRemovalListeners = getDocument()->hasListenerType(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
+
+ // dispatch the DOMNodeRemovedFromDocument event to all descendants
+ NodeImpl *p = this;
+ while (p->parentNode())
+ p = p->parentNode();
+ if (p->nodeType() == Node::DOCUMENT_NODE) {
+ for (NodeImpl *c = child; c; c = c->traverseNextNode(child)) {
+ if (hasRemovalListeners) {
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT,false,false,0,DOMString(),DOMString(),DOMString(),0);
+ evt->ref();
+ c->dispatchEvent(evt,exceptioncode,true);
+ evt->deref();
+ if (exceptioncode)
+ return;
+ }
+ }
+ }
+}
+
+void NodeBaseImpl::setTextContent( const DOMString &text, int& exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ removeChildren();
+
+ if ( !text.isEmpty() && !text.isNull() ) {
+ TextImpl *t = new TextImpl( docPtr(), text.implementation() );
+ appendChild( t, exceptioncode );
+ }
+}
+
+// ---------------------------------------------------------------------------
+NodeImpl *NodeListImpl::item( unsigned long index ) const
+{
+ unsigned long requestIndex = index;
+
+ m_cache->updateNodeListInfo(m_refNode->getDocument());
+
+ NodeImpl* n;
+ bool usedCache = false;
+ if (m_cache->current.node) {
+ //Compute distance from the requested index to the cache node
+ long cacheDist = QABS(long(index) - long(m_cache->position));
+
+ if (cacheDist < (long)index) { //Closer to the cached position
+ usedCache = true;
+ if (index >= m_cache->position) { //Go ahead
+ unsigned long relIndex = index - m_cache->position;
+ n = recursiveItem(m_refNode, m_cache->current.node, relIndex);
+ } else { //Go backwards
+ unsigned long relIndex = m_cache->position - index;
+ n = recursiveItemBack(m_refNode, m_cache->current.node, relIndex);
+ }
+ }
+ }
+
+ if (!usedCache)
+ n = recursiveItem(m_refNode, m_refNode->firstChild(), index);
+
+ //We always update the cache state, to make starting iteration
+ //where it was left off easy.
+ m_cache->current.node = n;
+ m_cache->position = requestIndex;
+ return n;
+}
+
+unsigned long NodeListImpl::length() const
+{
+ m_cache->updateNodeListInfo(m_refNode->getDocument());
+ if (!m_cache->hasLength) {
+ m_cache->length = calcLength( m_refNode );
+ m_cache->hasLength = true;
+ }
+ return m_cache->length;
+}
+
+unsigned long NodeListImpl::calcLength(NodeImpl *start) const
+{
+ unsigned long len = 0;
+ for(NodeImpl *n = start->firstChild(); n != 0; n = n->nextSibling()) {
+ bool recurse = true;
+ if (nodeMatches(n, recurse))
+ len++;
+ if (recurse)
+ len+= NodeListImpl::calcLength(n);
+ }
+
+ return len;
+}
+
+NodeListImpl::NodeListImpl( NodeImpl *n, int type, CacheFactory* factory )
+{
+ m_refNode = n;
+ m_refNode->ref();
+
+ m_cache = m_refNode->getDocument()->acquireCachedNodeListInfo(
+ factory ? factory : Cache::make,
+ n, type );
+}
+
+NodeListImpl::~NodeListImpl()
+{
+ m_refNode->getDocument()->releaseCachedNodeListInfo(m_cache);
+ m_refNode->deref();
+}
+
+
+/**
+ Next item in the pre-order walk of tree from node, but not going outside
+ absStart
+*/
+static NodeImpl* helperNext(NodeImpl* node, NodeImpl* absStart)
+{
+ //Walk up until we wind a sibling to go to.
+ while (!node->nextSibling() && node != absStart)
+ node = node->parentNode();
+
+ if (node != absStart)
+ return node->nextSibling();
+ else
+ return 0;
+}
+
+NodeImpl *NodeListImpl::recursiveItem ( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const
+{
+ for(NodeImpl *n = start; n != 0; n = helperNext(n, absStart)) {
+ bool recurse = true;
+ if (nodeMatches(n, recurse))
+ if (!offset--)
+ return n;
+
+ NodeImpl *depthSearch = recurse ? recursiveItem(n, n->firstChild(), offset) : 0;
+ if (depthSearch)
+ return depthSearch;
+ }
+
+ return 0; // no matching node in this subtree
+}
+
+
+NodeImpl *NodeListImpl::recursiveItemBack ( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const
+{
+ //### it might be cleaner/faster to split nodeMatches and recursion
+ //filtering.
+ bool dummy = true;
+ NodeImpl* n = start;
+
+ do {
+ bool recurse = true;
+
+ //Check whether the current node matches.
+ if (nodeMatches(n, dummy))
+ if (!offset--)
+ return n;
+
+ if (n->previousSibling()) {
+ //Move to the last node of this whole subtree that we should recurse into
+ n = n->previousSibling();
+ recurse = true;
+
+ while (n->lastChild()) {
+ (void)nodeMatches(n, recurse);
+ if (!recurse)
+ break; //Don't go there
+ n = n->lastChild();
+ }
+ } else {
+ //We're done with this whole subtree, so move up
+ n = n->parentNode();
+ }
+ }
+ while (n && n != absStart);
+
+ return 0;
+}
+
+
+NodeListImpl::Cache::~Cache()
+{}
+
+void NodeListImpl::Cache::clear(DocumentImpl* doc)
+{
+ hasLength = false;
+ current.node = 0;
+ version = doc->domTreeVersion();
+}
+
+void NodeListImpl::Cache::updateNodeListInfo(DocumentImpl* doc)
+{
+ //If version doesn't match, clear
+ if (doc->domTreeVersion() != version)
+ clear(doc);
+}
+
+ChildNodeListImpl::ChildNodeListImpl( NodeImpl *n ): NodeListImpl(n, CHILD_NODES)
+{}
+
+bool ChildNodeListImpl::nodeMatches( NodeImpl* /*testNode*/, bool& doRecurse ) const
+{
+ doRecurse = false;
+ return true;
+}
+
+TagNodeListImpl::TagNodeListImpl( NodeImpl *n, NodeImpl::Id id )
+ : NodeListImpl(n, UNCACHEABLE),
+ m_id(id),
+ m_namespaceAware(false)
+{
+ // An id of 0 here means "*" (match all nodes)
+ m_matchAllNames = (id == 0);
+ m_matchAllNamespaces = false;
+}
+
+TagNodeListImpl::TagNodeListImpl( NodeImpl *n, const DOMString &namespaceURI, const DOMString &localName )
+ : NodeListImpl(n, UNCACHEABLE),
+ m_id(0),
+ m_namespaceURI(namespaceURI),
+ m_localName(localName),
+ m_namespaceAware(true)
+{
+ m_matchAllNames = (localName == "*");
+ m_matchAllNamespaces = (namespaceURI == "*");
+}
+
+
+bool TagNodeListImpl::nodeMatches( NodeImpl *testNode, bool& /*doRecurse*/ ) const
+{
+ if ( testNode->nodeType() != Node::ELEMENT_NODE ) return false;
+ if (m_namespaceAware)
+ return (m_matchAllNamespaces || testNode->namespaceURI() == m_namespaceURI) &&
+ (m_matchAllNames || testNode->localName() == m_localName);
+ else {
+ NodeImpl::Id testId = testNode->id();
+ //we have to strip the namespaces if we compare in a namespace unaware fashion
+ if ( !m_namespaceAware ) testId = localNamePart(testId);
+ return (m_id == 0 || m_id == testId);
+ }
+}
+
+NameNodeListImpl::NameNodeListImpl(NodeImpl *n, const DOMString &t )
+ : NodeListImpl(n, UNCACHEABLE),
+ nodeName(t)
+{}
+
+bool NameNodeListImpl::nodeMatches( NodeImpl *testNode, bool& /*doRecurse*/ ) const
+{
+ if ( testNode->nodeType() != Node::ELEMENT_NODE ) return false;
+ return static_cast<ElementImpl *>(testNode)->getAttribute(ATTR_NAME) == nodeName;
+}
+
+// ---------------------------------------------------------------------------
+
+NamedNodeMapImpl::NamedNodeMapImpl()
+{
+}
+
+NamedNodeMapImpl::~NamedNodeMapImpl()
+{
+}
+
+// ----------------------------------------------------------------------------
+
+GenericRONamedNodeMapImpl::GenericRONamedNodeMapImpl(DocumentImpl* doc)
+ : NamedNodeMapImpl()
+{
+ m_doc = doc;
+ m_contents = new TQPtrList<NodeImpl>;
+}
+
+GenericRONamedNodeMapImpl::~GenericRONamedNodeMapImpl()
+{
+ while (!m_contents->isEmpty())
+ m_contents->take(0)->deref();
+
+ delete m_contents;
+}
+
+NodeImpl *GenericRONamedNodeMapImpl::getNamedItem ( NodeImpl::Id id, bool /*nsAware*/, DOMStringImpl* /*qName*/ ) const
+{
+ // ## do we need namespace support in this class?
+ TQPtrListIterator<NodeImpl> it(*m_contents);
+ for (; it.current(); ++it)
+ if (it.current()->id() == id)
+ return it.current();
+ return 0;
+}
+
+Node GenericRONamedNodeMapImpl::setNamedItem ( NodeImpl* /*arg*/, bool /*nsAware*/, DOMStringImpl* /*qName*/, int &exceptioncode )
+{
+ // can't modify this list through standard DOM functions
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+}
+
+Node GenericRONamedNodeMapImpl::removeNamedItem ( NodeImpl::Id /*id*/, bool /*nsAware*/, DOMStringImpl* /*qName*/, int &exceptioncode )
+{
+ // can't modify this list through standard DOM functions
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+}
+
+NodeImpl *GenericRONamedNodeMapImpl::item ( unsigned long index ) const
+{
+ if (index >= m_contents->count())
+ return 0;
+
+ return m_contents->at(index);
+}
+
+unsigned long GenericRONamedNodeMapImpl::length( ) const
+{
+ return m_contents->count();
+}
+
+void GenericRONamedNodeMapImpl::addNode(NodeImpl *n)
+{
+ // The spec says that in the case of duplicates we only keep the first one
+ if (getNamedItem(n->id(), false, 0))
+ return;
+
+ n->ref();
+ m_contents->append(n);
+}
+
+NodeImpl::Id GenericRONamedNodeMapImpl::mapId(DOMStringImpl* namespaceURI,
+ DOMStringImpl* localName, bool readonly)
+{
+ if (!m_doc)
+ return 0;
+
+ return m_doc->getId(NodeImpl::ElementId,
+ namespaceURI, 0, localName, readonly,
+ false /*don't lookupHTML*/);
+}
+
+// -----------------------------------------------------------------------------
+
+void RegisteredListenerList::addEventListener(int id, EventListener *listener, const bool useCapture)
+{
+ RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
+ if (!listeners)
+ listeners = new TQValueList<RegisteredEventListener>;
+
+ // if this id/listener/useCapture combination is already registered, do nothing.
+ // the DOM2 spec says that "duplicate instances are discarded", and this keeps
+ // the listener order intact.
+ TQValueList<RegisteredEventListener>::iterator it;
+ for (it = listeners->begin(); it != listeners->end(); ++it)
+ if (*it == rl)
+ return;
+
+ listeners->append(rl);
+}
+
+void RegisteredListenerList::removeEventListener(int id, EventListener *listener, bool useCapture)
+{
+ if (!listeners) // nothing to remove
+ return;
+
+ RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,useCapture);
+
+ TQValueList<RegisteredEventListener>::iterator it;
+ for (it = listeners->begin(); it != listeners->end(); ++it)
+ if (*it == rl) {
+ listeners->remove(it);
+ return;
+ }
+}
+
+bool RegisteredListenerList::isHTMLEventListener(EventListener* listener)
+{
+ return (listener->eventListenerType() == "_tdehtml_HTMLEventListener");
+}
+
+void RegisteredListenerList::setHTMLEventListener(int id, EventListener *listener)
+{
+ if (!listeners)
+ listeners = new TQValueList<RegisteredEventListener>;
+
+ TQValueList<RegisteredEventListener>::iterator it;
+ if (!listener) {
+ for (it = listeners->begin(); it != listeners->end(); ++it) {
+ if ((*it).id == id && isHTMLEventListener((*it).listener)) {
+ listeners->remove(it);
+ break;
+ }
+ }
+ return;
+ }
+
+ // if this event already has a registered handler, insert the new one in
+ // place of the old one, to preserve the order.
+ RegisteredEventListener rl(static_cast<EventImpl::EventId>(id),listener,false);
+
+ int i;
+ for (i = 0, it = listeners->begin(); it != listeners->end(); ++it, ++i)
+ if ((*it).id == id && isHTMLEventListener((*it).listener)) {
+ listeners->insert(it, rl);
+ listeners->remove(it);
+ return;
+ }
+
+ listeners->append(rl);
+}
+
+EventListener *RegisteredListenerList::getHTMLEventListener(int id)
+{
+ if (!listeners)
+ return 0;
+
+ TQValueList<RegisteredEventListener>::iterator it;
+ for (it = listeners->begin(); it != listeners->end(); ++it)
+ if ((*it).id == id && isHTMLEventListener((*it).listener)) {
+ return (*it).listener;
+ }
+ return 0;
+}
+
+bool RegisteredListenerList::hasEventListener(int id)
+{
+ if (!listeners)
+ return false;
+
+ TQValueList<RegisteredEventListener>::iterator it;
+ for (it = listeners->begin(); it != listeners->end(); ++it)
+ if ((*it).id == id)
+ return true;
+
+ return false;
+}
+
+void RegisteredListenerList::clear()
+{
+ delete listeners;
+ listeners = 0;
+}
+
+bool RegisteredListenerList::stillContainsListener(const RegisteredEventListener& listener)
+{
+ if (!listeners)
+ return false;
+ return listeners->find(listener) != listeners->end();
+}
+
+RegisteredListenerList::~RegisteredListenerList() {
+ delete listeners; listeners = 0;
+}
diff --git a/tdehtml/xml/dom_nodeimpl.h b/tdehtml/xml/dom_nodeimpl.h
new file mode 100644
index 000000000..c01e69c0a
--- /dev/null
+++ b/tdehtml/xml/dom_nodeimpl.h
@@ -0,0 +1,736 @@
+/*
+ * 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) 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 _DOM_NodeImpl_h_
+#define _DOM_NodeImpl_h_
+
+#include "dom/dom_misc.h"
+#include "dom/dom_string.h"
+#include "dom/dom_node.h"
+#include "misc/helper.h"
+#include "misc/shared.h"
+
+// The namespace used for XHTML elements
+#define XHTML_NAMESPACE "http://www.w3.org/1999/xhtml"
+
+class TQPainter;
+template <class type> class TQPtrList;
+template <class type> class TQValueList;
+class KHTMLView;
+class TQRect;
+class TQMouseEvent;
+class TQKeyEvent;
+class TQTextStream;
+
+namespace tdehtml {
+ class RenderStyle;
+ class RenderObject;
+ class RenderArena;
+}
+
+namespace DOM {
+
+class NodeListImpl;
+class NamedNodeMapImpl;
+class DocumentImpl;
+class CSSStyleDeclarationImpl;
+class RegisteredEventListener;
+class EventImpl;
+
+struct RegisteredListenerList {
+ RegisteredListenerList() : listeners(0)
+ {}
+
+ ~RegisteredListenerList();
+
+ void addEventListener(int id, EventListener *listener, const bool useCapture);
+ void removeEventListener(int id, EventListener *listener, bool useCapture);
+
+ void setHTMLEventListener(int id, EventListener *listener);
+ EventListener *getHTMLEventListener(int id);
+
+ bool hasEventListener(int id);
+ void clear();
+
+ //### KDE4: should disappear
+ bool stillContainsListener(const RegisteredEventListener& listener);
+
+ TQValueList<RegisteredEventListener>* listeners;//The actual listener list - may be 0
+private:
+ bool isHTMLEventListener(EventListener* listener);
+};
+
+
+// this class implements nodes, which can have a parent but no children:
+#define NodeImpl_IdNSMask 0xffff0000
+#define NodeImpl_IdLocalMask 0x0000ffff
+
+const TQ_UINT16 defaultNamespace = 0;
+const TQ_UINT16 xhtmlNamespace = 1;
+const TQ_UINT16 emptyNamespace = 2;
+const TQ_UINT16 anyNamespace = 0xffff;
+const TQ_UINT16 anyLocalName = 0xffff;
+
+inline TQ_UINT16 localNamePart(TQ_UINT32 id) { return id & NodeImpl_IdLocalMask; }
+inline TQ_UINT16 namespacePart(TQ_UINT32 id) { return (((unsigned int)id) & NodeImpl_IdNSMask) >> 16; }
+inline TQ_UINT32 makeId(TQ_UINT16 n, TQ_UINT16 l) { return (n << 16) | l; }
+
+const TQ_UINT32 anyQName = makeId(anyNamespace, anyLocalName);
+
+class NodeImpl : public tdehtml::TreeShared<NodeImpl>
+{
+ friend class DocumentImpl;
+public:
+ NodeImpl(DocumentImpl *doc);
+ virtual ~NodeImpl();
+
+ // DOM methods & attributes for Node
+ virtual DOMString nodeName() const;
+ virtual DOMString nodeValue() const;
+ virtual void setNodeValue( const DOMString &_nodeValue, int &exceptioncode );
+ virtual unsigned short nodeType() const;
+ NodeImpl *parentNode() const { return m_parent; }
+ NodeImpl *previousSibling() const { return m_previous; }
+ NodeImpl *nextSibling() const { return m_next; }
+ virtual NodeListImpl *childNodes();
+ virtual NodeImpl *firstChild() const;
+ virtual NodeImpl *lastChild() const;
+ // insertBefore, replaceChild and appendChild also close newChild
+ // unlike the speed optimized addChild (which is used by the parser)
+ virtual NodeImpl *insertBefore ( NodeImpl *newChild, NodeImpl *refChild, int &exceptioncode );
+
+ /* These two methods may delete the old node, so make sure to reference it if you need it */
+ virtual void replaceChild ( NodeImpl *newChild, NodeImpl *oldChild, int &exceptioncode );
+ virtual void removeChild ( NodeImpl *oldChild, int &exceptioncode );
+ virtual NodeImpl *appendChild ( NodeImpl *newChild, int &exceptioncode );
+ virtual bool hasChildNodes ( ) const;
+ virtual NodeImpl *cloneNode ( bool deep ) = 0;
+ virtual DOMString localName() const;
+ virtual DOMString prefix() const;
+ virtual DOMString namespaceURI() const;
+ virtual void setPrefix(const DOMString &_prefix, int &exceptioncode );
+ void normalize ();
+
+ // Other methods (not part of DOM)
+ virtual bool isElementNode() const { return false; }
+ virtual bool isHTMLElement() const { return false; }
+ virtual bool isAttributeNode() const { return false; }
+ virtual bool isTextNode() const { return false; }
+ virtual bool isDocumentNode() const { return false; }
+ virtual bool isXMLElementNode() const { return false; }
+ virtual bool isGenericFormElement() const { return false; }
+ virtual bool containsOnlyWhitespace() const { return false; }
+ virtual bool contentEditable() const;
+
+ // helper functions not being part of the DOM
+ // Attention: they assume that the caller did the consistency checking!
+ void setPreviousSibling(NodeImpl *previous) { m_previous = previous; }
+ void setNextSibling(NodeImpl *next) { m_next = next; }
+
+ virtual void setFirstChild(NodeImpl *child);
+ virtual void setLastChild(NodeImpl *child);
+
+ // used by the parser. Doesn't do as many error checkings as
+ // appendChild(), and returns the node into which will be parsed next.
+ virtual NodeImpl *addChild(NodeImpl *newChild);
+
+ typedef TQ_UINT32 Id;
+ // id() is used to easily and exactly identify a node. It
+ // is optimized for quick comparison and low memory consumption.
+ // its value depends on the owner document of the node and is
+ // categorized in the following way:
+ // 1..ID_LAST_TAG: the node inherits HTMLElementImpl and is
+ // part of the HTML namespace.
+ // The HTML namespace is either the global
+ // one (no namespace) or the XHTML namespace
+ // depending on the owner document's doctype
+ // ID_LAST_TAG+1..0xffff: non-HTML elements in the global namespace
+ // others non-HTML elements in a namespace.
+ // the upper 16 bit identify the namespace
+ // the lower 16 bit identify the local part of the
+ // qualified element name.
+ virtual Id id() const { return 0; }
+
+ // These are the DOM 3 Core answer to innerText/setInnerText, and are used
+ // quite a bit since Mozilla doesn't do innerText. They do, however, behave slightly
+ // differently. The default implementation is for ELEMENT_NODE, ATTRIBUTE_NODE,
+ // ENTITY_NODE, ENTITY_REFERENCE_NODE, DOCUMENT_FRAGMENT_NODE.
+ virtual DOMStringImpl* textContent() const;
+ virtual void setTextContent( const DOMString &text, int& exceptioncode ) = 0;
+
+ enum IdType {
+ AttributeId,
+ ElementId,
+ NamespaceId
+ };
+
+ enum MouseEventType {
+ MousePress,
+ MouseRelease,
+ MouseClick,
+ MouseDblClick,
+ MouseMove
+ };
+
+ struct MouseEvent
+ {
+ MouseEvent( int _button, MouseEventType _type,
+ const DOMString &_url = DOMString(), const DOMString& _target = DOMString(),
+ NodeImpl *_innerNode = 0, NodeImpl *_innerNonSharedNode = 0)
+ {
+ button = _button; type = _type;
+ url = _url; target = _target;
+ innerNode = _innerNode;
+ innerNonSharedNode = _innerNonSharedNode;
+ }
+
+ int button;
+ MouseEventType type;
+ DOMString url; // url under mouse or empty
+ DOMString target;
+ Node innerNode;
+ Node innerNonSharedNode;
+ };
+
+ // for LINK and STYLE
+ virtual void sheetLoaded() {}
+
+ bool hasID() const { return m_hasId; }
+ bool hasClass() const { return m_hasClass; }
+ bool active() const { return m_active; }
+ bool focused() const { return m_focused; }
+ bool hovered() const { return m_hovered; }
+ bool attached() const { return m_attached; }
+ bool closed() const { return m_closed; }
+ bool changed() const { return m_changed; }
+ bool hasChangedChild() const { return m_hasChangedChild; }
+ bool hasAnchor() const { return m_hasAnchor; }
+ bool inDocument() const { return m_inDocument; }
+ bool implicitNode() const { return m_implicit; }
+ bool htmlCompat() const { return m_htmlCompat; }
+ void setHasID(bool b=true) { m_hasId = b; }
+ void setHasClass(bool b=true) { m_hasClass = b; }
+ void setHasChangedChild( bool b = true ) { m_hasChangedChild = b; }
+ void setInDocument(bool b=true) { m_inDocument = b; }
+ void setHTMLCompat(bool b) { m_htmlCompat = b; }
+ virtual void setFocus(bool b=true) { m_focused = b; }
+ virtual void setActive(bool b=true) { m_active = b; }
+ virtual void setHovered(bool b=true) { m_hovered = b; }
+ virtual void setChanged(bool b=true);
+
+ // for descending restyle when ID or CLASS changes
+ bool changedAscendentAttribute() const { return m_changedAscendentAttribute; }
+ void setChangedAscendentAttribute(bool b) { m_changedAscendentAttribute = b; }
+
+ // for style selection performance: whether the element matches several CSS Classes
+ bool hasClassList() const { return m_hasClassList; }
+ void setHasClassList(bool b) { m_hasClassList = b; }
+
+ unsigned short tabIndex() const { return m_tabIndex; }
+ void setTabIndex(unsigned short _tabIndex) { m_tabIndex = _tabIndex; }
+
+ virtual bool isFocusable() const { return false; }
+ virtual bool isMouseFocusable() const { return isFocusable(); }
+ virtual bool isTabFocusable() const { return isFocusable(); }
+
+ virtual bool isInline() const;
+
+ virtual void getCaret(int offset, bool override, int &_x, int &_y, int &width, int &height);
+ virtual TQRect getRect() const;
+
+ enum StyleChange { NoChange, NoInherit, Inherit, Detach, Force };
+ virtual void recalcStyle( StyleChange = NoChange ) {}
+ static StyleChange diff( tdehtml::RenderStyle *s1, tdehtml::RenderStyle *s2 );
+ static bool pseudoDiff( tdehtml::RenderStyle *s1, tdehtml::RenderStyle *s2, unsigned int pid);
+
+ unsigned long nodeIndex() const;
+ // Returns the document that this node is associated with. This is guaranteed to always be non-null, as opposed to
+ // DOM's ownerDocument() which is null for Document nodes (and sometimes DocumentType nodes).
+ DocumentImpl* getDocument() const { return m_document.get(); }
+
+ void addEventListener(int id, EventListener *listener, const bool useCapture);
+ void removeEventListener(int id, EventListener *listener, bool useCapture);
+ void setHTMLEventListener(int id, EventListener *listener);
+ EventListener *getHTMLEventListener(int id);
+
+ void dispatchEvent(EventImpl *evt, int &exceptioncode, bool tempEvent = false);
+ void dispatchGenericEvent( EventImpl *evt, int &exceptioncode);
+ // return true if event not prevented
+ bool dispatchHTMLEvent(int _id, bool canBubbleArg, bool cancelableArg);
+ void dispatchWindowEvent(int _id, bool canBubbleArg, bool cancelableArg);
+ void dispatchMouseEvent(TQMouseEvent *e, int overrideId = 0, int overrideDetail = 0);
+ void dispatchUIEvent(int _id, int detail = 0);
+ void dispatchSubtreeModifiedEvent();
+ // return true if defaultPrevented (i.e. event should be swallowed)
+ // this matches the logic in KHTMLView.
+ bool dispatchKeyEvent(TQKeyEvent *key, bool keypress);
+
+ void handleLocalEvents(EventImpl *evt, bool useCapture);
+
+ /**
+ * Perform the default action for an event e.g. submitting a form
+ */
+ virtual void defaultEventHandler(EventImpl *evt);
+
+ virtual bool isReadOnly();
+ virtual bool childTypeAllowed( unsigned short /*type*/ ) { return false; }
+ virtual unsigned long childNodeCount();
+ virtual NodeImpl *childNode(unsigned long index);
+
+ /**
+ * Does a pre-order traversal of the tree to find the node next node after this one. This uses the same order that
+ * the tags appear in the source file.
+ *
+ * @param stayWithin If not null, the traversal will stop once the specified node is reached. This can be used to
+ * restrict traversal to a particular sub-tree.
+ *
+ * @return The next node, in document order
+ *
+ * see traversePreviousNode()
+ */
+ NodeImpl *traverseNextNode(NodeImpl *stayWithin = 0) const;
+
+ /**
+ * Does a reverse pre-order traversal to find the node that comes before the current one in document order
+ *
+ * see traverseNextNode()
+ */
+ NodeImpl *traversePreviousNode() const;
+
+ DocumentImpl *docPtr() const { return m_document.get(); }
+
+ tdehtml::RenderObject *renderer() const { return m_render; }
+ tdehtml::RenderObject *nextRenderer();
+ tdehtml::RenderObject *previousRenderer();
+ void setRenderer(tdehtml::RenderObject* renderer) { m_render = renderer; }
+
+ void checkSetPrefix(const DOMString &_prefix, int &exceptioncode);
+ void checkAddChild(NodeImpl *newChild, int &exceptioncode);
+ bool isAncestor( NodeImpl *other );
+ virtual bool childAllowed( NodeImpl *newChild );
+
+ /**
+ * Returns the minimum caret offset that is allowed for this node.
+ *
+ * This default implementation always returns 0. Textual child nodes
+ * may return other values.
+ */
+ virtual long minOffset() const;
+ /**
+ * Returns the maximum caret offset that is allowed for this node.
+ *
+ * This default implementation always returns the node count.
+ * Textual child nodes return the character count instead.
+ */
+ virtual long maxOffset() const;
+
+ // -----------------------------------------------------------------------------
+ // Integration with rendering tree
+
+ /**
+ * Attaches this node to the rendering tree. This calculates the style to be applied to the node and creates an
+ * appropriate RenderObject which will be inserted into the tree (except when the style has display: none). This
+ * makes the node visible in the KHTMLView.
+ */
+ virtual void attach();
+
+ /**
+ * Detaches the node from the rendering tree, making it invisible in the rendered view. This method will remove
+ * the node's rendering object from the rendering tree and delete it.
+ */
+ virtual void detach();
+
+ /**
+ * Notifies the node that no more children will be added during parsing.
+ * After a node has been closed all changes must go through the DOM interface.
+ */
+ virtual void close();
+
+ virtual void structureChanged() {};
+ virtual void backwardsStructureChanged() {};
+
+ void createRendererIfNeeded();
+ virtual tdehtml::RenderStyle *styleForRenderer(tdehtml::RenderObject *parent);
+ virtual bool rendererIsNeeded(tdehtml::RenderStyle *);
+ virtual tdehtml::RenderObject *createRenderer(tdehtml::RenderArena *, tdehtml::RenderStyle *);
+
+ // -----------------------------------------------------------------------------
+ // Methods for maintaining the state of the element between history navigation
+
+ /**
+ * Indicates whether or not this type of node maintains its state. If so, the state of the node will be stored when
+ * the user goes to a different page using the state() method, and restored using the restoreState() method if the
+ * user returns (e.g. using the back button). This is used to ensure that user-changeable elements such as form
+ * controls maintain their contents when the user returns to a previous page in the history.
+ */
+ virtual bool maintainsState();
+
+ /**
+ * Returns the state of this node represented as a string. This string will be passed to restoreState() if the user
+ * returns to the page.
+ *
+ * @return State information about the node represented as a string
+ */
+ virtual TQString state();
+
+ /**
+ * Sets the state of the element based on a string previosuly returned by state(). This is used to initialize form
+ * controls with their old values when the user returns to the page in their history.
+ *
+ * @param state A string representation of the node's previously-stored state
+ */
+ virtual void restoreState(const TQString &state);
+
+ // -----------------------------------------------------------------------------
+ // Notification of document stucture changes
+
+ /**
+ * Notifies the node that it has been inserted into the document. This is called during document parsing, and also
+ * when a node is added through the DOM methods insertBefore(), appendChild() or replaceChild(). Note that this only
+ * happens when the node becomes part of the document tree, i.e. only when the document is actually an ancestor of
+ * the node. The call happens _after_ the node has been added to the tree.
+ *
+ * This is similar to the DOMNodeInsertedIntoDocument DOM event, but does not require the overhead of event
+ * dispatching.
+ */
+ virtual void insertedIntoDocument();
+
+ /**
+ * Notifies the node that it is no longer part of the document tree, i.e. when the document is no longer an ancestor
+ * node.
+ *
+ * This is similar to the DOMNodeRemovedFromDocument DOM event, but does not require the overhead of event
+ * dispatching, and is called _after_ the node is removed from the tree.
+ */
+ virtual void removedFromDocument();
+
+ /**
+ * Notifies the node that its list of children have changed (either by adding or removing child nodes), or a child
+ * node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE has changed its value.
+ */
+ virtual void childrenChanged();
+
+ virtual DOMString toString() const = 0;
+ /**
+ * Sometimes we need to get the string between two points on the DOM graph. Use this function to do this.
+ * For example, when the user copies some selected text to the clipboard as html.
+ * @param selectionStart Where to start the selection. If selectionStart != this, it is assumed we are after the start point
+ * @param selectionEnd Where to end the selection. If selectionEnd != this, it is assumed we are before the end point (unless found is true)
+ * @param startOffset Number of characters into the text in selectionStart that the start of the selection is.
+ * @param endOffset Number of characters into the text in selectionEnd that the end of the selection is.
+ * @param found When this is set to true, don't print anymore but closing tags.
+ * @return An html formatted string for this node and its children between the selectionStart and selectionEnd.
+ */
+ virtual DOMString selectionToString(NodeImpl * selectionStart,
+ NodeImpl * selectionEnd,
+ int startOffset,
+ int endOffset,
+ bool &found) const
+ { Q_UNUSED(selectionStart);
+ Q_UNUSED(selectionEnd);
+ Q_UNUSED(startOffset);
+ Q_UNUSED(endOffset);
+ Q_UNUSED(found);
+ return toString();
+ }
+
+private: // members
+ tdehtml::DocPtr<DocumentImpl> m_document;
+ NodeImpl *m_previous;
+ NodeImpl *m_next;
+protected:
+ tdehtml::RenderObject *m_render;
+ RegisteredListenerList m_regdListeners;
+
+ unsigned short m_tabIndex : 15;
+ bool m_hasTabIndex : 1;
+
+ bool m_hasId : 1;
+ bool m_attached : 1;
+ bool m_closed : 1;
+ bool m_changed : 1;
+ bool m_hasChangedChild : 1;
+ bool m_changedAscendentAttribute : 1;
+ bool m_inDocument : 1;
+ bool m_hasAnchor : 1;
+ bool m_specified : 1; // used in AttrImpl. Accessor functions there
+
+ bool m_hovered : 1;
+ bool m_focused : 1;
+ bool m_active : 1;
+ bool m_implicit : 1; // implicitely generated by the parser
+ bool m_htmlCompat : 1; // true if element was created in HTML compat mode
+ bool m_hasClassList : 1;
+ bool m_hasClass : 1; // true if element has a class property, as relevant to CSS
+};
+
+// this is the full Node Implementation with parents and children.
+class NodeBaseImpl : public NodeImpl
+{
+public:
+ NodeBaseImpl(DocumentImpl *doc)
+ : NodeImpl(doc), _first(0), _last(0) {}
+ virtual ~NodeBaseImpl();
+
+ // DOM methods overridden from parent classes
+ virtual NodeImpl *firstChild() const;
+ virtual NodeImpl *lastChild() const;
+ 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 bool hasChildNodes ( ) const;
+
+ virtual void setTextContent( const DOMString &text, int& exceptioncode );
+
+ // Other methods (not part of DOM)
+ void removeChildren();
+ void cloneChildNodes(NodeImpl *clone);
+
+ virtual void setFirstChild(NodeImpl *child);
+ virtual void setLastChild(NodeImpl *child);
+ virtual NodeImpl *addChild(NodeImpl *newChild);
+ virtual void attach();
+ virtual void detach();
+
+
+ bool getUpperLeftCorner(int &xPos, int &yPos) const;
+ bool getLowerRightCorner(int &xPos, int &yPos) const;
+
+ virtual void setFocus(bool=true);
+ virtual void setActive(bool=true);
+ virtual void setHovered(bool=true);
+ virtual unsigned long childNodeCount();
+ virtual NodeImpl *childNode(unsigned long index);
+
+protected:
+ NodeImpl *_first;
+ NodeImpl *_last;
+
+ // helper functions for inserting children:
+
+ // ### this should vanish. do it in dom/ !
+ // check for same source document:
+ bool checkSameDocument( NodeImpl *newchild, int &exceptioncode );
+ // check for being child:
+ bool checkIsChild( NodeImpl *oldchild, int &exceptioncode );
+ // ###
+
+ // find out if a node is allowed to be our child
+ void dispatchChildInsertedEvents( NodeImpl *child, int &exceptioncode );
+ void dispatchChildRemovalEvents( NodeImpl *child, int &exceptioncode );
+};
+
+// --------------------------------------------------------------------------
+class Node;
+class NodeImpl;
+
+class NodeListImpl : public tdehtml::Shared<NodeListImpl>
+{
+public:
+ //Type of the item stored in the cache.
+ enum Type {
+ UNCACHEABLE, //Too complex to be cached like this
+ CHILD_NODES,
+ LAST_NODE_LIST = CHILD_NODES
+ };
+
+ struct CacheKey
+ {
+ NodeImpl* baseNode;
+ int type;
+
+ CacheKey(): type(UNCACHEABLE) {}
+
+ CacheKey(NodeImpl* _baseNode, int _type):
+ baseNode(_baseNode), type(_type)
+ {}
+
+ int hash() const
+ {
+ return int(reinterpret_cast<unsigned long>(baseNode) >> 2) ^
+ (unsigned(type) << 26);
+ }
+
+ bool operator==(const CacheKey& other) const
+ {
+ return baseNode == other.baseNode &&
+ type == other.type;
+ }
+ };
+
+ struct Cache: public tdehtml::Shared<Cache>
+ {
+ static Cache* make() { return new Cache; }
+
+ CacheKey key;//### We must store this in here due to TQCache in Qt3 sucking
+
+ unsigned int version;
+ union
+ {
+ NodeImpl* node;
+ unsigned int index;
+ } current;
+ unsigned int position;
+ unsigned int length;
+ bool hasLength;
+
+ void updateNodeListInfo(DocumentImpl* doc);
+
+ virtual void clear(DocumentImpl* doc);
+ virtual ~Cache();
+ };
+
+ typedef Cache* CacheFactory();
+
+ NodeListImpl(NodeImpl* node, int type, CacheFactory* factory = 0);
+ virtual ~NodeListImpl();
+
+ // DOM methods & attributes for NodeList
+ virtual unsigned long length() const;
+ virtual NodeImpl *item ( unsigned long index ) const;
+
+ // Other methods (not part of DOM)
+
+protected:
+ virtual unsigned long calcLength(NodeImpl *start) const;
+ // helper functions for searching all ElementImpls in a tree
+
+ NodeImpl *recursiveItem ( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const;
+ NodeImpl *recursiveItemBack( NodeImpl* absStart, NodeImpl *start, unsigned long &offset ) const;
+
+ // Override this to determine what nodes to return. Set doRecurse to
+ // false if the children of this node do not need to be entered.
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const = 0;
+
+ NodeImpl* m_refNode;
+ mutable Cache* m_cache;
+};
+
+class ChildNodeListImpl : public NodeListImpl
+{
+public:
+
+ ChildNodeListImpl( NodeImpl *n);
+
+protected:
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const;
+};
+
+
+/**
+ * NodeList which lists all Nodes in a document with a given tag name
+ */
+class TagNodeListImpl : public NodeListImpl
+{
+public:
+ TagNodeListImpl( NodeImpl *n, NodeImpl::Id id );
+ TagNodeListImpl( NodeImpl *n, const DOMString &namespaceURI, const DOMString &localName );
+
+ // Other methods (not part of DOM)
+
+protected:
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const;
+ NodeImpl::Id m_id;
+ DOMString m_namespaceURI;
+ DOMString m_localName;
+
+ bool m_matchAllNames;
+ bool m_matchAllNamespaces;
+ bool m_namespaceAware;
+};
+
+
+/**
+ * NodeList which lists all Nodes in a Element with a given "name=" tag
+ */
+class NameNodeListImpl : public NodeListImpl
+{
+public:
+ NameNodeListImpl( NodeImpl *doc, const DOMString &t );
+
+ // Other methods (not part of DOM)
+
+protected:
+ virtual bool nodeMatches( NodeImpl *testNode, bool& doRecurse ) const;
+
+ DOMString nodeName;
+};
+
+// Generic NamedNodeMap interface
+// Other classes implement this for more specific situations e.g. attributes
+// of an element
+class NamedNodeMapImpl : public tdehtml::Shared<NamedNodeMapImpl>
+{
+public:
+ NamedNodeMapImpl();
+ virtual ~NamedNodeMapImpl();
+
+ // DOM methods & attributes for NamedNodeMap
+ virtual NodeImpl *getNamedItem ( NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0 ) const = 0;
+ virtual Node removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode ) = 0;
+ virtual Node setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode ) = 0;
+
+ virtual NodeImpl *item ( unsigned long index ) const = 0;
+ virtual unsigned long length( ) const = 0;
+
+ // Other methods (not part of DOM)
+ virtual NodeImpl::Id mapId(DOMStringImpl* namespaceURI,
+ DOMStringImpl* localName, bool readonly) = 0;
+ virtual bool isReadOnly() { return false; }
+};
+
+// Generic read-only NamedNodeMap implementation
+// Used for e.g. entities and notations in DocumentType.
+// You can add nodes using addNode
+class GenericRONamedNodeMapImpl : public NamedNodeMapImpl
+{
+public:
+ GenericRONamedNodeMapImpl(DocumentImpl* doc);
+ virtual ~GenericRONamedNodeMapImpl();
+
+ // DOM methods & attributes for NamedNodeMap
+
+ virtual NodeImpl *getNamedItem ( NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0 ) const;
+ virtual Node removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode );
+ virtual Node setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode );
+
+ virtual NodeImpl *item ( unsigned long index ) const;
+ virtual unsigned long length( ) const;
+
+ // Other methods (not part of DOM)
+ virtual NodeImpl::Id mapId(DOMStringImpl* namespaceURI,
+ DOMStringImpl* localName, bool readonly);
+
+ virtual bool isReadOnly() { return true; }
+
+ void addNode(NodeImpl *n);
+
+protected:
+ DocumentImpl* m_doc;
+ TQPtrList<NodeImpl> *m_contents;
+};
+
+} //namespace
+#endif
diff --git a/tdehtml/xml/dom_restyler.cpp b/tdehtml/xml/dom_restyler.cpp
new file mode 100644
index 000000000..acd89620f
--- /dev/null
+++ b/tdehtml/xml/dom_restyler.cpp
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006 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.
+ *
+ */
+
+#include "dom_restyler.h"
+#include "dom_elementimpl.h"
+
+namespace tdehtml {
+
+DynamicDomRestyler::DynamicDomRestyler()
+{
+}
+
+void DynamicDomRestyler::addDependency(ElementImpl* subject, ElementImpl* dependency, StructuralDependencyType type)
+{
+ assert(type < LastStructuralDependency);
+
+ dependency_map[type].append(dependency, subject);
+ reverse_map.append(subject,dependency);
+}
+
+void DynamicDomRestyler::removeDependency(ElementImpl* subject, ElementImpl* dependency, StructuralDependencyType type)
+{
+ dependency_map[type].remove(dependency, subject);
+ // don't remove from reverse_map as there might be other depencies to the same element
+}
+
+void DynamicDomRestyler::removeDependencies(ElementImpl* subject, StructuralDependencyType type)
+{
+ KMultiMap<ElementImpl>::List* my_dependencies = reverse_map.find(subject);
+
+ if (!my_dependencies) return;
+
+ for (my_dependencies->first(); my_dependencies->current() ; my_dependencies->next())
+ {
+ ElementImpl* e = my_dependencies->current();
+ dependency_map[type].remove(e,subject);
+ }
+
+ // don't remove from reverse_map as there might be other depencies to the same elements
+}
+
+void DynamicDomRestyler::resetDependencies(ElementImpl* subject)
+{
+ KMultiMap<ElementImpl>::List* my_dependencies = reverse_map.find(subject);
+
+ if (!my_dependencies) return;
+
+ for (my_dependencies->first(); my_dependencies->current() ; my_dependencies->next())
+ {
+ ElementImpl* e = my_dependencies->current();
+ for (int type = 0; type < LastStructuralDependency; type++) {
+ dependency_map[type].remove(e,subject);
+ }
+ }
+
+ reverse_map.remove(subject);
+}
+
+void DynamicDomRestyler::restyleDepedent(ElementImpl* dependency, StructuralDependencyType type)
+{
+ assert(type < LastStructuralDependency);
+ KMultiMap<ElementImpl>::List* dep = dependency_map[type].find(dependency);
+
+ if (!dep) return;
+
+ // take copy as the restyle will change the list
+ KMultiMap<ElementImpl>::List dependent(*dep);
+
+ for (dependent.first(); dependent.current() ; dependent.next())
+ {
+// kdDebug() << "Restyling dependent" << endl;
+ dependent.current()->setChanged(true);
+ }
+}
+
+void DynamicDomRestyler::dumpStats() const
+{
+/*
+ kdDebug() << "Keys in structural dependencies: " << dependency_map[StructuralDependency].size() << endl;
+ kdDebug() << "Keys in attribute dependencies: " << dependency_map[AttributeDependency].size() << endl;
+
+ kdDebug() << "Keys in reverse map: " << reverse_map.size() << endl;
+ */
+}
+
+void DynamicDomRestyler::addDependency(uint attrID, AttributeDependencyType type)
+{
+ assert(type < LastAttributeDependency);
+
+ unsigned int hash = (attrID * 257) % 512;
+ attribute_map[type][hash] = true;
+}
+
+bool DynamicDomRestyler::checkDependency(uint attrID, AttributeDependencyType type)
+{
+ assert(type < LastAttributeDependency);
+
+ unsigned int hash = (attrID * 257) % 512;
+ // ### gives false positives, but that's okay.
+ return attribute_map[type][hash];
+}
+
+} // namespace
diff --git a/tdehtml/xml/dom_restyler.h b/tdehtml/xml/dom_restyler.h
new file mode 100644
index 000000000..54d5ad798
--- /dev/null
+++ b/tdehtml/xml/dom_restyler.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006 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.
+ *
+ */
+
+#ifndef _DOM_restyler_h_
+#define _DOM_restyler_h_
+
+#include "misc/multimap.h"
+#include <bitset>
+
+namespace DOM {
+ class ElementImpl;
+}
+
+// Restyle dependency tracker for dynamic DOM
+
+namespace tdehtml {
+
+using DOM::ElementImpl;
+
+// These types are different types of dependencies, and serves to identify which element should be
+// restyled when a change of that kind triggers on the element
+enum StructuralDependencyType {
+ // Style relies on the children of the element (unaffected by append & close)
+ StructuralDependency = 0,
+ // Style relies on the last children of the element (affected by append & close)
+ BackwardsStructuralDependency = 1,
+ // Style relies on the element having hover
+ HoverDependency = 2,
+ // Style relies on the element being active
+ ActiveDependency = 3,
+ // Style relies on another state of element (focus, disabled, checked, etc.)
+ // (focus is special cased though since elements always depend on their own focus)
+ OtherStateDependency = 4,
+ LastStructuralDependency
+};
+
+// Attribute dependencies are much coarser than structural, for memory reasons rather than performance
+// This tracks global depencies of various kinds.
+// The groups are separated into where possible depending elements might be:
+enum AttributeDependencyType {
+ // Style of the changed element depend on this attribute
+ PersonalDependency = 0,
+ // Style of the elements children depend on this attribute
+ AncestorDependency = 1,
+ // Style of the elements later siblings or their children depend on this attribute
+ PredecessorDependency = 2,
+ LastAttributeDependency
+};
+
+
+/**
+ * @internal
+ */
+class DynamicDomRestyler {
+public:
+ DynamicDomRestyler();
+
+ // Structural dependencies are tracked from element to subject
+ void addDependency(ElementImpl* subject, ElementImpl* dependency, StructuralDependencyType type);
+ void resetDependencies(ElementImpl* subject);
+ void removeDependency(ElementImpl* subject, ElementImpl* dependency, StructuralDependencyType type);
+ void removeDependencies(ElementImpl* subject, StructuralDependencyType type);
+ void restyleDepedent(ElementImpl* dependency, StructuralDependencyType type);
+
+ // Attribute dependencies are traced on attribute alone
+ void addDependency(uint attrID, AttributeDependencyType type);
+ bool checkDependency(uint attrID, AttributeDependencyType type);
+
+ void dumpStats() const;
+private:
+ // Map of dependencies.
+ KMultiMap<ElementImpl> dependency_map[LastStructuralDependency];
+ // Map of reverse dependencies. For fast reset
+ KMultiMap<ElementImpl> reverse_map;
+
+ // Map of the various attribute dependencies
+ std::bitset<512> attribute_map[LastAttributeDependency];
+};
+
+}
+
+#endif
+
diff --git a/tdehtml/xml/dom_stringimpl.cpp b/tdehtml/xml/dom_stringimpl.cpp
new file mode 100644
index 000000000..12f1481c0
--- /dev/null
+++ b/tdehtml/xml/dom_stringimpl.cpp
@@ -0,0 +1,460 @@
+/**
+ * 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) 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 "dom_stringimpl.h"
+
+#include <kdebug.h>
+
+#include <string.h>
+#include <tqstringlist.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+
+DOMStringImpl::DOMStringImpl(const char *str)
+{
+ if(str && *str)
+ {
+ l = strlen(str);
+ s = QT_ALLOC_QCHAR_VEC( l );
+ int i = l;
+ TQChar* ptr = s;
+ while( i-- )
+ *ptr++ = *str++;
+ }
+ else
+ {
+ s = QT_ALLOC_QCHAR_VEC( 1 ); // crash protection
+ s[0] = 0x0; // == TQChar::null;
+ l = 0;
+ }
+}
+
+// FIXME: should be a cached flag maybe.
+bool DOMStringImpl::containsOnlyWhitespace() const
+{
+ if (!s)
+ return true;
+
+ for (uint i = 0; i < l; i++) {
+ TQChar c = s[i];
+ if (c.unicode() <= 0x7F) {
+ if (c.unicode() > ' ')
+ return false;
+ } else {
+ if (c.direction() != TQChar::DirWS)
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void DOMStringImpl::append(DOMStringImpl *str)
+{
+ if(str && str->l != 0)
+ {
+ int newlen = l+str->l;
+ TQChar *c = QT_ALLOC_QCHAR_VEC(newlen);
+ memcpy(c, s, l*sizeof(TQChar));
+ memcpy(c+l, str->s, str->l*sizeof(TQChar));
+ if(s) QT_DELETE_QCHAR_VEC(s);
+ s = c;
+ l = newlen;
+ }
+}
+
+void DOMStringImpl::insert(DOMStringImpl *str, unsigned int pos)
+{
+ if(pos > l)
+ {
+ append(str);
+ return;
+ }
+ if(str && str->l != 0)
+ {
+ int newlen = l+str->l;
+ TQChar *c = QT_ALLOC_QCHAR_VEC(newlen);
+ memcpy(c, s, pos*sizeof(TQChar));
+ memcpy(c+pos, str->s, str->l*sizeof(TQChar));
+ memcpy(c+pos+str->l, s+pos, (l-pos)*sizeof(TQChar));
+ if(s) QT_DELETE_QCHAR_VEC(s);
+ s = c;
+ l = newlen;
+ }
+}
+
+void DOMStringImpl::truncate(int len)
+{
+ if(len > (int)l) return;
+
+ int nl = len < 1 ? 1 : len;
+ TQChar *c = QT_ALLOC_QCHAR_VEC(nl);
+ memcpy(c, s, nl*sizeof(TQChar));
+ if(s) QT_DELETE_QCHAR_VEC(s);
+ s = c;
+ l = len;
+}
+
+void DOMStringImpl::remove(unsigned int pos, int len)
+{
+ if(pos >= l ) return;
+ if(pos+len > l)
+ len = l - pos;
+
+ uint newLen = l-len;
+ TQChar *c = QT_ALLOC_QCHAR_VEC(newLen);
+ memcpy(c, s, pos*sizeof(TQChar));
+ memcpy(c+pos, s+pos+len, (l-len-pos)*sizeof(TQChar));
+ if(s) QT_DELETE_QCHAR_VEC(s);
+ s = c;
+ l = newLen;
+}
+
+DOMStringImpl *DOMStringImpl::split(unsigned int pos)
+{
+ if( pos >=l ) return new DOMStringImpl();
+
+ uint newLen = l-pos;
+ DOMStringImpl *str = new DOMStringImpl(s + pos, newLen);
+ truncate(pos);
+ return str;
+}
+
+DOMStringImpl *DOMStringImpl::substring(unsigned int pos, unsigned int len)
+{
+ if( pos >=l ) return new DOMStringImpl();
+ if(pos+len > l)
+ len = l - pos;
+
+ return new DOMStringImpl(s + pos, len);
+}
+
+// Collapses white-space according to CSS 2.1 rules
+DOMStringImpl *DOMStringImpl::collapseWhiteSpace(bool preserveLF, bool preserveWS)
+{
+ if (preserveLF && preserveWS) return this;
+
+ // Notice we are likely allocating more space than needed (worst case)
+ TQChar *n = QT_ALLOC_QCHAR_VEC(l);
+
+ unsigned int pos = 0;
+ bool collapsing = false; // collapsing white-space
+ bool collapsingLF = false; // collapsing around linefeed
+ bool changedLF = false;
+ for(unsigned int i=0; i<l; i++) {
+ TQChar ch = s[i];
+
+ // We act on \r as we would on \n because CSS uses it to indicate new-line
+ if (ch == '\r') ch = '\n';
+ else
+ // ### The XML parser lets \t through, for now treat them as spaces
+ if (ch == '\t') ch = ' ';
+
+ if (!preserveLF && ch == '\n') {
+ // ### Not strictly correct according to CSS3 text-module.
+ // - In ideographic languages linefeed should be ignored
+ // - and in Thai and Khmer it should be treated as a zero-width space
+ ch = ' '; // Treat as space
+ changedLF = true;
+ }
+
+ if (collapsing) {
+ if (ch == ' ')
+ continue;
+ if (ch == '\n') {
+ collapsingLF = true;
+ continue;
+ }
+
+ n[pos++] = (collapsingLF) ? '\n' : ' ';
+ collapsing = false;
+ collapsingLF = false;
+ }
+ else
+ if (!preserveWS && ch == ' ') {
+ collapsing = true;
+ continue;
+ }
+ else
+ if (!preserveWS && ch == '\n') {
+ collapsing = true;
+ collapsingLF = true;
+ continue;
+ }
+
+ n[pos++] = ch;
+ }
+ if (collapsing)
+ n[pos++] = ((collapsingLF) ? '\n' : ' ');
+
+ if (pos == l && !changedLF) {
+ QT_DELETE_QCHAR_VEC(n);
+ return this;
+ }
+ else {
+ DOMStringImpl* out = new DOMStringImpl();
+ out->s = n;
+ out->l = pos;
+
+ return out;
+ }
+}
+
+static Length parseLength(const TQChar *s, unsigned int l)
+{
+ if (l == 0) {
+ return Length(1, Relative);
+ }
+
+ unsigned i = 0;
+ while (i < l && s[i].isSpace())
+ ++i;
+ if (i < l && (s[i] == '+' || s[i] == '-'))
+ ++i;
+ while (i < l && s[i].isDigit())
+ ++i;
+
+ bool ok;
+ int r = TQConstString(s, i).string().toInt(&ok);
+
+ /* Skip over any remaining digits, we are not that accurate (5.5% => 5%) */
+ while (i < l && (s[i].isDigit() || s[i] == '.'))
+ ++i;
+
+ /* IE Quirk: Skip any whitespace (20 % => 20%) */
+ while (i < l && s[i].isSpace())
+ ++i;
+
+ if (ok) {
+ if (i == l) {
+ return Length(r, Fixed);
+ } else {
+ const TQChar* next = s+i;
+
+ if (*next == '%')
+ return Length(r, Percent);
+
+ if (*next == '*')
+ return Length(r, Relative);
+ }
+ return Length(r, Fixed);
+ } else {
+ if (i < l) {
+ const TQChar* next = s+i;
+
+ if (*next == '*')
+ return Length(1, Relative);
+
+ if (*next == '%')
+ return Length(1, Relative);
+ }
+ }
+ return Length(0, Relative);
+}
+
+tdehtml::Length* DOMStringImpl::toCoordsArray(int& len) const
+{
+ TQString str(s, l);
+ for(unsigned int i=0; i < l; i++) {
+ TQChar cc = s[i];
+ if (cc > TQChar('9') || (cc < TQChar('0') && cc != '-' && cc != '*' && cc != '.'))
+ str[i] = ' ';
+ }
+ str = str.simplifyWhiteSpace();
+
+ len = str.contains(' ') + 1;
+ tdehtml::Length* r = new tdehtml::Length[len];
+
+ int i = 0;
+ int pos = 0;
+ int pos2;
+
+ while((pos2 = str.find(' ', pos)) != -1) {
+ r[i++] = parseLength((TQChar *) str.unicode()+pos, pos2-pos);
+ pos = pos2+1;
+ }
+ r[i] = parseLength((TQChar *) str.unicode()+pos, str.length()-pos);
+
+ return r;
+}
+
+tdehtml::Length* DOMStringImpl::toLengthArray(int& len) const
+{
+ TQString str(s, l);
+ str = str.simplifyWhiteSpace();
+
+ len = str.contains(',') + 1;
+
+ // If we have no commas, we have no array.
+ if( len == 1 )
+ return 0L;
+
+ tdehtml::Length* r = new tdehtml::Length[len];
+
+ int i = 0;
+ int pos = 0;
+ int pos2;
+
+ while((pos2 = str.find(',', pos)) != -1) {
+ r[i++] = parseLength((TQChar *) str.unicode()+pos, pos2-pos);
+ pos = pos2+1;
+ }
+
+ /* IE Quirk: If the last comma is the last char skip it and reduce len by one */
+ if (str.length()-pos > 0)
+ r[i] = parseLength((TQChar *) str.unicode()+pos, str.length()-pos);
+ else
+ len--;
+
+ return r;
+}
+
+bool DOMStringImpl::isLower() const
+{
+ unsigned int i;
+ for (i = 0; i < l; i++)
+ if (s[i].lower() != s[i])
+ return false;
+ return true;
+}
+
+DOMStringImpl *DOMStringImpl::lower() const
+{
+ DOMStringImpl *c = new DOMStringImpl;
+ if(!l) return c;
+
+ c->s = QT_ALLOC_QCHAR_VEC(l);
+ c->l = l;
+
+ for (unsigned int i = 0; i < l; i++)
+ c->s[i] = s[i].lower();
+
+ return c;
+}
+
+DOMStringImpl *DOMStringImpl::upper() const
+{
+ DOMStringImpl *c = new DOMStringImpl;
+ if(!l) return c;
+
+ c->s = QT_ALLOC_QCHAR_VEC(l);
+ c->l = l;
+
+ for (unsigned int i = 0; i < l; i++)
+ c->s[i] = s[i].upper();
+
+ return c;
+}
+
+DOMStringImpl *DOMStringImpl::capitalize(bool noFirstCap) const
+{
+ bool canCapitalize= !noFirstCap;
+ DOMStringImpl *c = new DOMStringImpl;
+ if(!l) return c;
+
+ c->s = QT_ALLOC_QCHAR_VEC(l);
+ c->l = l;
+
+ for (unsigned int i=0; i<l; i++)
+ {
+ if (s[i].isLetterOrNumber() && canCapitalize)
+ {
+ c->s[i]=s[i].upper();
+ canCapitalize=false;
+ }
+ else
+ {
+ c->s[i]=s[i];
+ if (s[i].isSpace())
+ canCapitalize=true;
+ }
+ }
+
+ return c;
+}
+
+TQString DOMStringImpl::string() const
+{
+ return TQString(s, l);
+}
+
+int DOMStringImpl::toInt(bool* ok) const
+{
+ // match \s*[+-]?\d*
+ unsigned i = 0;
+ while (i < l && s[i].isSpace())
+ ++i;
+ if (i < l && (s[i] == '+' || s[i] == '-'))
+ ++i;
+ while (i < l && s[i].isDigit())
+ ++i;
+
+ return TQConstString(s, i).string().toInt(ok);
+}
+
+static const unsigned short amp[] = {'&', 'a', 'm', 'p', ';'};
+static const unsigned short lt[] = {'&', 'l', 't', ';'};
+static const unsigned short gt[] = {'&', 'g', 't', ';'};
+
+DOMStringImpl *DOMStringImpl::escapeHTML()
+{
+ unsigned outL = 0;
+ for (unsigned int i = 0; i < l; ++i ) {
+ if ( s[i] == '&' )
+ outL += 5; //&amp;
+ else if (s[i] == '<' || s[i] == '>')
+ outL += 4; //&gt;/&lt;
+ else
+ ++outL;
+ }
+ if (outL == l)
+ return this;
+
+
+ DOMStringImpl* toRet = new DOMStringImpl();
+ toRet->s = QT_ALLOC_QCHAR_VEC(outL);
+ toRet->l = outL;
+
+ unsigned outP = 0;
+ for (unsigned int i = 0; i < l; ++i ) {
+ if ( s[i] == '&' ) {
+ memcpy(&toRet->s[outP], amp, sizeof(amp));
+ outP += 5;
+ } else if (s[i] == '<') {
+ memcpy(&toRet->s[outP], lt, sizeof(lt));
+ outP += 4;
+ } else if (s[i] == '>') {
+ memcpy(&toRet->s[outP], gt, sizeof(gt));
+ outP += 4;
+ } else {
+ toRet->s[outP] = s[i];
+ ++outP;
+ }
+ }
+ return toRet;
+}
+
diff --git a/tdehtml/xml/dom_stringimpl.h b/tdehtml/xml/dom_stringimpl.h
new file mode 100644
index 000000000..c8f5ce7d8
--- /dev/null
+++ b/tdehtml/xml/dom_stringimpl.h
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 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.
+ *
+ */
+#ifndef _DOM_DOMStringImpl_h_
+#define _DOM_DOMStringImpl_h_
+
+#include <tqstring.h>
+
+#include "dom/dom_misc.h"
+#include "misc/tdehtmllayout.h"
+#include "misc/shared.h"
+
+#define QT_ALLOC_QCHAR_VEC( N ) (TQChar*) new char[ sizeof(TQChar)*( N ) ]
+#define QT_DELETE_QCHAR_VEC( P ) delete[] ((char*)( P ))
+
+namespace DOM {
+
+class DOMStringImpl : public tdehtml::Shared<DOMStringImpl>
+{
+private:
+ DOMStringImpl(const DOMStringImpl&);
+ DOMStringImpl& operator=(const DOMStringImpl&);
+protected:
+ DOMStringImpl() { s = 0, l = 0; }
+public:
+ DOMStringImpl(const TQChar *str, unsigned int len) {
+ bool havestr = str && len;
+ s = QT_ALLOC_QCHAR_VEC( havestr ? len : 1 );
+ if(str && len) {
+ memcpy( s, str, len * sizeof(TQChar) );
+ l = len;
+ } else {
+ // crash protection
+ s[0] = 0x0;
+ l = 0;
+ }
+ }
+
+ explicit DOMStringImpl(const char *str);
+ explicit DOMStringImpl(const TQChar &ch) {
+ s = QT_ALLOC_QCHAR_VEC( 1 );
+ s[0] = ch;
+ l = 1;
+ }
+ ~DOMStringImpl() {
+ if(s) QT_DELETE_QCHAR_VEC(s);
+ }
+
+ void append(DOMStringImpl *str);
+ void insert(DOMStringImpl *str, unsigned int pos);
+ void truncate(int len);
+ void remove(unsigned int pos, int len=1);
+ DOMStringImpl *split(unsigned int pos);
+ DOMStringImpl *copy() const {
+ return new DOMStringImpl(s,l);
+ };
+
+
+ DOMStringImpl *substring(unsigned int pos, unsigned int len);
+ DOMStringImpl *collapseWhiteSpace(bool preserveLF, bool preserveWS);
+
+ const TQChar &operator [] (int pos) { return s[pos]; }
+ bool containsOnlyWhitespace() const;
+
+ // ignores trailing garbage, unlike QString
+ int toInt(bool* ok = 0) const;
+
+ tdehtml::Length* toLengthArray(int& len) const;
+ tdehtml::Length* toCoordsArray(int& len) const;
+ bool isLower() const;
+ DOMStringImpl *lower() const;
+ DOMStringImpl *upper() const;
+ DOMStringImpl *capitalize(bool noFirstCap=false) const;
+ DOMStringImpl *escapeHTML();
+
+ TQChar *unicode() const { return s; }
+ uint length() const { return l; }
+ TQString string() const;
+
+ unsigned int l;
+ TQChar *s;
+};
+
+}
+#endif
diff --git a/tdehtml/xml/dom_textimpl.cpp b/tdehtml/xml/dom_textimpl.cpp
new file mode 100644
index 000000000..aa478b922
--- /dev/null
+++ b/tdehtml/xml/dom_textimpl.cpp
@@ -0,0 +1,522 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2001-2003 Dirk Mueller (mueller@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.
+ */
+
+#include "dom/dom_exception.h"
+#include "css/cssstyleselector.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_docimpl.h"
+
+#include "misc/htmlhashes.h"
+#include "rendering/render_text.h"
+#include "rendering/render_flow.h"
+
+#include <kdebug.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+static DOMString escapeHTML( const DOMString& in )
+{
+ return in.implementation()->escapeHTML();
+}
+
+CharacterDataImpl::CharacterDataImpl(DocumentImpl *doc, DOMStringImpl* _text)
+ : NodeImpl(doc)
+{
+ str = _text ? _text : new DOMStringImpl(0, 0);
+ str->ref();
+}
+
+CharacterDataImpl::~CharacterDataImpl()
+{
+ if(str) str->deref();
+}
+
+void CharacterDataImpl::setData( const DOMString &_data, int &exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ if(str == _data.impl) return; // ### fire DOMCharacterDataModified if modified?
+ DOMStringImpl *oldStr = str;
+ str = _data.impl;
+ if(str) str->ref();
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+
+ dispatchModifiedEvent(oldStr);
+ if(oldStr) oldStr->deref();
+}
+
+unsigned long CharacterDataImpl::length() const
+{
+ return str->l;
+}
+
+DOMString CharacterDataImpl::substringData( const unsigned long offset, const unsigned long count, int &exceptioncode )
+{
+ exceptioncode = 0;
+ if ((long)count < 0)
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ else
+ checkCharDataOperation(offset, exceptioncode);
+ if (exceptioncode)
+ return DOMString();
+
+ return str->substring(offset,count);
+}
+
+void CharacterDataImpl::appendData( const DOMString &arg, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ DOMStringImpl *oldStr = str;
+ str = str->copy();
+ str->ref();
+ str->append(arg.impl);
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+
+ dispatchModifiedEvent(oldStr);
+ oldStr->deref();
+}
+
+void CharacterDataImpl::insertData( const unsigned long offset, const DOMString &arg, int &exceptioncode )
+{
+ exceptioncode = 0;
+ checkCharDataOperation(offset, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ DOMStringImpl *oldStr = str;
+ str = str->copy();
+ str->ref();
+ str->insert(arg.impl, offset);
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+
+ dispatchModifiedEvent(oldStr);
+ oldStr->deref();
+}
+
+void CharacterDataImpl::deleteData( const unsigned long offset, const unsigned long count, int &exceptioncode )
+{
+ exceptioncode = 0;
+ if ((long)count < 0)
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ else
+ checkCharDataOperation(offset, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ DOMStringImpl *oldStr = str;
+ str = str->copy();
+ str->ref();
+ str->remove(offset,count);
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+
+ dispatchModifiedEvent(oldStr);
+ oldStr->deref();
+}
+
+void CharacterDataImpl::replaceData( const unsigned long offset, const unsigned long count, const DOMString &arg, int &exceptioncode )
+{
+ exceptioncode = 0;
+ if ((long)count < 0)
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ else
+ checkCharDataOperation(offset, exceptioncode);
+ if (exceptioncode)
+ return;
+
+ unsigned long realCount;
+ if (offset + count > str->l)
+ realCount = str->l-offset;
+ else
+ realCount = count;
+
+ DOMStringImpl *oldStr = str;
+ str = str->copy();
+ str->ref();
+ str->remove(offset,realCount);
+ str->insert(arg.impl, offset);
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+
+ dispatchModifiedEvent(oldStr);
+ oldStr->deref();
+}
+
+DOMString CharacterDataImpl::nodeValue() const
+{
+ return str;
+}
+
+bool CharacterDataImpl::containsOnlyWhitespace() const
+{
+ return str->containsOnlyWhitespace();
+}
+
+void CharacterDataImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
+ setData(_nodeValue, exceptioncode);
+}
+
+void CharacterDataImpl::dispatchModifiedEvent(DOMStringImpl *prevValue)
+{
+ if (parentNode())
+ parentNode()->childrenChanged();
+ if (!getDocument()->hasListenerType(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER))
+ return;
+
+ DOMStringImpl *newValue = str->copy();
+ newValue->ref();
+ int exceptioncode = 0;
+ MutationEventImpl* const evt = new MutationEventImpl(EventImpl::DOMCHARACTERDATAMODIFIED_EVENT,true,false,0,prevValue,newValue,DOMString(),0);
+ evt->ref();
+ dispatchEvent(evt,exceptioncode);
+ evt->deref();
+ newValue->deref();
+ dispatchSubtreeModifiedEvent();
+}
+
+void CharacterDataImpl::checkCharDataOperation( const unsigned long offset, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than the number of 16-bit
+ // units in data.
+ if (offset > str->l) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ return;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+}
+
+long CharacterDataImpl::minOffset() const
+{
+ RenderText *r = static_cast<RenderText *>(renderer());
+ if (!r || !r->isText()) return 0;
+
+ // take :first-letter into consideration
+#ifdef __GNUC__
+#warning FIXME
+#endif
+#if 0
+ if (r->forcedMinOffset()) {
+ RenderFlow *firstLetter = static_cast<RenderFlow *>(r->previousSibling());
+ if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) {
+ RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild());
+ return letterText->minOffset();
+ }
+ }
+#endif
+
+ return r->minOffset();
+}
+
+long CharacterDataImpl::maxOffset() const
+{
+ RenderText *r = static_cast<RenderText *>(renderer());
+ if (!r || !r->isText()) return (long)length();
+ return r->maxOffset();
+}
+
+DOMStringImpl* CharacterDataImpl::textContent() const
+{
+ return new DOMStringImpl(str->s, str->l);
+}
+
+void CharacterDataImpl::setTextContent( const DOMString &str, int& exceptioncode )
+{
+ setData(str, exceptioncode);
+}
+
+// ---------------------------------------------------------------------------
+
+DOMString CommentImpl::nodeName() const
+{
+ return "#comment";
+}
+
+unsigned short CommentImpl::nodeType() const
+{
+ return Node::COMMENT_NODE;
+}
+
+NodeImpl *CommentImpl::cloneNode(bool /*deep*/)
+{
+ return getDocument()->createComment( str );
+}
+
+NodeImpl::Id CommentImpl::id() const
+{
+ return ID_COMMENT;
+}
+
+// DOM Section 1.1.1
+bool CommentImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+DOMString CommentImpl::toString() const
+{
+ // FIXME: substitute entity references as needed!
+ return DOMString("<!--") + escapeHTML( nodeValue() ) + "-->";
+}
+
+// ---------------------------------------------------------------------------
+
+TextImpl *TextImpl::splitText( const unsigned long offset, int &exceptioncode )
+{
+ exceptioncode = 0;
+
+ // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than
+ // the number of 16-bit units in data.
+
+ // ### we explicitly check for a negative long that has been cast to an unsigned long
+ // ... this can happen if JS code passes in -1 - we need to catch this earlier! (in the
+ // kjs bindings)
+ if (offset > str->l || (long)offset < 0) {
+ exceptioncode = DOMException::INDEX_SIZE_ERR;
+ return 0;
+ }
+
+ // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return 0;
+ }
+
+ DOMStringImpl *oldStr = str;
+ TextImpl *newText = createNew(str->substring(offset,str->l-offset));
+ str = str->copy();
+ str->ref();
+ str->remove(offset,str->l-offset);
+
+ dispatchModifiedEvent(oldStr);
+ oldStr->deref();
+
+ if (parentNode())
+ parentNode()->insertBefore(newText,nextSibling(), exceptioncode );
+ if ( exceptioncode )
+ return 0;
+
+ if (m_render)
+ (static_cast<RenderText*>(m_render))->setText(str);
+ setChanged(true);
+ return newText;
+}
+
+DOMString TextImpl::nodeName() const
+{
+ return "#text";
+}
+
+unsigned short TextImpl::nodeType() const
+{
+ return Node::TEXT_NODE;
+}
+
+NodeImpl *TextImpl::cloneNode(bool /*deep*/)
+{
+ return getDocument()->createTextNode(str);
+}
+
+bool TextImpl::rendererIsNeeded(RenderStyle *style)
+{
+ if (!CharacterDataImpl::rendererIsNeeded(style)) {
+ return false;
+ }
+ bool onlyWS = containsOnlyWhitespace();
+ if (!onlyWS) {
+ return true;
+ }
+
+ RenderObject *par = parentNode()->renderer();
+
+ if (par->isTable() || par->isTableRow() || par->isTableSection()) {
+ return false;
+ }
+
+ if (style->preserveWS() || style->preserveLF()) {
+ return true;
+ }
+
+ RenderObject *prev = previousRenderer();
+ if (par->isInlineFlow()) {
+ // <span><div/> <div/></span>
+ if (prev && !prev->isInline()) {
+ return false;
+ }
+ } else {
+ if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline())) {
+ return false;
+ }
+
+ RenderObject *first = par->firstChild();
+ while (first && first->isFloatingOrPositioned())
+ first = first->nextSibling();
+ RenderObject *next = nextRenderer();
+ if (!first || next == first) {
+ // Whitespace at the start of a block just goes away. Don't even
+ // make a render object for this text.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+RenderObject *TextImpl::createRenderer(RenderArena *arena, RenderStyle *style)
+{
+ return new (arena) RenderText(this, str);
+}
+
+void TextImpl::attach()
+{
+ createRendererIfNeeded();
+ CharacterDataImpl::attach();
+}
+
+NodeImpl::Id TextImpl::id() const
+{
+ return ID_TEXT;
+}
+
+void TextImpl::recalcStyle( StyleChange change )
+{
+// tqDebug("textImpl::recalcStyle");
+ // Create renderer if now needed
+ if ( changed() && !m_render) {
+ createRendererIfNeeded();
+ }
+ if (change != NoChange && parentNode()) {
+// tqDebug("DomText::recalcStyle");
+ if(m_render)
+ m_render->setStyle(parentNode()->renderer()->style());
+ }
+ if ( changed() && m_render && m_render->isText() )
+ static_cast<RenderText*>(m_render)->setText(str);
+ setChanged( false );
+}
+
+// DOM Section 1.1.1
+bool TextImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+TextImpl *TextImpl::createNew(DOMStringImpl *_str)
+{
+ return new TextImpl(docPtr(),_str);
+}
+
+DOMStringImpl* TextImpl::renderString() const
+{
+ if (renderer())
+ return static_cast<RenderText*>(renderer())->string();
+ else
+ return string();
+}
+
+DOMString TextImpl::toString() const
+{
+ // FIXME: substitute entity references as needed!
+ return escapeHTML( nodeValue() );
+}
+
+DOMString TextImpl::toString(long long startOffset, long long endOffset) const
+{
+ // FIXME: substitute entity references as needed!
+
+ DOMString str = nodeValue();
+ if(endOffset >=0 || startOffset >0)
+ str = str.copy(); //we are going to modify this, so make a copy. I hope I'm doing this right.
+ if(endOffset >= 0)
+ str.truncate(endOffset);
+ if(startOffset > 0) //note the order of these 2 'if' statements so that it works right when n==m_startContainer==m_endContainer
+ str.remove(0, startOffset);
+ return escapeHTML( str );
+}
+
+// ---------------------------------------------------------------------------
+
+DOMString CDATASectionImpl::nodeName() const
+{
+ return "#cdata-section";
+}
+
+unsigned short CDATASectionImpl::nodeType() const
+{
+ return Node::CDATA_SECTION_NODE;
+}
+
+NodeImpl *CDATASectionImpl::cloneNode(bool /*deep*/)
+{
+ return getDocument()->createCDATASection(str);
+}
+
+// DOM Section 1.1.1
+bool CDATASectionImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+TextImpl *CDATASectionImpl::createNew(DOMStringImpl *_str)
+{
+ return new CDATASectionImpl(docPtr(),_str);
+}
+
+DOMString CDATASectionImpl::toString() const
+{
+ // FIXME: substitute entity references as needed!
+ return DOMString("<![CDATA[") + nodeValue() + "]]>";
+}
+
+
+
diff --git a/tdehtml/xml/dom_textimpl.h b/tdehtml/xml/dom_textimpl.h
new file mode 100644
index 000000000..07d2c0011
--- /dev/null
+++ b/tdehtml/xml/dom_textimpl.h
@@ -0,0 +1,176 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2001-2003 Dirk Mueller (mueller@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 _DOM_CharacterDataImpl_h_
+#define _DOM_CharacterDataImpl_h_
+
+#include "xml/dom_nodeimpl.h"
+#include "dom/dom_string.h"
+
+namespace DOM {
+
+ class DocumentImpl;
+ class CharacterData;
+ class Text;
+
+class CharacterDataImpl : public NodeImpl
+{
+public:
+ CharacterDataImpl(DocumentImpl *doc, DOMStringImpl* _text);
+ CharacterDataImpl(DocumentImpl *doc)
+ : NodeImpl(doc), str(0) {}
+
+ virtual ~CharacterDataImpl();
+
+ // DOM methods & attributes for CharacterData
+
+ virtual void setData( const DOMString &_data, int &exceptioncode );
+ virtual unsigned long length ( ) const;
+ virtual DOMString substringData ( const unsigned long offset, const unsigned long count, int &exceptioncode );
+ virtual void appendData ( const DOMString &arg, int &exceptioncode );
+ virtual void insertData ( const unsigned long offset, const DOMString &arg, int &exceptioncode );
+ virtual void deleteData ( const unsigned long offset, const unsigned long count, int &exceptioncode );
+ virtual void replaceData ( const unsigned long offset, const unsigned long count, const DOMString &arg, int &exceptioncode );
+
+ virtual bool containsOnlyWhitespace() const;
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeValue() const;
+ virtual void setNodeValue( const DOMString &_nodeValue, int &exceptioncode );
+
+ virtual DOMStringImpl* textContent() const;
+ virtual void setTextContent( const DOMString &text, int& exceptioncode );
+
+ // Other methods (not part of DOM)
+
+ DOMStringImpl *string() const { return str; }
+ DOMString data() const { return str; }
+
+ virtual void checkCharDataOperation( const unsigned long offset, int &exceptioncode );
+
+ virtual long minOffset() const;
+ virtual long maxOffset() const;
+
+protected:
+ // note: since DOMStrings are shared, str should always be copied when making
+ // a change or returning a string
+ DOMStringImpl *str;
+
+ void dispatchModifiedEvent(DOMStringImpl *prevValue);
+};
+
+// ----------------------------------------------------------------------------
+
+class CommentImpl : public CharacterDataImpl
+{
+public:
+ CommentImpl(DocumentImpl *doc, DOMStringImpl* _text)
+ : CharacterDataImpl(doc, _text) {}
+ CommentImpl(DocumentImpl *doc)
+ : CharacterDataImpl(doc) {}
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode(bool deep);
+
+ // Other methods (not part of DOM)
+
+ virtual Id id() const;
+ virtual bool childTypeAllowed( unsigned short type );
+
+ virtual DOMString toString() const;
+};
+
+// ----------------------------------------------------------------------------
+
+class TextImpl : public CharacterDataImpl
+{
+public:
+ TextImpl(DocumentImpl *impl, DOMStringImpl* _text)
+ : CharacterDataImpl(impl, _text) {}
+ TextImpl(DocumentImpl *impl)
+ : CharacterDataImpl(impl) {}
+
+ // DOM methods & attributes for CharacterData
+
+ TextImpl *splitText ( const unsigned long offset, int &exceptioncode );
+
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode(bool deep);
+
+ // Other methods (not part of DOM)
+
+ virtual bool isTextNode() const { return true; }
+ virtual Id id() const;
+ virtual void attach();
+ virtual bool rendererIsNeeded(tdehtml::RenderStyle *);
+ virtual tdehtml::RenderObject *createRenderer(tdehtml::RenderArena *, tdehtml::RenderStyle *);
+ virtual void recalcStyle( StyleChange = NoChange );
+ virtual bool childTypeAllowed( unsigned short type );
+
+ DOMStringImpl *renderString() const;
+
+ virtual DOMString toString() const;
+ /** Return the text for the node, with < replaced with &lt; and so on.
+ * @param startOffset The number of characters counted from the left, zero indexed, counting "<" as one character, to start from. Use -1 to start from 0.
+ * @param endOffset The number of characters counted from the left, zero indexed, counting "<" as one character, to end on. Use -1 to end at the end of the string.
+ * @return An html escaped version of the substring.
+ */
+ DOMString toString(long long startOffset, long long endOffset) const;
+protected:
+ virtual TextImpl *createNew(DOMStringImpl *_str);
+};
+
+// ----------------------------------------------------------------------------
+
+class CDATASectionImpl : public TextImpl
+{
+public:
+ CDATASectionImpl(DocumentImpl *impl, DOMStringImpl* _text)
+ : TextImpl(impl, _text) {}
+ CDATASectionImpl(DocumentImpl *impl)
+ : TextImpl(impl) {}
+
+ // DOM methods overridden from parent classes
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode(bool deep);
+
+ // Other methods (not part of DOM)
+
+ virtual bool childTypeAllowed( unsigned short type );
+
+ virtual DOMString toString() const;
+
+protected:
+ virtual TextImpl *createNew(DOMStringImpl *_str);
+};
+
+
+
+} //namespace
+#endif
diff --git a/tdehtml/xml/dom_xmlimpl.cpp b/tdehtml/xml/dom_xmlimpl.cpp
new file mode 100644
index 000000000..121ad436a
--- /dev/null
+++ b/tdehtml/xml/dom_xmlimpl.cpp
@@ -0,0 +1,498 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Peter Kelly (pmk@post.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.
+ */
+
+#include "dom/dom_exception.h"
+
+#include "xml/dom_xmlimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_stringimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "misc/loader.h"
+
+using namespace DOM;
+
+EntityImpl::EntityImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
+{
+ m_publicId = 0;
+ m_systemId = 0;
+ m_notationName = 0;
+ m_name = 0;
+}
+
+EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _name) : NodeBaseImpl(doc)
+{
+ m_publicId = 0;
+ m_systemId = 0;
+ m_notationName = 0;
+ m_name = _name.implementation();
+ if (m_name)
+ m_name->ref();
+}
+
+EntityImpl::EntityImpl(DocumentImpl *doc, DOMString _publicId, DOMString _systemId, DOMString _notationName) : NodeBaseImpl(doc)
+{
+ m_publicId = _publicId.implementation();
+ if (m_publicId)
+ m_publicId->ref();
+ m_systemId = _systemId.implementation();
+ if (m_systemId)
+ m_systemId->ref();
+ m_notationName = _notationName.implementation();
+ if (m_notationName)
+ m_notationName->ref();
+ m_name = 0;
+}
+
+
+EntityImpl::~EntityImpl()
+{
+ if (m_publicId)
+ m_publicId->deref();
+ if (m_systemId)
+ m_systemId->deref();
+ if (m_notationName)
+ m_notationName->deref();
+ if (m_name)
+ m_name->deref();
+}
+
+DOMString EntityImpl::publicId() const
+{
+ return m_publicId;
+}
+
+DOMString EntityImpl::systemId() const
+{
+ return m_systemId;
+}
+
+DOMString EntityImpl::notationName() const
+{
+ return m_notationName;
+}
+
+DOMString EntityImpl::nodeName() const
+{
+ return m_name;
+}
+
+unsigned short EntityImpl::nodeType() const
+{
+ return Node::ENTITY_NODE;
+}
+
+NodeImpl *EntityImpl::cloneNode ( bool /*deep*/)
+{
+ // Spec says cloning Document nodes is "implementation dependent"
+ // so we do not support it...
+ return 0;
+}
+
+// DOM Section 1.1.1
+bool EntityImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::ELEMENT_NODE:
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ case Node::COMMENT_NODE:
+ case Node::TEXT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+DOMString EntityImpl::toString() const
+{
+ DOMString result = "<!ENTITY' ";
+
+ if (m_name && m_name->l != 0) {
+ result += " ";
+ result += m_name;
+ }
+
+ if (m_publicId && m_publicId->l != 0) {
+ result += " PUBLIC \"";
+ result += m_publicId;
+ result += "\" \"";
+ result += m_systemId;
+ result += "\"";
+ } else if (m_systemId && m_systemId->l != 0) {
+ result += " SYSTEM \"";
+ result += m_systemId;
+ result += "\"";
+ }
+
+ if (m_notationName && m_notationName->l != 0) {
+ result += " NDATA ";
+ result += m_notationName;
+ }
+
+ result += ">";
+
+ return result;
+}
+
+// -------------------------------------------------------------------------
+
+EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
+{
+ m_entityName = 0;
+}
+
+EntityReferenceImpl::EntityReferenceImpl(DocumentImpl *doc, DOMStringImpl *_entityName) : NodeBaseImpl(doc)
+{
+ m_entityName = _entityName;
+ if (m_entityName)
+ m_entityName->ref();
+}
+
+EntityReferenceImpl::~EntityReferenceImpl()
+{
+ if (m_entityName)
+ m_entityName->deref();
+}
+
+DOMString EntityReferenceImpl::nodeName() const
+{
+ return m_entityName;
+}
+
+unsigned short EntityReferenceImpl::nodeType() const
+{
+ return Node::ENTITY_REFERENCE_NODE;
+}
+
+NodeImpl *EntityReferenceImpl::cloneNode ( bool deep )
+{
+ EntityReferenceImpl *clone = new EntityReferenceImpl(docPtr(),m_entityName);
+ // ### make sure children are readonly
+ // ### since we are a reference, should we clone children anyway (even if not deep?)
+ if (deep)
+ cloneChildNodes(clone);
+ return clone;
+}
+
+// DOM Section 1.1.1
+bool EntityReferenceImpl::childTypeAllowed( unsigned short type )
+{
+ switch (type) {
+ case Node::ELEMENT_NODE:
+ case Node::PROCESSING_INSTRUCTION_NODE:
+ case Node::COMMENT_NODE:
+ case Node::TEXT_NODE:
+ case Node::CDATA_SECTION_NODE:
+ case Node::ENTITY_REFERENCE_NODE:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+DOMString EntityReferenceImpl::toString() const
+{
+ DOMString result = "&";
+ result += m_entityName;
+ result += ";";
+
+ return result;
+}
+
+// -------------------------------------------------------------------------
+
+NotationImpl::NotationImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
+{
+ m_publicId = 0;
+ m_systemId = 0;
+ m_name = 0;
+}
+
+NotationImpl::NotationImpl(DocumentImpl *doc, DOMString _name, DOMString _publicId, DOMString _systemId) : NodeBaseImpl(doc)
+{
+ m_name = _name.implementation();
+ if (m_name)
+ m_name->ref();
+ m_publicId = _publicId.implementation();
+ if (m_publicId)
+ m_publicId->ref();
+ m_systemId = _systemId.implementation();
+ if (m_systemId)
+ m_systemId->ref();
+}
+
+NotationImpl::~NotationImpl()
+{
+ if (m_name)
+ m_name->deref();
+ if (m_publicId)
+ m_publicId->deref();
+ if (m_systemId)
+ m_systemId->deref();
+}
+
+DOMString NotationImpl::publicId() const
+{
+ return m_publicId;
+}
+
+DOMString NotationImpl::systemId() const
+{
+ return m_systemId;
+}
+
+DOMString NotationImpl::nodeName() const
+{
+ return m_name;
+}
+
+unsigned short NotationImpl::nodeType() const
+{
+ return Node::NOTATION_NODE;
+}
+
+NodeImpl *NotationImpl::cloneNode ( bool /*deep*/)
+{
+ // Spec says cloning Document nodes is "implementation dependent"
+ // so we do not support it...
+ return 0;
+}
+
+// DOM Section 1.1.1
+bool NotationImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+// -------------------------------------------------------------------------
+
+// ### need a way of updating these properly whenever child nodes of the processing instruction
+// change or are added/removed
+
+ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc) : NodeBaseImpl(doc)
+{
+ m_target = 0;
+ m_data = 0;
+ m_localHref = 0;
+ m_sheet = 0;
+ m_cachedSheet = 0;
+}
+
+ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentImpl *doc, DOMString _target, DOMString _data) : NodeBaseImpl(doc)
+{
+ m_target = _target.implementation();
+ if (m_target)
+ m_target->ref();
+ m_data = _data.implementation();
+ if (m_data)
+ m_data->ref();
+ m_sheet = 0;
+ m_cachedSheet = 0;
+ m_localHref = 0;
+}
+
+ProcessingInstructionImpl::~ProcessingInstructionImpl()
+{
+ if (m_target)
+ m_target->deref();
+ if (m_data)
+ m_data->deref();
+ if (m_cachedSheet)
+ m_cachedSheet->deref(this);
+ if (m_sheet)
+ m_sheet->deref();
+}
+
+DOMString ProcessingInstructionImpl::target() const
+{
+ return m_target;
+}
+
+void ProcessingInstructionImpl::setData( const DOMString &_data, int &exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
+ if (isReadOnly()) {
+ exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+ return;
+ }
+
+ if (m_data)
+ m_data->deref();
+ m_data = _data.implementation();
+ if (m_data)
+ m_data->ref();
+}
+
+DOMString ProcessingInstructionImpl::nodeName() const
+{
+ return m_target;
+}
+
+unsigned short ProcessingInstructionImpl::nodeType() const
+{
+ return Node::PROCESSING_INSTRUCTION_NODE;
+}
+
+DOMString ProcessingInstructionImpl::nodeValue() const
+{
+ return m_data;
+}
+
+void ProcessingInstructionImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode )
+{
+ // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
+ setData(_nodeValue, exceptioncode);
+}
+
+NodeImpl *ProcessingInstructionImpl::cloneNode ( bool /*deep*/)
+{
+ // ### copy m_localHref
+ return new ProcessingInstructionImpl(docPtr(),m_target,m_data);
+}
+
+DOMString ProcessingInstructionImpl::localHref() const
+{
+ return m_localHref;
+}
+
+// DOM Section 1.1.1
+bool ProcessingInstructionImpl::childTypeAllowed( unsigned short /*type*/ )
+{
+ return false;
+}
+
+void ProcessingInstructionImpl::checkStyleSheet()
+{
+ if (m_target && DOMString(m_target) == "xml-stylesheet") {
+ // see http://www.w3.org/TR/xml-stylesheet/
+ // ### check that this occurs only in the prolog
+ // ### support stylesheet included in a fragment of this (or another) document
+ // ### make sure this gets called when adding from javascript
+ XMLAttributeReader attrReader(DOMString(m_data).string());
+ bool attrsOk;
+ TQXmlAttributes attrs = attrReader.readAttrs(attrsOk);
+ if (!attrsOk)
+ return;
+ if (attrs.value("type") != "text/css" && !attrs.value("type").isEmpty())
+ return;
+
+ DOMString href = attrs.value("href");
+
+ if (href.length()>1)
+ {
+ if (href[0]=='#')
+ {
+ if (m_localHref)
+ m_localHref->deref();
+ m_localHref=href.implementation()->split(1);
+ if (m_localHref)
+ m_localHref->ref();
+ }
+ else
+ {
+ // ### some validation on the URL?
+ // ### FIXME charset
+ if (m_cachedSheet) m_cachedSheet->deref(this);
+ m_cachedSheet = getDocument()->docLoader()->requestStyleSheet(getDocument()->completeURL(href.string()), TQString::null);
+ if (m_cachedSheet) {
+ getDocument()->addPendingSheet(); //before ref, because during the ref it might load!
+ m_cachedSheet->ref( this );
+ }
+ }
+
+ }
+ }
+}
+
+StyleSheetImpl *ProcessingInstructionImpl::sheet() const
+{
+ return m_sheet;
+}
+
+void ProcessingInstructionImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset)
+{
+ if (m_sheet)
+ m_sheet->deref();
+ m_sheet = new CSSStyleSheetImpl(getDocument(), url);
+ m_sheet->ref();
+ m_sheet->setCharset(charset);
+ m_sheet->parseString(sheet);
+ if (m_cachedSheet)
+ m_cachedSheet->deref(this);
+ m_cachedSheet = 0;
+
+ getDocument()->styleSheetLoaded();
+}
+
+void ProcessingInstructionImpl::setStyleSheet(CSSStyleSheetImpl* sheet)
+{
+ if (m_sheet)
+ m_sheet->deref();
+ m_sheet = sheet;
+ if (m_sheet)
+ m_sheet->ref();
+}
+
+DOMString ProcessingInstructionImpl::toString() const
+{
+ DOMString result = "<?";
+ result += m_target;
+ result += " ";
+ result += m_data;
+ result += ">";
+ return result;
+}
+
+// -------------------------------------------------------------------------
+
+XMLAttributeReader::XMLAttributeReader(const TQString& _attrString)
+{
+ m_attrString = _attrString;
+}
+
+XMLAttributeReader::~XMLAttributeReader()
+{
+}
+
+TQXmlAttributes XMLAttributeReader::readAttrs(bool &ok)
+{
+ // parse xml file
+ TQXmlInputSource source;
+ source.setData("<?xml version=\"1.0\"?><attrs "+m_attrString+" />");
+ TQXmlSimpleReader reader;
+ reader.setContentHandler( this );
+ ok = reader.parse( source );
+ return attrs;
+}
+
+bool XMLAttributeReader::startElement(const TQString& /*namespaceURI*/, const TQString& localName,
+ const TQString& /*qName*/, const TQXmlAttributes& atts)
+{
+ if (localName == "attrs") {
+ attrs = atts;
+ return true;
+ }
+ else
+ return false; // we shouldn't have any other elements
+}
diff --git a/tdehtml/xml/dom_xmlimpl.h b/tdehtml/xml/dom_xmlimpl.h
new file mode 100644
index 000000000..29ad1471f
--- /dev/null
+++ b/tdehtml/xml/dom_xmlimpl.h
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _DOM_XmlImpl_h_
+#define _DOM_XmlImpl_h_
+
+#include "xml/dom_nodeimpl.h"
+#include "misc/loader_client.h"
+
+#include <tqxml.h>
+
+namespace tdehtml {
+class CachedCSSStyleSheet;
+}
+
+namespace DOM {
+
+class DocumentImpl;
+class CSSStyleSheetImpl;
+class StyleSheetImpl;
+class DOMString;
+
+class EntityImpl : public NodeBaseImpl
+{
+public:
+ EntityImpl(DocumentImpl *doc);
+ EntityImpl(DocumentImpl *doc, DOMString _name);
+ EntityImpl(DocumentImpl *doc, DOMString _publicId, DOMString _systemId, DOMString _notationName);
+ virtual ~EntityImpl();
+
+ // DOM methods & attributes for Entity
+
+ virtual DOMString publicId() const;
+ virtual DOMString systemId() const;
+ virtual DOMString notationName() const;
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+
+ virtual bool childTypeAllowed( unsigned short type );
+
+ virtual DOMString toString() const;
+
+protected:
+ DOMStringImpl *m_publicId;
+ DOMStringImpl *m_systemId;
+ DOMStringImpl *m_notationName;
+ DOMStringImpl *m_name;
+};
+
+
+class EntityReferenceImpl : public NodeBaseImpl
+{
+public:
+ EntityReferenceImpl(DocumentImpl *doc);
+ EntityReferenceImpl(DocumentImpl *doc, DOMStringImpl *_entityName);
+ virtual ~EntityReferenceImpl();
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+
+ virtual bool childTypeAllowed( unsigned short type );
+
+ virtual DOMString toString() const;
+protected:
+ DOMStringImpl *m_entityName;
+};
+
+class NotationImpl : public NodeBaseImpl
+{
+public:
+ NotationImpl(DocumentImpl *doc);
+ NotationImpl(DocumentImpl *doc, DOMString _name, DOMString _publicId, DOMString _systemId);
+ virtual ~NotationImpl();
+
+ // DOM methods & attributes for Notation
+
+ virtual DOMString publicId() const;
+ virtual DOMString systemId() const;
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+
+ virtual bool childTypeAllowed( unsigned short type );
+protected:
+ DOMStringImpl *m_name;
+ DOMStringImpl *m_publicId;
+ DOMStringImpl *m_systemId;
+};
+
+
+class ProcessingInstructionImpl : public NodeBaseImpl, private tdehtml::CachedObjectClient
+{
+public:
+ ProcessingInstructionImpl(DocumentImpl *doc);
+ ProcessingInstructionImpl(DocumentImpl *doc, DOMString _target, DOMString _data);
+ virtual ~ProcessingInstructionImpl();
+
+ // DOM methods & attributes for Notation
+
+ virtual DOMString target() const;
+ DOMString data() const { return m_data; }
+ virtual void setData( const DOMString &_data, int &exceptioncode );
+
+ // DOM methods overridden from parent classes
+
+ virtual DOMString nodeName() const;
+ virtual unsigned short nodeType() const;
+ virtual DOMString nodeValue() const;
+ virtual void setNodeValue( const DOMString &_nodeValue, int &exceptioncode );
+ virtual NodeImpl *cloneNode ( bool deep );
+
+ // Other methods (not part of DOM)
+
+ virtual DOMString localHref() const;
+ virtual bool childTypeAllowed( unsigned short type );
+ StyleSheetImpl *sheet() const;
+ void checkStyleSheet();
+ virtual void setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset);
+ virtual void setStyleSheet(CSSStyleSheetImpl* sheet);
+
+ virtual DOMString toString() const;
+
+protected:
+ DOMStringImpl *m_target;
+ DOMStringImpl *m_data;
+ DOMStringImpl *m_localHref;
+ tdehtml::CachedCSSStyleSheet *m_cachedSheet;
+ CSSStyleSheetImpl *m_sheet;
+};
+
+class XMLAttributeReader : public TQXmlDefaultHandler
+{
+public:
+ XMLAttributeReader(const TQString& _attrString);
+ virtual ~XMLAttributeReader();
+ TQXmlAttributes readAttrs(bool &ok);
+ bool startElement(const TQString& namespaceURI, const TQString& localName, const TQString& qName, const TQXmlAttributes& atts);
+
+protected:
+ TQXmlAttributes attrs;
+ TQString m_attrString;
+};
+
+} //namespace
+
+#endif
diff --git a/tdehtml/xml/xml_tokenizer.cpp b/tdehtml/xml/xml_tokenizer.cpp
new file mode 100644
index 000000000..ff4a33a99
--- /dev/null
+++ b/tdehtml/xml/xml_tokenizer.cpp
@@ -0,0 +1,609 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Peter Kelly (pmk@post.com)
+ * Copyright (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.
+ */
+
+
+#include "xml_tokenizer.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom_xmlimpl.h"
+#include "html/html_tableimpl.h"
+#include "html/html_headimpl.h"
+#include "rendering/render_object.h"
+#include "misc/htmltags.h"
+#include "misc/htmlattrs.h"
+#include "misc/loader.h"
+
+#include "tdehtmlview.h"
+#include "tdehtml_part.h"
+#include <tqvariant.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace DOM;
+using namespace tdehtml;
+
+XMLIncrementalSource::XMLIncrementalSource()
+ : TQXmlInputSource(), m_pos( 0 ), m_unicode( 0 ),
+ m_finished( false )
+{
+}
+
+void XMLIncrementalSource::fetchData()
+{
+ //just a dummy to overwrite default behavior
+}
+
+TQChar XMLIncrementalSource::next()
+{
+ if ( m_finished )
+ return TQXmlInputSource::EndOfDocument;
+ else if ( m_data.length() <= m_pos )
+ return TQXmlInputSource::EndOfData;
+ else
+ return m_unicode[m_pos++];
+}
+
+void XMLIncrementalSource::setData( const TQString& str )
+{
+ m_data = str;
+ m_unicode = m_data.unicode();
+ m_pos = 0;
+ if ( !str.isEmpty() )
+ m_finished = false;
+}
+void XMLIncrementalSource::setData( const TQByteArray& data )
+{
+ setData( fromRawData( data, true ) );
+}
+
+void XMLIncrementalSource::appendXML( const TQString& str )
+{
+ m_data += str;
+ m_unicode = m_data.unicode();
+}
+
+TQString XMLIncrementalSource::data()
+{
+ return m_data;
+}
+
+void XMLIncrementalSource::setFinished( bool finished )
+{
+ m_finished = finished;
+}
+
+XMLHandler::XMLHandler(DocumentImpl *_doc, KHTMLView *_view)
+ : errorLine(0)
+{
+ m_doc = _doc;
+ m_view = _view;
+ pushNode( _doc );
+}
+
+XMLHandler::~XMLHandler()
+{
+}
+
+void XMLHandler::pushNode( NodeImpl *node )
+{
+ m_nodes.push( node );
+}
+
+NodeImpl *XMLHandler::popNode()
+{
+ return m_nodes.pop();
+}
+
+NodeImpl *XMLHandler::currentNode() const
+{
+ return m_nodes.current();
+}
+
+TQString XMLHandler::errorProtocol()
+{
+ return errorProt;
+}
+
+
+bool XMLHandler::startDocument()
+{
+ // at the beginning of parsing: do some initialization
+ errorProt = "";
+ state = StateInit;
+
+ return true;
+}
+
+bool XMLHandler::startPrefixMapping(const TQString& prefix, const TQString& uri)
+{
+ namespaceInfo[prefix].push(uri);
+ return true;
+}
+
+bool XMLHandler::endPrefixMapping(const TQString& prefix)
+{
+ TQValueStack<TQString>& stack = namespaceInfo[prefix];
+ stack.pop();
+ if (stack.isEmpty())
+ namespaceInfo.remove(prefix);
+ return true;
+}
+
+void XMLHandler::fixUpNSURI(TQString& uri, const TQString& qname)
+{
+ /* QXml does not resolve the namespaces of attributes in the same
+ tag that preceed the xmlns declaration. This fixes up that case */
+ if (uri.isEmpty() && qname.find(':') != -1) {
+ TQXmlNamespaceSupport ns;
+ TQString localName, prefix;
+ ns.splitName(qname, prefix, localName);
+ if (namespaceInfo.contains(prefix)) {
+ uri = namespaceInfo[prefix].top();
+ }
+ }
+}
+
+bool XMLHandler::startElement( const TQString& namespaceURI, const TQString& /*localName*/,
+ const TQString& qName, const TQXmlAttributes& atts )
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE)
+ exitText();
+
+ DOMString nsURI;
+ if (!namespaceURI.isNull())
+ nsURI = DOMString(namespaceURI);
+ else
+ // No namespace declared, default to the no namespace
+ nsURI = DOMString("");
+ ElementImpl *newElement = m_doc->createElementNS(nsURI,qName);
+ if (!newElement)
+ return false;
+ int i;
+ for (i = 0; i < atts.length(); i++) {
+ int exceptioncode = 0;
+ TQString uriString = atts.uri(i);
+ TQString qnString = atts.qName(i);
+ fixUpNSURI(uriString, qnString);
+ DOMString uri(uriString);
+ DOMString qn(qnString);
+ DOMString val(atts.value(i));
+ newElement->setAttributeNS(uri, qn, val, exceptioncode);
+ if (exceptioncode) // exception setting attributes
+ return false;
+ }
+
+ if (newElement->id() == ID_SCRIPT || newElement->id() == makeId(xhtmlNamespace, ID_SCRIPT))
+ static_cast<HTMLScriptElementImpl *>(newElement)->setCreatedByParser(true);
+
+ //this is tricky. in general the node doesn't have to attach to the one it's in. as far
+ //as standards go this is wrong, but there's literally thousands of documents where
+ //we see <p><ul>...</ul></p>. the following code is there for those cases.
+ //when we can't attach to the currently holding us node we try to attach to its parent
+ bool attached = false;
+ for ( NodeImpl *current = currentNode(); current; current = current->parent() ) {
+ attached = current->addChild( newElement );
+ if ( attached )
+ break;
+ }
+ if (attached) {
+ if (m_view && !newElement->attached() && !m_doc->hasPendingSheets())
+ newElement->attach();
+ pushNode( newElement );
+ return true;
+ }
+ else {
+ delete newElement;
+ return false;
+ }
+
+ // ### DOM spec states: "if there is no markup inside an element's content, the text is contained in a
+ // single object implementing the Text interface that is the only child of the element."... do we
+ // need to ensure that empty elements always have an empty text child?
+}
+
+
+bool XMLHandler::endElement( const TQString& /*namespaceURI*/, const TQString& /*localName*/, const TQString& /*qName*/ )
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE)
+ exitText();
+
+ NodeImpl *node = popNode();
+ if ( node ) {
+ node->close();
+ while ( currentNode() && currentNode()->implicitNode() ) //for the implicit HTMLTableSectionElementImpl
+ popNode()->close();
+ } else
+ return false;
+
+ return true;
+}
+
+
+bool XMLHandler::startCDATA()
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE)
+ exitText();
+
+ NodeImpl *newNode = m_doc->createCDATASection(new DOMStringImpl(""));
+ if (currentNode()->addChild(newNode)) {
+ if (m_view && !newNode->attached() && !m_doc->hasPendingSheets())
+ newNode->attach();
+ pushNode( newNode );
+ return true;
+ }
+ else {
+ delete newNode;
+ return false;
+ }
+
+}
+
+bool XMLHandler::endCDATA()
+{
+ popNode();
+ Q_ASSERT( currentNode() );
+ return currentNode();
+}
+
+bool XMLHandler::characters( const TQString& ch )
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE ||
+ currentNode()->nodeType() == Node::CDATA_SECTION_NODE ||
+ enterText()) {
+ int exceptioncode = 0;
+ static_cast<TextImpl*>(currentNode())->appendData(ch,exceptioncode);
+ if (exceptioncode)
+ return false;
+ return true;
+ }
+ else {
+ // Don't worry about white-space violating DTD
+ if (ch.stripWhiteSpace().isEmpty()) return true;
+
+ return false;
+ }
+
+}
+
+bool XMLHandler::comment(const TQString & ch)
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE)
+ exitText();
+ // ### handle exceptions
+ currentNode()->addChild(m_doc->createComment(new DOMStringImpl(ch.unicode(), ch.length())));
+ return true;
+}
+
+bool XMLHandler::processingInstruction(const TQString &target, const TQString &data)
+{
+ if (currentNode()->nodeType() == Node::TEXT_NODE)
+ exitText();
+ // ### handle exceptions
+ ProcessingInstructionImpl *pi =
+ m_doc->createProcessingInstruction(target, new DOMStringImpl(data.unicode(), data.length()));
+ currentNode()->addChild(pi);
+ pi->checkStyleSheet();
+ return true;
+}
+
+
+TQString XMLHandler::errorString()
+{
+ // ### Make better error-messages
+ return i18n("the document is not in the correct file format");
+}
+
+
+bool XMLHandler::fatalError( const TQXmlParseException& exception )
+{
+ errorProt += i18n( "fatal parsing error: %1 in line %2, column %3" )
+ .arg( exception.message() )
+ .arg( exception.lineNumber() )
+ .arg( exception.columnNumber() );
+
+ errorLine = exception.lineNumber();
+ errorCol = exception.columnNumber();
+
+ return false;
+}
+
+bool XMLHandler::enterText()
+{
+ NodeImpl *newNode = m_doc->createTextNode("");
+ if (currentNode()->addChild(newNode)) {
+ pushNode( newNode );
+ return true;
+ }
+ else {
+ delete newNode;
+ return false;
+ }
+}
+
+void XMLHandler::exitText()
+{
+ if ( m_view && !currentNode()->attached() && !m_doc->hasPendingSheets() )
+ currentNode()->attach();
+ popNode();
+}
+
+bool XMLHandler::attributeDecl(const TQString &/*eName*/, const TQString &/*aName*/, const TQString &/*type*/,
+ const TQString &/*valueDefault*/, const TQString &/*value*/)
+{
+ // qt's xml parser (as of 2.2.3) does not currently give us values for type, valueDefault and
+ // value. When it does, we can store these somewhere and have default attributes on elements
+ return true;
+}
+
+bool XMLHandler::externalEntityDecl(const TQString &/*name*/, const TQString &/*publicId*/, const TQString &/*systemId*/)
+{
+ // ### insert these too - is there anything special we have to do here?
+ return true;
+}
+
+bool XMLHandler::internalEntityDecl(const TQString &name, const TQString &value)
+{
+ EntityImpl *e = new EntityImpl(m_doc,name);
+ // ### further parse entities inside the value and add them as separate nodes (or entityreferences)?
+ e->addChild(m_doc->createTextNode(new DOMStringImpl(value.unicode(), value.length())));
+ if (m_doc->doctype())
+ static_cast<GenericRONamedNodeMapImpl*>(m_doc->doctype()->entities())->addNode(e);
+ return true;
+}
+
+bool XMLHandler::notationDecl(const TQString &/*name*/, const TQString &/*publicId*/, const TQString &/*systemId*/)
+{
+// ### FIXME
+// if (m_doc->document()->doctype()) {
+// NotationImpl *n = new NotationImpl(m_doc,name,publicId,systemId);
+// static_cast<GenericRONamedNodeMapImpl*>(m_doc->document()->doctype()->notations())->addNode(n);
+// }
+ return true;
+}
+
+bool XMLHandler::unparsedEntityDecl(const TQString &/*name*/, const TQString &/*publicId*/,
+ const TQString &/*systemId*/, const TQString &/*notationName*/)
+{
+ // ###
+ return true;
+}
+
+
+//------------------------------------------------------------------------------
+
+XMLTokenizer::XMLTokenizer(DOM::DocumentImpl *_doc, KHTMLView *_view)
+ : m_handler(_doc,_view)
+{
+ m_doc = _doc;
+ m_view = _view;
+ m_scriptsIt = 0;
+ m_cachedScript = 0;
+ m_noErrors = true;
+ m_reader.setContentHandler( &m_handler );
+ m_reader.setLexicalHandler( &m_handler );
+ m_reader.setErrorHandler( &m_handler );
+ m_reader.setDeclHandler( &m_handler );
+ m_reader.setDTDHandler( &m_handler );
+ m_reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+}
+
+XMLTokenizer::~XMLTokenizer()
+{
+ if (m_scriptsIt)
+ delete m_scriptsIt;
+ if (m_cachedScript)
+ m_cachedScript->deref(this);
+}
+
+
+void XMLTokenizer::begin()
+{
+ // parse xml file
+ m_reader.parse( &m_source, true );
+}
+
+void XMLTokenizer::write( const TokenizerString &str, bool appendData )
+{
+ if ( !m_noErrors && appendData )
+ return;
+ if ( appendData ) {
+ m_source.appendXML( str.toString() );
+
+ } else {
+ m_source.setData( str.toString() );
+ }
+ m_noErrors = m_reader.parseContinue();
+}
+
+void XMLTokenizer::end()
+{
+ m_source.setFinished( true );
+ //if ( m_noErrors )
+ //m_noErrors = m_reader.parseContinue();
+ emit finishedParsing();
+}
+
+void XMLTokenizer::finish()
+{
+ m_source.setFinished( true );
+ if (!m_noErrors) {
+ // An error occurred during parsing of the code. Display an error page to the user (the DOM
+ // tree is created manually and includes an excerpt from the code where the error is located)
+
+ // ### for multiple error messages, display the code for each (can this happen?)
+
+ // Clear the document
+ int exceptioncode = 0;
+ while (m_doc->hasChildNodes())
+ static_cast<NodeImpl*>(m_doc)->removeChild(m_doc->firstChild(),exceptioncode);
+
+ TQString line, errorLocPtr;
+ if ( m_handler.errorLine ) {
+ TQString xmlCode = m_source.data();
+ TQTextIStream stream(&xmlCode);
+ for (unsigned long lineno = 0; lineno < m_handler.errorLine-1; lineno++)
+ stream.readLine();
+ line = stream.readLine();
+
+ for (unsigned long colno = 0; colno < m_handler.errorCol-1; colno++)
+ errorLocPtr += " ";
+ errorLocPtr += "^";
+ }
+
+ // Create elements for display
+ DocumentImpl *doc = m_doc;
+ NodeImpl *html = doc->createElementNS(XHTML_NAMESPACE,"html");
+ NodeImpl *body = doc->createElementNS(XHTML_NAMESPACE,"body");
+ NodeImpl *h1 = doc->createElementNS(XHTML_NAMESPACE,"h1");
+ NodeImpl *headingText = doc->createTextNode(i18n("XML parsing error"));
+ NodeImpl *errorText = doc->createTextNode(m_handler.errorProtocol());
+ NodeImpl *hr = 0;
+ NodeImpl *pre = 0;
+ NodeImpl *lineText = 0;
+ NodeImpl *errorLocText = 0;
+ if ( !line.isNull() ) {
+ hr = doc->createElementNS(XHTML_NAMESPACE,"hr");
+ pre = doc->createElementNS(XHTML_NAMESPACE,"pre");
+ lineText = doc->createTextNode(line+"\n");
+ errorLocText = doc->createTextNode(errorLocPtr);
+ }
+
+ // Construct DOM tree. We ignore exceptions as we assume they will not be thrown here (due to the
+ // fact we are using a known tag set)
+ doc->appendChild(html,exceptioncode);
+ html->appendChild(body,exceptioncode);
+ if ( body )
+ body->appendChild(h1,exceptioncode);
+ h1->appendChild(headingText,exceptioncode);
+ body->appendChild(errorText,exceptioncode);
+ body->appendChild(hr,exceptioncode);
+ body->appendChild(pre,exceptioncode);
+ if ( pre ) {
+ pre->appendChild(lineText,exceptioncode);
+ pre->appendChild(errorLocText,exceptioncode);
+ }
+
+ // Close the renderers so that they update their display correctly
+ // ### this should not be necessary, but requires changes in the rendering code...
+ h1->close();
+ if ( pre ) pre->close();
+ body->close();
+
+ m_doc->recalcStyle( NodeImpl::Inherit );
+ m_doc->updateRendering();
+
+ end();
+ }
+ else {
+ // Parsing was successful. Now locate all html <script> tags in the document and execute them
+ // one by one
+ addScripts(m_doc);
+ m_scriptsIt = new TQPtrListIterator<HTMLScriptElementImpl>(m_scripts);
+ executeScripts();
+ }
+
+}
+
+void XMLTokenizer::addScripts(NodeImpl *n)
+{
+ // Recursively go through the entire document tree, looking for html <script> tags. For each of these
+ // that is found, add it to the m_scripts list from which they will be executed
+
+ if (n->id() == ID_SCRIPT || n->id() == makeId(xhtmlNamespace, ID_SCRIPT)) {
+ m_scripts.append(static_cast<HTMLScriptElementImpl*>(n));
+ }
+
+ NodeImpl *child;
+ for (child = n->firstChild(); child; child = child->nextSibling())
+ addScripts(child);
+}
+
+void XMLTokenizer::executeScripts()
+{
+ // Iterate through all of the html <script> tags in the document. For those that have a src attribute,
+ // start loading the script and return (executeScripts() will be called again once the script is loaded
+ // and continue where it left off). For scripts that don't have a src attribute, execute the code
+ // inside the tag
+ while (m_scriptsIt->current()) {
+ DOMString scriptSrc = m_scriptsIt->current()->getAttribute(ATTR_SRC);
+ TQString charset = m_scriptsIt->current()->getAttribute(ATTR_CHARSET).string();
+
+ if (!scriptSrc.isEmpty()) {
+ // we have a src attribute
+ m_cachedScript = m_doc->docLoader()->requestScript(scriptSrc, charset);
+ ++(*m_scriptsIt);
+ if (m_cachedScript) {
+ m_cachedScript->ref(this); // will call executeScripts() again if already cached
+ return;
+ }
+ }
+ else {
+ // no src attribute - execute from contents of tag
+ TQString scriptCode = "";
+ NodeImpl *child;
+ for (child = m_scriptsIt->current()->firstChild(); child; child = child->nextSibling()) {
+ if ( ( child->nodeType() == Node::TEXT_NODE || child->nodeType() == Node::CDATA_SECTION_NODE) &&
+ static_cast<TextImpl*>(child)->string() )
+ scriptCode += TQConstString(static_cast<TextImpl*>(child)->string()->s,
+ static_cast<TextImpl*>(child)->string()->l).string();
+ }
+ // the script cannot do document.write until we support incremental parsing
+ // ### handle the case where the script deletes the node or redirects to
+ // another page, etc. (also in notifyFinished())
+ // ### the script may add another script node after this one which should be executed
+ if (m_view) {
+ m_view->part()->executeScript(DOM::Node(), scriptCode);
+ }
+ ++(*m_scriptsIt);
+ }
+ }
+
+ // All scripts have finished executing, so calculate the style for the document and close
+ // the last element
+ m_doc->updateStyleSelector();
+
+ // We are now finished parsing
+ end();
+}
+
+void XMLTokenizer::notifyFinished(CachedObject *finishedObj)
+{
+ // This is called when a script has finished loading that was requested from executeScripts(). We execute
+ // the script, and then call executeScripts() again to continue iterating through the list of scripts in
+ // the document
+ if (finishedObj == m_cachedScript) {
+ DOMString scriptSource = m_cachedScript->script();
+ m_cachedScript->deref(this);
+ m_cachedScript = 0;
+ if (m_view)
+ m_view->part()->executeScript(DOM::Node(), scriptSource.string());
+ executeScripts();
+ }
+}
+
+bool XMLTokenizer::isWaitingForScripts() const
+{
+ return m_cachedScript != 0;
+}
+
+#include "xml_tokenizer.moc"
+
diff --git a/tdehtml/xml/xml_tokenizer.h b/tdehtml/xml/xml_tokenizer.h
new file mode 100644
index 000000000..49a9c970d
--- /dev/null
+++ b/tdehtml/xml/xml_tokenizer.h
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2000 Peter Kelly (pmk@post.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.
+ *
+ */
+
+#ifndef _XML_Tokenizer_h_
+#define _XML_Tokenizer_h_
+
+#include <tqxml.h>
+#include <tqptrlist.h>
+#include <tqptrstack.h>
+#include <tqvaluestack.h>
+#include <tqobject.h>
+#include "misc/loader_client.h"
+#include "misc/stringit.h"
+
+class KHTMLView;
+
+namespace tdehtml {
+ class CachedObject;
+ class CachedScript;
+}
+
+namespace DOM {
+ class DocumentImpl;
+ class NodeImpl;
+ class HTMLScriptElementImpl;
+ class DocumentImpl;
+ class HTMLScriptElementImpl;
+}
+
+namespace tdehtml {
+
+class XMLHandler : public TQXmlDefaultHandler
+{
+public:
+ XMLHandler(DOM::DocumentImpl *_doc, KHTMLView *_view);
+ virtual ~XMLHandler();
+
+ // return the error protocol if parsing failed
+ TQString errorProtocol();
+
+ // overloaded handler functions
+ bool startDocument();
+ bool startElement(const TQString& namespaceURI, const TQString& localName, const TQString& qName, const TQXmlAttributes& atts);
+ bool endElement(const TQString& namespaceURI, const TQString& localName, const TQString& qName);
+ bool startCDATA();
+ bool endCDATA();
+ bool characters(const TQString& ch);
+ bool comment(const TQString & ch);
+ bool processingInstruction(const TQString &target, const TQString &data);
+
+ // namespace handling, to workaround problem in QXML where some attributes
+ // do not get the namespace resolved properly
+ bool startPrefixMapping(const TQString& prefix, const TQString& uri);
+ bool endPrefixMapping(const TQString& prefix);
+ void fixUpNSURI(TQString& uri, const TQString& qname);
+ TQMap<TQString, TQValueStack<TQString> > namespaceInfo;
+
+
+ // from QXmlDeclHandler
+ bool attributeDecl(const TQString &eName, const TQString &aName, const TQString &type, const TQString &valueDefault, const TQString &value);
+ bool externalEntityDecl(const TQString &name, const TQString &publicId, const TQString &systemId);
+ bool internalEntityDecl(const TQString &name, const TQString &value);
+
+ // from QXmlDTDHandler
+ bool notationDecl(const TQString &name, const TQString &publicId, const TQString &systemId);
+ bool unparsedEntityDecl(const TQString &name, const TQString &publicId, const TQString &systemId, const TQString &notationName);
+
+ bool enterText();
+ void exitText();
+
+ TQString errorString();
+
+ bool fatalError( const TQXmlParseException& exception );
+
+ unsigned long errorLine;
+ unsigned long errorCol;
+
+private:
+ void pushNode( DOM::NodeImpl *node );
+ DOM::NodeImpl *popNode();
+ DOM::NodeImpl *currentNode() const;
+private:
+ TQString errorProt;
+ DOM::DocumentImpl *m_doc;
+ KHTMLView *m_view;
+ TQPtrStack<DOM::NodeImpl> m_nodes;
+ DOM::NodeImpl *m_rootNode;
+
+ enum State {
+ StateInit,
+ StateDocument,
+ StateQuote,
+ StateLine,
+ StateHeading,
+ StateP
+ };
+ State state;
+};
+
+class Tokenizer : public TQObject
+{
+ Q_OBJECT
+public:
+ virtual void begin() = 0;
+ // script output must be prepended, while new data
+ // received during executing a script must be appended, hence the
+ // extra bool to be able to distinguish between both cases. document.write()
+ // always uses false, while tdehtmlpart uses true
+ virtual void write( const TokenizerString &str, bool appendData) = 0;
+ virtual void end() = 0;
+ virtual void finish() = 0;
+ virtual void setOnHold(bool /*_onHold*/) {}
+ virtual bool isWaitingForScripts() const = 0;
+ virtual bool isExecutingScript() const = 0;
+ virtual void abort() {}
+ virtual void setAutoClose(bool b=true) = 0;
+
+signals:
+ void finishedParsing();
+
+};
+
+class XMLIncrementalSource : public TQXmlInputSource
+{
+public:
+ XMLIncrementalSource();
+ virtual void fetchData();
+ virtual TQChar next();
+ virtual void setData( const TQString& str );
+ virtual void setData( const TQByteArray& data );
+ virtual TQString data();
+
+ void appendXML( const TQString& str );
+ void setFinished( bool );
+
+private:
+ TQString m_data;
+ uint m_pos;
+ const TQChar *m_unicode;
+ bool m_finished;
+};
+
+class XMLTokenizer : public Tokenizer, public tdehtml::CachedObjectClient
+{
+public:
+ XMLTokenizer(DOM::DocumentImpl *, KHTMLView * = 0);
+ virtual ~XMLTokenizer();
+ virtual void begin();
+ virtual void write( const TokenizerString &str, bool );
+ virtual void end();
+ virtual void finish();
+ virtual void setAutoClose(bool b=true) { tqWarning("XMLTokenizer::setAutoClose: stub."); (void)b; }
+
+ // from CachedObjectClient
+ void notifyFinished(tdehtml::CachedObject *finishedObj);
+
+ virtual bool isWaitingForScripts() const;
+ virtual bool isExecutingScript() const { return false; }
+
+protected:
+ DOM::DocumentImpl *m_doc;
+ KHTMLView *m_view;
+
+ void executeScripts();
+ void addScripts(DOM::NodeImpl *n);
+
+ TQPtrList<DOM::HTMLScriptElementImpl> m_scripts;
+ TQPtrListIterator<DOM::HTMLScriptElementImpl> *m_scriptsIt;
+ tdehtml::CachedScript *m_cachedScript;
+
+ XMLHandler m_handler;
+ TQXmlSimpleReader m_reader;
+ XMLIncrementalSource m_source;
+ bool m_noErrors;
+};
+
+} // end namespace
+
+#endif