lined_20240419.0.0_da23d88f/src/lined-buffer.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
with Ada.Containers.Indefinite_Vectors;
with Ada.Directories;
with Ada.Strings.Unbounded;
with Ada.Text_IO;

package body Lined.Buffer is
   type Line_Info (Length : Natural) is record
      Mark : Boolean := False;
      Line : String (1 .. Length);
   end record;

   package Line_Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Line_Info);

   Line_List : Line_Lists.Vector;
   File_Name : Ada.Strings.Unbounded.Unbounded_String;

   procedure Clear is
      -- Empty
   begin -- Clear
      Line_List.Clear;
   end Clear;

   procedure Mark (Number : in Positive; Status : in Boolean) is
      procedure Update (Item : in out Line_Info);
      -- Sets Item.Mark to Status

      procedure Update (Item : in out Line_Info) is
         -- Empty
      begin -- Update
         Item.Mark := Status;
      end Update;
   begin -- Mark
      Line_List.Update_Element (Index => Number, Process => Update'Access);
   end Mark;

   function Marked (Number : Positive) return Boolean is (Line_List.Element (Number).Mark);

   procedure Clear_Marks is
      -- Empty
   begin -- Clear_Marks
      All_Lines : for I in 1 .. Line_List.Last_Index loop
         Mark (Number => I, Status => False);
      end loop All_Lines;
   end Clear_Marks;

   procedure Insert (Line : in String; Before : in Positive) is
      -- Empty
   begin -- Insert
      Line_List.Insert (Before => Before, New_Item => (Length => Line'Length, Mark => False, Line => Line) );
   end Insert;

   procedure Delete (Number : in Positive) is
      -- Empty
   begin -- Delete
      Line_List.Delete (Index => Number);
   end Delete;

   procedure Replace (Number : in Positive; Line : in String) is
      -- Empty
   begin -- Replace
      Line_List.Replace_Element
         (Index => Number, New_Item => (Length => Line'Length, Mark => Line_List.Element (Number).Mark, Line => Line) );
   end Replace;

   use Ada.Strings.Unbounded;

   function Default_File return String is (To_String (File_Name) );

   procedure Set_File (Name : in String) is
      -- Empty
   begin -- Set_File
      File_Name := To_Unbounded_String (Name);
   end Set_File;

   procedure Load (File_Name : in String) is
      File : Ada.Text_IO.File_Type;
   begin -- Load
      Buffer.File_Name := To_Unbounded_String (File_Name);

      if not Ada.Directories.Exists (File_Name) then
         return;
      end if;

      Clear;
      Ada.Text_IO.Open (File => File, Mode => Ada.Text_IO.In_File, Name => File_Name);

      Handle_EOF : declare
         -- Empty
      begin -- Handle_EOF
         All_Lines : loop
            Insert (Line => Ada.Text_IO.Get_Line (File), Before => Last + 1);
         end loop All_Lines;
      exception -- Handle_EOF
      when Ada.Text_IO.End_Error =>
         null;
      end Handle_EOF;

      Ada.Text_IO.Close (File => File);
   end Load;

   procedure Write (File_Name : in String := "") is
      File : Ada.Text_IO.File_Type;
   begin -- Write
      if File_Name = "" and Buffer.File_Name = Null_Unbounded_String then
         return;
      end if;

      if File_Name = "" then
         Ada.Text_IO.Create (File => File, Name => To_String (Buffer.File_Name) );
      else
         Ada.Text_IO.Create (File => File, Name => File_Name);
         Buffer.File_Name := To_Unbounded_String (File_Name);
      end if;

      All_Lines : for I in 1 .. Last loop
         Ada.Text_IO.Put_Line (File => File, Item => Line (I) );
      end loop All_Lines;

      Ada.Text_IO.Close (File => File);
   end Write;

   function Last return Natural is (Line_List.Last_Index);

   function Line (Number : Positive) return String is (Line_List.Element (Number).Line);

   function Next (Number : Natural) return Positive is (if Number >= Last then 1 else Number + 1);

   function Prev (Number : Natural) return Positive is (if Number < 2 then Last else Number - 1);
end Lined.Buffer;