-------------------------------------------------------------------------------
--
--  This file is part of AdaBrowse.
--
-- <STRONG>Copyright (c) 2002 by Thomas Wolf.</STRONG>
-- <BLOCKQUOTE>
--    AdaBrowse is free software; you can redistribute it and/or modify it
--    under the terms of the  GNU General Public License as published by the
--    Free Software  Foundation; either version 2, or (at your option) any
--    later version. AdaBrowse is distributed in the hope that it will be
--    useful, but <EM>without any warranty</EM>; without even the implied
--    warranty of <EM>merchantability or fitness for a particular purpose.</EM>
--    See the GNU General Public License for  more details. You should have
--    received a copy of the GNU General Public License with this distribution,
--    see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
--    Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
--    USA.
-- </BLOCKQUOTE>
--
-- <DL><DT><STRONG>
-- Author:</STRONG><DD>
--   Thomas Wolf  (TW)
--   <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
--
-- <DL><DT><STRONG>
-- Purpose:</STRONG><DD>
--   Storage of user-defined HTML tags.</DL>
--
-- <!--
-- Revision History
--
--   29-APR-2002   TW  Initial version.
--   03-MAY-2002   TW  Changed interface to use new environment variable
--                     expander.
--   11-JUN-2002   TW  Using Util.Text instead of standard unbounded strings.
-- -->
-------------------------------------------------------------------------------

pragma License (GPL);

with Util.Environment;
with Util.Text;

package AD.User_Tags is

   pragma Elaborate_Body;

   Invalid_Tag : exception;

   procedure Parse_Tag
     (Key        : in     String;
      Definition : in     String;
      Expander   : access Util.Environment.String_Expander'Class);
   --  @Key@ should be the part of the key after the initial "User_Tag."
   --  @Definition@ should be whatever the key's definition is. If an
   --  error occurs, @Invalid_Tag@ with a descriptive error message is
   --  raised.

   type Tag (N : Natural) is abstract tagged
      record
         Name : String (1 .. N);
      end record;

   type Tag_Ptr is access all Tag'Class;
   for Tag_Ptr'Storage_Size use 0;
   --  No storage allocation through this pointer type: hence do not try
   --  to deallocate!

   type HTML_Content   is (Dont_Touch, Pure, Inline, Block, Flow);
   --  'Pure' means "never do anything with empty lines".

   type HTML_Container is (Single, Begin_End, End_Optional);

   type Follow_Set is array (Natural range <>) of Tag_Ptr;

   type Standard_Tag (N, F : Natural) is new Tag (N) with
      record
         Syntax   : HTML_Container;
         Class    : HTML_Content;
         Contains : HTML_Content;
         Follow   : Follow_Set (1 .. F);
      end record;
   --  If the top tag can have only inline content, the formatter emits
   --  "<BR><BR>" if handling paragraphs (unless the last thing written
   --  already was a "<BR>", in which case we emit only one "<BR>").
   --
   --  If the top tag's content is pure, nothing is done for empty lines:
   --  they're written as-is.
   --
   --  If the top tag's content is flow, we emit a <P> if we're on the first
   --  text line of the container or the last last line was empty. (Note that
   --  we rely on P's being implicitly closed!)
   --
   --  Whenever a closing tag is hit, we pop the stack until the corresponding
   --  opening tag is hit (if it exists, if not, ignore!).
   --
   --  The follow sets are set only for tags whose end tag is optional. They're
   --  used to determine when to close e.g. a paragraph. A follow set entry
   --  "null" means "any block tag closes this open block".

   type Standard_Ptr is access all Standard_Tag'Class;
   for Standard_Ptr'Storage_Size use 0;

   type Tag_Kind is (Container, Normal, Include, Execute, Initialize);

   type User_Defined_Tag is new Tag with
      record
         Kind         : Tag_Kind := Normal;
         Enabled      : Boolean  := True;
         In_Expansion : Boolean  := False;
         Start        : Util.Text.Unbounded_String;
         Final        : Util.Text.Unbounded_String;
      end record;
   --  @Start@ is the replacement in case on @Normal@ and @Container@,
   --  the file name in case of @Include@, and the command in case of
   --  @Execute@ or @Initialize@.
   --
   --  @Final@ is set only for @Container@ tags.

   type User_Tag_Ptr is access all User_Defined_Tag'Class;
   for User_Tag_Ptr'Storage_Size use 0;

   function Find_Tag
     (Key : in String)
     return Tag_Ptr;
   --  Returns @null@ if no such tag is found.

   procedure Verify;
   --  Verifies all the tags. If an error is found, @Invalid_Tag@ with a
   --  descriptive message is raised.

   procedure Reset_Tags;
   --  Resets the @In_Expansion@ flag of all tags, and resets all @Initialize@
   --  tags.

end AD.User_Tags;
