unit UGameOptions;
{ ********************************************************************************* }
{ (c) GNU                                                                           }
{ author: Heiko Tietze                                                              }
{ version: 1.5                                                                      }
{ date: 23.04.2005                                                                  }
{ description: all game options are defined and can be changed here;                }
{              the visualization is informed about changes immediately by           }
{              OnChange(); all options are stored in one inifile with different     }
{              entries/presets for fast and easy reconfiguration                    }
{ ********************************************************************************* }


{$I Def.inc}

interface

uses SysUtils, Types, Classes, Variants, IniFiles,
     {$IFDEF VCL}
     Controls, Graphics, Forms, Dialogs, StdCtrls, ExtCtrls, Grids, Buttons, ComCtrls,
     {$ELSE}
     QControls, QTypes, QGraphics, QForms, QDialogs, QStdCtrls, QExtCtrls, QGrids, QButtons, QComCtrls,
     {$ENDIF}
     UTools, UDictionary, ULanguage;

type TOnChanged=procedure of Object;
     TGameOptions = class(TForm)
        PageControl: TPageControl;
        tsLanguage: TTabSheet;
        tsDesign: TTabSheet;
        tsOptions: TTabSheet;
        gbFieldColor: TGroupBox;
        c1Label: TLabel;
        c2Label: TLabel;
        c3Label: TLabel;
        c4Label: TLabel;
        c5Label: TLabel;
        c6Label: TLabel;
        c7Label: TLabel;
        c1: TPanel;
        c2: TPanel;
        c3: TPanel;
        c4: TPanel;
        c5: TPanel;
        c6: TPanel;
        c7: TPanel;
        btnTexture: TBitBtn;
        gbPlayerColor: TGroupBox;
        pnPlayerColor1: TPanel;
        pnPlayerColor2: TPanel;
        pnPlayerColor3: TPanel;
        pnPlayerColor4: TPanel;
        cbPlayerColored: TCheckBox;
        cbShowErrors: TCheckBox;
        gbFont: TGroupBox;
        lbFont: TLabel;
        lbLetterSize: TLabel;
        lbValueSize: TLabel;
        edLetterSize: TEdit;
        edValueSize: TEdit;
        lbFontName: TLabel;
        btnFont: TButton;
        OpenDialog: TOpenDialog;
        SaveDialog: TSaveDialog;
        FontDialog: TFontDialog;
        ColorDialog: TColorDialog;
        gbDictionary: TGroupBox;
        btnLoadDictionary: TBitBtn;
        btnSaveDictionary: TBitBtn;
        gbLetters: TGroupBox;
        lbLetterCount: TLabel;
        sgLetters: TStringGrid;
        edLetterCount: TEdit;
        gbLanguage: TGroupBox;
        cbLanguage: TComboBox;
        gbWords: TGroupBox;
        lbMeaning: TLabel;
        lbWord: TLabel;
        edWord: TEdit;
        edMeaning: TMemo;
        btnAdd: TBitBtn;
        btnDelete: TBitBtn;
        pnBottom: TPanel;
        lbPresets: TLabel;
        cbPresets: TComboBox;
        btnSavePresets: TBitBtn;
        btnClose: TBitBtn;
        btnLoadPresets: TBitBtn;
        edPort: TEdit;
        gbDesign: TGroupBox;
        rgDimensions: TRadioGroup;
        gbNetwork: TGroupBox;
        lbPort: TLabel;
        cbResetLetters: TCheckBox;
        cbCoordinates: TCheckBox;
        cbDoubleFirstMove: TCheckBox;
        cbSoundOnMove: TCheckBox;
        cbSoundOnChat: TCheckBox;
        cbSoundOnPoll: TCheckBox;
        edSoundName: TEdit;
        btnSoundName: TButton;
        cbComputerInHighScore: TCheckBox;
        sgLibraryInfo: TStringGrid;
        cbSaveOnClose: TCheckBox;
        cbSaveLibOnExit: TCheckBox;
        cbLettersSet: TComboBox;
        procedure FormCreate(Sender: TObject);
        procedure edWordChange(Sender: TObject);
        procedure edWordKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
        procedure btnAddClick(Sender: TObject);
        procedure btnDeleteClick(Sender: TObject);
        procedure btnLoadDictionaryClick(Sender: TObject);
        procedure btnSaveDictionaryClick(Sender: TObject);
        procedure sgLettersKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
        procedure edKeyPressNumberOnly(Sender: TObject; var Key: Char);
        procedure ColorClick(Sender: TObject);
        procedure cbPlayerColoredClick(Sender: TObject);
        procedure btnFontClick(Sender: TObject);
        procedure edFontChange(Sender: TObject);
        procedure btnSavePresetsClick(Sender: TObject);
        procedure btnLoadPresetsClick(Sender: TObject);
        procedure edKeyUpCursorUpDown(Sender: TObject; var Key: Word; Shift: TShiftState);
        procedure cbPresetsKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
        procedure btnSoundClick(Sender: TObject);
        procedure OptionsChanged(Sender: TObject);
        procedure edLetterCountExit(Sender: TObject);
        procedure cbLanguageChange(Sender: TObject);
        procedure FormActivate(Sender: TObject);
        procedure sgLibraryInfoDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
        procedure FormShow(Sender: TObject);
        procedure FormHide(Sender: TObject);
        procedure cbLettersSetChange(Sender: TObject);
     private
        FOnChanged : TOnChanged;
        FDictionaryName : string;
        procedure SaveOptions;
        procedure LoadOptions(Name:string='');
        procedure ChangeWord(i:integer);
        function GetPlayerColor(index: Byte): TColor;
        function GetLettersSet: integer;
        procedure SetLettersSet(const Value: integer);
        property LettersSet:integer read GetLettersSet write SetLettersSet;
     public
        FieldColor : array[0..7] of TColor;
        function LoadDictionary(const FileName:string):boolean;
        property DictionaryName : string read FDictionaryName;
        property PlayerColor[index:Byte] : TColor read GetPlayerColor;
        property OnOptionsChanged : TOnChanged read FOnChanged write FOnChanged;
     end;

