-------------------------------------------------------------------------------
--
--  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>
--   A collection of writing operations, with cross-reference and anchor
--   generation. For entities that are part of generic instantiations, tries
--   to generate references to the generic template.</DL>
--
-- <!--
-- Revision History
--
--   20-FEB-2002   TW  Created from stuff originally in AD.Scanner.
--   09-JUL-2003   TW  New operation 'Write_Special_Anchor' for XRefs to
--                     pragmas.
-- -->
-------------------------------------------------------------------------------

pragma License (GPL);

with Asis;
with Asis.Text;

with Asis2.Spans;

with AD.Printers;

package AD.Writers is

   pragma Elaborate_Body;

   type Write_State is tagged
      record
         Unit         : Asis.Declaration             := Asis.Nil_Element;
         Write_From   : Asis2.Spans.Position         :=
           Asis2.Spans.Nil_Position;
         Last_Written : Asis2.Spans.Position         :=
           Asis2.Spans.Nil_Position;
         Indent       : Asis.Text.Character_Position := 0;
         Need_Newline : Boolean                      := False;
         The_Printer  : AD.Printers.Printer_Ref;
      end record;

   --  This type collects state information for the writing routines below.
   --
   --  The semantics of these fields are:
   --
   --  <DL>
   --  <DT><CODE>
   --  Unit</CODE><DD>
   --      The library unit declaration of the unit currently being processed.
   --      We need this to determine whether a cross-reference is within the
   --      same unit or shall go to some other file.
   --      <BR><BR>
   --  <DT><CODE>
   --  Write_From</CODE><DD>
   --      The next position to write. If this is < the start of the span to
   --      write, the <CODE>Write*</CODE> operations also write everything
   --      from <CODE>Write_From</CODE> up to the span that is to be written.
   --      <BR><BR>
   --  <DT><CODE>
   --  Last_Written</CODE><DD>
   --      The last position that was written. Initially set to
   --      <CODE>Nil_Position</CODE>. Needed to determine whether we have to
   --      omit leading white space from a line gotten from Asis.Text. Such
   --      lines may contain leading white space, if the span used starts
   --      somewhere in the middle of a source line. If
   --      <CODE>Last_Written.Line</CODE> = the current line, we know that we
   --      may omit the first <CODE>Last_Written.Column</CODE> white spaces.
   --      <BR><BR>
   --  <DT><CODE>
   --  Indent</CODE><DD>
   --      The indentation of the beginning of a declaration. Whenever
   --      <CODE>Last_Written.Line</CODE> /= the current line, and we have
   --      more than <CODE>Indent</CODE> white spaces at the beginning of a
   --      line, we strip away <CODE>Indent</CODE> white spaces.
   --      <BR><BR>
   --  <DT><CODE>
   --  Need_Newline</CODE><DD>
   --      Is set to <CODE>True</CODE> whenever the span written by any of the
   --      <CODE>Write*</CODE> operations ends at the end of a line. The
   --      caller can then generate newlines as it sees fit. Note that ASIS
   --      text positions never include end-of-line markers such as CR-LF!
   --  </DL>
   --
   --  To write a span with indentation removed, set:
   --  <PRE>
   --    Write_From   := <start of the span>;
   --    Last_Written := (Write_From.Line, Write_From.Column - 1);
   --    Indent       := Write_From.Column - 1;
   --  </PRE>
   --
   --  All the <CODE>Write*</CODE> operations update <CODE>Write_From</CODE>
   --  and <CODE>Last_Written</CODE> to reflect the first position after what
   --  was written and the last position actually written, respectively.

   procedure Terminate_Line
     (State : in out Write_State);
   --  Write a newline if <CODE>State.Need_Newline</CODE> = <CODE>True</CODE>
   --  and then sets the flag to <CODE>False</CODE>.

   procedure Write_Reference
     (Name  : in     Asis.Expression;
      State : in out Write_State);
   --  Appropriate <CODE>Expression_Kinds</CODE>:
   --  <CODE><PRE>
   --    An_Identifier
   --    An_Operator_Symbol
   --    An_Enumeration_Literal
   --  </PRE></CODE>
   --  Writes anything between <CODE>State.Write_From</CODE> and the
   --  <CODE>Name</CODE>, and then writes the <CODE>Name</CODE> itself as
   --  a cross-reference to the declaration it references.
   --
   --  Assumes that <CODE>State.Write_From</CODE> <= the start of the
   --  <CODE>Name</CODE>'s span.

   procedure Write_Attribute
     (Name  : in     Asis.Expression;
      State : in out Write_State);
   --  Appropriate <CODE>Expression_Kinds</CODE>:
   --
   --    <CODE>An_Identifier</CODE>
   --
   --  Writes anything between <CODE>State.Write_From</CODE> and the
   --  identifier, and then Writes the identifier as an attribute designator:
   --  First letter and any letter following an underscore is capitalized, all
   --  other letters are lower case. The identifier is enclosed by the HTML
   --  defined by the configuration key "Attribute.Before/After".
   --
   --  Assumes that <CODE>State.Write_From</CODE> <= the start of
   --  the <CODE>Name</CODE>'s span.

   procedure Write_Name
     (Name  : in     Asis.Defining_Name;
      State : in out Write_State);
   --  Appropriate <CODE>Defining_Name_Kinds</CODE>:
   --
   --    <CODE>A_Defining_Name</CODE>
   --
   --  Writes anything between <CODE>State.Write_From</CODE> and the
   --  identifier, and then Writes the defining name, generating an anchor
   --  for it. Assumes that <CODE>State.Write_From</CODE> <= the start of
   --  the <CODE>Name</CODE>'s span.

   procedure Write_Special_Anchor
     (Element : in     Asis.Element;
      State   : in out Write_State);
   --  Appropriate <CODE>Element_Kinds</CODE>:
   --
   --    <CODE>A_Pragma, A_Clause</CODE>
   --
   --  Appropriate @Clause_Kinds@:
   --
   --    @An_Attribute_Definition_Clause@,
   --    @An_Enumeration_Representation_Clause@,
   --    @A_Record_Representation_Clause@
   --
   --  Writes anything between <CODE>State.Write_From</CODE> and the
   --  start oif the element, and then writes "pragma" or "for", generating
   --  an anchor for it. Assumes that <CODE>State.Write_From</CODE> <= the
   --  start of the <CODE>Element</CODE>'s span.

   procedure Write
     (Element : in     Asis.Element;
      State   : in out Write_State);
   --  <CODE>Element</CODE> can be anything. Writes everything between
   --  <CODE>State.Write_From</CODE> up to and including the end of the
   --  <CODE>Element</CODE>'s span. If <CODE>State.Write_From</CODE> >=
   --  the start of the <CODE>Element</CODE>'s span, only that part of
   --  the <CODE>Element</CODE>'s span beyond <CODE>State.Write_From</CODE>
   --  is written (including <CODE>State.Write_From</CODE> itself).

   procedure Write_Span
     (Span  : in     Asis.Text.Span;
      State : in out Write_State);
   --  Writes anything from <CODE>State.Write_From</CODE> to the start of
   --  the given <CODE>Span</CODE>, and then writes the <CODE>Span</CODE>
   --  itself.
   --
   --  Make sure that <CODE>State.Unit</CODE> is the true unit containing the
   --  span, and then <CODE>State.Write_From</CODE> is set correctly.
   --
   --  If <CODE>State.Write_From</CODE> > <CODE>Start (Span)</CODE>, only the
   --  remaining span <CODE>(State.Write_From,&nbsp;Stop&nbsp;(Span))</CODE>
   --  is written.

end AD.Writers;
