unit Options;

interface

uses
  Unicode, XMLUtils, Dockable,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, ComCtrls, TntComCtrls, TntStdCtrls, DBCtrls;

type
  TfmOptions = class(TfrmDockable)
    Panel1: TPanel;
    Panel3: TPanel;
    btnOK: TButton;
    btnCancel: TButton;
    Button6: TButton;
    Panel2: TPanel;
    PageOptions: TPageControl;
    tabSystem: TTabSheet;
    tabDialog: TTabSheet;
    tabBlock: TTabSheet;
    tabPlugins: TTabSheet;
    tabNetWork: TTabSheet;
    tabUser: TTabSheet;
    Label1: TLabel;
    Bevel2: TBevel;
    chkAutoStart: TCheckBox;
    chkCloseMin: TCheckBox;
    chkStartMin: TCheckBox;
    Label6: TLabel;
    lblPluginScan: TLabel;
    btnAddPlugin: TButton;
    btnConfigPlugin: TButton;
    btnRemovePlugin: TButton;
    txtPluginDir: TEdit;
    btnBrowsePluginPath: TButton;
    lstPlugins: TTntListView;
    chkAutoAway: TCheckBox;
    txtAwayTime: TEdit;
    spnAway: TUpDown;
    Label3: TLabel;
    txtXATime: TEdit;
    spnXA: TUpDown;
    Label4: TLabel;
    Label11: TLabel;
    Bevel4: TBevel;
    lblProxyHost: TLabel;
    lblProxyPort: TLabel;
    lblProxyUsername: TLabel;
    lblProxyPassword: TLabel;
    Label28: TLabel;
    txtProxyHost: TEdit;
    txtProxyPort: TEdit;
    chkProxyAuth: TCheckBox;
    txtProxyUsername: TEdit;
    txtProxyPassword: TEdit;
    cboProxyApproach: TComboBox;
    Label5: TLabel;
    Bevel6: TBevel;
    Label13: TLabel;
    Bevel7: TBevel;
    TntLvBlock: TTntListView;
    TntLvUnBlock: TTntListView;
    btnUnBlock: TButton;
    btnBlock: TButton;
    TntLabel1: TTntLabel;
    TntLabel2: TTntLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label18: TLabel;
    txtXFerPath: TEdit;
    btnTransferBrowse: TButton;
    Label19: TLabel;
    Bevel9: TBevel;
    FontDialog1: TFontDialog;
    Label20: TLabel;
    Bevel10: TBevel;
    Label21: TLabel;
    btnVcard: TButton;
    tabShare: TTabSheet;
    Label22: TLabel;
    Bevel11: TBevel;
    TntLabel3: TTntLabel;
    TntLabel4: TTntLabel;
    Label23: TLabel;
    Label24: TLabel;
    TntLVUnShare: TTntListView;
    TntLVShare: TTntListView;
    Button1: TButton;
    Button2: TButton;
    Label25: TLabel;
    Bevel12: TBevel;
    chkOicq: TCheckBox;
    chkMsn: TCheckBox;
    chkIcq: TCheckBox;
    chkAim: TCheckBox;
    chkYahoo: TCheckBox;
    btnCfgOicq: TButton;
    btnCfgMsn: TButton;
    btnCfgIcq: TButton;
    btnCfgAim: TButton;
    btnCfgYahoo: TButton;
    Label27: TLabel;
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Label2: TLabel;
    Bevel3: TBevel;
    chkSound: TCheckBox;
    chkOnline: TCheckBox;
    chkMsg: TCheckBox;
    btnSound: TButton;
    Label16: TLabel;
    Bevel8: TBevel;
    Label17: TLabel;
    ChatFont: TLabel;
    btnFont: TButton;
    chkEmoticons: TCheckBox;
    Label29: TLabel;
    Bevel5: TBevel;
    Label12: TLabel;
    chkRosterAlpha: TCheckBox;
    trkRosterAlpha: TTrackBar;
    txtRosterAlpha: TEdit;
    spnRosterAlpha: TUpDown;
    chkToastAlpha: TCheckBox;
    trkToastAlpha: TTrackBar;
    txtToastAlpha: TEdit;
    spnToastAlpha: TUpDown;
    chkBusy: TCheckBox;
    txtToastDuration: TEdit;
    Label10: TLabel;
    Bevel1: TBevel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    txtReconnectTries: TEdit;
    spnAttempts: TUpDown;
    txtReconnectTime: TEdit;
    spnTime: TUpDown;
    lblSocksHost: TLabel;
    lblSocksPort: TLabel;
    lblSocksType: TLabel;
    lblSocksUsername: TLabel;
    lblSocksPassword: TLabel;
    Label26: TLabel;
    Bevel13: TBevel;
    chkSocksAuth: TCheckBox;
    txtSocksHost: TEdit;
    txtSocksPort: TEdit;
    cboSocksType: TComboBox;
    txtSocksUsername: TEdit;
    txtSocksPassword: TEdit;
    chkSSL: TCheckBox;
    CheckBox1: TLabel;
    CheckBox2: TLabel;
    CheckBox3: TLabel;
    CheckBox4: TLabel;
    CheckBox5: TLabel;
    Image4: TImage;
    Image5: TImage;
    Image6: TImage;
    Image7: TImage;
    Image8: TImage;
    Image9: TImage;
    Image10: TImage;
    Image11: TImage;
    Image12: TImage;
    Image13: TImage;
    Image14: TImage;
    Label30: TLabel;
    Bevel14: TBevel;
    Label31: TLabel;
    Image15: TImage;
    btnPassWord: TButton;
    chkAutoUpdate: TCheckBox;
    btnUpdate: TButton;
    chkFlash: TCheckBox;
    chkTrayNotify: TCheckBox;
    tabSkin: TTabSheet;
    Label32: TLabel;
    Bevel15: TBevel;
    Label33: TLabel;
    edtSkinfilename: TEdit;
    btnskinfile: TButton;
    opendlgskn: TOpenDialog;
    GroupBox1: TGroupBox;
    pnlpreview: TPanel;
    RadioGroupSkin: TRadioGroup;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure chkAutoAwayClick(Sender: TObject);
    procedure chkRosterAlphaClick(Sender: TObject);
    procedure chkToastAlphaClick(Sender: TObject);
    procedure txtRosterAlphaChange(Sender: TObject);
    procedure trkRosterAlphaChange(Sender: TObject);
    procedure trkToastAlphaChange(Sender: TObject);
    procedure txtToastAlphaChange(Sender: TObject);
    procedure btnConfigPluginClick(Sender: TObject);
    procedure lblPluginScanClick(Sender: TObject);
    procedure btnBrowsePluginPathClick(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure cboProxyApproachChange(Sender: TObject);
    procedure chkProxyAuthClick(Sender: TObject);
    procedure TntLvInfoTip(Sender: TObject; Item: TListItem;
      var InfoTip: string);
    procedure TntLvCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure tabBlockEnter(Sender: TObject);
    procedure TntLvUnBlockEnter(Sender: TObject);
    procedure TntLvBlockEnter(Sender: TObject);
    procedure btnBlockClick(Sender: TObject);
    procedure btnUnBlockClick(Sender: TObject);
    procedure btnSoundClick(Sender: TObject);
    procedure btnFontClick(Sender: TObject);
    procedure btnTransferBrowseClick(Sender: TObject);
    procedure btnVcardClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure btnCfgOicqClick(Sender: TObject);
    procedure btnCfgMsnClick(Sender: TObject);
    procedure btnCfgIcqClick(Sender: TObject);
    procedure btnCfgAimClick(Sender: TObject);
    procedure btnCfgYahooClick(Sender: TObject);
    procedure btnPassWordClick(Sender: TObject);
    procedure btnUpdateClick(Sender: TObject);
    procedure chkOicqClick(Sender: TObject);
    procedure chkIcqClick(Sender: TObject);
    procedure chkMsnClick(Sender: TObject);
    procedure chkAimClick(Sender: TObject);
    procedure chkYahooClick(Sender: TObject);
    procedure tabShareEnter(Sender: TObject);
    procedure tabSkinShow(Sender: TObject);
    procedure RadioGroupSkinClick(Sender: TObject);
    procedure btnskinfileClick(Sender: TObject);
    procedure edtSkinfilenameChange(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
  private
    { Private declarations }

    procedure loadPlugins();
    procedure savePlugins();
    procedure scanPluginDir(selected: TWidestringList);
    procedure CheckPluginDll(dll: WideString; selected: TWidestringlist);


    procedure LoadPrefSystem;
    procedure LoadPrefDialog;
    procedure LoadPrefPlugins;
    procedure LoadPrefNetWork;
    procedure LoadPrefBlock;
    procedure LoadPrefShare;
    procedure LoadPrefTransports;
    procedure LoadPrefSkin;


    procedure SavePrefSystem;
    procedure SavePrefDialog;
    procedure SavePrefPlugins;
    procedure SavePrefNetWork;
    procedure SavePrefBlock;
    procedure SavePrefShare;
    procedure SavePrefTransports;
    procedure SavePrefSkin;

  public
    { Public declarations }
    procedure LoadPrefs;
    procedure SavePrefs;
    procedure Disabletab(tab: TTabSheet);
  end;

type
  TRegProc = function: HResult; stdcall;

resourcestring
  sRegPluginError = '插件无法在Windows中注册.';
  sPrefsXFerDir = '选择下载目录';

var
  fmOptions: TfmOptions;

procedure StartOptions(PageIndex: Integer = 0);


implementation

{$R *.dfm}
uses
  GnuGetText, PrefController, Shellapi, ExUtils, FileCtrl,
  ActiveX, COMController, ComObj, AnyQCOM_TLB, Registry,
  PathSelector, Session, vcard, cfgtransport, RiserWindow, iq, Password,
  Jabber1, AutoUpdate, XMLTag, JabberConst;

const
  RUN_ONCE: string = '\Software\Microsoft\Windows\CurrentVersion\Run';

procedure StartOptions(PageIndex: Integer = 0);
var
  f: TfmOptions;
begin
  f := TfmOptions.Create(Application);
  f.LoadPrefs;
  f.PageOptions.ActivePageIndex := PageIndex;
    // frmAnyQ.PreModal(f);
  f.ShowModal;
    //frmAnyQ.PostModal();
  f.Free();
end;

procedure TfmOptions.LoadPrefs;
begin
  LoadPrefSystem;
  LoadPrefDialog;
  LoadPrefPlugins;
  LoadPrefNetWork;
  LoadPrefBlock;
  LoadPrefShare;
  LoadPrefTransports;
  LoadPrefSkin;
end;

procedure TfmOptions.SavePrefs;
begin
  with MainSession.Prefs do
  begin
    BeginUpdate();

    SavePrefSystem;
    SavePrefDialog;
    SavePrefPlugins;
    SavePrefNetWork;
    SavePrefBlock;
    SavePrefShare;
    SavePrefTransports;
    SavePrefSkin;
    endUpdate();
  end;

  MainSession.FireEvent('/session/prefs', nil);
end;

procedure TfmOptions.FormCreate(Sender: TObject);
begin
  TranslateProperties(Self);
  if not MainSession.Active then
  begin
    Disabletab(tabBlock);
    Disabletab(tabShare);
    Disabletab(tabUser);
  end;
  tabPlugins.TabVisible := False;
//  tabUser.TabVisible := MainSession.Active;
//  tabBlock.TabVisible := MainSession.Active;
  PageOptions.ActivePage := tabSystem;
  MainSession.Prefs.RestorePosition(Self);

{
  SkinViewForm := TSkinViewForm.Create(Application);
  SkinViewForm.Parent := pnlpreview;
  SkinViewForm.Align := alClient;
  SkinViewForm.Show;
  SkinViewForm.SkinData1.Active := true;   {}
{}
end;

procedure TfmOptions.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  MainSession.Prefs.SavePosition(Self);
  Action := caFree;
end;

procedure TfmOptions.LoadPrefDialog;
var
  value: integer;
begin
  with MainSession.Prefs do begin
    // Dialog Options
    chkRosterAlpha.Checked := getBool('roster_alpha');
    chkToastAlpha.Checked := getBool('toast_alpha');
    chkBusy.Checked := getBool('warn_closebusy');
    chkRosterAlphaClick(Self);
    if chkRosterAlpha.Checked then begin
      trkRosterAlpha.Position := getInt('roster_alpha_val');
      spnRosterAlpha.Position := trkRosterAlpha.Position;
    end
    else begin
      trkRosterAlpha.Position := 255;
      spnRosterAlpha.Position := 255;
    end;

    chkToastAlphaClick(Self);
    if chkToastAlpha.Checked then begin
      trkToastAlpha.Position := getInt('toast_alpha_val');
      spnToastAlpha.Position := trkToastAlpha.Position;
    end
    else begin
      trkToastAlpha.Position := 255;
      spnToastAlpha.Position := 255;
    end;

    txtToastDuration.Text := IntToStr(getInt('toast_duration'));
    chkEmoticons.Checked := getBool('emoticons');

    with ChatFont do begin
      Font.Name := getString('font_name');
      Font.Size := getInt('font_size');
      Font.Color := TColor(getInt('font_color'));
      Font.Charset := getInt('font_charset');
      if (Font.Charset = 0) then Font.Charset := 1;

      Font.Style := [];
      if (getBool('font_bold')) then Font.Style := Font.Style + [fsBold];
      if (getBool('font_italic')) then Font.Style := Font.Style + [fsItalic];
      if (getBool('font_underline')) then Font.Style := Font.Style + [fsUnderline];
    end;

    chkSound.Checked := getBool('notify_sounds');
    chkOnline.Checked := getInt('notify_online') > 0;
    value := getInt('notify_normalmsg');
    chkMsg.Checked := (value and notify_toast) = notify_toast;
    chkFlash.Checked := (value and notify_flash) = notify_flash;
    chkTrayNotify.Checked := (value and notify_tray) = notify_tray;
  end;
end;

procedure TfmOptions.LoadPrefPlugins;
var
  dir: Widestring;
begin
  with MainSession.Prefs do begin
        // plugins
    dir := getString('plugin_dir');
    if (dir = '') then
      dir := ExtractFilePath(Application.ExeName) + 'plugins';

    if (not DirectoryExists(dir)) then
      dir := ExtractFilePath(Application.ExeName) + 'plugins';

    txtPluginDir.Text := dir;
    loadPlugins();
  end;
end;

procedure TfmOptions.LoadPrefSystem;
var
  reg: TRegistry;
begin
  with MainSession.Prefs do begin
    chkAutoUpdate.Checked := getBool('auto_updates');
    chkAutoStart.Checked := getBool('auto_start');
    chkStartMin.Checked := getBool('min_start');
    chkCloseMin.Checked := getBool('close_min');
    chkAutoAway.Checked := getBool('auto_away');
    spnAway.Position := getInt('away_time');
    spnXA.Position := getInt('xa_time');
    txtXFerPath.Text := getString('xfer_path');

    // Check to see if Exodus runs when windows starts
    reg := TRegistry.Create();
    try
      reg.RootKey := HKEY_CURRENT_USER;
      reg.OpenKey(RUN_ONCE, true);
      chkAutoStart.Checked := (reg.ValueExists('AnyQ'));
      reg.CloseKey();
    finally
      reg.Free();
    end;
  end;
end;

procedure TfmOptions.SavePrefDialog;
var
  value: Integer;
begin
  with MainSession.Prefs do begin
        // Dialog Prefs
    setBool('roster_alpha', chkRosterAlpha.Checked);
    setInt('roster_alpha_val', trkRosterAlpha.Position);
    setBool('toast_alpha', chkToastAlpha.Checked);
    setInt('toast_alpha_val', trkToastAlpha.Position);
    setInt('toast_duration', SafeInt(txtToastDuration.Text));

    setBool('warn_closebusy', chkBusy.Checked);

    setBool('notify_sounds', chkSound.Checked);
    if chkOnline.Checked then
      setInt('notify_online', 1)
    else
      setInt('notify_online', 0);

    value := 0;
    if chkMsg.Checked then value := value or notify_toast;
    if chkFlash.Checked then value := value or notify_flash;
    if chkTrayNotify.Checked then value := value or notify_tray;

    setInt('notify_normalmsg', value);
    setInt('notify_chatactivity', value);
    setInt('notify_roomactivity', value);
    setInt('notify_newchat', value);

    setBool('emoticons', chkEmoticons.Checked);

    with ChatFont do begin
      setString('font_name', Font.Name);
      setInt('font_charset', Font.Charset);
      setInt('font_size', Font.Size);
      setBool('font_bold', (fsBold in Font.Style));
      setBool('font_italic', (fsItalic in Font.Style));
      setBool('font_underline', (fsUnderline in Font.Style));
      setInt('font_color', TColor(Font.Color));
    end;
  end;
end;

procedure TfmOptions.SavePrefPlugins;
begin
  with MainSession.Prefs do begin
        // Plugins
    setString('plugin_dir', txtPluginDir.Text);
    savePlugins();
  end;
end;

procedure TfmOptions.SavePrefSystem;
begin
  with MainSession.Prefs do
  begin
    setBool('auto_updates', chkAutoUpdate.Checked);
    setBool('auto_start', chkAutoStart.Checked);
    setBool('min_start', chkStartMin.Checked);
    setBool('close_min', chkCloseMin.Checked);
    setBool('auto_away', chkAutoAway.Checked);
    setInt('away_time', spnAway.Position);
    setInt('xa_time', spnXA.Position);
    setString('xfer_path', txtXFerPath.Text);
  end;
end;

procedure TfmOptions.chkAutoAwayClick(Sender: TObject);
begin
  spnAway.Enabled := chkAutoAway.Checked;
  txtAwayTime.Enabled := chkAutoAway.Checked;
  spnXA.Enabled := chkAutoAway.Checked;
  txtXATime.Enabled := chkAutoAway.Checked;
end;

procedure TfmOptions.chkRosterAlphaClick(Sender: TObject);
begin
  trkRosterAlpha.Enabled := chkRosterAlpha.Checked;
  spnRosterAlpha.Enabled := chkRosterAlpha.Checked;
  txtRosterAlpha.Enabled := chkRosterAlpha.Checked;
end;

procedure TfmOptions.chkToastAlphaClick(Sender: TObject);
begin
  trkToastAlpha.Enabled := chkToastAlpha.Checked;
  spnToastAlpha.Enabled := chkToastAlpha.Checked;
  txtToastAlpha.Enabled := chkToastAlpha.Checked;
end;

procedure TfmOptions.txtRosterAlphaChange(Sender: TObject);
begin
  try
    trkRosterAlpha.Position := StrToInt(txtRosterAlpha.Text);
  except
  end;
end;

procedure TfmOptions.trkRosterAlphaChange(Sender: TObject);
begin
  spnRosterAlpha.Position := trkRosterAlpha.Position;
end;

procedure TfmOptions.trkToastAlphaChange(Sender: TObject);
begin
  spnToastAlpha.Position := trkToastAlpha.Position;
end;

procedure TfmOptions.txtToastAlphaChange(Sender: TObject);
begin
  try
    trkToastAlpha.Position := StrToInt(txtToastAlpha.Text);
  except
  end;
end;

procedure TfmOptions.CheckPluginDll(dll: WideString;
  selected: TWidestringlist);
var
  lib: ITypeLib;
  idx, i, j: integer;
  item: TTntListItem;
  tinfo, iface: ITypeInfo;
  tattr, iattr: PTypeAttr;
  r: cardinal;
  libname, obname, doc: WideString;
begin
    // load the .dll.  This SHOULD register the bloody thing if it's not, but that
    // doesn't seem to work for me.
  OleCheck(LoadTypeLibEx(PWideChar(dll), REGKIND_REGISTER, lib));

    // get the project name
  OleCheck(lib.GetDocumentation(-1, @libname, nil, nil, nil));

    // for each type in the project
  for i := 0 to lib.GetTypeInfoCount() - 1 do begin
        // get the info about the type
    OleCheck(lib.GetTypeInfo(i, tinfo));

        // get attributes of the type
    OleCheck(tinfo.GetTypeAttr(tattr));
        // is this a coclass?
    if (tattr.typekind <> TKIND_COCLASS) then continue;

        // for each interface that the coclass implements
    for j := 0 to tattr.cImplTypes - 1 do begin
            // get the type info for the interface
      OleCheck(tinfo.GetRefTypeOfImplType(j, r));
      OleCheck(tinfo.GetRefTypeInfo(r, iface));

            // get the attributes of the interface
      OleCheck(iface.GetTypeAttr(iattr));

            // is this the IAnyQPlugin interface?
      if (IsEqualGUID(iattr.guid, AnyQCOM_TLB.IID_IAnyQPlugin)) then begin
                // oho!  it IS.  Get the name of this coclass, so we can show
                // what we did.  Get the doc string, just to show off.
        OleCheck(tinfo.GetDocumentation(-1, @obname, @doc, nil, nil));
                // SysFreeString of obname and doc needed?  In C, yes, but here?

        item := lstPlugins.Items.Add();
        item.Caption := libname + '.' + obname;
        item.SubItems.Add(doc);
        item.SubItems.Add(dll);

                // check to see if this is selected
        idx := selected.IndexOf(item.Caption);
        item.Checked := (idx >= 0);
      end;
      iface.ReleaseTypeAttr(iattr);
    end;
    tinfo.ReleaseTypeAttr(tattr);
  end;
end;

procedure TfmOptions.loadPlugins;
var
  sl: TWidestringList;
begin
    // load the listview
  lstPlugins.Clear();

    // get the list of selected plugins..
  sl := TWidestringList.Create();
  MainSession.Prefs.fillStringlist('plugin_selected', sl);

    // Scan the director
  scanPluginDir(sl);

  with lstPlugins do begin
    btnConfigPlugin.Enabled := (Items.Count > 0);
    btnRemovePlugin.Enabled := (Items.Count > 0);
  end;

  sl.Free();
end;

procedure TfmOptions.savePlugins;
var
  i: integer;
  item: TTntListItem;
  sl: TWidestringlist;
  fl: TWidestringlist;

    // stuff for reg
  LibHandle: THandle;
  RegProc: TRegProc;
begin
    // save all "checked" captions
  sl := TWidestringlist.Create();
  fl := TWidestringlist.Create();

  for i := 0 to lstPlugins.Items.Count - 1 do begin
    item := lstPlugins.Items[i];
    fl.Add(item.SubItems[1]);

    if (item.Checked) then begin
            // save the Classname
      sl.Add(item.Caption);

            // try to register it??
            // From the TRegSvr example.
      LibHandle := LoadLibrary(PChar(string(item.SubItems[1])));
      if LibHandle = 0 then begin
        ShowRiserWindow(nil, sRegPluginError, ico_info);
                //MessageBox(Handle,Pchar(sRegPluginError), '错误', MB_OK OR MB_ICONERROR);
        continue;
      end;


      try
        @RegProc := GetProcAddress(LibHandle, 'DllRegisterServer');
        if @RegProc = nil then begin
          ShowRiserWindow(nil, sRegPluginError, ico_info);
                    //MessageBox(Handle,Pchar(sRegPluginError), '错误', MB_OK OR MB_ICONERROR);
          continue;
        end;

        if RegProc <> 0 then begin
          ShowRiserWindow(nil, sRegPluginError, ico_info);
                    //MessageBox(Handle,Pchar(sRegPluginError), '错误', MB_OK OR MB_ICONERROR);
          continue;
        end;

      finally
        FreeLibrary(LibHandle);
      end;

    end;
  end;

  MainSession.Prefs.setStringlist('plugin_selected', sl);
  MainSession.Prefs.setStringlist('plugin_files', fl);
  ReloadPlugins(sl);
  sl.Free();
  fl.Free();
end;

procedure TfmOptions.scanPluginDir(selected: TWidestringList);
var
  dir: Widestring;
  sr: TSearchRec;
begin
  dir := txtPluginDir.Text;
  if (not DirectoryExists(dir)) then exit;
  if (FindFirst(dir + '\\*.dll', faAnyFile, sr) = 0) then begin
    repeat
      CheckPluginDll(dir + '\' + sr.Name, selected);
    until FindNext(sr) <> 0;
    FindClose(sr);
  end;
end;

procedure TfmOptions.btnConfigPluginClick(Sender: TObject);
var
  li: TListItem;
  com_name: string;
begin
  li := lstPlugins.Selected;
  if (li = nil) then exit;
  com_name := li.Caption;
  ConfigurePlugin(com_name);
end;

procedure TfmOptions.lblPluginScanClick(Sender: TObject);
begin
  loadPlugins();
end;

procedure TfmOptions.btnBrowsePluginPathClick(Sender: TObject);
var
  p: string;
begin
    // Change the plugin dir
  p := txtPluginDir.Text;
  if (browsePath(p)) then begin
    if (p <> txtPluginDir.Text) then begin
      txtPluginDir.Text := p;
      loadPlugins();
    end;
  end;
end;

procedure TfmOptions.btnOKClick(Sender: TObject);
begin
  SavePrefs;
  Self.BringToFront();
end;

procedure TfmOptions.LoadPrefNetWork;
var
  i: integer;
begin
  with MainSession.Prefs do begin
        // reconnect config
    i := getInt('recon_tries');
    if (i <= 0) then i := 3;
    spnAttempts.Position := i;
    spnTime.Position := getInt('recon_time');

        // proxy config
    cboProxyApproach.ItemIndex := getInt('http_proxy_approach');
    cboProxyApproachChange(cboProxyApproach);
    txtProxyHost.Text := getString('http_proxy_host');
    txtProxyPort.Text := getString('http_proxy_port');
    chkProxyAuth.Checked := getBool('http_proxy_auth');
    chkProxyAuthClick(chkProxyAuth);
    txtProxyUsername.Text := getString('http_proxy_user');
    txtProxyPassword.Text := getString('http_proxy_password');
  end;
{
    with MainSession.Profile do begin
        cboSocksType.ItemIndex := SocksType;
        cboSocksTypeChange(cboSocksType);
        txtSocksHost.Text := SocksHost;
        txtSocksPort.Text := IntToStr(SocksPort);
        chkSocksAuth.Checked := SocksAuth;
        chkSocksAuthClick(chkSocksAuth);
        txtSocksUsername.Text := SocksUsername;
        txtSocksPassword.Text := SocksPassword;
    end;
   {}
end;

procedure TfmOptions.SavePrefNetWork;
begin
  with MainSession.Prefs do begin
        // reconnect config
    setInt('recon_tries', spnAttempts.Position);
    setInt('recon_time', spnTime.Position);

        // Network
    setInt('http_proxy_approach', cboProxyApproach.ItemIndex);
    setString('http_proxy_host', txtProxyHost.Text);
    setInt('http_proxy_port', StrToIntDef(txtProxyPort.Text, 0));
    setBool('http_proxy_auth', chkProxyAuth.Checked);
    setString('http_proxy_user', txtProxyUsername.Text);
    setString('http_proxy_password', txtProxyPassword.Text);
  end;
{
    with MainSession.profile do begin
        Host := txtHost.Text;
        Port := StrToIntDef(txtPort.Text, 5522);
        ssl := chkSSL.Checked;

        SocksType := cboSocksType.ItemIndex;
        SocksHost := txtSocksHost.Text;
        SocksPort := StrToIntDef(txtSocksPort.Text, 0);
        SocksAuth := chkSocksAuth.Checked;
        SocksUsername := txtSocksUsername.Text;
        SocksPassword := txtSocksPassword.Text;
    end;
{}
end;

procedure TfmOptions.cboProxyApproachChange(Sender: TObject);
begin
  if (cboProxyApproach.ItemIndex = http_proxy_custom) then begin
    txtProxyHost.Enabled := true;
    txtProxyPort.Enabled := true;
    chkProxyAuth.Enabled := true;
    lblProxyHost.Enabled := true;
    lblProxyPort.Enabled := true;
  end
  else begin
    txtProxyHost.Enabled := false;
    txtProxyPort.Enabled := false;
    chkProxyAuth.Enabled := false;
    chkProxyAuth.Checked := false;
    txtProxyUsername.Enabled := false;
    txtProxyPassword.Enabled := false;
    lblProxyHost.Enabled := false;
    lblProxyPort.Enabled := false;
    lblProxyUsername.Enabled := false;
    lblProxyPassword.Enabled := false;
  end;
end;

procedure TfmOptions.chkProxyAuthClick(Sender: TObject);
begin
  if (chkProxyAuth.Checked) then begin
    lblProxyUsername.Enabled := true;
    lblProxyPassword.Enabled := true;
    txtProxyUsername.Enabled := true;
    txtProxyPassword.Enabled := true;
  end
  else begin
    lblProxyUsername.Enabled := false;
    lblProxyPassword.Enabled := false;
    txtProxyUsername.Enabled := false;
    txtProxyPassword.Enabled := false;
  end;
end;

procedure TfmOptions.LoadPrefBlock;
var
  blockers: TWideStringList;
  i: Integer;
begin
  if not MainSession.Active then
  begin
    for i := 0 to tabBlock.ControlCount - 1 do
      tabBlock.Controls[i].Enabled := false;
    Label13.Enabled := True;
    exit;
  end;
  blockers := TWideStringList.Create();
  with MainSession.Prefs do
  begin
    fillStringlist('blockers', blockers);
    if getBool('block_nonroster') then
      with TntLvBlock.Items.Insert(0) do
        Caption := '所有其他用户'
    else
      with TntLvUnBlock.Items.Insert(0) do
        Caption := '所有其他用户';
    for i := 0 to MainSession.roster.Count - 1 do
    begin
      with MainSession.roster.Items[i] do
      begin
        if jid.jid = MainSession.BareJid then
          continue;
        if jid.user = '' then
          continue;
        if ask <> 'subscribe' then
          if ((subscription = 'none') or (subscription = '')
            or (subscription = 'remove')) then
            continue;
        if blockers.IndexOf(jid.jid) >= 0 then
          with TntLvBlock.Items.Add do
          begin
            caption := Nickname;
            SubItems.add(jid.jid);
          end
        else
        begin
          with TntLvUnBlock.Items.Add do
          begin
            caption := Nickname;
            SubItems.add(jid.jid);
          end
        end;
      end;
    end;
  end;
  blockers.Free;
end;

procedure TfmOptions.SavePrefBlock;
var
  blockers: TWideStringList;
  i: Integer;
begin
  if not MainSession.Active then
  begin
    exit;
  end;
  blockers := TWideStringList.Create();

  if TntLvUnBlock.Items.Count > 0 then
    if TntLvUnBlock.Items.Item[0].SubItems.count = 0 then
      MainSession.Prefs.setBool('block_nonroster', false);

  for i := 0 to TntLvBlock.Items.Count - 1 do
  begin
    if TntLvBlock.Items.Item[i].SubItems.count = 0 then
      MainSession.Prefs.setBool('block_nonroster', True)
    else
      blockers.Add(TntLvBlock.Items.Item[i].SubItems[0]);
  end;

  MainSession.Prefs.setStringlist('blockers', blockers);
  blockers.Free;
end;

procedure TfmOptions.TntLvInfoTip(Sender: TObject; Item: TListItem;
  var InfoTip: string);
begin
  if item.SubItems.Count > 0 then
    InfoTip := item.SubItems.Text;
end;

procedure TfmOptions.TntLvCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if Item.SubItems.Count > 0 then
    sender.Canvas.Font.Style := sender.Canvas.Font.Style - [fsBold]
  else
    sender.Canvas.Font.Style := sender.Canvas.Font.Style + [fsBold];

  DefaultDraw := true;
end;

procedure TfmOptions.tabBlockEnter(Sender: TObject);
begin
  if TntLvUnBlock.Enabled then
    TntLvUnBlock.SetFocus;
end;

procedure TfmOptions.TntLvUnBlockEnter(Sender: TObject);
begin
  btnUnBlock.Enabled := false;
  btnBlock.Enabled := TntLvUnBlock.Items.Count > 0;
end;

procedure TfmOptions.TntLvBlockEnter(Sender: TObject);
begin
  btnBlock.Enabled := false;
  btnUnBlock.Enabled := TntLvBlock.Items.Count > 0;
end;

procedure TfmOptions.btnBlockClick(Sender: TObject);
var
  s, d: TTntListItem;
  i: Integer;
begin
  if TntLvUnBlock.Selected <> nil then
  begin
    s := TntLvUnBlock.Items.item[TntLvUnBlock.Selected.Index];
    if s.SubItems.Count = 0 then
      d := TntLvBlock.Items.Insert(0)
    else
      d := TntLvBlock.Items.Add;
    d.Assign(s);
    TntLvUnBlock.Selected.Delete;
  end;
  for i := 0 to TntLvUnBlock.Items.Count - 1 do
    if TntLvUnBlock.Items.Item[i].Focused then
      TntLvUnBlock.Items.Item[i].Selected := true;
  TntLvUnBlock.SetFocus;
end;

procedure TfmOptions.btnUnBlockClick(Sender: TObject);
var
  s, d: TTntListItem;
  i: Integer;
begin
  if TntLvBlock.Selected <> nil then
  begin
    s := TntLvBlock.Items.item[TntLvBlock.Selected.Index];
    if s.SubItems.Count = 0 then
      d := TntLvUnBlock.Items.Insert(0)
    else
      d := TntLvUnBlock.Items.Add;
    d.Assign(s);
    TntLvBlock.Selected.Delete;
  end;
  for i := 0 to TntLvBlock.Items.Count - 1 do
    if TntLvBlock.Items.Item[i].Focused then
      TntLvBlock.Items.Item[i].Selected := true;
  TntLvBlock.SetFocus;
end;

procedure TfmOptions.btnSoundClick(Sender: TObject);
var
  ver: integer;
  win: string;
begin
    // pop open the proper control panel applet.
    // It sure was nice of MS to change this for various versions
    // of the OS. *SIGH*
  ver := WindowsVersion(win);
  if (ver = cWIN_XP) then
    ShellExecute(Self.Handle, nil, 'rundll32.exe',
      'shell32.dll,Control_RunDLL mmsys.cpl,,1', nil, SW_SHOW)
  else if ((ver = cWIN_98) or (ver = cWIN_NT)) then
    ShellExecute(Self.Handle, nil, 'rundll32.exe',
      'shell32.dll,Control_RunDLL mmsys.cpl,sounds,0', nil, SW_SHOW)
  else
    ShellExecute(Self.Handle, nil, 'rundll32.exe',
      'shell32.dll,Control_RunDLL mmsys.cpl,,0', nil, SW_SHOW);
end;

procedure TfmOptions.btnFontClick(Sender: TObject);
begin
  FontDialog1.Font := ChatFont.Font;
  if FontDialog1.Execute then
    ChatFont.Font := FontDialog1.Font;
end;

procedure TfmOptions.btnTransferBrowseClick(Sender: TObject);
var
  tmps: string;
begin
  tmps := txtXFerPath.Text;
  if SelectDirectory(sPrefsXFerDir, '', tmps) then
    txtXFerPath.Text := tmps;
end;

procedure TfmOptions.btnVcardClick(Sender: TObject);
begin
  ShowMyProfile;
end;

procedure TfmOptions.LoadPrefShare;
var
  UnShares: TWideStringList;
  i: Integer;
begin
  if not MainSession.Active then
  begin
    for i := 0 to tabBlock.ControlCount - 1 do
      tabBlock.Controls[i].Enabled := false;
    Label13.Enabled := True;
    exit;
  end;
  UnShares := TWideStringList.Create();
  with MainSession.Prefs do
  begin
    fillStringlist('UnShares', UnShares);
    if getBool('UnShare_nonroster') then
      with TntLvUnShare.Items.Insert(0) do
        Caption := '所有其他用户'
    else
      with TntLvShare.Items.Insert(0) do
        Caption := '所有其他用户';
    for i := 0 to MainSession.roster.Count - 1 do
    begin
      with MainSession.roster.Items[i] do
      begin
        if jid.jid = MainSession.BareJid then
          continue;
        if jid.user = '' then
          continue;
        if ask <> 'subscribe' then
          if ((subscription = 'none') or (subscription = '')
            or (subscription = 'remove')) then
            continue;
        if UnShares.IndexOf(jid.jid) >= 0 then
          with TntLvUnShare.Items.Add do
          begin
            caption := Nickname;
            SubItems.add(jid.jid);
          end
        else
        begin
          with TntLvShare.Items.Add do
          begin
            caption := Nickname;
            SubItems.add(jid.jid);
          end
        end;
      end;
    end;
  end;
  UnShares.Free;
end;

procedure TfmOptions.SavePrefShare;
var
  UnShares: TWideStringList;
  i: Integer;
begin
  if not MainSession.Active then
  begin
    exit;
  end;
  UnShares := TWideStringList.Create();

  if TntLVShare.Items.Count > 0 then
    if TntLVShare.Items.Item[0].SubItems.count = 0 then
      MainSession.Prefs.setBool('UnShare_nonroster', false);

  for i := 0 to TntLVUnShare.Items.Count - 1 do
  begin
    if TntLVUnShare.Items.Item[i].SubItems.count = 0 then
      MainSession.Prefs.setBool('UnShare_nonroster', True)
    else
      UnShares.Add(TntLVUnShare.Items.Item[i].SubItems[0]);
  end;

  MainSession.Prefs.setStringlist('UnShares', UnShares);
  UnShares.Free;
end;

procedure TfmOptions.Button1Click(Sender: TObject);
var
  s, d: TTntListItem;
  i: Integer;
begin
  if TntLVUnShare.Selected <> nil then
  begin
    s := TntLVUnShare.Items.item[TntLVUnShare.Selected.Index];
    if s.SubItems.Count = 0 then
      d := TntLvShare.Items.Insert(0)
    else
      d := TntLvShare.Items.Add;
    d.Assign(s);
    TntLVUnShare.Selected.Delete;
  end;
  for i := 0 to TntLVUnShare.Items.Count - 1 do
    if TntLVUnShare.Items.Item[i].Focused then
      TntLVUnShare.Items.Item[i].Selected := true;
  TntLVUnShare.SetFocus;
end;

procedure TfmOptions.Button2Click(Sender: TObject);
var
  s, d: TTntListItem;
  i: Integer;
begin
  if TntLvShare.Selected <> nil then
  begin
    s := TntLvShare.Items.item[TntLvShare.Selected.Index];
    if s.SubItems.Count = 0 then
      d := TntLVUnShare.Items.Insert(0)
    else
      d := TntLVUnShare.Items.Add;
    d.Assign(s);
    TntLvShare.Selected.Delete;
  end;
  for i := 0 to TntLvShare.Items.Count - 1 do
    if TntLvShare.Items.Item[i].Focused then
      TntLvShare.Items.Item[i].Selected := true;
  TntLvShare.SetFocus;
end;

procedure TfmOptions.btnCfgOicqClick(Sender: TObject);
begin
  TransportsCfg('oicq');
end;

procedure TfmOptions.btnCfgMsnClick(Sender: TObject);
begin
  TransportsCfg('msn');
end;

procedure TfmOptions.btnCfgIcqClick(Sender: TObject);
begin
  TransportsCfg('icq');
end;

procedure TfmOptions.btnCfgAimClick(Sender: TObject);
begin
  TransportsCfg('aim');
end;

procedure TfmOptions.btnCfgYahooClick(Sender: TObject);
begin
  TransportsCfg('yahoo');
end;

procedure TfmOptions.LoadPrefTransports;
var
  NoAutologins: TWideStringList;
  i: Integer;
begin
  if not MainSession.Active then
  begin
    chkOicq.Enabled := false;
    chkMsn.Enabled := false;
    chkIcq.Enabled := false;
    chkAim.Enabled := false;
    chkYahoo.Enabled := false;

    btnCfgOicq.Enabled := false;
    btnCfgMsn.Enabled := false;
    btnCfgIcq.Enabled := false;
    btnCfgAim.Enabled := false;
    btnCfgYahoo.Enabled := false;

    exit;
  end;
  NoAutologins := TWideStringList.Create();
  with MainSession.Prefs do
    fillStringlist('notautologins', NoAutologins);

  chkOicq.Checked := NoAutologins.IndexOf('oicq') < 0;
  chkMsn.Checked := NoAutologins.IndexOf('msn') < 0;
  chkIcq.Checked := NoAutologins.IndexOf('icq') < 0;
  chkAim.Checked := NoAutologins.IndexOf('aim') < 0;
  chkYahoo.Checked := NoAutologins.IndexOf('yahoo') < 0;

  NoAutologins.Free;
end;

procedure TfmOptions.SavePrefTransports;
var
  NoAutologins: TWideStringList;
  i: Integer;
  procedure remove(jid: widestring);
  var
    iq: TXMLTag;
  begin
    iq := TXMLTag.Create('iq');
    iq.setAttribute('id', MainSession.generateID());
    iq.setAttribute('type', 'set');
    iq.setAttribute('to', jid);
    with iq.AddTag('query') do
    begin
      setAttribute('xmlns', XMLNS_REGISTER);
      AddTag('remove');
    end;

    MainSession.SendTag(iq);

    iq := TXMLTag.Create('iq');
    with iq do begin
      setAttribute('type', 'set');
      setAttribute('id', MainSession.generateID);
      with AddTag('query') do begin
        setAttribute('xmlns', XMLNS_ROSTER);
        with AddTag('item') do begin
          setAttribute('jid', jid);
          setAttribute('subscription', 'remove');
        end;
      end;
    end;
    MainSession.SendTag(iq);
  end;
begin
  if not MainSession.Active then
  begin
    exit;
  end;

  NoAutologins := TWideStringList.Create();

  if not chkOicq.Checked then NoAutologins.Add('oicq');
  if not chkMsn.Checked then NoAutologins.Add('msn');
  if not chkIcq.Checked then NoAutologins.Add('icq');
  if not chkAim.Checked then NoAutologins.Add('aim');
  if not chkYahoo.Checked then NoAutologins.Add('yahoo');

  if not chkOicq.Checked then Remove('oicq.' + MainSession.server);
  if not chkMsn.Checked then Remove('msn.' + MainSession.server);
  if not chkIcq.Checked then Remove('icq.' + MainSession.server);
  if not chkAim.Checked then Remove('aim.' + MainSession.server);
  if not chkYahoo.Checked then Remove('yahoo.' + MainSession.server);

  MainSession.Prefs.setStringlist('notautologins', NoAutologins);

  NoAutologins.Free;
end;

procedure TfmOptions.Disabletab(tab: TTabSheet);
var
  i: integer;
begin
  for i := 0 to tab.ControlCount - 1 do
    tab.Controls[i].Enabled := false;
end;

procedure TfmOptions.btnPassWordClick(Sender: TObject);
begin
  frmAnyQ.mnuPasswordClick(frmAnyQ.mnuPassword);
end;

procedure TfmOptions.btnUpdateClick(Sender: TObject);
var
  available: boolean;
begin
  Screen.Cursor := crHourGlass;
  available := InitAutoUpdate(false);
  Screen.Cursor := crDefault;

  if (not available) then
    ShowRiserWindow(nil, '目前没有更新版本。', ico_info);
end;

procedure TfmOptions.chkOicqClick(Sender: TObject);
begin
  btnCfgOicq.Enabled := chkOicq.Enabled;
end;

procedure TfmOptions.chkIcqClick(Sender: TObject);
begin
  btnCfgIcq.Enabled := chkIcq.Enabled;
end;

procedure TfmOptions.chkMsnClick(Sender: TObject);
begin
  btnCfgMsn.Enabled := chkMsn.Enabled;
end;

procedure TfmOptions.chkAimClick(Sender: TObject);
begin
  btnCfgAim.Enabled := chkAim.Enabled;
end;

procedure TfmOptions.chkYahooClick(Sender: TObject);
begin
  btnCfgYahoo.Enabled := chkYahoo.Enabled;
end;

procedure TfmOptions.tabShareEnter(Sender: TObject);
begin
  if TntLVShare.Enabled then
    TntLVShare.SetFocus;
end;

procedure TfmOptions.tabSkinShow(Sender: TObject);
{var
  idx: Integer;
  skinfn: string;{}
begin
{  idx := MainSession.Prefs.getInt('skinindex');
  if idx>=0 then
    SkinViewForm.SkinData1.LoadFromCollection(frmAnyQ.SkinStore1,idx)
  else
  begin
    skinfn := MainSession.Prefs.getString('skinfile');
    if skinfn<>'' then
      SkinViewForm.SkinData1.LoadFromFile(skinfn)
    else
      SkinViewForm.SkinData1.LoadFromCollection(frmAnyQ.SkinStore1,0)
  end;
  SkinViewForm.SkinData1.Active := true;   {}
end;

procedure TfmOptions.RadioGroupSkinClick(Sender: TObject);
begin
  edtSkinfilename.Enabled := RadioGroupSkin.ItemIndex=4;
  btnskinfile.Enabled := RadioGroupSkin.ItemIndex=4;
  case RadioGroupSkin.ItemIndex of
    0..3: frmAnyQ.SkinData1.LoadFromCollection(frmAnyQ.SkinStore1, RadioGroupSkin.ItemIndex);
    4: if edtSkinfilename.Text<>'' then
      begin
        if FileExists(edtSkinfilename.Text) then
          frmAnyQ.SkinData1.LoadFromFile(edtSkinfilename.Text);
      end;
  end;
end;

procedure TfmOptions.btnskinfileClick(Sender: TObject);
begin
  inherited;
  if opendlgskn.Execute then
    if FileExists(opendlgskn.FileName) then
      edtSkinfilename.Text := opendlgskn.FileName;
end;

procedure TfmOptions.edtSkinfilenameChange(Sender: TObject);
begin
  inherited;
  if edtSkinfilename.Enabled then
  begin
    if FileExists(edtSkinfilename.Text) then
      frmAnyQ.SkinData1.LoadFromFile(edtSkinfilename.Text);
  end;
end;

procedure TfmOptions.SavePrefSkin;
var
  idx: Integer;
  skinfn: string;
begin
  idx := RadioGroupSkin.ItemIndex;
  if idx = RadioGroupSkin.Items.Count-1 then
    idx := -1;
  MainSession.Prefs.setInt('skinindex', idx);
  skinfn := edtSkinfilename.Text;
  if idx<0 then
    if FileExists(skinfn) then
      MainSession.Prefs.setString('skinfile', skinfn);
end;

procedure TfmOptions.LoadPrefSkin;
var
  idx: Integer;
  skinfn: string;
begin
  idx := MainSession.Prefs.getInt('skinindex');
  if idx >= 0 then
    RadioGroupSkin.ItemIndex := idx
  else
  begin
    RadioGroupSkin.ItemIndex := 4;
    skinfn := MainSession.Prefs.getString('skinfile');
    edtSkinfilename.Text := skinfn;
    edtSkinfilename.Enabled := True;
    btnskinfile.Enabled := True;
  end;
end;

procedure TfmOptions.btnCancelClick(Sender: TObject);
begin
  LoadPrefSkin;
  inherited;
end;

end.
