Browse Source

* Merging fcl-web_joost branch into trunk
--- Merging r13710 through r14654 into '.':
G utils/debugsvr/README.txt
G utils/fpmc/README.txt
G utils/tply/COPYING.txt
G utils/tply/README.txt
G utils/fpdoc/COPYING.txt
G utils/fpdoc/README.txt
G utils/fppkg/README.txt
G utils/README.txt
G utils/h2pas/README.txt
G ide/README.txt
G ide/TODO.txt
G rtl/macos/README.txt
G rtl/freebsd/x86_64/cprt0.as
G rtl/freebsd/x86_64/gprt0.as
G rtl/freebsd/buildrtl.pp
G rtl/freebsd/buildrtl.lpi
G rtl/COPYING.txt
G rtl/netware/README.txt
G rtl/inc/ustrings.inc
C rtl/inc/objpash.inc
G rtl/inc/ustringh.inc
G rtl/README.txt
G rtl/objpas/README.txt
G tests/test/README.txt
G tests/test/tunistr6.pp
G tests/test/tunistr1.pp
G tests/test/tunistr7.pp
G tests/test/tunistr2.pp
G tests/test/opt/README.txt
G tests/test/tunistr4.pp
C tests/test/tobject5.pp
G tests/test/tunistr5.pp
G tests/webtbs/uw13345y.pp
G tests/webtbs/tw11846a.pp
G tests/webtbs/tw12993.pp
G tests/webtbs/tw11846b.pp
--- Merging r13710 through r14654 into 'tests/webtbf/tw13815.pp':
U tests/webtbf/tw13815.pp
--- Merging r13710 through r14654 into 'tests/tbf/tb0216.pp':
U tests/tbf/tb0216.pp
--- Merging r13710 through r14654 into '.':
G compiler/ccharset.pas
G compiler/README.txt
G compiler/COPYING.txt
G compiler/optloop.pas
G compiler/utils/README.txt
G packages/sdl/README.txt
G packages/fcl-net/README.txt
--- Merging r13710 through r14654 into 'packages/fcl-xml/tests/README_DOM.txt':
U packages/fcl-xml/tests/README_DOM.txt
--- Merging r13710 through r14654 into '.':
G packages/fcl-xml/tests/README.txt
G packages/fcl-xml/src/README.txt
--- Merging r13710 through r14654 into 'packages/unzip/src/unzip51g.pp':
U packages/unzip/src/unzip51g.pp
--- Merging r13710 through r14654 into '.':
G packages/libc/README.txt
G packages/newt/README.txt
G packages/fcl-process/src/dummy
G packages/fcl-db/src/memds/README.txt
G packages/fcl-db/src/README.txt
U packages/fcl-web/Makefile.fpc
A packages/fcl-web/src/webpage.pp
U packages/fcl-web/src/fphtml.pp
G packages/fcl-web/src/README.txt
C packages/fcl-web/Makefile
G packages/libgd/src/gd.pas
G packages/libgd/README.txt
G packages/ptc/docs/TODO.txt
G packages/ptc/docs/README.txt
G packages/postgres/README.txt
G packages/fcl-base/examples/intl/README.txt
G packages/fcl-base/examples/README.txt
G packages/xforms/README.txt
G packages/amunits/README.txt
G packages/ibase/README.txt
G packages/sndfile/README.txt
G packages/libxml/src/xml2.pas
G packages/svgalib/README.txt
--- Merging r13710 through r14654 into 'packages/winunits-base/src/dwmapi.pp':
U packages/winunits-base/src/dwmapi.pp
--- Merging r13710 through r14654 into '.':
G packages/cdrom/README.txt
G packages/mysql/README.txt
G packages/oracle/README.txt
G packages/gtk1/README.txt
G packages/uuid/README.txt
G packages/odbc/README.txt
G packages/gdbm/README.txt
Summary of conflicts:
Text conflicts: 2
Tree conflicts: 1

git-svn-id: trunk@14808 -

joost 15 years ago
parent
commit
8ef245699a

+ 1 - 0
.gitattributes

@@ -2173,6 +2173,7 @@ packages/fcl-web/src/fphttp.pp svneol=native#text/plain
 packages/fcl-web/src/fptemplate.pp svneol=native#text/plain
 packages/fcl-web/src/fpweb.pp svneol=native#text/plain
 packages/fcl-web/src/httpdefs.pp svneol=native#text/plain
+packages/fcl-web/src/webpage.pp svneol=native#text/plain
 packages/fcl-web/src/websession.pp svneol=native#text/plain
 packages/fcl-web/src/webutil.pp svneol=native#text/plain
 packages/fcl-xml/Makefile svneol=native#text/plain

+ 90 - 62
packages/fcl-web/Makefile

@@ -1,8 +1,8 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/12/10]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2010/01/26]
 #
 default: all
-MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-solaris x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded mipsel-linux
 BSDs = freebsd netbsd openbsd darwin
 UNIXs = linux $(BSDs) solaris qnx haiku
 LIMIT83fs = go32v2 os2 emx watcom
@@ -267,184 +267,187 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F
 override PACKAGE_NAME=fcl-web
 override PACKAGE_VERSION=2.5.1
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache  custfcgi fpfcgi
+override TARGET_UNITS+=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb webutil fpdatasetform cgiapp ezcgi fpapache webpage  custfcgi fpfcgi
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_RSTS+=fpcgi fphtml fpweb websession cgiapp
@@ -506,6 +509,9 @@ endif
 ifeq ($(FULL_TARGET),i386-symbian)
 override TARGET_RSTS+=fpcgi fphtml fpweb websession cgiapp
 endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override TARGET_RSTS+=fpcgi fphtml fpweb websession cgiapp
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override TARGET_RSTS+=fpcgi fphtml fpweb websession cgiapp
 endif
@@ -687,6 +693,9 @@ endif
 ifeq ($(FULL_TARGET),i386-symbian)
 override COMPILER_OPTIONS+=-S2h
 endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_OPTIONS+=-S2h
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_OPTIONS+=-S2h
 endif
@@ -867,6 +876,9 @@ endif
 ifeq ($(FULL_TARGET),i386-symbian)
 override COMPILER_SOURCEDIR+=src
 endif
+ifeq ($(FULL_TARGET),i386-nativent)
+override COMPILER_SOURCEDIR+=src
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 override COMPILER_SOURCEDIR+=src
 endif
