unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2, Unit3, ExtCtrls, Unit4, Menus,CioinaEval,Math;
type
  TMatrix=array of array of TReal;
  TVector=array of TReal;


type
  TForm1 = class(TForm)
    Frame21: TFrame2;
    Frame31: TFrame3;
    Frame41: TFrame4;
    Splitter1: TSplitter;
    Splitter2: TSplitter;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Solve1: TMenuItem;
    Help1: TMenuItem;
    SystemSolve1: TMenuItem;
    Determinant1: TMenuItem;
    Inversmatix1: TMenuItem;
    View1: TMenuItem;
    Initialmatrix1: TMenuItem;
    Rightpart1: TMenuItem;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    SaveAs1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ExecuteErrorMesssage(Sender: TObject);
    procedure ParseErrorMesssage(Sender: TObject);
    procedure UnCheckAll;
    procedure Complectare;
    procedure SystemSolve1Click(Sender: TObject);
    procedure Determinant1Click(Sender: TObject);
    procedure Inversmatix1Click(Sender: TObject);
    procedure Help1Click(Sender: TObject);
    procedure Initialmatrix1Click(Sender: TObject);
    procedure Rightpart1Click(Sender: TObject);
    procedure ScrieFisier;
    procedure CitesteFisier;

    procedure SaveAs1Click(Sender: TObject);
    procedure Open1Click(Sender: TObject);
    procedure Save1Click(Sender: TObject);
    procedure Splitter1CanResize(Sender: TObject; var NewSize: Integer;
      var Accept: Boolean);
    procedure Splitter2CanResize(Sender: TObject; var NewSize: Integer;
      var Accept: Boolean);
    procedure Frame31Memo1Change(Sender: TObject);
    procedure Frame21Memo1Change(Sender: TObject);
  private
   Eval          : TCioinaEval;
   Vector,Sol    : TVector;
   Matrix        : TMatrix;
   ErrorFlag,
   FlagFile      : Boolean;
   Det           : TReal;
   CurentFileName: string;
   procedure LinearSolve(mtrx:TMatrix; vec:TVector);
    { Private declarations }
  public
    { Public declarations }
  end;
const Eps=1.0E-12;
var
  Form1         : TForm1;
implementation
 uses Unit5;
{$R *.dfm}
//---------------------------------------------------------------------------
procedure TForm1.ExecuteErrorMesssage(Sender: TObject);
var s,s1:string;
    i   :Integer;