type TLettersByLanguage=record
                   Letters, LetterCount, LetterValue : string;
                 end;
const LettersByLanguage : array[0..5] of TLettersByLanguage=
      ((Letters:'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
        LetterCount:'9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1';
        LetterValue:'1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10'
       ), //english
       (Letters:'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,Ä,Ö,Ü';
        LetterCount:'5,2,2,4,15,2,3,4,6,1,2,3,4,9,3,1,1,6,7,6,6,1,1,1,1,1,1,1,1';
        LetterValue:'1,3,4,1,1,4,2,2,1,6,4,2,3,1,2,4,10,1,1,1,1,6,3,8,10,3,6,8,6'
       ),//german
       (Letters:'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
        LetterCount:'9,2,2,3,15,2,2,2,8,1,1,5,3,6,6,2,1,6,6,6,6,2,1,1,1,1';
        LetterValue:'1,3,3,2,1,4,2,4,1,8,10,1,2,1,1,3,8,1,1,1,1,4,10,10,10,10'
       ),//french
       (Letters:'A,B,C,D,E,F,G,H,I,L,M,N,O,P,Q,R,S,T,U,V,Z';
        LetterCount:'13,3,4,3,13,2,3,2,13,5,5,6,13,3,1,6,6,6,5,4,2';
        LetterValue:'1,5,4,5,1,8,5,8,1,3,3,2,1,5,10,2,2,2,3,4,8'
       ),//italian
       (Letters:'A,B,C,D,E,F,G,H,I,J,L,M,N,Ñ,O,P,Q,R,S,T,U,V,X,Y,Z';
        LetterCount:'12,2,4,5,12,1,2,2,6,1,4,2,5,1,9,2,1,5,6,4,5,1,1,1,1';
        LetterValue:'1,3,3,2,1,4,2,4,1,8,1,3,1,8,1,3,5,1,1,1,1,4,8,4,10'
       ),//spanish
       (Letters:'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
        LetterCount:'6,2,2,5,18,2,3,2,4,2,3,3,3,10,6,2,1,5,5,5,3,2,2,1,1,2';
        LetterValue:'1,3,5,2,1,4,3,4,1,4,3,3,3,1,1,3,10,2,2,2,4,4,5,8,8,4'
        ) //dutch
       );