@@ -1360,6 +1372,10 @@ ifeq ($(OS_TARGET),symbian)
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=symbian
 endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
 else
 ifeq ($(OS_TARGET),go32v1)
 PPUEXT=.pp1
@@ -2028,6 +2044,15 @@ REQUIRE_PACKAGES_FCL-PROCESS=1
 REQUIRE_PACKAGES_HTTPD22=1
 REQUIRE_PACKAGES_FASTCGI=1
 endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-BASE=1
+REQUIRE_PACKAGES_FCL-XML=1
+REQUIRE_PACKAGES_FCL-DB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HTTPD22=1
+REQUIRE_PACKAGES_FASTCGI=1
+endif
 ifeq ($(FULL_TARGET),m68k-linux)
 REQUIRE_PACKAGES_RTL=1
 REQUIRE_PACKAGES_FCL-BASE=1
@@ -3362,6 +3387,9 @@ fpc_zipdistinstall:
 ifdef EXEFILES
 override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
 endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+endif
 ifdef CLEAN_UNITS
 override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
 endif

+ 1 - 1
packages/fcl-web/Makefile.fpc

@@ -8,7 +8,7 @@ version=2.5.1
 
 [target]
 units=httpdefs fphttp custweb custcgi fpcgi fptemplate fphtml websession fpweb \
-      webutil fpdatasetform cgiapp ezcgi fpapache
+      webutil fpdatasetform cgiapp ezcgi fpapache webpage
 rsts=fpcgi fphtml fpweb websession cgiapp
 
 # these units are listed separately because they don't work for

+ 556 - 7
packages/fcl-web/src/fphtml.pp

@@ -18,7 +18,7 @@ unit fphtml;
 interface
 
 uses
-  Classes, SysUtils, htmlelements, htmlwriter, httpdefs, fphttp, db;
+  Classes, SysUtils, htmlelements, htmlwriter, httpdefs, fphttp, DB, DOM, contnrs;
 
 type
   THtmlEntities = (heHtml,heBody,heHead,heDiv,heParagraph);
@@ -29,24 +29,177 @@ const
 
 type
 
+  { TJavaScriptStack }
+  TWebButtonType = (btOk, btCancel, btCustom);
+  TWebButton = record
+    ButtonType: TWebButtonType;
+    Caption: String;
+    OnClick: String;
+  end;
+  TWebButtons = array of TWebButton;
+
+  TMessageBoxHandler = function(Sender: TObject; AText: String; Buttons: TWebButtons): string of object;
+  TWebController = class;
+  THTMLContentProducer = class;
+
+  TJavaScriptStack = class(TObject)
+  private
+    FMessageBoxHandler: TMessageBoxHandler;
+    FScript: TStrings;
+    FWebController: TWebController;
+  protected
+    function GetWebController: TWebController;
+  public
+    constructor Create(const AWebController: TWebController); virtual;
+    destructor Destroy; override;
+    procedure AddScriptLine(ALine: String); virtual;
+    procedure MessageBox(AText: String; Buttons: TWebButtons); virtual;
+    procedure RedrawContentProducer(AContentProducer: THTMLContentProducer); virtual;
+    procedure CallServerEvent(AHTMLContentProducer: THTMLContentProducer; AEvent: Integer; APostVariable: string = ''); virtual;
+    procedure Clear; virtual;
+    function ScriptIsEmpty: Boolean; virtual;
+    function GetScript: String; virtual;
+    property WebController: TWebController read GetWebController;
+  end;
+
+  { TWebController }
+
+  TWebController = class(TComponent)
+  private
+    FBaseURL: string;
+    FMessageBoxHandler: TMessageBoxHandler;
+    FScriptName: string;
+    procedure SetBaseURL(const AValue: string);
+    procedure SetScriptName(const AValue: string);
+  protected
+    function GetScriptFileReferences: TStringList; virtual; abstract;
+    function GetCurrentJavaScriptStack: TJavaScriptStack; virtual; abstract;
+    function GetScripts: TFPObjectList; virtual; abstract;
+    function GetRequest: TRequest;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure AddScriptFileReference(AScriptFile: String); virtual; abstract;
+    function InitializeJavaScriptStack: TJavaScriptStack; virtual; abstract;
+    function HasJavascriptStack: boolean; virtual; abstract;
+    function GetUrl(ParamNames, ParamValues, KeepParams: array of string; Action: string = ''): string; virtual; abstract;
+    procedure InitializeAjaxRequest; virtual;
+    procedure InitializeShowRequest; virtual;
+    procedure CleanupAfterRequest; virtual;
+    procedure FreeJavascriptStack; virtual; abstract;
+    procedure BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; AnEvent: string); virtual; abstract;
+    function MessageBox(AText: String; Buttons: TWebButtons): string; virtual;
+    function DefaultMessageBoxHandler(Sender: TObject; AText: String; Buttons: TWebButtons): string; virtual; abstract;
+    function CreateNewScript: TStringList; virtual; abstract;
+    procedure FreeScript(var AScript: TStringList); virtual; abstract;
+    property ScriptFileReferences: TStringList read GetScriptFileReferences;
+    property Scripts: TFPObjectList read GetScripts;
+    property CurrentJavaScriptStack: TJavaScriptStack read GetCurrentJavaScriptStack;
+    property MessageBoxHandler: TMessageBoxHandler read FMessageBoxHandler write FMessageBoxHandler;
+  published
+    property BaseURL: string read FBaseURL write SetBaseURL;
+    property ScriptName: string read FScriptName write SetScriptName;
+  end;
+
+  { TAjaxResponse }
+
+  TAjaxResponse= class(TObject)
+  private
+    FJavascriptCallStack: TJavaScriptStack;
+    FResponse: TResponse;
+    FSendXMLAnswer: boolean;
+    FXMLAnswer: TXMLDocument;
+    FRootNode: TDOMNode;
+    function GetXMLAnswer: TXMLDocument;
+  public
+    constructor Create(AWebController: TWebController; AResponse: TResponse); virtual;
+    destructor Destroy; override;
+    procedure BindToResponse; virtual;
+    property Response: TResponse read FResponse;
+    property XMLAnswer: TXMLDocument read GetXMLAnswer;
+    property SendXMLAnswer: boolean read FSendXMLAnswer;
+    property JavascriptCallStack: TJavaScriptStack read FJavascriptCallStack;
+  end;
+
+  TCSAjaxEvent=procedure(Sender: TComponent; AJavascriptClass: TJavaScriptStack; var Handled: boolean) of object;
+  THandleAjaxEvent = procedure(Sender: TObject; ARequest: TRequest; AnAjaxResponse: TAjaxResponse) of object;
+
+  TEventRecord = record
+    csCallback: TCSAjaxEvent;
+    ServerEvent: THandleAjaxEvent;
+    ServerEventID: integer;
+    JavaEventName: string;
+  end;
+  TEventRecords = array of TEventRecord;
+
+  TForeachContentProducerProc = procedure(const AContentProducer: THTMLContentProducer) of object;
+
+  IHTMLContentProducerContainer = interface
+   ['{8B4D8AE0-4873-49BF-B677-D03C8A02CDA5}']
+    procedure AddContentProducer(AContentProducer: THTMLContentProducer);
+    procedure RemoveContentProducer(AContentProducer: THTMLContentProducer);
+    function ExchangeContentProducers(Child1, Child2: THTMLContentProducer) : boolean;
+    function MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer) : boolean;
+    procedure ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
+  end;
+
   { THTMLContentProducer }
 
