--------------------------------------------------------------------------------
--                                                                            --
-- Copyright (C) 2004, RISC OS Ada Library (RASCAL) developers.               --
--                                                                            --
-- This library is free software; you can redistribute it and/or              --
-- modify it under the terms of the GNU Lesser General Public                 --
-- License as published by the Free Software Foundation; either               --
-- version 2.1 of the License, or (at your option) any later version.         --
--                                                                            --
-- This library 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           --
-- Lesser General Public License for more details.                            --
--                                                                            --
-- You should have received a copy of the GNU Lesser General Public           --
-- License along with this library; if not, write to the Free Software        --
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    --
--                                                                            --
--------------------------------------------------------------------------------

-- $Author$
-- $Date$
-- $Revision$

with RASCAL.OS;
with RASCAL.Utility;    use RASCAL.Utility;
with RASCAL.Memory;     use RASCAL.Memory;

with System.Unsigned_Types; use System.Unsigned_Types;
with Interfaces.C;          use Interfaces.C;
with Kernel;                use Kernel;


package body RASCAL.ToolboxTextArea is

   -- SWIs
   Toolbox_ObjectMiscOp           : constant :=16#44EC6#;

   TextGadgets_TextArea           : constant := 16#140180#;
   TextGadgets_TextField          : constant := 16#140181#;
   TextGadgets_ScrollList         : constant := 16#140182#;
   TextGadgets_Scrollbar          : constant := 16#140183#;
   TextGadgets_RedrawAll          : constant := 16#140184#;
   TextGadgets_Filter             : constant := 16#140185#;
   TextGadgets_ProdPoll           : constant := 16#140186#;

   -- Reason codes
   TextArea_GetState              : constant := 16#4018#;
   TextArea_SetState              : constant := 16#4019#;
   TextArea_SetText               : constant := 16#401A#;
   TextArea_GetTextSize           : constant := 16#401B#;
   TextArea_GetText               : constant := 16#401B#;
   TextArea_InsertText            : constant := 16#401C#;
   TextArea_ReplaceText           : constant := 16#401D#;
   TextArea_GetSelection          : constant := 16#401E#;
   TextArea_GetSelectionTextSize  : constant := 16#401E#;
   TextArea_GetSelectionText      : constant := 16#401E#;
   TextArea_SetSelection          : constant := 16#401F#;
   TextArea_SetFont               : constant := 16#4020#;
   TextArea_SetColour             : constant := 16#4021#;
   TextArea_GetColour             : constant := 16#4022#;
   TextArea_SetTextBorder         : constant := 16#4023#;
   TextArea_SetBackground         : constant := 16#4024#;
   TextArea_GetWindowID           : constant := 16#4025#;

   --
      
   function Get_State (Window    : in Object_ID;
                       Component : in Component_ID;
                       Flags     : in System.Unsigned_Types.Unsigned := 0) return integer is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetState;
      Register.R(3) := int(Component);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_State: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      return integer(Register.R(0));
   end Get_State;

   --

   procedure Set_State (Window    : in Object_ID;
                        Component : in Component_ID;
                        State     : in integer;
                        Flags     : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetState;
      Register.R(3) := int(Component);
      Register.R(4) := int(State);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_State: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_State;

   --

   procedure Set_Text (Window    : in Object_ID;
                       Component : in Component_ID;
                       Text      : in string;
                       Flags     : in System.Unsigned_Types.Unsigned := 0) is

      Register  : aliased Kernel.swi_regs;
      Error     : oserror_access;
      Text_0    : string := Text & ASCII.NUL;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetText;
      Register.R(3) := int(Component);
      Register.R(4) := Adr_To_Int(Text_0'Address);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Text: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Text;

   --

   function Get_Text (Window    : in Object_ID;
                      Component : in Component_ID) return String is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
      Buffer_Size    : integer := 0;
   begin
      Register.R(0) := 0;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetTextSize;
      Register.R(3) := int(Component);
      Register.R(4) := 0;
      Register.R(5) := 0;
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_Text: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      Buffer_Size := integer(Register.R(5));
      declare
         Buffer : Char_Array(1..size_t(Buffer_Size + 1));
      begin
         Register.R(0) := 0;
         Register.R(1) := int(Window);
         Register.R(2) := TextArea_GetText;
         Register.R(3) := int(Component);
         Register.R(4) := Adr_To_Int(Buffer'Address);
         Register.R(5) := int(Buffer_Size);
         Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

         if Error /= null then
            pragma Debug(Report("ToolboxTextArea.Get_Text: " & To_Ada(Error.ErrMess)));
            OS.Raise_Error(Error);
         end if;
         return To_Ada(Buffer);
      end;
   end Get_Text;

   --

   procedure Insert_Text (Window    : in Object_ID;
                          Component : in Component_ID;
                          Text      : in string;
                          Index     : in integer := 0;
                          Flags     : in System.Unsigned_Types.Unsigned := 0) is

      Register  : aliased Kernel.swi_regs;
      Error     : oserror_access;
      Null_Text : string := Text & ASCII.NUL;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_InsertText;
      Register.R(3) := int(Component);
      Register.R(4) := int(Index);
      Register.R(5) := Adr_To_Int(Null_Text'Address);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Insert_Text: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Insert_Text;

   --

   procedure Replace_Text (Window       : in Object_ID;
                           Component    : in Component_ID;
                           Text         : in string;
                           End_Index    : in integer := 0;
                           Start_Index  : in integer := 0;
                           Flags        : in System.Unsigned_Types.Unsigned := 0) is

      Register  : aliased Kernel.swi_regs;
      Error     : oserror_access;
      Null_Text : string := Text & ASCII.NUL;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_ReplaceText;
      Register.R(3) := int(Component);
      Register.R(4) := int(Start_Index);
      Register.R(5) := int(End_Index);
      Register.R(6) := Adr_To_Int(Null_Text'Address);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Replace_Text: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Replace_Text;

   --

   function Is_Selection (Window    : in Object_ID;
                          Component : in Component_ID) return Boolean is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
      Buffer_Size    : integer := 0;
   begin
      Register.R(0) := 1;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetSelectionTextSize;
      Register.R(3) := int(Component);
      Register.R(4) := 0;
      Register.R(5) := 0;
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_Selection: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      Buffer_Size := integer(Register.R(5));
      return Buffer_Size >0;
   end Is_Selection;

   --

   function Get_Selection (Window    : in Object_ID;
                           Component : in Component_ID) return String is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
      Buffer_Size    : integer := 0;
   begin
      Register.R(0) := 1;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetSelectionTextSize;
      Register.R(3) := int(Component);
      Register.R(4) := 0;
      Register.R(5) := 0;
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_Selection: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      Buffer_Size := integer(Register.R(5));
      declare
         Buffer : String(1..Buffer_Size + 1);
      begin
         Register.R(0) := 1;
         Register.R(1) := int(Window);
         Register.R(2) := TextArea_GetSelectionText;
         Register.R(3) := int(Component);
         Register.R(4) := Adr_To_Int(Buffer'Address);
         Register.R(5) := int(Buffer_Size);
         Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

         if Error /= null then
            pragma Debug(Report("ToolboxTextArea.Get_Selection: " & To_Ada(Error.ErrMess)));
            OS.Raise_Error(Error);
         end if;
         return MemoryToString(Buffer'Address);
      end;
   end Get_Selection;

   --

   procedure Get_Selection_Index (Window     : in Object_ID;
                                  Component  : in Component_ID;
                                  Start_Index: out integer;
                                  End_Index  : out integer) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := 0;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetSelection;
      Register.R(3) := int(Component);
      Register.R(4) := 0;
      Register.R(5) := 0;
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_Selection: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      Start_Index := integer(Register.R(0));
      End_Index   := integer(Register.R(1));
   end Get_Selection_Index;

   --

   procedure Set_Selection (Window      : in Object_ID;
                            Component   : in Component_ID;
                            End_Index   : in integer;
                            Start_Index : in integer :=0;                        
                            Flags       : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetSelection;
      Register.R(3) := int(Component);
      Register.R(4) := int(Start_Index);
      Register.R(5) := int(End_Index);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Selection: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Selection;

   --

   procedure Set_Font (Window       : in Object_ID;
                       Component    : in Component_ID;
                       Font         : in String;
                       Font_Width   : in integer := 12;
                       Font_Height  : in integer := 12;
                       Flags        : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
      Null_Font      : string := Font & ASCII.NUL;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetFont;
      Register.R(3) := int(Component);
      Register.R(4) := Adr_To_Int(Null_Font'Address);
      Register.R(5) := int(Font_Width);
      Register.R(6) := int(Font_Height);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Font: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Font;

   --

   procedure Set_Colour (Window     : in Object_ID;
                         Component  : in Component_ID;
                         Foreground : in OS_Colour;
                         Background : in OS_Colour) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := 0;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetColour;
      Register.R(3) := int(Component);
      Register.R(4) := int(Unsigned_To_Int(System.Unsigned_Types.Unsigned(Foreground)));
      Register.R(5) := int(Unsigned_To_Int(System.Unsigned_Types.Unsigned(Background)));
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Colour: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Colour;

   --

   procedure Set_Colour (Window     : in Object_ID;
                         Component  : in Component_ID;
                         Foreground : in Toolbox_Colour := 7;
                         Background : in Toolbox_Colour := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := 1;
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetColour;
      Register.R(3) := int(Component);
      Register.R(4) := int(Foreground);
      Register.R(5) := int(Background);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Colour: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Colour;

   --

   procedure Get_Colour (Window    : in Object_ID;
                         Component : in Component_ID;
                         Foreground: out OS_Colour;
                         Background: out OS_Colour;
                         Flags     : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetColour;
      Register.R(3) := int(Component);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Get_Selected: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      Foreground := OS_Colour(Int_To_Unsigned(integer(Register.R(0))));
      Background := OS_Colour(Int_To_Unsigned(integer(Register.R(1))));
   end Get_Colour;

   --

   function Get_WindowID (Window    : in Object_ID;
                          Component : in Component_ID;
                          Flags     : in System.Unsigned_Types.Unsigned := 0) return Object_ID is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_GetWindowID;
      Register.R(3) := int(Component);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxOptionButton.Get_WindowID: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
      return Object_ID(Register.R(0));
   end Get_WindowID;

   --

   procedure Set_Background (Window     : in Object_ID;
                             Component  : in Component_ID;
                             Sprite     : in String;
                             Flags      : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
      Sprite_0       : String := Sprite & ASCII.NUL;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetBackground;
      Register.R(3) := int(Component);
      Register.R(4) := Adr_To_Int(Sprite_0'Address);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_Background: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_Background;

   --

   procedure Set_TextBorder (Window     : in Object_ID;
                             Component  : in Component_ID;
                             BorderSize : in Integer;
                             Flags      : in System.Unsigned_Types.Unsigned := 0) is

      Register       : aliased Kernel.swi_regs;
      Error          : oserror_access;
   begin
      Register.R(0) := int(Unsigned_to_Int(Flags));
      Register.R(1) := int(Window);
      Register.R(2) := TextArea_SetTextBorder;
      Register.R(3) := int(Component);
      Register.R(4) := int(BorderSize);
      Error := Kernel.swi(Toolbox_ObjectMiscOp,Register'Access,Register'Access);

      if Error /= null then
         pragma Debug(Report("ToolboxTextArea.Set_TextBorder: " & To_Ada(Error.ErrMess)));
         OS.Raise_Error(Error);
      end if;
   end Set_TextBorder;

   --
   
end RASCAL.ToolboxTextArea;
