Index: openacs-4/packages/xotcl-core/xotcl-core.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/xotcl-core.info,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/xotcl-core.info	11 Oct 2005 08:41:17 -0000	1.1
+++ openacs-4/packages/xotcl-core/xotcl-core.info	14 Dec 2005 15:55:28 -0000	1.2
@@ -8,10 +8,10 @@
     <singleton-p>t</singleton-p>
     <auto-mount>xotcl</auto-mount>
 
-    <version name="0.15" url="http://media.wu-wien.ac.at/download/xotcl-core-0.15.apm">
+    <version name="0.27" url="http://media.wu-wien.ac.at/download/xotcl-core-0.27.apm">
         <owner url="mailto:neumann@wu-wien.ac.at">Gustaf Neumann</owner>
-        <summary>XOTcl library functionality (e.g. thread handling, online documentation)</summary>
-        <release-date>2005-10-07</release-date>
+        <summary>XOTcl library functionality (e.g. thread handling, online documentation, Generic Form and List Classes)</summary>
+        <release-date>2005-12-08</release-date>
         <description format="text/html">This component contains some core functionality for OACS
 applications using XOTcl. It includes
 XOTcl thread handling for OACS (supporting persistent and
@@ -22,9 +22,10 @@
 and ad_instproc. This component  provides as 
 well an XOTcl Object and Class browser, as well as
 means to control the recreation of objects and classes
-when components are reloaded.</description>
+when components are reloaded. 0.23 contains a major overhaul of the Generic classes. Object preliminary object layer for content repository, oo templating.</description>
+        <maturity>0</maturity>
 
-        <provides url="xotcl-core" version="0.15"/>
+        <provides url="xotcl-core" version="0.27"/>
 
         <callbacks>
         </callbacks>
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml	14 Dec 2005 15:57:52 -0000	1.1
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<message_catalog package_key="xotcl-core" package_version="0.18" locale="de_DE" charset="ISO-8859-1">
+
+  <msg key="live_revision">Aktuelle Version</msg>
+  <msg key="revision_title">Versionen des Eintrags</msg>
+  <msg key="revisions">Verlauf</msg>
+</message_catalog>
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml.orig
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/Attic/xotcl-core.de_DE.ISO-8859-1.xml.orig,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml.orig	14 Dec 2005 15:57:52 -0000	1.1
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<message_catalog package_key="xotcl-core" package_version="0.18" locale="de_DE" charset="ISO-8859-1">
+
+  <msg key="live_revision">Aktuelle Version</msg>
+  <msg key="revision_title">Versionen des Eintrags</msg>
+  <msg key="revisions">Verlauf</msg>
+</message_catalog>
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml	14 Dec 2005 15:57:52 -0000	1.1
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<message_catalog package_key="xotcl-core" package_version="0.17" locale="en_US" charset="ISO-8859-1">
+
+  <msg key="live_revision">Live Revision</msg>
+  <msg key="revision_title">Revisions of Entry</msg>
+  <msg key="revisions">Revisions</msg>
+</message_catalog>
Index: openacs-4/packages/xotcl-core/lib/revisions-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/lib/revisions-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/lib/revisions-postgresql.xql	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+
+<queryset>
+  <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+  <fullquery name="revisions_info">      
+    <querytext>
+    select  n.title, n.revision_id as version_id,
+      person__name(n.creation_user) as author,
+      n.creation_user as author_id,
+      to_char(n.last_modified,'YYYY-MM-DD HH24:MI:SS') as last_modified_ansi,
+      n.description,
+      acs_permission__permission_p(n.revision_id,:user_id,'admin') as admin_p,
+      acs_permission__permission_p(n.revision_id,:user_id,'delete') as delete_p,
+      char_length(n.data) as content_size,
+      content_revision__get_number(n.revision_id) as version_number	
+    from cr_revisionsi n, cr_items ci
+    where ci.item_id = n.item_id and ci.item_id = :page_id
+          and exists (select 1 from acs_object_party_privilege_map m
+                      where m.object_id = n.revision_id
+                        and m.party_id = :user_id
+                        and m.privilege = 'read')
+	order by n.revision_id desc
+    </querytext>
+  </fullquery> 
+</queryset>
+
+
Index: openacs-4/packages/xotcl-core/lib/revisions.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/lib/revisions.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/lib/revisions.adp	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1 @@
+<listtemplate name="revisions"></listtemplate>
Index: openacs-4/packages/xotcl-core/lib/revisions.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/lib/revisions.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/lib/revisions.tcl	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,99 @@
+ad_page_contract {
+  display information about revisions of content items
+
+  @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+  @creation-date Oct 23, 2005
+  @cvs-id $Id: revisions.tcl,v 1.1 2005/12/14 15:57:53 maltes Exp $
+} {
+  page_id:integer,notnull
+  {title ""}
+} -properties {
+  title:onevalue
+  context:onevalue
+  page_id:onevalue
+  revisions:multirow
+  gc_comments:onevalue
+}
+
+# check they have read permission on content item
+permission::require_permission -object_id $page_id -privilege read
+
+set user_id [ad_conn user_id]
+set live_revision_id [content::item::get_live_revision -item_id $page_id]
+
+template::list::create \
+    -name revisions \
+    -no_data [_ file-storage.lt_There_are_no_versions] \
+    -multirow revisions \
+    -elements {
+      version_number {label "" html {align right}}
+      title { label ""
+	display_template {
+	  <img src='/resources/acs-subsite/Zoom16.gif' \
+	      title='View Item' alt='view' \
+	      width="16" height="16" border="0">
+	}
+	sub_class narrow
+	link_url_col version_link
+      }
+      author { label #file-storage.Author#
+	display_template {@revisions.author_link;noquote@}
+      }
+      content_size { label #file-storage.Size# html {align right}
+	display_col content_size_pretty
+      }
+      last_modified_ansi { label #file-storage.Last_Modified#
+	display_col last_modified_pretty
+      }
+      description { label #file-storage.Version_Notes#}
+      live_revision { label #xotcl-core.live_revision#
+	display_template {
+	  <a href='@revisions.live_revision_link@'> \
+	  <img src='@revisions.live_revision_icon@' \
+	      title='@revisions.live_revision@' alt='@revisions.live_revision@' \
+	      width="16" height="16" border="0"></a>
+	}
+	html {align center}
+	sub_class narrow
+      }
+      version_delete { label "" link_url_col version_delete_link
+	display_template {
+	  <img src='/resources/acs-subsite/Delete16.gif' \
+	      title='Delete Revision' alt='delete' \
+	      width="16" height="16" border="0">
+	}
+	html {align center}
+      }
+    }
+
+db_multirow -unclobber -extend { 
+  author_link last_modified_pretty 
+  content_size_pretty version_link version_delete version_delete_link 
+  live_revision live_revision_icon live_revision_link
+} revisions revisions_info {} {
+  set version_number $version_number:
+  set last_modified_ansi   [lc_time_system_to_conn $last_modified_ansi]
+  set last_modified_pretty [lc_time_fmt $last_modified_ansi "%x %X"]
+  if {$content_size < 1024} {
+    set content_size_pretty "[lc_numeric $content_size] [_ file-storage.bytes]"
+  } else {
+    set content_size_pretty "[lc_numeric [format %.2f [expr {$content_size/1024.0}]]] [_ file-storage.kb]"
+  }
+  
+  if {$title eq ""} {set title [_ file-storage.untitled]}
+  set live_revision_link [export_vars -base make-live-revision \
+			      {page_id title {revision_id $version_id}}]
+  set version_delete_link [export_vars -base delete-revision \
+			       {page_id title {revision_id $version_id}}]
+  set version_link [export_vars -base view {{revision_id $version_id} {item_id $page_id}}]
+  if {$version_id != $live_revision_id} {
+    set live_revision "Make this Revision Current"
+    set live_revision_icon /resources/acs-subsite/radio.gif
+  } else {
+    set live_revision "Current Live Revision"
+    set live_revision_icon /resources/acs-subsite/radiochecked.gif
+  }
+  set version_delete [_ file-storage.Delete_Version]
+  set author_link [acs_community_member_link -user_id $author_id -label $author]
+}
+
Index: openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl	14 Dec 2005 15:55:29 -0000	1.2
@@ -2,11 +2,17 @@
 ::Serializer exportMethods {
   ::xotcl::Object instproc log 
   ::xotcl::Object instproc debug
+  ::xotcl::Object instproc contains
 }
 
+::xotcl::Object instproc contains cmds {
+  my requireNamespace
+  namespace eval [self] $cmds
+}
+
 ::xotcl::Object instproc log msg {
-  ns_log notice "[self] $msg"
+  ns_log notice "[self] [self callingclass]->[self callingproc]: $msg"
 }
 ::xotcl::Object instproc debug msg {
-  ns_log debug "[self] $msg"
+  ns_log debug "[self] [self callingclass]->[self callingproc]: $msg"
 }
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/05-doc-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/05-doc-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/tcl/05-doc-procs.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/tcl/05-doc-procs.tcl	14 Dec 2005 15:55:29 -0000	1.2
@@ -20,21 +20,14 @@
   ::xotcl::Class  instproc ad_instproc
   ::xotcl::Object instproc ad_doc
   ::xotcl::Object instproc __api_make_doc
+  ::xotcl::Object instproc __api_make_forward_doc
 }
 ::Serializer exportObjects {
   ::xotcl::api
 }
 
 ::xotcl::Object create ::xotcl::api \
-    -proc split_arguments {} {
-      my upvar args args arguments arguments doc doc body body
-      if {[llength $args]==3} {
-	foreach {arguments doc body} $args break
-      } else {
-	error "wrong number of arguments provided to ad_proc or ad_instproc"
-      }
-
-    } -proc isclass {scope obj} {
+    -proc isclass {scope obj} {
       if {$scope eq ""} {
 	set isclass [::xotcl::Object isclass $obj]
       } else {
@@ -59,7 +52,7 @@
       return $scope
 
     } -proc inscope {scope args} {
-      expr {$scope eq "" ? [eval $args] : [$scope do $args]}
+      expr {$scope eq "" ? [eval $args] : [eval $scope do $args]}
 
     } -proc script_name {scope} {
       #set kind [expr {[my istype ::xotcl::Class] ? "Class" : "Object"}]
@@ -180,28 +173,78 @@
   nsv_set api_proc_doc $proc_index [array get doc_elements]
 }
 
-::xotcl::Object instproc ad_proc {
-   {-private:switch false}
-   {-deprecated:switch false}
-   {-warn:switch false}
-   {-debug:switch false} 
-} {proc_name args} {
-  ::xotcl::api split_arguments
-  uplevel [list [self] proc $proc_name $arguments $body]
-  my __api_make_doc "" $proc_name
+::xotcl::Object instproc __api_make_forward_doc {inst method_name} {
+  upvar doc doc private private public public deprecated deprecated
+  if {$doc eq ""} {
+    set doc_elements(main) ""
+  } else {
+    ad_parse_documentation_string $doc doc_elements
+    #my log "doc_elements=[array get doc_elements]"
+  }
+  set defaults [list]
+  set public [expr {$private ? false : true}]
+  set doc_elements(public_p) $public
+  set doc_elements(private_p) $private
+  set doc_elements(deprecated_p) $deprecated
+  set doc_elements(varargs_p) false
+  set doc_elements(flags) [list]
+  set doc_elements(switches) [list]
+  set doc_elements(default_values) [list]
+  set doc_elements(positionals) [list] 
+  # argument documentation finished
+  set scope [::xotcl::api scope]
+  set doc_elements(script) [::xotcl::api script_name $scope]
+  set proc_index [::xotcl::api proc_index $scope [self] ${inst}forward $method_name]
+  if {![nsv_exists api_proc_doc $proc_index]} {
+    nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
+  }
+  my log "doc_elements=[array get doc_elements]"
+  my log "SETTING api_proc_doc '$proc_index'"
+  nsv_set api_proc_doc $proc_index [array get doc_elements]
 }
 
+::xotcl::Object instproc ad_proc {
+  {-private:switch false}
+  {-deprecated:switch false}
+  {-warn:switch false}
+  {-debug:switch false} 
+  proc_name arguments doc body} {
+    uplevel [list [self] proc $proc_name $arguments $body]
+    my __api_make_doc "" $proc_name
+  }
+
+::xotcl::Object instproc ad_forward {
+  {-private:switch false}
+  {-deprecated:switch false}
+  {-warn:switch false}
+  {-debug:switch false} 
+  method_name doc args} {
+    uplevel [self] forward $method_name $args
+    my __api_make_forward_doc "" $method_name
+  }
+
 ::xotcl::Class instproc ad_instproc {
    {-private:switch false}
    {-deprecated:switch false}
    {-warn:switch false}
    {-debug:switch false} 
-} {proc_name args} {
-  ::xotcl::api split_arguments
-  uplevel [list [self] instproc $proc_name $arguments $body]
-  my __api_make_doc inst $proc_name
-}
+  proc_name arguments doc body} {
+    uplevel [list [self] instproc $proc_name $arguments $body]
+    my __api_make_doc inst $proc_name
+  }
 
+::xotcl::Object instproc ad_instforward {
+  {-private:switch false}
+  {-deprecated:switch false}
+  {-warn:switch false}
+  {-debug:switch false} 
+  method_name doc args} {
+    uplevel [self] instforward $method_name $args
+    my __api_make_forward_doc inst $method_name
+  }
+
+
+
 ::xotcl::Object instproc ad_doc {doc_string} {
   ad_parse_documentation_string $doc_string doc_elements
   set scope [::xotcl::api scope]
Index: openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl	14 Dec 2005 15:55:29 -0000	1.2
@@ -8,7 +8,7 @@
   XOTcl provides support for altering this behavior through 
   the recreate method.
 
-  @author Gustaf Neumann
+  @author Gustaf Neumann (neumann@wu-wien.ac.at)
   @creation-date 2005-05-13
   @cvs-id $Id$
 }
@@ -54,7 +54,7 @@
     {instreinit}
   } -superclass ::xotcl::Class \
       -instproc recreate {obj args} {
-	my log "### recreateclass instproc $obj <$args>"
+	#my log "### recreateclass instproc $obj <$args>"
 	# the minimal reconfiguration is to set the class and remove methods
 	$obj class [self]
 	foreach p [$obj info procs] {$obj proc $p {} {}}
@@ -133,19 +133,27 @@
 } {
   # clean on the object level
   my log "+++ instproc recreate $obj <$args> old class = [$obj info class], new class = [self]"
+  $obj filter set {}
+  $obj mixin set {}
   set cl [self] 
-  $obj class $cl
-  foreach p [$obj info procs] {$obj proc $p {} {}}
+  foreach p [$obj info commands] {$obj proc $p {} {}}
   foreach c [$obj info children] {
     my log "recreate destroy <$c destroy"
     $c destroy
   }
-  foreach var [$obj info vars] {$obj unset $var}
-  $obj mixin set {}
-  $obj filter set {}
+  #my log "+++ $obj recreate unset vars"
+  #my log "+++ $obj vars = {[$obj info vars]}"
+  foreach var [$obj info vars] {
+    #my log "$obj unset $var"
+    $obj unset $var
+  }
+  #my log "+++ $obj recreate unset vars done" 
+  # set p new values
+  $obj class $cl 
   set pcl [$cl info parameterclass]
+  #my log "+++ $obj recreate calling searchDefaults"
   $pcl searchDefaults $obj
-  #my log "+++ recreate calling $obj configure $args"
+  #my log "+++ $obj recreate calling $obj configure $args"
   set pos [eval $obj configure $args]
   #my log "+++ recreate instproc configure returns $pos"
   if {[lsearch -exact $args -init] == -1} {
@@ -155,7 +163,10 @@
   }
 }
 
+#::xotcl::Object instforward unset -objscope 
+#  ::xotcl::Object instforward unset
 ::Serializer exportMethods {
   ::xotcl::Class instproc recreate
   ::xotcl::Class proc recreate
+  ::xotcl::Object instforward unset
 }
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl-old
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/10-recreation-procs.tcl-old,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl-old	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,161 @@
+ad_library {
+  Support for the recreation of classes objects without
+  destroying foreign references. Normally, when a class
+  definition is reloaded, the class is destroyed and created
+  again with the same name. During the destruction of a class
+  several references to this class are removed (e.g. in a
+  class hierarchy, the relation from instances to this class, etc.).
+  XOTcl provides support for altering this behavior through 
+  the recreate method.
+
+  @author Gustaf Neumann
+  @creation-date 2005-05-13
+  @cvs-id $Id: 10-recreation-procs.tcl-old,v 1.1 2005/12/14 15:57:53 maltes Exp $
+}
+
+if {![::xotcl::Object isclass ::xotcl::RecreationClass]} {
+  ::xotcl::Class create ::xotcl::RecreationClass -ad_doc {
+    <p>This meta-class controlls the behavior of classes (and optionally
+    their instances), when the classes (or their instances) are	
+    overwritten by same named new objects; we call this situation
+    a recreate of an object.</p>
+					     
+    <p>Normally, when files with e.g. class definitions are sourced,
+    the classes and objects are newly defined. When e.g. class 
+    definitions exists already in this file, these classes are 
+    deleted first before they are newly created. When a class is 
+    deleted, the instances of this class are changed into 
+    instances of class ::xotcl::Object. </p>
+
+    <p>This can be a problem when the class instances are not 
+    reloaded and when they should survife the redefintion with the
+    same class relationships. Therefore we define a 
+    meta class RecreationClass, which can be used to parameterize 
+    the behavior on redefinitions. Alternatively, Classes or objects
+    could provide their own recreate methods.</p>
+
+    <p>Per default, this meta-class handles only the class redefintion
+    case and does only a reconfigure on the class object (in order
+    to get e.g. ad_doc updated).</p>
+    The following parameters are defined:
+    <ul>
+    <li><b>reconfigure:</b> reconfigure class (default 1)
+    <li><b>reinit:</b> run init after configure for this class (default unset)
+    <li><b>instrecreate:</b> handle recreate of class instances (default unset)
+      When this flag is set to 0, instreconfigure and instreinit are ignored.
+    <li><b>instreconfigure:</b> reconfigure instances of this class (default 1)
+    <li><b>instreinit:</b> re-init instances of this class (default unset)
+    </ul>
+  } -parameter {
+    {reconfigure 1}
+    {reinit}
+    {instrecreate}
+    {instreconfigure 1}
+    {instreinit}
+  } -superclass ::xotcl::Class \
+      -instproc recreate {obj args} {
+	my log "### recreateclass instproc $obj <$args>"
+	# the minimal reconfiguration is to set the class and remove methods
+	$obj class [self]
+	foreach p [$obj info procs] {$obj proc $p {} {}}
+	if {![my exists instrecreate]} {
+	  #my log "### no instrecreate for $obj <$args>"
+	  next
+	  return
+	}
+	if {[my exists instreconfigure]} {
+	  # before we set defaults, we must unset vars
+	  foreach var [$obj info vars] {$obj unset $var}
+	  set pcl [my info parameterclass]
+	  # set defaults and run configure
+	  $pcl searchDefaults $obj
+	  eval $obj configure $args
+	  #my log "### instproc recreate $obj + configure $args ..."
+	}
+	if {[my exists instreinit]} {
+	  #my log "### instreinit for $obj <$args>"
+	  eval $obj init 
+	  #my log "### instproc recreate $obj + init ..."
+	}
+      } -proc recreate {obj args} {
+	my log "### recreateclass proc $obj <$args>"
+	# the minimal reconfiguration is to set the class and remove methods
+	$obj class [self]
+	foreach p [$obj info instprocs] {$obj instproc $p {} {}}
+	if {[my exists reconfigure]} {
+	  # before we set defaults, we must unset vars
+	  foreach var [$obj info vars] {$obj unset $var}
+	  set pcl [my info parameterclass]
+	  $pcl searchDefaults $obj
+	  # set defaults and run configure
+	  eval $obj configure $args
+	}
+	if {[my exists reinit]} {
+	  eval $obj init 
+	}
+      }
+
+  ::Serializer exportObjects {
+    ::xotcl::RecreationClass 
+  }
+}
+
+Class ad_proc recreate {obj args} { 
+  The re-definition of recreate makes reloading of class definitions via 
+  apm possible, since the foreign keys of the class relations 
+  to these classes survive these calls. One can define specialized
+  versions of this for certain classes or use ::xotcl::RecreationClass.
+
+  Class proc recreate is called on the class level, while 
+  Class instproc recreate is called on the instance level.
+
+  @param obj name of the object to be recreated
+  @param args arguments passed to recreate (might contain parameters)
+} {
+  # clean on the class level
+  #my log "proc recreate $obj $args"
+  foreach p [$obj info instprocs] {$obj instproc $p {} {}}
+  $obj instmixin set {}
+  $obj instfilter set {}
+  next ; # clean next on object level
+}
+Class ad_instproc recreate {obj args} { 
+  The re-definition of recreate makes reloading of class definitions via 
+  apm possible, since the foreign keys of the class relations 
+  to these classes survive these calls. One can define specialized
+  versions of this for certain classes or use ::xotcl::RecreationClass.
+
+  Class proc recreate is called on the class level, while 
+  Class instproc recreate is called on the instance level.
+
+  @param obj name of the object to be recreated
+  @param args arguments passed to recreate (might contain parameters)
+} {
+  # clean on the object level
+  my log "+++ instproc recreate $obj <$args> old class = [$obj info class], new class = [self]"
+  set cl [self] 
+  $obj class $cl
+  foreach p [$obj info procs] {$obj proc $p {} {}}
+  foreach c [$obj info children] {
+    my log "recreate destroy <$c destroy"
+    $c destroy
+  }
+  foreach var [$obj info vars] {$obj unset $var}
+  $obj mixin set {}
+  $obj filter set {}
+  set pcl [$cl info parameterclass]
+  $pcl searchDefaults $obj
+  #my log "+++ recreate calling $obj configure $args"
+  set pos [eval $obj configure $args]
+  #my log "+++ recreate instproc configure returns $pos"
+  if {[lsearch -exact $args -init] == -1} {
+    incr pos -1
+    #my log "+++ $obj init [lrange $args 0 $pos]"
+    eval $obj init [lrange $args 0 $pos]
+  }
+}
+
+::Serializer exportMethods {
+  ::xotcl::Class instproc recreate
+  ::xotcl::Class proc recreate
+}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,88 @@
+ad_library {
+  ::xo::OrderedComposite to create tree structures with aggregated
+  objects. This is similar to object aggregations, but
+  preserves the order. The OrderedComposite supports
+  hierarchical sorting.
+
+  @author Gustaf Neumann (neumann@wu-wien.ac.at)
+  @creation-date 2005-11-26
+  @cvs-id $Id: 20-Ordered-Composite-procs.tcl,v 1.1 2005/12/14 15:57:53 maltes Exp $
+}
+
+namespace eval ::xo {
+  Class OrderedComposite 
+
+  OrderedComposite instproc show {} {
+    next
+    foreach child [my children] {
+      $child show
+    }
+  }
+
+  OrderedComposite instproc orderby {{-order "increasing"} variable} {
+    my set __order $order
+    my set __orderby $variable
+  }
+
+  OrderedComposite instproc __compare {a b} {
+    set by [my set __orderby]
+    set x [$a set $by]
+    set y [$b set $by]
+    if {$x < $y} {
+      return -1
+    } elseif {$x > $y} {
+      return 1
+    } else {
+      return 0
+    }
+  }
+
+  OrderedComposite instproc children {} {
+    set children [expr {[my exists __children] ? [my set __children] : ""}]
+    if {[my exists __orderby]} {
+      set order [expr {[my exists __order] ? [my set __order] : "increasing"}]
+      return [lsort -command [list my __compare] -$order $children]
+    } else {
+      return $children
+    }
+  }
+  OrderedComposite instproc add obj {
+    my lappend __children $obj
+    $obj set __parent [self]
+    #my log "-- adding __parent [self] to $obj -- calling after_insert"
+    #$obj __after_insert
+  }
+
+  OrderedComposite instproc destroy {} {
+    # destroy all children of the ordered composite
+    foreach c [my set __children] { $c destroy }
+    next
+  }
+
+  OrderedComposite instproc contains cmds {
+    my requireNamespace ;# legacy for older xotcl versions
+    set m [Object info instmixin]
+    if {[lsearch $m [self class]::ChildManager] == -1} {
+      set insert 1
+      Object instmixin add [self class]::ChildManager
+    } else { 
+      set insert 0
+    }
+    set errorOccurred [catch {namespace eval [self] $cmds} errorMsg]
+    if {$insert} {
+      Object instmixin delete [self class]::ChildManager
+    }
+    if {$errorOccurred} {error $errorMsg}
+  }
+  Class OrderedComposite::ChildManager -instproc init args {
+    set r [next]
+    [self callingobject] lappend __children [self]
+    my set __parent [self callingobject]
+    #my __after_insert
+    #my log "-- adding __parent  [self callingobject] to [self]"
+    return $r
+  }
+
+  Class OrderedComposite::Child -instproc __after_insert {} {;}
+
+}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,319 @@
+ad_library {
+  XOTcl HTML Widget Classes based on tdom
+
+  @author Gustaf Neumann (neumann@wu-wien.ac.at)
+  @author Neophytos Demetriou (k2pts@phigita.net)
+  @creation-date 2005-11-26
+  @cvs-id $Id: 30-widget-procs.tcl,v 1.1 2005/12/14 15:57:53 maltes Exp $
+}
+
+::Serializer exportMethods {
+  ::xotcl::Object instproc asHTML
+}
+
+Object instproc asHTML {{-master defaultMaster} -page:switch} {
+  require_html_procs
+  dom createDocument html doc
+  set root [$doc documentElement]
+  if {!$page} {
+    $root appendFromScript {my render}
+    return [[$root childNode] asHTML]
+  } else {
+    set slave [$master decorate $root]
+    $slave appendFromScript {my render}
+    ns_return 200 text/html [$root asHTML]
+  }
+}
+
+#
+# Define Widget classes
+#
+# ::xo::Table, somewhat similar to the classical multirow 
+
+namespace eval ::xo {
+  Class Table -superclass OrderedComposite \
+      -parameter {{no_data  "No Data"} {renderer TABLE2}}
+
+  Table instproc actions {cmd} {
+    set M [OrderedComposite create [self]::__actions]
+    namespace eval $M {namespace import -force [self class]::*}
+    $M contains $cmd
+  }
+  Table instproc columns {cmd} {
+    set M [OrderedComposite create [self]::__columns]
+    namespace eval $M {namespace import -force [self class]::*}
+    $M contains $cmd
+    set slots [list]
+    foreach c [$M children] {
+      eval lappend slots [$c get-slots]
+    }
+    my proc add $slots {
+      set __self [Object new]
+      foreach __v [info vars] {$__self set $__v [set $__v]}
+      next $__self
+    }
+  }
+
+  Table instproc render_with {renderer} {
+    #my log "--"
+    set cl [self class]
+    [self] mixin ${cl}::$renderer 
+    foreach child [$cl info classchildren] {
+      #my log "-- $child heritage [$child info heritage]"
+      if {[$child info heritage ::xo::OrderedComposite::Child] eq ""} continue
+      $child instmixin ${cl}::${renderer}::[namespace tail $child]
+      #my log "-- $child instmixin ${cl}::${renderer}::[namespace tail $child]"
+    }
+    my init_renderer
+  }
+
+  Table instproc write_csv {} {
+    set output ""
+    set line [list]
+    foreach column [[self]::__columns children] {
+      set value [string map {\" \\\"} [$column name]]
+      lappend line \"$value\"
+    }
+    append output [join $line ,] \n
+    foreach row [my children] {
+      set line [list]
+      foreach column [[self]::__columns children] {
+	set value [string map {\" \\\"} [$row set [$column name]]]
+	lappend line \"$value\"
+      }
+      append output [join $line ,] \n
+    }
+    ns_return 200 text/csv $output
+  }
+
+  #
+  # Define elements of a Table
+  #
+  namespace eval ::xo::Table {
+    Class Action \
+	-superclass ::xo::OrderedComposite::Child \
+	-parameter {label url {tooltip {}}}
+
+    Class Field \
+	-superclass ::xo::OrderedComposite::Child \
+	-parameter {label {html {}} {orderby ""} name} \
+	-instproc init {} {
+	  my set name [namespace tail [self]]
+	} \
+	-instproc get-slots {} {
+	  return -[my name]
+	}
+
+    Class AnchorField \
+	-superclass ::xo::Table::Field \
+	-instproc get-slots {} {
+	  set slots [list -[my name]]
+	  foreach subfield {href text} {
+	    lappend slots [list -[my name].$subfield ""]
+	  }
+	  return $slots
+	}
+  
+    # export table elements
+    namespace export Field AnchorField  Action
+  }
+}
+
+
+namespace eval ::xo::Table {
+  #
+  # Class for rendering ::xo::Table as the html TABLE
+  #
+  Class TABLE \
+      -instproc init_renderer {} {
+	#my log "--"
+	my set __rowcount 0
+      }
+
+  TABLE instproc render-actions {} {
+    html::tr -class list-button-bar  {
+      set cols [llength [[self]::__columns children]]
+      html::td -colspan $cols -class list-button-bar {
+	set children [[self]::__actions children]
+	set last [lindex $children end]
+	foreach o $children {
+	  $o render
+	  if {$o ne $last} {
+	    html::t -disableOutputEscaping "&middot;"
+	  }
+	}
+      } 
+    }
+  }
+  
+  TABLE instproc render-body {} {
+    html::tr -class list-header {
+      foreach o [[self]::__columns children] {
+	$o render
+      }
+    }
+    set children [my children]
+    if {[llength $children] == 0} {
+      html::tr {html::td { html::t [my set no_data]}}
+    } else {
+      foreach line [my children] {
+	html::tr -class [expr {[my incr __rowcount]%2 ? "list-odd" : "list-even" }] {
+	  foreach field [[self]::__columns children] {
+	    html::td  [concat [list class list] [$field html]] { 
+	      $field render-data $line
+	    }
+	  }
+	}
+      }
+    }
+  }
+  
+  TABLE instproc render {} {
+    if {![my isobject [self]::__actions]} {my actions {}}
+    html::table -class list {
+      my render-actions
+      my render-body
+    }
+  }
+
+  #
+  # Define renderer for elements of a Table
+  # 
+  # ::xo:Table requires the elements to have the methods render and render-data 
+  #
+
+  Class create TABLE::Action -instproc render {} {
+    html::a -class button -title [my tooltip] -href [my url] { html::t [my label] } 
+  }
+
+  Class create TABLE::Field
+  TABLE::Field instproc render-data {line} {
+    html::t [$line set [my name]] 
+  }
+
+  TABLE::Field instproc render {} {
+    html::th [concat [list class list] [my html]] { 
+      if {[my set orderby] eq ""} {
+	html::t [my set label] 
+      } else {
+	my renderSortLabels
+      }
+    }
+  }
+
+  TABLE::Field instproc renderSortLabels {} {
+    set field [my set orderby]
+    upvar #[template::adp_level] orderby orderby
+    if {![info exists orderby]} {set orderby ""}
+    set new_orderby $orderby
+    if {$orderby eq "$field,desc"} {
+      set new_orderby $field,asc
+      set title "Sort by this column ascending"
+      set img /resources/acs-templating/sort-ascending.png
+    } elseif {$orderby eq "$field,asc"} {
+      set new_orderby $field,desc
+      set title "Sort by this column descending"
+      set img /resources/acs-templating/sort-descending.png
+    } else {
+      set new_orderby $field,asc
+      set title "Sort by this column"
+      set img /resources/acs-templating/sort-neither.png
+    }
+    set query [list [list orderby $new_orderby]]
+    foreach pair [split [ns_conn query] &] {
+      foreach {key value} [split $pair =] break
+      if {$key eq "orderby"} continue
+      lappend query [list [ns_urldecode $key] [ns_urldecode $value]]
+    }
+    set href [export_vars -base [ad_conn url] $query]
+    html::a -href $href -title $title {
+      html::t [my set label]
+      html::img -src $img -alt ""
+    }
+  }
+
+  Class create TABLE::AnchorField \
+      -superclass TABLE::Field \
+      -instproc render-data {line} {
+	if {[$line exists [my name].href] && 
+	    [set href [$line set [my name].href]] ne ""} {
+	  html::a -href $href { 
+	    return [next]
+	  }
+	}
+	next
+      }
+
+
+  Class TABLE2 \
+      -superclass TABLE \
+      -instproc render-actions {} {
+	html::div -id "actions" -style "float: left" {
+	  html::ul -style "list-style:none; padding: 10px;" {
+	    foreach o [[self]::__actions children] {
+	      html::li -class "button" {$o render}
+	    }
+	  }
+	}
+      } \
+      -instproc render {} {
+	if {![my isobject [self]::__actions]} {my actions {}}
+	html::div  {
+	  my render-actions
+	  html::div -class table {
+	    html::table -class list {my render-body}
+	  }
+	}
+      }
+
+  Class create TABLE2::Action -superclass TABLE::Action
+  Class create TABLE2::Field -superclass TABLE::Field
+  Class create TABLE2::AnchorField -superclass TABLE::AnchorField
+  
+}
+
+Class TableWidget \
+    -superclass ::xo::Table \
+    -instproc init {} {
+      my render_with [my renderer]
+      next
+    }
+
+
+
+#
+# Pure List widget
+#
+
+Class ListWidget -superclass ::xo::OrderedComposite -instproc render {} {
+  html::ul {
+    foreach o [my children] {
+      html::li {
+        $o render
+      }
+    }
+  }
+}
+
+
+#
+# Define two Master templates, an empty one and one page master
+#
+
+Object defaultMaster -proc decorate {node} {
+   $node appendFromScript {
+     set slave [tmpl::div]
+   }
+  return $slave
+}
+
+Object pageMaster -proc decorate {node} {
+  $node appendFromScript {
+    html::div -class defaultMasterClass {
+      html::t "hello header"
+      set slave [tmpl::body]
+      html::t "hello footer"
+    }
+  }
+  return $slave
+}
Index: openacs-4/packages/xotcl-core/tcl/generic-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/generic-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/tcl/generic-procs.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/tcl/generic-procs.tcl	14 Dec 2005 15:55:29 -0000	1.2
@@ -8,25 +8,24 @@
 
 namespace eval ::Generic {
 
-  # We do not want to re-source all of the user-data-models,
-  # when small things in the definition of the CrClass change. Normally,
-  # sourcing of this file causes CrClass do be destroyed with 
-  # the consequence, that instances of CrClass loose their 
-  # class-releationship. 
-
   Class CrClass -superclass Class -parameter {
     pretty_name
     pretty_plural
     {supertype content_revision}
     table_name
     id_column
-    sql_attributes
+    {cr_attributes {}}
+    {sql_attribute_names {}}
+    form
+    edit_form
     {name_method ""}
-    {description ""}
+    {description " "}
     {mime_type text/plain}
     {nls_language ""}
-    {text ""}
+    {text " "}
     {storage_type "text"}
+    {folder_id -100}
+    {object_type [self]}
   } -ad_doc {
     <p>The meta class CrClass serves for a class of applications that mostly 
     store information in the content repository and that use a few 
@@ -43,30 +42,31 @@
     (requires that 
     all instances of this type are deleted).</p>
 
-    <p>Each content item is retrieved though the method 
-    <a href='#instproc-get'>get</a>,
-    added through the method 
-    <a href='#instproc-add'>add</a>,
-    edited (updated) throught the 
-    method 
-    <a href='#instproc-edit'>edit</a>,
-    and deleted though the the method 
-    <a href='#instproc-delete'>delete</a>. </p>
+    <p>Each content item can be retrieved either through the 
+    general method 
+    <a href='proc-view?proc=%3a%3aGeneric%3a%3aCrItem+proc+instantiate'>
+    CrItem instantiate</a> or through the "instantiate" method of 
+    every subclass of CrItem.
 
-    <p>This Class provides generic methods for these purposes. For more 
-    complex applications, these methods will be most probably overwritten
-    by defining subclasses with (some of) these methods or by object 
-    specific methods.</p>
+    <p>This Class is a meta-class providing methods for Classes 
+    manageing CrItems.</p>
   }
 
+  proc package_id_from_package_key { key } {
+    set id [apm_version_id_from_package_key $key]
+    set mount_url [site_node::get_children -all -package_key $key -node_id $id]
+    array set site_node [site_node::get -url $mount_url]
+    return $site_node(package_id)
+  }
+
   CrClass instproc unknown { obj args } {
     my log "unknown called with $obj $args"
   }
 
-  CrClass set query_atts {
+  CrClass set common_query_atts {
     item_id creation_user creation_date last_modified object_type
   }
-  CrClass set insert_atts {title description mime_type nls_language text}
+  CrClass set common_insert_atts {title description mime_type nls_language text}
 
   CrClass instproc object_types {
     {-subtypes_first:boolean false}
@@ -79,20 +79,10 @@
       $order_clause
     "]
   }
-  
+
   CrClass instproc edit_atts {} {
-    concat [[self class] set insert_atts] [my atts]
+    concat [[self class] set common_insert_atts] [my sql_attribute_names]
   }
-  CrClass instproc atts {} {
-    set atts [list [my id_column]]
-    if {[my exists sql_attributes]} {
-      foreach att [my sql_attributes] {
-	lappend atts [lindex $att 0]
-      }
-    }
-    return $atts
-  }
-  
 
   CrClass instproc object_type_exists {} {
     my instvar object_type
@@ -101,39 +91,65 @@
       object_type = :object_type
     }]}
   }
-  
+
+  CrClass ad_instproc folder_type {
+    -folder_id
+    operation
+  } {
+    register the current object type for folder_id. If folder_id 
+    is not specified, use the instvar of the class instead.
+  } {
+    if {$operation ne "register" && $operation ne "unregister"} {
+      error "[self] operation for folder_type must be '\
+	register' or 'unregister'"
+    }
+    my instvar object_type
+    if {![info exists folder_id]} {
+      my instvar folder_id
+    }
+    db_1row register_type "select content_folder__${operation}_content_type(\
+	$folder_id,:object_type,'t')"
+  }
+
   CrClass ad_instproc create_object_type {} {
     Create an oacs object_type and a table for keeping the
     additional attributes.
   } {
     my instvar object_type supertype pretty_name pretty_plural \
 	table_name id_column name_method
 
-    my log "[self proc] $object_type"
-    set st [my info superclass]
-    if {$st ne "::xotcl::Object"} {
-      set supertype [string trimleft $st :]
+    set supertype [my info superclass]
+    switch -- $supertype {
+      ::xotcl::Object -
+      ::Generic::CrItem {set supertype content_revision}
     }
+    my log "--supertype = $supertype"
+
     db_transaction {
-      if {[my exists sql_attributes]} {
-	set sql_atts [list]
-	lappend sql_atts "$id_column integer primary key \
-		references cr_revisions(revision_id)"
-	foreach {att spec} [my sql_attributes] {
-	  lappend sql_atts "$att $spec"
-	}
-	
-	db_dml table_add "create table $table_name (\n[join $sql_atts ,\n])"
-	my log "adding table explicitely"
-      }
       db_1row create_type {
-	select content_type__create_type(:object_type,:supertype,
-					 :pretty_name, :pretty_plural,
-					 :table_name, :id_column, :name_method)
+	select content_type__create_type(
+           :object_type,:supertype,:pretty_name, :pretty_plural,
+  	   :table_name, :id_column, :name_method
+        )
       }
-      db_1row register_type {
-	select content_folder__register_content_type(-100,:object_type,'t')
+      if {[my cr_attributes] ne ""} {
+	set o [Object new -volatile -contains [my cr_attributes]]
+	foreach att [$o info children] {
+	  $att instvar attribute_name datatype pretty_name
+	  db_1row create_att {
+	    select content_type__create_attribute(
+                :object_type,:attribute_name,:datatype,
+                :pretty_name,null,null,null,'text'
+            )
+	  }
+	  #content::type::attribute::new \
+	      -content_type $object_type \
+	      -attribute_name [$att attribute_name] \
+	      -datatype [$att datatype] \
+	      -pretty_name [$att pretty_name]
+	}
       }
+      my folder_type register
     }
   }
 
@@ -144,156 +160,162 @@
   } {
     my instvar object_type table_name
     db_transaction {
-      db_1row unregister_type {
-	select content_folder__unregister_content_type(-100,:object_type,'t')
-      }
+      my folder_type unregister
       db_1row drop_type {
 	select content_type__drop_type(:object_type,'t','t')
       }
     }
   }
 
+  CrClass ad_instproc require_folder {
+    {-parent_id -100} 
+    -package_id 
+    -name
+  } {
+    Get folder_id for a community id or the actual package.
+    If everything fails, return -100
+
+    @return folder_id
+  } {
+    my instvar object_type table_name
+    if {[info exists package_id]} {
+      set cid $package_id
+    } elseif {[ad_conn isconnected]} {
+      set cid ""
+      if {[info command dotlrn_community::get_community_id_from_url] ne ""} {
+	set cid [dotlrn_community::get_community_id_from_url -url [ad_conn url]]
+      }
+      if {$cid eq ""} {
+	set cid [ad_conn package_id]
+      }
+    } else {
+      set cid -100
+    }
+    set fullname "$name: $cid"
+
+    if {[info command content::item::get_id_by_name] eq ""} {
+      set folder_id ""
+      db_0or1row get_id_by_name "select item_id as folder_id from cr_items \
+	 where name = :fullname and parent_id = :parent_id"
+    } else {
+      set folder_id [content::item::get_id_by_name \
+			 -name $fullname -parent_id $parent_id]
+    }
+    if {$folder_id eq ""} {
+      set folder_id [content::folder::new -name $fullname -parent_id $parent_id]
+    }
+    return $folder_id
+  }
+
+  CrClass instproc getFormClass {} {
+    set nsform [ns_getform]
+    set item_id [ns_set get $nsform item_id] ;# item_id should be be hardcoded
+    set confirmed_p [ns_set get $nsform __confirmed_p]
+    set new_p [ns_set get $nsform __new_p]
+    my log "-- item_id '$item_id', confirmed_p '$confirmed_p', new_p '$new_p'"
+    if {$item_id ne "" && $new_p ne "1" && [my exists edit_form]} {
+      return [my edit_form]
+    } else {
+      return [my form]
+    }
+  }
+
   CrClass instproc init {} {
-    my instvar object_type
-    set object_type [string trimleft [self] :]
-    if {[my info superclass] ne "::xotcl::Object"} {
+    my log "-- "
+    my instvar object_type sql_attribute_names
+    if {[my info superclass] ne "::Generic::CrItem"} {
       my set superclass [[my info superclass] set object_type]
     }
+    set sql_attribute_names [list]
+    set o [Object new -volatile -contains [my cr_attributes]]
+    foreach att [$o info children] {
+      lappend sql_attribute_names [$att attribute_name]
+    }
+    my log "-- attribute_names <$sql_attribute_names> [$o info children]"
+
     if {![my object_type_exists]} {
       my create_object_type
     }
     my set object_type_key [db_list get_tree_sortkey {
       select tree_sortkey from acs_object_types 
       where object_type = :object_type
     }]
+    my log "-- type key = [my set object_type_key]"
     next
   }
   
-  CrClass ad_instproc get {
-    -item_id:required
-  } { 
-    Retrieve the live revision of a content item with all attributes. 
-    The retrieved attributes are strored in the instance variables in
-    class representing the object_type.
+  CrClass ad_instproc lookup {
+    -title:required
+    -parent_id:required
+  } {
+    Check, whether an content item with the given title exists.
+    If not, return 0.
 
-    @param item_id id of the item to be retreived.
+    @return item_id
   } {
-    my instvar title table_name
-    set raw_atts [concat [[self class] set query_atts] [my edit_atts]]
-    set atts [list data]
-    foreach v $raw_atts {
-      catch {my instvar $v}
-      lappend atts n.$v
+    my instvar table_name
+
+    if {[db_0or1row entry_exists_select "
+       select n.item_id from cr_items ci, ${table_name}i n
+       where  n.title = :title and    
+       n.[my id_column] = ci.live_revision and ci.parent_id = :parent_id"]} {
+      return $item_id
     }
-    
-    db_1row note_select "
-       select [join $atts ,] from cr_items ci, ${table_name}i n
-       where  ci.item_id = :item_id 
-       and    n.[my id_column] = ci.live_revision
-    "
-    my set text $data
-    my set item_id $item_id
+    return 0
   }
-  
-  CrClass ad_instproc add {
-    form
-  } { 
-    Insert a new item to the content repository and makes 
-    it the live revision. This method obtains the values of 
-    the new content item from the specified form.
 
-    @param form form-object (instance of <a href='/xotcl/show-object?object=::Generic::Form'>::Generic::Form</a>) from where the values are obtained
-    @return item_id of the new note.
+  CrClass ad_instproc fetch_object {
+    -item_id:required
+    {-revision_id 0}
+    -object:required
   } {
-    my instvar object_type table_name storage_type
+    Load a content item into the specified object. If revision_id is
+    provided, the specified revision is returned, otherwise the live
+    revision of the item_id.
 
-    set atts [list item_id revision_id]
-    foreach v [[self class] set insert_atts] {
-      my instvar $v
-      lappend atts $v
+    @return cr item object
+  } {
+    #my log "-- [self args]"
+    my instvar table_name 
+    $object instvar parent_id
+    set raw_atts [concat [[self class] set common_query_atts] [my edit_atts]]
+    set atts [list data]
+    foreach v $raw_atts {
+      catch {$object instvar $v}
+      lappend atts n.$v
     }
-
-    set form_vars [list]
-    foreach var [$form form_vars] {lappend form_vars $var [uplevel set $var]}
-    foreach var [$form form_vars] {set $var [uplevel set $var]}
-
-    db_transaction {
-      set item_id [db_exec_plsql note_insert {
-	select content_item__new(:title,-100,null,null,null,null,null,null,
-				 'content_item',:object_type,:title,
-				 :description,:mime_type,
-				 :nls_language,:text,:storage_type)
-      }]
-      
-      set revision_id [db_nextval acs_object_id_seq]
-
-      db_dml revision_add "
-	insert into ${table_name}i ([join $atts ,]) 
-	values (:[join $atts ,:])"
- 
-      my update_main_table -revision_id $revision_id -form_vars $form_vars
-
-      db_exec_plsql make_live {
-	select content_item__set_live_revision(:revision_id)
-      }
+    if {$revision_id} {
+      db_1row note_select "
+       select [join $atts ,], i.parent_id from [my set table_name]i n, cr_items i
+       where  n.revision_id = :revision_id and i.item_id = :item_id"
+    } else {
+      db_1row note_select "
+       select [join $atts ,], i.parent_id from cr_items i, [my set table_name]i n
+       where  i.item_id = :item_id 
+       and    n.[my id_column] = i.live_revision"
     }
-    return $item_id
+    $object set text $data
+    $object set item_id $item_id
+    return $object
   }
-  
-  CrClass instproc update_main_table {
-    -revision_id
-    -form_vars
-  } {
-    my instvar table_name
-    if {[llength [my atts]]>1} {
-      set vars [list]
-      foreach a [lrange [my atts] 1 end] {lappend vars $a}
-      catch {my instvar $vars}
-      foreach {att val} $form_vars {set $att $val}
-      if {[llength $vars]>1} {
-	db_dml main_table_update "
-	   update $table_name set ([join $vars ,]) = (:[join $vars ,:])
-	   where [my id_column] = :revision_id"
-      } else {
-	db_dml main_table_update "
-	   update $table_name set $vars = :$vars
-	   where [my id_column] = :revision_id"
-      }
-    }
-  }
 
-  CrClass ad_instproc edit {
-    form
+
+  CrClass ad_instproc instantiate {
+    -item_id
+    {-revision_id 0}
   } { 
-    Updates an item in the content repository and makes
-    it the live revision. We insert a new revision instead of 
-    changing the current revision.
+    Retrieve either the live revision or a specified revision
+    of a content item with all attributes. 
+    The retrieved attributes are strored in the instance variables in
+    class representing the object_type.
 
-    @param form form-object (instance of <a href='/xotcl/show-object?object=::Generic::Form'>::Generic::Form</a>) from where the values are obtained
+    @param item_id id of the item to be retrieved.
+    @param revision_id revision-id of the item to be retrieved.
   } {
-    my instvar table_name item_id
-    
-    set atts [concat [list item_id revision_id] [[self class] set insert_atts]]
-    catch {eval my instvar $atts}
-
-    set form_vars [list]
-    foreach var [$form form_vars] {lappend form_vars $var [uplevel set $var]}
-    foreach var [$form form_vars] {set $var [uplevel set $var]}
-
-    db_transaction {
-      set revision_id [db_nextval acs_object_id_seq]
-      
-      db_dml revision_add "
-	insert into ${table_name}i ([join $atts ,]) 
-	values (:[join $atts ,:])"
-      
-      db_exec_plsql make_live {
-	select content_item__set_live_revision(:revision_id)
-      }
-      my update_main_table -revision_id $revision_id -form_vars $form_vars
-    }
+    set o [my create ::[expr {$revision_id ? $revision_id : $item_id}]]
+    my fetch_object -object $o -item_id $item_id -revision_id $revision_id
   }
-  
+
   CrClass ad_instproc delete {
     -item_id:required
   } { 
@@ -308,16 +330,24 @@
   CrClass ad_instproc instance_select_query {
     {-select_attributes ""}
     {-order_clause ""}
+    {-where_clause ""}
     {-with_subtypes:boolean true}
     {-count:boolean false}
+    {-folder_id}
   } {
     returns the SQL-query to select the CrItems of the specified object_type
     @select_attributes attributes for the sql query to be retrieved, in addion
-      to ci.item_id acs_objects.object_type
+      to ci.item_id acs_objects.object_type, which are always returned
     @param order_clause clause for ordering the solution set
+    @param where_clause clause for restricting the answer set
+    @param with_subtypes return subtypes as well
+    @param count return the query for counting the solutions
+    @param folder_id parent_id
     @return sql query
   } {
     my instvar object_type_key
+    if {![info exists folder_id]} {my instvar folder_id}
+
     set attributes [list ci.item_id acs_objects.object_type] 
     foreach a $select_attributes {
       if {$a eq "title"} {set a cr.title}
@@ -328,61 +358,233 @@
                '$object_type_key' and tree_right('$object_type_key')" :
 	      "acs_object_types.tree_sortkey = '$object_type_key'"}]
     set attribute_selection [expr {$count ? "count(*)" : [join $attributes ,]}]
+    if {$where_clause ne ""} {
+      set where_clause "and $where_clause"
+    }
     return "select $attribute_selection
     from acs_object_types, acs_objects, cr_items ci, cr_revisions cr 
         where $type_selection
         and acs_object_types.object_type = ci.content_type
-        and ci.live_revision = cr.revision_id and
-        acs_objects.object_id = cr.revision_id $order_clause"
+        and ci.live_revision = cr.revision_id 
+        and parent_id = $folder_id
+        and acs_objects.object_id = cr.revision_id $where_clause $order_clause"
   }
 
+  CrClass ad_instproc instantiate_all {
+    {-select_attributes ""}
+    {-order_clause ""}
+    {-where_clause ""}
+    {-with_subtypes:boolean true}
+    {-folder_id}
+  } {
+    Return all instances of an content type class matching the
+    specified clauses.
+  } {
+    set __result [::xo::OrderedComposite new]
+    uplevel #1 [list $__result volatile]
+    $__result proc destroy {} {my log "-- "; next}
+
+    set __attributes [list] 
+    foreach a [concat [list ci.item_id acs_objects.object_type] \
+		   $select_attributes] {
+      lappend __attributes [lindex [split $a .] end]
+    }
+
+    db_foreach instance_select \
+	[my instance_select_query \
+	     -folder_id $folder_id \
+	     -select_attributes $select_attributes \
+	     -with_subtypes $with_subtypes \
+	     -where_clause $where_clause \
+	     -order_clause $order_clause] {
+	       set __o [$object_type create ${__result}::$item_id]
+	       $__result add $__o
+	       #my log "-- $__result add $__o, $object_type $item_id"
+	       foreach __a $__attributes {$__o set $__a [set $__a]}
+ 	     }
+    return $__result
+  }
+
+
+  Class create Attribute -parameter {attribute_name datatype pretty_name}
+  # create new objects as child of the callers namespace
+  #Attribute proc new args {
+  #  eval next -childof [uplevel namespace current] $args
+  #}
+
+  Class create CrItem 
+
+  CrItem ad_proc instantiate {
+    -item_id
+    {-revision_id 0}
+  } {
+    Instantiate the live revision or the specified revision of an 
+    CrItem. 
+    @return object containing the attributes of the CrItem
+  } { 
+    db_1row get_class "select content_type as object_type from cr_items \
+	where item_id=$item_id"
+    if {![string match ::* $object_type]} {set object_type ::$object_type}
+    set o [$object_type create ::[expr {$revision_id ? $revision_id : $item_id}]]
+    $object_type fetch_object \
+	-item_id $item_id -revision_id $revision_id -object $o
+    #my log "-- fetched $o of type $object_type"
+    return $o
+  }
+  
+
+  CrItem ad_proc delete {
+    -item_id 
+  } {
+    Delete a CrItem in the database
+  } {
+    db_1row get_class_and_folder \
+        "select content_type as object_type from cr_items where item_id = $item_id"
+    $object_type delete -item_id $item_id
+  }
+
+  CrItem ad_proc lookup {
+    -title:required
+    -parent_id:required
+  } {
+    Lookup CR item from  title and folder (parent_id)
+    @return item_id or 0 if not successful
+  } {
+    if {[db_0or1row entry_exists_select "
+	select i.item_id from cr_revisions r, cr_items i 
+	where revision_id = i.live_revision and r.title = :title 
+	and i.parent_id = :parent_id" ]} {
+      #my log "-- found $item_id for $title in folder '$parent_id'"
+      return $item_id
+    }
+    #my log "-- nothing found for $title in folder '$parent_id'"
+    return 0
+  }
+
+  CrItem ad_instproc save {} {
+    Updates an item in the content repository and makes
+    it the live revision. We insert a new revision instead of 
+    changing the current revision.
+  } {
+    set __atts [concat [list item_id revision_id] [[my info class] edit_atts]]
+    eval my instvar $__atts 
+
+    db_transaction {
+      set revision_id [db_nextval acs_object_id_seq]
+      
+      db_dml revision_add "
+	insert into [[my info class] set table_name]i ([join $__atts ,]) 
+	values (:[join $__atts ,:])"
+      
+      db_exec_plsql make_live {
+	select content_item__set_live_revision(:revision_id)
+      }
+    }
+    return $item_id
+  }
+
+  CrItem ad_instproc save_new {} {
+    Insert a new item to the content repository and make
+    it the live revision. 
+  } {
+    set __class [my info class]
+    my instvar parent_id item_id
+
+    set __atts  [list item_id revision_id]
+    foreach __var [$__class edit_atts] {
+      my instvar $__var
+      lappend __atts $__var
+      if {![info exists $__var]} {set $__var ""}
+    }
+
+    db_transaction {
+      $__class instvar mime_type storage_type object_type
+      $__class folder_type -folder_id $parent_id register
+      set item_id [db_exec_plsql note_insert "
+	select content_item__new(:title,$parent_id,null,null,null,null,null,null,
+				 'content_item',:object_type,:title,
+				 :description,:mime_type,
+				 :nls_language,:text,:storage_type)"]
+      
+      set revision_id [db_nextval acs_object_id_seq]
+      my log "-- NEW item_id = $item_id, revision_id = $revision_id"
+      db_dml revision_add "
+	insert into [$__class set table_name]i ([join $__atts ,]) 
+	values (:[join $__atts ,:])"
+      
+      db_exec_plsql make_live {
+	select content_item__set_live_revision(:revision_id)
+      }
+      my log "-- end object_type == $object_type"
+    }
+    return $item_id
+  }
+
+  CrItem ad_instproc delete {} {
+    Delete the item from the content repositiory with the item_id taken from the 
+    instance variable.
+  } {
+    # delegate deletion to the class
+    [my info class] delete [my set instance_id]
+  }
+
   #
   # Form template class
   #
   
   Class Form -parameter {
     fields 
-    object_type
+    data
+    {folder_id -100}
     {name {[namespace tail [self]]}}
     add_page_title
     edit_page_title
+    {validate ""}
     {with_categories false}
+    {submit_link "."}
   } -ad_doc {
     Class for the simplified generation of forms. This class was designed 
     together with the content repository class 
     <a href='/xotcl/show-object?object=::Generic::CrClass'>::Generic::CrClass</a>.
-    This class can be parameterized with
+
     <ul>
     <li><b>fields:</b> form elements as described in 
        <a href='/api-doc/proc-view?proc=ad_form'>ad_form</a>.
-    <li><b>object_type:</b> instance of
-       <a href='/xotcl/show-object?object=::Generic::CrClass'>::Generic::CrClass</a>,
-       used as a data source for this form
+    <li><b>data:</b> data object (e.g. instance if CrItem) 
+    <li><b>folder_id:</b> associated folder id
     <li><b>name:</b> of this form, used for naming the template, 
        defaults to the object name
     <li><b>add_page_title:</b> page title when adding content items
     <li><b>edit_page_title:</b> page title when editing content items
+    <li><b>with_categories:</b> display form with categories (default false)
+    <li><b>submit_link:</b> link for page after submit
     </ul>
   }
   
   Form instproc init {} {
+    set level [template::adp_level]
+    my forward var uplevel #$level set 
+
+    my instvar data folder_id
+    set class     [$data info class]
+    set folder_id [$data set parent_id]
+
     if {![my exists add_page_title]} {
-      my set add_page_title "Add [[my object_type] pretty_name]"
+      my set add_page_title "New [$class pretty_name]"
     }
     if {![my exists edit_page_title]} {
-      my set edit_page_title "Edit [[my object_type] pretty_name]"
+      my set edit_page_title "Edit [$class pretty_name]"
     }
+
     # check, if the specified fields are available from the data source
     # and ignore the unavailable entries
     set checked_fields [list]
-    set available_atts [[my object_type] edit_atts]
-    lappend available_atts [[my object_type] id_column] item_id
-    foreach varspec [my fields] {
-      set var [lindex [split [lindex $varspec 0] :] 0]
-      if {[lsearch -exact $available_atts $var] == -1} continue
-      lappend checked_fields $varspec
-    }
-    my fields $checked_fields
+    set available_atts [$class edit_atts]
+    #my log "-- available atts <$available_atts>"
+    lappend available_atts [$class id_column] item_id
+
+    if {![my exists fields]} {my mkFields}
+    #my log --fields=[my fields]
   }
   
   Form instproc form_vars {} {
@@ -392,13 +594,62 @@
     }
     return $vars
   }
-  Form instproc get_vars {object_type} {
-    foreach var [my form_vars] {
-      uplevel [list set $var [$object_type set $var]]
+  Form instproc new_data {} {
+    my instvar data
+    my log "--- new_data ---"
+    foreach __var [my form_vars] {
+      $data set $__var [my var $__var]
     }
+    $data save_new
+    return [$data set item_id]
   }
+  Form instproc edit_data {} {
+    my log "--- edit_data ---"
+    my instvar data
+    foreach __var [my form_vars] {
+      $data set $__var [my var $__var]
+    }
+    $data save
+    return [$data set item_id]
+  }
+  Form instproc request {privelege} {
+    my instvar page_title context
+    auth::require_login
+    permission::require_permission -object_id [ad_conn package_id] -privilege $privelege
+    set page_title [my add_page_title]
+    set context [list $page_title]
+  }
+  Form instproc new_request {} {
+    my log "--- new_request ---"
+    my request create
+  }
+  Form instproc edit_request {item_id} {
+    my instvar data
+    my log "--- edit_request ---"
+    my request write
+    foreach var [[$data info class] edit_atts] {
+      my var $var [list [$data set $var]]
+    }
+  }
 
-
+  Form instproc on_validation_error {} {
+    my instvar page_title context
+    my log "-- "
+    set page_title [my edit_page_title]
+    set context [list $page_title]
+  }
+  Form instproc after_submit {item_id} {
+    my instvar data
+    my log "-- item_id=$item_id [$data set item_id]"
+    set link [my submit_link]
+    if {$link ne "." && ![string match {*[?]*} $link]} {
+      set link [export_vars -base $link {item_id}]
+    }
+    ns_log notice "-- redirect to $link // [string match *\?* $link]"
+    ad_returnredirect $link
+    ad_script_abort
+  }
+ 
   Form ad_instproc generate {
     {-template "formTemplate"}
   } {
@@ -409,21 +660,31 @@
   } {
     # set form name for adp file
     uplevel set $template [my name]
-    
-    ad_form -name [my name] -form [my fields] \
-	-export [list [list object_type [my object_type]]] 
+    my instvar data folder_id
+    set object_type [[$data info class] object_type]
+    my log "-- $data, cl=[$data info class] [[$data info class] object_type]"
 
-    set new_data [subst -novariables {[my object_type] add [self]}]
-    set edit_data [subst -novariables {[my object_type] edit [self]}]
+    #my log "--final fields [my fields]"
+    ad_form -name [my name] -form [my fields] \
+	-export [list [list object_type $object_type] [list folder_id $folder_id]] 
+    
+    set new_data            "set item_id \[[self] new_data\]"
+    set edit_data           "set item_id \[[self] edit_data\]"
+    set new_request         "[self] new_request"
+    set edit_request        "[self] edit_request \$item_id"
+    set after_submit        "[self] after_submit \$item_id"
+    set on_validation_error "[self] on_validation_error"
     set on_submit {}
 
     if {[my with_categories]} {
-      upvar item_id item_id
+      set coid [expr {[$data exists item_id] ? [$data set item_id] : ""}]
       category::ad_form::add_widgets -form_name [my name] \
 	  -container_object_id [ad_conn package_id] \
-	  -categorized_object_id [value_if_exists item_id]
+	  -categorized_object_id $coid
+
       append new_data {
 	category::map_object -remove_old -object_id $item_id $category_ids
+	ns_log notice "-- new data category::map_object -remove_old -object_id $item_id $category_ids"
 	db_dml insert_asc_named_object \
 	    "insert into acs_named_objects (object_id,object_name,package_id) \
              values (:item_id, :title, :package_id)"
@@ -432,6 +693,7 @@
 	db_dml update_asc_named_object \
 	    "update acs_named_objects set object_name = :title, \
 		package_id = :package_id where object_id = :item_id"
+	ns_log notice "-- edit data category::map_object -remove_old -object_id $item_id $category_ids"
 	category::map_object -remove_old -object_id $item_id $category_ids
       }
       append on_submit {
@@ -440,30 +702,14 @@
       }
     }
 
+    ns_log notice "-- ad_form new_data=<$new_data> edit_data=<$edit_data>"
+    
     # action blocks must be added last
     ad_form -extend -name [my name] \
+	-validate [my validate] \
 	-new_data $new_data -edit_data $edit_data -on_submit $on_submit \
-	-new_request  [subst -novariables {
-	  auth::require_login
-	  permission::require_permission \
-	      -object_id [ad_conn package_id] \
-	      -privilege create
-	  set page_title "[my add_page_title]"
-	  set context \[list $page_title\]
-	}] -edit_request [subst -novariables {
-	  auth::require_login
-	  permission::require_write_permission -object_id $item_id
-	  [my object_type] get -item_id $item_id 
-	  my get_vars [my object_type]
-	  set page_title "[my edit_page_title]"
-	  set context \[list $page_title\]
-	}] -on_validation_error [subst -novariables {
-	  set page_title "[my edit_page_title]"
-	  set context \[list $page_title\]
-	}] -after_submit {
-	  ad_returnredirect "."
-	  ad_script_abort
-	}
+	-new_request $new_request -edit_request $edit_request \
+	-on_validation_error $on_validation_error -after_submit $after_submit
   }
 
   #
@@ -477,7 +723,9 @@
     {with_subtypes true}
     {name {[namespace tail [self]]}}
     {edit_link edit}
+    {view_link view}
     {delete_link delete}
+    {folder_id -100}
   } -ad_doc {
     Class for the simplified generation of lists. This class was designed 
     together with the content repository class 
@@ -500,10 +748,10 @@
        defaults to the object name
     <li><b>edit_link:</b> link to edit content item (default: edit)
     <li><b>delete_link:</b> link to delete content item (default: delete)
+    <li><b>view_link:</b> link to view content item (default: view)
     </ul>
   }
 
-
   List ad_instproc actions {} {
     actions is a method to compute the actions of the list
     depending on the object types. It can be easily overwritten 
@@ -514,7 +762,7 @@
     foreach object_type $object_types {
       lappend actions \
 	  "Add [$object_type pretty_name]" \
-	  [export_vars -base [my edit_link] {object_type}] \
+	  [export_vars -base [my edit_link] {object_type folder_id}] \
 	  "Add a new item of kind [$object_type pretty_name]"
     }
     return $actions
@@ -550,6 +798,17 @@
 	    sub_class narrow
 	  }
 	}
+	VIEW {
+	  lappend elements view {
+	    link_url_col view_url
+	    display_template {
+	      <img src='/resources/acs-subsite/Zoom16.gif' \
+		  title='View Item' alt='view' \
+		  width="16" height="16" border="0">
+	    }
+	    sub_class narrow
+	  }
+	}
 	default {
 	  lappend elements $e $spec
 	}
@@ -579,7 +838,7 @@
     
     set select_attributes [list]
     foreach {e spec} [my fields] {
-      if {[lsearch -exact {item_id object_type EDIT DELETE} $e] == -1} {
+      if {[lsearch -exact {item_id object_type EDIT DELETE VIEW} $e] == -1} {
 	lappend select_attributes $e
       }
     }
@@ -593,12 +852,18 @@
 	-extend {
 	  edit_url
 	  delete_url
+	  view_url
 	} $template instance_select [$object_type instance_select_query \
+  	      -folder_id [my folder_id] \
   	      -select_attributes $select_attributes \
               -with_subtypes $with_subtypes \
   	      -order_clause $order_clause] {
-	set edit_url [export_vars -base [my edit_link] {item_id object_type}]
-	set delete_url [export_vars -base [my delete_link] {item_id object_type}]
+        set view_url [export_vars -base [my view_link] {item_id}]
+	set edit_url [export_vars -base [my edit_link] {item_id}]
+	set delete_url [export_vars -base [my delete_link] {item_id}]
       }
   }
+
+  namespace export CrItem
 }
+namespace import -force ::Generic::*
Index: openacs-4/packages/xotcl-core/tcl/html-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/html-procs.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/html-procs.tcl	14 Dec 2005 15:57:53 -0000	1.1
@@ -0,0 +1,138 @@
+package require tdom
+
+proc require_html_procs {} {
+  if {[info command ::html::a] eq ""} { 
+    namespace eval ::html {
+
+      # Declare Tcl commands for building HTML elements. This is an complete 
+      # set taken from W3C on http://www.w3.org/TR/html4/index/elements.html
+      #
+
+      #
+      # Miscelaneous commands. Not part of html specs
+      # but needed for generation of special dom nodes.
+      #
+
+      dom createNodeCmd cdataNode   cdata
+      dom createNodeCmd textNode    t
+      dom createNodeCmd commentNode c
+      dom createNodeCmd parserNode  x
+      dom createNodeCmd piNode      runtime
+
+      #
+      # Command generating HTML tags. All these commands have
+      # following sytax: <cmd> ?-option value ...? ?script?
+      #
+      #    -option   name of HTML attribute
+      #     value    attribute value
+      #     script   tcl script to run in command's context.
+      #
+      # Example: table -border 1 {...}
+      #
+
+      dom createNodeCmd elementNode a
+      dom createNodeCmd elementNode abbr
+      dom createNodeCmd elementNode acronym
+      dom createNodeCmd elementNode address
+      dom createNodeCmd elementNode applet
+      dom createNodeCmd elementNode area
+      dom createNodeCmd elementNode b
+      dom createNodeCmd elementNode base
+      dom createNodeCmd elementNode basefont
+      dom createNodeCmd elementNode bdo
+      dom createNodeCmd elementNode big
+      dom createNodeCmd elementNode blockquote
+      dom createNodeCmd elementNode body
+      dom createNodeCmd elementNode br
+      dom createNodeCmd elementNode button
+      dom createNodeCmd elementNode caption
+      dom createNodeCmd elementNode center
+      dom createNodeCmd elementNode cite
+      dom createNodeCmd elementNode code
+      dom createNodeCmd elementNode col
+      dom createNodeCmd elementNode colgroup
+      dom createNodeCmd elementNode dd
+      dom createNodeCmd elementNode del
+      dom createNodeCmd elementNode dfn
+      dom createNodeCmd elementNode dir
+      dom createNodeCmd elementNode div
+      dom createNodeCmd elementNode dl
+      dom createNodeCmd elementNode dt
+      dom createNodeCmd elementNode em
+      dom createNodeCmd elementNode fieldset
+      dom createNodeCmd elementNode font
+      dom createNodeCmd elementNode form
+      dom createNodeCmd elementNode frame
+      dom createNodeCmd elementNode frameset
+      dom createNodeCmd elementNode h1
+      dom createNodeCmd elementNode h2 
+      dom createNodeCmd elementNode h3 
+      dom createNodeCmd elementNode h4 
+      dom createNodeCmd elementNode h5 
+      dom createNodeCmd elementNode h6
+      dom createNodeCmd elementNode head
+      dom createNodeCmd elementNode hr
+      dom createNodeCmd elementNode html
+      dom createNodeCmd elementNode i
+      dom createNodeCmd elementNode iframe
+      dom createNodeCmd elementNode img
+      dom createNodeCmd elementNode input
+      dom createNodeCmd elementNode ins
+      dom createNodeCmd elementNode isindex
+      dom createNodeCmd elementNode kbd
+      dom createNodeCmd elementNode label
+      dom createNodeCmd elementNode legend
+      dom createNodeCmd elementNode li
+      dom createNodeCmd elementNode link
+      dom createNodeCmd elementNode map
+      dom createNodeCmd elementNode menu
+      dom createNodeCmd elementNode meta 
+      dom createNodeCmd elementNode noframes
+      dom createNodeCmd elementNode noscript
+      dom createNodeCmd elementNode object 
+      dom createNodeCmd elementNode ol
+      dom createNodeCmd elementNode optgroup
+      dom createNodeCmd elementNode option
+      dom createNodeCmd elementNode p
+      dom createNodeCmd elementNode param
+      dom createNodeCmd elementNode pre
+      dom createNodeCmd elementNode q
+      dom createNodeCmd elementNode s 
+      dom createNodeCmd elementNode samp
+      dom createNodeCmd elementNode script
+      dom createNodeCmd elementNode select
+      dom createNodeCmd elementNode small
+      dom createNodeCmd elementNode span
+      dom createNodeCmd elementNode strike
+      dom createNodeCmd elementNode strong
+      dom createNodeCmd elementNode style
+      dom createNodeCmd elementNode sub
+      dom createNodeCmd elementNode sup
+      dom createNodeCmd elementNode table
+      dom createNodeCmd elementNode tbody
+      dom createNodeCmd elementNode td
+      dom createNodeCmd elementNode textarea
+      dom createNodeCmd elementNode tfoot
+      dom createNodeCmd elementNode th
+      dom createNodeCmd elementNode thead
+      dom createNodeCmd elementNode title
+      dom createNodeCmd elementNode tr
+      dom createNodeCmd elementNode tt
+      dom createNodeCmd elementNode u
+      dom createNodeCmd elementNode ul
+      dom createNodeCmd elementNode var
+
+
+    }
+
+    namespace eval ::tmpl {
+      dom createNodeCmd -returnNodeCmd elementNode div
+      dom createNodeCmd -returnNodeCmd elementNode body
+    }
+
+    namespace eval :: {
+      namespace import -force ::html::*
+      namespace import -force ::tmpl::*
+    }
+  }
+}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/thread_mod-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/thread_mod-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/tcl/thread_mod-procs.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/tcl/thread_mod-procs.tcl	14 Dec 2005 15:55:29 -0000	1.2
@@ -123,12 +123,13 @@
       "set ::xotcl::currentThread [self]" \n\
       $cmd 
   my set mutex [thread::mutex create]
+  ns_log notice "mutex [my set mutex] created"
   next
 }
 
-::xotcl::THREAD ad_proc recreate {obj args} {
-  # this method catches recreation of THREADs in worker threads 
-  # it reinitializes the thread according to the new definition.
+::xotcl::THREAD ad_proc -private recreate {obj args} {
+  this method catches recreation of THREADs in worker threads 
+  it reinitializes the thread according to the new definition.
 } {
   my log "recreating [self] $obj, tid [$obj exists tid]"
   if {![string match ::* $obj]} { set obj ::$obj }
@@ -153,12 +154,25 @@
     if {$refcount == 0} {
       my log "thread terminated"
       nsv_unset [self class] [self]
+      thread::mutex destroy [my set mutex]
+      ns_log notice "mutex [my set mutex] destroyed"
     }
   }
-  thread::mutex destroy [my set mutex]
   next
 }
-::xotcl::THREAD instproc do {o args} {
+
+::xotcl::THREAD instproc get_tid {} {
+  if {[nsv_exists [self class] [self]]} {
+    # the thread was already started
+    return [nsv_get [self class] [self]]
+  }
+  # start a small command in the thread
+  my do info exists x
+  # now we have the thread and can return the tid
+  return [my set tid]
+}
+
+::xotcl::THREAD instproc do {-async:switch args} {
   if {![nsv_exists [self class] [self]]} {
     # lazy creation of a new slave thread
 
@@ -193,8 +207,12 @@
     }
     my set tid $tid
   }
-  #my log "calling [self class] ($tid, [pid]) $o $args"
-  return [thread::send $tid "$o $args"]
+  #my log "calling [self class] ($tid, [pid]) $args"
+  if {$async} {
+    return [thread::send -async $tid $args]
+  } else {
+    return [thread::send $tid $args]
+  }
 }
 
 # create a sample persistent thread that can be acessed 
@@ -209,37 +227,35 @@
 #
 
 ################## forwarding  proxy ##################
-Class ::xotcl::THREAD::Proxy -parameter {attach} 
-::xotcl::THREAD::Proxy configure \
-    -instproc forward args {
-      set cp [self calledproc]
-      if { [string equal $cp attach] 
-	   || [string equal $cp filter] 
-	   || [string equal $cp detachAll]} {
-	next
-      } elseif {[string equal $cp destroy]} {
-	eval [my attach] do [self] $cp $args
-	my log "destroy"
-	next
-      } else {
-	my log "forwarding [my attach] do [self] $cp $args"
-	eval [my attach] do [self] $cp $args
-      }
-    } -instproc init args {
-      my filter forward
-    } -proc detachAll {} {
-      foreach i [my info instances] {$i filter ""}
-    }
-# the following does not work yet
-#::xotcl::THREAD::Proxy proc create {obj args} {
-#  my log "[self proc] $obj"
-#  my filter ""
-#  next
-#}
+# Class ::xotcl::THREAD::Proxy -parameter {attach} 
+# ::xotcl::THREAD::Proxy configure \
+#     -instproc forward args {
+#       set cp [self calledproc]
+#       if { [string equal $cp attach] 
+# 	   || [string equal $cp filter] 
+# 	   || [string equal $cp detachAll]} {
+# 	next
+#       } elseif {[string equal $cp destroy]} {
+# 	eval [my attach] do [self] $cp $args
+# 	my log "destroy"
+# 	next
+#       } else {
+# 	my log "forwarding [my attach] do [self] $cp $args"
+# 	eval [my attach] do [self] $cp $args
+#       }
+#     } -instproc init args {
+#       my filter forward
+#     } -proc detachAll {} {
+#       foreach i [my info instances] {$i filter ""}
+#     }
 
+
 # sample Thread client routine, calls a same named object in the server thread
-Class create ::xotcl::THREAD::Client -parameter server
+# a thread client should be created in an connection thread dynamically to 
+# avoid name clashes in the blueprint.
+ 
+Class create ::xotcl::THREAD::Client -parameter {server {serverobj [self]}}
 ::xotcl::THREAD::Client instproc do args {
-  eval [my server] do [self] $args
+  eval [my server] do [my serverobj] $args
 }
 
Index: openacs-4/packages/xotcl-core/www/show-object.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/www/show-object.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/xotcl-core/www/show-object.tcl	11 Oct 2005 08:41:18 -0000	1.1
+++ openacs-4/packages/xotcl-core/www/show-object.tcl	14 Dec 2005 15:55:30 -0000	1.2
@@ -138,20 +138,32 @@
   append output [::xotcl::api source_to_html $obj_create_source] \n
 }
 
+proc api_src_doc {out show_source scope object proc m} {
+  set output "<a name='$proc-$m'></a><li>$out"
+  if { $show_source } { 
+    append output \
+	"<pre class='code'>" \
+	[api_tcl_to_html [::xotcl::api proc_index $scope $object $proc $m]] \
+	</pre>
+  }
+  return $output
+}
+
 if {$show_methods} {
   append output "<h3>Methods</h3>\n" <ul> \n
-   foreach m [lsort [DO $object info procs]] {
+  foreach m [lsort [DO $object info procs]] {
     set out [api_documentation $scope $object proc $m]
     if {$out ne ""} {
-      append output "<a name='proc-$m'></a><li>$out"
-      if { $show_source } { 
-	append output \
-	    "<pre class='code'>" \
-	    [api_tcl_to_html [::xotcl::api proc_index $scope $object proc $m]] \
-	    </pre>
-      }
+      append output [api_src_doc $out $show_source $scope $object proc $m]
     }
   }
+  foreach m [lsort [DO $object info forward]] {
+    set out [api_documentation $scope $object forward $m]
+    if {$out ne ""} {
+      append output [api_src_doc $out $show_source $scope $object forward $m]
+    }
+  }
+
   if {$isclass} {
     set cls [lsort [DO $object info instprocs]]
     foreach m $cls {