--
-- @filename module-latex.adb
-- @author Julien Burdy & Vincent Decorges
-- @date 17.6.02
-- @brief AdaDoc LaTeX writer module
--
-- History  :
-- Date     Modification               Author
--
with Ada.Text_IO;
with Ada.Strings.Unbounded;  use Ada.Strings.Unbounded;


package body Module.Latex is

   File : Ada.Text_IO.File_Type;

   --
   -- Purpose : Overload of the Text_IO put to replace some symbols.
   --
   -- Item : Item to put.
   --
   procedure Put(Item: String) is
      String_Tmp : Unbounded_String := To_Unbounded_String(Item);

      -- Value of the TeX symbols
      Tex_Low_Line  : constant string := "\_"  ;

   begin -- Replacement of some symbols.

      while Index(String_Tmp, "_") /= 0 loop
         Replace_Slice (String_Tmp, Index(String_Tmp, "_"),
                        Index(String_Tmp, "_"), "@");
      end loop;

      -- Temporary symbole to avoid recursivity
      while Index(String_Tmp, "@") /= 0 loop
         Replace_Slice (String_Tmp, Index(String_Tmp, "@"),
                        Index(String_Tmp, "@"), Tex_Low_Line);
      end loop;

      while Index(String_Tmp, "¶") /= 0 loop
         Replace_Slice (String_Tmp, Index(String_Tmp, "¶"),
                        Index(String_Tmp, "¶"), "\\");
      end loop;

      Ada.Text_IO.Put(To_String(String_Tmp));
   end Put;


   --
   -- Purpose : Overload of the Text_IO put_line
   --
   -- Item : Item to put.
   --
   procedure Put_Line(Item: String) is
   begin
      Put(Item);
      Ada.Text_IO.New_Line;
   end Put_Line;


   --
   -- Purpose : Write specification comment.
   --
   -- Atts : Dict whom contain comment.
   --
   procedure Put_Comment(Atts : Dict_Type) is
   begin
      if Exist(Atts, "comment") then
         Put_Line("\cat{Comment : } {\it "&Value_Of(Atts,"comment")&"}\\");
      end if;
   end Put_Comment;

   --
   -- Purpose : Write a LaTeX comment from item
   --
   -- Item : The comment to write.
   --
   procedure Comment( C : String) is
   begin
      Ada.Text_IO.New_Line(2);
      Ada.Text_IO.Put_Line("% "&C);
   end Comment;


   --------------------
   -- Begin_Document --
   --------------------
   -- Receive notification of the beginning of a document.
   -- This callback will be called only once.
   procedure Begin_Document (Self : Object;
                             Package_Name : String;
                             Atts, Tags : Dict_Type) is
   begin
      Ada.Text_IO.Create(File, Name => Value_Of(Atts, "file")&".tex");
      Ada.Text_IO.Set_Output(File);
      Comment("The next lines are ready for an inclusion (or a copy paste) in a "&
                                                                          "LaTeX file.");
   end Begin_Document;


   ------------------
   -- End_Document --
   ------------------
   -- Receive notification of the end of a document.
   -- This callback will be called only once.
   procedure End_Document (Self : Object) is
   begin
      Ada.Text_IO.Set_Output(Ada.Text_IO.Standard_Output);
      Ada.Text_IO.Close(File);
      Put_Line(".tex is Done !");
   end End_Document;


   -----------------
   -- Start_Group --
   -----------------
   -- Receive notification of the beginning of a group of elements.
   procedure Start_Group (Self : Object; Group : Element_Type) is
   begin
      case Group is

         when Is_ContextClauses =>
            Comment("Context Clauses");
            Put_Line("\begin{tabular}{l|l}");
            Put_Line("\cat{Clause} & \cat{Comment}\\");
         when Is_UseClauses =>
            Comment("Use Clauses");
            Put_Line("\begin{tabular}{l|l}");
            Put_Line("\cat{Clause} & \cat{Comment}\\");
         when Is_UseTypeClauses =>
            Comment("UseType Clauses");
            Put_Line("\begin{tabular}{l|l}");
            Put_Line("\cat{Clause} & \cat{Comment}\\");
         when Is_Exceptions =>
            Comment("Exceptions");
            Put_Line("\begin{tabular}{l|l}");
            Put_Line("\cat{Name} & \cat{Comment}\\");
         when Is_Parameters =>
            Put_Line("\begin{tabular}{l|l|c|l|l}");
            Put_Line(
            "\cat{Name}&\cat{Type}&\cat{Mode}&\cat{default}&\cat{Comment}\\");
         when Is_Types =>
            Comment("Types");
            Put_Line("\begin{tabular}{l|l|l}");
            Put_Line("\cat{Name} & \cat{Declaration} & \cat{Comment}\\");
         when Is_PackagesSubprograms =>
            Comment("Packages or Subprograms");
            Put_Line("\begin{list}{\textbullet}{}");
         when Is_GenericInstanciations =>
            Comment("Generic Instanciations");
            Put_Line("\begin{list}{\textbullet}{}");
         when others => Null;
      end case;
   end Start_Group;


   --------------
   -- A_Clause --
   --------------
   -- Receive notification of each clause.
   procedure A_Clause (Self : Object; Atts : Dict_Type; Its_Value : String) is
   begin
      Put_Line(Its_Value&"&"&Value_Of(Atts, "comment")&"\\");
   end A_Clause;


   ------------------------------
   -- A_Package_Subprogram_Gen --
   ------------------------------
   -- Receive notification of each generic package or subprogram.
   procedure A_Package_Subprogram_Gen (Self : Object;
                                       Atts : Dict_Type;
                                       Its_Name : String) is
   begin
      Put_Line("\item "&Its_Name&"\\");
   end A_Package_Subprogram_Gen;


   ---------------
   -- An_Object --
   ---------------
   -- Receive notification of each object.
   procedure An_Object (Self : Object; Atts : Dict_Type;
                        Its_Name, Its_Type : String; Is_Component : Boolean) is
   begin
      Put(Its_Name);
      Put("&"&Its_Type);
      Put("&"&Value_Of(Atts,"init"));
      Put_Line("&"&Value_Of(Atts,"comment")&"\\");
   end An_Object;


   --------------
   -- A_Record --
   --------------
   -- Receive notification of each record.
   procedure A_Record (Self : Object; Atts : Dict_Type; Its_Name : String) is
   begin
      Put_Line("\cat{"&Its_Name&"}\\");
   end A_Record;


   -----------------------
   -- A_Type_Definition --
   -----------------------
   -- Receive notification of each type definition.
   procedure A_Type_Definition (Self : Object; Atts : Dict_Type;
                                Its_Name, Its_Def : String) is
   begin
      Put(Its_Name);
      Put(" & "&Its_Def);
      Put_Line(" & "&Value_Of(Atts, "comment")&"\\");
   end A_Type_Definition;


   --------------------
   -- A_Variant_Part --
   --------------------
   -- Receive notification of each variant part.
   procedure A_Variant_Part (Self : Object; Atts : Dict_Type; Its_Discriminant : String)
   is
   begin
      Put_Line("\subsubsection{Varient Part}");
      Put_Comment(Atts);
   end A_Variant_Part;


   --------------
   -- A_Choice --
   --------------
   -- Receive notification of each variant part choice.
   procedure A_Choice (Self : Object; Atts : Dict_Type; Its_Value : String) is
   begin
      Put_Line("\\ \cat{When dicriminant =} "&Its_Value&"\\");
      Put_Comment(Atts);
   end A_Choice;


   --------------
   -- An_Entry --
   --------------
   -- Receive notification of each entry.
   procedure An_Entry (Self : Object; Atts : Dict_Type; Its_Name : String) is
   begin
      Put_Line("\subsubsection{"&Its_Name&" {\it (entry)}}");
      Put_Comment(Atts);
   end An_Entry;


   -----------------
   -- A_Parameter --
   -----------------
   -- Receive notification of each parameter (procedure, function, entry).
   procedure A_Parameter (Self : Object; Atts : Dict_Type;
                          Its_Name, Its_Type, Its_Mode : String) is
   begin
      Put(Its_Name&"&"); Put(Its_Type&"&"); Put(Its_Mode&"&");
      Put(Value_Of(Atts, "Init")&"&");
      Put_Line(Value_Of(Atts, "comment")&"     \\");
   end A_Parameter;


   -----------------
   -- A_Procedure --
   -----------------
   -- Receive notification of each procedure.
   procedure A_Procedure (Self : Object; Atts : Dict_Type;
                          Its_Name : String; In_Prot_Obj : Boolean) is
   begin
      Comment("procedure : "&Its_Name);
      Put_Line("\subsection*{"&Its_Name&" {\it \scriptsize (procedure)}}");
      if Exist(Atts,"comment") then
         Put_Line("\noindent");
         Put_Line("{\it "&Value_Of(Atts,"comment")&"}\\");
      end if;
   end A_Procedure;


   ----------------
   -- A_Function --
   ----------------
   -- Receive notification of each function.
   procedure A_Function (Self : Object; Atts : Dict_Type;
                         Its_Name, Its_Return_Type : String; In_Prot_Obj : Boolean) is
   begin
      Comment("function : "&Its_Name);
      Put_Line("\subsection*{"&Its_Name&" {\it \scriptsize (function)}}");
      Put_Line("{\bf Return : }"&Value_Of(Atts, "return")&"\\\\");
      if Exist(Atts,"comment") then
         Put_Line("\noindent");
         Put_Line("{\it "&Value_Of(Atts,"comment")&"}\\");
      end if;
   end A_Function;


   ------------------
   -- An_Exception --
   ------------------
   -- Receive notification of each exception.
   procedure An_Exception (Self : Object; Atts : Dict_Type; Its_Name : String) is
   begin
      Put_Line(Its_Name&"& "&Value_Of(Atts, "comment")&"\\");
   end An_Exception;


   -----------------
   -- End_Element --
   -----------------
   -- Receive notification of the end of each elements (Module.Element_Type).
   procedure End_Element (Self : Object; Element : Element_Type) is
   begin
      case Element is
         when Is_ContextClauses | Is_Parameters | Is_UseClauses | Is_UseTypeClauses
            | Is_BasicObjects | Is_Types | Is_Exceptions =>
            Put_Line("\end{tabular}\\");
         when Is_PackagesSubprograms | Is_GenericInstanciations =>
            Put_Line("\end{list}");

         when others =>
            null;
      end case;
   end End_Element;


   ------------------------
   -- A_Generic_Instance --
   ------------------------
   -- Receive notification of each generic instance.
   procedure A_Generic_Instance (Self : Object;  Atts : Dict_Type; Its_Name : String) is
   begin
      Put_Line("\item "&Its_Name&"\\");
   end A_Generic_Instance;


end Module.Latex;

