unit ucs4multilineunit;
{$MODE OBJFPC}{$H+}
{$RANGECHECKS ON}

interface

uses
  SysUtils, Classes, ucs4unit, ucs4opunit, ucs4functionsunit;

type
  ucs4multiline = object
  public
    Lines: TUC4Array;
    FCount: Integer;
    FUseTrailingLineBreak: ByteBool;
    procedure Init;
    procedure Clear;
    procedure Add(const Line: ucs4);
    procedure AddCopy(const Line: ucs4);
    procedure LoadFromFile(const Filename: string);
    procedure SaveToFile(const Filename: string);
    function ToString: string;
    function Join(const Delimiter: ucs4): ucs4;
    property Count: Integer read FCount;
    property UseTrailingLineBreak: ByteBool read FUseTrailingLineBreak write FUseTrailingLineBreak;
  end;

implementation

procedure ucs4multiline.Init;
begin
  SetLength(Lines, 0);
  FCount := 0;
  FUseTrailingLineBreak := False;
end;

procedure ucs4multiline.Clear;
var
  i: Integer;
begin
  for i := 0 to FCount - 1 do
    Lines[i].Clear;
  SetLength(Lines, 0);
  FCount := 0;
  FUseTrailingLineBreak := False;
end;

procedure ucs4multiline.Add(const Line: ucs4);
begin
  if FCount >= Length(Lines) then
    SetLength(Lines, FCount + 8);
  Lines[FCount].Init;
  Lines[FCount] := Line;
  Inc(FCount);
end;

procedure ucs4multiline.AddCopy(const Line: ucs4);
var f:LongInt;
begin
  if FCount >= Length(Lines) then
    SetLength(Lines, FCount + 8);
  Lines[FCount].Init(Line.Length);
  for f := 0 to Line.Length-1 do Lines[FCount][f]:=Line[f];
  Inc(FCount);
end;

procedure ucs4multiline.LoadFromFile(const Filename: string);
var
  F: Text;
  Line: string;
begin
  Clear;
  try
    if not FileExists(FileName) then
    begin
      Writeln('ucs4multiline.LoadFromFile: Ошибка: файл не найден');
      Halt(1);
    end else WriteLn('ucs4multiline.LoadFromFile: Загружается файл: ', FileName);

    AssignFile(F, FileName);
    FileMode := 0;
    Reset(F);
    while not Eof(F) do
    begin
      Readln(F, Line);
      Inc(FCount);
    end;
    WriteLn('ucs4multiline.LoadFromFile: Файл содержит ', FCount, ' строк (предварительно)');
    SetLength(Lines, FCount);
    if Count < 1 then begin
      Close(F);
      Exit;
    end;

    Reset(F);
    FCount := 0;

    while not Eof(F) do
    begin
      Readln(F, Line);
      Lines[FCount] := Line;
    Inc(FCount);
    end;

    // Проверяем последнюю строку на пустоту (признак trailing line break)
    if FUseTrailingLineBreak and ((FCount > 0) and (Lines[FCount-1].Length = 0)) then begin
      Dec(FCount);
      SetLength(Lines, FCount);
    end;

    WriteLn('ucs4multiline.LoadFromFile: Файл загружен, содержит ', FCount, ' строк');
  finally
  end;
Close(F);
end;

procedure ucs4multiline.SaveToFile(const Filename: string);
var
  i: Integer;
  F: Text;
begin
AssignFile(F, FileName);
  FileMode := 1;
  try
    ReWrite(F);
    for i := 0 to FCount - 2 do
      WriteLn(F, Lines[i].ToUTF8);
    if FCount > 0 then Write(F, Lines[FCount - 1].ToUTF8);
    if FUseTrailingLineBreak then WriteLn(F, '');
  finally
  end;
Close(F);
end;

function ucs4multiline.ToString: string;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to FCount - 1 do
  begin
    if i > 0 then Result := Result + LineEnding;
    Result := Result + Lines[i].ToUTF8;
  end;
end;

function ucs4multiline.Join(const Delimiter: ucs4): ucs4;
var
  i: Integer;
begin
  if FCount = 0 then
  begin
    Result.Init;
    Exit;
  end;

  Result := Lines[0];
  for i := 1 to FCount - 1 do
    Result := Result.Concat(Delimiter).Concat(Lines[i]);
end;

end.