var GameOptions: TGameOptions;

implementation

{$IFDEF VCL}
  {$R *.dfm}
{$ELSE}
  {$R *.xfm}
{$ENDIF}

procedure TGameOptions.FormCreate(Sender: TObject);
var sr: TSearchRec;
begin
   if FindFirst(ExtractFilePath(Application.ExeName)+'*.lang', faAnyFile, sr)=0 then
   repeat
     cbLanguage.Items.Add(ChangeFileExt(sr.Name,''));
   until FindNext(sr)<>0;
   FindClose(sr);
   LoadOptions;
   btnSavePresets.Enabled:=false;
   {$IFNDEF VCL} //how to play a sound on linux?
   edSoundName.Enabled:=false;
   btnSoundName.Enabled:=false;
   cbSoundOnMove.Enabled:=false;
   cbSoundOnChat.Enabled:=false;
   cbSoundOnPoll.Enabled:=false;
   {$ENDIF}
   sgLibraryInfo.ColWidths[0]:=sgLibraryInfo.Width-110;
   sgLibraryInfo.ColWidths[1]:=110;
end;

procedure TGameOptions.FormActivate(Sender: TObject);
begin
   {$IFDEF VCL} //CLX calls Active() directly after Create() so Language isn't available yet
    if Language<>nil then cbLanguageChange(self);
   {$ELSE}
    sgLetters.Cells[0,0]:='Letter:';
    sgLetters.Cells[1,0]:='Count:';
    sgLetters.Cells[2,0]:='Value:';
   {$ENDIF}
end;

procedure TGameOptions.FormShow(Sender: TObject);
begin
  lbFontName.Caption:=lbFontName.Font.Name;
end;

procedure TGameOptions.LoadOptions(Name:string);
var i  : integer;
    sl : TStringList;
