program Parallel2;

uses
  Windows,
  Messages,
  KOL in '..\Unicode\KOL\Kol.pas',
  mmsystem;

{$R parallel.res}

const
  FORM_WIDTH                    = 700;
  FORM_HEIGHT                   = 500;
  FORM_TOPROW                   = 60;
  FORM_BOTROW                   = 40;
  FORM_SEP                      = 15;
  FORM_MARGIN                   = 20;

  FORM_BARHEIGHT = (FORM_HEIGHT-FORM_TOPROW-FORM_SEP-FORM_BOTROW) div 2;


  ZD = WideChar($000D);
  ZA = WideChar($000A);

var
  Form:                         PControl;
  OpenButton:                   PControl;
  ScrollBar:                    PControl;
  OpenDialog:                   POpenSaveDialog;
  ScreenX, ScreenY:             Word;

  StartDir:                     string;
  DirName:                      string;
  LastFile:                     string;

  FS:                           PStream;

  NumberOfSentences:            Word;
  TargetSentences:              array of WideString;
  SourceSentences:              array of WideString;
  Sounds:                       array of string;

  Rect1, Rect2:                 TRect;
  Prog, SoundName:              PControl;

  F:                            TextFile;
  s:                            string;
  v:                            LongInt;
  ec: Integer;

  FileName:                     string;

  HideTarget: PControl;




procedure ReadW(var WS: WideString);
var
  C, D: WideChar;
label ReadMore;
begin
  WS:='';
  ReadMore:
  if FS.Read(C, 2)=2 then
  begin
    if C<>ZD then WS:=WS+C
    else
    begin
      if FS.Read(D, 2)=2 then
      begin
        if D<>ZA then
          WS:=WS+C+D
        else
          Exit;
      end
      else
      begin
        WS:=WS+C;
        Exit;
      end;
    end;
  end
  else Exit;
  goto ReadMore;
end;

procedure DisplaySentence;
begin
  if NumberOfSentences>0 then
  begin
    Form.Canvas.Brush.Color:=$302000;
    Form.Canvas.Font.Color:=$FFFFFF;
    Form.Canvas.FillRect(Rect1);
    Form.Canvas.WDrawText(SourceSentences[ScrollBar.SBPosition-1], Rect1, 16);

    Form.Canvas.Brush.Color:=$603000;
    Form.Canvas.FillRect(Rect2);

    if not HideTarget.Checked then
    begin
      Form.Canvas.Font.Color:=$FFFF;
      Form.Canvas.WDrawText(TargetSentences[ScrollBar.SBPosition-1], Rect2, 16);
    end;

    Prog.Caption:='['+Int2Str(ScrollBar.SBPosition)+'/'+Int2Str(NumberOfSentences)+']';
    if Sounds[ScrollBar.SBPosition-1]='' then
      SoundName.Caption:=''
    else
      SoundName.Caption:=Sounds[ScrollBar.SBPosition-1]+'.wav';
  end
end;


function LoadFile(FN: string): Boolean;
var
  WC: WideString;
  C: Word;
  ReadBorder: DWord;
  i, j: Integer;
  SRC, TGT, SND: WideString;