begin
 with Sender as TCioinaEval do
 begin
  i:=Pos(':',ErrorMessageInfo);
  if i>0 then  s1:=' : '+Copy(ErrorMessageInfo,i+1,Length(ErrorMessageInfo)-i) else s1:='';
  if Length(s1)>256 then s1:=Copy(s1,1,256);
  s1:=LowerCase(s1);

  s:='';
  case MathException of
   EX_NONMATH:s:=' : NONMATH';
   EX_Overflow:s:=' : Overflow';
   EX_Underflow:s:=' : Underflow';
   EX_InvalidArgument:s:=' : InvalidArgument';
   EX_ZeroDivide:s:=' : ZeroDivide';
   EX_InvalidOp:s:=' : InvalidOp';
  end;

  case ErrorNumber of
   ERR_NO_MATH_EXPRESSION_WAS_PARSED:           Frame41.Memo1.Text:=('No math expression was parsed');
   ERR_VARIABLES_AND_VALUES_ARE_DIFFERENT:      Frame41.Memo1.Text:=('Variable count and value caunt do not corespond');
   ERR_MATH_EXPRESSIONS_ARRAY:                  Frame41.Memo1.Text:=('Use ''DoVectorOfMathExpressions'' for calculate a vector of math expression');
   ERR_DEF_FUNCTION_STACK_OVERFLOW:             Frame41.Memo1.Text:=('Stack overflow'+s1);
   ERR_SYSTEM_STACK_OVERFLOW:                   Frame41.Memo1.Text:=('Fatal error'+s1);
   ERR_EXECUTE:                                 Frame41.Memo1.Text:=('Execution error'+s1);
   ERR_MULTIPLY:                                Frame41.Memo1.Text:=('Invalid value for *'+s1+s);
   ERR_DIVISION:                                if MathException=EX_ZeroDivide
                                                then Frame41.Memo1.Text:=('Division by 0 ')
                                                else Frame41.Memo1.Text:=('Invalid value for /'+s1+s);
   ERR_PLUS:                                    Frame41.Memo1.Text:=('Invalid value for +'+s1+s);
   ERR_MINUS:                                   Frame41.Memo1.Text:=('Invalid value for -'+s1+s);
   ERR_POWER:                                   Frame41.Memo1.Text:=('Invalid value for ^'+s1+s);
   ERR_EQUAL:                                   Frame41.Memo1.Text:=('Invalid value for ='+s1+s);
   1..FunCount:
               if s=''
               then Frame41.Memo1.Text:=('Invalid number of function arguments for: '+ UpperCase(aStr[ErrorNumber]))
               else Frame41.Memo1.Text:=('Invalid value for '+ UpperCase(aStr[ErrorNumber])+s1+s);
   else if (ErrorNumber>FunCount)and(ErrorNumber<=FunCount+UserFunctionCount)
        then
         if s=''
         then  Frame41.Memo1.Text:=('Invalid number of function arguments for: '+UpperCase(UserFunctionName[ErrorNumber-FunCount-1]))
         else  Frame41.Memo1.Text:=('Invalid value for '+ UpperCase(UserFunctionName[ErrorNumber-FunCount-1])+s1+s)
        else Frame41.Memo1.Text:=(ErrorMessageInfo);
  end;
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.ParseErrorMesssage(Sender: TObject);
var s,s1:string;
    i :Integer;
