OSDN Git Service

Version string
[winbottle/winbottle.git] / bottleclient / BottleChainRule.pas
1 unit BottleChainRule;
2
3 interface
4
5 uses Windows, Classes, SysUtils, Dialogs, Contnrs, BottleChainEvent, Forms,
6   MinMaxEditor, StrListEditor, MultipleChoiceEditor, Logs,
7   HeadValue, SakuraSeekerInstance, Controls, BottleDef, BRegExp,
8   OpenFileEditor;
9
10 {
11 \83A\83N\83V\83\87\83\93\82ð\8eÀ\91\95\82·\82é\83\86\83j\83b\83g\81B
12 \83\8b\81[\83\8b = \82»\82Ì\83\8b\81[\83\8b\82ª\8bN\93®\82·\82é\8fð\8c\8f\82Ì\83\8a\83X\83g + \82»\82Ì\83\8b\81[\83\8b\82ª\8bN\82±\82·\83A\83N\83V\83\87\83\93\82Ì\83\8a\83X\83g
13 \96|\96ó\82·\82é\82Æ\81A
14 TBottleChainRule = TBottleChainCondition\82Ì\83\8a\83X\83g + TBottleChainAction\82Ì\83\8a\83X\83g
15
16 \88È\89º\83g\83b\83v\83_\83E\83\93\8e®\82É\83N\83\89\83X\82ð\8aT\97ª\82·\82é\81B
17
18 TBottleChainRuleList\82Í\81A\82·\82×\82Ä\82Ì\83\8b\81[\83\8b\82Ì\83\8a\83X\83g\82Å\82 \82è\81A
19 rule.txt\82É\95Û\91\82³\82ê\82é\91S\91Ì\82Å\82 \82é\81B
20
21 TBottleChainRule\82Í\81ATBottleChainCondition\82ÆTBottleChainAction\82Ì\83\8a\83X\83g\82ð
22 \8ai\94[\82·\82é\83R\83\93\83e\83i\82Å\82 \82è\81A1\82Â\82Ì\83\8b\81[\83\8b(\81\9b\81\9b\82©\82Â\81\9b\82Ü\82é\82Ì\82Æ\82«\81\9b\81\9b\82·\82é)\82ð\95\\82·\81B
23
24 \82»\82ê\82¼\82ê\82Ì\8fð\8c\8f\82Í\81A\92\8a\8fÛ\83N\83\89\83X\82Å\82 \82éTBottleChainCondition\82©\82ç\8cp\8f³\82µ\81A
25 \82»\82Ì\8fð\8c\8f\82ª\95Û\91\82·\82é\82×\82«\92Ç\89Á\83p\83\89\83\81\81[\83^(\90F\82È\82è\95\8e\9a\97ñ\83\8a\83X\83g\82È\82è)\82â\81A
26 \82»\82Ì\8fð\8c\8f\82Ì\95\8e\9a\97ñ\82É\82æ\82é\95\\8c»(\81\9b\81\9b\82Ì\82Æ\82«)\82ð\8aÇ\97\9d\82·\82é\81B
27
28 \93¯\97l\82É\81A\82»\82ê\82¼\82ê\82Ì\83A\83N\83V\83\87\83\93\82Í\92\8a\8fÛ\83N\83\89\83X\82Å\82 \82éTBottleChainAction\82©\82ç\8cp\8f³\82·\82é\81B
29 }
30
31
32 type
33   TBottleChainCondition = class;
34   TBottleChainConditionClass = class of TBottleChainCondition;
35   TBottleChainAction = class;
36   TBottleChainActionClass = class of TBottleChainAction;
37   TBottleChainRule = class;
38   TBottleChainRuleList = class;
39
40   // \8fð\8c\8f\82ð\96\9e\82½\82µ\82½\8cã\82Ì\93®\8dì
41   TBottleChainAction = class(TComponent)
42   private
43     FRule: TBottleChainRule;
44     procedure SetRule(const Value: TBottleChainRule);
45   protected
46     procedure SetParentComponent(AParent: TComponent); override;
47     procedure ReadState(Reader: TReader); override;
48   public
49     destructor Destroy; override;
50     function HasParent: boolean; override;
51     function GetParentComponent: TComponent; override;
52     class function Title: String; virtual; abstract;
53     function Edit: boolean; virtual;
54     function StringExpression: String; virtual;
55     property Rule: TBottleChainRule read FRule write SetRule;
56   end;
57
58   // \83C\83x\83\93\83g\82Ì\8fð\8c\8f\82ð\8eÀ\91\95\82·\82é
59   TBottleChainCondition = class(TComponent)
60   private
61     FRule: TBottleChainRule;
62     procedure SetRule(const Value: TBottleChainRule);
63   protected
64     procedure SetParentComponent(AParent: TComponent); override;
65     procedure ReadState(Reader: TReader); override;
66   public
67     destructor Destroy; override;
68     function HasParent: boolean; override;
69     function GetParentComponent: TComponent; override;
70     class function Title: String; virtual; abstract;
71     function Check(Event: TBottleChainEvent): boolean; virtual; abstract;
72     function Edit: boolean; virtual;
73     function StringExpression: String; virtual;
74     property Rule: TBottleChainRule read FRule write SetRule;
75   end;
76
77   // \8fð\8c\8f\82Æ\83A\83N\83V\83\87\83\93\82ð\91g\82Ý\8d\87\82í\82¹\82½1\82Â\82Ì\83\8b\81[\83\8b
78   TBottleChainRule = class(TComponent)
79   private
80     FConditions: TObjectList;
81     FActions: TObjectList;
82     FRuleList: TBottleChainRuleList;
83     FEnabled: boolean;
84     FTitle: String;
85     procedure SetActions(const Value: TObjectList);
86     procedure SetConditions(const Value: TObjectList);
87     procedure SetRuleList(const Value: TBottleChainRuleList);
88     procedure SetEnabled(const Value: boolean);
89     procedure SetTitle(const Value: String);
90   protected
91     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
92     procedure SetParentComonent(AParent: TComponent);
93     procedure ReadState(Reader: TReader); override;
94   public
95     function HasParent: boolean; override;
96     function GetParentComponent: TComponent; override;
97     procedure AddCondition(ACondition: TBottleChainCondition);
98     procedure RemoveCondition(ACondition: TBottleChainCondition);
99     procedure AddAction(AnAction: TBottleChainAction);
100     procedure RemoveAction(AnAction: TBottleChainAction);
101     constructor Create(AOwner: TComponent); override;
102     destructor Destroy; override;
103     function StringExpression: String;
104     property Conditions: TObjectList read FConditions write SetConditions;
105     property Actions: TObjectList read FActions write SetActions;
106     property RuleList: TBottleChainRuleList read FRuleList write SetRuleList;
107     function Check(Event: TBottleChainEvent): boolean;
108   published
109     property Enabled: boolean read FEnabled write SetEnabled;
110     property Title: String read FTitle write SetTitle;
111   end;
112
113   // \83\8b\81[\83\8b\82Ì\83\8a\83X\83g
114   TBottleChainRuleList = class(TComponent)
115   private
116     FRules: TObjectList;
117     function GetCount: integer;
118     function GetRules(Index: integer): TBottleChainRule;
119   protected
120     //procedure DefineProperties(Filer: TFiler); override;
121     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
122   public
123     procedure AddRule(ARule: TBottleChainRule);
124     procedure RemoveRule(ARule: TBottleChainRule);
125     constructor Create(AOwner: TComponent); override;
126     destructor Destroy; override;
127     property Count: integer read GetCount;
128     property Rules[Index: integer]: TBottleChainRule read GetRules; default;
129     property List: TObjectList read FRules;
130   end;
131
132   {\82±\82±\82©\82ç\8cÂ\95Ê}
133   {***** \8fð\8c\8f *****}
134
135   // \83`\83\83\83\93\83l\83\8b\96¼\82ª\8ew\92è\82Ì\82à\82Ì\82Å\82 \82é\82Æ\82«
136   TBottleChainChannelCondition = class(TBottleChainCondition)
137   private
138     FChannels: TStrings;
139     procedure SetChannels(const Value: TStrings);
140   public
141     constructor Create(AOwner: TComponent); override;
142     destructor Destroy; override;
143     class function Title: String; override;
144     function Check(Event: TBottleChainEvent): boolean; override;
145     function Edit: boolean; override;
146     function StringExpression: String; override;
147   published
148     property Channels: TStrings read FChannels write SetChannels;
149   end;
150
151   // \83`\83\83\83\93\83l\83\8b\96¼\82ª\8ew\92è\82Ì\82à\82Ì\82Å\82È\82¢\82Æ\82«
152   TBottleChainChannelNotCondition = class (TBottleChainChannelCondition)
153   public
154     class function Title: String; override;
155     function Check(Event: TBottleChainEvent): boolean; override;
156     function StringExpression: String; override;
157   end;
158
159   // \83S\81[\83X\83g\82ª\8ew\92è\82Ì\82à\82Ì\82Å\82 \82é\82Æ\82«
160   TBottleChainGhostCondition = class (TBottleChainCondition)
161   private
162     FGhosts: TStrings;
163     procedure SetGhosts(const Value: TStrings);
164   public
165     constructor Create(AOwner: TComponent); override;
166     destructor Destroy; override;
167     class function Title: String; override;
168     function Check(Event: TBottleChainEvent): boolean; override;
169     function Edit: boolean; override;
170     function StringExpression: String; override;
171   published
172     property Ghosts: TStrings read FGhosts write SetGhosts;
173   end;
174
175   // \83S\81[\83X\83g\82ª\8ew\92è\82Ì\82à\82Ì\82Å\82È\82¢\82Æ\82«
176   TBottleChainGhostNotCondition = class (TBottleChainGhostCondition)
177   public
178     class function Title: String; override;
179     function Check(Event: TBottleChainEvent): boolean; override;
180     function StringExpression: String; override;
181   end;
182
183   // \83X\83N\83\8a\83v\83g\82Ì\92·\82³\82ªn\88È\8fãm\96¢\96\9e\82Å\82 \82é\82Æ\82«
184   TBottleChainScriptLengthCondition = class(TBottleChainCondition)
185   private
186     FMinLength: integer;
187     FMaxLength: integer;
188     procedure SetMaxLength(const Value: integer);
189     procedure SetMinLength(const Value: integer);
190   public
191     class function Title: String; override;
192     function Check(Event: TBottleChainEvent): boolean; override;
193     function Edit: boolean; override;
194     function StringExpression: String; override;
195   published
196     property MinLength: integer read FMinLength write SetMinLength;
197     property MaxLength: integer read FMaxLength write SetMaxLength;
198   end;
199
200   // \83X\83N\83\8a\83v\83g\82ª\81\9b\81\9b\82ð\8aÜ\82Þ\82Æ\82«
201   TBottleChainScriptCondition = class(TBottleChainCondition)
202   private
203     FPatterns: TStrings;
204     FAll: boolean;
205     procedure SetPatterns(const Value: TStrings);
206     procedure SetAll(const Value: boolean);
207   public
208     class function Title: String; override;
209     function Check(Event: TBottleChainEvent): boolean; override;
210     function Edit: boolean; override;
211     function StringExpression: String; override;
212     constructor Create(AOwner: TComponent); override;
213     destructor Destroy; override;
214   published
215     property Patterns: TStrings read FPatterns write SetPatterns;
216     property All: boolean read FAll write SetAll default false;
217   end;
218
219   // \83X\83N\83\8a\83v\83g\82ª\81\9b\81\9b\82ð\8aÜ\82Ü\82È\82¢\82Æ\82«
220   TBottleChainScriptNotCondition = class(TBottleChainScriptCondition)
221   public
222     class function Title: String; override;
223     function StringExpression: String; override;
224     function Check(Event: TBottleChainEvent): boolean; override;
225   end;
226
227   // \83\81\83b\83Z\81[\83W\82Ì\83^\83C\83v(\92Ê\8fí\83{\83g\83\8b\81E\82¨\92m\82ç\82¹)
228   TBottleChainBottleTypeCondition = class(TBottleChainCondition)
229   private
230     FLogType: TLogType;
231     procedure SetLogType(const Value: TLogType);
232   public
233     class function Title: String; override;
234     function Check(Event: TBottleChainEvent): boolean; override;
235     function Edit: boolean; override;
236     function StringExpression: String; override;
237   published
238     property LogType: TLogType read FLogType write SetLogType;
239   end;
240
241   // \91\97\90M\90æ\83S\81[\83X\83g\82ª\91\8dÝ\82µ\82È\82¢\82Æ\82«
242   TBottleChainTargetGhostNotExistCondition = class(TBottleChainCondition)
243   public
244     class function Title: String; override;
245     function Check(Event: TBottleChainEvent): boolean; override;
246   end;
247
248   // \83X\83N\83\8a\83v\83g\82ª\8ew\92è\82Ì\90³\8bK\95\\8c»\82É\83}\83b\83`\82·\82é\82Æ\82«
249   TBottleChainScriptRegExpCondition = class(TBottleChainCondition)
250   private
251     FPattern: String;
252     procedure SetPattern(const Value: String);
253   public
254     class function Title: String; override;
255     function Check(Event: TBottleChainEvent): boolean; override;
256     function Edit: boolean; override;
257     function StringExpression: String; override;
258     constructor Create(AOwner: TComponent); override;
259   published
260     property Pattern: String read FPattern write SetPattern;
261   end;
262
263   {***** \83A\83N\83V\83\87\83\93 *****}
264
265   // \89¹\82ð\96Â\82ç\82·
266   TBottleChainSoundAction = class(TBottleChainAction)
267   private
268     FSoundFile: String;
269     procedure SetSoundFile(const Value: String);
270   public
271     class function Title: String; override;
272     function StringExpression: String; override;
273     function Edit: boolean; override;
274   published
275     property SoundFile: String read FSoundFile write SetSoundFile;
276   end;
277
278   // \82±\82ê\88È\8d~\82Ì\83\8b\81[\83\8b\82Ì\8f\88\97\9d\82ð\92\86\8e~\82·\82é
279   TBottleChainAbortRuleAction = class(TBottleChainAction)
280   public
281     class function Title: String; override;
282   end;
283
284   // \82±\82ê\88È\8d~\82Ìn\8cÂ\82Ì\83\8b\81[\83\8b\82ð\83X\83L\83b\83v\82·\82é
285   TBottleChainSkipRuleAction = class(TBottleChainAction)
286   private
287     FSkipCount: integer;
288     procedure SetSkipCount(const Value: integer);
289   public
290     class function Title: String; override;
291     function StringExpression: String; override;
292     function Edit: boolean; override;
293     constructor Create(AOwner: TComponent); override;
294   published
295     property SkipCount: integer read FSkipCount write SetSkipCount;
296   end;
297
298   // \8e©\94\9a\82·\82é
299   TBottleChainQuitAction = class(TBottleChainAction)
300   public
301     class function Title: String; override;
302     function Edit: boolean; override;
303   end;
304
305   // \8ew\92è\83^\83u\82É\83\8d\83O\82ð\8ec\82·
306   TBottleChainLogAction = class(TBottleChainAction)
307   private
308     FLogNames: TStrings;
309     procedure SetLogNames(const Value: TStrings);
310   public
311     class function Title: String; override;
312     function StringExpression: String; override;
313     function Edit: boolean; override;
314     constructor Create(AOwner: TComponent); override;
315     destructor Destroy; override;
316   published
317     property LogNames: TStrings read FLogNames write SetLogNames;
318   end;
319
320   // \91\97\90M\90æ\83S\81[\83X\83g\82ð\95Ï\8dX\82·\82é
321   TBottleChainOverrideGhostAction = class(TBottleChainAction)
322   private
323     FTargetGhost: String;
324     procedure SetTargetGhost(const Value: String);
325   public
326     class function Title: String; override;
327     function StringExpression: String; override;
328     function Edit: boolean; override;
329   published
330     property TargetGhost: String read FTargetGhost write SetTargetGhost;
331   end;
332
333   // \83\81\83b\83Z\81[\83W\82ðSSTP\83T\81[\83o\82É\91\97\90M\82µ\82È\82¢
334   TBottleChainNoDispatchAction = class(TBottleChainAction)
335   public
336     class function Title: String; override;
337   end;
338
339   // \83\8d\83O\82ð\8ec\82·(\8b¤\92Ê\93®\8dì)
340   TBottleChainSaveLogAction = class(TBottleChainAction)
341   private
342     FFileName: String;
343     procedure SetFileName(const Value: String);
344   protected
345     function Filter: String; virtual; abstract;
346   public
347     function Edit: boolean; override;
348   published
349     property FileName: String read FFileName write SetFileName;
350   end;
351
352   // \83e\83L\83X\83g\8c`\8e®\82Ì\83\8d\83O\82ð\8ec\82·
353   TBottleChainSaveTextLogAction = class(TBottleChainSaveLogAction)
354   protected
355     function Filter: String; override;
356   public
357     class function Title: String; override;
358     function StringExpression: String; override;
359   end;
360
361   // XML\8c`\8e®\82Ì\83\8d\83O\82ð\8ec\82·
362   TBottleChainSaveXMLLogAction = class (TBottleChainSaveLogAction)
363   protected
364     function Filter: String; override;
365   public
366     class function Title: String; override;
367     function StringExpression: String; override;
368   end;
369
370 const
371   BottleChainActions: array [0..8] of TBottleChainActionClass = (
372     TBottleChainLogAction,
373     TBottleChainSoundAction,
374     TBottleChainNoDispatchAction,
375     TBottleChainOverrideGhostAction,
376     TBottleChainAbortRuleAction,
377     TBottleChainSkipRuleAction,
378     TBottleChainSaveXMLLogAction,
379     TBottleChainSaveTextLogAction,
380     TBottleChainQuitAction
381   );
382   BottleChainConditions: array [0..9] of TBottleChainConditionClass = (
383     TBottleChainBottleTypeCondition,
384     TBottleChainChannelCondition, TBottleChainChannelNotCondition,
385     TBottleChainGhostCondition, TBottleChainGhostNotCondition,
386     TBottleChainScriptCondition, TBottleChainScriptNotCondition,
387     TBottleChainScriptLengthCondition, TBottleChainScriptRegExpCondition,
388     TBottleChainTargetGhostNotExistCondition
389   );
390
391 var BottleChainRuleList: TBottleChainRuleList;
392
393 implementation
394
395 var classregister_counter: integer; // RegisterClass\97p
396
397 { TBottleChainCondition }
398
399 destructor TBottleChainCondition.Destroy;
400 begin
401   if Rule <> nil then Rule.RemoveCondition(self);
402   inherited;
403 end;
404
405 function TBottleChainCondition.Edit: boolean;
406 begin
407   Result := true;
408 end;
409
410 function TBottleChainCondition.GetParentComponent: TComponent;
411 begin
412   if Rule <> nil then Result := Rule
413   else Result := inherited GetParentComponent;
414 end;
415
416 function TBottleChainCondition.HasParent: boolean;
417 begin
418   if Rule <> nil then Result := true
419   else Result := inherited HasParent;
420 end;
421
422 procedure TBottleChainCondition.ReadState(Reader: TReader);
423 begin
424   inherited;
425   if Reader.Parent is TBottleChainRule then begin
426     Rule := Reader.Parent as TBottleChainRule;
427   end;
428 end;
429
430 procedure TBottleChainCondition.SetParentComponent(AParent: TComponent);
431 begin
432   if not (csLoading in ComponentState) and (AParent is TBottleChainRule) then
433     Rule := AParent as TBottleChainRule;
434 end;
435
436 procedure TBottleChainCondition.SetRule(const Value: TBottleChainRule);
437 begin
438   if Value <> Rule then begin
439     if Rule <> nil then Rule.RemoveCondition(self);
440     if Value <> nil then Value.AddCondition(self);
441     FRule := Value;
442   end;
443 end;
444
445 function TBottleChainCondition.StringExpression: String;
446 begin
447   Result := Title;
448 end;
449
450 { TBottleChainAction }
451
452 destructor TBottleChainAction.Destroy;
453 begin
454   if Rule <> nil then Rule.RemoveAction(self);
455   inherited;
456 end;
457
458 function TBottleChainAction.Edit: boolean;
459 begin
460   Result := true;
461 end;
462
463 function TBottleChainAction.GetParentComponent: TComponent;
464 begin
465   if Rule <> nil then Result := Rule
466   else Result := inherited GetParentComponent;
467 end;
468
469 function TBottleChainAction.HasParent: boolean;
470 begin
471   if Rule <> nil then Result := true
472   else Result := inherited HasParent;
473 end;
474
475 procedure TBottleChainAction.ReadState(Reader: TReader);
476 begin
477   inherited;
478   if Reader.Parent is TBottleChainRule then begin
479     Rule := Reader.Parent as TBottleChainRule;
480   end;
481 end;
482
483 procedure TBottleChainAction.SetParentComponent(AParent: TComponent);
484 begin
485   if not (csLoading in ComponentState) and (AParent is TBottleChainRule) then
486     Rule := AParent as TBottleChainRule;
487 end;
488
489 procedure TBottleChainAction.SetRule(const Value: TBottleChainRule);
490 begin
491   if Value <> Rule then begin
492     if Rule <> nil then Rule.RemoveAction(self);
493     if Value <> nil then Value.AddAction(self);
494     FRule := Value;
495   end;
496 end;
497
498 function TBottleChainAction.StringExpression: String;
499 begin
500   Result := Title;
501 end;
502
503 { TBottleChainChannelCondition }
504
505 function TBottleChainChannelCondition.Check(
506   Event: TBottleChainEvent): boolean;
507 var i: integer;
508     Dat: THeadValue;
509 begin
510   Result := false;
511   if not (Event is TBottleChainBottleEvent) then Exit;
512   Dat := (Event as TBottleChainBottleEvent).Data;
513   for i := 0 to FChannels.Count-1 do
514     if Dat['Channel'] = FChannels[i] then begin
515       Result := true;
516       Exit;
517     end;
518 end;
519
520 constructor TBottleChainChannelCondition.Create;
521 begin
522   inherited;
523   FChannels := TStringList.Create;
524 end;
525
526 destructor TBottleChainChannelCondition.Destroy;
527 begin
528   FChannels.Free;
529   inherited;
530 end;
531
532 function TBottleChainChannelCondition.Edit: boolean;
533 var Chs: TStringList;
534     i: integer;
535 begin
536   Chs := TStringList.Create;
537   try
538     for i := 0 to ChannelList.Count-1 do
539       Chs.Add(ChannelList.ChannelItem[i].Name);
540     Result := StrListEdit(FChannels, '\83`\83\83\83\93\83l\83\8b\82ð1\8ds\82¸\82Â\8ew\92è', false, Chs);
541   finally
542     Chs.Free;
543   end;
544 end;
545
546 procedure TBottleChainChannelCondition.SetChannels(const Value: TStrings);
547 begin
548   FChannels.Assign(Value);
549 end;
550
551 function TBottleChainChannelCondition.StringExpression: String;
552 var i: integer;
553     chs: String;
554 begin
555   chs := '';
556   for i := 0 to FChannels.Count-1 do begin
557     if i > 0 then chs := chs + ' \82© ';
558     chs := Format('%s\81u%s\81v', [chs, FChannels[i]]);
559   end;
560   Result := Format('\8eó\90M\83`\83\83\83\93\83l\83\8b\82ª %s \82Ì\82Æ\82«', [chs]);
561 end;
562
563 class function TBottleChainChannelCondition.Title: String;
564 begin
565   Result := '\8eó\90M\83`\83\83\83\93\83l\83\8b\82ª(\8ew\92è)\82Ì\82Æ\82«';
566 end;
567
568 { TBottleChainRule }
569
570 procedure TBottleChainRule.AddAction(AnAction: TBottleChainAction);
571 begin
572   FActions.Add(AnAction);
573 end;
574
575 procedure TBottleChainRule.AddCondition(ACondition: TBottleChainCondition);
576 begin
577   FConditions.Add(ACondition);
578 end;
579
580 constructor TBottleChainRule.Create;
581 begin
582   inherited;
583   // Do NOT own objects!!
584   FConditions := TObjectList.Create(false);
585   FActions := TObjectList.Create(false);
586 end;
587
588 destructor TBottleChainRule.Destroy;
589 begin
590   // \8e©\95ª\8e©\90g\82ª\8fÁ\82¦\82é\82Æ\82«\82É\82Í\8eq\82ð\89ð\95ú\82·\82é
591   FConditions.OwnsObjects := true;
592   FConditions.Free;
593   FActions.OwnsObjects := true;
594   FActions.Free;
595   if RuleList <> nil then RuleList.RemoveRule(Self);
596   inherited;
597 end;
598
599 procedure TBottleChainRule.GetChildren(Proc: TGetChildProc;
600   Root: TComponent);
601 var i: integer;
602 begin
603   inherited;
604   for i := 0 to FConditions.Count-1 do Proc(FConditions[i] as TComponent);
605   for i := 0 to FActions.Count-1 do Proc(FActions[i] as TComponent);
606 end;
607
608 function TBottleChainRule.GetParentComponent: TComponent;
609 begin
610   if RuleList <> nil then Result := RuleList
611   else Result := inherited GetParentComponent;
612 end;
613
614 function TBottleChainRule.HasParent: boolean;
615 begin
616   if FRuleList <> nil then Result := true
617   else Result := inherited HasParent;
618 end;
619
620 procedure TBottleChainRule.ReadState(Reader: TReader);
621 begin
622   inherited;
623   if Reader.Parent is TBottleChainRuleList then begin
624     RuleList := Reader.Parent as TBottleChainRuleList;
625   end;
626 end;
627
628 procedure TBottleChainRule.RemoveCondition(
629   ACondition: TBottleChainCondition);
630 begin
631   FConditions.Remove(ACondition);
632 end;
633
634 procedure TBottleChainRule.RemoveAction(AnAction: TBottleChainAction);
635 begin
636   FActions.Remove(AnAction);
637 end;
638
639 procedure TBottleChainRule.SetActions(const Value: TObjectList);
640 begin
641   FActions.Assign(Value);
642 end;
643
644 procedure TBottleChainRule.SetConditions(const Value: TObjectList);
645 begin
646   FConditions.Assign(Value);
647 end;
648
649 procedure TBottleChainRule.SetParentComonent(AParent: TComponent);
650 begin
651   if not (csLoading in ComponentState) and (AParent is TBottleChainRuleList) then
652     RuleList := AParent as TBottleChainRuleList;
653 end;
654
655 procedure TBottleChainRule.SetRuleList(const Value: TBottleChainRuleList);
656 begin
657   if Value <> FRuleList then begin
658     if FRuleList <> nil then FRuleList.RemoveRule(self);
659     if Value <> nil then Value.AddRule(self);
660     FRuleList := Value;
661   end;
662 end;
663
664 function TBottleChainRule.StringExpression: String;
665 var i: integer;
666 begin
667   Result := '';
668   for i := 0 to FConditions.Count-1 do begin
669     if i > 0 then Result := Result + '\81A\82©\82Â';
670     Result := Result + (FConditions[i] as TBottleChainCondition).StringExpression;
671   end;
672   if FActions.Count = 0 then begin
673     Result := Result + '\89½\82à\82µ\82È\82¢';
674   end else begin
675     for i := 0 to FActions.Count-1 do begin
676       if i > 0 then Result := Result + '\81B\82³\82ç\82É';
677       Result := Result + (FActions[i] as TBottleChainAction).StringExpression;
678     end;
679   end;
680   Result := Result + '\81B';
681 end;
682
683 procedure TBottleChainRule.SetEnabled(const Value: boolean);
684 begin
685   FEnabled := Value;
686 end;
687
688 procedure TBottleChainRule.SetTitle(const Value: String);
689 begin
690   FTitle := Value;
691 end;
692
693 function TBottleChainRule.Check(Event: TBottleChainEvent): boolean;
694 var i: integer;
695     re: boolean;
696     {str: String;}
697 begin
698   Result := true;
699   for i := 0 to Conditions.Count-1 do begin
700     re := (Conditions[i] as TBottleChainCondition).Check(Event);
701     {if re then Str := 'true' else Str := 'false';
702     ShowMessage((Conditions[i] as TBottleChainCondition).StringExpression + #13#10 + str + #13#10 +
703       (Event as TBottleChainBottleEvent).Data.ToStr);}
704     if not re then begin
705       Result := false;
706       Exit;
707     end;
708   end;
709 end;
710
711 { TBottleChainRuleList }
712
713 procedure TBottleChainRuleList.AddRule(ARule: TBottleChainRule);
714 begin
715   FRules.Add(ARule);
716 end;
717
718 constructor TBottleChainRuleList.Create(AOwner: TComponent);
719 begin
720   inherited;
721   // Do NOT own object!!
722   FRules := TObjectList.Create(false);
723 end;
724
725 destructor TBottleChainRuleList.Destroy;
726 begin
727   FRules.Free;
728   inherited;
729 end;
730
731 procedure TBottleChainRuleList.GetChildren(Proc: TGetChildProc;
732   Root: TComponent);
733 var i: integer;
734 begin
735   inherited;
736   for i := 0 to FRules.Count-1 do begin
737     Proc(FRules[i] as TComponent);
738   end;
739 end;
740
741 function TBottleChainRuleList.GetCount: integer;
742 begin
743   Result := FRules.Count;
744 end;
745
746 function TBottleChainRuleList.GetRules(Index: integer): TBottleChainRule;
747 begin
748   Result := FRules[Index] as TBottleChainRule;
749 end;
750
751 procedure TBottleChainRuleList.RemoveRule(ARule: TBottleChainRule);
752 begin
753   FRules.Remove(ARule);
754 end;
755
756 { TBottleChainSoundAction }
757
758 function TBottleChainSoundAction.Edit: boolean;
759 var FileName: String;
760 begin
761   FileName := SoundFile;
762   Result := OpenFileEdit(FileName,
763     '\83T\83E\83\93\83h\83t\83@\83C\83\8b(*.wav)|*.wav|\82·\82×\82Ä\82Ì\83t\83@\83C\83\8b(*.*)|*.*',
764     '\83t\83@\83C\83\8b\8ew\92è(\83\81\83^\95\8e\9a\81u%ghost%\81v\81u%channel%\81v\97\98\97p\89Â)', []);
765   if Result then SoundFile := FileName;
766 end;
767
768 procedure TBottleChainSoundAction.SetSoundFile(const Value: String);
769 begin
770   FSoundFile := Value;
771 end;
772
773 function TBottleChainSoundAction.StringExpression: String;
774 begin
775   Result := Format('\83T\83E\83\93\83h\81u%s\81v\82ð\96Â\82ç\82·', [ExtractFileName(SoundFile)]);
776 end;
777
778 class function TBottleChainSoundAction.Title: String;
779 begin
780   Result := '(\89¹)\82ð\96Â\82ç\82·'
781 end;
782
783 { TBottleChainChannelNotCondition }
784
785 function TBottleChainChannelNotCondition.Check(Event: TBottleChainEvent): boolean;
786 var i: integer;
787     Dat: THeadValue;
788 begin
789   Result := false;
790   if not (Event is TBottleChainBottleEvent) then Exit;
791   Result := true;
792   Dat := (Event as TBottleChainBottleEvent).Data;
793   for i := 0 to FChannels.Count-1 do
794     if Dat['Channel'] = FChannels[i] then begin
795       Result := false;
796       Exit;
797     end;
798 end;
799
800 function TBottleChainChannelNotCondition.StringExpression: String;
801 var i: integer;
802     chs: String;
803 begin
804   chs := '';
805   for i := 0 to FChannels.Count-1 do begin
806     if i > 0 then chs := chs + ' \82â ';
807     chs := Format('%s\81u%s\81v', [chs, FChannels[i]]);
808   end;
809   Result := Format('\8eó\90M\83`\83\83\83\93\83l\83\8b\82ª %s \82Å\82Í\82È\82¢\82Æ\82«', [chs]);
810 end;
811
812 class function TBottleChainChannelNotCondition.Title: String;
813 begin
814   Result := '\8eó\90M\83`\83\83\83\93\83l\83\8b\82ª(\8ew\92è)\82Å\82Í\82È\82¢\82Æ\82«';
815 end;
816
817 { TBottleChainGhostCondition }
818
819 function TBottleChainGhostCondition.Check(
820   Event: TBottleChainEvent): boolean;
821 var i: integer;
822     Dat: THeadValue;
823 begin
824   Result := false;
825   if not (Event is TBottleChainBottleEvent) then Exit;
826   Dat := (Event as TBottleChainBottleEvent).Data;
827   for i := 0 to FGhosts.Count-1 do
828     if Dat['IfGhost'] = FGhosts[i] then begin
829       Result := true;
830       Exit;
831     end;
832 end;
833
834 constructor TBottleChainGhostCondition.Create(AOwner: TComponent);
835 begin
836   inherited;
837   FGhosts := TStringList.Create;
838 end;
839
840 destructor TBottleChainGhostCondition.Destroy;
841 begin
842   FGhosts.Free;
843   inherited;
844 end;
845
846 function TBottleChainGhostCondition.Edit: boolean;
847 var Consts: TStringList;
848     i: integer;
849 begin
850   Consts := TStringList.Create;
851   try
852     SakuraSeeker.BeginDetect;
853     for i := 0 to SakuraSeeker.Count-1 do
854       if Consts.IndexOf(SakuraSeeker[i].Name) < 0 then
855         Consts.Add(SakuraSeeker[i].Name);
856     Result := StrListEdit(FGhosts, '\83S\81[\83X\83g\82ð1\8ds\82¸\82Â\8ew\92è', false, Consts);
857   finally
858     Consts.Free;
859   end;
860 end;
861
862 procedure TBottleChainGhostCondition.SetGhosts(const Value: TStrings);
863 begin
864   FGhosts.Assign(Value);
865 end;
866
867 function TBottleChainGhostCondition.StringExpression: String;
868 var i: integer;
869     ghosts: String;
870 begin
871   ghosts := '';
872   for i := 0 to FGhosts.Count-1 do begin
873     if i > 0 then ghosts := ghosts + ' \82© ';
874     ghosts := Format('%s\81u%s\81v', [ghosts, FGhosts[i]]);
875   end;
876   Result := Format('\83S\81[\83X\83g\82ª %s \82Ì\82Æ\82«', [ghosts]);
877 end;
878
879 class function TBottleChainGhostCondition.Title: String;
880 begin
881   Result := '\83S\81[\83X\83g\82ª(\8ew\92è)\82Ì\82Æ\82«';
882 end;
883
884 { TBottleChainGhostNotCondition }
885
886 function TBottleChainGhostNotCondition.Check(
887   Event: TBottleChainEvent): boolean;
888 var i: integer;
889     Dat: THeadValue;
890 begin
891   Result := false;
892   if not (Event is TBottleChainBottleEvent) then Exit;
893   Result := true;
894   Dat := (Event as TBottleChainBottleEvent).Data;
895   for i := 0 to FGhosts.Count-1 do
896     if Dat['Channel'] = FGhosts[i] then begin
897       Result := false;
898       Exit;
899     end;
900 end;
901
902 function TBottleChainGhostNotCondition.StringExpression: String;
903 var i: integer;
904     ghosts: String;
905 begin
906   ghosts := '';
907   for i := 0 to FGhosts.Count-1 do begin
908     if i > 0 then ghosts := ghosts + ' \82â ';
909     ghosts := Format('%s\81u%s\81v', [ghosts, FGhosts[i]]);
910   end;
911   Result := Format('\83S\81[\83X\83g\82ª %s \82Å\82È\82¢\82Æ\82«', [ghosts]);
912 end;
913
914 class function TBottleChainGhostNotCondition.Title: String;
915 begin
916   Result := '\83S\81[\83X\83g\82ª(\8ew\92è)\82Å\82È\82¢\82Æ\82«';
917 end;
918
919 { TBottleChainAbortRuleAction }
920
921 class function TBottleChainAbortRuleAction.Title: String;
922 begin
923   Result := '\82±\82ê\88È\8d~\82Ì\83\8b\81[\83\8b\82Ì\8f\88\97\9d\82ð\92\86\8e~\82·\82é';
924 end;
925
926 { TBottleChainScriptLengthCondition }
927
928 function TBottleChainScriptLengthCondition.Check(
929   Event: TBottleChainEvent): boolean;
930 var Dat: THeadValue;
931     len: integer;
932 begin
933   Result := false;
934   if not (Event is TBottleChainBottleEvent) then Exit;
935   Dat := (Event as TBottleChainBottleEvent).Data;
936   len := Length(Dat['Script']);
937   Result := (len >= FMinLength) and (len <= FMaxLength);
938 end;
939
940 function TBottleChainScriptLengthCondition.Edit: boolean;
941 begin
942   Application.CreateForm(TfrmMinMaxEditor, frmMinMaxEditor);
943   with frmMinMaxEditor do begin
944     spnMin.Value := FMinLength;
945     spnMax.Value := FMaxLength;
946     Result := Execute;
947     if Result then begin
948       FMinLength := spnMin.Value;
949       FMaxLength := spnMax.Value;
950     end;
951     Release;
952   end;
953 end;
954
955 procedure TBottleChainScriptLengthCondition.SetMaxLength(
956   const Value: integer);
957 begin
958   if Value >= 0 then FMaxLength := Value;
959 end;
960
961 procedure TBottleChainScriptLengthCondition.SetMinLength(
962   const Value: integer);
963 begin
964   if Value >= 0 then FMinLength := Value;
965 end;
966
967 function TBottleChainScriptLengthCondition.StringExpression: String;
968 begin
969   Result := Format('\83X\83N\83\8a\83v\83g\82Ì\92·\82³\82ª%d\83o\83C\83g\88È\8fã%d\83o\83C\83g\88È\89º\82Ì\82Æ\82«', [FMinLength, FMaxLength]);
970 end;
971
972 class function TBottleChainScriptLengthCondition.Title: String;
973 begin
974   Result := '\83X\83N\83\8a\83v\83g\82Ì\92·\82³\82ª(\8ew\92è)\83o\83C\83g\88È\8fã(\8ew\92è)\83o\83C\83g\88È\89º\82Ì\82Æ\82«';
975 end;
976
977 { TBottleChainQuitAction }
978
979 function TBottleChainQuitAction.Edit: boolean;
980 begin
981   Result := MessageDlg('\96{\8bC\82Å\82·\82©?', mtWarning, mbOkCancel, 0) = mrOk;
982 end;
983
984 class function TBottleChainQuitAction.Title: String;
985 begin
986   Result := '\8e©\94\9a\82·\82é';
987 end;
988
989 { TBottleChainScriptCondition }
990
991 function TBottleChainScriptCondition.Check(Event: TBottleChainEvent): boolean;
992 var i: integer;
993     Dat: THeadValue;
994 begin
995   Result := false;
996   if not (Event is TBottleChainBottleEvent) then Exit;
997   Dat := (Event as TBottleChainBottleEvent).Data;
998   if All then
999   begin
1000     Result := true;
1001     for i := 0 to FPatterns.Count-1 do
1002       if AnsiPos(FPatterns[i], Dat['Script']) <= 0 then
1003       begin
1004         Result := false;
1005         Exit;
1006       end;
1007   end else
1008   begin
1009     for i := 0 to FPatterns.Count-1 do
1010       if AnsiPos(FPatterns[i], Dat['Script']) > 0 then
1011       begin
1012         Result := true;
1013         Exit;
1014       end;
1015   end;
1016 end;
1017
1018 constructor TBottleChainScriptCondition.Create(AOwner: TComponent);
1019 begin
1020   inherited;
1021   FPatterns := TStringList.Create;
1022 end;
1023
1024 destructor TBottleChainScriptCondition.Destroy;
1025 begin
1026   FPatterns.Free;
1027   inherited;
1028 end;
1029
1030 function TBottleChainScriptCondition.Edit: boolean;
1031 var Index: integer;
1032     SavedPattern: TStringList;
1033 begin
1034   SavedPattern := TStringList.Create;
1035   try
1036     SavedPattern.Assign(FPatterns);
1037     Result := StrListEdit(FPatterns, '\83p\83^\81[\83\93\82ð1\8ds\82¸\82Â\8ew\92è');
1038     if FAll then
1039       Index := 1
1040     else
1041       Index := 0;
1042     if not Result then
1043       Exit;
1044     if FPatterns.Count > 1 then
1045     begin
1046       Result := MultipleChoiceEdit('\83I\83v\83V\83\87\83\93', ['\82¢\82¸\82ê\82©', '\82·\82×\82Ä'], Index);
1047       if Result then
1048         FAll := Index = 1
1049       else
1050         FPatterns.Assign(SavedPattern);
1051     end;
1052   finally
1053     SavedPattern.Free;
1054   end;
1055 end;
1056
1057 procedure TBottleChainScriptCondition.SetAll(const Value: boolean);
1058 begin
1059   FAll := Value;
1060 end;
1061
1062 procedure TBottleChainScriptCondition.SetPatterns(const Value: TStrings);
1063 begin
1064   FPatterns.Assign(Value);
1065 end;
1066
1067 function TBottleChainScriptCondition.StringExpression: String;
1068 var i: integer;
1069     patterns: String;
1070 begin
1071   patterns := '';
1072   for i := 0 to FPatterns.Count-1 do begin
1073     if i > 0 then
1074     begin
1075       if All then
1076         patterns := patterns + ' \82Æ '
1077       else
1078         patterns := patterns + ' \82© ';
1079     end;
1080     patterns := Format('%s\81u%s\81v', [patterns, FPatterns[i]]);
1081   end;
1082   Result := Format('\83X\83N\83\8a\83v\83g\95\8e\9a\97ñ\82É %s \82ª\8aÜ\82Ü\82ê\82Ä\82¢\82é\82Æ\82«', [patterns]);
1083 end;
1084
1085 class function TBottleChainScriptCondition.Title: String;
1086 begin
1087   Result := '\83X\83N\83\8a\83v\83g\95\8e\9a\97ñ\82É(\8ew\92è)\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82é\82Æ\82«';
1088 end;
1089
1090 { TBottleChainScriptNotCondition }
1091
1092 function TBottleChainScriptNotCondition.Check(
1093   Event: TBottleChainEvent): boolean;
1094 var i: integer;
1095     Dat: THeadValue;
1096 begin
1097   Result := false;
1098   if not (Event is TBottleChainBottleEvent) then Exit;
1099   Result := true;
1100   Dat := (Event as TBottleChainBottleEvent).Data;
1101   for i := 0 to FPatterns.Count-1 do
1102     if AnsiPos(FPatterns[i], Dat['Script']) > 0 then begin
1103       Result := false;
1104       Exit;
1105     end;
1106 end;
1107
1108 function TBottleChainScriptNotCondition.StringExpression: String;
1109 var i: integer;
1110     patterns: String;
1111 begin
1112   patterns := '';
1113   for i := 0 to FPatterns.Count-1 do begin
1114     if i > 0 then patterns := patterns + ' \82â ';
1115     patterns := Format('%s\81u%s\81v', [patterns, FPatterns[i]]);
1116   end;
1117   Result := Format('\83X\83N\83\8a\83v\83g\95\8e\9a\97ñ\82É %s \82ª\8aÜ\82Ü\82ê\82Ä\82¢\82È\82¢\82Æ\82«', [patterns]);
1118 end;
1119
1120 class function TBottleChainScriptNotCondition.Title: String;
1121 begin
1122   Result := '\83X\83N\83\8a\83v\83g\95\8e\9a\97ñ\82É(\8ew\92è)\82ª\8aÜ\82Ü\82ê\82Ä\82¢\82È\82¢\82Æ\82«';
1123 end;
1124
1125 { TBottleChainLogAction }
1126
1127 constructor TBottleChainLogAction.Create(AOwner: TComponent);
1128 begin
1129   inherited;
1130   FLogNames := TStringList.Create;
1131 end;
1132
1133 destructor TBottleChainLogAction.Destroy;
1134 begin
1135   FLogNames.Free;
1136   inherited;
1137 end;
1138
1139 function TBottleChainLogAction.Edit: boolean;
1140 var Consts: TStringList;
1141 begin
1142   Consts := TStringList.Create;
1143   try
1144     with Consts do begin
1145       Add('%channel%');
1146       Add('%ghost%');
1147       Add('%date%');
1148     end;
1149     Result := StrListEdit(FLogNames, '\83^\83u\96¼\82ð\8ew\92è(\83\81\83^\95\8e\9a\8eg\97p\89Â\94\)', false, Consts);
1150   finally
1151     Consts.Free;
1152   end;
1153 end;
1154
1155 procedure TBottleChainLogAction.SetLogNames(const Value: TStrings);
1156 begin
1157   FLogNames.Assign(Value);
1158 end;
1159
1160 function TBottleChainLogAction.StringExpression: String;
1161 var i: integer;
1162     logs: String;
1163 begin
1164   logs := '';
1165   for i := 0 to FLogNames.Count-1 do begin
1166     if i > 0 then logs := logs + ' \82Æ ';
1167     logs := Format('%s\81u%s\81v', [logs, FLogNames[i]]);
1168   end;
1169   Result := Format('%s\83^\83u\82É\83\8d\83O\82ð\8ec\82·', [logs]);
1170 end;
1171
1172 class function TBottleChainLogAction.Title: String;
1173 begin
1174   Result := '(\8ew\92è)\83^\83u\82É\83\8d\83O\82ð\8ec\82·';
1175 end;
1176
1177 { TBottleChainBottleTypeCondition }
1178
1179 function TBottleChainBottleTypeCondition.Check(
1180   Event: TBottleChainEvent): boolean;
1181 begin
1182   Result := false;
1183   if not (Event is TBottleChainBottleEvent) then Exit;
1184   Result := ((Event as TBottleChainBottleEvent).LogType = FLogType);
1185 end;
1186
1187 function TBottleChainBottleTypeCondition.Edit: boolean;
1188 var Index: integer;
1189 begin
1190   Index := Ord(FLogType);
1191   Result := MultipleChoiceEdit('\83^\83C\83v', ['\92Ê\8fí\83{\83g\83\8b', '\82¨\92m\82ç\82¹'], Index);
1192   if Result then FLogType := TLogType(Index);
1193 end;
1194
1195 procedure TBottleChainBottleTypeCondition.SetLogType(
1196   const Value: TLogType);
1197 begin
1198   FLogType := Value;
1199 end;
1200
1201 function TBottleChainBottleTypeCondition.StringExpression: String;
1202 const
1203   Mes: array[TLogType] of String = ('\92Ê\8fí\83{\83g\83\8b', '\82¨\92m\82ç\82¹');
1204 begin
1205   Result := Format('\83\81\83b\83Z\81[\83W\82Ì\83^\83C\83v\82ª%s\82Ì\82Æ\82«', [Mes[FLogType]]);
1206 end;
1207
1208 class function TBottleChainBottleTypeCondition.Title: String;
1209 begin
1210   Result := '\83\81\83b\83Z\81[\83W\82Ì\83^\83C\83v\82ª(\8ew\92è)\82Ì\82Æ\82«';
1211 end;
1212
1213 { TBottleChainNoDispatchAction }
1214
1215 class function TBottleChainNoDispatchAction.Title: String;
1216 begin
1217   Result := '\82±\82Ì\83\81\83b\83Z\81[\83W\82ðSSTP\83T\81[\83o\82É\93]\91\97\82µ\82È\82¢';
1218 end;
1219
1220 { TBottleChainTargetGhostNotExistCondition }
1221
1222 function TBottleChainTargetGhostNotExistCondition.Check(
1223   Event: TBottleChainEvent): boolean;
1224 var Dat: THeadValue;
1225 begin
1226   Result := false;
1227   if not (Event is TBottleChainBottleEvent) then Exit;
1228   Dat := (Event as TBottleChainBottleEvent).Data;
1229   SakuraSeeker.BeginDetect;
1230   Result := SakuraSeeker.ProcessByName[Dat['TargetGhost']] = nil;
1231 end;
1232
1233 class function TBottleChainTargetGhostNotExistCondition.Title: String;
1234 begin
1235   Result := '\8ew\92è\83S\81[\83X\83g\82ª\8bN\93®\82µ\82Ä\82¢\82È\82¢\82Æ\82«';
1236 end;
1237
1238 { TBottleChainOverrideGhostAction }
1239
1240 function TBottleChainOverrideGhostAction.Edit: boolean;
1241 var Ans: String;
1242 begin
1243   Ans := FTargetGhost;
1244   Result := InputQuery('\83S\81[\83X\83g\96¼\8ew\92è', '\91\97\90M\90æ\83S\81[\83X\83g', Ans);
1245   if Ans = '' then Result := false;
1246   if Result then FTargetGhost := Ans;
1247 end;
1248
1249 procedure TBottleChainOverrideGhostAction.SetTargetGhost(
1250   const Value: String);
1251 begin
1252   FTargetGhost := Value;
1253 end;
1254
1255 function TBottleChainOverrideGhostAction.StringExpression: String;
1256 begin
1257   Result := Format('\94z\91\97\90æ\83S\81[\83X\83g\82ð\81u%s\81v\82É\95Ï\8dX\82·\82é', [FTargetGhost]);
1258 end;
1259
1260 class function TBottleChainOverrideGhostAction.Title: String;
1261 begin
1262   Result := '\94z\91\97\90æ\83S\81[\83X\83g\82ð(\8ew\92è)\82É\95Ï\8dX\82·\82é';
1263 end;
1264
1265 { TBottleChainScriptRegExpCondition }
1266
1267 function TBottleChainScriptRegExpCondition.Check(
1268   Event: TBottleChainEvent): boolean;
1269 var Dat: THeadValue;
1270 begin
1271   Result := false;
1272   if not (Event is TBottleChainBottleEvent) then Exit;
1273   Dat := (Event as TBottleChainBottleEvent).Data;
1274   try
1275     if Dat['Script'] <> '' then
1276       Result := RegExp.Match(Pattern, Dat['Script'])
1277     else
1278       Result := false;
1279   except
1280     on E: EBRegExpError do begin
1281       ShowMessage('\90³\8bK\95\\8c»\83G\83\89\81['#13#10#13#10 + E.Message);
1282       Result := false;
1283     end;
1284   end;
1285 end;
1286
1287 constructor TBottleChainScriptRegExpCondition.Create(AOwner: TComponent);
1288 begin
1289   inherited;
1290   FPattern := 'm//k';
1291 end;
1292
1293 function TBottleChainScriptRegExpCondition.Edit: boolean;
1294 var Str: String;
1295 begin
1296   Str := Pattern;
1297   Result := InputQuery('\90³\8bK\95\\8c»', '\83p\83^\81[\83\93', Str);
1298   if Result then begin
1299     if Str = '' then Result := false else begin
1300       try
1301         RegExp.Match(Str, 'DUMMY');
1302         Pattern := Str;
1303       except
1304         on E: EBRegExpError do begin
1305           ShowMessage('\97L\8cø\82È\95\\8c»\82Å\82Í\82 \82è\82Ü\82¹\82ñ\81B');
1306           Result := false;
1307         end;
1308       end;
1309     end;
1310   end;
1311 end;
1312
1313 procedure TBottleChainScriptRegExpCondition.SetPattern(const Value: String);
1314 begin
1315   FPattern := Value;
1316 end;
1317
1318 function TBottleChainScriptRegExpCondition.StringExpression: String;
1319 begin
1320   Result := Format('\83X\83N\83\8a\83v\83g\82ª\90³\8bK\95\\8c»\81u%s\81v\82É\83}\83b\83`\82·\82é\82Æ\82«', [Pattern]);
1321 end;
1322
1323 class function TBottleChainScriptRegExpCondition.Title: String;
1324 begin
1325   Result := '\83X\83N\83\8a\83v\83g\82ª\90³\8bK\95\\8c»(\8ew\92è)\82É\83}\83b\83`\82·\82é\82Æ\82«';
1326 end;
1327
1328 { TBottleChainSkipRuleAction }
1329
1330 constructor TBottleChainSkipRuleAction.Create(AOwner: TComponent);
1331 begin
1332   inherited;
1333   FSkipCount := 1;
1334 end;
1335
1336 function TBottleChainSkipRuleAction.Edit: boolean;
1337 var Str: String;
1338 begin
1339   Str := IntToStr(FSkipCount);
1340   Result := InputQuery('\90\94\92l', '\83X\83L\83b\83v\82·\82é\83\8b\81[\83\8b\82Ì\90\94', Str);
1341   if Result then begin
1342     try
1343       FSkipCount := StrToInt(Str);
1344     except
1345       on EConvertError do begin
1346         Beep;
1347         Result := false;
1348       end;
1349     end;
1350   end;
1351 end;
1352
1353 procedure TBottleChainSkipRuleAction.SetSkipCount(const Value: integer);
1354 begin
1355   if FSkipCount >= 0 then FSkipCount := Value;
1356 end;
1357
1358 function TBottleChainSkipRuleAction.StringExpression: String;
1359 begin
1360   Result := Format('\82±\82ê\88È\8d~\82Ì%d\8cÂ\82Ì\83\8b\81[\83\8b\82Ì\8f\88\97\9d\82ð\83X\83L\83b\83v\82·\82é', [SkipCount]);
1361 end;
1362
1363 class function TBottleChainSkipRuleAction.Title: String;
1364 begin
1365   Result := '\82±\82ê\88È\8d~\82Ì(\8ew\92è)\8cÂ\82Ì\83\8b\81[\83\8b\82Ì\8f\88\97\9d\82ð\83X\83L\83b\83v\82·\82é';
1366 end;
1367
1368 { TBottleChainSaveLogAction }
1369
1370 function TBottleChainSaveLogAction.Edit: boolean;
1371 var LogFileName: String;
1372 begin
1373   LogFileName := FileName;
1374   Result := SaveFileEdit(LogFileName, Self.Filter,
1375     '\83t\83@\83C\83\8b\8ew\92è(\83\81\83^\95\8e\9a\97\98\97p\89Â)', []);
1376   if Result and (LogFileName <> '') then
1377     FileName := LogFileName;
1378   Result := true;
1379 end;
1380
1381 procedure TBottleChainSaveLogAction.SetFileName(const Value: String);
1382 begin
1383   FFileName := Value;
1384 end;
1385
1386 { TBottleChainSaveTextLogAction }
1387
1388 function TBottleChainSaveTextLogAction.Filter: String;
1389 begin
1390   Result := '\83e\83L\83X\83g\83t\83@\83C\83\8b(*.txt)|*.txt|\82·\82×\82Ä\82Ì\83t\83@\83C\83\8b(*.*)|*.*'
1391 end;
1392
1393 function TBottleChainSaveTextLogAction.StringExpression: String;
1394 begin
1395   Result := Format('\83e\83L\83X\83g\83t\83@\83C\83\8b"%s"\82É\8bL\98^\82·\82é', [FileName]);
1396 end;
1397
1398 class function TBottleChainSaveTextLogAction.Title: String;
1399 begin
1400   Result := '\83e\83L\83X\83g\83t\83@\83C\83\8b(\8ew\92è)\82É\8bL\98^\82·\82é'
1401 end;
1402
1403 { TBottleChainSaveXMLLogAction }
1404
1405 function TBottleChainSaveXMLLogAction.Filter: String;
1406 begin
1407   Result := 'XML\83t\83@\83C\83\8b(*.xml;*.xbl)|*.xml;*.xbl|\82·\82×\82Ä\82Ì\83t\83@\83C\83\8b(*.*)|*.*';
1408 end;
1409
1410 function TBottleChainSaveXMLLogAction.StringExpression: String;
1411 begin
1412   Result := Format('XML\83t\83@\83C\83\8b"%s"\82É\8bL\98^\82·\82é', [FileName]);
1413 end;
1414
1415 class function TBottleChainSaveXMLLogAction.Title: String;
1416 begin
1417   Result := 'XML\83t\83@\83C\83\8b(\8ew\92è)\82É\8bL\98^\82·\82é'
1418 end;
1419
1420 initialization
1421
1422 RegisterClasses([TBottleChainRule, TBottleChainRuleList]);
1423 for classregister_counter := 0 to High(BottleChainConditions) do
1424   Classes.RegisterClass(BottleChainConditions[classregister_counter]);
1425 for classregister_counter := 0 to High(BottleChainActions) do
1426   Classes.RegisterClass(BottleChainActions[classregister_counter]);
1427
1428 end.