-  THTMLContentProducer = Class(THTTPContentProducer)
+  THTMLContentProducer = Class(THTTPContentProducer, IHTMLContentProducerContainer)
   private
     FDocument: THTMLDocument;
     FElement: THTMLCustomElement;
     FWriter: THTMLWriter;
     procedure SetDocument(const AValue: THTMLDocument);
     procedure SetWriter(const AValue: THTMLWriter);
+  private
+    // for streaming
+    FChilds: TFPList; // list of THTMLContentProducer
+    FParent: TComponent;
+    function GetContentProducerList: TFPList;
+    function GetContentProducers(Index: integer): THTMLContentProducer;
+    procedure SetParent(const AValue: TComponent);
   Protected
     function CreateWriter (Doc : THTMLDocument) : THTMLWriter; virtual;
+  protected
+    // Methods for streaming
+    FAcceptChildsAtDesignTime: boolean;
+    procedure SetParentComponent(Value: TComponent); override;
+    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
+    procedure DoBeforeGenerateContent(const AContentProducer: THTMLContentProducer);
+    function GetEvents: TEventRecords; virtual;
+    procedure AddEvent(var Events: TEventRecords; AServerEventID: integer; AServerEvent: THandleAjaxEvent; AJavaEventName: string; AcsCallBack: TCSAjaxEvent); virtual;
+    procedure DoOnEventCS(AnEvent: TEventRecord; AJavascriptStack: TJavaScriptStack; var Handled: boolean); virtual;
+    procedure SetupEvents(AHtmlElement: THtmlCustomElement); virtual;
+    function GetWebController(const ExceptIfNotAvailable: boolean = true): TWebController;
+    property ContentProducerList: TFPList read GetContentProducerList;
   public
-    function WriteContent (aWriter : THTMLWriter) : THTMLCustomElement; virtual; abstract;
+    procedure BeforeGenerateContent; virtual;
+    function WriteContent (aWriter : THTMLWriter) : THTMLCustomElement; virtual;
     Function ProduceContent : String; override; // Here to test the output. Replace to protected after tests
+    function GetParentComponent: TComponent; override;
     property ParentElement : THTMLCustomElement read FElement write FElement;
     property Writer : THTMLWriter read FWriter write SetWriter;
     Property HTMLDocument : THTMLDocument read FDocument write SetDocument;
+  public
+    // for streaming
+    constructor Create(AOwner: TComponent); override;
+    destructor destroy; override;
+    function HasParent: Boolean; override;
+    function ChildCount: integer;
+    procedure CleanupAfterRequest; virtual;
+    procedure AddContentProducer(AContentProducer: THTMLContentProducer);
+    procedure RemoveContentProducer(AContentProducer: THTMLContentProducer);
+    function ExchangeContentProducers(Child1, Child2: THTMLContentProducer) : boolean;
+    function MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer) : boolean;
+    procedure HandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse); virtual;
+    procedure ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
+    property Childs[Index: integer]: THTMLContentProducer read GetContentProducers;
+    property AcceptChildsAtDesignTime: boolean read FAcceptChildsAtDesignTime;
+    property parent: TComponent read FParent write SetParent;
   end;
+  THTMLContentProducerClas = class of THTMLContentProducer;
+
 
   TWriterElementEvent = procedure (Sender:THTMLContentProducer; aWriter : THTMLWriter; var anElement : THTMLCustomElement) of object;
   TAfterElementEvent = procedure (Sender:THTMLContentProducer; anElement : THTMLCustomElement) of object;
@@ -228,7 +381,6 @@ type
     Procedure HandleRequest(ARequest : TRequest; HTMLPage : THTMLWriter; Var Handled : Boolean);
   end;
 
-
   { TCustomHTMLDataModule }
 
   { TCustomHTMLModule }
@@ -262,17 +414,75 @@ type
   end;
   
   EHTMLError = Class(Exception);
-  
-implementation
 
+const SimpleOkButton: array[0..0] of TWebButton = ((buttontype: btok;caption: 'Ok';onclick: ''));
+
+implementation
+Uses
 {$ifdef cgidebug}
-Uses dbugintf;
+  dbugintf
 {$endif cgidebug}
+  webpage, XMLWrite;
 
 resourcestring
   SErrRequestNotHandled = 'Web request was not handled by actions.';
   SErrNoContentProduced = 'The content producer "%s" didn''t produce any content.';
 
+{ TJavaScriptStack }
+
+function TJavaScriptStack.GetWebController: TWebController;
+begin
+  result := FWebController;
+end;
+
+constructor TJavaScriptStack.Create(const AWebController: TWebController);
+begin
+  FWebController := AWebController;
+  FScript := TStringList.Create;
+end;
+
+destructor TJavaScriptStack.Destroy;
+begin
+  FScript.Free;
+  inherited Destroy;
+end;
+
+procedure TJavaScriptStack.AddScriptLine(ALine: String);
+begin
+  FScript.Add(ALine);
+end;
+
+procedure TJavaScriptStack.MessageBox(AText: String; Buttons: TWebButtons);
+begin
+  AddScriptLine(WebController.MessageBox(AText,Buttons));
+end;
+
+procedure TJavaScriptStack.RedrawContentProducer(AContentProducer: THTMLContentProducer);
+begin
+  raise exception.Create('RedrawContentProducer not supported by current WebController');
+end;
+
+procedure TJavaScriptStack.CallServerEvent(AHTMLContentProducer: THTMLContentProducer; AEvent: Integer; APostVariable: string = '');
+begin
+  raise exception.Create('SendServerEvent not supported by current WebController');
+end;
+
+procedure TJavaScriptStack.Clear;
+begin
+  FScript.Clear;
+end;
+
+function TJavaScriptStack.ScriptIsEmpty: Boolean;
+begin
+  result := FScript.Count=0;
+end;
+
+function TJavaScriptStack.GetScript: String;
+begin
+  result := FScript.Text;
+end;
+
+
 { THTMLContentProducer }
 
 procedure THTMLContentProducer.SetWriter(const AValue: THTMLWriter);