begin
  with TINIFile.Create(ChangeFileExt(Application.ExeName,'.ini')) do
  try
     cbLanguage.ItemIndex:=cbLanguage.Items.IndexOf(ReadString('General','DialogLanguage','english'));
     cbPresets.Items.CommaText:=ReadString('General','Presets','Standard');
     if Name='' then
        cbPresets.ItemIndex:=cbPresets.Items.IndexOf(ReadString('General','CurrentPreset','Standard')) else
        cbPresets.ItemIndex:=cbPresets.Items.IndexOf(Name);
     WriteString('General','CurrentPreset',cbPresets.Text);
     sl:=TStringList.Create;
     try
       sl.Delimiter:=',';
       sl.DelimitedText:=ReadString(cbPresets.Text,'Letters','A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z');
       sgLetters.RowCount:=sl.Count+1;
       for i:=0 to sl.Count-1 do sgLetters.Cells[0,i+1]:=sl[i];
       sl.Clear;
       sl.DelimitedText:=ReadString(cbPresets.Text,'LetterCount','9,2,2,4,12,2,3,2,9,1,1,4,2,6,8,2,1,6,4,6,4,2,2,1,2,1');
       for i:=0 to sl.Count-1 do sgLetters.Cells[1,i+1]:=sl[i];
       sl.Clear;
       sl.DelimitedText:=ReadString(cbPresets.Text,'LetterValue','1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10');
       for i:=0 to sl.Count-1 do sgLetters.Cells[2,i+1]:=sl[i];
     finally
       sl.Free;
     end;
     cbLettersSet.ItemIndex:=LettersSet;
     edLetterCount.Text:=ReadString(cbPresets.Text,'CurrentLettersCount','7');
     cbLettersSet.ItemIndex:=ReadInteger(cbPresets.Text,'LetterSet',0);

     c1.Color:=ReadInteger(cbPresets.Text,'Color1',clGreen);    FieldColor[0]:=c1.Color;
     c2.Color:=ReadInteger(cbPresets.Text,'Color2',$00BFFFFF);  FieldColor[1]:=c2.Color;
     c3.Color:=ReadInteger(cbPresets.Text,'Color3',clAqua);     FieldColor[2]:=c3.Color;
     c4.Color:=ReadInteger(cbPresets.Text,'Color4',clBlue);     FieldColor[3]:=c4.Color;
     c5.Color:=ReadInteger(cbPresets.Text,'Color5',$008080FF);  FieldColor[4]:=c5.Color;
     c6.Color:=ReadInteger(cbPresets.Text,'Color6',clRed);      FieldColor[5]:=c6.Color;
     c7.Color:=ReadInteger(cbPresets.Text,'Color7',clYellow);   FieldColor[6]:=c7.Color;
     FieldColor[7]:=clDkGray;
     pnPlayerColor1.Color:=ReadInteger(cbPresets.Text,'PlayerColor1',clRed);
     pnPlayerColor2.Color:=ReadInteger(cbPresets.Text,'PlayerColor2',clBlue);
     pnPlayerColor3.Color:=ReadInteger(cbPresets.Text,'PlayerColor3',clGreen);
     pnPlayerColor4.Color:=ReadInteger(cbPresets.Text,'PlayerColor4',$0000BBBB);
     cbPlayerColored.Checked:=ReadBool(cbPresets.Text,'UsePlayerColor',true);
     cbShowErrors.Checked:=ReadBool(cbPresets.Text,'ShowErrors',false);
     lbFontName.Font.Name:=ReadString(cbPresets.Text,'FontName','Times New Roman');
     lbFontName.Caption:=lbFontName.Font.Name;
     edLetterSize.Text:=ReadString(cbPresets.Text,'LetterSize','60');
     edValueSize.Text:=ReadString(cbPresets.Text,'ValueSize','25');
     FDictionaryName:=ReadString(cbPresets.Text,'DictionaryName','');
     rgDimensions.ItemIndex:=ReadInteger(cbPresets.Text,'Dimensions',0);
     {$IFDEF VCL}
     cbSoundOnChat.Checked:=ReadBool(cbPresets.Text,'SoundOnChat',true);
     cbSoundOnMove.Checked:=ReadBool(cbPresets.Text,'SoundOnMove',true);
     cbSoundOnPoll.Checked:=ReadBool(cbPresets.Text,'SoundOnPoll',true);
     edSoundName.Text:=ReadString(cbPresets.Text,'SoundName','');
     {$ENDIF}
     cbResetLetters.Checked:=ReadBool(cbPresets.Text,'ResetLetters',true);
     cbCoordinates.Checked:=ReadBool(cbPresets.Text,'Coordinates',true);
     cbDoubleFirstMove.Checked:=ReadBool(cbPresets.Text,'DoubleFirstMove',true);
     cbComputerInHighScore.Checked:=ReadBool(cbPresets.Text,'ComputerInHighScore',false);
     cbSaveOnClose.Checked:=ReadBool(cbPresets.Text,'SaveOnClose',true);
     cbSaveLibOnExit.Checked:=ReadBool(cbPresets.Text,'SaveLibOnExit',true);
  finally
     Free;
  end;
end;

procedure TGameOptions.SaveOptions;
var s  : string;
    i  : integer;
