Plasma GitLab Archive
Projects Blog Knowledge

(*
 * <COPYRIGHT>
 * Copyright 2002 Joachim Schrod Network and Publication Consultance GmbH, Gerd Stolpmann
 *
 * <GPL>
 * This file is part of WDialog.
 *
 * WDialog is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * WDialog is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WDialog; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * </>
 *)

(* $Id: wd_types.ml,v 3.9 2005-06-11 14:24:14 stolpmann Exp $
 * ----------------------------------------------------------------------
 *
 *)

type (+'a) dict = 'a Wd_dictionary.t

type event =
    Button of string
  | Image_button of (string * int * int)
  | Indexed_button of (string * string)
  | Indexed_image_button of (string * string * int * int)
  | No_event
  | Popup_request of string

(* event:
 * Button n: The button with name n has been pressed
 *   (<ui:button name="n" ...>)
 * Image_button (n,x,y): The image button with name n has been pressed
 *   at the coordinates (x,y). (<ui:imagebutton name="n" ...>)
 * Indexed_button (n,i): The button with name n and index i has been pressed
 *   (<ui:button name="n" index="i" ...>)
 * Indexed_image_button (n,i,x,y): The image button with name n and index i
 *   has been pressed at the coordinates (x,y).
 *   (<ui:imagebutton name="n" index="i" ...)
 * No_event: This value indicates that there was no event (or no
 *   recognized event)
 * Popup_request s: A server popup window has just popped up, and the contents
 *   for the window have been requested. The argument is the second argument
 *   of the "open" function.
 *)


type interactors =
    { mutable ui_buttons :             string option Wd_interactor.t;
      mutable ui_imagebuttons :        string option Wd_interactor.t;
      mutable ui_anchors :             string option Wd_interactor.t;
      mutable ui_indexed_buttons :     string option Wd_interactor.t;
      mutable ui_indexed_imagebuttons :string option Wd_interactor.t;
      mutable ui_indexed_anchors :     string option Wd_interactor.t;
      mutable ui_vars :                unit Wd_interactor.t;
      mutable ui_enumvars :            (string * string option * string) list;
      mutable ui_uploads :             unit Wd_interactor.t;
    }
    (* Values of this type store the mapping from the (name,index) pairs
     * of interactor elements to the real CGI parameter names together
     * with an auxiliary component.
     *
     * What's the problem? Interactor elements like ui:a allow the programmer
     * to identify these either by a single name (which is an arbitrary
     * string) or by a pair of a "name" and an "index" (i.e. two arbitrary
     * strings). In contrast to this, CGI parameter names are much more
     * restricted. First, these names are only strings; there is no
     * built-in representation for pairs of strings. Second, you cannot
     * use arbitrary characters within these names because of limitations
     * of the transport protocol and because of bugs in browsers. (As
     * the "multipart/form-data" representation used in the transport
     * protocol bases on the RFC 822 mail format, it is neither possible to
     * pass 8 bit values, nor to pass control characters. A known bug
     * in Netscape browsers is that the double-quote and backslash characters
     * are incorrectly represented.)
     *
     * The solution is to generate the CGI parameter names using only
     * unproblematic characters, and to keep the mapping of the original
     * string or string * string to the generated CGI name. This record
     * stores the mappings for the various namespaces. The mapping is
     * encapsulated in the Wd_interactor module, and the type
     * 'a Wd_interactor.t (where 'a is arbitrary) represents such a mapping. The
     * CGI names are simply enumerated, and the Wd_interactor.t value stores only
     * the numbers (IDs) of the CGI parameters. The complete CGI name is formed
     * using a prefix and the number stored in Wd_interactor.t. For example,
     * ui:buttons without index have the prefix "button_"; and if the
     * ui_button record component contains entries for the IDs 0, 1, and 2,
     * the complete CGI names are "button_0", "button_1", and "button_2",
     * respectively.
     *
     * The type parameter 'a of 'a Wd_interactor.t is the type of the
     * auxiliary component stored with every entry. See below for the
     * meanings in every case.
     *
     * The Wd_interactor.t structure always maps from pairs string * string to
     * numerical IDs. Because of this, there are usually two mappings, one
     * for the (name,index) PAIRS, and one for the simple names. The record
     * components listed below that have a name with "indexed" are responsible
     * for the pairs, the corresponding component without "indexed" stores
     * the mapping for the simple case.
     *
     * The simple case is represented as Wd_interactor.t by using always the
     * empty string "" as index.
     *
     * THE COMPONENTS ARE:
     *
     * (A) BUTTON-TYPE INTERACTORS:
     *
     * ui_buttons:              Enumerates the ui:button interactors
     *                          that have only a name, not an index.
     *                          CGI prefix: "button_".
     * ui_indexed_buttons:      Enumerates the ui:button interactors
     *                          that have both a name and an index.
     *                          CGI prefix: "xbutton_".
     * ui_imagebuttons:         Enumerates the ui:imagebutton interactors
     *                          that have only a name, not an index.
     *                          CGI prefix: "imagebutton_".
     * ui_indexed_imagebuttons: Enumerates the ui:imagebutton interactors
     *                          that have both a name and an index.
     *                          CGI prefix: "ximagebutton_".
     * ui_anchors:              Enumerates the ui:a interactors
     *                          that have only a name, not an index.
     *                          CGI prefix: "anchor_".
     * ui_indexed_anchors:      Enumerates the ui:a interactors
     *                          that have both a name and an index.
     *                          CGI prefix: "xanchor_".
     *
     * These components use the auxiliary component to store the "goto"
     * attribute of the interactor, if present.
     *
     * (B) BOX-LIKE INTERACTORS:
     *
     * ui_vars:                 Enumerates the interactors that are bound
     *                          to an object variable (i.e. they have a
     *                          "variable" attribute, like ui:text).
     *                          As variables allow either only non-indexed
     *                          names or only indexed names, this component
     *                          contains both interactors identified by a simple
     *                          string name and interactors identified by
     *                          (name,index) pairs; it is not possible that
     *                          there are conflicts between the two naming
     *                          methods.
     *                          CGI prefix: "var_".
     *                          This component does not have an auxiliary
     *                          component.
     *
     * ui_enumvars:             This list enumerates the simple names
     *                          (name, None, pg) or pairs (name, Some index, pg)
     *                          that occur in checkbox, radiobutton and select
     *                          list interactors. pg is the name of the page
     *                          where the interactor occurs (knowing the page
     *                          is necessary for popup dialogues).
     *
     * ui_uploads:              Enumerates the ui:file interactors. These
     *                          may only have a simple name.
     *                          CGI prefix: "upload_".
     *                          This component does not have an auxiliary
     *                          component.
     *)