@@ -291,6 +501,28 @@ begin
     FWriter.Document := AValue;
 end;
 
+procedure THTMLContentProducer.SetParent(const AValue: TComponent);
+begin
+  if FParent=AValue then exit;
+  if FParent<>nil then
+    (FParent as IHTMLContentProducerContainer).RemoveContentProducer(Self);
+  FParent:=AValue;
+  if FParent<>nil then
+    (FParent as IHTMLContentProducerContainer).AddContentProducer(Self);
+end;
+
+function THTMLContentProducer.GetContentProducers(Index: integer): THTMLContentProducer;
+begin
+  Result:=THTMLContentProducer(ContentProducerList[Index]);
+end;
+
+function THTMLContentProducer.GetContentProducerList: TFPList;
+begin
+  if not assigned(FChilds) then
+    fchilds := tfplist.Create;
+  Result := FChilds;
+end;
+
 function THTMLContentProducer.ProduceContent: String;
 var WCreated, created : boolean;
     el : THtmlCustomElement;
@@ -307,6 +539,7 @@ begin
       el := WriteContent (FWriter);
       if not assigned(el) then
         Raise EHTMLError.CreateFmt(SErrNoContentProduced,[Self.Name]);
+      ForeachContentProducer(@DoBeforeGenerateContent,True);
       result := el.asstring;
     finally
       if WCreated then
@@ -318,12 +551,223 @@ begin
   end;
 end;
 
+constructor THTMLContentProducer.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FAcceptChildsAtDesignTime:=True;
+end;
+
+destructor THTMLContentProducer.destroy;
+begin
+  Parent:=nil;
+  while ChildCount>0 do Childs[ChildCount-1].Free;
+  FreeAndNil(FChilds);
+  inherited destroy;
+end;
+
+function THTMLContentProducer.GetEvents: TEventRecords;
+begin
+  result := nil;
+end;
+
+procedure THTMLContentProducer.AddEvent(var Events: TEventRecords;
+  AServerEventID: integer; AServerEvent: THandleAjaxEvent; AJavaEventName: string;
+  AcsCallBack: TCSAjaxEvent);
+begin
+  SetLength(Events,length(Events)+1);
+  with Events[high(Events)] do
+    begin
+    ServerEvent:=AServerEvent;
+    ServerEventID:=AServerEventID;
+    JavaEventName:=AJavaEventName;
+    csCallback:=AcsCallBack;
+    end;
+end;
+
+procedure THTMLContentProducer.DoOnEventCS(AnEvent: TEventRecord; AJavascriptStack: TJavaScriptStack; var Handled: boolean);
+begin
+  if assigned(AnEvent.csCallback) then
+    AnEvent.csCallback(self, AJavascriptStack, Handled);
+end;
+
+procedure THTMLContentProducer.SetupEvents(AHtmlElement: THtmlCustomElement);
+var AJSClass: TJavaScriptStack;
+    wc: TWebController;
+    Handled: boolean;
+    Events: TEventRecords;
+    i: integer;
+begin
+  Events := GetEvents;
+  if length(Events)>0 then
+    begin
+    wc := GetWebController(false);
+    if assigned(wc) then
+      begin
+      AJSClass := wc.InitializeJavaScriptStack;
+      try
+        for i := 0 to high(Events) do
+          begin
+          Handled:=false;
+          DoOnEventCS(events[i],AJSClass, Handled);
+          if not handled and assigned(events[i].ServerEvent) then
+            AJSClass.CallServerEvent(self,events[i].ServerEventID);
+          wc.BindJavascriptCallstackToElement(Self, AHtmlElement,events[i].JavaEventName);
+          AJSClass.clear;
+          end;
+      finally
+        wc.FreeJavascriptStack;
+      end;
+      end
+    else
+      begin
+      for i := 0 to high(Events) do if assigned(events[i].csCallback) or assigned(events[i].ServerEvent) then
+        raise exception.Create('There is no webcontroller available, which is necessary to use events.');
+      end;
+    end;
+end;
+
+function THTMLContentProducer.GetWebController(const ExceptIfNotAvailable: boolean): TWebController;
+var i : integer;
+begin
+  result := nil;
+  if assigned(owner)  then
+    begin
+    if (owner is TWebPage) and TWebPage(owner).HasWebController then
+      begin
+      result := TWebPage(owner).WebController;
+      exit;
+      end
+    else //if (owner is TDataModule) then
+      begin
+      for i := 0 to owner.ComponentCount-1 do if owner.Components[i] is TWebController then
+        begin
+        result := TWebController(Owner.Components[i]);
+        Exit;
+        end;
+      end;
+    end;
+  if ExceptIfNotAvailable then
+    raise Exception.Create('No webcontroller available');
+end;
+
+procedure THTMLContentProducer.BeforeGenerateContent;
+begin
+  // do nothing
+end;
+
+function THTMLContentProducer.WriteContent(aWriter: THTMLWriter): THTMLCustomElement;
+var i: integer;
+begin
+  for i := 0 to ChildCount-1 do
+    if Childs[i] is THTMLContentProducer then
+      result := THTMLContentProducer(Childs[i]).WriteContent(aWriter);
+end;
+
+function THTMLContentProducer.ChildCount: integer;
+begin
+  if assigned(FChilds) then
+    result := FChilds.Count
+  else
+    result := 0;
+end;
+
+procedure THTMLContentProducer.CleanupAfterRequest;
+begin
+  // Do Nothing
+end;
+
+procedure THTMLContentProducer.AddContentProducer(AContentProducer: THTMLContentProducer);
+begin
+  ContentProducerList.Add(AContentProducer);
+end;
+
+procedure THTMLContentProducer.RemoveContentProducer(AContentProducer: THTMLContentProducer);
+begin
+  ContentProducerList.Remove(AContentProducer);
+end;
+
+function THTMLContentProducer.ExchangeContentProducers(Child1, Child2: THTMLContentProducer): boolean;
+var ChildIndex1, ChildIndex2: integer;
+begin
+  result := false;
+  ChildIndex1:=GetContentProducerList.IndexOf(Child1);
+  if (ChildIndex1=-1) then
+    Exit;
+  ChildIndex2:=GetContentProducerList.IndexOf(Child2);
+  if (ChildIndex2=-1) then
+    Exit;
+  GetContentProducerList.Exchange(ChildIndex1,ChildIndex2);
+  result := true;
+end;
+
+function THTMLContentProducer.MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer): boolean;
+var ChildIndex1, ChildIndex2: integer;
+begin
+  result := false;
+  ChildIndex1:=GetContentProducerList.IndexOf(MoveElement);
+  if (ChildIndex1=-1) then
+    Exit;
+  ChildIndex2:=GetContentProducerList.IndexOf(MoveBeforeElement);
+  if (ChildIndex2=-1) then
+    Exit;
+  GetContentProducerList.Move(ChildIndex1,ChildIndex2);
+  result := true;
+end;
+
+procedure THTMLContentProducer.HandleAjaxRequest(ARequest: TRequest; AnAjaxResponse: TAjaxResponse);
+begin
+  // Do nothing
+end;
+
+procedure THTMLContentProducer.ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
+var i : integer;
+    tmpChild: THTMLContentProducer;
+begin
+  for i := 0 to ChildCount -1 do
+    begin
+    tmpChild := Childs[i];
+    AForeachChildsProc(tmpChild);
+    if recursive then
+      tmpChild.ForeachContentProducer(AForeachChildsProc,Recursive);
+    end;
+end;
+
 function THTMLContentProducer.CreateWriter (Doc : THTMLDocument): THTMLWriter;
 begin
   FDocument := Doc;
   result := THTMLWriter.Create (Doc);
 end;
 
