OSDN Git Service

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