begin
  with TINIFile.Create(ChangeFileExt(Application.ExeName,'.ini')) do
  try
     WriteString('General','DialogLanguage',cbLanguage.Text);
     WriteString('General','Presets',cbPresets.Items.CommaText);
     WriteString('General','CurrentPreset',cbPresets.Text);
     s:=sgLetters.Cells[0,1];
     for i:=2 to sgLetters.RowCount-1 do s:=s+','+sgLetters.Cells[0,i];
     WriteString(cbPresets.Text,'Letters',s);
     s:=sgLetters.Cells[1,1];
     for i:=2 to sgLetters.RowCount-1 do s:=s+','+sgLetters.Cells[1,i];
     WriteString(cbPresets.Text,'LetterCount',s);
     s:=sgLetters.Cells[2,1];
     for i:=2 to sgLetters.RowCount-1 do s:=s+','+sgLetters.Cells[2,i];
     WriteString(cbPresets.Text,'LetterValue',s);
     WriteInteger(cbPresets.Text,'LetterSet',cbLettersSet.ItemIndex);
     WriteInteger(cbPresets.Text,'DialogLanguage',cbLanguage.ItemIndex);
     WriteString(cbPresets.Text,'CurrentLettersCount',edLetterCount.Text);
     WriteInteger(cbPresets.Text,'Color1',c1.Color);
     WriteInteger(cbPresets.Text,'Color2',c2.Color);
     WriteInteger(cbPresets.Text,'Color3',c3.Color);
     WriteInteger(cbPresets.Text,'Color4',c4.Color);
     WriteInteger(cbPresets.Text,'Color5',c5.Color);
     WriteInteger(cbPresets.Text,'Color6',c6.Color);
     WriteInteger(cbPresets.Text,'Color7',c7.Color);
     WriteInteger(cbPresets.Text,'PlayerColor1',pnPlayerColor1.Color);
     WriteInteger(cbPresets.Text,'PlayerColor2',pnPlayerColor2.Color);
     WriteInteger(cbPresets.Text,'PlayerColor3',pnPlayerColor3.Color);
     WriteInteger(cbPresets.Text,'PlayerColor4',pnPlayerColor4.Color);
     WriteBool(cbPresets.Text,'UsePlayerColor',cbPlayerColored.Checked);
     WriteBool(cbPresets.Text,'ShowErrors',cbShowErrors.Checked);
     WriteString(cbPresets.Text,'FontName',lbFontName.Font.Name);
     WriteString(cbPresets.Text,'LetterSize',edLetterSize.Text);
     WriteString(cbPresets.Text,'ValueSize',edValueSize.Text);
     WriteString(cbPresets.Text,'DictionaryName',FDictionaryName);
     WriteInteger(cbPresets.Text,'Dimensions',rgDimensions.ItemIndex);

     WriteBool(cbPresets.Text,'SoundOnChat',cbSoundOnChat.Checked);
     WriteBool(cbPresets.Text,'SoundOnMove',cbSoundOnMove.Checked);
     WriteBool(cbPresets.Text,'SoundOnPoll',cbSoundOnPoll.Checked);
     WriteString(cbPresets.Text,'SoundName',edSoundName.Text);

     WriteBool(cbPresets.Text,'ResetLetters',cbResetLetters.Checked);
     WriteBool(cbPresets.Text,'Coordinates',cbCoordinates.Checked);
     WriteBool(cbPresets.Text,'DoubleFirstMove',cbDoubleFirstMove.Checked);
     WriteBool(cbPresets.Text,'ComputerInHighScore',cbComputerInHighScore.Checked);
     WriteBool(cbPresets.Text,'SaveOnClose',cbSaveOnClose.Checked);
     WriteBool(cbPresets.Text,'SaveLibOnExit',cbSaveLibOnExit.Checked);
  finally
     Free;
  end;
end;

{ ----- gbDictionary ----- }