label NOGOOD, FINISH, LOOP, PLUS1;
begin
  Result:=True;
  FS:= NewReadFileStream(FN);
  ReadBorder:=FS.Size-2;

  // Now we read the first two bytes in order to understand they are FF FE

  if FS.Read(C, 2)<2 then goto NOGOOD;
  if C<>$FEFF then goto NOGOOD;

  // We shall now read the first line which must contain the name of the folder
  // with sounds for it

  NumberOfSentences:=0;

  j:=0;
  for i:=1 to Length(FN) do
    if FN[i]='\' then j:=i;


  if FS.Position>ReadBorder then
  begin
    MsgOK('The first line must contain the name of the folder with sounds');
    Result:=False;
    Exit;
  end;


  ReadW(WC);

  DirName:=Copy(FN, 1, j)+WC+'\';


  Loop:


  if FS.Position>ReadBorder then goto FINISH;
  ReadW(Src);

  if Length(Src)>1 then
  begin
    if Src[1]='+' then
    if NumberOfSentences>0 then
    begin
      TargetSentences[NumberOfSentences-1]:=TargetSentences[NumberOfSentences-1]
        +#13+Copy(Src, 2, Length(Src)-1);
      goto LOOP;
    end;
  end;

  Plus1:

  if FS.Position>ReadBorder then goto FINISH;
  ReadW(Tgt);

  if Length(Tgt)>1 then
  begin
    if Tgt[1]='+' then
    begin
      Src:=Src+#13+Copy(Tgt, 2, Length(Tgt)-1);
      goto Plus1;
    end;
  end;

  Snd:='';

  if Tgt[1]='`' then
  begin
    for i:=2 to Length(Tgt) do
    if Tgt[i]='`' then
    begin
      Snd:=Copy(Tgt, 2, i-2);
      Tgt:=Copy(Tgt,i+1, Length(Tgt)-i);
      Break;
    end;
  end;

  Inc(NumberOfSentences);
  if NumberOfSentences mod 100 = 1 then
  begin
    SetLength(SourceSentences, NumberOfSentences+99);
    SetLength(TargetSentences, NumberOfSentences+99);
    SetLength(Sounds, NumberOfSentences+99);
  end;

  SourceSentences[NumberOfSentences-1]:=Src;
  TargetSentences[NumberOfSentences-1]:=Tgt;
  Sounds[NumberOfSentences-1]:=Snd;

  goto Loop;
  FINISH:

  Result:=True;
  FS.Free;
  LastFile:=FN;

  Form.Caption:='Parallel 2.0 - '+FN;

  ScrollBar.SBMax:=NumberOfSentences+1;
  ScrollBar.SBMin:=1;
  ScrollBar.SBPosition:=1;
  ScrollBar.Visible:=True;
  HideTarget.Visible:=True;


  Exit;

NOGOOD:
  Result:=False;
  MsgOK('You should open a Unicode text file!');

end;


procedure OpenButtonClick(Dummy: Pointer; Sender: PControl);
begin

  if OpenDialog.Execute then
  begin
    LoadFile(OpenDialog.Filename);
  end;
end;







procedure ScrollBarChange(Sender: PControl; Cmd: Word);
begin
  DisplaySentence;
end;

procedure Recite;
var FN: string;
begin
  if NumberOfSentences=0 then Exit;
  if Sounds[ScrollBar.SBPosition-1]<>'' then
  begin
    FN:=DirName+Sounds[ScrollBar.SBPosition-1]+'.wav';
    if FileExists(FN) then
    PlaySound(PChar(FN),0,SND_ASYNC);
  end;
end;


procedure FormKeyDown(Dummy: Pointer; Sender: PControl; var Key: Longint; Shift: DWORD);
begin
  case Key of
  32: // space
  begin
    Recite;
    Key:=0;
  end;
  34: // PgDown
  if ScrollBar.SBPosition<ScrollBar.SBMax-1 then
  begin
    ScrollBar.SBPosition:=ScrollBar.SBPosition+1;
    DisplaySentence;
    Key:=0;
  end;
  33, 8: // PgUp
  if ScrollBar.SBPosition>1 then
  begin
    ScrollBar.SBPosition:=ScrollBar.SBPosition-1;
    DisplaySentence;
    Key:=0;
  end;
  36: // Home
  begin
    if NumberOfSentences>0 then
    begin
      ScrollBar.SBPosition:=1;
      DisplaySentence;
    end;
    Key:=0;
  end;
  35: // End
  begin
    if NumberOfSentences>0 then
    begin
      ScrollBar.SBPosition:=NumberOfSentences;
      DisplaySentence;
    end;
    Key:=0;
  end;

  end;

end;

procedure FormPaint(Sender: PControl; DC: HDC);
begin
  DisplaySentence;
end;

procedure FormMouseWheel(Dummy: Pointer; Sender: PControl; var Mouse: TMouseEventData);
var z: SmallInt;
begin

  z:=HiWord(Mouse.Shift);
  if z<0 then
  if ScrollBar.SBPosition<ScrollBar.SBMax-1 then
  begin
    ScrollBar.SBPosition:=ScrollBar.SBPosition+1;
    DisplaySentence;
    Exit;
  end;
  if z>0 then
  if ScrollBar.SBPosition>1 then
  begin
    ScrollBar.SBPosition:=ScrollBar.SBPosition-1;
    DisplaySentence;
  end;
end;

procedure HideTextChange(Dummy: Pointer; Sender: PObj);
begin
  DisplaySentence;
end;

procedure FormClose(Sender: PObj; var Accept: Boolean);
Var
  F: TextFile;
begin
  //PlaySound(0, 0, SND_PURGE);

  // writing the ini file
  AssignFile(F, StartDir+'\parallel.ini');
  Rewrite(F);
  Writeln(F, LastFile);
  WriteLn(F, ScrollBar.SBPosition);
  if HideTarget.Checked then WriteLn(F, 1)
  else WriteLn(F, 0);

  CloseFile(F);
end;



begin

  GetDir(0, StartDir);

  ScreenX:=GetSystemMetrics(SM_CXSCREEN);
  ScreenY:=GetSystemMetrics(SM_CYSCREEN);

  Form := NewForm(Applet,'Parallel 2');
  Form.Style:=WS_BORDER or WS_SYSMENU or WS_VISIBLE;
  Form.SetSize(FORM_WIDTH, FORM_HEIGHT);
  Form.Shift((ScreenX-FORM_WIDTH) div 2,(ScreenY-FORM_HEIGHT) div 2);
  Form.Color:=$904000;
  Form.Font.FontName:='Tahoma';
  Form.Font.FontHeight:=13;
  Form.OnPaint:=TOnPaint(MakeMethod(nil, @FormPaint));

  OpenButton := NewButton(Form,'Open').SetSize(60,20);
  OpenButton.Shift(5,5);
  OpenButton.OnClick := TOnEvent(MakeMethod(nil, @OpenButtonClick));
  OpenButton.OnKeyDown :=TOnKey(MakeMethod(nil, @FormKeyDown));
  OpenButton.OnMouseWheel := TOnMouse(MakeMethod(nil, @FormMouseWheel));

  OpenDialog:= NewOpenSaveDialog('Open a unicode TXT:',StartDir,[]);
  OpenDialog.OpenDialog:=True;
  OpenDialog.Filter:='*.txt (Unicode ONLY)|*.TXT';

  ScrollBar := NewScrollBar(Form, sbHorizontal);
  ScrollBar.Shift(80, -41);
  ScrollBar.Width:=FORM_WIDTH-110;
  ScrollBar.OnSBScroll := TOnSBScroll(MakeMethod(nil, @ScrollBarChange));
  ScrollBar.SBMin:=0;
  ScrollBar.SBMax:=1;
  ScrollBar.Visible:=False;

  Prog:=NewLabel(Form, '');
  Prog.Font.Color:=$FFFFFF;
  Prog.Shift(85,25);


  Rect1.Left  :=FORM_MARGIN;
  Rect1.Right :=FORM_WIDTH-FORM_MARGIN;
  Rect1.Top   :=FORM_TOPROW;
  Rect1.Bottom:=FORM_TOPROW+FORM_BARHEIGHT;

  Rect2.Left  :=FORM_MARGIN;
  Rect2.Right :=FORM_WIDTH-FORM_MARGIN;
  Rect2.Top   :=FORM_TOPROW+FORM_BARHEIGHT+FORM_SEP;
  Rect2.Bottom:=FORM_TOPROW+2*FORM_BARHEIGHT+FORM_SEP;


  SoundName:=NewLabel(Form, '');
  SoundName.Font.Color:=$FFFFFF;
  SoundName.Shift(200, 25);


  Form.Canvas.Font.FontHeight:=26;

  HideTarget:=NewCheckbox(Form,'Hide target');
  HideTarget.Shift(FORM_WIDTH-130,25);
  HideTarget.Visible:=False;
  HideTarget.OnClick:= TOnEvent(MakeMethod(nil, @HideTextChange));


  HideTarget.OnKeyDown :=TOnKey(MakeMethod(nil, @FormKeyDown));
  HideTarget.OnMouseWheel := TOnMouse(MakeMethod(nil, @FormMouseWheel));

  Form.OnClose := TOnEventAccept(MakeMethod(nil, @FormClose));


  LastFile:='';

  FileName:=StartDir+'\parallel.ini';

  if FileExists(FileName) then
  begin
    // trying to open the file

    AssignFile(F, FileName);
    Reset(F);

    if not EOF(F) then
    begin
      ReadLn(F, s);
      if s<>'' then
      if LoadFile(s) then
      begin
        if not EOF(F) then
        begin
          ReadLn(F, s);
          Val(s, v, ec);
          if ec=0 then
            if v<=NumberOfSentences then ScrollBar.SBPosition:=v;
          if not EOF(F) then
          begin
            ReadLn(F, s);
            if s='1' then HideTarget.Checked:=True;
          end;
        end;
      end;
    end;
    CloseFile(F);
  end;



  Run(Form);
end.
