-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset 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 distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

package body ScreenEcho is

   procedure Put_Char (Item : in Character) is
   begin
      SPARK_IO.Put_Char (SPARK_IO.Standard_Output, Item);
   end Put_Char;

   ----------------------------------------------------------------------------

   procedure Put_Integer (Item  : in Integer;
                          Width : in Natural;
                          Base  : in SPARK_IO.Number_Base) is
   begin
      SPARK_IO.Put_Integer (SPARK_IO.Standard_Output, Item, Width, Base);
   end Put_Integer;

   ----------------------------------------------------------------------------

   procedure Put_String (Item : in String) is
   begin
      SPARK_IO.Put_String (SPARK_IO.Standard_Output, Item, 0);
   end Put_String;

   ----------------------------------------------------------------------------

   procedure Put_Line (Item : in String) is
   begin
      SPARK_IO.Put_Line (SPARK_IO.Standard_Output, Item, 0);
   end Put_Line;

   ----------------------------------------------------------------------------

   procedure Put_StringWithLength (Item : in String;
                                   Stop : in Natural) is
   begin
      SPARK_IO.Put_String (SPARK_IO.Standard_Output, Item, Stop);
   end Put_StringWithLength;

   ----------------------------------------------------------------------------

   procedure Put_LineWithLength (Item : in String;
                                 Stop : in Natural) is
   begin
      SPARK_IO.Put_Line (SPARK_IO.Standard_Output, Item, Stop);
   end Put_LineWithLength;

   ----------------------------------------------------------------------------

   procedure New_Line (Spacing : in Positive) is
   begin
      SPARK_IO.New_Line (SPARK_IO.Standard_Output, Spacing);
   end New_Line;

   ----------------------------------------------------------------------------

   procedure Set_Col (Posn : in Positive) is
   begin
      SPARK_IO.Set_Col (SPARK_IO.Standard_Output, Posn);
   end Set_Col;

   ----------------------------------------------------------------------------

   procedure Put_ExaminerString (Item : in E_Strings.T) is
   begin
      E_Strings.Put_String (File  => SPARK_IO.Standard_Output,
                            E_Str => Item);
   end Put_ExaminerString;

   ----------------------------------------------------------------------------

   procedure Put_ExaminerLine (Item : in E_Strings.T) is
   begin
      E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                          E_Str => Item);
   end Put_ExaminerLine;

   ----------------------------------------------------------------------------

   procedure Echo (Str : in E_Strings.T) is
      procedure Print_Line (Start_Pos, End_Pos, Indent : in Natural;
                            Line                       : in E_Strings.T)
      --# global in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys from *,
      --#                                End_Pos,
      --#                                Indent,
      --#                                Line,
      --#                                Start_Pos;
      is
         Pos, Current_Line_End, Current_Line_Start : Natural;

         procedure Print_Current_Line
         --# global in     Current_Line_End;
         --#        in     Current_Line_Start;
         --#        in     Line;
         --#        in out SPARK_IO.File_Sys;
         --# derives SPARK_IO.File_Sys from *,
         --#                                Current_Line_End,
         --#                                Current_Line_Start,
         --#                                Line;
         is
         begin
            E_Strings.Put_String
              (File  => SPARK_IO.Standard_Output,
               E_Str => E_Strings.Section
                 (E_Str     => Line,
                  Start_Pos => Current_Line_Start,
                  Length    => (Current_Line_End - Current_Line_Start) + 1));
         end Print_Current_Line;

         procedure Find_Current_Line_End (Current_Line_Pos : in Natural)
         --# global in     Current_Line_Start;
         --#        in     End_Pos;
         --#        in     Line;
         --#        in     Pos;
         --#           out Current_Line_End;
         --# derives Current_Line_End from Current_Line_Pos,
         --#                               Current_Line_Start,
         --#                               End_Pos,
         --#                               Line,
         --#                               Pos;
         is
            Next_Space_Pos, Current_Space_Pos : Integer;

            function Find_Next_Space (Curr_Pos : in E_Strings.Positions) return Natural
            --# global in Line;
            is
               Found    : Boolean;
               Next_Pos : Natural;
            begin
               E_Strings.Find_Char_After
                 (E_Str        => Line,
                  Search_Start => Curr_Pos,
                  Search_Char  => ' ',
                  Char_Found   => Found,
                  Char_Pos     => Next_Pos);
               if not Found then
                  Next_Pos := E_Strings.Get_Length (E_Str => Line);
               end if;
               return Next_Pos;
            end Find_Next_Space;

         begin
            Current_Space_Pos := Find_Next_Space (Curr_Pos => Current_Line_Pos + 1);
            loop
               exit when Current_Space_Pos = E_Strings.Get_Length (E_Str => Line);
               Next_Space_Pos := Find_Next_Space (Curr_Pos => Current_Space_Pos + 1);
               exit when (Pos + Next_Space_Pos) - Current_Line_Start > End_Pos;
               Current_Space_Pos := Next_Space_Pos;
            end loop;
            Current_Line_End := Current_Space_Pos;
         end Find_Current_Line_End;

      begin
         Current_Line_Start := 1;
         Pos                := Start_Pos;
         Find_Current_Line_End (0);
         loop
            Print_Current_Line;
            exit when Current_Line_End = E_Strings.Get_Length (E_Str => Line);

            New_Line (1);
            Set_Col (Indent);
            Pos                := Indent;
            Current_Line_Start := Current_Line_End + 1;
            Find_Current_Line_End (Current_Line_Start);
         end loop;
      end Print_Line;

   begin
      New_Line (1);
      Set_Col (12);
      Print_Line (12, 80, 12, Str);
      Put_Line (" ...");
   end Echo;

end ScreenEcho;