function TGameOptions.LoadDictionary(const FileName:string):boolean;
begin
   Result:=Dictionary.LoadAsText(FileName);
   sgLibraryInfo.Cells[0,0]:=Language.Translate['file name:']; sgLibraryInfo.Cells[1,0]:=ExtractFileName(Dictionary.DictFileName);
   sgLibraryInfo.Cells[0,1]:=Language.Translate['file size:']; sgLibraryInfo.Cells[1,1]:=Dictionary.DictFileSize;
   sgLibraryInfo.Cells[0,2]:=Language.Translate['file date:']; sgLibraryInfo.Cells[1,2]:=Dictionary.DictFileDate;
   sgLibraryInfo.Cells[0,3]:=Language.Translate['number of words:']; sgLibraryInfo.Cells[1,3]:=Dictionary.DictWordCount;
   FDictionaryName:=ExtractFileName(FileName);
end;

procedure TGameOptions.sgLibraryInfoDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
   sgLibraryInfo.Canvas.Brush.Color:=clBtnFace;
   sgLibraryInfo.Canvas.Brush.Style:=bsSolid;
   sgLibraryInfo.Canvas.FillRect(Rect);
   sgLibraryInfo.Canvas.TextRect(Rect,Rect.Left,Rect.Top,sgLibraryInfo.Cells[aCol,aRow]);
end;

procedure TGameOptions.btnLoadDictionaryClick(Sender: TObject);
begin
   OpenDialog.FileName:='*.dic';
   Opendialog.Filter:=Language.Translate['Dictionaries']+' [*.dic]|*.dic';
   if OpenDialog.Execute then
   begin
      LoadDictionary(OpenDialog.FileName);
      btnSavePresets.Enabled:=true;
   end;
end;

procedure TGameOptions.btnSaveDictionaryClick(Sender: TObject);
begin
   if SaveDialog.Execute then Dictionary.SaveAsText(SaveDialog.FileName);
end;

{ ----- gbWord ----- }

procedure TGameOptions.edWordChange(Sender: TObject);
var i:integer;
begin
   if Dictionary.Find(edWord.Text,i) then ChangeWord(i) else lbWord.Caption:=Language.Translate[' not found'];
end;

procedure TGameOptions.edWordKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   case Key of
    ke_CursorUp : if edWord.Tag<Dictionary.Count-1 then ChangeWord(edWord.Tag+1);
    ke_CursorDown : if edWord.Tag>0 then ChangeWord(edWord.Tag-1);
   end;
end;

procedure TGameOptions.ChangeWord(i: integer);
begin
   edWord.Tag:=i;
   edWord.Text:=Dictionary[edWord.Tag];
   edMeaning.Text:=Dictionary.Meaning[edWord.Tag];
   lbWord.Caption:=inttostr(Dictionary.IndexOf(Dictionary[edWord.Tag])+1)+'/'+inttostr(Dictionary.Count);
end;

procedure TGameOptions.btnAddClick(Sender: TObject);
var i:integer;
begin
   if not Dictionary.Find(edWord.Text,i) then edWord.Tag:=Dictionary.Add(edWord.Text);
   Dictionary.Meaning[edWord.Tag]:=edMeaning.Text;
end;

procedure TGameOptions.btnDeleteClick(Sender: TObject);
var i:integer;
begin
   if Dictionary.Find(edWord.Text,i) then Dictionary.Delete(i);
end;

{ ----- gbLetters ----- }