type 'dlg poly_var_value =
    String_value   of string
  | Enum_value     of string list
  | Dialog_value   of 'dlg option
  | Dyn_enum_value of (string * string) list
  | Alist_value    of (string * 'dlg poly_var_value) list

(* (poly_)var_value is the type of instance variables of uiobjects. There are
 * six possibilities for var_values:
 * - String_value s: The instance variable contains the string s
 * - Enum_value [x1;x2;...]: The instance variable contains an enumerator
 *   value with the internal items x1, x2, etc. (As variables are declared
 *   it is known which items are possible, and whether there are corresponding
 *   external values.)
 * - Dialog_value None: The instance variable does not contain a dialog.
 * - Dialog_value (Some obj): The variable contains the dialog obj.
 * - Dyn_enum_value [(x1,y1);(x2,y2);...]: The variable contains the enumerator
 *   with internal items x1, x2,... and the corresponding external values
 *   y1, y2, ...
 * - Alist_value [(i1,v1); (i2,v2); ...]: The variable contains the associative
 *   list where the index i1 is mapped to the value v1, i2 is mapped to v2 etc.
 *
 * See also [var_value] below.
 *)


type enum_decl =
    { enum_name : string;
      mutable (* XXX *) enum_definition : (string * string) list;
    }


type var_type_name =
    String_type
  | Enum_type of enum_decl
  | Dialog_type
  | Dyn_enum_type


type 'dlg poly_var_decl =
    { var_name : string;
      var_type : var_type_name;
      var_default : 'dlg poly_var_value option;
      var_temporary : bool;
      var_associative : bool;
      var_protected : bool;
    }


type response_header =
    { mutable rh_status : Nethttp.http_status;
      mutable rh_content_type : string;
      mutable rh_cache : Netcgi_common.cache_control;
      mutable rh_filename : string option;
      mutable rh_language : string option;
      mutable rh_script_type : string option;
      mutable rh_style_type : string option;
      mutable rh_set_cookie : Nethttp.cookie list;
      mutable rh_fields : (string * string list) list;
    }

type debug_mode_style =
  [ `Fully_encoded
  | `Partially_encoded
  ]

type environment =
    { (* Overall way of operation: *)
      debug_mode : bool;
      debug_mode_style : debug_mode_style;
      prototype_mode : bool;
      server_popup_mode : bool;
      (* Web variables *)
      self_url : string;
      response_header : response_header;
      cgi : Netcgi.cgi_activation;
    }


type trans_vars =
    { mutable within_popup : bool;
      mutable current_page : string;
      mutable popup_env_initialized : bool;
      mutable condition_code : bool;
              (* last result of <ui:if>, <ui:ifvar>, <ui:iflang> *)
      mutable serialize_session : unit -> string;
    }
    (* Some local variables that are used in the recursive transformation.
     * By putting them all into a record it is simpler to pass them to the
     * subsequent transformers.
     *)


type ('universe,'dialog,'environment) poly_ds_buf = 
    ('universe,'dialog,'environment) Wd_serialize_types.poly_ds_buf =
    { ds_str : string;         (* String to deserialize *)
      mutable ds_pos : int;    (* Current position *)
      ds_end : int;            (* End position *)
      ds_universe : 'universe;
      ds_environment : 'environment;
      ds_dialogs : (int, 'dialog) Hashtbl.t;   
         (* maps dialog IDs to dialogs *)
    }


class type dialog_decl_type =
  object ('self)
    (* PUBLIC *)
    method name : string
    method enumeration : string -> enum_decl
    method variable_names : string list
    method variable : string -> dialog_type poly_var_decl
    method page_names : string list
    method page : string -> syntax_tree_type
    method page_is_declared_as_popup : string -> bool
    method start_page : string
    method default_context : syntax_tree_type dict
    method language_variable : string option
    (* RESTRICTED *)
    method set_name : string -> unit
    method set_start_page : string -> unit
    method add_enumeration : enum_decl -> unit
    method add_variable : dialog_type poly_var_decl -> unit
    method add_page : string -> syntax_tree_type -> unit
    method set_default_context : syntax_tree_type dict -> unit
    method set_language_variable : string -> unit
  end

and virtual dialog_type =
  object ('self)
    method copy : dialog_type
      (* return a copy of the dialog *)
    method name : string
      (* return the name of the dialog *)
    method page_name : string
      (* return the name of the current page *)
    method page_names : string list
      (* returns the names of all defined pages of this dialog *)
    method variable : string -> dialog_type poly_var_value
      (* variable n: Get the variable with name n, or raise No_such_variable *)
    method variable_decl : string -> dialog_type poly_var_decl
    method string_variable : string -> string
      (* string_variable n: Get the contents of the string variable n.
       * Raise No_such_variable if the variable does not exist. Runtime_error
       * if the variable is not a string.
       *)
    method enum_variable : string -> string list
      (* enum_variable n: Get the contents of the enumerator variable n.
       * The enumerator must have been declared. The returned list contains
       * only the external values.
       * Raise No_such_variable if the variable does not exist. Runtime_error
       * if the variable is not a declared enumerator.
       *)
    method dyn_enum_variable : string -> (string * string) list
      (* dyn_enum_variable n: Get the contents of the enumerator variable n.
       * The enumerator may be dynamic or may be declared. The returned
       * list contains both the internal and the external values.
       * Raise No_such_variable if the variable does not exist. Runtime_error
       * if the variable is not an enumerator.
       *)
    method dialog_variable : string -> dialog_type option
      (* dialog_variable n: Get the contents of the dialog variable n.
       * Raise No_such_variable if the variable does not exist.
       * Runtime_error if the variable is not a dialog.
       *)
    method alist_variable : string -> (string * dialog_type poly_var_value) list
      (* alist_variable n: Get the contents of the associative variable n.
       * Raise No_such_variable if the variable does not exist.
       * Runtime_error if the variable is not an alist.
       *)
    method lookup_string_variable : string -> string -> string
    method lookup_enum_variable : string -> string -> string list
    method lookup_dyn_enum_variable : string -> string -> (string * string) list
    method lookup_dialog_variable : string -> string -> dialog_type option
      (* lookup_*_variable n x: Get the contents of the associative
       * variable n at index x.
       * No_such_variable if the variable does not exist.
       * Not_found if the variable is undefined at x.
       * Runtime_error if the variable has the wrong type.
       *)
    method set_variable : string -> dialog_type poly_var_value -> unit
      (* set_variable n v: Sets the variable n to the value v. The value v
       * must be compatible to the declared type of the variable.
       * No_such_variable if the variable does not exist.
       * Runtime_error if the variable is not compatible.
       *)
    method unset_variable : string -> unit
      (* unset_variable n: Sets the variable n to the declared default
       * value.
       * If the default is not declared, the following default values apply:
       * For strings: the default is the empty string.
       * For enumerators: the default is the empty list.
       * For dialogs: the default is that the value does not exist.
       *)
    method lookup_uploaded_file : string -> Netcgi.cgi_argument option
      (* lookup_uploaded_file name:
       * Checks whether the file upload box 'name' was used. If so,
       * 'Some arg', where 'arg' is the transporting CGI argument is returned.
       * If the box was not used, but the box exists, None is returned.
       * Raises a Runtime_error if the named box does not exist.
       *
       * IMPORTANT NOTE: Uploaded files are not persistent. This means that
       * they are only existent in the 'handle' phase, not during initialization
       * nor the 'prepare_page' phase. You get a failure
       * "Upload.get: not initialized" if you try to access uploaded files
       * in the wrong moment.
       *)
    method dump : Format.formatter -> unit
	(* dump f: output a textual description of the current state into
	 * formatter f.
	 *)
    method next_page : string
      (* Returns the name of the designated next page. *)
    method set_next_page : string -> unit
      (* Sets the name of the designated next page *)
    method event : event
      (* returns the event that just has happened *)
    method is_server_popup_request : bool
      (* Returns whether someone invoked set_server_popup_request before.
       * This is usually done if an dialog is restored for a server-driven
       * popup window (tag ui:server-popup).
       *)
    method serialize : (dialog_type,unit) Hashtbl.t -> Buffer.t -> unit
      (* Returns the state of this dialog as string *)
    method unserialize : (universe_type,dialog_type,environment) poly_ds_buf -> unit
      (* Sets the state of this dialog from the string which must be a
       * previously serialized dialog.
       *)

    method enter_session_scope : session_type -> unit
    method leave_session_scope : unit -> unit
    method session : session_type

    method environment : environment
    method declaration : dialog_decl_type
    method application : application_type
    method universe : universe_type

    (*********************************************************************)

    (* The following methods needs to be defined in subclasses: *)

    method virtual prepare_page : unit -> unit
      (* This method is invoked just before a new output page is generated.
       *
       * PRECONDITIONS:
       * The method 'page_name' returns the name of this page.
       * The method 'event' still returns the action last happened, but
       * the name of the page where this action happened is lost. It may
       * be interesting whether the last event was 'No_event' because this
       * indicates that the page is initially entered.
       *
       * This method should set any variables which are necessary to
       * generate the new page (mostly variable containing HTML fragments).
       * Furthermore, any state that needs to be saved should be put into
       * variables, too.
       *)
    method virtual handle : unit -> unit
      (* This method is invoked just after the user triggered an event (e.g.
       * pressed a button).
       *
       * PRECONDITIONS:
       * The method 'page_name' returns the name of the page that was visible
       * while the event was triggered.
       * The method 'event' returns the description of the event.
       *
       * POSTCONDITIONS:
       * The method may set the next page to display by invoking
       * 'set_next_page'; if it does not then the default will be used.
       * The default is either specified by the XML element describing
       * the interactor that triggered the event, or the default is
       * otherwise this page again.
       *
       * This method should modify the variables according to the event
       * that happened, and optionally set the next page to display.
       *
       * There is also an alternate way to go to another page: raising
       * the exception Change_page.
       *
       * By raising the exception Change_dialog this method may force to go to
       * another dialog.
       *)

    (*********************************************************************)

    (* Internal methods *)
    method set_event : event -> unit
      (* set_event e: Sets the current event to e. *)
    method set_server_popup_request : unit -> unit
      (* Sets that this dialog is restored for a server popup window *)
    method init : string -> unit
      (* MOSTLY INTERNAL USE:
       * init p: re-initializes the dialog in order to go to page p.
       *)
    method interactors : interactors
      (* ONLY INTERNAL USE *)

    (* -- class [dialog] also has a private method:
     * method private put_tree : string -> Template.tree -> unit
     *)

  end

and application_type =
  object ('self)
    (* PUBLIC *)
    method start_dialog_name : string
    method dialog_names : string list
    method dialog_declaration : string -> dialog_decl_type
    method template_names : string list
    method template : string -> template_type
    method study : unit -> unit
    method output_encoding : string -> (string -> string)
    method var_function : 
             string -> 
               ( dialog_type -> 
		 dialog_type poly_var_value list -> 
		   dialog_type poly_var_value)
    method lazy_var_function : 
             string -> 
               ( dialog_type -> 
		 dialog_type poly_var_value Lazy.t list -> 
		   dialog_type poly_var_value)
    method dtd : Pxp_dtd.dtd
    method charset : Pxp_types.rep_encoding
    method debug_mode : bool
    method debug_mode_style : debug_mode_style
    method prototype_mode : bool
    method onstartup_call_handle : bool
    method add_var_function : 
             string -> 
	     ( dialog_type ->
	       dialog_type poly_var_value list -> 
		 dialog_type poly_var_value) ->
	       unit
    method add_lazy_var_function : 
             string -> 
	     ( dialog_type -> 
	       dialog_type poly_var_value Lazy.t list -> 
		 dialog_type poly_var_value) ->
	       unit
    (* RESTRICTED *)
    method set_start_dialog_name : string -> unit
    method add_dialog_declaration : dialog_decl_type -> unit
    method add_template : ?lib:bool -> string -> template_type -> unit
    method add_output_encoding : string -> (string -> string) -> unit
    method set_debug_mode : bool -> debug_mode_style -> unit
    method set_prototype_mode : bool -> unit
    method set_onstartup_call_handle : bool -> unit
  end

and template_type =
  object
    method study : application_type -> unit
    method instantiate :
             ?context: syntax_tree_type dict ->
	     ?vars: trans_vars ->
             ?params:  syntax_tree_type dict ->
             dialog_type ->
               syntax_tree_type
      (* Note: Raises Instantiation_error if something goes wrong *)
  end

and syntax_tree_type =
  object ('self)
    (* PXP *)
    inherit [syntax_tree_type Pxp_document.node] Pxp_document.extension
    (* TEMPLATES *)
    inherit template_type
    (* SCANNERS *)
    (* The side-effect of the scanners is to put the result into the passed
     * argument.
     *)
    method scan_application : application_type -> unit
    method scan_dialog : application_type -> dialog_decl_type -> unit
    method scan_enumeration : enum_decl -> unit
    (* This one is functional: *)
    method scan_literal : unit -> dialog_type poly_var_value
    (* ACCESS *)
    method escaped_data : string
    (* OUTPUT *)
    method to_html :
      ?context: syntax_tree_type dict ->
      ?vars:    trans_vars ->
      dialog_type ->
      Netchannels.out_obj_channel ->
	unit
    (* TODO: to_xhtml *)
    method to_text :
      ?context: syntax_tree_type dict ->
      ?vars:    trans_vars ->
      dialog_type ->
      Netchannels.out_obj_channel ->
	unit
  end

and universe_type =
  object ('self)
    method application : application_type
    method register : string -> (universe_type -> string -> environment -> dialog_type) -> unit
    method create : environment -> string -> dialog_type
  end

and session_manager_type =
  object
    method create : dialog_type -> session_type
    method unserialize : universe_type -> environment -> string -> session_type
  end

and session_type =
object
    method session_id : string
    method dialog_name : string
    method dialog : dialog_type
      (* Returns the dialog *)
    method commit_changes : unit -> unit
      (* Causes that [serialize] returns the current state of the dialog *)
    method serialize : string
      (* Returns the state of the dialog at the time of the last [commit_change]
       * or the state of the initial dialog
       *)
    method change_dialog : dialog_type -> unit
      (* Continue with a new dialog. The methods [dialog_name] and [dialog] will
       * immediately reflect the change. However, you have to call [commit_changes]
       * to make [serialize] return the state of the new dialog.
       *)
  end


type var_value = dialog_type poly_var_value
type var_decl  = dialog_type poly_var_decl
type ds_buf = (universe_type,dialog_type,environment) poly_ds_buf

exception Change_dialog of dialog_type
  (* The implementation of the 'handle' method of a dialog may raise
   * Change_dialog to drop the current dialog and continue with another
   * dialog.
   *)

exception Change_page of string
  (* The implementation of the 'handle' method of a dialog  may raise
   * Change_page to set the next page to display for the current dialog.
   *)

exception Formal_user_error of string
exception Runtime_error of string
exception No_such_variable of string

exception Instantiation_error of string
  (* An error generated by the [instantiate] method. The caller should
   * catch this exception and report the error from its own view
   *)

let revision_types = "$Revision: 3.9 $" ;;
  (* Intentionally the CVS revision string! *)

(* ======================================================================
 * History:
 *
 * $Log: wd_types.ml,v $
 * Revision 3.9  2005-06-11 14:24:14  stolpmann
 * Extension of bracket expressions: many new functions.
 * Functions in bracket expressions may now lazily evaluate their arguments.
 * ui:if and ui:ifvar may refer to any functions defined for bracket
 * expressions.
 * New: ui:ifexpr
 * Parsing of bracket expressions is now done with ulex. Private interfaces
 * of PXP are no longer used for this purpose.
 * Serialization has been rewritten, and it is now safe.
 * Fix: In ui:context there may now be macro references at any location.
 * Also documented all these changes.
 *
 * Revision 3.8  2004/12/12 17:57:32  stolpmann
 * 	Added <q:wd-link> and <q:wd-xlink> to generate links for
 * applications that cannot use Javascript. Limited functionality, however.
 * See stdlib.xml for details.
 *
 * Revision 3.7  2003/02/16 23:48:15  stolpmann
 * 	Improved wd-debug-mode: there are now two styles
 *
 * Revision 3.6  2003/01/04 21:55:25  stolpmann
 * 	new record response_header
 *
 * Revision 3.5  2002/11/09 11:41:19  stolpmann
 * 	Fix: ui:select accepts dot notation. A new method
 * variable_decl needs to be defined for dialogs. This method
 * returns the var_decl record and interprets the dot notation.
 *
 * Revision 3.4  2002/10/20 19:39:17  stolpmann
 * 	New feature: The brackets $[...] can contain expressions,
 * not only variables
 *
 * Revision 3.3  2002/04/10 20:04:05  stolpmann
 * 	The CVS revision number is exported.
 *
 * Revision 3.2  2002/02/14 16:15:21  stolpmann
 * 	Added copyright notice.
 *
 * Revision 3.1  2002/02/12 20:29:21  stolpmann
 * 	Initial release at sourceforge.
 *
 * Revision 2.9  2002/02/11 11:14:21  gerd
 * 	Fix: It is now possible to change the dialog of sessions (required
 * for the Change_dialog exception)
 *
 * Revision 2.8  2002/02/07 18:49:59  gerd
 * 	Standard library
 *
 * Revision 2.7  2002/02/05 18:43:04  gerd
 * 	New: var_protected
 * 	New: page_is_declared_as_popup
 * 	New: debug_mode, prototype_mode, onstartup_call_handle
 * 	New: Session management
 *
 * Revision 2.6  2002/01/31 23:06:40  gerd
 * 	Revised conditional expansion (ui:if, ui:ifvar, ui:iflang,
 * ui:cond).
 * 	Added some support for internationalization (xml:lang).
 *
 * Revision 2.5  2002/01/30 15:16:10  gerd
 * 	New: charset
 * 	New argument application_type for [study]
 * 	New argument application_type for [scan_dialog]
 *
 * Revision 2.4  2002/01/28 02:12:54  gerd
 * 	Added support for output encodings.
 *
 * Revision 2.3  2002/01/26 22:38:27  gerd
 * 	Changed the type for passing parameters to templates. It is
 * now syntax_tree dict instead of a simple list. Furthermore, the
 * method [instantiate] no longer returns the new context. The new element
 * ui:context creates the new contexts now.
 *
 * Revision 2.2  2002/01/24 23:35:18  gerd
 * 	New exception: [Instantiation_error]
 *
 * Revision 2.1  2002/01/21 14:29:04  gerd
 * 	Initial revision.
 *
 *
 *)

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml