OSDN Git Service

80305f3593942629e9ac3e17318ea5b12d7c8c11
[winbottle/winbottle.git] / bottleclient / SettingForm.pas
1 unit SettingForm;
2
3 {
4   \90Ý\92è\89æ\96Ê\81B\82»\82ê\96¢\96\9e\82Å\82à\82»\82ê\88È\8fã\82Å\82à\82È\82¢\81B
5   Pref\83I\83u\83W\83F\83N\83g\82ð\8eÀ\8dÛ\82É\91\80\8dì\82·\82é\81B
6 }
7
8 interface
9
10 uses
11   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
12   ComCtrls, StdCtrls, ExtCtrls, BottleDef, Spin,
13   CPCConfigTreeView, ColorSettingFrame, BottleChainListFrame, SakuraSeekerInstance,
14   ImgList, StrListEditor, SppList, Plugins, Clipbrd, SsPlayTime, StrUtils,
15   SpecialCharEditor, ReplacePresetListFrame;
16
17 type
18   TfrmSetting = class(TForm)
19     PageControl: TPageControl;
20     btnClose: TButton;
21     tstGeneral: TTabSheet;
22     tstDisplay: TTabSheet;
23     tstKeys: TTabSheet;
24     rgpWhenReturn: TRadioGroup;
25     rgpWhenShiftReturn: TRadioGroup;
26     rgpWhenCtrlReturn: TRadioGroup;
27     memDefaultScript: TMemo;
28     lblDefaultScript: TLabel;
29     tstReceive: TTabSheet;
30     OpenDialog: TOpenDialog;
31     spnWaitScriptEnd: TSpinEdit;
32     lblWaitScriptEnd: TLabel;
33     cbxConfirmOnExit: TCheckBox;
34     ctvBottle: TCPCConfigTreeView;
35     gbxColor: TGroupBox;
36     frmColorSetting: TfrmColorSetting;
37     tstRule: TTabSheet;
38     frmRuleList: TfrmBottleChainList;
39     tstDetailed: TTabSheet;
40     lblFMOName: TLabel;
41     memFMOName: TMemo;
42     tstChannel: TTabSheet;
43     lblAutoJoinChannels: TLabel;
44     memAutoJoinChannels: TMemo;
45     cbxAutoStart: TCheckBox;
46     btnUseCurrentJoinChannels: TButton;
47     ImageList: TImageList;
48     tstSurfacePreview: TTabSheet;
49     lblSurfacePreview: TLabel;
50     lvwPluginList: TListView;
51     lblPluginList: TLabel;
52     ctvSurfacePreview: TCPCConfigTreeView;
53     btnVisibleGhosts: TButton;
54     cbxHideGhosts: TCheckBox;
55     cbxNoExtraSSTPHeaders: TCheckBox;
56     lblLUID: TLabel;
57     edtLUID: TEdit;
58     cbxShowRuler: TCheckBox;
59     rgpTabPosition: TRadioGroup;
60     lblGhostDropDownCount: TLabel;
61     spnGhostDropDownCount: TSpinEdit;
62     cbxIgnoreTimeCritical: TCheckBox;
63     cbxAutoClip: TCheckBox;
64     btnCopyLUID: TButton;
65     tvwCategory: TTreeView;
66     Label1: TLabel;
67     pnlHeading: TPanel;
68     cbxConfirmOnTabClose: TCheckBox;
69     tstConnection: TTabSheet;
70     grpProxy: TGroupBox;
71     lblProxyAddress: TLabel;
72     lblProxyPort: TLabel;
73     Label6: TLabel;
74     edtProxyAddress: TEdit;
75     edtProxyPort: TEdit;
76     cbxUseHttpProxy: TCheckBox;
77     spnReconnectWait: TSpinEdit;
78     lblReconnectWait: TLabel;
79     lblPartialConfirmFormat: TLabel;
80     edtPartialConfirmFormat: TEdit;
81     cbxAutoPartialConfirm: TCheckBox;
82     tstPlayTime: TTabSheet;
83     grpPlayTimeParams: TGroupBox;
84     lblPlayTimeProfile: TLabel;
85     cbxPlayTimeProfile: TComboBox;
86     spnCostDBChar: TSpinEdit;
87     spnCostWait: TSpinEdit;
88     spnCostSurface: TSpinEdit;
89     spnCostChar: TSpinEdit;
90     spnCostQuickChar: TSpinEdit;
91     lblCostWait: TLabel;
92     lblCostSurface: TLabel;
93     lblCostChar: TLabel;
94     lblCostDBChar: TLabel;
95     lblCostQuickChar: TLabel;
96     btnSavePlayTimeProfile: TButton;
97     lvwCostSpecials: TListView;
98     lblCostSpecials: TLabel;
99     btnPlaySpecialAdd: TButton;
100     btnPlaySpecialDelete: TButton;
101     gbxTabWidth: TGroupBox;
102     cbxAutoTabWidth: TCheckBox;
103     spnTabWidth: TSpinEdit;
104     lblBrowser: TLabel;
105     edtBrowserName: TEdit;
106     BrowserLocateOpenDialog: TOpenDialog;
107     btnBrowserLocate: TButton;
108     tstPresetReplace: TTabSheet;
109     ReplacePresetList: TfrmReplacePresetList;
110     procedure FormClose(Sender: TObject; var Action: TCloseAction);
111     procedure edtProxyPortKeyPress(Sender: TObject; var Key: Char);
112     procedure ctvBottleNodeChecked(Sender: TObject;
113       Node: TCPCConfigItemNode);
114     procedure ctvBottleNodeChecking(Sender: TObject;
115       Node: TCPCConfigItemNode; var Allow: Boolean);
116     procedure tstRuleShow(Sender: TObject);
117     procedure btnUseCurrentJoinChannelsClick(Sender: TObject);
118     procedure btnVisibleGhostsClick(Sender: TObject);
119     procedure lvwPluginListDblClick(Sender: TObject);
120     procedure edtLUIDEnter(Sender: TObject);
121     procedure edtLUIDExit(Sender: TObject);
122     procedure btnCopyLUIDClick(Sender: TObject);
123     procedure FormCreate(Sender: TObject);
124     procedure tvwCategoryChange(Sender: TObject; Node: TTreeNode);
125     procedure tvwCategoryMouseMove(Sender: TObject; Shift: TShiftState; X,
126       Y: Integer);
127     procedure cbxPlayTimeProfileChange(Sender: TObject);
128     procedure btnSavePlayTimeProfileClick(Sender: TObject);
129     procedure spnCostWaitChange(Sender: TObject);
130     procedure btnPlaySpecialAddClick(Sender: TObject);
131     procedure btnPlaySpecialDeleteClick(Sender: TObject);
132     procedure lvwCostSpecialsDblClick(Sender: TObject);
133     procedure spnTabWidthChange(Sender: TObject);
134     procedure cbxAutoTabWidthClick(Sender: TObject);
135     procedure btnBrowserLocateClick(Sender: TObject);
136     procedure tstPresetReplaceShow(Sender: TObject);
137   private
138     { Private \90é\8c¾ }
139     FOldLUID: String;
140     FSpinUpdateFlag: boolean;
141     procedure LoadPlayTimeProfiles;
142     procedure PlayTimeParamsToSpinControl(Params: TSsPlayTimeParams);
143     procedure SpinControlToPlayTimeParams(Params: TSsPlayTimeParams);
144     procedure UpdateSpecialChars;
145   public
146     { Public \90é\8c¾ }
147     procedure Execute;
148   end;
149
150 var
151   frmSetting: TfrmSetting;
152
153 const
154   DefaultNode = -1;
155   ChannelDefaultGhost = '(\83`\83\83\83\93\83l\83\8b\90\84\8f§\83S\81[\83X\83g)';
156   CheckedBottle = 22;
157   UnCheckedBottle = 17;
158
159 implementation
160
161 {$R *.DFM}
162
163 const
164   SettingIcon = 4;
165
166 procedure TfrmSetting.Execute;
167 var i: integer;
168     Node: TCPCGroupNode;
169 begin
170   PageControl.ActivePage := tstGeneral;
171   memDefaultScript.Text := Pref.DefaultScript;
172   cbxShowRuler.Checked := Pref.ShowRuler;
173   cbxIgnoreTimeCritical.Checked := Pref.IgnoreTimeCritical;
174   edtPartialConfirmFormat.Text := Pref.PartialConfirmFormat;
175   cbxAutoPartialConfirm.Checked := Pref.AutoPartialConfirm;
176   cbxConfirmOnExit.Checked := Pref.ConfirmOnExit;
177   cbxConfirmOnTabClose.Checked := Pref.ConfirmOnTabClose;
178   cbxAutoClip.Checked := Pref.AutoClip;
179   //
180   with frmColorSetting do begin
181     Color['H'] := Pref.TalkColorH;
182     Color['U'] := Pref.TalkColorU;
183     Color['Synchro'] := Pref.TalkColorS;
184     Color['Tag'] := Pref.MarkUpColor;
185     Color['Meta'] := Pref.MetaWordColor;
186     Color['Error'] := Pref.MarkErrorColor;
187     Color['Text'] := Pref.TextColor;
188     Color['Background'] := Pref.BgColor;
189   end;
190   //
191   cbxPlayTimeProfile.Items.Clear;
192   cbxPlayTimeProfile.Items.Add(Pref.PlayTimeParams.ProfileName);
193   cbxPlayTimeProfile.ItemIndex := 0;
194   LoadPlayTimeProfiles;
195   PlayTimeParamsToSpinControl(Pref.PlayTimeParams);
196   UpdateSpecialChars;
197   //
198   cbxAutoStart.Checked := Pref.AutoStart;
199   rgpTabPosition.ItemIndex := Ord(Pref.TabPosition);
200   spnTabWidth.Value := Pref.TabWidth;
201   if Pref.TabWidth <= 0 then
202     spnTabWidth.Value := 0;
203   cbxAutoTabWidth.Checked := Pref.TabWidth <= 0;
204   spnGhostDropDownCount.Value := Pref.GhostDropDownCount;
205   try
206     with ctvBottle do begin
207       (GetNodeFromKeyPath('Arrive\NoTranslate') as TCPCCheckBoxNode).Checked := Pref.NoTranslate;
208       (GetNodeFromKeyPath('Arrive\NoDescript') as TCPCCheckBoxNode).Checked := Pref.NoDescript;
209       if Pref.NoTransUrl then
210         (GetNodeFromKeyPath('Arrive\UrlTag\NoSelection') as TCPCRadioNode).Check
211       else
212         (GetNodeFromKeyPath('Arrive\UrlTag\WithSelection') as TCPCRadioNode).Check;
213       (GetNodeFromKeyPath('Arrive\SilentWhenHidden') as TCPCCheckBoxNode).Checked := Pref.SilentWhenHidden;
214       (GetNodeFromKeyPath('Arrive\FixMessySurface') as TCPCCheckBoxNode).Checked := Pref.FixMessySurface;
215       (GetNodeFromKeyPath('Arrive\HUTagTo01Tag') as TCPCCheckBoxNode).Checked := Pref.HUTagTo01Tag;
216       (GetNodeFromKeyPath('Out\ResetIfGhostAfterSend') as TCPCCheckBoxNode).Checked := Pref.ResetIfGhostAfterSend;
217       (GetNodeFromKeyPath('Out\ClearAfterSend') as TCPCCheckBoxNode).Checked := Pref.ClearAfterSend;
218       (GetNodeFromKeyPath('Out\NeedConfirmBeforeSend') as TCPCCheckBoxNode).Checked := Pref.NeedConfirmBeforeSend;
219       (GetNodeFromKeyPath('Out\Confirm') as TCPCCheckBoxNode).Checked := not Pref.NoConfirm;
220       (GetNodeFromKeyPath('Out\Warn\ScopeChangeInSynchronize') as TCPCCheckBoxNode).Checked := Pref.WarnScopeChangeInSynchronize;
221       (GetNodeFromKeyPath('Out\Warn\YenTNotExist') as TCPCCheckBoxNode).Checked := Pref.WarnYenTNotExist;
222     end;
223   except
224     on E: Exception do ShowMessage(E.Message);
225   end;
226   //cbxIgnoreFrequentYenS.Checked := Pref.IgnoreFrequentYenS;
227   spnWaitScriptEnd.Value := Pref.WaitScriptEnd;
228   //
229   rgpWhenReturn.ItemIndex := Ord(Pref.WhenReturn);
230   rgpWhenShiftReturn.ItemIndex := Ord(Pref.WhenShiftReturn);
231   rgpWhenCtrlReturn.ItemIndex := Ord(Pref.WhenCtrlReturn);
232   //
233   cbxUseHttpProxy.Checked := Pref.UseHttpProxy;
234   edtProxyAddress.Text := Pref.ProxyAddress;
235   edtProxyPort.Text := IntToStr(Pref.ProxyPort);
236   //
237   spnReconnectWait.Value := Pref.ReconnectWait;
238   //
239   edtLUID.Text := Pref.LUID;
240   //
241   memFMOName.Lines := Pref.FMOName;
242   cbxHideGhosts.Checked := Pref.HideGhosts;
243   memAutoJoinChannels.Lines := Pref.AutoJoinChannels;
244   cbxNoExtraSSTPHeaders.Checked := Pref.NoExtraSSTPHeaders;
245   //
246   with ctvSurfacePreview do
247   begin
248     (GetNodeFromKeyPath('OnHint\DoPreview') as TCPCCheckBoxNode).Checked := Pref.SurfacePreviewOnHint;
249     (GetNodeFromKeyPath('OnScriptPoint\DoPreview') as TCPCCheckBoxNode).Checked := Pref.SurfacePreviewOnScriptPoint;
250     Node := GetNodeFromKeyPath('OnScriptPoint\Position') as TCPCGroupNode;
251     (Node.Item[Ord(Pref.SurfacePreviewOnScriptPointPosition)] as TCPCRadioNode).Check;
252   end;
253   for i := 0 to Spps.Count-1 do
254   begin
255     with lvwPluginList.Items.Add do
256     begin
257       Caption := ExtractFileName(Spps.SppItem[i].ModuleName);
258       SubItems.Add(Spps.SppItem[i].PluginName);
259     end;
260   end;
261   edtBrowserName.Text := Pref.BrowserExeName;
262
263   //
264   ShowModal;
265 end;
266
267 procedure TfrmSetting.FormClose(Sender: TObject; var Action: TCloseAction);
268 var i: integer;
269     Node: TCPCGroupNode;
270 begin
271   Pref.DefaultScript := memDefaultScript.Text;
272   Pref.ShowRuler := cbxShowRuler.Checked;
273   Pref.IgnoreTimeCritical := cbxIgnoreTimeCritical.Checked;
274   Pref.PartialConfirmFormat := edtPartialConfirmFormat.Text;
275   Pref.AutoPartialConfirm := cbxAutoPartialConfirm.Checked;
276   Pref.ConfirmOnExit := cbxConfirmOnExit.Checked;
277   Pref.ConfirmOnTabClose := cbxConfirmOnTabClose.Checked;
278   Pref.AutoClip := cbxAutoClip.Checked;
279   //
280   with frmColorSetting do begin
281     Pref.TalkColorH := Color['H'];
282     Pref.TalkColorU := Color['U'];
283     Pref.TalkColorS := Color['Synchro'];
284     Pref.MarkUpColor := Color['Tag'];
285     Pref.MetaWordColor := Color['Meta'];
286     Pref.MarkErrorColor := Color['Error'];
287     Pref.TextColor := Color['Text'];
288     Pref.BgColor := Color['Background'];
289   end;
290   //
291   Pref.PlayTimeParams.ProfileName := cbxPlayTimeProfile.Text;
292   SpinControlToPlayTimeParams(Pref.PlayTimeParams);
293   //
294   Pref.AutoStart := cbxAutoStart.Checked;
295   Pref.TabPosition := TTabPosition(rgpTabPosition.ItemIndex);
296   Pref.TabWidth := spnTabWidth.Value;
297   if cbxAutoTabWidth.Checked then
298     Pref.TabWidth := 0;
299   Pref.GhostDropDownCount := spnGhostDropDownCount.Value;
300   try
301     with ctvBottle do begin
302       Pref.NoTranslate := (GetNodeFromKeyPath('Arrive\NoTranslate') as TCPCCheckBoxNode).Checked;
303       Pref.NoDescript := (GetNodeFromKeyPath('Arrive\NoDescript') as TCPCCheckBoxNode).Checked;
304       Pref.NoTransUrl := (GetNodeFromKeyPath('Arrive\UrlTag\NoSelection') as TCPCRadioNode).Checked;
305       Pref.SilentWhenHidden := (GetNodeFromKeyPath('Arrive\SilentWhenHidden') as TCPCCheckBoxNode).Checked;
306       Pref.FixMessySurface := (GetNodeFromKeyPath('Arrive\FixMessySurface') as TCPCCheckBoxNode).Checked;
307       Pref.HUTagTo01Tag := (GetNodeFromKeyPath('Arrive\HUTagTo01Tag') as TCPCCheckBoxNode).Checked;
308       Pref.ResetIfGhostAfterSend := (GetNodeFromKeyPath('Out\ResetIfGhostAfterSend') as TCPCCheckBoxNode).Checked;
309       Pref.ClearAfterSend := (GetNodeFromKeyPath('Out\ClearAfterSend') as TCPCCheckBoxNode).Checked;
310       Pref.NeedConfirmBeforeSend := (GetNodeFromKeyPath('Out\NeedConfirmBeforeSend') as TCPCCheckBoxNode).Checked;
311       Pref.NoConfirm := not (GetNodeFromKeyPath('Out\Confirm') as TCPCCheckBoxNode).Checked;
312       Pref.WarnYenTNotExist := (GetNodeFromKeyPath('Out\Warn\YenTNotExist') as TCPCCheckBoxNode).Checked;
313       Pref.WarnScopeChangeInSynchronize := (GetNodeFromKeyPath('Out\Warn\ScopeChangeInSynchronize') as TCPCCheckBoxNode).Checked;
314     end;
315   except
316     on E: Exception do ShowMessage(E.Message);
317   end;
318   //Pref.IgnoreFrequentYenS := cbxIgnoreFrequentYenS.Checked;
319   Pref.WaitScriptEnd := spnWaitScriptEnd.Value;
320   //
321   Pref.WhenReturn := TReturnKeyFunction(rgpWhenReturn.ItemIndex);
322   Pref.WhenShiftReturn := TReturnKeyFunction(rgpWhenShiftReturn.ItemIndex);
323   Pref.WhenCtrlReturn := TReturnKeyFunction(rgpWhenCtrlReturn.ItemIndex);
324   //
325   Pref.UseHttpProxy := cbxUseHttpProxy.Checked;
326   Pref.ProxyAddress := edtProxyAddress.Text;
327   Pref.ProxyPort := StrToInt(edtProxyPort.Text);
328   //
329   Pref.ReconnectWait := spnReconnectWait.Value;
330   //
331   Pref.LUID := edtLUID.Text;
332   //
333   Pref.FMOName := memFMOName.Lines;
334   SakuraSeeker.FileMappingTarget := Pref.FMOName;
335   Pref.HideGhosts := cbxHideGhosts.Checked;
336   Pref.NoExtraSSTPHeaders := cbxNoExtraSSTPHeaders.Checked;
337   //
338   Pref.AutoJoinChannels := memAutoJoinChannels.Lines;
339   //
340   with ctvSurfacePreview do
341   begin
342     Pref.SurfacePreviewOnHint := (GetNodeFromKeyPath('OnHint\DoPreview') as TCPCCheckBoxNode).Checked;
343     Pref.SurfacePreviewOnScriptPoint := (GetNodeFromKeyPath('OnScriptPoint\DoPreview') as TCPCCheckBoxNode).Checked;
344     Node := GetNodeFromKeyPath('OnScriptPoint\Position') as TCPCGroupNode;
345     for i := 0 to Node.Count-1 do
346       if (Node.Item[i] as TCPCRadioNode).Checked then
347         Pref.SurfacePreviewOnScriptPointPosition := TSurfacePreviewOnScriptPointPosition(i);
348   end;
349   //
350   Pref.BrowserExeName := edtBrowserName.Text;
351
352 end;
353
354 procedure TfrmSetting.edtProxyPortKeyPress(Sender: TObject; var Key: Char);
355 begin
356   if not(Key in ['0'..'9']) then Key := Char(0);
357 end;
358
359 procedure TfrmSetting.ctvBottleNodeChecked(Sender: TObject;
360   Node: TCPCConfigItemNode);
361 begin
362   //ShowMessage(ctvBottle.GetFullKeyPath(Node));
363 end;
364
365 procedure TfrmSetting.ctvBottleNodeChecking(Sender: TObject;
366   Node: TCPCConfigItemNode; var Allow: Boolean);
367 begin
368   if Node.KeyName = 'IgnoreBottle' then begin
369     MessageDlg('\82±\82Ì\8b@\94\\82Í\8eÀ\91\95\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ', mtError, [mbOk], 0);
370     Allow := false;
371   end;
372 end;
373
374 procedure TfrmSetting.tstRuleShow(Sender: TObject);
375 begin
376   frmRuleList.UpdateDisplay;
377 end;
378
379 procedure TfrmSetting.btnUseCurrentJoinChannelsClick(Sender: TObject);
380 begin
381   memAutoJoinChannels.Lines := JoinChannels;
382 end;
383
384 procedure TfrmSetting.btnVisibleGhostsClick(Sender: TObject);
385 var i: integer;
386     FullGhosts: TStringList;
387 begin
388   FullGhosts := TStringList.Create;
389   SakuraSeeker.BeginDetect;
390   try
391     for i := 0 to SakuraSeeker.Count-1 do
392       FullGhosts.Add(SakuraSeeker[i].Name);
393     StrListEdit(Pref.VisibleGhostsList, '\83S\81[\83X\83g\82ð\8ew\92è', true, FullGhosts);
394   finally
395     FullGhosts.Free;
396   end;
397 end;
398
399 procedure TfrmSetting.lvwPluginListDblClick(Sender: TObject);
400 var Index: integer;
401 begin
402   if lvwPluginList.Selected = nil then
403     Exit;
404   Index := lvwPluginList.Selected.Index;
405   if pfConfigure in Spps.SppItem[Index].PluginFunctions then
406     Spps.SppItem[Index].Configure
407   else
408     ShowMessage('\92Ç\89Á\82Ì\90Ý\92è\8d\80\96Ú\82Í\82 \82è\82Ü\82¹\82ñ\81B');
409 end;
410
411 procedure TfrmSetting.edtLUIDEnter(Sender: TObject);
412 begin
413   FOldLUID := edtLUID.Text;
414 end;
415
416 procedure TfrmSetting.edtLUIDExit(Sender: TObject);
417 var TmpLUID: String;
418     i: integer;
419     Err: boolean;
420 begin
421   TmpLUID := edtLUID.Text;
422   i := 1;
423   Err := false;
424   if Length(TmpLUID) <> 82 then
425     Err := true
426   else
427     while i <= Length(TmpLUID) do
428     begin
429       if not (TmpLUID[i] in ['0'..'9', 'a'..'z', 'A'..'Z', '.', ',']) then
430       begin
431         Err := true;
432         Break;
433       end;
434       Inc(i);
435     end;
436   if Err then
437   begin
438     ShowMessage('LUID\82Ì\93à\97e\82ª\95s\90³\82Å\82·');
439     edtLUID.Text := FOldLUID;
440   end;
441 end;
442
443 procedure TfrmSetting.btnCopyLUIDClick(Sender: TObject);
444 begin
445   Clipboard.SetTextBuf(PChar(edtLUID.Text));
446 end;
447
448 procedure TfrmSetting.FormCreate(Sender: TObject);
449 var
450   i: integer;
451   Cap: String;
452   Node: TTreeNode;
453 begin
454   for i := 0 to PageControl.PageCount-1 do
455   begin
456     Cap := PageControl.Pages[i].Caption;
457     if Pos(':', Cap) > 0 then
458       Cap := Copy(Cap, 1, Pos(':', Cap)-1);
459     Node := tvwCategory.Items.Add(nil, Cap);
460     Node.ImageIndex := -1;
461     Node.SelectedIndex := SettingIcon;
462   end;
463   tvwCategoryChange(Self, tvwCategory.Items[0]);
464   tvwCategory.Items[0].Selected := true;
465 end;
466
467 procedure TfrmSetting.tvwCategoryChange(Sender: TObject; Node: TTreeNode);
468 begin
469   PageControl.ActivePageIndex := Node.Index;
470   pnlHeading.Caption := PageControl.ActivePage.Caption;
471 end;
472
473 procedure TfrmSetting.tvwCategoryMouseMove(Sender: TObject;
474   Shift: TShiftState; X, Y: Integer);
475 var
476   Node: TTreeNode;
477   NewHint: String;
478   CPos: TPoint;
479 begin
480   Node := tvwCategory.GetNodeAt(X, Y);
481   if Node <> nil then
482   begin
483     NewHint := PageControl.Pages[Node.Index].Caption;
484     if tvwCategory.Hint <> NewHint then
485     begin
486       tvwCategory.Hint := NewHint;
487       GetCursorPos(CPos);
488       Application.ActivateHint(CPos);
489     end;
490   end else
491   begin
492     tvwCategory.Hint := '';
493     Application.HideHint;
494   end;
495 end;
496
497 procedure TfrmSetting.PlayTimeParamsToSpinControl(Params: TSsPlayTimeParams);
498 begin
499   FSpinUpdateFlag := true;
500   with Params do
501   begin
502     spnCostWait.Value         := CostWait;
503     spnCostSurface.Value      := CostSurface;
504     spnCostChar.Value         := CostChar;
505     spnCostDBChar.Value       := CostDBChar;
506     spnCostQuickChar.Value    := CostQuickChar;
507     lvwCostSpecials.Items.Clear;
508   end;
509   FSpinUpdateFlag := false;
510 end;
511
512 procedure TfrmSetting.SpinControlToPlayTimeParams(Params: TSsPlayTimeParams);
513 begin
514   with Params do
515   begin
516     CostWait         := spnCostWait.Value;
517     CostSurface      := spnCostSurface.Value;
518     CostChar         := spnCostChar.Value;
519     CostDBChar       := spnCostDBChar.Value;
520     CostQuickChar    := spnCostQuickChar.Value;
521   end;
522 end;
523
524
525 procedure TfrmSetting.LoadPlayTimeProfiles;
526 var i: integer;
527     F: TSearchRec;
528     Path, Item: String;
529 begin
530   Path := ExtractFilePath(Application.ExeName);
531   i := FindFirst(Path + 'playtime\*.txt', 0, F);
532   if i = 0 then begin
533     repeat
534       Item := ChangeFileExt(F.Name, '');
535       if cbxPlayTimeProfile.Items.IndexOf(Item) < 0 then
536         cbxPlayTimeProfile.Items.Add(ChangeFileExt(F.Name, ''));
537       i := FindNext(F);
538     until i <> 0;
539   end;
540   FindClose(F);
541 end;
542
543 procedure TfrmSetting.cbxPlayTimeProfileChange(Sender: TObject);
544 var
545   Params: TSsPlayTimeParams;
546   Strs: TStringList;
547   Path, ProName: String;
548 begin
549   try
550     Strs := TStringList.Create;
551     ProName := cbxPlayTimeProfile.Text;
552     try
553       Path := ExtractFilePath(Application.ExeName) + 'playtime\';
554       Strs.LoadFromFile(Path + ProName + '.txt');
555       Params := StringToComponent(Strs.Text) as TSsPlayTimeParams;
556       try
557         PlayTimeParamsToSpinControl(Params);
558         Pref.PlayTimeParams.Assign(Params);
559         UpdateSpecialChars;
560       finally
561         Params.Free;
562       end;
563     finally
564       Strs.Free;
565     end;
566     with cbxPlayTimeProfile do
567     begin
568       Items.Clear;
569       LoadPlayTimeProfiles;
570       ItemIndex := Items.IndexOf(ProName);
571     end;
572   except
573     ; // Do nothing
574   end;
575 end;
576
577 procedure TfrmSetting.btnSavePlayTimeProfileClick(Sender: TObject);
578 var
579   ProfileName, Path, FileName: String;
580   Strs: TStringList;
581 begin
582   ProfileName := cbxPlayTimeProfile.Text;
583   if InputQuery('\83v\83\8d\83t\83@\83C\83\8b\96¼', '\95Û\91\82·\82é\83v\83\8d\83t\83@\83C\83\8b\96¼', ProfileName) then
584   begin
585     try
586       Path := ExtractFilePath(Application.ExeName) + 'playtime\';
587       FileName := Path + ProfileName + '.txt';
588       if FileExists(FileName) then
589         if MessageDlg(Format('\83v\83\8d\83t\83@\83C\83\8b"%s"\82ð\8fã\8f\91\82«\82µ\82Ü\82·', [ProfileName]),
590           mtConfirmation, mbOkCancel, 0) = mrCancel then
591           Exit;
592       Strs := TStringList.Create;
593       try
594         SpinControlToPlayTimeParams(Pref.PlayTimeParams);
595         Pref.PlayTimeParams.ProfileName := ProfileName;
596         Strs.Text := ComponentToString(Pref.PlayTimeParams);
597         Strs.SaveToFile(FileName);
598       finally
599         Strs.Free;
600       end;
601       with cbxPlayTimeProfile do
602       begin
603         Items.Clear;
604         Items.Add(ProfileName);
605         ItemIndex := 0;
606         LoadPlayTimeProfiles;
607       end;
608     except
609       on E: Exception do
610         ShowMessage('\95Û\91\82É\8e¸\94s\82µ\82Ü\82µ\82½\81B' + E.Message);
611     end;
612   end;
613 end;
614
615 procedure TfrmSetting.spnCostWaitChange(Sender: TObject);
616 var
617   ProName: String;
618 const
619   Modified = '(\95Ï\8dX\8dÏ\82Ý)';
620 begin
621   if FSpinUpdateFlag then
622     Exit;
623   ProName := cbxPlayTimeProfile.Text;
624   if Copy(ProName, Length(ProName)-Length(Modified)+1, Length(Modified)) <> Modified then
625   begin
626     ProName := Format('%s%s', [ProName, Modified]);
627     with cbxPlayTimeProfile do
628     begin
629       Items.Clear;
630       Items.Add(ProName);
631       ItemIndex := 0;
632       LoadPlayTimeProfiles;
633     end;
634   end;
635 end;
636
637 procedure TfrmSetting.btnPlaySpecialAddClick(Sender: TObject);
638 var
639   Item: TListItem;
640   SPChar: TSsPlayTimeSpecialChar;
641 begin
642   Application.CreateForm(TfrmSpecialCharEditor, frmSpecialCharEditor);
643   try
644     with frmSpecialCharEditor do
645     begin
646       SpecialChar := '';
647       Cost := 50;
648       if Execute then
649       begin
650         SPChar := Pref.PlayTimeParams.SpecialChars.Add as TSsPlayTimeSpecialChar;
651         SPChar.Char := SpecialChar;
652         SPChar.Wait := Cost;
653         Item := lvwCostSpecials.Items.Add;
654         Item.Caption := SPChar.DisplayChar;
655         Item.SubItems.Add(IntToStr(Cost));
656         spnCostWaitChange(Self);
657       end;
658     end;
659   finally
660     frmSpecialCharEditor.Release;
661   end;
662 end;
663
664 procedure TfrmSetting.btnPlaySpecialDeleteClick(Sender: TObject);
665 begin
666   with lvwCostSpecials do
667     if Selected <> nil then
668     begin
669       Pref.PlayTimeParams.SpecialChars.Delete(Selected.Index);
670       Selected.Delete;
671       spnCostWaitChange(Self);
672     end;
673 end;
674
675 procedure TfrmSetting.lvwCostSpecialsDblClick(Sender: TObject);
676 var
677   Item: TListItem;
678   SPChar: TSsPlayTimeSpecialChar;
679 begin
680   with lvwCostSpecials do
681   begin
682     Item := Selected;
683     if Item <> nil then
684     begin
685       Application.CreateForm(TfrmSpecialCharEditor, frmSpecialCharEditor);
686       try
687         with frmSpecialCharEditor do
688         begin
689           SPChar := Pref.PlayTimeParams.SpecialChars.Items[Item.Index] as TSsPlayTimeSpecialChar;
690           SpecialChar := SPChar.Char;
691           Cost := SPChar.Wait;
692           if Execute then
693           begin
694             SPChar.Char := SpecialChar;
695             SPChar.Wait := Cost;
696             Item.Caption := SPChar.DisplayChar;
697             Item.SubItems[0] := IntToStr(Cost);
698             spnCostWaitChange(Self);
699           end;
700         end;
701       finally
702         frmSpecialCharEditor.Release;
703       end;
704     end;
705   end;
706 end;
707
708 procedure TfrmSetting.UpdateSpecialChars;
709 var
710   i: integer;
711   Item: TListItem;
712   SPChar: TSsPlayTimeSpecialChar;
713 begin
714   with lvwCostSpecials do
715   begin
716     Items.Clear;
717     for i := 0 to Pref.PlayTimeParams.SpecialChars.Count-1 do
718     begin
719       SPChar := Pref.PlayTimeParams.SpecialChars.Items[i] as TSsPlayTimeSpecialChar;
720       Item := Items.Add;
721       Item.Caption := SPChar.DisplayChar;
722       Item.SubItems.Add(IntToStr(SPChar.Wait));
723     end;
724   end;
725 end;
726
727 procedure TfrmSetting.spnTabWidthChange(Sender: TObject);
728 begin
729   with cbxAutoTabWidth do
730   begin
731     OnClick := nil;
732     cbxAutoTabWidth.Checked := false;
733     OnClick := cbxAutoTabWidthClick;
734   end;
735 end;
736
737 procedure TfrmSetting.cbxAutoTabWidthClick(Sender: TObject);
738 begin
739   with spnTabWidth do
740   begin
741     OnChange := nil;
742     try
743       if not cbxAutoTabWidth.Checked then
744         if Value = 0 then
745           Value := 80;
746     finally
747       OnChange := spnTabWidthChange;
748     end;
749   end;
750 end;
751
752 procedure TfrmSetting.btnBrowserLocateClick(Sender: TObject);
753 begin
754   with BrowserLocateOpenDialog do
755   begin
756     FileName := edtBrowserName.Text;
757     if Execute then
758       edtBrowserName.Text := FileName;
759   end;
760 end;
761
762 procedure TfrmSetting.tstPresetReplaceShow(Sender: TObject);
763 begin
764   ReplacePresetList.UpdateControls;
765 end;
766
767 end.