procedure TGameOptions.sgLettersKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
var i,z:integer;
begin
   z:=sgLetters.Selection.Bottom;
   i:=sgLetters.RowCount-1;
   if (z=i) then //last col
   begin
      if (sgLetters.Cells[0,i]<>'') and (Key=ke_CursorDown) then //col before has data, key down was pressed
      begin
        sgLetters.RowCount:=sgLetters.RowCount+1;
        sgLetters.Cells[0,sgLetters.RowCount-1]:='';
        sgLetters.Cells[1,sgLetters.RowCount-1]:='';
        sgLetters.Cells[2,sgLetters.RowCount-1]:='';
        sgLetters.Selection:=TGridRect(Bounds(0,sgLetters.RowCount-1,0,sgLetters.RowCount-1));
        btnSavePresets.Enabled:=true;
      end;
   end else
   begin
      //a col was deleted completely
      if (sgLetters.Cells[0,z]='') and (sgLetters.Cells[1,z]='') and (sgLetters.Cells[2,z]='') then
      begin
        for i:=z to sgLetters.RowCount-2 do //if data not from the end were deleted
        begin
          sgLetters.Cells[0,i]:=sgLetters.Cells[0,i+1];
          sgLetters.Cells[1,i]:=sgLetters.Cells[1,i+1];
          sgLetters.Cells[2,i]:=sgLetters.Cells[2,i+1];
        end;
        sgLetters.RowCount:=sgLetters.RowCount-1;
        btnSavePresets.Enabled:=true;
      end;
      //last col is empty
      if (sgLetters.Cells[0,i]='') and (sgLetters.Cells[1,i]='') and (sgLetters.Cells[2,i]='') then
         sgLetters.RowCount:=sgLetters.RowCount-1;
   end;
   //is it a known letterset?
   cbLettersSet.ItemIndex:=LettersSet;
end;

procedure TGameOptions.edKeyPressNumberOnly(Sender: TObject; var Key: Char);
begin
   if not (Key in ['0'..'9',#8]) then Key:=#0;
end;

procedure TGameOptions.edKeyUpCursorUpDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   case Key of
    ke_CursorUp : (Sender as TEdit).Text:=inttostr(strtoint((Sender as TEdit).Text)+1);
    ke_CursorDown : (Sender as TEdit).Text:=inttostr(strtoint((Sender as TEdit).Text)-1);
   end;
end;

{ ----- Design ----- }

procedure TGameOptions.ColorClick(Sender: TObject);
begin
   ColorDialog.Color:=(Sender as TPanel).Color;
   if ColorDialog.Execute then
   begin
      (Sender as TPanel).Color:=ColorDialog.Color;
      (Sender as TPanel).Font.Color:=LightOrDark(ColorDialog.Color);
      if (Sender as TPanel).Tag<7 then FieldColor[(Sender as TPanel).Tag]:=(Sender as TPanel).Color;
      if assigned(FOnChanged) then FOnChanged;
      btnSavePresets.Enabled:=true;
   end;
end;

procedure TGameOptions.cbPlayerColoredClick(Sender: TObject);
begin
   if assigned(FOnChanged) then FOnChanged;
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.btnFontClick(Sender: TObject);
begin
   FontDialog.Font.Name:=lbFontName.Caption;
   if FontDialog.Execute then
   begin
      lbFontName.Font:=FontDialog.Font;
      lbFontName.Font.Size:=8;
      lbFontName.Caption:=FontDialog.Font.Name;
      if assigned(FOnChanged) then FOnChanged;
      btnSavePresets.Enabled:=true;
   end;
end;

procedure TGameOptions.edFontChange(Sender: TObject);
const MaxValue=100;
      MinValue=1;
begin
   if StrToIntDef((Sender as TEdit).Text,0)<MinValue then (Sender as TEdit).Text:=inttostr(MinValue);
   if StrToIntDef((Sender as TEdit).Text,255)>MaxValue then (Sender as TEdit).Text:=inttostr(MaxValue);
   if assigned(FOnChanged) then FOnChanged;
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.btnSavePresetsClick(Sender: TObject);
begin
   with TStringList.Create do
   try
     AddStrings(cbPresets.Items);
     Sorted:=true;
     Duplicates:=dupIgnore;
     Add(cbPresets.Text);
     cbPresets.Items.CommaText:=CommaText;
   finally
     Free;
   end;
   SaveOptions;
   btnSavePresets.Enabled:=false;
end;

procedure TGameOptions.btnLoadPresetsClick(Sender: TObject);
begin
   LoadOptions(cbPresets.Text);
   if FDictionaryName<>Dictionary.DictFileName then LoadDictionary(FDictionaryName);
   if assigned(FOnChanged) then FOnChanged;
   btnSavePresets.Enabled:=false;
end;

procedure TGameOptions.cbPresetsKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   if (Key=ke_Enter) and btnSavePresets.Enabled then btnSavePresetsClick(self);
end;

function TGameOptions.GetPlayerColor(index: Byte): TColor;
begin
  if cbPlayerColored.Checked then
    case index of
      0 : Result:=pnPlayerColor1.Color;
      1 : Result:=pnPlayerColor2.Color;
      2 : Result:=pnPlayerColor3.Color;
      3 : Result:=pnPlayerColor4.Color;
      else Result:=clBlack;
    end //case
  else Result:=clBlack;
end;

procedure TGameOptions.btnSoundClick(Sender: TObject);
begin
   OpenDialog.FileName:='*.wav';
   Opendialog.Filter:='WAVE [*.wav]|*.wav';
   if OpenDialog.Execute then edSoundName.Text:=OpenDialog.FileName else edSoundName.Text:='';
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.OptionsChanged(Sender: TObject);
begin
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.edLetterCountExit(Sender: TObject);
const MaxLetterCount=24;
      MinLetterCount=2;
begin
   if StrToIntDef(edLetterCount.Text,0)<MinLetterCount then edLetterCount.Text:=inttostr(MinLetterCount);
   if StrToIntDef(edLetterCount.Text,255)>MaxLetterCount then edLetterCount.Text:=inttostr(MaxLetterCount);
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.cbLanguageChange(Sender: TObject);
begin
   Language.CurrentLanguage:=cbLanguage.Text;
   sgLetters.Cells[0,0]:=Language.Translate['Letter:'];
   sgLetters.Cells[1,0]:=Language.Translate['Count:'];
   sgLetters.Cells[2,0]:=Language.Translate['Value:'];
   btnSavePresets.Enabled:=true;
end;

procedure TGameOptions.FormHide(Sender: TObject);
begin
   if cbSaveOnClose.Checked then SaveOptions;
end;

procedure TGameOptions.cbLettersSetChange(Sender: TObject);
begin
  LettersSet:=cbLettersSet.ItemIndex;
end;

function TGameOptions.GetLettersSet: integer;
var i:integer;
    s1,s2,s3:string;
begin
   s1:='';s2:='';s3:='';
   for i:=1 to sgLetters.RowCount-1 do
   begin
     s1:=s1+sgLetters.Cells[0,i]+',';
     s2:=s2+sgLetters.Cells[1,i]+',';
     s3:=s3+sgLetters.Cells[2,i]+',';
   end;
   delete(s1,length(s1),1); delete(s2,length(s2),1); delete(s3,length(s3),1);
   Result:=high(LettersByLanguage)+1;
   for i:=0 to high(LettersByLanguage) do
     if (s1=LettersByLanguage[i].Letters) and
        (s2=LettersByLanguage[i].LetterCount) and
        (s3=LettersByLanguage[i].LetterValue) then Result:=i;
end;

procedure TGameOptions.SetLettersSet(const Value: integer);
var i:integer;
    tmp:array[0..2] of TStringList;
begin
  if Value<high(LettersByLanguage)+1 then
  begin
    for i:=0 to 2 do
    begin
      tmp[i]:=TStringList.Create;
      tmp[i].Delimiter:=',';
    end;
    try
      tmp[0].CommaText:=LettersByLanguage[Value].Letters;
      tmp[1].CommaText:=LettersByLanguage[Value].LetterCount;
      tmp[2].CommaText:=LettersByLanguage[Value].LetterValue;
      sgLetters.RowCount:=tmp[0].Count+1;
      for i:=0 to tmp[0].Count-1 do
      begin
        sgLetters.Cells[0,i+1]:=tmp[0][i];
        sgLetters.Cells[1,i+1]:=tmp[1][i];
        sgLetters.Cells[2,i+1]:=tmp[2][i];
      end;
    finally
      for i:=0 to 2 do tmp[i].Free;
    end;
  end;//Value<'special' (6)
end;

end.
