unit Unit1;

{$MODE Delphi}

interface

uses
  LCLIntf, LCLType, LMessages, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, StdCtrls, ComCtrls, CheckLst, ExtCtrls, Buttons,
  FileUtil, SynEdit, SynHighlighterAny,  StrUtils, erg_base,
  erg_types, SynHighlighterPosition, unit4, unit5, unit6;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button4: TButton;
    Button5: TButton;
    Memo1: TMemo;
    Label2: TLabel;
    Edit1: TEdit;
    Label3: TLabel;
    Panel2: TPanel;
    Panel4: TPanel;
    Panel5: TPanel;
    SaveDialog1: TSaveDialog;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    Label1: TLabel;
    SpeedButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    SpeedButton5: TSpeedButton;
    SpeedButton6: TSpeedButton;
    Panel1: TPanel;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    RadioButton4: TRadioButton;
    RadioButton5: TRadioButton;
    RadioButton6: TRadioButton;
    RadioButton7: TRadioButton;
    CheckListBox1: TCheckListBox;
    OpenDialog1: TOpenDialog;
    ListBox1: TListBox;
    Button2: TButton;
    Panel3: TPanel;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Label4: TLabel;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Edit5: TEdit;
    Edit6: TEdit;
    Edit7: TEdit;
    Button3: TButton;
    SynAnySyn1: TSynAnySyn;
    SynEdit1: TSynEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
    procedure RadioButton3Click(Sender: TObject);
    procedure RadioButton4Change(Sender: TObject);
    procedure RadioButton4Click(Sender: TObject);
    procedure RadioButton5Click(Sender: TObject);
    procedure RadioButton6Click(Sender: TObject);
    procedure RadioButton7Click(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure CheckListBox1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure Edit2Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure CheckListBox1ClickCheck(Sender: TObject);
    procedure CheckListBox1Exit(Sender: TObject);
    procedure Memo1Change(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure SpeedButton1Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
    procedure SpeedButton4Click(Sender: TObject);
    procedure SpeedButton5Click(Sender: TObject);
    procedure SpeedButton6Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure SynEdit1Change(Sender: TObject);
    procedure SynEdit1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure GoToExpression(s: String; BackButtonPressed: Boolean=false);
procedure SaveAllFiles;
procedure LoadAllFiles;
var
  Form1: TForm1;
  ShowFirstTime: Boolean;
  selConstant, selTracer, selAuxiliary, selProcess, selElement, selCElement: Integer;
  TempFileName: String;
  SynEditBusy: Boolean;
  ChangedCheck: Boolean;
  BackList: TStringList; BackListPosition: Integer;
  Highlighter: SynHighlighterPosition.TSynPositionHighlighter;
  InconsistencyString: String;

implementation

uses Unit3;

{$R *.lfm}

function IsStandardChar(c: Char):Boolean;
begin
  if (ord(c)>=ord(char('a'))) and (ord(c)<=ord(char('z'))) then
    result:=true
  else if (ord(c)>=ord(char('A'))) and (ord(c)<=ord(char('Z'))) then
    result:=true
  else if (ord(c)>=ord(char('0'))) and (ord(c)<=ord(char('9'))) then
    result:=true
  else if (ord(c)=ord(char('_'))) or (ord(c)=ord(char('$')))  then
    result:=true
  else
    result:=false;
end;

procedure PaintTheWord(myWord: String; lines: TStrings; tk: TtkTokenKind; Highlighter: TSynPositionHighlighter; matchCase: Boolean=false);
var
  i: Integer;
  text, lmyword: String;
  found: Boolean;
  myPos: Integer;
  c: Char;
begin
  for i:=0 to lines.Count-1 do
  begin
    text:=lines[i];
    if matchCase=false then text:=lowercase(text);
    myPos:=0;
    lmyWord:=myWord;
    if matchCase=false then lmyWord:=lowercase(lmyWord);
    while pos(lmyWord,text)>0 do
    begin
      found:=true;
      if pos(lmyWord,text)>1 then
      begin
        c:=copy(text,pos(lmyWord,text)-1,1)[1];
        if IsStandardChar(c) then found:=false;
      end;
      if pos(lmyWord,text)+length(myWord)-1<length(text) then
      begin
        c:=copy(text,pos(lmyWord,text)+length(myWord),1)[1];
        if IsStandardChar(c) then found:=false;
      end;
      if found then
      begin
        Highlighter.AddToken(i,myPos+pos(lmyWord,text)-1,tkText);
        Highlighter.AddToken(i,myPos+pos(lmyWord,text)-1+length(myWord),tk);
      end;
      myPos:=myPos+pos(lmyWord,text)+length(myWord)-2;
      text:=copy(text,pos(lmyWord,text)+length(myWord)-1,length(text));
      if (length(myWord)=1) and (pos(lmyWord,text)=1) then
        if myWord='_' then text:='a'+copy(text,2,length(text))
          else text:='_'+copy(text,2,length(text));
    end;
  end;
end;

procedure PaintTheWords;
var
  tkConstant, tkTracer, tkAuxiliary, tkProcess, tkElement, tkCElement, tkKeyword: TtkTokenKind;
  i, line: Integer;
  s: String;
begin
  // add some attributes
  tkConstant:=Highlighter.CreateTokenID('constant',clBlack,Form1.RadioButton1.Color,[]);
  tkTracer:=Highlighter.CreateTokenID('tracer',clBlack,Form1.RadioButton2.Color,[]);
  tkAuxiliary:=Highlighter.CreateTokenID('auxiliary',clBlack,Form1.RadioButton3.Color,[]);
  tkProcess:=Highlighter.CreateTokenID('process',clBlack,Form1.RadioButton4.Color,[]);
  tkElement:=Highlighter.CreateTokenID('element',clBlack,Form1.RadioButton5.Color,[]);
  tkCElement:=Highlighter.CreateTokenID('celement',clBlack,clSilver,[]);
  tkKeyword:=Highlighter.CreateTokenID('keyword',clBlack,clSilver,[]);

  for line:=0 to Form1.SynEdit1.Lines.Count do
    Highlighter.ClearTokens(line);
  for i:=0 to length(constants)-1 do
    PaintTheWord(constants[i].name,Form1.SynEdit1.lines,tkConstant,Highlighter);
  for i:=0 to length(tracers)-1 do
    PaintTheWord(tracers[i].name,Form1.SynEdit1.lines,tkTracer,Highlighter);
  for i:=0 to length(auxiliaries)-1 do
    PaintTheWord(auxiliaries[i].name,Form1.SynEdit1.lines,tkAuxiliary,Highlighter);
  for i:=0 to length(processes)-1 do
    PaintTheWord(processes[i].name,Form1.SynEdit1.lines,tkProcess,Highlighter);
  for i:=0 to length(elements)-1 do
    PaintTheWord(elements[i].name,Form1.SynEdit1.lines,tkElement,Highlighter);
  for i:=0 to length(celements)-1 do
    PaintTheWord(celements[i].color+'_'+celements[i].element,Form1.SynEdit1.lines,tkCElement,Highlighter);
  for i:=0 to length(keywords)-1 do
    PaintTheWord(keywords[i],Form1.SynEdit1.lines,tkKeyword,Highlighter,true);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  F: TextFile;
  s: string;
begin
  AssignFile(F,TempFileName);
  rewrite(F);
  if RadioButton1.Checked then //constants
    WriteConstantsHeader(F)
  else if RadioButton2.Checked then //tracers
    WriteTracersHeader(F)
  else if RadioButton3.Checked then //auxiliaries
    WriteAuxiliariesHeader(F)
  else if RadioButton4.Checked then //processes
    WriteProcessesHeader(F)
  else if RadioButton5.Checked then //elements
    WriteElementsHeader(F)
  else if RadioButton6.Checked then //celements
    WriteCElementsHeader(F)
  else if RadioButton7.Checked then //modelinfos
    WriteModelinfosHeader(F);
  closefile(F);

  Form5.Memo1.lines.clear;
  AssignFile(F,TempFileName);
  reset(F);
  readln(F,s); readln(F,s); readln(F,s);
  while not EOF(F) do
  begin
    readln(F,s);
    Form5.Memo1.Lines.add(s);
  end;
  closefile(F);

  Form5.ShowModal;
end;

procedure LoadAllFiles;
var
  s: String;
  err: Integer;
begin
  s:=ExtractFilePath(Form1.OpenDialog1.FileName);
  if FileExistsUTF8(s+'/modelinfos.txt') { *Converted from FileExists*  } then
  begin
    TempFileName:=s+'/temp.txt';

    err:=LoadModelInfos(s+'/modelinfos.txt');
    if err=1 then MessageDlg('Could not load modelinfos file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the modelinfos file contained errors.',mtWarning,[mbOk],0);

    err:=LoadConstants(s+'/constants.txt');
    if err=1 then MessageDlg('Could not load constants file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the constants file contained errors.',mtWarning,[mbOk],0);

    err:=LoadElements(s+'/elements.txt');
    if err=1 then MessageDlg('Could not load elements file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the elements file contained errors.',mtWarning,[mbOk],0);

    err:=LoadTracers(s+'/tracers.txt');
    if err=1 then MessageDlg('Could not load tracers file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the tracers file contained errors.',mtWarning,[mbOk],0);

    err:=LoadAuxiliaries(s+'/auxiliaries.txt');
    if err=1 then MessageDlg('Could not load auxiliaries file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the auxiliaries file contained errors.',mtWarning,[mbOk],0);

    err:=LoadProcesses(s+'/processes.txt');
    if err=1 then MessageDlg('Could not load processes file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the processes file contained errors.',mtWarning,[mbOk],0)
    else if err=3 then MessageDlg('The processes file contained an invalid equation.',mtWarning,[mbOk],0)
    else if err=4 then MessageDlg('The processes file contained an invalid limitation.',mtWarning,[mbOk],0);

    err:=LoadCElements(s+'/celements.txt');
    if err=1 then MessageDlg('Could not load celements file.',mtError,[mbOk],0)
    else if err=2 then MessageDlg('Some lines of the celements file contained errors.',mtWarning,[mbOk],0);

    InconsistencyString:=GenerateIndexes;
    if InconsistencyString<>'' then
      Form1.Panel5.Visible:=true
    else
      Form1.Panel5.Visible:=false;
  end
  else Halt;
end;

procedure SaveAllFiles;
var
  s: String;
begin
  s:=ExtractFilePath(Form1.OpenDialog1.FileName);
  if FileExistsUTF8(s+'/modelinfos.txt') { *Converted from FileExists*  } then
  begin
    SaveModelInfos(s+'modelinfos.txt');
    SaveConstants(s+'constants.txt');
    SaveElements(s+'elements.txt');
    SaveTracers(s+'tracers.txt');
    SaveAuxiliaries(s+'auxiliaries.txt');
    SaveProcesses(s+'processes.txt');
    SaveCElements(s+'celements.txt');
  end
  else Halt;
end;


procedure LoadTheTracer(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleTracer(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') and
       (copy(trim(lowercase(s)),1,8)<>'isoutput') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=tracers[i].name;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(tracers[i].comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
  Label3.caption:='tracer';
  if tracers[i].vertLoc=1 then Label3.caption:='bottom '+Label3.caption;
  if tracers[i].vertLoc=2 then Label3.caption:='surface '+Label3.caption;
  if (tracers[i].vertSpeed<>'0') and (tracers[i].vertSpeed<>'0.0') then Label3.caption:='moving '+Label3.caption;
  if tracers[i].isActive=0 then Label3.caption:='virtual '+Label3.caption;
  if tracers[i].isCombined=1 then Label3.caption:='combined '+Label3.caption;
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheAuxiliary(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleAuxiliary(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') and
       (copy(trim(lowercase(s)),1,8)<>'isoutput') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=auxiliaries[i].name;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(auxiliaries[i].comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
  Label3.caption:='auxiliary variable';
  if auxiliaries[i].vertLoc=1 then Label3.caption:='bottom '+Label3.caption;
  if auxiliaries[i].vertLoc=2 then Label3.caption:='surface '+Label3.caption;
  if auxiliaries[i].isUsedElsewhere=1 then Label3.caption:=Label3.caption+' for external use';
  if auxiliaries[i].calcAfterProcesses=1 then Label3.caption:=Label3.caption+', calculated after the process rates';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheProcess(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleProcess(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') and
       (copy(trim(lowercase(s)),1,8)<>'isoutput') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=processes[i].name;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(processes[i].comment,'\\',chr(13)+chr(10)));

  //check if this process is conservative
  if InconsistencyString='' then
  begin
    if ProcessIsConservative(i) then
      Form1.Panel4.Color:=Form1.Color
    else
      Form1.Panel4.Color:=Form1.Edit1.Color;
  end
  else
    Form1.Panel4.Visible:=false;

  //write Label3
  with form1 do
  begin
  Label3.caption:='process';
  if processes[i].vertLoc=1 then Label3.caption:='bottom '+Label3.caption;
  if processes[i].vertLoc=2 then Label3.caption:='surface '+Label3.caption;
  if processes[i].isActive=0 then Label3.caption:='inactive '+Label3.caption;
  if (CheckListBox1.ItemEnabled[i]=false) and (processes[i].isActive=1) then Label3.caption:=Label3.caption+', deactivated by settings in modelinfos';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheConstant(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleConstant(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=Constants[i].name;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(Constants[i].comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
    Label3.caption:='constant';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheElement(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleElement(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=Elements[i].name;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(Elements[i].comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
    Label3.caption:='element';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheCElement(i: Integer);
var
  F: TextFile;
  s: String;
begin
 if i<0 then
 begin
  SynEditBusy:=true;
  Form1.Edit1.Text:='';
  Form1.SynEdit1.Lines.Clear;
  Form1.Memo1.Clear;
  SynEditBusy:=false;
 end
 else
 begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the tracer to a temporary file
  AssignFile(F,TempFileName);
  rewrite(F);
  SaveSingleCElement(F,i);
  closefile(F);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,4)<>'name') and
       (copy(trim(lowercase(s)),1,7)<>'comment') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:=CElements[i].color+'_'+CElements[i].element;
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(CElements[i].comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
    Label3.caption:='colored element';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
 end;
end;

procedure LoadTheModelinfos;
var
  F: TextFile;
  s: String;
begin
  SynEditBusy:=true;
  Form1.SynEdit1.Font.Color:=clWhite;

  //first, export the modelinfos to a temporary file
  SaveModelInfos(tempfilename);

  //now, load the contents of the exported file to the SynEdit
  Form1.SynEdit1.Lines.Clear;
  AssignFile(F,TempFileName);
  reset(F);
  while not EOF(F) do
  begin
    readln(F,s);
    if (copy(trim(lowercase(s)),1,1)<>'!') and
       (copy(trim(lowercase(s)),1,1)<>'*') and
       (copy(trim(lowercase(s)),1,7)<>'comment') then
    Form1.SynEdit1.Lines.Add(s);
  end;
  closefile(F);
  Form1.SynEdit1.Font.Color:=clBlack;
  //apply the painting
  PaintTheWords;

  //put name and comment to their places
  Form1.Edit1.text:='';
  Form1.Memo1.Lines.Clear;
  Form1.Memo1.Lines.Add(AnsiReplaceStr(Modelinfos.comment,'\\',chr(13)+chr(10)));

  //write Label3
  with form1 do
  begin
    Label3.caption:='modelinfos';
  end;

  //finally, delete the file
  DeleteFileUTF8(tempFileName); { *Converted from DeleteFile*  }
  SynEditBusy:=false;
end;

procedure AppendToBackList(s: String);
var i: Integer;
begin
  if BackListPosition>=0 then
    if trim(lowercase(s))= trim(lowercase(BackList[BackListPosition])) then
      exit;
  BackListPosition:=BackListPosition+1;
  for i:=BackList.Count-1 downto BackListPosition do
    BackList.Delete(i);
  BackList.Add(s);
end;

procedure MyListBox1Click(BackButtonPressed: Boolean=false);
begin
 with Form1 do
 begin
  if RadioButton1.checked then //constant selected
  begin
    selConstant:=ListBox1.ItemIndex;
    LoadTheConstant(selConstant);
    if selConstant>=0 then
      if not BackButtonPressed then AppendToBackList(constants[selConstant].name);
  end
  else if RadioButton5.Checked then //element selected
  begin
    selElement:=ListBox1.ItemIndex;
    LoadTheElement(selElement);
    if selElement>=0 then
      if not BackButtonPressed then AppendToBackList(elements[selElement].name);
  end
  else if RadioButton6.Checked then //colored element selected
  begin
    selCElement:=ListBox1.ItemIndex;
    LoadTheCElement(selCElement);
    if selCElement>=0 then
      if not BackButtonPressed then AppendToBackList(CElements[selCElement].color+'_'+CElements[selCElement].element);
  end;
 end;
end;

procedure MyCheckListBox1Click(BackButtonPressed: Boolean=false);
begin
 with Form1 do
 begin
  if RadioButton2.checked then //tracer selected
  begin
    selTracer:=CheckListBox1.ItemIndex;
    LoadTheTracer(selTracer);
    if selTracer>=0 then
      if not BackButtonPressed then AppendToBackList(tracers[selTracer].name);
  end
  else if RadioButton3.Checked then //auxiliary selected
  begin
    selAuxiliary:=CheckListBox1.ItemIndex;
    LoadTheAuxiliary(selAuxiliary);
    if selAuxiliary>=0 then
      if not BackButtonPressed then AppendToBackList(Auxiliaries[selAuxiliary].name);
  end
  else if RadioButton4.Checked then //process selected
  begin
    selProcess:=CheckListBox1.ItemIndex;
    LoadTheProcess(selProcess);
    if selProcess>=0 then
      if not BackButtonPressed then AppendToBackList(processes[selProcess].name);
  end;
 end;
end;

procedure AfterRadioButton(BackButtonPressed: Boolean=false);
var
  i: Integer;
  s, s1: String;
  oldSynEditBusy: Boolean;
begin
  oldSynEditBusy:=SynEditBusy;
  SynEditBusy:=true;
  with Form1 do
  begin
    CheckListBox1.Items.Clear;
    ListBox1.Items.Clear;
    Label1.Visible:=true; SpeedButton3.Visible:=true; SpeedButton4.Visible:=true; SpeedButton5.Visible:=true; SpeedButton6.Visible:=true;
    Button3.Visible:=false;
    if RadioButton1.checked then //Constants selected;
    begin
      CheckListBox1.Visible:=false;
      ListBox1.Visible:=true;
      ListBox1.Color:=RadioButton1.Color; Edit1.Color:=RadioButton1.Color; Button2.Visible:=true;
      Panel4.Visible:=false;
      for i:=0 to length(Constants)-1 do
      begin
        ListBox1.Items.Add(Constants[i].name);
      end;
      if ListBox1.Items.Count > selConstant then ListBox1.ItemIndex:=selConstant else ListBox1.ItemIndex:=-1;
      MyListBox1Click(BackButtonPressed);
    end
    else if RadioButton2.checked then //tracers selected;
    begin
      Button3.Visible:=true;
      CheckListBox1.Visible:=true;
      ListBox1.Visible:=false;
      CheckListBox1.Color:=RadioButton2.Color; Edit1.Color:=RadioButton2.Color; Button2.Visible:=true;
      Panel4.Visible:=false;
      for i:=0 to length(tracers)-1 do
      begin
        CheckListBox1.Items.Add(tracers[i].name);
        if tracers[i].isOutput>0 then CheckListBox1.Checked[i]:=true else CheckListBox1.Checked[i]:=false;
        if tracers[i].isActive>0 then CheckListBox1.ItemEnabled[i]:=true else
        begin
          CheckListBox1.ItemEnabled[i]:=false;
          CheckListBox1.Checked[i]:=false;
        end;
      end;
      if CheckListBox1.Items.Count > selTracer then CheckListBox1.ItemIndex:=selTracer else CheckListBox1.ItemIndex:=-1;
      CheckListBox1.Repaint;
      MyCheckListBox1Click(BackButtonPressed);
    end
    else if RadioButton3.checked then //Auxiliaries selected;
    begin
      CheckListBox1.Visible:=true;
      ListBox1.Visible:=false;
      CheckListBox1.Color:=RadioButton3.Color; Edit1.Color:=RadioButton3.Color; Button2.Visible:=true;
      Panel4.Visible:=false;
      for i:=0 to length(Auxiliaries)-1 do
      begin
        CheckListBox1.Items.Add(Auxiliaries[i].name);
        if Auxiliaries[i].isOutput>0 then CheckListBox1.Checked[i]:=true else CheckListBox1.Checked[i]:=false;
        CheckListBox1.ItemEnabled[i]:=true;
      end;
      if CheckListBox1.Items.Count > selAuxiliary then CheckListBox1.ItemIndex:=selAuxiliary else CheckListBox1.ItemIndex:=-1;
      MyCheckListBox1Click(BackButtonPressed);
    end
    else if RadioButton4.checked then //Processes selected;
    begin
      CheckListBox1.Visible:=true;
      ListBox1.Visible:=false;
      CheckListBox1.Color:=RadioButton4.Color; Edit1.Color:=RadioButton4.Color; Button2.Visible:=true;
      Panel4.Visible:=true;
      for i:=0 to length(Processes)-1 do
      begin
        CheckListBox1.Items.Add(Processes[i].name);
        if Processes[i].isOutput>0 then CheckListBox1.Checked[i]:=true else CheckListBox1.Checked[i]:=false;
        CheckListBox1.ItemEnabled[i]:=true;
        if Processes[i].isActive=0 then CheckListBox1.ItemEnabled[i]:=false;
        s:=ModelInfos.inactiveProcessTypes;
        while s<>'' do
        begin
          s1:=SemiItem(s);
          if trim(lowercase(s1))=trim(lowercase(Processes[i].processType)) then
          begin
            CheckListBox1.ItemEnabled[i]:=false;
            CheckListBox1.Checked[i]:=false;
          end;
        end;
      end;
      if CheckListBox1.Items.Count > selProcess then CheckListBox1.ItemIndex:=selProcess else CheckListBox1.ItemIndex:=-1;
      MyCheckListBox1Click(BackButtonPressed);
    end
    else if RadioButton5.checked then //Elements selected;
    begin
      CheckListBox1.Visible:=false;
      ListBox1.Visible:=true;
      ListBox1.Color:=RadioButton5.Color; Edit1.Color:=RadioButton5.Color; Button2.Visible:=true;
      Panel4.Visible:=false;
      for i:=0 to length(Elements)-1 do
      begin
        ListBox1.Items.Add(Elements[i].name);
      end;
      if ListBox1.Items.Count > selElement then ListBox1.ItemIndex:=selElement else ListBox1.ItemIndex:=-1;
      MyListBox1Click(BackButtonPressed);
    end
    else if RadioButton6.checked then //CElements selected;
    begin
      CheckListBox1.Visible:=false;
      ListBox1.Visible:=true;
      ListBox1.Color:=clWhite; Edit1.Color:=clWhite; Button2.Visible:=false;
      Panel4.Visible:=false;
      for i:=0 to length(CElements)-1 do
      begin
        ListBox1.Items.Add(CElements[i].color+'_'+CElements[i].element);
      end;
      if ListBox1.Items.Count > selCElement then ListBox1.ItemIndex:=selCElement else ListBox1.ItemIndex:=-1;
      MyListBox1Click(BackButtonPressed);
    end
    else if RadioButton7.checked then //Modelinfos selected;
    begin
      CheckListBox1.Visible:=false;
      ListBox1.Visible:=false;
      Edit1.Color:=clSilver; Button2.Visible:=false;
      Label1.Visible:=false; SpeedButton3.Visible:=false; SpeedButton4.Visible:=false; SpeedButton5.Visible:=false; SpeedButton6.Visible:=false;
      Panel4.Visible:=false;
      LoadTheModelinfos;
            if not BackButtonPressed then AppendToBackList('modelinfos');
    end
  end;
  SynEditBusy:=OldSynEditBusy;
end;

procedure GoToExpression(s: String; BackButtonPressed: Boolean=false);
//will seek if this string is the name of a constant, tracer, ... and load it
var
  i, num: Integer;
begin
  num:=-1;

  with Form1 do
  begin

  for i:=0 to length(elements)-1 do
    if trim(lowercase(elements[i].name))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selElement:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton5.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  for i:=0 to length(processes)-1 do
    if trim(lowercase(processes[i].name))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selProcess:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton4.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  for i:=0 to length(auxiliaries)-1 do
    if trim(lowercase(auxiliaries[i].name))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selAuxiliary:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton3.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  for i:=0 to length(tracers)-1 do
    if trim(lowercase(tracers[i].name))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selTracer:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton2.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  for i:=0 to length(constants)-1 do
    if trim(lowercase(constants[i].name))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selConstant:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton1.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  for i:=0 to length(celements)-1 do
    if trim(lowercase(celements[i].color+'_'+celements[i].element))=trim(lowercase(s)) then
      num:=i;
  if num<>-1 then
  begin
    selCElement:=num;
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton6.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  if trim(lowercase(s))='modelinfos' then
  begin
    RadioButton1.checked:=false; RadioButton2.checked:=false;RadioButton3.checked:=false; RadioButton4.checked:=false; RadioButton5.checked:=false; RadioButton6.checked:=false; RadioButton7.checked:=false;
    RadioButton6.checked:=true;
    AfterRadioButton(BackButtonPressed);
    exit;
  end;

  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  if ShowFirstTime then
  begin
    ShowFirstTime:=false;

    Panel3.Left:=0;
    panel4.Left:=640;
    Panel3.Visible:=false;
    Edit2.Color:=RadioButton1.Color;
    Edit3.Color:=RadioButton2.Color;
    Edit4.Color:=RadioButton3.Color;
    Edit5.Color:=RadioButton4.Color;
    Edit6.Color:=RadioButton5.Color;

    Form6.ShowModal;
    If Form6.ModalResult=1 then
    begin
      If OpenDialog1.Execute then
      begin
        selConstant:=0;
        selTracer:=0;
        selAuxiliary:=0;
        selProcess:=0;
        selElement:=0;
        selCElement:=0;
        LoadAllFiles;
        AfterRadioButton;
      end
      else
        Application.Terminate;
    end
    else if Form6.ModalResult=3 then
    begin
      If SaveDialog1.Execute then
      begin
        OpenDialog1.FileName:=SaveDialog1.FileName;
        SaveAllFiles;
        selConstant:=0;
        selTracer:=0;
        selAuxiliary:=0;
        selProcess:=0;
        selElement:=0;
        selCElement:=0;
        LoadAllFiles;
        AfterRadioButton;
      end
      else
        Application.Terminate;
    end
    else
      Application.Terminate;
  end;
  SynEditBusy:=false;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  SynEditBusy:=true;
  ShowFirstTime:=true;
  ChangedCheck:=false;
  BackList:=TStringList.Create;
  BackListPosition:=-1;
  // create highlighter
  Highlighter:=TSynPositionHighlighter.Create(Self);
  SynEdit1.Highlighter:=Highlighter;
  erg_base.initKeywords;
end;

procedure TForm1.RadioButton1Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton2Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton3Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton4Change(Sender: TObject);
begin

end;

procedure TForm1.RadioButton4Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton5Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton6Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.RadioButton7Click(Sender: TObject);
begin
  AfterRadioButton;
end;

procedure TForm1.ListBox1Click(Sender: TObject);
begin
  MyListBox1Click;
end;

procedure TForm1.CheckListBox1Click(Sender: TObject);
begin
  MyCheckListBox1Click;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  Panel3.Visible:=false;
  Panel2.Visible:=true;
  ListBox1Click(sender);
  CheckListBox1Click(sender);
end;

procedure TForm1.Edit2Click(Sender: TObject);
begin
  SynEdit1.SelText:='const';
  SynEdit1.SetFocus;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  F: TextFile;
  i: Integer;
  s: String;
begin
  AssignFile(F,TempFileName);
  rewrite(F);
  if (RadioButton6.Checked=false) and (RadioButton7.Checked=false) then
    writeln(F,'name='+Edit1.text);
  writeln(F,SynEdit1.text);
  s:='';
  for i:=0 to Memo1.Lines.Count do
  begin
    if Memo1.Lines[i]<>'' then
    begin
      if i>0 then s:=s+'\\';
      s:=s+Memo1.Lines[i];
    end;
  end;
  if RadioButton2.Checked or RadioButton3.Checked or RadioButton4.Checked then
    if CheckListBox1.Checked[CheckListBox1.ItemIndex] then
      writeln(F,'isOutput=1')
    else
      writeln(F,'isOutput=0');
  writeln(F,'comment='+s);
  closefile(F);

  if RadioButton7.Checked=false then
  begin
    AssignFile(F,TempFileName);
    reset(F);
    if RadioButton1.Checked then //constant selected
      LoadSingleConstant(F)
    else if RadioButton2.Checked then //tracer selected
      LoadSingleTracer(F)
   else if RadioButton3.Checked then //auxiliary selected
      LoadSingleAuxiliary(F)
    else if RadioButton4.Checked then //process selected
      LoadSingleProcess(F)
    else if RadioButton5.Checked then //element selected
      LoadSingleElement(F)
    else if RadioButton6.Checked then //colored element selected
      LoadSingleCElement(F);
    closefile(F);
  end
  else
    LoadModelInfos(tempFileName);

  SaveAllFiles;
  LoadAllFiles;

  Panel3.Visible:=false;
  Panel2.Visible:=true;

  AfterRadioButton;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
end;

procedure TForm1.CheckListBox1ClickCheck(Sender: TObject);
var i: Integer;
begin
   if RadioButton2.Checked then //tracers
      for i:=0 to length(tracers)-1 do
        if CheckListBox1.Checked[i] then tracers[i].isOutput:=1 else tracers[i].isOutput:=0;
    if RadioButton3.Checked then //auxiliaries
      for i:=0 to length(auxiliaries)-1 do
        if CheckListBox1.Checked[i] then auxiliaries[i].isOutput:=1 else auxiliaries[i].isOutput:=0;
    if RadioButton4.Checked then //processes
      for i:=0 to length(processes)-1 do
        if CheckListBox1.Checked[i] then processes[i].isOutput:=1 else processes[i].isOutput:=0;
    SaveAllFiles;
end;

procedure TForm1.CheckListBox1Exit(Sender: TObject);
begin
end;

procedure TForm1.Memo1Change(Sender: TObject);
begin
  if SynEditBusy=false then
  begin
    Panel2.Visible:=false;
    Panel3.Visible:=true;
    Panel4.Visible:=false;
    Panel5.Visible:=false;
    Button2.Visible:=false;
    Button3.Visible:=false;
  end;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  if BackListPosition>0 then
  begin
    BackListPosition:=BackListPosition-1;
    GoToExpression(BackList[BackListPosition],true);
  end;
end;

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
  if BackListPosition<BackList.Count-1 then
  begin
    BackListPosition:=BackListPosition+1;
    GoToExpression(BackList[BackListPosition],true);
  end;
end;

procedure TForm1.SpeedButton3Click(Sender: TObject);
var
  chosenString, newname, newelement: String;
begin
  if RadioButton1.Checked then chosenString:='constant';
  if RadioButton2.Checked then chosenString:='tracer';
  if RadioButton3.Checked then chosenString:='auxiliary variable';
  if RadioButton4.Checked then chosenString:='process';
  if RadioButton5.Checked then chosenString:='element';
  newname:='new_name';

  if RadioButton6.Checked then
  begin
    newelement:='N';
    newname:='white';
    if InputQuery('new colored element','Please enter the name of the element, e.g. N',newelement) then
      if InputQuery('new colored element','Please enter the name of the color',newname) then
        begin
          SetLength(celements,length(celements)+1);
          selCElement:=length(CElements)-1;
          InitErgCElement(CElements[selCElement]);
          CElements[selCElement].element:=newelement;
          CElements[selCElement].color:=newname;
          SaveAllFiles;
          AfterRadioButton;
        end;
  end
  else
  begin
    if InputQuery('new '+chosenString,'Please enter the name for the new '+chosenString,newname) then
    begin
      newname:=trim(newname);
      //check if name exists might be introduced here

      if RadioButton1.checked then //constant
      begin
        SetLength(constants,length(constants)+1);
        selConstant:=length(constants)-1;
        InitErgConstant(constants[selConstant]);
        constants[selConstant].name:=newname;
        SaveAllFiles;
        AfterRadioButton;
      end;

      if RadioButton2.checked then //tracer
      begin
        SetLength(tracers,length(tracers)+1);
        seltracer:=length(tracers)-1;
        InitErgtracer(tracers[seltracer]);
        tracers[seltracer].name:=newname;
        SaveAllFiles;
        AfterRadioButton;
      end;

      if RadioButton3.checked then //auxiliary
      begin
        SetLength(auxiliaries,length(auxiliaries)+1);
        selauxiliary:=length(auxiliaries)-1;
        InitErgauxiliary(auxiliaries[selauxiliary]);
        auxiliaries[selauxiliary].name:=newname;
        SaveAllFiles;
        AfterRadioButton;
      end;

      if RadioButton4.checked then //process
      begin
        SetLength(processes,length(processes)+1);
        selprocess:=length(processes)-1;
        InitErgprocess(processes[selprocess]);
        processes[selprocess].name:=newname;
        SaveAllFiles;
        AfterRadioButton;
      end;

      if RadioButton5.checked then //element
      begin
        SetLength(elements,length(elements)+1);
        selelement:=length(elements)-1;
        InitErgelement(elements[selelement]);
        elements[selelement].name:=newname;
        SaveAllFiles;
        AfterRadioButton;
      end;

    end;
  end;
end;

procedure TForm1.SpeedButton4Click(Sender: TObject);
var i: Integer;
begin
  if MessageDlg('really delete '+BackList[BackListPosition]+'?',mtConfirmation,[mbYes,mbAbort],0)=mrYes then
  begin
    if RadioButton1.Checked then
    begin
      for i:=selConstant to length(constants)-2 do
        copyErgConstant(constants[i+1],constants[i]);
      setLength(constants,length(constants)-1);
      if selConstant>=length(constants) then selConstant:=length(constants)-1;
    end;
    if RadioButton2.Checked then
    begin
      for i:=seltracer to length(tracers)-2 do
        copyErgtracer(tracers[i+1],tracers[i]);
      setLength(tracers,length(tracers)-1);
      if seltracer>=length(tracers) then seltracer:=length(tracers)-1;
    end;
    if RadioButton3.Checked then
    begin
      for i:=selauxiliary to length(auxiliaries)-2 do
        copyErgauxiliary(auxiliaries[i+1],auxiliaries[i]);
      setLength(auxiliaries,length(auxiliaries)-1);
      if selauxiliary>=length(auxiliaries) then selauxiliary:=length(auxiliaries)-1;
    end;
    if RadioButton4.Checked then
    begin
      for i:=selprocess to length(processes)-2 do
        copyErgprocess(processes[i+1],processes[i]);
      setLength(processes,length(processes)-1);
      if selprocess>=length(processes) then selprocess:=length(processes)-1;
    end;
    if RadioButton5.Checked then
    begin
      for i:=selelement to length(elements)-2 do
        copyErgelement(elements[i+1],elements[i]);
      setLength(elements,length(elements)-1);
      if selelement>=length(elements) then selelement:=length(elements)-1;
    end;
    if RadioButton6.Checked then
    begin
      for i:=selcelement to length(celements)-2 do
        copyErgcelement(celements[i+1],celements[i]);
      setLength(celements,length(celements)-1);
      if selcelement>=length(celements) then selcelement:=length(celements)-1;
    end;
    SaveAllFiles;
    AfterRadioButton;
  end;
end;

procedure TForm1.SpeedButton5Click(Sender: TObject);
var
  c: tErgConstant;
  t: tErgTracer;
  a: tErgAuxiliary;
  p: tErgProcess;
  e: tErgElement;
  ce: tErgCElement;
  i: Integer;
begin
  if ((RadioButton1.Checked or RadioButton5.Checked or RadioButton6.Checked) and (ListBox1.ItemIndex>0)) or
     ((RadioButton2.Checked or RadioButton3.Checked or RadioButton4.Checked) and (CheckListBox1.ItemIndex>0)) then
  begin
    if RadioButton1.Checked then
    begin
      i:=selConstant;
      copyErgConstant(constants[i],c);
      copyErgConstant(constants[i-1],constants[i]);
      copyErgConstant(c,constants[i-1]);
      selConstant:=selConstant-1;
    end;
    if RadioButton2.Checked then
    begin
      i:=seltracer;
      copyErgtracer(tracers[i],t);
      copyErgtracer(tracers[i-1],tracers[i]);
      copyErgtracer(t,tracers[i-1]);
      seltracer:=seltracer-1;
    end;
    if RadioButton3.Checked then
    begin
      i:=selauxiliary;
      copyErgauxiliary(auxiliaries[i],a);
      copyErgauxiliary(auxiliaries[i-1],auxiliaries[i]);
      copyErgauxiliary(a,auxiliaries[i-1]);
      selauxiliary:=selauxiliary-1;
    end;
    if RadioButton4.Checked then
    begin
      i:=selprocess;
      copyErgprocess(processes[i],p);
      copyErgprocess(processes[i-1],processes[i]);
      copyErgprocess(p,processes[i-1]);
      selprocess:=selprocess-1;
    end;
    if RadioButton5.Checked then
    begin
      i:=selelement;
      copyErgelement(elements[i],e);
      copyErgelement(elements[i-1],elements[i]);
      copyErgelement(e,elements[i-1]);
      selelement:=selelement-1;
    end;
    if RadioButton6.Checked then
    begin
      i:=selcelement;
      copyErgcelement(celements[i],ce);
      copyErgcelement(celements[i-1],celements[i]);
      copyErgcelement(ce,celements[i-1]);
      selcelement:=selcelement-1;
    end;
    SaveAllFiles;
    AfterRadioButton;
  end;
end;

procedure TForm1.SpeedButton6Click(Sender: TObject);
var
  c: tErgConstant;
  t: tErgTracer;
  a: tErgAuxiliary;
  p: tErgProcess;
  e: tErgElement;
  ce: tErgCElement;
  i: Integer;
begin
  if ((RadioButton1.Checked or RadioButton5.Checked or RadioButton6.Checked) and (ListBox1.ItemIndex<ListBox1.Items.Count-1)) or
     ((RadioButton2.Checked or RadioButton3.Checked or RadioButton4.Checked) and (CheckListBox1.ItemIndex<CheckListBox1.Items.Count-1)) then
  begin
    if RadioButton1.Checked then
    begin
      i:=selConstant;
      copyErgConstant(constants[i],c);
      copyErgConstant(constants[i+1],constants[i]);
      copyErgConstant(c,constants[i+1]);
      selConstant:=selConstant+1;
    end;
    if RadioButton2.Checked then
    begin
      i:=seltracer;
      copyErgtracer(tracers[i],t);
      copyErgtracer(tracers[i+1],tracers[i]);
      copyErgtracer(t,tracers[i+1]);
      seltracer:=seltracer+1;
    end;
    if RadioButton3.Checked then
    begin
      i:=selauxiliary;
      copyErgauxiliary(auxiliaries[i],a);
      copyErgauxiliary(auxiliaries[i+1],auxiliaries[i]);
      copyErgauxiliary(a,auxiliaries[i+1]);
      selauxiliary:=selauxiliary+1;
    end;
    if RadioButton4.Checked then
    begin
      i:=selprocess;
      copyErgprocess(processes[i],p);
      copyErgprocess(processes[i+1],processes[i]);
      copyErgprocess(p,processes[i+1]);
      selprocess:=selprocess+1;
    end;
    if RadioButton5.Checked then
    begin
      i:=selelement;
      copyErgelement(elements[i],e);
      copyErgelement(elements[i+1],elements[i]);
      copyErgelement(e,elements[i+1]);
      selelement:=selelement+1;
    end;
    if RadioButton6.Checked then
    begin
      i:=selcelement;
      copyErgcelement(celements[i],ce);
      copyErgcelement(celements[i+1],celements[i]);
      copyErgcelement(ce,celements[i+1]);
      selcelement:=selcelement+1;
    end;
    SaveAllFiles;
    AfterRadioButton;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var i, j: Integer;
begin
  if tracers[selTracer].isCombined<>0 then
    ShowMessage('This is a combined tracer. Its sources and sinks are the processes which are sources and sinks of its contents.')
  else
  begin
    Form3.Edit1.Text:=Edit1.Text;
    Form3.ListBox1.Items.Clear;
    Form3.ListBox2.Items.Clear;
    for i:=0 to length(processes)-1 do
    begin
      for j:=0 to length(processes[i].input)-1 do
        if (trim(lowercase(processes[i].input[j].tracer)) = lowercase(edit1.Text)) then
          Form3.ListBox2.Items.Add(processes[i].name);
      for j:=0 to length(processes[i].output)-1 do
        if (trim(lowercase(processes[i].output[j].tracer)) = lowercase(edit1.Text)) then
          Form3.ListBox1.Items.Add(processes[i].name);
    end;
    Form3.ShowModal;
  end;
end;

procedure TForm1.SynEdit1Change(Sender: TObject);
begin
  if SynEditBusy=false then
  begin
    Panel2.Visible:=false;
    Panel3.Visible:=true;
    Panel4.Visible:=false;
    Panel5.Visible:=false;
    Button2.Visible:=false;
    Button3.Visible:=false;
    PaintTheWords;
  end;
end;

procedure TForm1.SynEdit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  myword: String;
  found: Boolean;
  i: Integer;
  x1,y1: Integer;
begin
  if Button=mbRight then
  begin
    x1:=SynEdit1.PixelsToRowColumn(point(x,y)).X;
    y1:=SynEdit1.PixelsToRowColumn(point(x,y)).Y;
    myword:=SynEdit1.GetWordAtRowCol(point(x1,y1));
    found:=false;
    for i:=0 to length(keywords)-1 do
      if myword=keywords[i] then
      begin
        ShowMessage(keywords[i]+chr(13)+keywordDescriptions[i]);
        found:=true;
      end;
    if not found then
      if Panel3.Visible=false then
        GoToExpression(myword);
  end;
end;

procedure renameInString(oldName,newName: String; var myString: String);
var
  i: Integer;
  standsAlone: Boolean;
  s: String;
begin
  i:=1;
  while i <= length(myString)-length(oldName)+1 do
  begin
    if lowercase(copy(myString,i,length(oldName))) = lowercase(oldname) then
    begin
      standsAlone:=true;
      if i>1 then
      begin
        s:=copy(myString,i-1,1);
        if IsStandardChar(s[1]) then standsAlone:=false;
      end;
      if i < length(myString)-length(oldName)+1 then
      begin
        s:=copy(myString,i+length(oldName),1);
        if IsStandardChar(s[1]) then standsAlone:=false;
      end;
      if standsAlone then
      begin
        myString:=copy(myString,1,i-1)+newName+copy(myString,i+length(oldName),length(myString));
        i:=i+length(newName)-1;
      end;
    end;
    i:=i+1;
  end;
end;

function WhatIsTheName(name:String):String;
//returns 'a tracer' if name exists as a tracer, 'an element' if name exists as an element, ...
//returns '' if tracer does not exist
var
  i: Integer;
begin
  result:='';
  for i:=0 to length(constants)-1 do
    if lowercase(name)=lowercase(constants[i].name) then result:='a constant';
  for i:=0 to length(tracers)-1 do
    if lowercase(name)=lowercase(tracers[i].name) then result:='a tracer';
  for i:=0 to length(auxiliaries)-1 do
    if lowercase(name)=lowercase(auxiliaries[i].name) then result:='an auxiliary variable';
  for i:=0 to length(processes)-1 do
    if lowercase(name)=lowercase(processes[i].name) then result:='a process';
  for i:=0 to length(elements)-1 do
    if lowercase(name)=lowercase(elements[i].name) then result:='an element';
  for i:=0 to length(celements)-1 do
    if lowercase(name)=lowercase(celements[i].color+'_'+celements[i].element) then result:='a colored element';
end;

procedure renameInTextfiles(oldName,newName: String);
var
  i, j: Integer;
begin
  for i:=0 to length(constants)-1 do
  begin
    renameInString(oldName,newName,constants[i].name);
  end;
  for i:=0 to length(tracers)-1 do
  begin
    renameInString(oldName,newName,tracers[i].name);
    for j:=0 to length(tracers[i].contents)-1 do
    begin
      renameInString(oldName,newName,tracers[i].contents[j].element);
      renameInString(oldName,newName,tracers[i].contents[j].amount);
    end;
    renameInString(oldName,newName,tracers[i].vertSpeed);
    renameInString(oldName,newName,tracers[i].vertDiff);
    renameInString(oldName,newName,tracers[i].opacity);
    renameInString(oldName,newName,tracers[i].childOf);
    renameInString(oldName,newName,tracers[i].massLimits);
  end;
  for i:=0 to length(auxiliaries)-1 do
  begin
    renameInString(oldName,newName,auxiliaries[i].name);
    renameInString(oldName,newName,auxiliaries[i].formula);
    for j:=1 to 9 do
      renameInString(oldName,newName,auxiliaries[i].temp[j]);
  end;
  for i:=0 to length(processes)-1 do
  begin
    renameInString(oldName,newName,processes[i].name);
    renameInString(oldName,newName,processes[i].turnover);
    for j:=0 to length(processes[i].input)-1 do
    begin
      renameInString(oldName,newName,processes[i].input[j].tracer);
      renameInString(oldName,newName,processes[i].input[j].amount);
    end;
    for j:=0 to length(processes[i].output)-1 do
    begin
      renameInString(oldName,newName,processes[i].output[j].tracer);
      renameInString(oldName,newName,processes[i].output[j].amount);
    end;
    for j:=0 to length(processes[i].limitations)-1 do
    begin
      renameInString(oldName,newName,processes[i].limitations[j].elseProcess);
      renameInString(oldName,newName,limitations[processes[i].limitations[j].limitationNum].tracer);
      renameInString(oldName,newName,limitations[processes[i].limitations[j].limitationNum].value);
    end;
  end;
  for i:=0 to length(elements)-1 do
  begin
    renameInString(oldName,newName,elements[i].name);
  end;
  for i:=0 to length(celements)-1 do
  begin
    renameInString(oldName,newName,celements[i].element);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  oldName, newName: String;
begin
  oldName:=Edit1.Text;
  newName:=InputBox('rename '+Edit1.text,'Enter a new name for the '+Label3.Caption+' '+Edit1.Text,Edit1.Text);
  if newName <> oldName then
  begin
    if WhatIsTheName(newName)='' then
    begin
      renameInTextfiles(oldName,newName);
      SaveAllFiles;
      GoToExpression(newName);
    end
    else
      ShowMessage('Cannot rename '+oldName+' to '+newName+': '+chr(13)+chr(13)+newName+' is already the name of '+WhatIsTheName(newName)+'.');
  end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  i: Integer;
begin
  Form4.Caption := processes[Form1.CheckListBox1.ItemIndex].name+' - checking element conservation';
  Unit4.oldEquation:=GetInputOutputEquation(Form1.CheckListBox1.ItemIndex);
  Form4.Edit1.Text:=Unit4.oldEquation;
  Unit4.processNum:=Form1.CheckListBox1.ItemIndex;
  Unit4.InitStringGrid;
  Form1.Visible:=false;
  Form4.ShowModal;
  Form1.Visible:=true;
  LoadAllFiles;
  GoToExpression(processes[Form1.CheckListBox1.ItemIndex].name);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  ShowMessage(InconsistencyString);
end;

end.