begin
 with Sender as TCioinaEval do
 begin
  i:=Pos(':',ErrorMessageInfo);
  if i>0 then  s1:=' : '+Copy(ErrorMessageInfo,i+1,Length(ErrorMessageInfo)-i) else s1:='';
  if Length(s1)>256 then s1:=Copy(s1,1,256);
  s1:=LowerCase(s1);
  s:='';
  case MathException of
   EX_NONMATH:s:=' : NONMATH';
   EX_Overflow:s:=' : Overflow';
   EX_Underflow:s:=' : Underflow';
   EX_InvalidArgument:s:=' : InvalidArgument';
   EX_ZeroDivide:s:=' : ZeroDivide';
   EX_InvalidOp:s:=' : InvalidOp';
  end;

  case ErrorNumber of
   ERR_PARSE:                                   Frame41.Memo1.Text:=('Invalid expression'+s1);
   ERR_BAD_SYNTAX:                              Frame41.Memo1.Text:=('Syntax error'+s1);
   ERR_COMMA_SYNTAX:                            Frame41.Memo1.Text:=('Comma syntax error'+s1);
   ERR_NO_MATH_EXPRESSION_WAS_PARSED:           Frame41.Memo1.Text:=('No math expression was parsed');
   ERR_PARANTHESES_SYNTAX_ERROR:                Frame41.Memo1.Text:=('Mismatched parenthesis');
   ERR_INVALID_DERIVATIVE_VARIABLE_NAME:        Frame41.Memo1.Text:=('Invalid name of derivative variable'+s1);
   ERR_MATH_EXPRESSION_IS_EMPTY:                Frame41.Memo1.Text:=('Mathematical expression is empty');
   ERR_IDENTIFIER_CANNOT_BE_EMPTY:              Frame41.Memo1.Text:=('Identifier cannot be empty');
   ERR_IDENTIFIER_LENGTH:                       Frame41.Memo1.Text:=('Identifier length is too long'+s1);
   ERR_NOT_PASCAL_IDENTIFIER:                   Frame41.Memo1.Text:=('Invalid identifier'+s1);
   ERR_IDENTIFIER_CANNOT_BE_RESERVED_NAME:      Frame41.Memo1.Text:=('Identifier cannot be a reserved name'+s1);
   ERR_IDENTIFIER_ALREADY_EXISTS:               Frame41.Memo1.Text:=('Identifier already exists'+s1);
   ERR_DUBLICATING_USER_IDENTIFIER:             Frame41.Memo1.Text:=('Dublicating user identifier'+s1);
   ERR_UNKNOWN_EXPRESSION:                      Frame41.Memo1.Text:=('Unknown expression'+s1);
   ERR_UNKNOWN_FUNCTION:                        Frame41.Memo1.Text:=('Undefined function'+s1);
   ERR_UNKNOWN_VARIABLE:                        Frame41.Memo1.Text:=('Undefined variable'+s1);
   ERR_BAD_EXPONENTIAL_FORMAT:                  Frame41.Memo1.Text:=('Invalid exponent value'+s1);
   ERR_SET_OriginalMathExpressionString_FALSE:  Frame41.Memo1.Text:=('Set ''OriginalMathExpressionString'' to FALSE for differentiation or for Mathematica 4.1 export');
   ERR_MATH_EXPRESSION_WAS_ERASED:              Frame41.Memo1.Text:=('Mathematical expression string was erased');
   ERR_USE_VerifySyntaxSemanticsAndDerivation:  Frame41.Memo1.Text:=('Use ''VerifySyntaxSemanticsAndDerivation'' for differentiation');
   ERR_DERIVATIVE_EXPRESSION_WAS_ERASED:        Frame41.Memo1.Text:=('Derivative expression string was erased');
   ERR_VARIABLES_AND_VALUES_ARE_DIFFERENT:      Frame41.Memo1.Text:=('Variable count and value caunt do not corespond');
   ERR_MATH_EXPRESSIONS_ARRAY:                  Frame41.Memo1.Text:=('Use ''DoVectorOfMathExpressions'' for calculate a vector of math expression');
   ERR_FUNCTION_NUMBER_MUST_BE_LESS:            Frame41.Memo1.Text:=('Function number must be less'+s1);
   ERR_FUNCTION_ADDRESS_CANNOT_BE_NIL:          Frame41.Memo1.Text:=('Function address cannot be nil'+s1);
   ERR_PROTECTED_EXPRESSION:                    Frame41.Memo1.Text:=('Cannot set value for protected expression'+s1);
   ERR_DEF_FUNC_NAME:                           Frame41.Memo1.Text:=('Invalid function name'+s1);
   ERR_DEF_FUNC_DUBLICATING:                    Frame41.Memo1.Text:=('Dublicating defined function'+s1);
   ERR_DEF_FUNC_IMPLEMENTING:                   Frame41.Memo1.Text:=('Defined function was not implimented'+s1);
   ERR_DEF_FUNC_ARG_COUNT:                      Frame41.Memo1.Text:=('Invalid arguments number for defined function'+s1);
   ERR_DEF_FUNC_ARG_NAME:                       Frame41.Memo1.Text:=('Invalid argument name for defined function'+s1);
   ERR_DEF_FUNC_ARG_DUBLICATING:                Frame41.Memo1.Text:=('Dublicating argument name for defined function'+s1);
   ERR_MULTIPLY:                                Frame41.Memo1.Text:=('Invalid value for *'+s1+s);
   ERR_DIVISION:                                if MathException=EX_ZeroDivide
                                                then Frame41.Memo1.Text:=('Division by 0')
                                                else Frame41.Memo1.Text:=('Invalid value for /'+s1+s);
   ERR_PLUS:                                    Frame41.Memo1.Text:=('Invalid value for +'+s1+s);
   ERR_MINUS:                                   Frame41.Memo1.Text:=('Invalid value for -'+s1+s);
   ERR_POWER:                                   Frame41.Memo1.Text:=('Invalid value for ^'+s1+s);
   ERR_EQUAL:                                   Frame41.Memo1.Text:=('Invalid value for ='+s1+s);
   1..FunCount:
               if s=''
               then Frame41.Memo1.Text:=('Invalid number of function arguments for: '+ UpperCase(aStr[ErrorNumber]))
               else Frame41.Memo1.Text:=('Invalid value for '+ UpperCase(aStr[ErrorNumber])+s1+s);
   else if (ErrorNumber>FunCount)and(ErrorNumber<=FunCount+UserFunctionCount)
        then
         if s=''
         then  Frame41.Memo1.Text:=('Invalid number of function arguments for: '+UpperCase(UserFunctionName[ErrorNumber-FunCount-1]))
         else  Frame41.Memo1.Text:=('Invalid value for '+ UpperCase(UserFunctionName[ErrorNumber-FunCount-1])+s1+s)
        else Frame41.Memo1.Text:=(ErrorMessageInfo);
  end;
 end;
end;
//---------------------------------------------------------------------------
function MyE(Pv:PVectorPTReal;PvCount:Integer):TReal;
begin
 Result:=Exp(1);
end;
//---------------------------------------------------------------------------
function MySum(Pv:PVectorPTReal;PvCount:Integer):TReal;
var i:Integer;
begin
 Result:=0;
 for i:=1 to PvCount do
 begin
  Result:=Result+Pv^[i]^;
 end;
end;
//---------------------------------------------------------------------------
function MySqrt(Pv:PVectorPTReal;PvCount:Integer):TReal;
begin
 Result:=Sqrt(Pv^[1]^);
end;
//---------------------------------------------------------------------------
function MyRandom(Pv:PVectorPTReal;PvCount:Integer):TReal;
begin
 Result:=Random;
end;
//---------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
var v:TUserFuncArray;
begin
 DecimalSeparator:='.';
 SetLength(v,4);
 v[0].VarCount:=0;
 v[0].FuncName:='MyE';
 v[0].FuncAddress:=MyE;
 v[1].VarCount:=MaxFuncParam;
 v[1].FuncName:='MySum';
 v[1].FuncAddress:=MySum;
 v[2].VarCount:=1;
 v[2].FuncName:='MySqrt';
 v[2].FuncAddress:=MySqrt;
 v[3].VarCount:=-1;
 v[3].FuncName:='MyRandom';
 v[3].FuncAddress:=MyRandom;
 Eval:=TCioinaEval.Create(v);
 Eval.SpaceLikeMultiply:=true;
 Eval.ProtectVariablesEndedWithNumber:=true;
 Eval.ProtectVariablesEndedWithoutNumber:=true;
 Eval.OnVerifySyntaxSemanticsError:=ParseErrorMesssage;
 Eval.OnDoMathExpressionError:=ExecuteErrorMesssage;
 SetLength(v,0);
end;
//---------------------------------------------------------------------------
procedure TForm1.FormDestroy(Sender: TObject);
begin
 Eval.Free;
 SetLength(Vector,0);
 SetLength(Sol,0);
 SetLength(Matrix,0,0);
end;
//---------------------------------------------------------------------------
procedure TForm1.UnCheckAll;
begin
 SystemSolve1.Checked:=false;
 Determinant1.Checked:=false;
 Inversmatix1.Checked:=false;
 Initialmatrix1.Checked:=false;
 Rightpart1.Checked:=false;
end;
//---------------------------------------------------------------------------
procedure TForm1.Complectare;
var s,s1: string;
    i,j : Integer;
    res : PVectorPTReal;
begin
 ErrorFlag:=false;
 Frame41.Memo1.Clear;
 s1:=StringReplace(Frame21.Memo1.Text,''#$D#$A'','',[rfReplaceAll]);
 s:=StringReplace(Frame31.Memo1.Text,''#$D#$A'','',[rfReplaceAll]);
 Eval.VerifySyntaxSemantics(s,s1,false);
 if Eval.ErrorFlag
 then
 begin
  ErrorFlag:=true;
  Exit;
 end;
 if not(Eval.IsMathExpressionLinear)
 then
 begin
  ErrorFlag:=true;
  Frame41.Memo1.Text:='System of equations is not linear';
  Exit;
 end;
 for i:=1 to Eval.VariableCount do Eval.VariableArray[i].Value^:=0;
 res:=Eval.DoVectorOfMathExpressions;
 if Eval.ErrorFlag
 then
 begin
  ErrorFlag:=true;
  Exit;
 end;
 if Eval.MathExpressionCount<>Eval.VariableCount
 then
 begin
  ErrorFlag:=true;
  Frame41.Memo1.Text:='Number of variables do not corespond with number of equations';
  Exit;
 end;
 SetLength(Vector,Eval.VariableCount);
 SetLength(Sol,Eval.VariableCount);
 SetLength(Matrix,Eval.VariableCount,Eval.VariableCount);
 for i:=0 to High(Vector) do Vector[i]:=-res[i+1]^;
 for i:=1 to Eval.VariableCount do
 begin
  for j:=1 to Eval.VariableCount do
   if i=j then Eval.VariableArray[j].Value^:=1 else Eval.VariableArray[j].Value^:=0;
  res:=Eval.DoVectorOfMathExpressions;
  for j:=1 to Eval.VariableCount do Matrix[j-1,i-1]:=res[j]^+Vector[j-1];
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.LinearSolve(mtrx:TMatrix; vec:TVector);
var A : TMatrix;
    b : TVector;
    i,t,j,k,dim:Integer;
    tmp:TReal;
begin
 if ErrorFlag then Exit;
 try
  dim:=High(vec);
  SetLength(A,Length(vec),Length(vec));
  SetLength(b,Length(vec));
  Det:=1;
  for i:=0 to dim do
  begin
   for j:=0 to dim do A[i,j]:=mtrx[i,j];
   b[i]:=vec[i];
   Sol[i]:=Nan;
  end;
  for k:=0 to dim-1 do
  begin
   t:=k;
   tmp:=Abs(A[k,k]);
   for i:=k+1 to dim do
    if tmp<Abs(A[i,k])
    then
    begin
     t:=i;
     tmp:=Abs(A[i,k]);
    end;
   if t=k
   then Det:=Det*A[k,k]
   else
    begin
     for i:=k to dim do
     begin
      tmp:=A[k,i];
      A[k,i]:=A[t,i];
      A[t,i]:=tmp;
     end;
     tmp:=b[k];
     b[k]:=b[t];
     b[t]:=tmp;
     Det:=-Det*A[k,k];
    end;
   if IsZero(Det,Eps)
   then
   begin
    ErrorFlag:=true;
    ShowMessage('System is bad conditioned');
    Exit;
   end;
   for i:=k+1 to dim do
   begin
    b[i]:=b[i]-A[i,k]*b[k]/A[k,k];
    for j:=dim downto k do A[i,j]:=A[i,j]-A[i,k]*A[k,j]/A[k,k];
   end;
  end;
  Det:=Det*A[dim,dim];
  if IsZero(Det,Eps)
  then
  begin
   ErrorFlag:=true;
   ShowMessage('System is bad conditioned');
   Exit;
  end;
  Sol[dim]:=b[dim]/A[dim,dim];
  for i:=dim-1 downto 0 do
  begin
   tmp:=0;
   for j:=i+1 to dim do tmp:=tmp+A[i,j]*Sol[j];
   Sol[i]:=(b[i]-tmp)/A[i,i];
  end;
  SetLength(A,0,0);
  SetLength(b,0);
 except
  on E:Exception do
   begin
    ErrorFlag:=true;
    ShowMessage(E.Message);
   end;
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.SystemSolve1Click(Sender: TObject);
var i:Integer;
begin
 UnCheckAll;
 Complectare;
 LinearSolve(Matrix,Vector);
 if ErrorFlag then Exit;
 Frame41.Memo1.Lines.Add('Solution:');
 for i:=1 to Eval.VariableCount do
 Frame41.Memo1.Lines.Add(Eval.VariableName[i]+' = '+FloatToStr(Sol[i-1]));
 SystemSolve1.Checked:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.Determinant1Click(Sender: TObject);
begin
 UnCheckAll;
 Complectare;
 LinearSolve(Matrix,Vector);
 if ErrorFlag then Exit;
 Frame41.Memo1.Lines.Add('Determinant = '+FloatToStr(Det));
 Determinant1.Checked:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.Inversmatix1Click(Sender: TObject);
var i,j:Integer;
    s:string;
begin
 UnCheckAll;
 Complectare;
 for i:=0 to High(Vector) do
 begin
  s:='';
  for j:=0 to High(Vector) do
   if i=j then Vector[j]:=1 else Vector[j]:=0;
  LinearSolve(Matrix,Vector);
  if ErrorFlag then Exit;
  if i=0 then  Frame41.Memo1.Lines.Add('Inverse  matrix :');
  for j:=0 to High(Vector) do  s:=s+FloatToStrF(Sol[j],ffExponent,14,1)+'   ';
  Frame41.Memo1.Lines.Add(s);
 end;
 Inversmatix1.Checked:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.Help1Click(Sender: TObject);
var i:Integer;
begin
 Form5.Memo1.Clear;
 Form5.Memo1.Lines.Add('This application is absolutely free of charge.');
 Form5.Memo1.Lines.Add('I dedicate this work to moldavian mathematician  Leonid Gherman.');
 Form5.Memo1.Lines.Add('');
 Form5.Memo1.Lines.Add('BUILT-IN FUNCTIONS');
 Form5.Memo1.Lines.Add('====================================================');
 for i:=0 to Eval.TotalFunctionCount do
 Form5.Memo1.Lines.Add(IntToStr(i)+'.  '+Eval.BuiltInFunctionInfo[i]);
 Form5.Memo1.Lines.Add('====================================================');
 Form5.Memo1.Lines.Add('Owner Info = '+TCioinaEval.OwnerInfo);
 Form5.Memo1.Lines.Add('Version Info = Linear System Solver 1.0.0');
 Form5.Memo1.Lines.Add('Type Info = '+TCioinaEval.TypeInfo);
 Form5.Memo1.Lines.Add('URL = http://groups.yahoo.com/group/applied_mathematics/');
 Form5.Show;
end;
//---------------------------------------------------------------------------
procedure TForm1.Initialmatrix1Click(Sender: TObject);
var i,j:Integer;
    s:string;
begin
 UnCheckAll;
 Complectare;
 if ErrorFlag then Exit;
 Frame41.Memo1.Lines.Add('Initial matrix:');
 for i:=0 to High(Vector) do
 begin
  s:='';
  for j:=0 to High(Vector) do
   s:=s+FloatToStrF(Matrix[i,j],ffExponent,14,1)+'   ';
  Frame41.Memo1.Lines.Add(s);
 end;
 Initialmatrix1.Checked:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.Rightpart1Click(Sender: TObject);
var j:Integer;
begin
 UnCheckAll;
 Complectare;
 if ErrorFlag then Exit;
 Frame41.Memo1.Lines.Add('Right part:');
 for j:=0 to High(Vector) do Frame41.Memo1.Lines.Add(FloatToStr(Vector[j]));
 Rightpart1.Checked:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.ScrieFisier;
var
    s           : string;
    i,j         : Integer;
    fFile       : TextFile;
begin
 if FlagFile
 then
 try
  AssignFile(fFile,CurentFileName);
  Rewrite(fFile);
  s:=StringReplace(Frame21.Memo1.Text,''#$D#$A'','',[rfReplaceAll]);
  Writeln(fFile,'List of variables');
  Writeln(fFile,'{');
  Writeln(fFile,s);
  Writeln(fFile,'}');
  Writeln(fFile,'');
  Writeln(fFile,'System of linear equatins');
  Writeln(fFile,'{');
  Writeln(fFile,Frame31.Memo1.Text);
  Writeln(fFile,'}');
  Caption:=CurentFileName;
 finally
  try
   CloseFile(fFile);
  except
  end;
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.CitesteFisier;
var
    s,s1,s2       : string;
    i,j,k         : Integer;
    fFile         : TextFile;
    ErrorFlg,l    : Boolean;
begin
 if FlagFile
 then
 try
  l:=false;
  s1:='';
  s2:='';
  j:=0;
  k:=0;
  ErrorFlg:=false;
  AssignFile(fFile,CurentFileName);
  Reset(fFile);
  while not(Eof(fFile))and(not(ErrorFlg))do
  begin
   i:=1;
   Readln(fFile,s);
   if (l)and(j=2)and(Trim(s)<>'') then s:=s+''#$D#$A'';
   while (i<=Length(s))and(not(ErrorFlg))do
   begin
    if s[i]='}'
    then
    begin
     Inc(k);
     l:=false;
    end;
    if s[i]='{'
    then
    begin
     Inc(j);
     l:=true;
    end
    else
     if l
     then
     case j of
      1: s1:=s1+s[i];
      2: s2:=s2+s[i];
     end;
    if j<k then ErrorFlg:=true;
    Inc(i);
   end;
  end;
  if (j<>k)or(j<>2)or(ErrorFlg)
  then
  begin
   FlagFile:=false;
   ShowMessage('Bad file format');
   Save1.Enabled:=false;
   Exit;
  end;
 s:=Trim(StringReplace(s1,''#$D#$A'','',[rfReplaceAll]));
 s:=Trim(StringReplace(s,' ','',[rfReplaceAll]));
 Frame21.Memo1.Text:=s;
 Frame31.Memo1.Text:=s2;
 Caption:=CurentFileName;
 Frame41.Memo1.Clear;
 UnCheckAll;
 finally
  try
   CloseFile(fFile);
  except
  end;
 end;
 if not(FlagFile) then Save1.Enabled:=false else Save1.Enabled:=true;
end;
//---------------------------------------------------------------------------
procedure TForm1.SaveAs1Click(Sender: TObject);
begin
 Caption:='System of linear equations solver';
 if SaveDialog1.Execute
 then
 begin
  FlagFile:=true;
  CurentFileName:=SaveDialog1.FileName;
  ScrieFisier;
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.Open1Click(Sender: TObject);
begin
 Caption:='System of linear equations solver';
 if OpenDialog1.Execute
 then
 begin
  FlagFile:=true;
  CurentFileName:=OpenDialog1.FileName;
  CitesteFisier;
 end;
end;
//---------------------------------------------------------------------------
procedure TForm1.Save1Click(Sender: TObject);
begin
 if FlagFile then ScrieFisier;
end;

procedure TForm1.Splitter1CanResize(Sender: TObject; var NewSize: Integer;
  var Accept: Boolean);
begin
 if NewSize<50 then NewSize:=50;
end;

procedure TForm1.Splitter2CanResize(Sender: TObject; var NewSize: Integer;
  var Accept: Boolean);
begin
  if NewSize<50 then NewSize:=50;
end;

procedure TForm1.Frame31Memo1Change(Sender: TObject);
begin
 Frame41.Memo1.Clear;
end;

procedure TForm1.Frame21Memo1Change(Sender: TObject);
begin
 Frame41.Memo1.Clear;
end;

end.