+procedure THTMLContentProducer.SetParentComponent(Value: TComponent);
+begin
+  if Supports(Value,IHTMLContentProducerContainer) then
+    Parent:=Value;
+end;
+
+function THTMLContentProducer.HasParent: Boolean;
+begin
+  Result:=FParent<>nil;
+end;
+
+function THTMLContentProducer.GetParentComponent: TComponent;
+begin
+  Result:=TComponent(Parent);
+end;
+
+procedure THTMLContentProducer.GetChildren(Proc: TGetChildProc; Root: TComponent);
+var
+  i: Integer;
+begin
+  for i:=0 to ChildCount-1 do
+    if Childs[i].Owner=Root then
+      Proc(Childs[i]);
+end;
+
+procedure THTMLContentProducer.DoBeforeGenerateContent(const AContentProducer: THTMLContentProducer);
+begin
+  AContentProducer.BeforeGenerateContent;
+end;
+
 { THTMLCustomDatasetContentProducer }
 
 function THTMLCustomDatasetContentProducer.WriteHeader(aWriter: THTMLWriter): THTMLCustomElement;
@@ -564,6 +1008,7 @@ function THTMLCustomEntityProducer.WriteContent(aWriter: THTMLWriter
 begin
   result := aWriter.StartElement(THtmlEntitiesClasses[FEntity]);
   DoWriteEntity(aWriter);
+  inherited WriteContent(aWriter);
   aWriter.EndElement(THtmlEntitiesClasses[FEntity]);
 end;
 
@@ -630,5 +1075,109 @@ begin
   Entity := heHtml;
 end;
 
+{ TAjaxResponse }
+
+function TAjaxResponse.GetXMLAnswer: TXMLDocument;
+begin
+  if not assigned(FXMLAnswer) then
+    begin
+    FXMLAnswer := TXMLDocument.create;
+    FRootNode := FXMLAnswer.CreateElement('CallResponse');
+    FXMLAnswer.Appendchild(FRootNode);
+    end;
+  result := FXMLAnswer;
+end;
+
+constructor TAjaxResponse.Create(AWebController: TWebController;
+  AResponse: TResponse);
+begin
+  FSendXMLAnswer:=true;
+  FResponse:=AResponse;
+  FJavascriptCallStack:=AWebController.InitializeJavaScriptStack;
+end;
+
+destructor TAjaxResponse.Destroy;
+begin
+  FXMLAnswer.Free;
+  FJavascriptCallStack.Free;
+  inherited Destroy;
+end;
+
+procedure TAjaxResponse.BindToResponse;
+var SubNode: TDOMNode;
+begin
+  if SendXMLAnswer then
+    begin
+    SubNode := XMLAnswer.CreateElement('ExecScript');
+    FRootNode.Appendchild(SubNode);
+    SubNode.Appendchild(XMLAnswer.CreateTextNode(FJavascriptCallStack.GetScript));
+
+    Response.ContentStream := TMemoryStream.Create;
+    Response.ContentType:='text/xml';
+    writeXMLFile(XMLAnswer,Response.ContentStream);
+    Response.ContentLength := Response.ContentStream.Size;
+    end
+end;
+
+{ TWebController }
+
+procedure TWebController.SetBaseURL(const AValue: string);
+begin
+  if FBaseURL=AValue then exit;
+  FBaseURL:=AValue;
+end;
+
+procedure TWebController.SetScriptName(const AValue: string);
+begin
+  if FScriptName=AValue then exit;
+  FScriptName:=AValue;
+end;
+
+procedure TWebController.InitializeAjaxRequest;
+begin
+  // do nothing
+end;
+
+procedure TWebController.InitializeShowRequest;
+begin
+  // do nothing
+end;
+
+procedure TWebController.CleanupAfterRequest;
+begin
+  // Do Nothing
+end;
+
+function TWebController.MessageBox(AText: String; Buttons: TWebButtons): string;
+begin
+  if assigned(MessageBoxHandler) then
+    result := MessageBoxHandler(self,AText,Buttons)
+  else
+    result := DefaultMessageBoxHandler(self,AText,Buttons);
+end;
+
+function TWebController.GetRequest: TRequest;
+begin
+  if assigned(Owner) and (owner is TWebPage) then
+    result := TWebPage(Owner).Request
+  else
+    result := nil;
+end;
+
+constructor TWebController.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  { TODO : Do this prperly using a notification. And make the WebController property readonly }
+  if owner is TWebPage then TWebPage(Owner).WebController := self;
+end;
+
+destructor TWebController.Destroy;
+begin
+  if (Owner is TWebPage) and (TWebPage(Owner).WebController=self) then
+    TWebPage(Owner).WebController := nil;
+  inherited Destroy;
+end;
+
+
 end.
 

+ 507 - 0
packages/fcl-web/src/webpage.pp

@@ -0,0 +1,507 @@
+unit WebPage;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fphtml, htmlelements, htmlwriter, HTTPDefs, fpweb, contnrs, dom;
+
+type
+  TRequestResponseEvent = procedure(Sender: TObject; ARequest: TRequest; AResponse: TResponse) of object;
+  TRequestEvent = procedure(Sender: TObject; ARequest: TRequest) of object;
+  THandleAjaxRequest = procedure(Sender: TObject; ARequest: TRequest; AResponse: TResponse; var handled: boolean) of object;
+
+type
+  IWebPageDesigner = interface(IUnknown)
+    procedure Invalidate;
+  end;
+
+  { TStandardWebController }
+
+  TStandardWebController = class(TWebController)
+  private
+    FScriptFileReferences: TStringList;
+    FCurrentJavascriptStack: TJavaScriptStack;
+    FScripts: TFPObjectList;
+  protected
+    function GetScriptFileReferences: TStringList; override;
+    function GetScripts: TFPObjectList; override;
+    function GetCurrentJavaScriptStack: TJavaScriptStack; override;
+    procedure SetCurrentJavascriptStack(const AJavascriptStack: TJavaScriptStack);
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    function InitializeJavaScriptStack: TJavaScriptStack; override;
+    function GetUrl(ParamNames, ParamValues, KeepParams: array of string; Action: string = ''): string; override;
+    procedure FreeJavascriptStack; override;
+    procedure BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; AnEvent: string); override;
+    procedure AddScriptFileReference(AScriptFile: String); override;
+    function DefaultMessageBoxHandler(Sender: TObject; AText: String; Buttons: TWebButtons): string; override;
+    function CreateNewScript: TStringList; override;
+    procedure FreeScript(var AScript: TStringList); override;
+  end;
+
+  { TWebPage }
+
+  TWebPage = class(TDataModule, IHTMLContentProducerContainer)
+  private
+    FAfterAjaxRequest: TRequestResponseEvent;
+    FBaseURL: string;
+    FBeforeAjaxRequest: TRequestResponseEvent;
+    FBeforeRequest: TRequestEvent;
+    FBeforeShowPage: TRequestEvent;
+    FDesigner: IWebPageDesigner;
+    FOnAjaxRequest: THandleAjaxRequest;
+    FRequest: TRequest;
+    FWebController: TWebController;
+    FWebModule: TFPWebModule;
+    FContentProducers: TFPList; // list of THTMLContentProducer
+    function GetContentProducer(Index: integer): THTMLContentProducer;
+    function GetContentProducerList: TFPList;
+    function GetContentProducers(Index: integer): THTMLContentProducer;
+    function GetHasWebController: boolean;
+    function GetWebController: TWebController;
+  protected
+    procedure DoBeforeAjaxRequest(ARequest: TRequest; AResponse: TResponse); virtual;
+    procedure DoAfterAjaxRequest(ARequest: TRequest; AResponse: TResponse); virtual;
+    procedure DoHandleAjaxRequest(ARequest: TRequest; AResponse: TResponse; var Handled: boolean); virtual;
+    procedure DoBeforeRequest(ARequest: TRequest); virtual;
+    procedure DoBeforeShowPage(ARequest: TRequest); virtual;
+    property WebModule: TFPWebModule read FWebModule;
+    procedure DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
+    procedure SetRequest(ARequest: TRequest); virtual;
+    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
+    property ContentProducerList: TFPList read GetContentProducerList;
+  public
+    function ContentProducerCount: integer;
+
+    function ProduceContent : string;
+    procedure AddContentProducer(AContentProducer: THTMLContentProducer);
+    procedure RemoveContentProducer(AContentProducer: THTMLContentProducer);
+    function ExchangeContentProducers(Child1, Child2: THTMLContentProducer) : boolean;
+    function MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer) : boolean;
+    procedure ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
+
+    procedure HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule = nil); virtual;
+    procedure DoBeforeGenerateXML; virtual;
+    procedure CleanupAfterRequest; virtual;
+    property Designer: IWebPageDesigner read FDesigner write FDesigner;
+    property Request: TRequest read FRequest;
+    property ContentProducers[Index: integer]: THTMLContentProducer read GetContentProducer;
+    property HasWebController: boolean read GetHasWebController;
+    property WebController: TWebController read GetWebController write FWebController;
+  published
+    property BeforeRequest: TRequestEvent read FBeforeRequest write FBeforeRequest;
+    property BeforeShowPage: TRequestEvent read FBeforeShowPage write FBeforeShowPage;
+    property BeforeAjaxRequest: TRequestResponseEvent read FBeforeAjaxRequest write FBeforeAjaxRequest;
+    property AfterAjaxRequest: TRequestResponseEvent read FAfterAjaxRequest write FAfterAjaxRequest;
+    property OnAjaxRequest: THandleAjaxRequest read FOnAjaxRequest write FOnAjaxRequest;
+    property BaseURL: string read FBaseURL write FBaseURL;
+  end;
+
+implementation
+
+uses rtlconsts, typinfo, XMLWrite;
+
+{ TWebPage }
+
+function TWebPage.ProduceContent: string;
+var i : integer;
+begin
+  result := '';
+  for i := 0 to ContentProducerCount-1 do
+    result := result + THTMLContentProducer(ContentProducers[i]).ProduceContent;
+end;
+
+procedure TWebPage.AddContentProducer(AContentProducer: THTMLContentProducer);
+begin
+  ContentProducerList.Add(AContentProducer);
+end;
+
+procedure TWebPage.RemoveContentProducer(AContentProducer: THTMLContentProducer);
+begin
+  ContentProducerList.Remove(AContentProducer);
+end;
+
+function TWebPage.ExchangeContentProducers(Child1, Child2: THTMLContentProducer): boolean;
+var ChildIndex1, ChildIndex2: integer;
+begin
+  result := false;
+  ChildIndex1:=GetContentProducerList.IndexOf(Child1);
+  if (ChildIndex1=-1) then
+    Exit;
+  ChildIndex2:=GetContentProducerList.IndexOf(Child2);
+  if (ChildIndex2=-1) then
+    Exit;
+  GetContentProducerList.Exchange(ChildIndex1,ChildIndex2);
+  result := true;
+end;
+
+function TWebPage.MoveContentProducer(MoveElement, MoveBeforeElement: THTMLContentProducer): boolean;
+var ChildIndex1, ChildIndex2: integer;
+begin
+  result := false;
+  ChildIndex1:=GetContentProducerList.IndexOf(MoveElement);
+  if (ChildIndex1=-1) then
+    Exit;
+  ChildIndex2:=GetContentProducerList.IndexOf(MoveBeforeElement);
+  if (ChildIndex2=-1) then
+    Exit;
+  GetContentProducerList.Move(ChildIndex1,ChildIndex2);
+  result := true;
+end;
+
+procedure TWebPage.ForeachContentProducer(AForeachChildsProc: TForeachContentProducerProc; Recursive: boolean);
+var i : integer;
+    tmpChild: THTMLContentProducer;
+begin
+  for i := 0 to ContentProducerCount -1 do
+    begin
+    tmpChild := ContentProducers[i];
+    AForeachChildsProc(tmpChild);
+    if recursive then
+      tmpChild.ForeachContentProducer(AForeachChildsProc,Recursive);
+    end;
+end;
+
+procedure TWebPage.HandlePage(ARequest: TRequest; AResponse: TResponse; AWriter: THTMLwriter; AWebModule: TFPWebModule=nil);
+var s : string;
+    Handled: boolean;
+    CompName: string;
+    AComponent: TComponent;
+    AnAjaxResponse: TAjaxResponse;
+begin
+  SetRequest(ARequest);
+  FWebModule := AWebModule;
+  try
+    try
+      DoBeforeRequest(ARequest);
+      s := Request.HTTPXRequestedWith;
+      if sametext(s,'XmlHttpRequest') then
+        begin
+        AnAjaxResponse := TAjaxResponse.Create(GetWebController, AResponse);
+        try
+          DoBeforeAjaxRequest(ARequest, AResponse);
+          if HasWebController then
+            WebController.InitializeAjaxRequest;
+          Handled := false;
+          DoHandleAjaxRequest(ARequest, AResponse, Handled);
+          if not Handled then
+            begin
+            CompName := Request.QueryFields.Values['AjaxID'];
+            if CompName='' then CompName := Request.GetNextPathInfo;
+            AComponent := FindComponent(CompName);
+            if assigned(AComponent) and (AComponent is THTMLContentProducer) then
+              THTMLContentProducer(AComponent).HandleAjaxRequest(ARequest, AnAjaxResponse);
+            AnAjaxResponse.BindToResponse;
+            end;
+          DoAfterAjaxRequest(ARequest, AResponse);
+        finally
+          AnAjaxResponse.Free;
+        end;
+        end
+      else
+        begin
+        if HasWebController then
+          WebController.InitializeShowRequest;
+        DoBeforeShowPage(ARequest);
+        AResponse.Content := ProduceContent;
+        end;
+    finally
+      CleanupAfterRequest;
+    end;
+  finally
+    SetRequest(nil);
+    AWebModule := nil;
+  end;
+end;
+
+procedure TWebPage.DoBeforeGenerateXML;
+begin
+  // Do Nothing
+end;
+
+procedure TWebPage.CleanupAfterRequest;
+begin
+  ForeachContentProducer(@DoCleanupAfterRequest, True);
+  if HasWebController then
+    WebController.CleanupAfterRequest;
+end;
+
+procedure TWebPage.DoCleanupAfterRequest(const AContentProducer: THTMLContentProducer);
+begin
+  AContentProducer.CleanupAfterRequest;
+end;
+
+procedure TWebPage.SetRequest(ARequest: TRequest);
+begin
+  FRequest := ARequest;
+end;
+
+procedure TWebPage.GetChildren(Proc: TGetChildProc; Root: TComponent);
+var i : integer;
+begin
+  inherited GetChildren(Proc, Root);
+  if (Root=Self) then
+    for I:=0 to ContentProducerCount-1 do
+      Proc(ContentProducers[i]);
+end;
+
+function TWebPage.ContentProducerCount: integer;
+begin
+  if assigned(FContentProducers) then
+    result := FContentProducers.Count
+  else
+    result := 0;
+end;
+
+function TWebPage.GetContentProducers(Index: integer): THTMLContentProducer;
+begin
+  Result:=THTMLContentProducer(ContentProducerList[Index]);
+end;
+
+function TWebPage.GetHasWebController: boolean;
+begin
+  result := assigned(FWebController);
+end;
+
+function TWebPage.GetWebController: TWebController;
+begin
+  if not assigned(FWebController) then
+    raise exception.create('No webcontroller available');
+  result := FWebController;
+end;
+
+function TWebPage.GetContentProducerList: TFPList;
+begin
+  if not assigned(FContentProducers) then
+    FContentProducers := tfplist.Create;
+  Result := FContentProducers;
+end;
+
+function TWebPage.GetContentProducer(Index: integer): THTMLContentProducer;
+begin
+  Result := THTMLContentProducer(ContentProducerList[Index]);
+end;
+
+procedure TWebPage.DoBeforeAjaxRequest(ARequest: TRequest; AResponse: TResponse);
+begin
+  if assigned(BeforeAjaxRequest) then
+    BeforeAjaxRequest(Self,ARequest,AResponse);
+end;
+
+procedure TWebPage.DoAfterAjaxRequest(ARequest: TRequest; AResponse: TResponse);
+begin
+  if assigned(AfterAjaxRequest) then
+    AfterAjaxRequest(Self,ARequest,AResponse);
+end;
+
+procedure TWebPage.DoHandleAjaxRequest(ARequest: TRequest; AResponse: TResponse; var Handled: boolean);
+begin
+  if assigned(OnAjaxRequest) then
+    OnAjaxRequest(Self,ARequest,AResponse, Handled);
+end;
+
+procedure TWebPage.DoBeforeRequest(ARequest: TRequest);
+begin
+  if assigned(BeforeRequest) then
+    BeforeRequest(Self,ARequest);
+end;
+
+procedure TWebPage.DoBeforeShowPage(ARequest: TRequest);
+begin
+  if assigned(BeforeShowPage) then
+    BeforeShowPage(Self,ARequest);
+end;
+
+{ TStandardWebController }
+
+function TStandardWebController.GetScriptFileReferences: TStringList;
+begin
+  Result:=FScriptFileReferences;
+end;
+
+function TStandardWebController.GetScripts: TFPObjectList;
+begin
+  if not assigned(FScripts) then
+    begin
+    FScripts:=TFPObjectList.Create;
+    FScripts.OwnsObjects:=true;
+    end;
+  Result:=FScripts;
+end;
+
+function TStandardWebController.GetCurrentJavaScriptStack: TJavaScriptStack;
+begin
+  Result:=FCurrentJavascriptStack;
+end;
+
+procedure TStandardWebController.SetCurrentJavascriptStack(const AJavascriptStack: TJavaScriptStack);
+begin
+  FCurrentJavascriptStack := AJavascriptStack;
+end;
+
+function TStandardWebController.CreateNewScript: TStringList;
+begin
+  Result:=TStringList.Create;
+  GetScripts.Add(result);
+end;
+
+procedure TStandardWebController.FreeScript(var AScript: TStringList);
+begin
+  with GetScripts do
+    GetScripts.Delete(IndexOf(AScript));
+  AScript := nil;
+end;
+
+function TStandardWebController.DefaultMessageBoxHandler(Sender: TObject;
+  AText: String; Buttons: TWebButtons): string;
+var i : integer;
+    HasCancel: boolean;
+    HasOk: boolean;
+    OnOk: string;
+    OnCancel: string;
+begin
+  HasCancel:=false;
+  HasOk:=false;
+  OnOk:='';
+  OnCancel:='';
+  for i := low(Buttons) to High(Buttons) do
+    begin
+    if Buttons[i].ButtonType=btOk then
+      begin
+      HasOk := True;
+      OnOk := Buttons[i].OnClick;
+      end;
+    if Buttons[i].ButtonType=btCancel then
+      begin
+      HasCancel := True;
+      OnCancel := Buttons[i].OnClick;
+      end;
+    end;
+
+  if HasCancel then
+    result := 'if (confirm('''+AText+''')==true) {'+OnOk+'} else {'+OnCancel+'}'
+  else
+    result := 'alert('''+AText+''');'+OnOk;
+end;
+
+constructor TStandardWebController.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FScriptFileReferences := TStringList.Create;
+  // For some reason the Duplicates property does not work when sorted is true,
+  // But we don't want a sorted list so do a manual check in AddScriptFileReference
+  //FScriptFileReferences.Sorted:=true;
+  FScriptFileReferences.Duplicates:=dupIgnore;
+end;
+
+destructor TStandardWebController.Destroy;
+begin
+  FScriptFileReferences.Free;
+  FScripts.Free;
+  inherited Destroy;
+end;
+
+function TStandardWebController.InitializeJavaScriptStack: TJavaScriptStack;
+begin
+  if assigned(FCurrentJavascriptStack) then
+    raise exception.Create('There is still an old JavascriptStack available');
+  FCurrentJavascriptStack := TJavaScriptStack.Create(self);
+  Result:=FCurrentJavascriptStack;
+end;
+
+function TStandardWebController.GetUrl(ParamNames, ParamValues,
+  KeepParams: array of string; Action: string): string;
+
+var qs,p : String;
+    i,j  : integer;
+    found: boolean;
+    FancyTitle: boolean;
+    CGIScriptName: string;
+    ActionVar: string;
+    ARequest: TRequest;
+
+begin
+  FancyTitle:=false;
+  qs := '';
+  result := Action;
+  ARequest := GetRequest;
+  if assigned(owner) and (owner is TWebPage) and assigned(TWebPage(Owner).WebModule) then
+    begin
+    ActionVar := TWebPage(Owner).WebModule.ActionVar;
+    if action = '' then
+      result := TWebPage(Owner).WebModule.Actions.CurrentAction.Name;
+    end
+  else
+    ActionVar := '';
+  if ActionVar='' then FancyTitle:=true;
+  if Assigned(ARequest) then
+    begin
+    if  (high(KeepParams)>=0) and (KeepParams[0]='*') then
+      begin
+      for i := 0 to ARequest.QueryFields.Count-1 do
+        begin
+        p := ARequest.QueryFields.Names[i];
+        found := False;
+        for j := 0 to high(ParamNames) do if sametext(ParamNames[j],p) then
+          begin
+          found := True;
+          break;
+          end;
+        if not FancyTitle and SameText(ActionVar,p) then
+          found := true;
+        if not found then
+          qs := qs + p + '=' + ARequest.QueryFields.ValueFromIndex[i] + '&';
+        end;
+      end
+    else for i := 0 to high(KeepParams) do
+      begin
+      p := ARequest.QueryFields.Values[KeepParams[i]];
+      if p <> '' then
+        qs := qs + KeepParams[i] + '=' + p + '&';
+      end;
+    end;
+  for i := 0 to high(ParamNames) do
+    qs := qs + ParamNames[i] + '=' + ParamValues[i] + '&';
+
+  if ScriptName='' then CGIScriptName:='.'
+  else CGIScriptName:=ScriptName;
+  if FancyTitle then // use ? or /
+    result := CGIScriptName + '/' + Result
+  else
+    result := CGIScriptName + '?'+ActionVar+'=' + Result;
+
+  p := copy(qs,1,length(qs)-1);
+  if p <> '' then
+    begin
+    if FancyTitle then
+      result := result + '?' + p
+    else
+      result := result + '&' + p;
+    end
+end;
+
+procedure TStandardWebController.FreeJavascriptStack;
+begin
+  FreeAndNil(FCurrentJavascriptStack);
+end;
+
+procedure TStandardWebController.BindJavascriptCallstackToElement(AComponent: TComponent; AnElement: THtmlCustomElement; AnEvent: string);
+begin
+  case AnEvent of
+    'onclick' : (AnElement as THTMLAttrsElement).onclick:=CurrentJavaScriptStack.GetScript;
+    'onchange' : if AnElement is THTML_input then (AnElement as THTML_input).onchange:=CurrentJavaScriptStack.GetScript;
+  end; {case}
+end;
+
+procedure TStandardWebController.AddScriptFileReference(AScriptFile: String);
+var i: integer;
+begin
+  if not FScriptFileReferences.Find(AScriptFile,i) then
+    FScriptFileReferences.Add(AScriptFile);
+end;
+
+end.
+