OSDN Git Service

設定項目に\eを自動付加しない、編集スクリプトのバイト数で予測をスキップする機能を追加。
[winbottle/winbottle.git] / bottleclient / MainForm.pas
1 unit MainForm;
2
3 {
4 \83A\83v\83\8a\83P\81[\83V\83\87\83\93\82Ì\83\81\83C\83\93\83t\83H\81[\83\80\81B
5 \91\97\90M\81E\8eó\90M\81E\83{\83g\83\8b\94z\91\97\8aÖ\8cW\82Ì\82¢\82ë\82¢\82ë\82È\8f\88\97\9d\82ð\8ds\82¤\81B
6 }
7
8 interface
9
10 uses
11   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
12   Menus, StdCtrls, ComCtrls, BRegExp, BottleDef, BottleSstp, DirectSstp,
13 //  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdSLPP20,
14   SsParser, ImgList, AppEvnts, TaskTray, StdActns,
15   ActnList, MPlayer, MenuBar, ToolWin,
16   IniFiles, ExtCtrls, ShellAPI, Contnrs,
17   ConstEditor, Buttons, Clipbrd, HeadValue, Logs, MultipleChoiceEditor,
18 //  IdException, HttpThread, IdHTTP, LogDownload,
19   ScriptConsts, DateUtils, BottleChainRule, BottleChainEvent,
20   SakuraSeekerInstance, HEditor, HTSearch, heClasses, heFountain,
21   SakuraScriptFountain, SppList, SurfacePreview, XDOM_2_3_J3, SsPlayTime,
22   RegexUtils, StrReplace, StrReplaceDialog, ReplacePresetEditor;
23
24 type
25   TSurfacePreviewType = (spHint, spEditor);
26
27   TfrmSender = class(TForm)
28     MainMenu: TMainMenu;
29     mnFile: TMenuItem;
30     mnExit: TMenuItem;
31     mnRegister: TMenuItem;
32     mnStart: TMenuItem;
33     mnScript: TMenuItem;
34     StatusBar: TStatusBar;
35     mnHelp: TMenuItem;
36     mnAbout: TMenuItem;
37     mnEditConst: TMenuItem;
38     ActionList: TActionList;
39     mnPopUp: TPopupMenu;
40     mnPopPaste: TMenuItem;
41     mnPopCut: TMenuItem;
42     mnPopCopy: TMenuItem;
43     mnPopSelectAll: TMenuItem;
44     N6: TMenuItem;
45     mnPopConst: TMenuItem;
46     mnEdit: TMenuItem;
47     mnPaste: TMenuItem;
48     mnCopy: TMenuItem;
49     mnCut: TMenuItem;
50     mnSelectAll: TMenuItem;
51     TaskTray: TTaskTray;
52     ApplicationEvents: TApplicationEvents;
53     mnPopUpTaskTray: TPopupMenu;
54     mnTaskStart: TMenuItem;
55     mnTaskEnd: TMenuItem;
56     mnTaskRestore: TMenuItem;
57     mnTaskNewMessage: TMenuItem;
58     actStart: TAction;
59     actStop: TAction;
60     N8: TMenuItem;
61     mnTaskExit: TMenuItem;
62     actSend: TAction;
63     actConfirm: TAction;
64     actClear: TAction;
65     mnSend: TMenuItem;
66     mnConfirm: TMenuItem;
67     mnClear: TMenuItem;
68     imgIcon: TImageList;
69     mnPopupConst: TPopupMenu;
70     actEditConst: TAction;
71     mnView: TMenuItem;
72     mnShowToolBar: TMenuItem;
73     mnShowConstBar: TMenuItem;
74     ConstBarMenu: TMainMenu;
75     ToolBar: TToolBar;
76     tbtnClear: TToolButton;
77     tbtnConfirm: TToolButton;
78     tbtnSend: TToolButton;
79     tbtnSeparator: TToolButton;
80     tbtnStart: TToolButton;
81     tbtnSeparator2: TToolButton;
82     tbtnInsertConst: TToolButton;
83     ConstMenuBar: TMenuBar;
84     mnGoToHP: TMenuItem;
85     LabelTimer: TTimer;
86     mnCopyAll: TMenuItem;
87     actCopyAll: TAction;
88     actCopyAllNoReturn: TAction;
89     mnCopyAllNoReturn: TMenuItem;
90     mnPopCopyAll: TMenuItem;
91     mnPopCopyAllNoReturn: TMenuItem;
92     actSetting: TAction;
93     tbtnSetting: TToolButton;
94     mnStayOnTop: TMenuItem;
95     mnSetting: TMenuItem;
96     actExitClient: TAction;
97     SsParser: TSsParser;
98     tbtnEditConst: TToolButton;
99     actClearBottles: TAction;
100     mnClearBottles: TMenuItem;
101     MediaPlayer: TMediaPlayer;
102     mnGetNewId: TMenuItem;
103     actNextChannel: TAction;
104     actPrevChannel: TAction;
105     N2: TMenuItem;
106     mnNextChannel: TMenuItem;
107     mnPrevChannel: TMenuItem;
108     actShowLog: TAction;
109     N3: TMenuItem;
110     tbtnShowLog: TToolButton;
111     tbtnSleep: TToolButton;
112     actSleep: TAction;
113     N1: TMenuItem;
114     mnSleep: TMenuItem;
115     mnTaskSleep: TMenuItem;
116     pnlEditor: TPanel;
117     tabChannel: TTabControl;
118     pnlPanel: TPanel;
119     lblMessage: TLabel;
120     cbxTargetGhost: TComboBox;
121     actVoteMessage: TAction;
122     mnPopUpChannelTab: TPopupMenu;
123     mnLeaveThisChannel: TMenuItem;
124     N4: TMenuItem;
125     mnGotoVote: TMenuItem;
126     mnGoToHelp: TMenuItem;
127     btnSend: TButton;
128     btnConfirm: TButton;
129     btnClear: TButton;
130     mnExitAllChannels: TMenuItem;
131     actAgreeMessage: TAction;
132     btnIfGhost: TButton;
133     actPrevGhost: TAction;
134     actNextGhost: TAction;
135     mnPrevGhost: TMenuItem;
136     mnNextGhost: TMenuItem;
137     actResetGhost: TAction;
138     mnResetGhost: TMenuItem;
139     DirectSstp: TDirectSstp;
140     actDownloadLog: TAction;
141     actFMOExplorer: TAction;
142     tbtnFMOExplorer: TToolButton;
143     mnFMOExplorer: TMenuItem;
144     mnLine: TMenuItem;
145     actInsertCue: TAction;
146     SakuraScriptFountain: TSakuraScriptFountain;
147     memScript: TEditor;
148     actCopy: TAction;
149     actPaste: TAction;
150     actCut: TAction;
151     actSelectAll: TAction;
152     actRecallScriptBuffer: TAction;
153     N5: TMenuItem;
154     mnRecallScriptBuffer: TMenuItem;
155     tbtnEditorPreview: TToolButton;
156     actEditorPreview: TAction;
157     mnEditorPreview: TMenuItem;
158     actResetPlugins: TAction;
159     N7: TMenuItem;
160     mnResetPlugins: TMenuItem;
161     actReplace: TAction;
162     N10: TMenuItem;
163     mnReplace: TMenuItem;
164     actSendToEditor: TAction;
165     actSendToLogWindow: TAction;
166     mnSendLogWindow: TMenuItem;
167     actDeleteLogItem: TAction;
168     actAbout: TAction;
169     actEditCopy: TEditCopy;
170     tbtnSendToLogWindow: TToolButton;
171     SsPlayTime: TSsPlayTime;
172     actUndo: TAction;
173     actRedo: TAction;
174     mnUndo: TMenuItem;
175     mnRedo: TMenuItem;
176     N9: TMenuItem;
177     ScriptBackUp: TTimer;
178     mnPresetReplaceRoot: TMenuItem;
179     OpenDialog: TOpenDialog;
180     mnFileOpen: TMenuItem;
181     actFileOpen: TAction;
182     actFileSaveAs: TAction;
183     mnSaveAs: TMenuItem;
184     SaveDialog: TSaveDialog;
185     N11: TMenuItem;
186     mnSave: TMenuItem;
187     actFileSave: TAction;
188     procedure actConfirmExecute(Sender: TObject);
189     procedure FormCreate(Sender: TObject);
190     procedure FormDestroy(Sender: TObject);
191     procedure actSendExecute(Sender: TObject);
192 //    procedure HTTPSuccess(Sender: TObject);
193 //    procedure HTTPFailure(Sender: TObject);
194     procedure actStartClick(Sender: TObject);
195     procedure actStopExecute(Sender: TObject);
196     procedure FormShow(Sender: TObject);
197     procedure actAboutClick(Sender: TObject);
198     procedure actExitClientExecute(Sender: TObject);
199     procedure actClearExecute(Sender: TObject);
200     procedure memScriptChange(Sender: TObject);
201     procedure mnStayOnTopClick(Sender: TObject);
202     procedure actEditConstExecute(Sender: TObject);
203     procedure mnTaskBarClick(Sender: TObject);
204     procedure FormClose(Sender: TObject; var Action: TCloseAction);
205     procedure ApplicationEventsMinimize(Sender: TObject);
206     procedure ApplicationEventsRestore(Sender: TObject);
207     procedure mnTaskRestoreClick(Sender: TObject);
208     procedure TaskTrayDblClick(Seft: TObject; Button: TMouseButton);
209     procedure FormActivate(Sender: TObject);
210     procedure mnTaskNewMessageClick(Sender: TObject);
211     procedure ApplicationEventsHint(Sender: TObject);
212     procedure memScriptKeyDown(Sender: TObject; var Key: Word;
213       Shift: TShiftState);
214     procedure mnShowToolBarClick(Sender: TObject);
215     procedure mnShowConstBarClick(Sender: TObject);
216     procedure mnGoToHPClick(Sender: TObject);
217     procedure LabelTimerTimer(Sender: TObject);
218     procedure actCopyAllExecute(Sender: TObject);
219     procedure actCopyAllNoReturnExecute(Sender: TObject);
220 //    procedure Slpp20SlppEvent(Sender: TObject; EventType: TIdSlppEventType;
221 //      const Param: String);
222     procedure actSettingExecute(Sender: TObject);
223     procedure memScriptKeyPress(Sender: TObject; var Key: Char);
224 //    procedure Slpp20Disconnect(Sender: TObject);
225     procedure actClearBottlesExecute(Sender: TObject);
226     procedure SakuraSeekerDetectResultChanged(Sender: TObject);
227     procedure mnGetNewIdClick(Sender: TObject);
228     procedure tabChannelChange(Sender: TObject);
229     procedure actPrevChannelExecute(Sender: TObject);
230     procedure actNextChannelExecute(Sender: TObject);
231     procedure cbxTargetGhostDropDown(Sender: TObject);
232     procedure actShowLogExecute(Sender: TObject);
233     procedure actSleepExecute(Sender: TObject);
234     procedure actVoteMessageExecute(Sender: TObject);
235     procedure tabChannelContextPopup(Sender: TObject; MousePos: TPoint;
236       var Handled: Boolean);
237     procedure mnLeaveThisChannelClick(Sender: TObject);
238     procedure mnGotoVoteClick(Sender: TObject);
239     procedure tabChannelMouseMove(Sender: TObject; Shift: TShiftState; X,
240       Y: Integer);
241     procedure mnGoToHelpClick(Sender: TObject);
242     procedure tabChannelMouseDown(Sender: TObject; Button: TMouseButton;
243       Shift: TShiftState; X, Y: Integer);
244     procedure tabChannelDragOver(Sender, Source: TObject; X, Y: Integer;
245       State: TDragState; var Accept: Boolean);
246     procedure tabChannelDragDrop(Sender, Source: TObject; X, Y: Integer);
247     procedure tabChannelEndDrag(Sender, Target: TObject; X, Y: Integer);
248     procedure cbxTargetGhostDrawItem(Control: TWinControl; Index: Integer;
249       Rect: TRect; State: TOwnerDrawState);
250     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
251     procedure actAgreeMessageExecute(Sender: TObject);
252     procedure actPrevGhostExecute(Sender: TObject);
253     procedure actNextGhostExecute(Sender: TObject);
254     procedure actResetGhostExecute(Sender: TObject);
255 //    procedure timDisconnectCheckTimerTimer(Sender: TObject);
256     procedure actDownloadLogExecute(Sender: TObject);
257     procedure cbxTargetGhostChange(Sender: TObject);
258     procedure actFMOExplorerExecute(Sender: TObject);
259     procedure actInsertCueExecute(Sender: TObject);
260     procedure FormResize(Sender: TObject);
261     procedure actCopyExecute(Sender: TObject);
262     procedure actPasteExecute(Sender: TObject);
263     procedure actCutExecute(Sender: TObject);
264     procedure actSelectAllExecute(Sender: TObject);
265     procedure memScriptMouseMove(Sender: TObject; Shift: TShiftState; X,
266       Y: Integer);
267     procedure actRecallScriptBufferExecute(Sender: TObject);
268     procedure actEditorPreviewExecute(Sender: TObject);
269     procedure actResetPluginsExecute(Sender: TObject);
270 //    procedure IdSLPP20Connect(Sender: TObject);
271     procedure actReplaceExecute(Sender: TObject);
272     procedure actSendToEditorExecute(Sender: TObject);
273     procedure actSendToLogWindowExecute(Sender: TObject);
274     procedure memScriptDragOver(Sender, Source: TObject; X, Y: Integer;
275       State: TDragState; var Accept: Boolean);
276     procedure memScriptDragDrop(Sender, Source: TObject; X, Y: Integer);
277     procedure actDeleteLogItemExecute(Sender: TObject);
278     procedure memScriptSelectionChange(Sender: TObject; Selected: Boolean);
279     procedure actUndoExecute(Sender: TObject);
280     procedure actRedoExecute(Sender: TObject);
281 //    procedure IdSLPP20ConnectFailed(Sender: TObject);
282     procedure ScriptBackUpTimer(Sender: TObject);
283     //DispatchBottle()\82Ö\83o\83C\83p\83X
284     procedure BottleCnv(Log: TLogItem);
285     procedure actFileOpenExecute(Sender: TObject);
286     procedure actFileSaveAsExecute(Sender: TObject);
287     procedure actFileSaveExecute(Sender: TObject);
288   private
289     FSleeping: boolean;  // \94z\91\97\83X\83\8a\81[\83v\92\86\82©\82Ç\82¤\82©
290     FStatusText: String;
291 //    FConnecting: boolean;
292 //    FAdded: boolean;
293     FBooted: boolean; //\8f\89\89ñ\8bN\93®\92Ê\90M\97p
294     FEndSession: Boolean; // Windows\8fI\97¹\82ð\8c\9f\92m\82µ\82Ätrue\82É\82È\82é
295     FOriginalCaption: String;
296 //    FAutoAddAfterGetChannel: boolean; //\83`\83\83\83\93\83l\83\8b\8eæ\93¾\8cã\82É\83_\83C\83A\83\8d\83O\82È\82µ\82É
297                                       //\83`\83\83\83\93\83l\83\8b\82É\8eQ\89Á\82·\82é\82©\82Ç\82¤\82©
298     FConstDir: String;
299     FSppDir: String;
300     //
301 //    FNowChannel: String; //\8c»\8dÝ\91I\91ð\82³\82ê\82Ä\82¢\82é\83`\83\83\83\93\83l\83\8b
302 //    JoinChannelsBackup: TStringList; //\88ê\8e\9e\8eg\97p
303     //
304 //    FScriptModified: boolean; // \83X\83N\83\8a\83v\83g\82ª\95Ï\8dX\82³\82ê\82Ä\82¢\82é\82©\82Ç\82¤\82©\81B
305 //                              // \83\8d\81[\83J\83\8b\8am\94F\8b­\90§\97p\83t\83\89\83O\81BTRichEdit.Modified\82Í
306 //                              //\95Ê\82Ì\97p\93r\82Å\8eg\82Á\82Ä\82¢\82é\82Ì\82Å\8eg\82¦\82È\82¢
307     //
308     FScriptBackModified: boolean; //\83X\83N\83\8a\83v\83g\8e©\93®\95Û\91\83t\83\89\83O
309     FFileModified: boolean;       //\83t\83@\83C\83\8b\93à\97e\82ª\95Ï\8dX\82³\82ê\82Ä\82¢\82é\82©\81B
310     FFileName: string;            //\90V\8bK\82©\8aù\91\83t\83@\83C\83\8b\82Ì\94»\92f\81A\82Ü\82½\82Í\8aù\91\83t\83@\83C\83\8b\82Ì\8fê\8f\8a
311     //
312 //    FDragTabIndex: integer; //\83^\83u\83h\83\89\83b\83O\83h\83\8d\83b\83v\8aÖ\98A
313 //    FDragTabDest: integer;  //\83h\83\8d\83b\83v\82·\82é\88Ê\92u(\82·\82®\89E\82É\82­\82é\83^\83u\82Ì\83C\83\93\83f\83b\83N\83X)
314     //
315     FBottleSstp: TBottleSstp; // \8dÄ\91\97\83v\83\8d\83O\83\89\83\80
316     //
317 //    FHttp: THTTPDownloadThread; //HTTP\83_\83E\83\93\83\8d\81[\83h\83X\83\8c\83b\83h(\83C\83\93\83X\83^\83\93\83X\82Í1\8cÂ\82Ì\82Ý)
318 //    FBeginConnectFailCount: integer; //\89½\93x\82à\90Ú\91±\8e¸\94s\82µ\82½\82ç\83\8a\83g\83\89\83C\92\86\8e~
319     //
320     FVisiblePreviewGhost: String;
321     FVisiblePreviewSurface: integer; //\83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[\82Å\8c©\82¦\82Ä\82¢\82é\82à\82Ì
322     FVisibleMenuItem: TMenuItem; //\83N\83\8a\83b\83N\82³\82ê\82½\83\81\83j\83\85\81[\83A\83C\83e\83\80\81B
323                                  //\83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[\82ª\83\81\83j\83\85\81[\82Ì\89º\82É
324                                  //\89B\82ê\82È\82¢\82æ\82¤\82É\95\\8e¦\82³\82ê\82Ä\82¢\82é\82à\82Ì\82ð\8bL\89¯\82µ\82Ä\82¨\82­
325     //
326     FTargetGhostExpand: boolean; //\83S\81[\83X\83g\91I\91ð\83{\83b\83N\83X\82ª\81A
327                                  //\88ê\8e\9e\93I\82É\91S\95\94\95\\8e¦\82³\82ê\82Ä\82¢\82é\82©\82Ç\82¤\82©\82Ì\83t\83\89\83O
328     //
329     FScriptBuffer: TObjectList;  //\83X\83N\83\8a\83v\83g\83N\83\8a\83A\83o\83b\83t\83@
330     //
331     FWM_TaskBarCreated: WORD; // \83^\83X\83N\83o\81[\93o\98^\97p\83E\83B\83\93\83h\83E\83\81\83b\83Z\81[\83WID
332     //
333 //    procedure SetStatusText(const Value: String);
334     procedure SetSleeping(const Value: boolean);
335     procedure YenETrans;
336 //    procedure SetConnecting(const Value: boolean);
337 //    procedure SetAdded(const Value: boolean);
338     procedure mnConstClick(Sender: TObject);
339     procedure mnConstGroupClick(Sender: TObject);
340     procedure mnPresetReplaceClick(Sender: TObject);
341 //    property Added: boolean read FAdded write SetAdded;
342     property Sleeping: boolean read FSleeping write SetSleeping;
343 //    property StatusText: String read FStatusText write SetStatusText;
344     function GetScriptText: String;
345     procedure ChangeTaskIcon;
346     procedure ShowHintLabel(const Mes: String; Col: TColor = clBlue);
347     procedure UpdateLayout;
348 //    procedure DispatchBottle(EventType: TIdSlppEventType; Dat: THeadValue);
349     procedure DispatchBottle(Dat: THeadValue; LogTime: TDateTime;
350       Vote, Agree: integer);
351     //\83`\83\83\83\93\83l\83\8b\8aÖ\8cW
352 //    procedure UpdateChannelInfo(Dat: THeadValue);
353 //    procedure UpdateJoinChannelList(Dat: THeadValue);
354     procedure UpdateJoinChannelList;
355     procedure UpdateChannelList;
356 //    procedure NoLuidError;
357     procedure UpdateIfGhostBox;
358     function BuildMenuConditionCheck(const IfGhost, Ghost: String): boolean;
359     procedure BuildMenu(Root: TMenuItem; Simple: boolean);
360     procedure BuildReplaceMenu(Root: TMenuItem);
361     procedure PlaySound(const FileName: String);
362     //TBottleSstp\8aÖ\8cW\83C\83x\83\93\83g\83n\83\93\83h\83\89
363     procedure BottleSstpResendCountChange(Sender: TObject);
364     procedure BottleSstpResendTrying(Sender: TObject; MID: String);
365     procedure BottleSstpResendEnd(Sender: TObject; MID: String);
366     function IsSurfaceTag(const Script: String; var ID: integer): boolean;
367     procedure DoSurfacePreview(Surface: integer; const Kind:
368       TSurfacePreviewType);
369     function GetSurfacePreviewPositionHint(w, h: integer): TPoint;
370     function GetSurfacePreviewPositionScriptPoint(w, h: integer): TPoint;
371     procedure EditorPreview;
372     // \83^\83O\82Ì\95\8e\9a\97ñ\82ð\95Ï\8a·\82·\82é
373     function TagReplace(Script: String;
374       Before, After: array of String): String; overload;
375     function TagReplace(Script: String;
376       Before, After: TStrings): String; overload;
377     // \83T\81[\83t\83B\83X\82ð\95Ï\8a·\82·\82é
378     function ReplaceSurface(Script: String; Params: TCollection): String;
379     procedure ClearEditor;
380     procedure CopyFromLogToEditor(Log: TLogItem);
381     //
382     procedure AppendTextLog(const FileName, Line: String);
383     procedure AppendXMLLog(const FileName: String; Args: THeadValue);
384     //\8e©\93®\95Û\91\90Ý\92è
385     procedure SetScriptAutoBackUp;
386     //\92P\91Ì\83t\83@\83C\83\8b\93ü\8fo\97Í\8aÖ\8cW
387     procedure PerformFileOpen(AFileName: string);
388     procedure SetFileName(const FileName: String; const Value: boolean);
389     function CheckFileSave(Sender: TObject): integer;
390     function FileSave(Sender: TObject): integer;
391     function FileSaveAs(Sender: TObject): integer;
392     procedure EditerStatusChange;
393     procedure SetFileModified(const Value: boolean);
394     //\83u\83\89\83E\83U\94»\92f\82ÆURL\88ø\93n\82µ
395     procedure OpenBrowser(const Url: string);
396 //    procedure CopyDataMessage(var WMCopyData: TWMCopyData); message WM_COPYDATA;
397
398   protected
399     procedure WndProc(var Message: TMessage); override;
400     procedure WMQueryEndSession(var msg: TWMQueryEndSession);
401       message WM_QUERYENDSESSION;
402   public
403     function DoTrans(var Script: String;
404       Options: TScriptTransOptions): String; overload;
405     function DoTrans(var Script: String;
406       Options: TScriptTransOptions; out FoundURL: boolean): String; overload;
407     function ScriptTransForSSTP(const Script: String;
408       out Error: String): String; overload;
409 //    procedure BeginConnect;
410 //    procedure RetryBeginConnect;
411 //    procedure EndConnect;
412     procedure ConstructMenu(Simple: boolean);
413 //    property Connecting: boolean read FConnecting write SetConnecting;
414     property BottleSstp: TBottleSstp read FBottleSstp;
415     function GhostNameToSetName(const Ghost: String): String;
416 //    procedure PostCommand(const Command: array of String); overload;
417 //    procedure PostCommand(Command: TStrings); overload;
418 //    procedure PostSetChannel(Channels: TStrings);
419     procedure SaveChainRuleList;
420   end;
421
422
423 var
424   frmSender: TfrmSender;
425
426 const
427   PanelConnecting = 0;  //\81u\90Ú\91±\92\86\81v\95\\8e¦\97p
428   PanelBytes      = 1;  //\81\9b\81\9b\83o\83C\83g
429   PanelCount      = 2;  //Local Proxy\81A\8c»\8dÝ\81\9b\8c\8f\91Ò\82¿
430   PanelMembers    = 3;  //\81\9b\81\9b\90l
431   PanelStatus     = 4;  //SSTP Bottle\83T\81[\83o\82É\93o\98^\82³\82ê\82Ä\82¢\82Ü\82·\81c\82È\82Ç
432
433   IconConnected    = 17;
434   IconDisconnected = 47;  //\8b\8c18  \8e¸\94s\8fó\91Ô\82ð\8fí\82É\8eg\97p
435   IconSleep        = 19;
436   IconSleepDisconnected = 47; //\8b\8c20
437
438   WarningColor = clRed;
439
440   SendButtonLongHint = 'Bottle\82Ì\91\97\90M';
441   NewFileTitle = '\96¼\8fÌ\96¢\92è';
442
443 function Token(const Str: String; const Delimiter: char;
444   const Index: integer): String;
445
446 function StringReplaceEx(const Before: String; List: THeadValue): String;
447
448 implementation
449
450 uses SettingForm, LogForm,
451   MessageBox, FMOExplorer, EditorTalkShow;
452 //SendConfirm, ChannelListForm, 
453
454 {$R *.DFM}
455
456 // \92P\8f\83\82É\83o\83C\83g\92P\88Ê\82Å\95\8e\9a\97ñ\82ð\8c©\82Ä\82¢\82«\95ª\89ð\82·\82é\83\86\81[\83e\83B\83\8a\83e\83B\8aÖ\90\94
457 function Token(const Str: String; const Delimiter: char;
458   const Index: integer): String;
459 var i, c, len: integer;
460 begin
461   i := 1;
462   c := 0;
463   len := length(Str);
464   Result := '';
465   while i <= len do begin
466     if (Str[i] = Delimiter) and (StrByteType(PChar(Str), i) <> mbTrailByte) then begin
467       Inc(c);
468       if c > Index then Break;
469     end else if c = Index then Result := Result + Str[i];
470     Inc(i);
471   end;
472 end;
473
474 // \95\8e\9a\97ñ\82ð\92u\82«\8a·\82¦\82é\83\86\81[\83e\83B\83\8a\83e\83B\8aÖ\90\94
475 function StringReplaceEx(const Before: String; List: THeadValue): String;
476 var
477   i, MinPos, MinKey, p: integer;
478   Work: String;
479 begin
480   Work := Before;
481   Result := '';
482   MinKey := -1;
483   while Work <> '' do
484   begin
485     MinPos := -1;
486     for i := 0 to List.Count-1 do
487     begin
488       p := Pos(List.KeyAt[i], Work);
489       if (p > 0) and ((p < MinPos) or (MinPos < 0)) then
490       begin
491         MinPos := p;
492         MinKey := i;
493       end;
494     end;
495     if MinPos < 0 then
496     begin
497       Result := Result + Work;
498       Break;
499     end else
500     begin
501       Result := Result + Copy(Work, 1, MinPos-1) + List.ValueAt[MinKey];
502       Delete(Work, 1, (MinPos - 1) + Length(List.KeyAt[MinKey]));
503     end;
504   end;
505 end;
506
507 {TfrmSender}
508
509 procedure TfrmSender.actConfirmExecute(Sender: TObject);
510 var
511   AScript, Err, AGhost: String;
512   Item: TLogItem;
513   Choice: integer;
514 begin
515   // Partial Confirmation
516   if memScript.SelText <> '' then
517   begin
518     Choice := 0;
519     if not Pref.AutoPartialConfirm then
520       if not MultipleChoiceEdit('\8am\94F', ['\91I\91ð\95\94\95ª\82Ì\82Ý', '\83X\83N\83\8a\83v\83g\91S\91Ì'], Choice) then
521         Exit;
522     if Choice = 0 then
523     begin
524       AScript := memScript.SelText;
525       AScript := StringReplace(Pref.PartialConfirmFormat, '|', AScript, []);
526     end else
527       AScript := GetScriptText;
528   end else
529     AScript := GetScriptText;
530   AScript := StringReplace(AScript, #13#10, '', [rfReplaceAll]);
531
532   if Length(AScript) = 0 then Exit;
533   YenETrans;
534   AScript := ScriptTransForSSTP(AScript, Err);
535   if Err <> '' then
536   begin
537     ShowMessage(Err);
538     Exit;
539   end;
540
541   if cbxTargetGhost.ItemIndex > 0 then
542     AGhost := cbxTargetGhost.Text
543\95K\82¸\8ew\92è\82³\82ê\82é\82Í\82¸
544   else if FNowChannel <> '' then
545     AGhost := ChannelList.Channel[FNowChannel].Ghost
546 }
547   else
548     AGhost := '';
549
550   if Pref.IgnoreTimeCritical then
551     AScript := TagReplace(AScript, ['\t'], ['']);
552
553   Item := TLogItem.Create;
554   try
555     with Item do
556     begin
557       LogType := ltBottle;
558       Script := AScript;
559       Channel := '\81y\8am\94F\81z';
560       Ghost := AGhost;
561     end;
562     BottleSstp.Unshift(Item);
563   except
564     Item.Free;
565   end;
566
567 //  FScriptModified := false;
568 end;
569
570 procedure TfrmSender.FormCreate(Sender: TObject);
571 var Str: TStringList;
572 begin
573   FScriptBuffer := TObjectList.Create(true);
574
575   SakuraSeeker.OnDetectResultChanged := SakuraSeekerDetectResultChanged;
576   FConstDir := ExtractFileDir(Application.ExeName)+'\consts';
577   ScriptConstList.LoadFromDir(FConstDir);
578   FSppDir := ExtractFileDir(Application.ExeName)+'\spp';
579   Spps.LoadFromDirectory(FSppDir);
580   ConstructMenu(false);
581   BuildReplaceMenu(mnPresetReplaceRoot);
582
583   Str := TStringList.Create;
584   try
585     try
586       Str.LoadFromFile(ExtractFilePath(Application.ExeName)+'rule.txt');
587       BottleChainRuleList := StringToComponent(Str.Text) as TBottleChainRuleList;
588     except
589       try
590         Str.LoadFromFile(ExtractFilePath(Application.ExeName)+'defrule.txt');
591         BottleChainRuleList := StringToComponent(Str.Text) as TBottleChainRuleList;
592       except
593         ShowMessage('defrule.txt\93Ç\82Ý\8d\9e\82Ý\92\86\82É\92v\96½\93I\83G\83\89\81[\82ª\94­\90\82µ\82Ü\82µ\82½\81Bdefrule.txt\82ð\8dÄ\83C\83\93\83X\83g\81[\83\8b\82µ\82Ä\82­\82¾\82³\82¢\81B');
594         Application.Terminate;
595         Application.ProcessMessages;
596         Exit;
597       end;
598     end;
599   finally
600     Str.Free;
601   end;
602
603   FOriginalCaption := Self.Caption;
604
605   UpdateLayout;
606   mnShowToolBar.Checked := Pref.ShowToolBar;
607   mnShowConstBar.Checked := Pref.ShowConstBar;
608   if Pref.StayOnTop then begin
609     FormStyle := fsStayOnTop;
610     mnStayOnTop.Checked := true;
611   end else begin
612     FormStyle := fsNormal;
613     mnStayOnTop.Checked := false;
614   end;
615
616   // URL\83W\83\83\83\93\83v\90æ\82ð\83q\83\93\83g\95\8e\9a\97ñ\82Æ\82µ\82Ä\90Ý\92è
617   mnGoToHP.Hint := Pref.HomePage;
618   mnGotoVote.Hint := Pref.VotePage;
619   mnGotoHelp.Hint := Pref.HelpPage;
620
621   mnGetNewId.Enabled := (Pref.LUID = '');
622
623   // \82³\82­\82ç\83X\83N\83\8a\83v\83g\89ð\90Í\83p\83^\81[\83\93\82ð\93Ç\82Ý\8d\9e\82Ý
624   try
625     SsParser.TagPattern.LoadFromFile(ExtractFilePath(Application.Exename) + 'tagpat.txt');
626     SsParser.MetaPattern.LoadFromFile(ExtractFilePath(Application.ExeName) + 'metapat.txt');
627   except
628     ShowMessage('tagpat.txt, metapat.txt\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ\81B');
629     Application.Terminate;
630   end;
631
632   // \8dÄ\90\8e\9e\8aÔ\90\84\92è\83R\83\93\83|\81[\83l\83\93\83g\82É\83p\83\89\83\81\81[\83^\82ð\8ew\92è
633   SsPlayTime.PlayTimeParams := Pref.PlayTimeParams;
634
635   // \83\81\83C\83\93\83E\83B\83\93\83h\83E\82Ì\88Ê\92u\82Æ\83T\83C\83Y\82ð\95\9c\8bA
636   with Pref.SenderWindowPosition do begin
637     Self.Left   := Left;
638     Self.Top    := Top;
639     Self.Width  := Right - Left + 1;
640     Self.Height := Bottom - Top + 1;
641   end;
642
643   // \83^\83X\83N\83o\81[\82Ì\8dÄ\8bN\93®(Explorer\82ª\97\8e\82¿\82½\82Æ\82«)\82ð\8c\9f\8fo\82·\82é
644   FWM_TaskBarCreated := RegisterWindowMessage('TaskBarCreated');
645
646   // \83X\83N\83\8a\83v\83g\95\8e\9a\97ñ\82Ì\8f\89\8aú\89»
647   actClearExecute(Sender);
648   // \83^\83X\83N\83g\83\8c\83C\82É\83A\83C\83R\83\93\82ð\92Ç\89Á
649   ChangeTaskIcon;
650   // \83`\83\83\83\93\83l\83\8b\8eQ\89Á\8aÖ\8cW\82Ì\83^\83u\82Ì\8f\88\97\9d\82È\82Ç(\83`\83\83\83\93\83l\83\8b\95s\8eQ\89Á\82Å\8f\89\8aú\89»)
651 //  UpdateJoinChannelList(nil);
652   //\8f\89\8aú\89»
653   UpdateJoinChannelList;
654
655   // SSTP\8dÄ\91\97\83I\83u\83W\83F\83N\83g
656   FBottleSstp := TBottleSstp.Create(false);
657   with FBottleSstp do begin
658     OnResendCountChange := BottleSstpResendCountChange;
659     OnResendTrying := BottleSstpResendTrying;
660     OnResendEnd := BottleSstpResendEnd;
661   end;
662 end;
663
664 procedure TfrmSender.FormDestroy(Sender: TObject);
665 begin
666   if FScriptBuffer <> nil then
667     FScriptBuffer.Free;
668
669   if FBottleSstp <> nil then begin
670     FBottleSstp.Terminate;
671     FBottleSstp.Free;
672   end;
673
674   with Pref.SenderWindowPosition do begin
675     Left   := Self.Left;
676     Top    := Self.Top;
677     Right  := Self.Left + Self.Width - 1;
678     Bottom := Self.Top + Self.Height - 1;
679   end;
680
681 //  if JoinChannelsBackup <> nil then JoinChannelsBackup.Free;
682
683   ScriptConstList.Save;
684
685   SaveChainRuleList;
686   BottleChainRuleList.Free;
687
688 end;
689
690
691 {
692 procedure TfrmSender.SetConnecting(const Value: boolean);
693 begin
694   FConnecting := Value;
695   if Value then begin
696     StatusBar.Panels[PanelConnecting].Text := '\92Ê\90M\92\86';
697     actStart.Enabled := false;
698     actStop.Enabled := false;
699     actSend.Enabled := false;
700     actVoteMessage.Enabled := false;
701     actAgreeMessage.Enabled := false;
702     mnGetNewId.Enabled := false;
703     Screen.Cursor := crAppStart;
704   end else begin
705     StatusBar.Panels[PanelConnecting].Text := '';
706     actStart.Enabled := true;
707     actStop.Enabled := true;
708     actSend.Enabled := true;
709     frmLog.lvwLogChange(Self, nil, ctState);
710     mnGetNewId.Enabled := Pref.LUID = '';
711     Screen.Cursor := crDefault;
712   end;
713 end;
714 }
715
716 // \83\81\83b\83Z\81[\83W\91\97\90M
717 procedure TfrmSender.actSendExecute(Sender: TObject);
718 var
719   Talk, AGhost: String;
720 //  Command: TStringList;
721   Err: String;
722 //  F: TextFile;
723   Item: TLogItem;
724 begin
725   //\83t\83\89\83O
726   if not Pref.SendAction then
727   begin
728     ShowHintLabel('\93®\8dì\82ª\96¢\90Ý\92è\82Å\82·');
729     Exit;
730   end;
731   if Length(GetScriptText) = 0 then
732   begin
733     ShowMessage('\83X\83N\83\8a\83v\83g\82ª\8bó\82Å\82·\81B');
734     Exit;
735   end;
736
737 {
738   if Pref.LUID = '' then begin
739     NoLuidError;
740     Exit;
741   end;
742   if tabChannel.TabIndex < 0 then begin
743     ShowMessage('\83`\83\83\83\93\83l\83\8b\82É\8eQ\89Á\82µ\82Ä\82¢\82Ü\82¹\82ñ\81B'#13#10+
744       '\83\81\83j\83\85\81[\82©\82ç\81u\83`\83\83\83\93\83l\83\8b\8eQ\89Á\81v\82ð\8ds\82Á\82Ä\82­\82¾\82³\82¢\81B');
745     Exit;
746   end;
747   if ChannelList.Channel[FNowChannel].NoPost then begin
748     Beep;
749     ShowMessage(FNowChannel + ' \82Í\8eó\90M\90ê\97p\82Å\82·');
750     Exit;
751   end;
752 }
753
754   YenETrans;
755   Talk := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]);
756   Err := DoTrans(Talk, [toWarnMessySurface, toWarnCheck]);
757   if Err <> '' then
758   begin
759     MessageDlg(Err, mtWarning, [mbOk], 0);
760     Exit;
761   end;
762
763 {
764   if Pref.NeedConfirmBeforeSend and FScriptModified then
765   begin
766     MessageDlg('\91\97\90M\91O\82É\83\8d\81[\83J\83\8b\8am\94F\82µ\82Ä\82­\82¾\82³\82¢\81B', mtError, [mbOk], 0);
767     Exit;
768   end;
769
770   if not Pref.NoConfirm then begin
771     if not SendConfirmDialog(FNowChannel, cbxTargetGhost.Text) then Exit;
772   end;
773 }
774
775   AGhost := '';
776   if cbxTargetGhost.ItemIndex > 0 then AGhost := cbxTargetGhost.Text;
777   //\92P\91Ì\83A\83N\83V\83\87\83\93
778   Item := TLogItem.Create;
779   try
780     with Item do
781     begin
782       MID := '';
783       Channel := 'local';
784       LogTime := now();
785       Script := Talk;
786       Ghost := AGhost;
787       Votes := 0;
788       Agrees := 0;
789     end;
790     BottleCnv(Item);
791   except
792     Item.Free;
793   end;
794   ShowHintLabel('[local]\82Ö\91\97\90M\82µ\82Ü\82µ\82½');
795
796 {
797   Command := TStringList.Create;
798   try
799     with Command do begin
800       Add('Command: sendBroadcast');
801       Add('Channel: ' + FNowChannel);
802       Add('LUID: ' + Pref.LUID);
803       Add('Agent: ' + VersionString);
804       if Ghost <> '' then Add('Ghost: ' + Ghost);
805       Add('Talk: ' + Talk);
806     end;
807     PostCommand(Command);
808   finally
809     Command.Free;
810   end;
811
812   //\91\97\90M\83\8d\83O\95Û\91
813   AssignFile(F, ExtractFilePath(Application.ExeName) + SentLogFile);
814   if FileExists(ExtractFilePath(Application.ExeName) + SentLogFile) then
815     Append(F)
816   else
817     Rewrite(F);
818   WriteLn(F, Format('%s,%s,%s,%s', [FNowChannel, Ghost, FormatDateTime('yy/mm/dd hh:nn:ss', Now), Talk]));
819   Flush(F);
820   CloseFile(F);
821 }
822 end;
823
824 {
825 procedure TfrmSender.BeginConnect;
826 begin
827   if Pref.LUID = '' then begin
828     NoLuidError;
829     Exit;
830   end;
831   IdSlpp20.LUID := Pref.LUID;
832   self.Cursor := crHourGlass;
833   if IdSlpp20.Connected then IdSlpp20.Disconnect;
834   if Pref.UseHttpProxy then begin
835     IdSlpp20.Host := Pref.ProxyAddress;
836     IdSlpp20.Port := Pref.ProxyPort;
837     IdSlpp20.ProxyMode := true;
838   end else begin
839     IdSlpp20.Host := Pref.BottleServer;
840     IdSlpp20.Port := Pref.BottleServerPort;
841     IdSlpp20.ProxyMode := false;
842   end;
843   IdSlpp20.ConnectServer;
844   self.Cursor := crDefault;
845 end;
846 }
847
848 {
849 procedure TfrmSender.EndConnect;
850 begin
851   IdSlpp20.OnDisconnect := nil;
852   IdSlpp20.Disconnect;
853 end;
854 }
855
856 {
857 procedure TfrmSender.SetAdded(const Value: boolean);
858 begin
859   if FAdded = Value then Exit;
860   FAdded := Value;
861   if Value then begin
862     StatusText := 'SSTP Bottle \83T\81[\83o\82É\90Ú\91±\82³\82ê\82Ä\82¢\82Ü\82·';
863     ChangeTaskIcon;
864   end else begin
865     StatusText := '\83T\81[\83o\82Æ\82Ì\90Ú\91±\82ª\90Ø\82ê\82Ä\82¢\82Ü\82·!';
866     ChangeTaskIcon;
867     ShowHintLabel('SSTP Bottle\83T\81[\83o\82©\82ç\90Ø\92f\82³\82ê\82Ü\82µ\82½!', WarningColor);
868   end;
869 end;
870 }
871
872 {
873 procedure TfrmSender.HTTPSuccess(Sender: TObject);
874 var Str, ResStr, Command: String;
875     HeadValue: THeadValue;
876     i: integer;
877     SetChannel: TStringList;
878 begin
879   Connecting := false;
880   Str := (Sender as THttpDownloadThread).RecvString;
881   HeadValue := nil;
882   try
883     try
884       HeadValue := THeadValue.Create(Str);
885     except
886       ShowMessage('SSTP Bottle\83T\81[\83o\82ª\89ð\90Í\82Å\82«\82È\82¢\83G\83\89\81[\82ð\95Ô\82µ\82Ü\82µ\82½\81B');
887       Exit;
888     end;
889     Command := HeadValue['Command'];
890     ResStr  := HeadValue['Result'];
891     if ResStr = 'Err' then begin
892       if HeadValue['ExtraMessage'] <> '' then begin
893         Beep;
894         ShowMessage('SSTP Bottle\83T\81[\83o\82ª\8e\9f\82Ì\83G\83\89\81[\82ð\95Ô\82µ\82Ü\82µ\82½:'#13#10 +
895                      HeadValue['ExtraMessage']);
896       end else begin
897         Beep;
898         ShowMessage('SSTP Bottle\83T\81[\83o\82ª\89½\82ç\82©\82Ì\83G\83\89\81[\82ð\95Ô\82µ\82Ü\82µ\82½\81B');
899       end;
900     end;
901     if (Command = 'sendBroadcast') and (ResStr = 'OK') then begin
902       ShowHintLabel(HeadValue['Channel'] + ' \82Ì ' + HeadValue['SentNum'] +
903                     '\90l\82É\91\97\90M\82µ\82Ü\82µ\82½');
904       //\83S\81[\83X\83g\82ð\83f\83t\83H\83\8b\83g\82É\96ß\82·
905       if Pref.ResetIfGhostAfterSend then begin
906         actResetGhostExecute(Self);
907       end;
908       //\83X\83N\83\8a\83v\83g\82ð\83N\83\8a\83A
909       if Pref.ClearAfterSend then begin
910         actClear.Execute;
911       end;
912     end else if (Command = 'sendBroadcast') and (ResStr <> 'OK') then begin
913       ShowHintLabel('\83\81\83b\83Z\81[\83W\82ð\91\97\90M\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½', WarningColor);
914     end;
915     if (Command = 'getNewId') then begin
916       if ResStr = 'OK' then begin
917         Pref.LUID := HeadValue['NewID'];
918         ShowHintLabel('LUID\8eæ\93¾\8a®\97¹\81B');
919         frmMessageBox.ShowMessage('\8f\89\89ñ\8bN\93®\82Ì\82½\82ß\81A' +
920           'SSTP Bottle\83T\81[\83o\90Ú\91±\97p\82ÌID(LUID)\82ð\90V\8bK\8eæ\93¾\82µ\82Ü\82µ\82½\81B'#13#10 +
921           'LUID: ' + Pref.LUID +  #13#10 +
922           '\90Ý\92è\83t\83@\83C\83\8b\82ð\8dí\8f\9c\82·\82é\82±\82Æ\82Å\81ALUID\82Í\8e©\97R\82É\8eæ\93¾\82Å\82«\82Ü\82·\82ª\81A' +
923           'LUID\82Ì\8eg\97p\8eÀ\90Ñ\82É\89\9e\82\82Ä\93Á\93T\82ª\82 \82é\82©\82à\82µ\82ê\82Ü\82¹\82ñ\82Ì\82Å\81A' +
924           '\8fo\97\88\82é\82¾\82¯\93¯\82\82à\82Ì\82ð\8eg\82Á\82Ä\82­\82¾\82³\82¢\81B\8fÚ\8d×\82Í\83w\83\8b\83v\82ð\82²\97\97\82­\82¾\82³\82¢\81B');
925         mnGetNewId.Enabled := false;
926         BeginConnect;
927       end else begin
928         ShowHintLabel('LUID\8eæ\93¾\82É\8e¸\94s\82µ\82Ü\82µ\82½');
929       end;
930     end;
931     if (Command = 'voteMessage') then begin
932       if ResStr = 'OK' then begin
933         ShowHintLabel('\83\81\83b\83Z\81[\83W\82É\93\8a\95[/\93¯\88Ó\82µ\82Ü\82µ\82½\81B\95[\90\94: ' + HeadValue['Votes']);
934       end;
935     end;
936     if (Command = 'getChannels') and (ResStr = 'OK') then begin
937       UpdateChannelInfo(HeadValue);
938       SetChannel := nil;
939       try
940         if FAutoAddAfterGetChannel then begin
941           SetChannel := TStringList.Create;
942           if JoinChannelsBackup <> nil then begin
943             //\88ê\92U\83`\83\83\83\93\83l\83\8b\8eQ\89Á\82É\90¬\8c÷\82µ\82½\8cã\82È\82ç\8dÅ\8cã\82É\8eQ\89Á\82µ\82Ä\82¢\82½\83`\83\83\83\93\83l\83\8b
944             SetChannel.Assign(JoinChannelsBackup);
945           end else begin
946             //\8a®\91S\82É\8f\89\89ñ\8bN\93®\82Ì\8fê\8d\87\82Í\83v\83\8c\83t\83@\83\8c\83\93\83X\82©\82ç\93o\98^\95ª\82ð\8eæ\93¾
947             for i := 0 to Pref.AutoJoinChannels.Count-1 do begin
948               if ChannelList.Channel[Pref.AutoJoinChannels[i]] <> nil then
949                 SetChannel.Add(Pref.AutoJoinChannels[i]);
950             end;
951           end;
952         end else begin
953           Application.CreateForm(TfrmChannelList, frmChannelList);
954           try
955             if frmChannelList.Execute(ChannelList, JoinChannels) then begin
956               SetChannel := TStringList.Create;
957               SetChannel.Assign(frmChannelList.JoinList);
958             end;
959           finally
960             frmChannelList.Release;
961           end;
962         end;
963         if SetChannel <> nil then PostSetChannel(SetChannel);
964       finally
965         if SetChannel <> nil then FreeAndNil(SetChannel);
966       end;
967     end;
968     if (Command = 'setChannels') then begin
969       if ResStr <> 'OK' then begin
970         Beep;
971         ShowMessage('\83`\83\83\83\93\83l\83\8b\90Ý\92è\82É\8e¸\94s\82µ\82Ü\82µ\82½\81B\82à\82¤\88ê\93x\93o\98^\82µ\82È\82¨\82µ\82Ä\82­\82¾\82³\82¢');
972         ShowHintLabel('\83`\83\83\83\93\83l\83\8b\90Ý\92è\82É\8e¸\94s\82µ\82Ü\82µ\82½', WarningColor);
973       end;
974     end;
975     if HeadValue['ExtraTip'] <> '' then ShowHintLabel(HeadValue['ExtraTip']);
976   finally
977     HeadValue.Free;
978   end;
979 end;
980 }
981
982 procedure TfrmSender.actStartClick(Sender: TObject);
983 begin
984   ShowHintLabel('SSTP Bottle\83T\81[\83o\82É\82Í\90Ú\91±\82Å\82«\82Ü\82¹\82ñ', WarningColor);
985 {
986   if Pref.LUID = '' then begin
987     NoLuidError;
988     Exit;
989   end;
990   if not IdSlpp20.Connected then begin
991     FBeginConnectFailCount := 0; // \8e©\93®\8dÄ\90Ú\91±\83J\83E\83\93\83^\83\8a\83Z\83b\83g
992     BeginConnect;
993   end;
994   if Added then begin
995     FAutoAddAfterGetChannel := false;
996     PostCommand(['Command: getChannels']);
997   end;
998 }
999 end;
1000
1001 procedure TfrmSender.actStopExecute(Sender: TObject);
1002 begin
1003   ShowHintLabel('SSTP Bottle\83T\81[\83o\82É\82Í\90Ú\91±\82Å\82«\82Ü\82¹\82ñ', WarningColor);
1004 {
1005   // \8b­\90§\8dÄ\90Ú\91±\82ð\8ds\82¤
1006   IdSlpp20.OnDisconnect := nil;
1007   if IdSlpp20.Connected then IdSlpp20.Disconnect;
1008   FAutoAddAfterGetChannel := true;
1009   BeginConnect;
1010   IdSlpp20.OnDisconnect := Slpp20Disconnect;
1011 }
1012 end;
1013
1014 procedure TfrmSender.FormShow(Sender: TObject);
1015 begin
1016   if FBooted or Application.Terminated then Exit;
1017 {
1018   //LUID\82ª\8eæ\93¾\82³\82ê\82Ä\82¢\82ê\82Î\91\81\91¬\93o\98^\81B\82»\82¤\82Å\82È\82¯\82ê\82ÎLUID\8eæ\93¾\81B
1019   if Pref.LUID <> '' then BeginConnect
1020   else mnGetNewIdClick(Self);
1021   FAutoAddAfterGetChannel := Pref.AutoStart;
1022 }
1023   FBooted := true;
1024   if NOT Pref.NotShowLog then frmLog.Show;
1025   frmSurfacePreview.Show;
1026   Self.Show;
1027   SakuraSeeker.BeginDetect;
1028   SakuraSeekerDetectResultChanged(self);
1029   //\8e©\93®\95Û\91\90Ý\92è\82Ì\83\8d\81[\83h
1030   SetScriptAutoBackUp;
1031 {
1032   if SakuraSeeker.Count = 0 then
1033     frmMessageBox.ShowMessage('\83S\81[\83X\83g(SSTP\83T\81[\83o)\82ª1\82Â\82à\8bN\93®\82µ\82Ä\82¢\82Ü\82¹\82ñ\81B'#13#10 +
1034       'SSTP Bottle\82ð\97\98\97p\82·\82é\82½\82ß\82É\82Í\81A\83S\81[\83X\83g\82ð\93¯\8e\9e\82É\8bN\93®\82µ\82Ä\82­\82¾\82³\82¢\81B'#13#10 +
1035       '\8fÚ\8d×\82Í\83w\83\8b\83v\82ð\82²\97\97\89º\82³\82¢\81B');
1036 }
1037 end;
1038
1039 procedure TfrmSender.actAboutClick(Sender: TObject);
1040 var Str: String;
1041 begin
1042   Str := VersionString + #13#10 + BottleDisclaimer + #13#10#13#10;
1043   Str := Str + Format('Compiler Version: %f', [CompilerVersion]);
1044   frmMessageBox.ShowMessage(Str);
1045 end;
1046
1047 procedure TfrmSender.actExitClientExecute(Sender: TObject);
1048 begin
1049   Close;
1050 end;
1051
1052 procedure TfrmSender.actClearExecute(Sender: TObject);
1053 var
1054   Script, Default: String;
1055 begin
1056   Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]);
1057   Default := StringReplace(Pref.DefaultScript, '|', '', [rfReplaceAll]);
1058   Default := StringReplace(Default, #13#10, '', [rfReplaceAll]);
1059
1060   if (Pref.AutoClip) and (Length(GetScriptText) > 0) and (Script <> Default) then
1061     actSendToLogWindow.Execute
1062   else
1063     ClearEditor;
1064 end;
1065
1066 procedure TfrmSender.memScriptChange(Sender: TObject);
1067 begin
1068   //\83G\83f\83B\83^\93à\97e\82ª\95Ï\8dX\82³\82ê\82½\82Æ\82«
1069   EditerStatusChange;
1070   FScriptBackModified := true; //\8e©\93®\95Û\91\8dÄ\8aJ
1071   SetFileModified(true);       //\83t\83@\83C\83\8b\95Ï\8dX\83t\83\89\83O
1072 end;
1073
1074 procedure TfrmSender.EditerStatusChange;
1075 var
1076   Script: String;
1077   Text: String;
1078 begin
1079   // \83X\83e\81[\83^\83X\95Ï\8dX\82¾\82¯
1080   // \93à\97e\82ª\83h\83\89\83b\83O\82³\82ê\82½\82Æ\82«\82à\8cÄ\82Ñ\8fo\82³\82ê\82é
1081   Script := GetScriptText;
1082   // \94»\92è\82·\82é\95ª\8fd\82¢\82©\82à\81H
1083   if Pref.NotScriptTime AND (Length(Script) > Pref.NotScriptTimeLen) then
1084     Text := Format('%d\83o\83C\83g/?', [Length(Script)])
1085   else
1086   begin
1087     Script := StringReplace(Script, #13#10, '', [rfReplaceAll]);
1088     Text := Format('%d\83o\83C\83g/%d\95b', [Length(Script), SsPlayTime.PlayTime(Script) div 1000])
1089   end;
1090   StatusBar.Panels[PanelBytes].Text := Text;
1091 //  FScriptModified := true;
1092   EditorPreview;
1093 end;
1094
1095 procedure TfrmSender.mnStayOnTopClick(Sender: TObject);
1096 begin
1097   Pref.StayOnTop := not Pref.StayOnTop;
1098   mnStayOnTop.Checked := Pref.StayOnTop;
1099   if Pref.StayOnTop then begin
1100     FormStyle := fsStayOnTop;
1101   end else begin
1102     FormStyle := fsNormal;
1103   end;
1104   Show;
1105 end;
1106
1107 function TfrmSender.GetScriptText: String;
1108 begin
1109   Result := memScript.Lines.Text;
1110 end;
1111
1112 procedure TfrmSender.mnConstClick(Sender: TObject);
1113 var i: integer;
1114 begin
1115   i := (Sender as TMenuItem).Tag;
1116   memScript.SelText := ScriptConstList.GetConstByID(i).ConstText;
1117 end;
1118
1119 procedure TfrmSender.actEditConstExecute(Sender: TObject);
1120 begin
1121   ScriptConstList.LoadFromDir(FConstDir);
1122   try
1123     Application.CreateForm(TfrmConstEditor, frmConstEditor);
1124     frmConstEditor.Execute;
1125     ScriptConstList.Save;
1126   finally
1127     frmConstEditor.Release;
1128   end;
1129   ConstructMenu(false);
1130 end;
1131
1132 procedure TfrmSender.mnTaskBarClick(Sender: TObject);
1133 begin
1134   Application.Minimize;
1135   WindowState := wsNormal;
1136 end;
1137
1138 procedure TfrmSender.FormClose(Sender: TObject; var Action: TCloseAction);
1139 begin
1140 //  EndConnect;
1141   TaskTray.Registered := false;
1142 end;
1143
1144 procedure TfrmSender.ApplicationEventsMinimize(Sender: TObject);
1145 begin
1146   Visible := false;
1147   Application.ShowMainForm := false;
1148   ShowWindow(Application.Handle, SW_HIDE);
1149 end;
1150
1151 procedure TfrmSender.ApplicationEventsRestore(Sender: TObject);
1152 begin
1153   Application.ShowMainForm := true;
1154   Visible := true;
1155 end;
1156
1157 procedure TfrmSender.mnTaskRestoreClick(Sender: TObject);
1158 begin
1159   Application.Restore;
1160 end;
1161
1162 procedure TfrmSender.TaskTrayDblClick(Seft: TObject; Button: TMouseButton);
1163 begin
1164   Application.Restore;
1165 end;
1166
1167 procedure TfrmSender.FormActivate(Sender: TObject);
1168 begin
1169   memScript.SetFocus;
1170 end;
1171
1172 procedure TfrmSender.mnTaskNewMessageClick(Sender: TObject);
1173 begin
1174   Application.Restore;
1175   actClearExecute(Sender);
1176 end;
1177
1178 procedure TfrmSender.ChangeTaskIcon;
1179 var Ico: TIcon;
1180     IcoNum: integer;
1181 begin
1182 {
1183   if Added then begin
1184     if Sleeping then IcoNum := IconSleep else IcoNum := IconConnected;
1185   end else begin
1186     if Sleeping then IcoNum := IconSleepDisconnected
1187     else IcoNum := IconDisconnected;
1188   end;
1189 }
1190   //\83^\83X\83N\83A\83C\83R\83\93\82Ì\8fó\91Ô\81i\8e¸\94s\8fó\91Ô\8eg\97p\81j
1191   if Sleeping then IcoNum := IconSleepDisconnected
1192     else IcoNum := IconDisconnected;
1193   try
1194     Ico := TIcon.Create;
1195     try
1196       imgIcon.GetIcon(IcoNum, Ico);
1197       TaskTray.Icon := Ico;
1198       TaskTray.Registered := true;
1199     finally
1200       Ico.Free;
1201     end;
1202   except
1203     ; // PC\82Ì\95\89\89×\82ª\8d\82\82¢\82Æ4\95b\88È\93à\82É\83^\83X\83N\83g\83\8c\83C\93o\98^\82Å\82«\82¸\81A
1204       // \83V\83F\83\8b\82ª\83n\83\93\83O\82µ\82Ä\82¢\82é\82Æ\94»\92f\82³\82ê\82Ä\97á\8aO\82ª\94­\90\82·\82é\81B
1205       // \82»\82Ì\8fê\8d\87\82Í\83G\83\89\81[\82ð\96³\8e\8b\82·\82é
1206   end;
1207 end;
1208
1209 {
1210 procedure TfrmSender.SetStatusText(const Value: String);
1211 begin
1212   FStatusText := Value;
1213   StatusBar.Panels[PanelStatus].Text := Value;
1214 end;
1215 }
1216
1217 procedure TfrmSender.ApplicationEventsHint(Sender: TObject);
1218 var id: integer;
1219 begin
1220   if Length(Application.Hint) > 0 then
1221   begin
1222     StatusBar.Panels[PanelStatus].Text := GetLongHint(Application.Hint);
1223     Application.HintColor := clInfoBk;
1224\91\97\90M\83{\83^\83\93\8aÖ\98A
1225     if (Application.Hint = SendButtonLongHint)
1226     and (FNowChannel <> '') then
1227     begin
1228       //\91\97\90M\83{\83^\83\93\82Ì\8fê\8d\87\82Í\91¬\8dU\8fo\82·
1229       Application.HintColor := clYellow;
1230       Application.ActivateHint(Mouse.CursorPos);
1231     end;
1232 }
1233     if IsSurfaceTag(Application.Hint, id) and Pref.SurfacePreviewOnHint then
1234     begin
1235       // \83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[
1236       DoSurfacePreview(id, spHint);
1237     end;
1238   end else
1239   begin
1240     StatusBar.Panels[PanelStatus].Text := FStatusText;
1241     frmSurfacePreview.HideAway;
1242   end;
1243 end;
1244
1245 procedure TfrmSender.ConstructMenu(Simple: boolean);
1246 begin
1247   BuildMenu(mnPopConst, Simple);
1248   BuildMenu(mnPopUpConst.Items, Simple);
1249   BuildMenu(ConstBarMenu.Items, Simple);
1250   //\96\88\89ñ\8f\89\8aú\89»?
1251   if Pref.EConstBar then ConstMenuBar.Menu := nil;
1252   ConstMenuBar.AutoSize := false;
1253   ConstMenuBar.Width := 1000;
1254   ConstMenuBar.Menu := ConstBarMenu;
1255   ConstMenuBar.AutoSize := true;
1256 end;
1257
1258 procedure TfrmSender.memScriptKeyDown(Sender: TObject; var Key: Word;
1259   Shift: TShiftState);
1260 var Pos: TPoint;
1261     Func: TReturnKeyFunction;
1262 begin
1263   if (Key = VK_RETURN) then begin
1264     if (ssShift in Shift) then
1265       Func := Pref.WhenShiftReturn
1266     else if (ssCtrl in Shift) then
1267       Func := Pref.WhenCtrlReturn
1268     else
1269       Func := Pref.WhenReturn;
1270     case Func of
1271       kfConstText: begin
1272         with tbtnInsertConst do
1273           Pos := tbtnInsertConst.ClientToScreen(Point(0, Height));
1274         mnPopUpConst.Popup(Pos.X, Pos.Y);
1275       end;
1276       kfYenN: begin
1277         memScript.SelText := '\n';
1278         Key := 0;
1279       end;
1280       kfYenNReturn: begin
1281         memScript.SelText := '\n'#13#10;
1282       end;
1283       kfReturn: begin
1284         memScript.SelText := #13#10
1285       end;
1286     end;
1287   end;
1288 end;
1289
1290 procedure TfrmSender.mnShowToolBarClick(Sender: TObject);
1291 begin
1292   mnShowToolBar.Checked := not mnShowToolBar.Checked;
1293   Pref.ShowToolBar := mnShowToolBar.Checked;
1294   UpdateLayout;
1295 end;
1296
1297 procedure TfrmSender.mnShowConstBarClick(Sender: TObject);
1298 begin
1299   mnShowConstBar.Checked := not mnShowConstBar.Checked;
1300   Pref.ShowConstBar := mnShowConstBar.Checked;
1301   UpdateLayout;
1302 end;
1303
1304 procedure TfrmSender.UpdateLayout;
1305 begin
1306   with SakuraScriptFountain do begin
1307     TagColor.Color := Pref.MarkUpColor;
1308     TagErrorColor.Color := Pref.MarkErrorColor;
1309     Scope0Color.Color := Pref.TalkColorH;
1310     Scope1Color.Color := Pref.TalkColorU;
1311     SynchronizedColor.Color := Pref.TalkColorS;
1312   end;
1313   memScript.Ruler.Visible := Pref.ShowRuler;
1314   memScript.Ruler.Color := Pref.TextColor;
1315   memScript.Color := Pref.BgColor;
1316
1317   ToolBar.Visible := Pref.ShowToolBar;
1318   ConstMenuBar.Visible := Pref.ShowConstBar;
1319   ToolBar.Top := 0;
1320   //
1321   with tabChannel do begin
1322     TabPosition := Pref.TabPosition;
1323     case Pref.TabPosition of
1324       tpTop:    Align  := alTop;
1325       tpBottom: Align := alBottom;
1326     end;
1327     TabWidth := Pref.TabWidth;
1328   end;
1329 end;
1330
1331 function TfrmSender.DoTrans(var Script: String;
1332   Options: TScriptTransOptions; out FoundURL: boolean): String;
1333 var UrlCancel, Mark: String;
1334     Url, UrlName: array[0..6] of String;
1335     i, j, u, UrlCount: integer;
1336     LastSurfaceH, LastSurfaceU: integer;
1337     UnyuTalking: boolean;
1338     QuickSection, Synchronize: boolean;
1339     Warnings: TStringList;
1340 begin
1341   UrlCount := 0;
1342   LastSurfaceH := 0;
1343   LastSurfaceU := 10;
1344   UnyuTalking := false;
1345   QuickSection := false;
1346   Synchronize := false;
1347   SsParser.LeaveEscape := true;
1348   SsParser.EscapeInvalidMeta := false;
1349   SsParser.InputString := Script;
1350   Script := '';
1351   Warnings := TStringList.Create;
1352   try
1353     for i := 0 to SsParser.Count-1 do begin
1354       if SsParser[i] = '\t' then begin
1355         if not(toIgnoreTimeCritical in Options) then
1356           Script := Script + '\t';
1357       end else if SsParser[i] = '\e' then begin
1358         Continue;
1359       end else if (SsParser.Match(SsParser[i], '\URL%b') > 0) then begin
1360         if toConvertURL in Options then begin
1361           UrlCount := 0; //\91O\82ÌURL\83^\83O\82Ì\89e\8b¿\82ð\96³\8e\8b\81B
1362           for u := 7 downto 1 do begin
1363             if (SsParser.Match(SsParser[i],
1364                 '\URL%b'+StringReplace(StringOfChar('-', u*2),
1365                 '-', '%b', [rfReplaceAll]))) > 0 then begin
1366               for j := 1 to u do begin
1367                 Url[UrlCount] := SsParser.GetParam(SsParser[i], UrlCount*2+2);
1368                 UrlName[UrlCount] := SsParser.GetParam(SsParser[i], UrlCount*2+3);
1369                 if UrlName[UrlCount] = '' then UrlName[UrlCount] := Url[UrlCount];
1370                 if Pos('http://', Url[UrlCount]) > 0 then Inc(UrlCount);
1371               end;
1372             end;
1373             if UrlCount > 0 then UrlCancel := SsParser.GetParam(SsParser[i], 1);
1374             if UrlCancel = '' then UrlCancel := '\8ds\82©\82È\82¢\81@\81@\81@\81@';
1375           end;
1376           if SsParser.Match(SsParser[i], '\URL%b%b') = 0 then begin //\8aÈ\88Õ\94ÅURL\95Ï\8a·
1377             //\8aÈ\88Õ\8c`\8e®\URL\83^\83O\95Ï\8a·
1378             Url[0] := SsParser.GetParam(SsParser[i], 1);
1379             UrlName[0] := '\8ds\82­\81@\81@\81@\81@\81@\81@';
1380             UrlCancel  := '\8ds\82©\82È\82¢\81@\81@\81@\81@';
1381             if Pos('http://', Url[0]) > 0 then begin
1382               UrlCount := 1;
1383               if not QuickSection then
1384                 Script := Script + '\_q' + Url[0] + '\_q'
1385               else
1386                 Script := Script + Url[0];
1387             end;
1388           end;
1389         end else Script := Script + SsParser[i];
1390       end else begin
1391         Mark := SsParser[i];
1392         if Mark = '\h' then begin
1393           UnyuTalking := false;
1394           if toHUTagTo01Tag in Options then Mark := '\0';
1395           if Synchronize and Pref.WarnScopeChangeInSynchronize then
1396             Warnings.Add('\83V\83\93\83N\83\8d\83i\83C\83Y\83h\83Z\83N\83V\83\87\83\93\92\86\82É\h\82ª\82 \82è\82Ü\82·\81B');
1397         end else if Mark = '\u' then begin
1398           UnyuTalking := true;
1399           if toHUTagTo01Tag in Options then Mark := '\1';
1400           if Synchronize and Pref.WarnScopeChangeInSynchronize then
1401             Warnings.Add('\83V\83\93\83N\83\8d\83i\83C\83Y\83h\83Z\83N\83V\83\87\83\93\92\86\82É\u\82ª\82 \82è\82Ü\82·\81B');
1402         end else if Mark = '\_q' then begin
1403           QuickSection := not QuickSection;
1404         end else if Mark = '\_s' then begin
1405           Synchronize := not Synchronize;
1406         end else if SsParser.Match(Mark, '\s%b') > 0 then begin
1407           if UnyuTalking then begin
1408             LastSurfaceU := StrToIntDef(SsParser.GetParam(Mark, 1),
1409                                         LastSurfaceU);
1410           end else begin
1411             LastSurfaceH := StrToIntDef(SsParser.GetParam(Mark, 1),
1412                                         LastSurfaceH);
1413           end;
1414         end else if SsParser.Match(Mark, '\s%d') > 0 then begin
1415           if UnyuTalking then begin
1416             LastSurfaceU := StrToIntDef(Mark[3], LastSurfaceU);
1417           end else begin
1418             LastSurfaceH := StrToIntDef(Mark[3], LastSurfaceH);
1419           end;
1420         end;
1421         Script := Script + Mark;
1422       end;
1423     end;
1424     if UrlCount > 0 then begin
1425       FoundUrl := true;
1426       Script := Script + '\h\n';
1427       if not (toNoChoice in Options) then begin
1428         for i := 0 to UrlCount-1 do begin
1429           Script := Script + Format('\q%d[%s][%s]',
1430                       [i, SsParser.EscapeParam(Url[i]), UrlName[i]]);
1431         end;
1432         Script := Script + Format('\q%d[#cancel][%s]', [UrlCount, UrlCancel]);
1433         //Script := Script + '\z'; //\8dÅ\90Vphase\82Å\82Í\8dí\8f\9c
1434       end else begin
1435         Script := Script + '\h';
1436         for i := 0 to UrlCount-1 do begin
1437           Script := Script + Format('\n{%s}(%s)', [UrlName[i], Url[i]]);
1438         end;
1439         Script := Script + Format('\n{%s}', [UrlCancel]);
1440       end;
1441     end else
1442       FoundUrl := false;
1443     //\83X\83N\83\8a\83v\83g\82Ì\8dÅ\8cã\82É\83E\83F\83C\83g\91}\93ü
1444     if toWaitScriptEnd in Options then begin
1445       i := Pref.WaitScriptEnd;
1446       while i > 0 do begin
1447         if i > 9 then begin
1448           Script := Script + '\w9';
1449           Dec(i, 9);
1450         end else begin
1451           Script := Script + '\w' + IntToStr(i);
1452           i := 0;
1453         end;
1454       end;
1455     end;
1456
1457     Script := Script + '\e';
1458     RegExp.Subst('s/\r\n//gk', Script);
1459
1460     //\83^\83O\83`\83F\83b\83N\8aÖ\98A
1461     for i := 0 to SsParser.Count-1 do begin
1462       if SsParser.MarkUpType[i] = mtTagErr then begin
1463         Result := '"' + SsParser[i] + '"'#13#10 +
1464                   '\82Í\81ASSTP Bottle\82Å\94F\82ß\82ç\82ê\82È\82¢\82©\81A\94F\8e¯\82Å\82«\82È\82¢\83^\83O\82Å\82·\81B';
1465         Exit;
1466       end;
1467     end;
1468     if (SsParser[0] <> '\t') and Pref.WarnYenTNotExist then begin
1469       Warnings.Add('\83X\83N\83\8a\83v\83g\82ª\t\82©\82ç\8en\82Ü\82Á\82Ä\82¢\82Ü\82¹\82ñ\81B');
1470     end;
1471
1472     //\83`\83F\83b\83N
1473     if (Warnings.Count > 0) and (toWarnCheck in Options) then begin
1474       if MessageDlg(Warnings.Text + #13#10 + '\91\97\90M\82µ\82Ü\82·\82©?', mtWarning,
1475                     mbOkCancel, 0) = mrCancel then
1476         Result := Warnings.Text;
1477     end;
1478   finally
1479     Warnings.Free;
1480   end;
1481 end;
1482
1483 function TfrmSender.DoTrans(var Script: String;
1484   Options: TScriptTransOptions): String;
1485 var dum: boolean;
1486 begin
1487   Result := DoTrans(Script, Options, dum);
1488 end;
1489
1490 procedure TfrmSender.mnGoToHPClick(Sender: TObject);
1491 begin
1492   OpenBrowser(Pref.HomePage);
1493 end;
1494
1495 procedure TfrmSender.ShowHintLabel(const Mes: String; Col: TColor);
1496 begin
1497   lblMessage.Caption := Mes;
1498   lblMessage.Font.Color := Col;
1499   lblMessage.Visible := true;
1500   LabelTimer.Enabled := false;
1501   LabelTimer.Enabled := true;
1502 end;
1503
1504 procedure TfrmSender.LabelTimerTimer(Sender: TObject);
1505 begin
1506   LabelTimer.Enabled := false;
1507   lblmessage.Visible := false;
1508 end;
1509
1510 procedure TfrmSender.actCopyAllExecute(Sender: TObject);
1511 var Str: String;
1512     Clip: TClipBoard;
1513 begin
1514   Str := memScript.Lines.Text;
1515   Clip := ClipBoard();
1516   Clip.SetTextBuf(PChar(Str));
1517 end;
1518
1519 procedure TfrmSender.actCopyAllNoReturnExecute(Sender: TObject);
1520 var Str: String;
1521     Clip: TClipBoard;
1522 begin
1523   Str := memScript.Lines.Text;
1524   RegExp.Subst('s/\r\n//gk', Str);
1525   Clip := ClipBoard();
1526   Clip.SetTextBuf(PChar(Str));
1527 end;
1528
1529 {
1530 procedure TfrmSender.Slpp20SlppEvent(Sender: TObject; EventType: TIdSlppEventType;
1531   const Param: String);
1532 var HeadValue: THeadValue;
1533 begin
1534   HeadValue := THeadValue.Create(Param);
1535   try
1536     case EventType of
1537       etScript, etForceBroadcast, etUnicast: begin
1538         //\83\81\83b\83Z\81[\83W\8eó\90M
1539         DispatchBottle(EventType, HeadValue);
1540       end;
1541       etMemberCount: begin
1542         StatusBar.Panels[PanelMembers].Text := HeadValue['Num'] + '\90l'
1543       end;
1544       etChannelCount: begin
1545         try
1546           ChannelList.Channel[HeadValue['Channel']].Members := StrToInt(HeadValue['Num']);
1547         except
1548         end;
1549       end;
1550       etConnectOk: begin
1551         ShowHintLabel('SSTP Bottle\83T\81[\83o\82Æ\92Ê\90M\8am\97§\81B');
1552         Added := true;
1553         FBeginConnectFailCount := 0;
1554         //\83`\83\83\83\93\83l\83\8b\8e©\93®\93o\98^
1555         if not Connecting then
1556           PostCommand(['Command: getChannels']);
1557         SakuraSeeker.BeginDetect;
1558       end;
1559       etChannelList: begin
1560         UpdateJoinChannelList(HeadValue);
1561         // \8dÅ\8cã\82É\8eQ\89Á\82µ\82Ä\82¢\82½\83`\83\83\83\93\83l\83\8b\82ð\8bL\98^\82·\82é
1562         if JoinChannelsBackup = nil then JoinChannelsBackup := TStringList.Create;
1563         JoinChannelsBackup.Assign(JoinChannels);
1564       end;
1565       etCloseChannel: begin
1566         with JoinChannels do
1567           if IndexOf(HeadValue['Channel']) >= 0 then
1568             Delete(IndexOf(HeadValue['Channel']));
1569         with tabChannel do begin
1570           if Tabs.IndexOf(HeadValue['Channel']) >= 0 then
1571             Tabs.Delete(Tabs.IndexOf(HeadValue['Channel']));
1572           if Tabs.Count > 0 then TabIndex := 0 else TabIndex := -1;
1573           tabChannelChange(self);
1574         end;
1575         ShowHintLabel(HeadValue['Channel'] + '\83`\83\83\83\93\83l\83\8b\82Í\94p\8e~\82³\82ê\82Ü\82µ\82½',
1576                       WarningColor);
1577         frmLog.AddCurrentSystemLog('SYSTEM', HeadValue['Channel'] + '\83`\83\83\83\93\83l\83\8b\82Í\94p\8e~\82³\82ê\82Ü\82µ\82½');
1578         frmMessageBox.ShowMessage(HeadValue['Channel'] + '\83`\83\83\83\93\83l\83\8b\82Í\94p\8e~\82³\82ê\82Ü\82µ\82½');
1579       end;
1580       etForceBroadcastInformation: begin
1581         if HeadValue['Type'] = 'Vote' then begin
1582           frmLog.VoteLog(HeadValue['MID'], StrToIntDef(HeadValue['Num'], 0));
1583         end else if HeadValue['Type'] = 'Agree' then begin
1584           frmLog.AgreeLog(HeadValue['MID'], StrToIntDef(HeadValue['Num'], 0));
1585         end;
1586       end;
1587     end;
1588   finally
1589     HeadValue.Free;
1590   end;
1591 end;
1592 }
1593
1594 procedure TfrmSender.BottleSstpResendCountChange(Sender: TObject);
1595 begin
1596   StatusBar.Panels[PanelCount].Text := IntToStr(FBottleSstp.CueCount) + '\8c\8f';
1597   try
1598     TaskTray.TipString := 'Yasagure Client (' +
1599                           IntToStr(FBottleSstp.CueCount) + '\8c\8f)';
1600   except
1601     ; // \83^\83X\83N\83g\83\8c\83C\93o\98^\8e¸\94s\82ð\96³\8e\8b\82·\82é
1602   end;
1603   actClearBottles.Enabled := (FBottleSstp.CueCount > 0);
1604 end;
1605
1606 procedure TfrmSender.actSettingExecute(Sender: TObject);
1607 begin
1608   Application.CreateForm(TfrmSetting, frmSetting);
1609   try
1610     frmSetting.Execute;
1611     Pref.SaveSettings;
1612     SaveChainRuleList;
1613   finally
1614     frmSetting.Release;
1615     frmSetting := nil;
1616   end;
1617   //
1618   BuildReplaceMenu(mnPresetReplaceRoot);
1619   UpdateLayout;
1620   tabChannel.Repaint;
1621   frmLog.UpdateWindow;
1622   SetScriptAutoBackUp;  //\83X\83N\83\8a\83v\83g\8e©\93®\95Û\91\90Ý\92è\8dX\90V
1623   UpdateChannelList;    //\83`\83\83\83\93\83l\83\8b\83S\81[\83X\83g\8dÄ\83\8d\81[\83h
1624 end;
1625
1626 procedure TfrmSender.memScriptKeyPress(Sender: TObject; var Key: Char);
1627 begin
1628   if (Key = #13) or (Key = #10) then Key := Char(0);
1629 end;
1630
1631 {
1632 procedure TfrmSender.Slpp20Disconnect(Sender: TObject);
1633 begin
1634   Added := false;
1635   UpdateJoinChannelList(nil);
1636   frmLog.AddCurrentSystemLog('SYSTEM', '\83T\81[\83o\82©\82ç\90Ø\92f\82³\82ê\82Ü\82µ\82½');
1637   if not Application.Terminated then RetryBeginConnect;
1638 end;
1639 }
1640
1641 procedure TfrmSender.SetSleeping(const Value: boolean);
1642 begin
1643   FSleeping := Value;
1644   FBottleSstp.ResendSleep := Value;
1645   ChangeTaskIcon;
1646 end;
1647
1648 procedure TfrmSender.actClearBottlesExecute(Sender: TObject);
1649 var Re: integer;
1650 begin
1651   Re := MessageDlg(Format('\96¢\94z\91\97\82Ì%d\8c\8f\82ÌBottle\82ð\91S\95\94\83N\83\8a\83A\82µ\82Ü\82·', [FBottleSstp.CueCount]),
1652                    mtWarning, mbOkCancel, 0);
1653   if Re = mrOk then begin
1654     FBottleSstp.Clear;
1655     frmLog.AllBottleOpened;
1656     frmLog.UpdateWindow;
1657   end;
1658 end;
1659
1660 procedure TfrmSender.SakuraSeekerDetectResultChanged(Sender: TObject);
1661 begin
1662   UpdateIfGhostBox; // \83h\83\8d\83b\83v\83_\83E\83\93\82Ì\92\86\90g\82ð\8f\91\82«\8a·\82¦\82é
1663 end;
1664
1665 {
1666 procedure TfrmSender.UpdateChannelInfo(Dat: THeadValue);
1667 var i: integer;
1668     Ch: TChannelListItem;
1669 begin
1670   ChannelList.Clear;
1671   for i := 1 to Dat.IntData['Count'] do begin
1672     Ch := TChannelListItem.Create;
1673     Ch.Name    := Dat[Format('CH%d_name', [i])];
1674     Ch.Ghost   := Dat[Format('CH%d_ghost', [i])];
1675     Ch.Info    := Dat[Format('CH%d_info', [i])];
1676     Ch.NoPost  := Dat[Format('CH%d_nopost', [i])] = '1';
1677     Ch.Members := Dat.IntData[Format('CH%d_count', [i])];
1678     Ch.WarnPost:= Dat[Format('CH%d_warnpost', [i])] = '1';
1679     ChannelList.Add(Ch);
1680   end;
1681   UpdateLayout;
1682 end;
1683 }
1684
1685 procedure TfrmSender.mnGetNewIdClick(Sender: TObject);
1686 begin
1687   ShowHintLabel('LUID\82Ì\8eæ\93¾\82Í\82Å\82«\82Ü\82¹\82ñ', WarningColor);
1688 //  PostCommand(['Command: getNewId', 'Agent: ' + VersionString]);
1689 end;
1690
1691 {
1692 procedure TfrmSender.NoLuidError;
1693 begin
1694   Beep;
1695   ShowMessage('SSTP Bottle ID\82Ì\8eæ\93¾\82ª\82Ü\82¾\8a®\97¹\82µ\82Ä\82¢\82Ü\82¹\82ñ\81B'#13#10+
1696               '\83w\83\8b\83v\83\81\83j\83\85\81[\82Ì[LUID\8eæ\93¾]\82©\82çID\82ð\8eæ\93¾\82µ\82Ä\82­\82¾\82³\82¢\81B'#13#10+
1697               '\82±\82Ì\91\80\8dì\82ÍClient\8f\89\89ñ\8bN\93®\8e\9e\82É1\89ñ\82¾\82¯\95K\97v\82Å\82·\81B');
1698 end;
1699 }
1700
1701 procedure TfrmSender.tabChannelChange(Sender: TObject);
1702 begin
1703 {
1704   if tabChannel.TabIndex >= 0 then begin
1705     FNowChannel := tabChannel.Tabs[tabChannel.TabIndex];
1706     actSend.Hint := Format('\81u%s\81v\82É\91\97\90M|%s', [FNowChannel, SendButtonLongHint]);
1707   end else begin
1708     FNowChannel := '';
1709     actSend.Hint := '';
1710   end;
1711   tabChannel.Repaint; //\82±\82ê\82ª\82È\82¢\82Æ\90F\82ª\95Ï\82í\82ç\82È\82¢\82±\82Æ\82ª\82 \82é
1712   ConstructMenu(true);
1713 }
1714 end;
1715
1716 procedure TfrmSender.actPrevChannelExecute(Sender: TObject);
1717 begin
1718 {
1719   with tabChannel do begin
1720     if Tabs.Count = 0 then Exit;
1721     if TabIndex=0 then TabIndex := Tabs.Count-1
1722     else TabIndex := TabIndex-1;
1723   end;
1724   tabChannelChange(Self);
1725 }
1726 end;
1727
1728 procedure TfrmSender.actNextChannelExecute(Sender: TObject);
1729 begin
1730 {
1731   with tabChannel do begin
1732     if Tabs.Count = 0 then Exit;
1733     if TabIndex=Tabs.Count-1 then TabIndex := 0
1734     else TabIndex := TabIndex+1;
1735   end;
1736   tabChannelChange(Self);
1737 }
1738 end;
1739
1740 {
1741 procedure TfrmSender.UpdateJoinChannelList(Dat: THeadValue);
1742 var
1743   i: integer;
1744   nodat: boolean;
1745 begin
1746   nodat := Dat = nil; //nil\82È\82ç\83`\83\83\83\93\83l\83\8b\91S\89ð\8f\9c
1747   if nodat then Dat := THeadValue.Create('');
1748   JoinChannels.Clear;
1749   for i := 0 to Dat.Count-1 do
1750     if Dat.KeyAt[i] = 'Entry' then begin
1751       if RegExp.Match('m/^(.+?) \((\d+?)\)$/', Dat.ValueAt[i]) then
1752         JoinChannels.Add(RegExp[1]);
1753     end;
1754   with tabChannel do begin
1755     OnChange := nil;
1756     JoinChannels.Sort;
1757     Tabs.BeginUpdate;
1758     Tabs.Clear;
1759     for i := 0 to JoinChannels.Count-1 do begin
1760       //\8eó\90M\90ê\97p\83`\83\83\83\93\83l\83\8b\82Í\95\\8e¦\82µ\82È\82¢
1761       if not ChannelList.Channel[JoinChannels[i]].NoPost then
1762         Tabs.Add(JoinChannels[i]);
1763     end;
1764     Tabs.EndUpdate;
1765     // \8c³\82©\82ç\83`\83\83\83\93\83l\83\8b\82É\8eQ\89Á\82µ\82Ä\82¢\82½\8fê\8d\87\82Í
1766     // \91I\91ð\82³\82ê\82Ä\82¢\82½\83`\83\83\83\93\83l\83\8b\82ª\95Ï\82í\82ç\82È\82¢\82æ\82¤\82É\82·\82é(\83^\83u\82ª\82¸\82ê\82È\82¢\8f\88\97\9d)
1767     TabIndex := 0;
1768     for i := 0 to Tabs.Count-1 do
1769       if Tabs[i] = FNowChannel then TabIndex := i;
1770     if Tabs.Count > 0 then begin
1771       FNowChannel := Tabs[TabIndex];
1772       actSend.Hint := Format('\81u%s\81v\82É\91\97\90M|%s', [FNowChannel, SendButtonLongHint]);
1773     end else begin
1774       FNowChannel := '';
1775       actSend.Hint := Format('\91\97\90M|%s', [SendButtonLongHint]);
1776     end;
1777     Visible := Tabs.Count > 0;
1778     if Tabs.Count > 1 then begin
1779       actNextChannel.Enabled := true;
1780       actPrevChannel.Enabled := true;
1781     end else begin
1782       actNextChannel.Enabled := false;
1783       actPrevChannel.Enabled := false;
1784     end;
1785     OnChange := tabChannelChange;
1786   end;
1787   if nodat then Dat.Free;
1788   if JoinChannels.Count = 0 then begin
1789     Self.Caption := FOriginalCaption + ' - \83`\83\83\83\93\83l\83\8b\82É\8eQ\89Á\82µ\82Ä\82¢\82Ü\82¹\82ñ';
1790     actSend.Enabled := false;
1791   end else begin
1792     Self.Caption := FOriginalCaption;
1793     actSend.Enabled := true;
1794   end;
1795 end;
1796 }
1797
1798 procedure TfrmSender.cbxTargetGhostDropDown(Sender: TObject);
1799 begin
1800   SakuraSeeker.BeginDetect;
1801   UpdateIfGhostBox;
1802 end;
1803
1804 procedure TfrmSender.actShowLogExecute(Sender: TObject);
1805 begin
1806   frmLog.Show;
1807   if frmLog.WindowState = wsMinimized then frmLog.WindowState := wsNormal;
1808 end;
1809
1810 procedure TfrmSender.actSleepExecute(Sender: TObject);
1811 begin
1812   if actSleep.Checked then begin
1813     actSleep.Checked := false;
1814     ShowHintLabel('\83X\83\8a\81[\83v\82ð\89ð\8f\9c\82µ\82Ü\82µ\82½');
1815   end else begin
1816     actSleep.Checked := true;
1817     ShowHintLabel('\83X\83\8a\81[\83v\82ð\90Ý\92è\82µ\82Ü\82µ\82½');
1818   end;
1819   Sleeping := actSleep.Checked;
1820   ChangeTaskIcon;
1821 end;
1822
1823
1824 procedure TfrmSender.DispatchBottle(Dat: THeadValue; LogTime: TDateTime;
1825   Vote, Agree: integer);
1826 //procedure TfrmSender.DispatchBottle(EventType: TIdSlppEventType;
1827 //  Dat: THeadValue);
1828 var Opt: TSstpSendOptions;
1829     Event: TBottleChainBottleEvent;
1830     Script, Sender, Ghost, Channel, ErrorMes: String;
1831     BreakFlag, NoDispatch: boolean;
1832     Sound, LogName: String;
1833     i, j, k, SkipCount: integer;
1834     Rule: TBottleChainRule;
1835     Action: TBottleChainAction;
1836     LogNameList: TStringList;
1837     CueItem: TLogItem;
1838     ReplaceHash: THeadValue;
1839 begin
1840   Opt := [];
1841   if Pref.NoTranslate then Opt := Opt + [soNoTranslate];
1842   if Pref.NoDescript  then Opt := Opt + [soNoDescript];
1843   Channel := Dat['Channel'];
1844 {
1845   case EventType of
1846     etScript: Sender := Channel;
1847     etForceBroadcast: Sender := '\81y\82¨\92m\82ç\82¹\81z';
1848     etUnicast: Sender := Dat['SenderUID'];
1849   end;
1850 }
1851   Sender := Channel; //\92Ê\8fí
1852
1853   //\96Ú\95W\83S\81[\83X\83g(\83I\81[\83o\81[\83\89\83C\83h\88È\91O)\8c\88\92è
1854   if Dat['IfGhost'] <> '' then begin
1855     Ghost := Dat['IfGhost'];
1856   end else begin
1857     if ChannelList.Channel[Channel] <> nil then
1858       Ghost := ChannelList.Channel[Channel].Ghost
1859     else
1860       Ghost := '';
1861   end;
1862   Dat['TargetGhost'] := Ghost;
1863
1864   // \83\81\83^\95\8e\9a\8f\80\94õ
1865   ReplaceHash := THeadValue.Create;
1866   ReplaceHash['%channel%'] := SafeFileName(Dat['Channel']);
1867   ReplaceHash['%ghost%'] := SafeFileName(Dat['IfGhost']);
1868   ReplaceHash['%date%'] := FormatDateTime('yy-mm-dd', Now());
1869   ReplaceHash['%year%'] := FormatDateTime('yyyy', Now());
1870   ReplaceHash['%yy%'] := FormatDateTime('yy', Now());
1871   ReplaceHash['%month%'] := FormatDateTime('mm', Now());
1872   ReplaceHash['%day%'] := FormatDateTime('dd', Now());
1873   ReplaceHash['%hour%'] := FormatDateTime('hh', Now());
1874   ReplaceHash['%minute%'] := FormatDateTime('nn', Now());
1875
1876   Event := TBottleChainBottleEvent.Create;
1877   try
1878     Event.Data := Dat;
1879 {
1880     if EventType = etScript then Event.LogType := ltBottle
1881     else Event.LogType := ltSystemLog;
1882 }
1883     Event.LogType := ltBottle; //\92Ê\8fí
1884
1885     //\83X\83N\83\8a\83v\83g\95Ï\8a·
1886     Script := ScriptTransForSSTP(Dat['Script'], ErrorMes);
1887     //\96â\91è\82Ì\97L\82é\95r\82É\91Î\82·\82é\93®\8dì
1888     if (ErrorMes <> '') AND (NOT Pref.ErrScript) then
1889     begin
1890       frmLog.AddCurrentSystemLog('SYSTEM', '\96â\91è\82Ì\82 \82é\89Â\94\\90«\82Ì\82 \82é\83X\83N\83\8a\83v\83g\82ª\93Í\82¢\82½\82½\82ß\81A'+
1891                     '\94z\91\97\82³\82ê\82Ü\82¹\82ñ\82Å\82µ\82½\81@\81c '+Dat['Script']);
1892       Exit;
1893     end;
1894
1895     BreakFlag := false;
1896     NoDispatch := false;
1897     Sound := '';
1898     LogNameList := TStringList.Create;
1899     SkipCount := 0;
1900     try
1901       for i := 0 to BottleChainRuleList.Count-1 do begin
1902         if SkipCount > 0 then begin
1903           Dec(SkipCount);
1904           Continue;
1905         end;
1906         Rule := BottleChainRuleList[i];
1907         if not Rule.Enabled then Continue;
1908         if not Rule.Check(Event) then Continue;
1909         for j := 0 to Rule.Actions.Count-1 do begin
1910           Action := (Rule.Actions[j] as TBottleChainAction);
1911           if Action is TBottleChainAbortRuleAction then
1912             BreakFlag := true;
1913           if Action is TBottleChainSkipRuleAction then
1914             SkipCount := (Action as TBottleChainSkipRuleAction).SkipCount;
1915           if (Action is TBottleChainSoundAction) and (Sound = '') then
1916           begin
1917             Sound := (Action as TBottleChainSoundAction).SoundFile;
1918             Sound := StringReplaceEx(Sound, ReplaceHash);
1919           end;
1920           if Action is TBottleChainNoDispatchAction then
1921             NoDispatch := true;
1922           if Action is TBottleChainLogAction then
1923           begin
1924             for k := 0 to (Action as TBottleChainLogAction).LogNames.Count-1 do begin
1925               LogName := (Action as TBottleChainLogAction).LogNames[k];
1926               LogName := StringReplaceEx(LogName, ReplaceHash);
1927               LogNameList.Add(LogName);
1928             end;
1929           end;
1930           if Action is TBottleChainOverrideGhostAction then
1931           begin
1932             Dat['TargetGhost'] := (Action as TBottleChainOverrideGhostAction).TargetGhost;
1933           end;
1934           if Action is TBottleChainQuitAction then
1935             Application.Terminate;
1936           if Action is TBottleChainSaveTextLogAction then
1937             AppendTextLog(StringReplaceEx((Action as TBottleChainSaveTextLogAction).FileName, ReplaceHash),
1938               Format('%s,%s,%s,%s', [Dat['Channel'], Dat['IfGhost'],
1939                 FormatDateTime('yy/mm/dd hh:nn:ss', Now), Dat['Script']]));
1940           if Action is TBottleChainSaveXMLLogAction then
1941             AppendXMLLog(StringReplaceEx((Action as TBottleChainSaveXMLLogAction).FileName, ReplaceHash),
1942               Dat);
1943           if Action is TBottleChainSurfaceReplaceAction then
1944             Script := ReplaceSurface(Script, (Action as TBottleChainSurfaceReplaceAction).Params);
1945         end;
1946         if BreakFlag then Break;
1947       end;
1948
1949       if Dat['Script'] <> '' then begin
1950         for i := 0 to LogNameList.Count-1 do
1951           frmLog.AddCurrentScriptLog(LogNameList[i], Dat['Script'], Sender, Dat['MID'], Dat['IfGhost'],
1952             LogTime, Vote, Agree);
1953         if NoDispatch or Pref.NotSSTP then begin
1954           frmLog.SetBottleState(Dat['MID'], lsOpened);
1955         end else begin
1956           Ghost := Dat['TargetGhost']; // \83I\81[\83o\81[\83\89\83C\83h\82³\82ê\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82é
1957           CueItem := TLogItem.Create(ltBottle, Dat['MID'], Dat['Channel'],
1958             Script, Ghost, Now());
1959           try
1960             FBottleSstp.Push(CueItem);
1961           except
1962             CueItem.Free;
1963           end;
1964         end;
1965       end;
1966
1967 {
1968       if Dat['DialogMessage'] <> '' then begin
1969         Beep;
1970         frmMessageBox.ShowMessage(
1971           DateTimeToStr(Now) + #13#10 +
1972           'SSTP Bottle\83T\81[\83o\82©\82ç\82¨\92m\82ç\82¹'#13#10+Dat['DialogMessage']);
1973         for i := 0 to LogNameList.Count-1 do
1974           frmLog.AddCurrentSystemLog(LogNameList[i], Dat['DialogMessage']);
1975       end;
1976 }
1977
1978       //\89¹\82Ì\8dÄ\90
1979       if (Sound <> '') then PlaySound(Sound);
1980     finally
1981       LogNameList.Free;
1982     end;
1983   finally
1984     Event.Free;
1985     ReplaceHash.Free;
1986   end;
1987 end;
1988
1989 procedure TfrmSender.YenETrans;
1990 var St, Le, i: integer;
1991     Orig, Text: String;
1992 begin
1993   if Pref.NotYenETrans then exit; // \e\83`\83F\83b\83N\82µ\82È\82¢
1994   St := memScript.SelStart;
1995   Le := memScript.SelLength;
1996   Orig := GetScriptText;
1997   RegExp.Subst('s/(\r\n)+$//kg', Orig);
1998
1999   with SsParser do begin
2000     LeaveEscape := true;
2001     EscapeInvalidMeta := false;
2002     InputString := Orig;
2003   end;
2004   for i := 0 to SsParser.Count-1 do begin
2005     if SsParser[i] <> '\e' then Text := Text + SsParser[i];
2006   end;
2007
2008   Text := Text + '\e';
2009
2010   if Orig <> Text then memScript.Lines.Text := Text;
2011   SsParser.InputString := Text;
2012
2013   RegExp.Subst('s/\r\n//kg', Text);
2014   memScript.SetFocus;
2015   memScript.SelStart := St;
2016   memScript.SelLength := Le;
2017 end;
2018
2019 {
2020 procedure TfrmSender.PostCommand(const Command: array of String);
2021 var PostStr: TStringList;
2022     i: integer;
2023 begin
2024   PostStr := nil;
2025   try
2026     PostStr := TStringList.Create;
2027     for i := Low(Command) to High(Command) do begin
2028       PostStr.Add(Command[i]);
2029     end;
2030     PostCommand(PostStr);
2031   finally
2032     PostStr.Free;
2033   end;
2034 end;
2035 }
2036
2037 {
2038 procedure TfrmSender.PostCommand(Command: TStrings);
2039 var PostStr: String;
2040 begin
2041   Connecting := true;
2042   PostStr := Command.Text;
2043   PostStr := ParamsEncode(PostStr);
2044   try
2045     FHttp := THTTPDownloadThread.Create(Pref.BottleServer, Pref.CgiName, PostStr);
2046     if Pref.UseHttpProxy then begin
2047       FHttp.ProxyServer := Pref.ProxyAddress;
2048       FHttp.ProxyPort   := Pref.ProxyPort;
2049     end;
2050     FHttp.OnSuccess := HttpSuccess;
2051     FHttp.OnConnectionFailed := HttpFailure;
2052     FHttp.FreeOnTerminate := true; // \8f\9f\8eè\82É\8e©\95ª\82ÅFree\82µ\82Ä\82­\82¾\82³\82¢
2053     FHTTP.Resume;
2054   except
2055     on EHeapException do begin
2056       Connecting := false;
2057       FHttp.Free;
2058     end;
2059   end;
2060 end;
2061 }
2062
2063 procedure TfrmSender.actVoteMessageExecute(Sender: TObject);
2064 //var Log: TLogItem;
2065 begin
2066   ShowHintLabel('\93\8a\95[\82Å\82«\82Ü\82¹\82ñ', WarningColor);
2067 {
2068   if frmLog.lvwLog.Selected = nil then Exit;
2069   Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem;
2070   if Log = nil then Exit;
2071   if Log.LogType <> ltBottle then Exit;
2072   PostCommand([
2073     'Command: voteMessage',
2074     'VoteType: Vote',
2075     'LUID: ' + Pref.LUID,
2076     'MID: ' + Log.MID
2077   ]);
2078 }
2079 end;
2080
2081
2082 procedure TfrmSender.actAgreeMessageExecute(Sender: TObject);
2083 //var Log: TLogItem;
2084 begin
2085   ShowHintLabel('\93¯\88Ó\82Å\82«\82Ü\82¹\82ñ', WarningColor);
2086 {
2087   if frmLog.lvwLog.Selected = nil then Exit;
2088   Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem;
2089   if Log = nil then Exit;
2090   if Log.LogType <> ltBottle then Exit;
2091   PostCommand([
2092     'Command: voteMessage',
2093     'VoteType: Agree',
2094     'LUID: ' + Pref.LUID,
2095     'MID: ' + Log.MID
2096   ]);
2097 }
2098 end;
2099
2100
2101 function TfrmSender.GhostNameToSetName(const Ghost: String): String;
2102 begin
2103   if SakuraSeeker.ProcessByName[Ghost] <> nil then
2104     Result := SakuraSeeker.ProcessByName[Ghost].SetName
2105   else
2106     Result := '';
2107 end;
2108
2109 procedure TfrmSender.tabChannelContextPopup(Sender: TObject;
2110   MousePos: TPoint; var Handled: Boolean);
2111 //var Ch: String;
2112 begin
2113 {
2114   with tabChannel do begin
2115     Tag := IndexOfTabAt(MousePos.X, MousePos.Y);
2116     if Tag < 0 then Handled := true;
2117     Ch := Tabs[Tag];
2118   end;
2119 }
2120 end;
2121
2122 {
2123 procedure TfrmSender.PostSetChannel(Channels: TStrings);
2124 var PostStr: TStringList;
2125     i: integer;
2126 begin
2127   PostStr := TStringList.Create;
2128   try
2129     with PostStr do begin
2130       Add('Command: setChannels');
2131       Add('Agent: ' + VersionString);
2132       Add('LUID: ' + Pref.LUID);
2133       if Channels <> nil then
2134         for i := 0 to Channels.Count-1 do begin
2135           Add(Format('Ch%d: %s'#13#10, [i+1, Channels[i]]));
2136         end;
2137     end;
2138     PostCommand(PostStr);
2139   finally
2140     PostStr.Free;
2141   end;
2142 end;
2143 }
2144
2145 procedure TfrmSender.mnLeaveThisChannelClick(Sender: TObject);
2146 //var Ch: String;
2147 //    Chs: TStringList;
2148 begin
2149 {
2150   // \8ew\92è\82µ\82½\83`\83\83\83\93\83l\83\8b\82©\82ç\94²\82¯\82é
2151   with tabChannel do
2152     Ch := Tabs[Tag]; // \94²\82¯\82½\82¢\83`\83\83\83\93\83l\83\8b\96¼
2153   Chs := TStringList.Create;
2154
2155   // \8c»\8dÝ\8eQ\89Á\92\86\82Ì\83`\83\83\83\93\83l\83\8b\82©\82ç\81A\94²\82¯\82½\82¢\83`\83\83\83\93\83l\83\8b\82ð
2156   // \8aO\82µ\82½\83\8a\83X\83g\82Å\81A\90V\82½\82É\83`\83\83\83\93\83l\83\8b\8eQ\89Á\83R\83}\83\93\83h\82ð\91\97\82é
2157   try
2158     Chs.Assign(JoinChannels);
2159     while Chs.IndexOf(Ch) >= 0 do
2160       Chs.Delete(Chs.IndexOf(Ch));
2161     PostSetChannel(Chs);
2162   finally
2163     Chs.Free;
2164   end;
2165 }
2166 end;
2167
2168 procedure TfrmSender.mnGotoVoteClick(Sender: TObject);
2169 begin
2170   OpenBrowser(Pref.VotePage);
2171 end;
2172
2173 procedure TfrmSender.tabChannelMouseMove(Sender: TObject;
2174   Shift: TShiftState; X, Y: Integer);
2175 //var Index: integer;
2176 //    Ch: String;
2177 begin
2178 {
2179   with tabChannel do begin
2180     Index := IndexOfTabAt(X, Y);
2181     Ch := Tabs[Index];
2182     Hint := Ch + ': ' + IntToStr(ChannelList.Channel[Ch].Members) + '\90l';
2183   end;
2184 }
2185 end;
2186
2187 procedure TfrmSender.mnGoToHelpClick(Sender: TObject);
2188 begin
2189   OpenBrowser(Pref.HelpPage);
2190 end;
2191
2192 procedure TfrmSender.tabChannelMouseDown(Sender: TObject;
2193   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
2194 //var Index: integer;
2195 begin
2196 {
2197   with tabChannel do begin
2198     Index := IndexOfTabAt(X, Y);
2199     if Index = -1 then Exit; //\83^\83u\82ª\82È\82¢\82Ì\82Å\83h\83\89\83b\83O\82Å\82«\82È\82¢
2200     if Button = mbLeft then begin
2201       FDragTabIndex := Index; //\83h\83\89\83b\83O\82·\82é\83^\83u\82Ì\83C\83\93\83f\83b\83N\83X\82ð\95Û\91
2202       BeginDrag(False);
2203       FDragTabDest := -1;     //\83h\83\89\83b\83O\98g\90ü\95`\89æ\83t\83\89\83O\83N\83\8a\83A\82Ì\82½\82ß
2204     end;
2205   end;
2206 }
2207 end;
2208
2209 procedure TfrmSender.tabChannelDragOver(Sender, Source: TObject; X,
2210   Y: Integer; State: TDragState; var Accept: Boolean);
2211 //var TargetRect: TRect;
2212 //    OldDest: integer;
2213 begin
2214 {
2215   Accept := Source = tabChannel;
2216   if not Accept then Exit;
2217   with tabChannel do begin
2218     OldDest := FDragTabDest;
2219     FDragTabDest := IndexOfTabAt(X, Y);
2220     if FDragTabDest = -1 then begin
2221       Accept := false; //\82±\82Ì\8fê\8d\87\82Í\83h\83\8d\83b\83v\82ð\94F\82ß\82È\82¢
2222       Exit;
2223     end;
2224     with Canvas do begin
2225       Pen.Mode := pmNot;
2226       Pen.Width := 3;
2227     end;
2228     if (OldDest <> FDragTabDest) and (OldDest >= 0) then begin
2229       //\88È\91O\82Ì\98g\90ü\8fÁ\8b\8e
2230       TargetRect := TabRect(OldDest);
2231       with Canvas do begin
2232         Brush.Style := bsClear;
2233         Rectangle(TargetRect.Left, TargetRect.Top,
2234                   TargetRect.Right, TargetRect.Bottom);
2235       end;
2236     end;
2237     if (OldDest <> FDragTabDest) then begin
2238       //\90V\82µ\82¢\98g\90ü\95`\89æ
2239       TargetRect := TabRect(FDragTabDest);
2240       with Canvas do begin
2241         Brush.Style := bsClear;
2242         Rectangle(TargetRect.Left, TargetRect.Top,
2243                   TargetRect.Right, TargetRect.Bottom);
2244       end;
2245     end;
2246   end;
2247 }
2248 end;
2249
2250 procedure TfrmSender.tabChannelDragDrop(Sender, Source: TObject; X,
2251   Y: Integer);
2252 //var DestIndex: integer;
2253 begin
2254 {
2255   with tabChannel do begin
2256     DestIndex := IndexOfTabAt(X, Y);
2257     Tabs.Move(FDragTabIndex, DestIndex);
2258   end;
2259 }
2260 end;
2261
2262 procedure TfrmSender.tabChannelEndDrag(Sender, Target: TObject; X,
2263   Y: Integer);
2264 begin
2265 {
2266   //\8b­\90§\93I\82É\83^\83u\82ð\8dÄ\95`\89æ\82³\82¹\82é\81B\98g\90ü\8fÁ\82µ\91Î\8dô
2267   tabChannel.Tabs.BeginUpdate;
2268   tabChannel.Tabs.EndUpdate;
2269 }
2270 end;
2271
2272 procedure TfrmSender.cbxTargetGhostDrawItem(Control: TWinControl;
2273   Index: Integer; Rect: TRect; State: TOwnerDrawState);
2274 var AlignRight: boolean;
2275     w: integer;
2276 begin
2277   //\83S\81[\83X\83g\91I\91ð\83{\83b\83N\83X\82Ì\83I\81[\83i\81[\83h\83\8d\81[
2278   with cbxTargetGhost do begin
2279     AlignRight := false;
2280     if Pref.HideGhosts and not FTargetGhostExpand and
2281        (Index = Items.Count-1) and (Index > 0) then
2282     begin
2283       // \81u\82·\82×\82Ä\95\\8e¦\81v
2284       Canvas.Font.Color := clWindowText;
2285       Canvas.Font.Style := [];
2286       AlignRight := true;
2287     end else if (Index > 0) then
2288     begin
2289       // \83S\81[\83X\83g\96¼\82ð\91I\91ð
2290       if SakuraSeeker.ProcessByName[Items[Index]] = nil then
2291         Canvas.Font.Color := clRed // \91\8dÝ\82µ\82È\82¢\83S\81[\83X\83g
2292       else
2293         Canvas.Font.Color := clBlue; // \91\8dÝ\82·\82é\83S\81[\83X\83g
2294       Canvas.Font.Style := [fsBold];
2295     end else
2296     begin
2297       Canvas.Font.Color := clWindowText;
2298       Canvas.Font.Style := [];
2299     end;
2300     if odSelected in State then
2301       Canvas.Font.Color := clHighlightText;
2302     // \95`\89æ
2303     if AlignRight then
2304     begin
2305       w := Canvas.TextWidth(cbxTargetGhost.Items[Index]);
2306       Canvas.TextRect(Rect, Rect.Right - w, Rect.Top,
2307         cbxTargetGhost.Items[Index]);
2308     end else
2309       Canvas.TextRect(Rect, Rect.Left, Rect.Top,
2310         cbxTargetGhost.Items[Index]);
2311   end;
2312 end;
2313
2314 procedure TfrmSender.FormCloseQuery(Sender: TObject;
2315   var CanClose: Boolean);
2316 begin
2317   //\83t\83@\83C\83\8b\82Ì\8dX\90V\83`\83F\83b\83N\81i\83G\83f\83B\83^\95\94\81j
2318   if CheckFileSave(Self) = idCancel then CanClose := false;
2319   //\83\8d\83O\81i\83^\83u\81j\93à\97e\82Ì\95Ï\8dX\83`\83F\83b\83N
2320   if frmLog.CheckLog(Self) = idCancel then CanClose := false;
2321   if (not Pref.ConfirmOnExit) or FEndSession then
2322     Exit;
2323   if MessageDlg('Yasagure Client\82ð\8fI\97¹\82µ\82Ü\82·', mtConfirmation,
2324                 mbOkCancel, 0) = mrCancel then
2325     CanClose := false;
2326 end;
2327
2328 procedure TfrmSender.UpdateIfGhostBox;
2329 var
2330   Selected: String;
2331   i: integer;
2332   HiddenCount: integer;
2333 begin
2334   cbxTargetGhost.DropDownCount := Pref.GhostDropDownCount;
2335   Selected := cbxTargetGhost.Text;
2336   HiddenCount := 0;
2337   with cbxTargetGhost do begin
2338     Items.BeginUpdate;
2339     Items.Clear;
2340     Items.Add(ChannelDefault);
2341     for i := 0 to SakuraSeeker.Count-1 do begin
2342       // \94j\91¹FMO\91Î\8dô\81BHWND\82Ì\92f\95Ð\82ª\8ec\82Á\82Ä\82¢\82é\82ªName\82ª\8fÁ\82¦\82Ä\82¢\82é\8fê\8d\87\82ª\82 \82é
2343       if Length(SakuraSeeker[i].Name) = 0 then Continue;
2344       if Pref.HideGhosts and not FTargetGhostExpand then
2345         if Pref.VisibleGhostsList.IndexOf(SakuraSeeker[i].Name) < 0 then
2346         begin
2347           Inc(HiddenCount);
2348           Continue;
2349         end;
2350       if cbxTargetGhost.Items.IndexOf(SakuraSeeker[i].Name) < 0 then
2351         cbxTargetGhost.Items.Add(SakuraSeeker[i].Name);
2352     end;
2353     cbxTargetGhost.ItemIndex := 0;
2354     if (Length(Selected) > 0) and (Selected <> ChannelDefault) then begin
2355       with cbxTargetGhost do begin
2356         for i := 1 to Items.Count-1 do begin
2357           if Items[i] = Selected then
2358             ItemIndex := i;
2359         end;
2360         //\83S\81[\83X\83g\82ª\93Ë\91R\91\8dÝ\82µ\82È\82­\82È\82Á\82½\8fê\8d\87\91Î\8dô
2361         if ItemIndex = 0 then begin
2362           Items.Add(Selected);
2363           ItemIndex := Items.Count - 1;
2364         end;
2365       end;
2366     end;
2367     if Pref.HideGhosts and not FTargetGhostExpand then
2368       Items.Add(Format('\82·\82×\82Ä(%d)...', [HiddenCount]));
2369     Items.EndUpdate;
2370   end;
2371 end;
2372
2373 {
2374 procedure TfrmSender.HTTPFailure(Sender: TObject);
2375 begin
2376   SysUtils.Beep;
2377   Beep;
2378   ShowHintLabel('SSTP Bottle\83T\81[\83o\82Æ\82Ì\90Ú\91±\82É\8e¸\94s\82µ\82Ü\82µ\82½', WarningColor);
2379   ShowMessage('SSTP Bottle\83T\81[\83o\82Æ\82Ì\90Ú\91±\82É\8e¸\94s\82µ\82Ü\82µ\82½'#13#10 +
2380     (Sender as THTTPDownloadThread).LastErrorMessage);
2381   Connecting := false;
2382 end;
2383 }
2384
2385 procedure TfrmSender.actPrevGhostExecute(Sender: TObject);
2386 var i: integer;
2387 begin
2388   SakuraSeeker.BeginDetect;
2389   UpdateIfGhostBox;
2390   i := cbxTargetGhost.ItemIndex;
2391   Dec(i);
2392   if i <= -1 then
2393   begin
2394     i := cbxTargetGhost.Items.Count-1;
2395     if Pref.HideGhosts and not FTargetGhostExpand then
2396       i := i - 1;
2397   end;
2398   cbxTargetGhost.ItemIndex := i;
2399   cbxTargetGhostChange(self);
2400 end;
2401
2402 procedure TfrmSender.actNextGhostExecute(Sender: TObject);
2403 var i: integer;
2404 begin
2405   SakuraSeeker.BeginDetect;
2406   UpdateIfGhostBox;
2407   i := cbxTargetGhost.ItemIndex;
2408   Inc(i);
2409   if Pref.HideGhosts and not FTargetGhostExpand then
2410   begin
2411     if  i > cbxTargetGhost.Items.Count-2 then i := 0;
2412   end else
2413   begin
2414     if  i > cbxTargetGhost.Items.Count-1 then i := 0;
2415   end;
2416   cbxTargetGhost.ItemIndex := i;
2417   cbxTargetGhostChange(self);
2418 end;
2419
2420 procedure TfrmSender.actResetGhostExecute(Sender: TObject);
2421 begin
2422   cbxTargetGhost.ItemIndex := 0; // (CH\90\84\8f§)\82É\96ß\82·
2423   FTargetGhostExpand := false;
2424   if Visible then memScript.SetFocus;
2425   cbxTargetGhostChange(self);
2426 end;
2427
2428 {
2429 procedure TfrmSender.timDisconnectCheckTimerTimer(Sender: TObject);
2430 begin
2431   if (IdSlpp20.LastReadTimeInterval > Pref.ReconnectWait * 60000) then begin
2432     SysUtils.Beep;
2433     frmLog.AddCurrentSystemLog('SYSTEM', 'SSTP Bottle\83T\81[\83o\82Æ\82Ì\90Ú\91±\82ª\83^\83C\83\80\83A\83E\83g\82µ\82Ü\82µ\82½');
2434     if IdSlpp20.Connected then IdSlpp20.Disconnect;
2435   end;
2436   if not IdSlpp20.Connected then begin
2437     if Added then begin
2438       Slpp20Disconnect(self); //\82È\82º\82©Disconnect\83C\83x\83\93\83g\82ª\8bN\82±\82ç\82¸\82É\90Ø\92f\82µ\82½\8fê\8d\87
2439     end else begin
2440       //\90Ø\92f\82µ\82½\82Ü\82Ü\8dÄ\90Ú\91±\82Å\82«\82¸\95ú\92u\82³\82ê\82Ä\82¢\82é\8fê\8d\87\82à\88ê\92è\8e\9e\8aÔ\92u\82«\82É\8dÄ\90Ú\91±\83g\83\89\83C
2441       //\82½\82¾\82µ\89ñ\90\94\90§\8cÀ\82 \82è
2442       RetryBeginConnect;
2443     end;
2444   end;
2445 end;
2446 }
2447
2448 {
2449 procedure TfrmSender.RetryBeginConnect;
2450 begin
2451   if FBeginConnectFailCount < 3 then begin
2452     // \90Ø\92f\82³\82ê\82Ä\82¢\82ê\82Î\8dÄ\90Ú\91±
2453     FAutoAddAfterGetChannel := true;
2454     BeginConnect;
2455   end else if FBeginConnectFailCount = 3 then begin
2456     frmLog.AddCurrentSystemLog('SYSTEM', '\8dÄ\90Ú\91±\8e©\93®\83\8a\83g\83\89\83C\82ð\92\86\8e~\82µ\82Ü\82·');
2457     frmMessageBox.ShowMessage(
2458       'SSTP Bottle\83T\81[\83o\82É\90Ú\91±\82Å\82«\82Ü\82¹\82ñ\81B'#13#10+
2459       '\83l\83b\83g\83\8f\81[\83N\82É\90Ú\91±\82µ\82Ä\82¢\82é\82±\82Æ\82ð\8am\94F\82µ\82½\8cã\82Å\81A\83`\83\83\83\93\83l\83\8b\8eQ\89Á\83{\83^\83\93\82ð\89\9f\82µ\82Ä\82­\82¾\82³\82¢\81B'#13#10+
2460       'SSTP Bottle\83T\81[\83o\82ª\83_\83E\83\93\82µ\82Ä\82¢\82é\8fê\8d\87\82Í\81A\82µ\82Î\82ç\82­\82µ\82Ä\82©\82ç\8dÄ\90Ú\91±\82µ\82Ä\82­\82¾\82³\82¢\81B'
2461     );
2462     Inc(FBeginConnectFailCount);
2463   end;
2464 end;
2465 }
2466
2467 procedure TfrmSender.actDownloadLogExecute(Sender: TObject);
2468 {
2469 var BottleLog: TBottleLogList;
2470     Title: String;
2471     Cond: TBottleLogDownloadCondition;
2472     NewIndex: integer;
2473   function TimeStr(Mins: integer): String;
2474   var day, hour, min: integer;
2475   begin
2476     day := Mins div (60 * 24);
2477     hour := (Mins div 60) mod 24;
2478     min := Mins mod 60;
2479     Result := '';
2480     if day  > 0 then Result := Result + Format('%d\93ú', [day]);
2481     if hour > 0 then Result := Result + Format('%d\8e\9e\8aÔ', [hour]);
2482     if (min  > 0) or (Result = '') then Result := Result + Format('%d\95ª', [min]);
2483   end;
2484 }
2485 begin
2486   ShowHintLabel('\83\8d\83O\82Ì\83_\83E\83\93\83\8d\81[\83h\82Í\82Å\82«\82Ü\82¹\82ñ', WarningColor);
2487 {
2488   Application.CreateForm(TfrmLogDownload, frmLogDownload);
2489   try
2490     if frmLogDownload.Execute then begin
2491       with frmLogDownload do begin
2492         if IsRange then begin
2493           if CompareDate(DateLo, DateHi) = 0 then
2494             Title := FormatDateTime('yy-mm-dd', DateLo)
2495           else
2496             Title := FormatDateTime('yy-mm-dd', DateLo) + ' - ' + FormatdateTime('yy-mm-dd', DateHi);
2497         end else begin
2498           Title := Format('\89ß\8b\8e%s', [TimeStr(RecentCount)]);
2499         end;
2500         if Channel <> '' then Title := Title + '(' + Channel + ')';
2501       end;
2502       BottleLog := TBottleLogList.Create(Title);
2503       try
2504         BottleLog.OnLoaded := frmLog.LogLoaded;
2505         BottleLog.OnLoadFailure := frmLog.LogLoadFailure;
2506         BottleLog.OnLoadWork := frmLog.LogLoadWork;
2507         with frmLogDownload do begin
2508           Cond.IsRange := IsRange;
2509           Cond.RecentCount := RecentCount;
2510           Cond.DateLo := DateLo;
2511           Cond.DateHi := DateHi;
2512           Cond.MinVote := MinVote;
2513           Cond.MinAgree := MinAgree;
2514           Cond.Channel := Channel;
2515         end;
2516         BottleLog.LoadFromWeb(Cond);
2517       except
2518         FreeAndNil(BottleLog);
2519       end;
2520       if BottleLog <> nil then begin
2521         NewIndex := frmLog.BottleLogList.Add(BottleLog);
2522         frmLog.UpdateTab;
2523         frmLog.tabBottleLog.TabIndex := NewIndex;
2524         frmLog.UpdateWindow;
2525       end;
2526     end;
2527   finally
2528     frmLogDownload.Release;
2529   end;
2530 }
2531 end;
2532
2533 function TfrmSender.BuildMenuConditionCheck(const IfGhost,
2534   Ghost: String): boolean;
2535 var i: integer;
2536     Cond: String;
2537 begin
2538   i := 0;
2539   Result := true;
2540   repeat
2541     Cond := Token(IfGhost, ',', i);
2542     if Cond <> '' then begin
2543       if Cond[1] = '!' then begin
2544         Cond := Copy(Cond, 2, High(integer));
2545         if Cond = Ghost then Result := false;
2546       end else begin
2547         if Cond <> Ghost then Result := false;
2548       end;
2549     end;
2550     Inc(i);
2551   until Cond = '';
2552 end;
2553
2554 procedure TfrmSender.BuildMenu(Root: TMenuItem; Simple: boolean);
2555 var i, j, k, count: integer;
2556     ConstData: TScriptConst;
2557     Menu1, Menu2: TMenuItem;
2558     Ghost: String;
2559 begin
2560   // Simple = false \82Ì\8fê\8d\87\82Í\83\81\83j\83\85\81[\82ð\8a®\91S\82É\8dÄ\8d\\92z\82·\82é\81B
2561   // Simple = true \82Ì\8fê\8d\87\82Í\83S\81[\83X\83g\8aÖ\8cW\82Ì\82Ý\8dÄ\8d\\92z\82·\82é\82Ì\82Å\8d\82\91¬\81B
2562   if cbxTargetGhost.ItemIndex > 0 then Ghost := cbxTargetGhost.Text
2563 //  else if FNowChannel <> '' then Ghost := ChannelList.Channel[FNowChannel].Ghost;
2564   else
2565     Ghost := '';
2566
2567   // \8aù\91\82Ì\83\81\83j\83\85\81[\8dí\8f\9c
2568   if Simple then begin
2569     // IfGhost\8fð\8c\8f\95t\82«\83\81\83j\83\85\81[\82Ì\82Ý\8dí\8f\9c
2570     for i := Root.Count-1 downto 0 do begin
2571       if ScriptConstList.GetMenuByID(Root.Items[i].Tag).IfGhost <> '' then
2572         Root.Items[i].Free;
2573     end;
2574   end else
2575     // \91S\95\94\8dí\8f\9c
2576     Root.Clear;
2577
2578   count := -1;
2579   for i := 0 to ScriptConstList.Count-1 do begin
2580     for j := 0 to ScriptConstList[i].Count-1 do begin
2581       // \83S\81[\83X\83g\88á\82¢\82Ì\8fê\8d\87\82Í\83X\83L\83b\83v
2582       if not BuildMenuConditionCheck(ScriptConstList[i][j].IfGhost, Ghost) then Continue;
2583       Inc(count);
2584       // Simple\82Ì\8fê\8d\87\82Í\8aù\82É\8aY\93\96\83\81\83j\83\85\81[\82ª\91\8dÝ\82·\82é\82±\82Æ\82ª\82 \82é\82Ì\82Å\83X\83L\83b\83v
2585       if Simple and (count < Root.Count) then
2586         if (Root.Items[count].Tag = ScriptConstList[i][j].ID) then begin
2587           Continue;
2588         end;
2589
2590       Menu1 := TMenuItem.Create(Root);
2591       with Menu1 do
2592       begin
2593         Caption := ScriptConstList[i][j].Caption;
2594         Hint    := ScriptConstList[i][j].Caption;
2595         AutoHotkeys := maManual;
2596         Tag := ScriptConstList[i][j].ID;
2597         OnClick := mnConstGroupClick;
2598       end;
2599
2600       if not Simple then begin
2601         Root.Add(Menu1);
2602       end else begin
2603         if count < Root.Count-1 then
2604           Root.Insert(count, Menu1)
2605         else
2606           Root.Add(Menu1);
2607       end;
2608
2609       Menu1.Enabled := ScriptConstList[i][j].Count > 0;
2610       for k := 0 to ScriptConstList[i][j].Count-1 do begin
2611         ConstData := ScriptConstList[i][j][k];
2612         Menu2 := TMenuItem.Create(Root);
2613         Menu2.Caption := ConstData.Caption;
2614         Menu2.Hint := ConstData.ConstText;
2615         // if ConstData.ShortCut <> 0 then Menu2.Hint := Menu2.Hint
2616         //   + ' (' + ShortCutToText(ConstData.ShortCut) + ')';
2617         // \83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[\8eÀ\8c»\82Ì\82½\82ß\8fã\8dí\8f\9c
2618         Menu2.ShortCut := ConstData.ShortCut;
2619         Menu2.OnClick := mnConstClick;
2620         Menu2.AutoHotkeys := maManual;
2621         Menu2.Tag := ConstData.ID;
2622         if (k mod 15 = 0) and (k > 0) then Menu2.Break := mbBarBreak;
2623         Menu1.Add(Menu2);
2624       end;
2625     end;
2626   end;
2627 end;
2628
2629 procedure TfrmSender.cbxTargetGhostChange(Sender: TObject);
2630 begin
2631   // \81u\82·\82×\82Ä\95\\8e¦\81v\82ð\91I\91ð\82³\82ê\82½\8fê\8d\87\82Í\83S\81[\83X\83g\91I\91ð\83{\83b\83N\83X\82ð\8dÄ\8d\\92z
2632   if Pref.HideGhosts and not FTargetGhostExpand then
2633   begin
2634     with cbxTargetGhost do
2635     begin
2636       // \88ê\94Ô\89º\82Ì\83A\83C\83e\83\80\82ª\91I\91ð\82³\82ê\82½\82Æ\82«\81B
2637       // \82½\82¾\82µItemIndex=0\82Ì\8fê\8d\87(\83S\81[\83X\83g\82ª\8bN\93®\82µ\82Ä\82¢\82È\82¢\8fê\8d\87)\82Í\97á\8aO
2638       if (ItemIndex = Items.Count-1) and (ItemIndex > 0) then
2639       begin
2640         FTargetGhostExpand := true;
2641         UpdateIfGhostBox;
2642         ItemIndex := 0;
2643         DroppedDown := true;
2644       end;
2645     end;
2646   end;
2647   // \92è\8c^\8bå\83\81\83j\83\85\81[\82ð\8dÄ\8d\\92z
2648   ConstructMenu(true);
2649   // \83v\83\8c\83r\83\85\81[\82ª\82 \82é\8fê\8d\87\82Í\83v\83\8c\83r\83\85\81[
2650   EditorPreview;
2651 end;
2652
2653 procedure TfrmSender.PlaySound(const FileName: String);
2654 begin
2655   if Pref.SilentWhenHidden and not Application.ShowMainForm then Exit;
2656   try
2657     MediaPlayer.FileName := FileName;
2658     MediaPlayer.Open;
2659     MediaPlayer.Play;
2660   except
2661     on E: EMCIDeviceError do begin
2662       ShowMessage('\83T\83E\83\93\83h\8dÄ\90\83G\83\89\81[:'#13#10 + FileName + #13#10#13#10 + E.Message);
2663     end;
2664   end;
2665 end;
2666
2667 procedure TfrmSender.actFMOExplorerExecute(Sender: TObject);
2668 begin
2669   try
2670     if not Assigned(frmFMOExplorer) then
2671       Application.CreateForm(TfrmFMOExplorer, frmFMOExplorer);
2672   except
2673     on E: Exception do
2674       ShowMessage('FMO\83G\83N\83X\83v\83\8d\81[\83\89\82ð\95\\8e¦\82Å\82«\82Ü\82¹\82ñ\81B'#13#10#13#10 +
2675         E.Message);
2676   end;
2677   frmFMOExplorer.Show;
2678 end;
2679
2680 procedure TfrmSender.SaveChainRuleList;
2681 var Str: TStringList;
2682 begin
2683   Str := TStringList.Create;
2684   try
2685     Str.Text := ComponentToString(BottleChainRuleList);
2686     Str.SaveToFile(ExtractFileDir(Application.ExeName)+'\rule.txt');
2687   finally
2688     Str.Free;
2689   end;
2690 end;
2691
2692 procedure TfrmSender.BottleSstpResendEnd(Sender: TObject; MID: String);
2693 begin
2694   frmLog.SetBottleState(MID, lsOpened);
2695 end;
2696
2697 procedure TfrmSender.BottleSstpResendTrying(Sender: TObject; MID: String);
2698 begin
2699   frmLog.SetBottleState(MID, lsPlaying);
2700 end;
2701
2702 procedure TfrmSender.actInsertCueExecute(Sender: TObject);
2703 var InsertItem: TLogItem;
2704     i, errCount, Res: integer;
2705     Log: TBottleLogList;
2706     ErrorMes: String; // \83X\83N\83\8a\83v\83g\82Ì\83G\83\89\81[\82Ì\93à\97e
2707 begin
2708   if FBottleSstp.CueCount > 0 then begin
2709     if MessageDlg(Format('\8c»\8dÝ\8dÄ\91\97\83L\83\85\81[\82É\93ü\82Á\82Ä\82¢\82é%d\8c\8f\82Ì\96¢\94z\91\97\83{\83g\83\8b\82ð\83N\83\8a\83A\82µ\82Ä\81A'+
2710       '\83\8d\83O\83E\83B\83\93\83h\83E\82É\82 \82é\83{\83g\83\8b\82ð\98A\91±\8dÄ\90\82µ\82Ü\82·\81B'#13#10+
2711       '\90V\92\85\83\81\83b\83Z\81[\83W\82Í\82»\82Ì\8cã\82É\8dÄ\90\82³\82ê\82Ü\82·\81B', [FBottleSstp.CueCount]),
2712       mtWarning, mbOkCancel, 0) = mrCancel then Exit;
2713   end;
2714   FBottleSstp.Clear;
2715   frmLog.AllBottleOpened;
2716   if frmLog.lvwLog.Selected = nil then Exit;
2717   Log := frmLog.SelectedBottleLog;
2718   if Log = nil then Exit;
2719   FBottleSSTP.OnResendCountChange := nil;
2720   errCount := 0;
2721   for i := frmLog.lvwLog.Selected.Index downto 0 do begin
2722     if (Log[i] as TLogItem).LogType <> ltBottle then Continue;
2723     InsertItem := TLogItem.Create(Log[i] as TLogItem);
2724     try
2725       //\83A\83N\83V\83\87\83\93\82ª\97L\8cø\82Å\82 \82ê\82Î\83X\83N\83\8a\83v\83g\82Ì\95Ï\8a·\82µ\82È\82¢
2726       if Pref.LogAction then
2727         ErrorMes := ''
2728       else
2729         InsertItem.Script := ScriptTransForSSTP(InsertItem.Script, ErrorMes);
2730
2731       if ErrorMes <> '' then
2732       begin
2733         Res := MessageDlg('\83X\83N\83\8a\83v\83g\82É\96â\91è\82ª\82 \82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B' +
2734           '\8dÄ\90\82µ\82Ü\82·\82©?'#13#10 + ErrorMes, mtWarning,
2735           mbYesNoCancel, 0);
2736         if Res = mrNo then
2737           raise Exception.Create('Script Syntax Error')
2738         else if Res = mrCancel then
2739         begin
2740           InsertItem.Free;
2741           FBottleSstp.Clear;
2742           frmLog.AllBottleOpened;
2743           Break;
2744         end;
2745       end;
2746       //\83A\83N\83V\83\87\83\93\82ª\97L\8cø\82Å\82 \82ê\82Î\92Ê\8fí\8f\88\97\9d\8fÈ\97ª
2747       if Pref.LogAction then
2748         //\8c^\95Ï\8a·\82Æ\8eó\90M
2749         BottleCnv(InsertItem)
2750       else
2751       begin
2752         //\83`\83\83\83\93\83l\83\8b\83S\81[\83X\83g\91Î\8dô
2753         if InsertItem.Ghost = '' then
2754           if ChannelList.Channel[InsertItem.Channel] <> nil then
2755             InsertItem.Ghost := ChannelList.Channel[InsertItem.Channel].Ghost;
2756         FBottleSSTP.Push(InsertItem);
2757         frmLog.SetBottleState(InsertItem.MID, lsUnopened);
2758       end;
2759     except
2760       InsertItem.Free;
2761       Inc(errCount);
2762     end;
2763   end;
2764   if errCount > 0 then
2765     ShowMessage(Format('%d\8c\8f\82Ì\83{\83g\83\8b\82É\96â\91è\82ª\82 \82Á\82½\82½\82ß\8dÄ\90\82Å\82«\82Ü\82¹\82ñ\81B', [errCount]));
2766   FBottleSSTP.OnResendCountChange := BottleSstpResendCountChange;
2767   BottleSstpResendCountChange(self);
2768   frmLog.lvwLog.Invalidate;
2769 end;
2770
2771 function TfrmSender.ScriptTransForSSTP(const Script: String;
2772   out Error: String): String;
2773 var TransOpt: TScriptTransOptions;
2774 begin
2775   if Pref.NoTransURL then
2776     TransOpt := [toConvertURL, toNoChoice, toWaitScriptEnd]
2777   else
2778     TransOpt := [toConvertURL, toWaitScriptEnd];
2779   if Pref.IgnoreFrequentYenS then TransOpt := TransOpt + [toIgnoreFrequentYenS];
2780   if Pref.FixMessySurface then TransOpt := TransOpt + [toFixMessySurface];
2781   if Pref.HUTagTo01Tag then TransOpt := TransOpt + [toHUTagTo01Tag];
2782   Result := Script;
2783   Error := DoTrans(Result, TransOpt);
2784 end;
2785
2786 procedure TfrmSender.FormResize(Sender: TObject);
2787 var w: integer;
2788 begin
2789   // \83G\83f\83B\83^\81[\95\94\95ª\82Ì\83\8f\81[\83h\83\89\83b\83v\95\9d\82ð\92²\90®\82·\82é
2790   if memScript.ColWidth <> 0 then
2791   begin
2792     with memScript do
2793     begin
2794       w := Width - LeftMargin - ColWidth div 2;
2795       if ScrollBars in [ssVertical, ssBoth] then
2796         w := w - GetSystemMetrics(SM_CYVSCROLL);
2797       WrapOption.WrapByte := w div ColWidth;
2798     end;
2799   end;
2800 end;
2801
2802 procedure TfrmSender.actCopyExecute(Sender: TObject);
2803 begin
2804   memScript.CopyToClipboard;
2805 end;
2806
2807 procedure TfrmSender.actPasteExecute(Sender: TObject);
2808 begin
2809   memScript.PasteFromClipboard;
2810 end;
2811
2812 procedure TfrmSender.actCutExecute(Sender: TObject);
2813 begin
2814   memScript.CutToClipboard;
2815 end;
2816
2817 procedure TfrmSender.actSelectAllExecute(Sender: TObject);
2818 begin
2819   memScript.SelectAll;
2820 end;
2821
2822 procedure TfrmSender.actUndoExecute(Sender: TObject);
2823 begin
2824   memScript.Undo;
2825 end;
2826
2827 procedure TfrmSender.actRedoExecute(Sender: TObject);
2828 begin
2829   memScript.Redo;
2830 end;
2831
2832 function TfrmSender.IsSurfaceTag(const Script: String;
2833   var ID: integer): boolean;
2834 begin
2835   Result := false;
2836   if SsParser.Match(Script, '\s%d') = 3 then
2837   begin
2838     Result := true;
2839     ID := Ord(Script[3]) - Ord('0')
2840   end
2841   else if (Length(Script) > 0) and (SsParser.Match(Script, '\s[%D]') = Length(Script)) then
2842   begin
2843     Result := true;
2844     ID := StrToIntDef(SsParser.GetParam(Script, 1), 0);
2845   end;
2846 end;
2847
2848 procedure TfrmSender.memScriptMouseMove(Sender: TObject;
2849   Shift: TShiftState; X, Y: Integer);
2850 var id: integer;
2851     token: String;
2852 begin
2853   // \95Ò\8fW\83E\83B\83\93\83h\83E\82Å\83}\83E\83X\83|\83C\83\93\83g\82·\82é\82Æ\83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[
2854   if not Pref.SurfacePreviewOnScriptPoint then
2855     Exit;
2856   token := memScript.TokenStringFromPos(Point(X, Y));
2857   if IsSurfaceTag(token, id) then
2858   begin
2859     DoSurfacePreview(id, spEditor);
2860   end else
2861   begin
2862     frmSurfacePreview.HideAway;
2863   end;
2864 end;
2865
2866 procedure TfrmSender.DoSurfacePreview(Surface: integer;
2867   const Kind: TSurfacePreviewType);
2868 var Ghost: String;
2869     Bmp: TBitmap;
2870     CPos: TPoint;
2871 begin
2872   if cbxTargetGhost.ItemIndex > 0 then
2873     ghost := cbxTargetGhost.Text
2874   else
2875     ghost := '';
2876 {  \8eè\93®\82Ì\82Í\82¸
2877   else if FNowChannel <> '' then
2878     ghost := ChannelList.Channel[FNowChannel].Ghost;
2879 }
2880
2881   // \93ñ\8fd\95\\8e¦\82Ì\97}\90§
2882   if (FVisiblePreviewGhost = Ghost) and (FVisiblePreviewSurface = Surface) and
2883     not (frmSurfacePreview.IsHidden) then
2884   begin
2885     Exit;
2886   end;
2887
2888   if ghost <> '' then
2889   begin
2890     Bmp := TBitmap.Create;
2891     try
2892       if Spps.TryGetImage(ghost, Surface, Bmp) then
2893       begin
2894         case Kind of
2895           spHint:
2896             CPos := GetSurfacePreviewPositionHint(Bmp.Width, Bmp.Height);
2897           spEditor:
2898             CPos := GetSurfacePreviewPositionScriptPoint(Bmp.Width, Bmp.Height);
2899           else
2900             CPos := Point(0, 0);
2901         end;
2902         frmSurfacePreview.ShowPreview(Bmp, CPos.X, CPos.Y);
2903         FVisiblePreviewGhost := Ghost;
2904         FVisiblePreviewSurface := Surface;
2905       end else
2906         frmSurfacePreview.HideAway;
2907     finally
2908       Bmp.Free;
2909     end;
2910   end;
2911 end;
2912
2913 function TfrmSender.GetSurfacePreviewPositionHint(w, h: integer): TPoint;
2914 {var MousePoint: TPoint;
2915     MenuRect: TRect;}
2916 begin
2917   // \83T\81[\83t\83B\83X\83v\83\8c\83r\83\85\81[\83E\83B\83\93\83h\83E\82Ì\95\\8e¦\88Ê\92u\82ð\8c\88\92è\82·\82é
2918   // \91\97\90M\83E\83B\83\93\83h\83E\82Ì\88Ê\92u\82É\82æ\82Á\82Ä\82Í\96­\82È\82Æ\82±\82ë\82É\83\81\83j\83\85\81[\82ª\95\\8e¦\82³\82ê\82Ä\82¢\82é\82Ì\82Å
2919   // \88Ä\8aO\82â\82â\82±\82µ\82¢
2920   {GetCursorPos(MousePoint);
2921   OutputDebugString(PChar(IntToStr(FVisibleMenuItem.Count)));
2922   //if GetMenuItemRect(Self.Handle, FVisibleMenuItem.Items[0].Handle, 1, MenuRect) then ;
2923   Result := Point(MenuRect.Left-10, MenuRect.Top-10);}
2924   Result := GetSurfacePreviewPositionScriptPoint(w, h);
2925 end;
2926
2927 function TfrmSender.GetSurfacePreviewPositionScriptPoint(w, h: integer): TPoint;
2928 var MousePoint: TPoint;
2929 begin
2930   GetCursorPos(MousePoint);
2931   case Pref.SurfacePreviewOnScriptPointPosition of
2932     spspMainWindowRight:
2933       Result := Point(Self.Left + Self.Width, MousePoint.Y);
2934   else
2935       Result := Point(Self.Left - w, MousePoint.Y);
2936   end;
2937 end;
2938
2939 procedure TfrmSender.mnConstGroupClick(Sender: TObject);
2940 begin
2941   if (Sender is TMenuItem) then
2942     FVisibleMenuItem := Sender as TMenuItem;
2943 end;
2944
2945 procedure TfrmSender.actRecallScriptBufferExecute(Sender: TObject);
2946 begin
2947   if FScriptBuffer.Count = 0 then
2948     Exit;
2949   memScript.Lines.Assign(FScriptBuffer[0] as TStringList);
2950   EditerStatusChange;
2951   ShowHintLabel('\83X\83N\83\8a\83v\83g\82ð\8cÄ\82Ñ\8fo\82µ\82Ü\82µ\82½');
2952 end;
2953
2954 procedure TfrmSender.EditorPreview;
2955 var Ghost, Script: String;
2956 begin
2957   if frmEditorTalkShow <> nil then
2958     if frmEditorTalkShow.Visible then
2959     begin
2960       Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]);
2961       Ghost := '';
2962       if cbxTargetGhost.ItemIndex > 0 then
2963         Ghost := cbxTargetGhost.Text;
2964\8eè\93®\82Å\8ew\92è\82³\82ê\82é
2965       else if FNowChannel <> '' then
2966         Ghost := ChannelList.Channel[FNowChannel].Ghost;
2967 }
2968       frmEditorTalkShow.TalkShowFrame.View(Script, Ghost);
2969     end;
2970 end;
2971
2972 procedure TfrmSender.actEditorPreviewExecute(Sender: TObject);
2973 begin
2974   if frmEditorTalkShow <> nil then
2975     frmEditorTalkShow.Show
2976   else
2977   begin
2978     Application.CreateForm(TfrmEditorTalkShow, frmEditorTalkShow);
2979     frmEditorTalkShow.Show;
2980   end;
2981   EditorPreview;
2982 end;
2983
2984 // \83v\83\89\83O\83C\83\93\83\8a\83Z\83b\83g
2985 procedure TfrmSender.actResetPluginsExecute(Sender: TObject);
2986 begin
2987   Spps.ClearImagePool;
2988   Spps.LoadFromDirectory(FSppDir);
2989 end;
2990
2991 {
2992 procedure TfrmSender.IdSLPP20Connect(Sender: TObject);
2993 begin
2994   ShowHintLabel('SSTP Bottle\83T\81[\83o\82ª\8c©\82Â\82©\82è\82Ü\82µ\82½');
2995 end;
2996 }
2997
2998 // \83X\83N\83\8a\83v\83g\92\86\82Ì\83^\83O\82ð\92u\8a·\82·\82é
2999 // \83T\83C\83Y\89Â\95Ï\82Ì\94z\97ñ\83p\83\89\83\81\81[\83^\94Å
3000 function TfrmSender.TagReplace(Script: String; Before,
3001   After: array of String): String;
3002 var BeforeList, AfterList: TStringList;
3003     i: integer;
3004 begin
3005   BeforeList := TStringList.Create;
3006   AfterList  := TStringList.Create;
3007   try
3008     for i := Low(Before) to High(Before) do
3009       BeforeList.Add(Before[i]);
3010     for i := Low(After) to High(After) do
3011       AfterList.Add(After[i]);
3012     Result := TagReplace(Script, BeforeList, AfterList);
3013   finally
3014     BeforeList.Free;
3015     AfterList.Free;
3016   end;
3017 end;
3018
3019 // \83X\83N\83\8a\83v\83g\92\86\82Ì\83^\83O\82ð\92u\8a·\82·\82é
3020 // StringReplace\82Æ\88á\82Á\82Ä\90³\8am\82É\83^\83O\82É\83}\83b\83`\82µ\81A
3021 // \82Ü\82½\83p\83^\81[\83\93\82ð\95¡\90\94\8ew\92è\82Å\82«\82é(\92u\8a·\8cã\82Ì\8c\8b\89Ê\82ª\82Ü\82½\92u\8a·\82³\82ê\82½\82è\82µ\82È\82¢)
3022 function TfrmSender.TagReplace(Script: String; Before,
3023   After: TStrings): String;
3024 var i, j: integer;
3025     Flag, OldLeaveEscape, OldEscapeInvalidMeta: boolean;
3026     OldStr: String;
3027 begin
3028   Result := '';
3029   with SsParser do
3030   begin
3031     OldStr := InputString;
3032     OldLeaveEscape := LeaveEscape;
3033     OldEscapeInvalidMeta := EscapeInvalidMeta;
3034     LeaveEscape := true;
3035     EscapeInvalidMeta := false;
3036     InputString := Script;
3037   end;
3038   for i := 0 to SsParser.Count-1 do
3039   begin
3040     Flag := false;
3041     for j := 0 to Before.Count-1 do
3042     begin
3043       if (SsParser.MarkUpType[i] = mtTag) and (SsParser[i] = Before[j]) then
3044       begin
3045         Flag := true;
3046         Result := Result + After[j];
3047       end;
3048     end;
3049     if not Flag then
3050       Result := Result + SsParser[i];
3051   end;
3052   with SsParser do
3053   begin
3054     LeaveEscape := OldLeaveEscape;
3055     EscapeInvalidMeta := OldEscapeInvalidMeta;
3056     InputString := OldStr;
3057   end;
3058 end;
3059
3060 // WndProc\82ð\83I\81[\83o\81[\83\89\83C\83h\82µ\82Ä\81AFWM_TaskBarCraeted\82É
3061 // \91Î\89\9e\82·\82é
3062 procedure TfrmSender.WndProc(var Message: TMessage);
3063 begin
3064   if (Message.Msg = FWM_TaskBarCreated) and (FWM_TaskBarCreated <> 0) then
3065   begin
3066     TaskTray.Registered := false; // TTaskTray\82É\83^\83X\83N\83g\83\8c\83C\82ª\8fÁ\82¦\82½\82±\82Æ\82ð
3067                                   // \8bC\82Ã\82©\82¹\82é
3068     ChangeTaskIcon;
3069   end
3070   else
3071     inherited;
3072 end;
3073
3074 // \92u\8a·
3075 procedure TfrmSender.actReplaceExecute(Sender: TObject);
3076 var
3077   Form: TfrmStrReplaceDialog;
3078   Lines: String;
3079   Options: TReplaceFlags;
3080 begin
3081   Application.CreateForm(TfrmStrReplaceDialog, Form);
3082   try
3083     if Form.Execute then
3084     begin
3085       with Form.Pair do
3086       begin
3087         Lines := memScript.Lines.Text;
3088         Options := [rfReplaceAll];
3089         if IgnoreCase then
3090           Options := Options + [rfIgnoreCase];
3091         if UseRegExp then
3092           Lines := StringReplaceRegExp(Lines, BeforeStr, AfterStr, Options)
3093         else
3094           Lines := StringReplace(Lines, BeforeStr, AfterStr, Options);
3095       end;
3096       if Lines <> memScript.Lines.Text then
3097       begin
3098         memScript.SelectAll;
3099         memScript.SelText := Lines;
3100       end;
3101     end;
3102   finally
3103     Form.Release;
3104   end;
3105 end;
3106
3107 procedure TfrmSender.actSendToEditorExecute(Sender: TObject);
3108 var Log: TLogItem;
3109 begin
3110   if frmLog.lvwLog.Selected = nil then Exit;
3111   Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem;
3112   if Log = nil then Exit;
3113   CopyFromLogToEditor(Log);
3114 end;
3115
3116 procedure TfrmSender.actSendToLogWindowExecute(Sender: TObject);
3117 var Ghost, Script: String;
3118 begin
3119   YenETrans;
3120   Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]);
3121   if cbxTargetGhost.ItemIndex > 0 then
3122     Ghost := cbxTargetGhost.Text
3123   else
3124     Ghost := '';
3125   frmLog.AddCurrentScriptLog('\83N\83\8a\83b\83v', Script, ClipChannel, '', Ghost, Now(), 0, 0);
3126   ClearEditor;
3127 end;
3128
3129 procedure TfrmSender.memScriptDragOver(Sender, Source: TObject; X,
3130   Y: Integer; State: TDragState; var Accept: Boolean);
3131 begin
3132   // \83\8d\83O\83E\83B\83\93\83h\83E\82©\82ç\82Ì\83\8d\83O\83A\83C\83e\83\80\82Ì\92¼\90ÚD&D\82ð\8b\96\89Â\82·\82é
3133   if Source is TBottleLogDragObject then
3134     Accept := (Source as TBottleLogDragObject).LogItem.LogType = ltBottle
3135 end;
3136
3137 procedure TfrmSender.memScriptDragDrop(Sender, Source: TObject; X,
3138   Y: Integer);
3139 var Src: TBottleLogDragObject;
3140     Log: TLogItem;
3141 begin
3142   // \83\8d\83O\83E\83B\83\93\83h\83E\82©\82ç\83\8d\83O\83A\83C\83e\83\80\82ðD&D\82µ\82Ä\82­\82é
3143   if not (Source is TBottleLogDragObject) then
3144     Exit;
3145   if (Source as TBottleLogDragObject).LogItem.LogType <> ltBottle then
3146     Exit;
3147   Src := Source as TBottleLogDragObject;
3148   Log := Src.LogItem;
3149   CopyFromLogToEditor(Log);
3150 end;
3151
3152 procedure TfrmSender.CopyFromLogToEditor(Log: TLogItem);
3153 var
3154   Ghost: string;
3155 begin
3156   if Log.LogType <> ltBottle then Exit;
3157   frmSender.actClear.Execute; // \8c»\8dÝ\82Ì\83X\83N\83\8a\83v\83g\82ð\83N\83\8a\83b\83v\82·\82é(\90Ý\92è\82É\82æ\82Á\82Ä)
3158   memScript.Lines.Clear;
3159   memScript.Lines.Add(Log.Script);
3160   SetFileName(Log.MID, false);  //\83^\83C\83g\83\8b\82¾\82¯\95Ï\8dX
3161   SetFileModified(false);       //\95Ï\8dX\96³\82µ\82É
3162   Ghost := Log.Ghost;
3163   //\83`\83\83\83\93\83l\83\8b\83S\81[\83X\83g\91Î\8dô
3164   if Ghost = '' then
3165     if ChannelList.Channel[Log.Channel] <> nil then
3166       Ghost := ChannelList.Channel[Log.Channel].Ghost;
3167   if Ghost <> '' then
3168   begin
3169     // \83S\81[\83X\83g\96¼\82ð\83{\83b\83N\83X\82É\93ü\82ê\82é
3170     // \96³\97\9d\96î\97\9d\83S\81[\83X\83g\96¼\82ð\92Ç\89Á\82µ\82Ä\82©\82ç\8dÄ\8d\\92z\82·\82é\82±\82Æ\82Å
3171     // \96³\97\9d\96î\97\9d\83S\81[\83X\83g\96¼\82ª\83{\83b\83N\83X\82É\93ü\82é
3172     cbxTargetGhost.Items.Add(Ghost);
3173     cbxTargetGhost.ItemIndex := cbxTargetGhost.Items.Count-1;
3174     UpdateIfGhostBox;
3175     cbxTargetGhost.Invalidate;
3176   end else
3177     cbxTargetGhost.ItemIndex := 0; // 'CH\90\84\8f§'\82É\82·\82é
3178   memScript.SetFocus;
3179 end;
3180
3181 procedure TfrmSender.actDeleteLogItemExecute(Sender: TObject);
3182 begin
3183   // \83\8d\83O\83E\83B\83\93\83h\83E\82Ì\8cÂ\95Ê\83\8d\83O\82ð\8dí\8f\9c\82·\82é
3184   if frmLog.SelectedBottleLog = nil then
3185     Exit;
3186   if frmLog.lvwLog.Selected = nil then
3187     Exit;
3188   frmLog.SelectedBottleLog.Delete(frmLog.lvwLog.Selected.Index);
3189   frmLog.UpdateWindow;
3190   frmLog.lvwLogChange(Self, nil, ctState);
3191   frmLog.SelectedBottleLog.LogModified := true; // \95Ï\8dX\82³\82ê\82½
3192 end;
3193
3194 procedure TfrmSender.ClearEditor;
3195 var TmpScript: String;
3196     Position: Integer;
3197     DoSaveBuffer: boolean;
3198     SavedScript: TStringList;
3199 begin
3200   //\90Ý\92è\82É\82æ\82è\83N\83\8a\83A\8e\9e\82É\83t\83@\83C\83\8b\83Z\81[\83u\82·\82é\82©\8am\94F\82·\82é
3201   if NOT Pref.NotCheckClear then
3202     if CheckFileSave(Self) = idCancel then exit;
3203   // \83X\83N\83\8a\83v\83g\82Ì\83N\83\8a\83A
3204   // \82Ü\82¸\81A\83X\83N\83\8a\83v\83g\83N\83\8a\83A\83o\83b\83t\83@\82É\8c»\8dÝ\82Ì\83X\83N\83\8a\83v\83g\82ð\95Û\91\82·\82é
3205   DoSaveBuffer := false;
3206   if FScriptBuffer.Count = 0 then
3207     DoSaveBuffer := true
3208   else if (FScriptBuffer[0] as TStringList).Text <> GetScriptText then
3209     DoSaveBuffer := true;
3210   if (GetScriptText = Pref.DefaultScript) or (GetScriptText = '') then
3211     DoSaveBuffer := false;
3212   if DoSaveBuffer then
3213   begin
3214     SavedScript := TStringList.Create;
3215     SavedScript.Text := GetScriptText;
3216     FScriptBuffer.Insert(0, SavedScript);
3217   end;
3218   if FScriptBuffer.Count >= 4 then
3219     FScriptBuffer.Delete(FScriptBuffer.Count-1);
3220   actRecallScriptBuffer.Enabled := FScriptBuffer.Count > 0;
3221
3222   TmpScript := Pref.DefaultScript;
3223   Position := Pos('|', TmpScript);
3224   if Position < 1 then Position := 1;
3225   TmpScript := StringReplace(TmpScript, '|', '', []);
3226   memScript.Lines.Text := TmpScript;
3227   Sendmessage(memScript.Handle, WM_VSCROLL, SB_LINEUP, 0);
3228   memScript.SelStart := Position-1;
3229
3230   if Visible then memScript.SetFocus;
3231 //  FScriptModified := false;
3232   FScriptBackModified := false; //\8e©\93®\95Û\91\88ê\8e\9e\92â\8e~
3233   SetFileName(NewFileTitle, true);    //\83t\83@\83C\83\8b\82ð\90V\8bK\88µ\82¢\82É\82·\82é
3234   SetFileModified(false);       //
3235   EditerStatusChange;           //\83X\83e\81[\83^\83X\8dX\90V
3236 end;
3237
3238 procedure TfrmSender.AppendTextLog(const FileName, Line: String);
3239 var
3240   F: TextFile;
3241 begin
3242   //\91\97\90M\83\8d\83O\95Û\91
3243   try
3244     ForceDirectories(ExtractFileDir(FileName));
3245     AssignFile(F, FileName);
3246     if FileExists(FileName) then
3247       Append(F)
3248     else
3249       Rewrite(F);
3250     WriteLn(F, Line);
3251     Flush(F);
3252     CloseFile(F);
3253   except
3254     on E: Exception do
3255       frmLog.AddCurrentSystemLog('SYSTEM', '\83e\83L\83X\83g\83\8d\83O\95Û\91\82É\8e¸\94s\81F'+E.Message);
3256   end;
3257 end;
3258
3259 procedure TfrmSender.AppendXMLLog(const FileName: String; Args: THeadValue);
3260 var
3261   F: TFileStream;
3262   Buf: String;
3263   P: integer;
3264   Impl: TDomImplementation;
3265   Parser: TXmlToDomParser;
3266   DOM: TdomDocument;
3267 begin
3268   try // Long try block to handle all kinds of exception in this method
3269     if not FileExists(FileName) then
3270     begin
3271       // Create empty XML log file
3272       Impl := TDomImplementation.create(nil);
3273       try
3274         ForceDirectories(ExtractFileDir(FileName));
3275         Parser := TXmlToDomParser.create(nil);
3276         Parser.DOMImpl := Impl;
3277         try
3278           try
3279             DOM := Parser.fileToDom(ExtractFilePath(Application.ExeName)+'xbtl.dat');
3280             with DOM do
3281             begin
3282               documentElement.setAttribute('saved',
3283                 FormatDateTime('yy/mm/dd hh:nn:ss', Now));
3284               documentElement.setAttribute('generator', VersionString);
3285               documentElement.setAttribute('version', '1.0');
3286             end;
3287             // \82±\82ê\82Í\96¾\8e¦\93I\82ÉFree\82µ\82È\82­\82Ä\82æ\82¢
3288             F := TFileStream.Create(FileName, fmCreate or fmShareExclusive);
3289             try
3290               DOM.writeCodeAsShiftJIS(F);
3291             finally
3292               F.Free;
3293             end;
3294           except
3295             frmLog.AddCurrentSystemLog('SYSTEM', 'XML\83\8d\83O\95Û\91\82É\8e¸\94s\82µ\82Ü\82µ\82½');
3296           end;
3297         finally
3298           Parser.DOMImpl.freeDocument(DOM);
3299           Parser.Free;
3300         end;
3301       finally;
3302         Impl.Free;
3303       end;
3304     end;
3305     F := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive);
3306     try
3307       P := -11;
3308       SetLength(Buf, 12);
3309       while P > -100 do
3310       begin
3311         F.Seek(P, soFromEnd);
3312         F.Read(Buf[1], 12);
3313         if Buf = '</bottlelog>' then
3314           Break;
3315         Dec(P);
3316       end;
3317       if P = -100 then
3318         raise Exception.Create(FileName + ' is not a valid XML bottle log file')
3319       else
3320       begin
3321         F.Seek(P, soFromEnd);
3322         Buf := Format('<message mid="%s">', [Args['MID']]);
3323         Buf := Buf + Format('<date>%s</date>', [FormatDateTime('yy/mm/dd hh:nn:ss', Now)]);
3324         Buf := Buf + Format('<channel>%s</channel>', [XMLEntity(Args['Channel'])]);
3325         Buf := Buf + Format('<script>%s</script>', [XMLEntity(Args['Script'])]);
3326         Buf := Buf + '<votes>0</votes><agrees>0</agrees>';
3327         Buf := Buf + Format('<ghost>%s</ghost>', [XMLEntity(Args['IfGhost'])]);
3328         Buf := Buf + '</message>';
3329         Buf := Buf + '</bottlelog>';
3330         F.Write(Buf[1], Length(Buf));
3331       end;
3332     finally
3333       F.Free;
3334     end;
3335   except
3336     on E: Exception do
3337       frmLog.AddCurrentSystemLog('SYSTEM', 'XML\83\8d\83O\95Û\91\82É\8e¸\94s\82µ\82Ü\82µ\82½:'+E.Message);
3338   end;
3339 end;
3340
3341 procedure TfrmSender.memScriptSelectionChange(Sender: TObject;
3342   Selected: Boolean);
3343 var
3344   SelText: String;
3345 begin
3346   SelText := memScript.SelText;
3347   if SelText <> '' then
3348   begin
3349     StatusBar.Panels[PanelBytes].Text := Format('(%d\83o\83C\83g)', [Length(SelText)]);
3350   end else
3351   begin
3352     EditerStatusChange;
3353   end;
3354 end;
3355
3356 function TfrmSender.ReplaceSurface(Script: String;
3357   Params: TCollection): String;
3358 var
3359   Flag, OldLeaveEscape, OldEscapeInvalidMeta: boolean;
3360   OldStr, Tag: String;
3361   i, j, k, Cur: integer;
3362   Item: TSurfaceReplaceItem;
3363   Before: TSurfaceReplaceBeforeItem;
3364 begin
3365   Result := '';
3366   Cur := 0;
3367   with SsParser do
3368   begin
3369     OldStr := InputString;
3370     OldLeaveEscape := LeaveEscape;
3371     OldEscapeInvalidMeta := EscapeInvalidMeta;
3372     LeaveEscape := true;
3373     EscapeInvalidMeta := false;
3374     InputString := Script;
3375   end;
3376   for i := 0 to SsParser.Count-1 do
3377   begin
3378     if SsParser.MarkUpType[i] <> mtTag then
3379     begin
3380       Result := Result + SsParser.Str[i];
3381       Continue;
3382     end;
3383     Tag := SsParser.Str[i];
3384     if SsParser.Match(Tag, '\s%d') = 2 then
3385       Cur := Ord(Tag[3]) - Ord('0')
3386     else if SsParser.Match(Tag, '\s[%D]') > 0 then
3387       Cur := StrToInt(SsParser.GetParam(Tag, 1))
3388     else
3389     begin
3390       Result := Result + Tag;
3391       Continue;
3392     end;
3393     Flag := false;
3394     for j := 0 to Params.Count-1 do
3395     begin
3396       Item := Params.Items[j] as TSurfaceReplaceItem;
3397       for k := 0 to Item.Before.Count-1 do
3398       begin
3399         Before := Item.Before.Items[k] as TSurfaceReplaceBeforeItem;
3400         if (Cur >= Before.FromNo) and (Cur <= Before.ToNo) then
3401         begin
3402           Flag := true;
3403           Result := Result + Format('\s[%d]', [Item.After]);
3404           Break;
3405         end;
3406       end;
3407       if Flag then
3408         Break;
3409     end;
3410     if not Flag then
3411       Result := Result + Tag;
3412   end;
3413   with SsParser do
3414   begin
3415     LeaveEscape := OldLeaveEscape;
3416     EscapeInvalidMeta := OldEscapeInvalidMeta;
3417     InputString := OldStr;
3418   end;
3419 end;
3420
3421 procedure TfrmSender.WMQueryEndSession(var msg: TWMQueryEndSession);
3422 begin
3423   // Windows\82ª\8fI\97¹\82µ\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\82Ì\82ð\8a´\92m\82·\82é
3424   FEndSession := true;
3425   inherited;
3426 end;
3427
3428 {
3429 procedure TfrmSender.IdSLPP20ConnectFailed(Sender: TObject);
3430 begin
3431   Added := false;
3432   if FBeginConnectFailCount = 0 then
3433   begin
3434     Beep;
3435     if Pref.UseHttpProxy then
3436       ShowMessage('HTTP Proxy\82ð\92Ê\82\82ÄSSTP Bottle\83T\81[\83o\82É\90Ú\91±\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B'#13#10 +
3437                   '\83l\83b\83g\83\8f\81[\83N\82Ì\8fó\91Ô\81EProxy\82Ì\8fó\91Ô\82ð\8am\94F\82µ\82Ä\82­\82¾\82³\82¢\81B'#13#10 +
3438                   '\82 \82é\82¢\82Í\83T\81[\83o\82ª\83_\83E\83\93\82µ\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B')
3439     else
3440       ShowMessage('SSTP Bottle\83T\81[\83o\82É\90Ú\91±\82Å\82«\82Ü\82¹\82ñ\82Å\82µ\82½\81B'#13#10 +
3441                   '\83l\83b\83g\83\8f\81[\83N\82É\8cq\82ª\82Á\82Ä\82¢\82é\82©\8am\94F\82µ\82Ä\82­\82¾\82³\82¢\81B'#13#10 +
3442                   '\82 \82é\82¢\82Í\83T\81[\83o\82ª\83_\83E\83\93\82µ\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B');
3443   end;
3444   ShowHintLabel('SSTP Bottle Server\90Ú\91±\82É\8e¸\94s\82µ\82Ü\82µ\82½', WarningColor);
3445   Inc(FBeginConnectFailCount);
3446 end;
3447 }
3448
3449 procedure TfrmSender.BuildReplaceMenu(Root: TMenuItem);
3450 var
3451   i: integer;
3452   Presets: TReplacePresetCollection;
3453   NewItem: TMenuItem;
3454 begin
3455   Root.Clear;
3456   Presets := Pref.ReplacePresets.Presets;
3457   for i := 0 to Presets.Count-1 do
3458   begin
3459     NewItem := TMenuItem.Create(Root);
3460     with NewItem do
3461     begin
3462       Caption := Presets[i].Title;
3463       ShortCut := Presets[i].ShortCut;
3464       AutoHotkeys := maManual;
3465       Hint := Presets[i].Pairs.StringExpression;
3466       Tag := i;
3467       OnClick := mnPresetReplaceClick;
3468     end;
3469     Root.Add(NewItem);
3470   end;
3471   Root.Enabled := Presets.Count > 0;
3472 end;
3473
3474 procedure TfrmSender.mnPresetReplaceClick(Sender: TObject);
3475 var
3476   Preset: TReplacePreset;
3477   Lines, New: string;
3478 begin
3479   // \83v\83\8a\83Z\83b\83g\92u\8a·\82ð\8eÀ\8ds
3480   Preset := Pref.ReplacePresets.Presets[(Sender as TMenuItem).Tag];
3481   Lines := memScript.Lines.Text;
3482   New := Preset.Pairs.ExecuteReplace(Lines);
3483   if New <> Lines then
3484   begin
3485     memScript.SelectAll;
3486     memScript.SelText := New;
3487   end;
3488   if Preset.ConfirmAfterReplace then
3489   begin
3490     btnConfirm.Click;
3491   end;
3492 end;
3493
3494 procedure TfrmSender.BottleCnv(Log: TLogItem);
3495 var
3496   HeadValue: THeadValue;
3497 begin
3498   //HeadValue\8c^\82Ö
3499   HeadValue := THeadValue.Create;
3500   HeadValue['MID'] := Log.MID;
3501   HeadValue['Channel'] := Log.Channel;
3502   HeadValue['SEND'] := 'SSTP/1.4';
3503   HeadValue['Sender'] := 'SSTP Bottle ' + Log.Channel;
3504   HeadValue['IfGhost'] := Log.Ghost;
3505   HeadValue['Script'] := Log.Script;
3506   HeadValue['Charset'] := 'Shift_JIS';
3507 //  HeadValue['DialogMessage'] := Log.Script;
3508   try
3509     //\83\81\83b\83Z\81[\83W\8eó\90M\8f\88\97\9d\82Ö
3510     DispatchBottle(HeadValue, Log.LogTime, Log.Votes, Log.Agrees);
3511   finally
3512     HeadValue.Free;
3513   end;
3514 end;
3515
3516 procedure TfrmSender.SetScriptAutoBackUp;
3517 begin
3518   //\83o\83b\83N\83A\83b\83v\83^\83C\83}\81[\82Ö\92l\82Ì\83Z\83b\83g
3519   frmSender.ScriptBackUp.Enabled := Pref.ScriptBackUp;
3520   frmSender.ScriptBackUp.Interval := Pref.ScriptBackUpTime * 60000;
3521 end;
3522
3523 procedure TfrmSender.ScriptBackUpTimer(Sender: TObject);
3524 var
3525   Script: string;
3526 begin
3527   //\83X\83N\83\8a\83v\83g\82Ì\8e©\93®\83o\83b\83N\83A\83b\83v
3528   if FScriptBackModified then
3529   begin
3530     Script := GetScriptText;
3531     AppendTextLog(ExtractFilePath(Application.ExeName) + 'Script.bak',
3532       FormatDateTime('yy/mm/dd hh:nn:ss', Now) + #13#10 + Script);
3533     ShowHintLabel('\83o\83b\83N\83A\83b\83v\8eÀ\8ds');
3534     FScriptBackModified := False;
3535   end;
3536 end;
3537
3538 procedure TfrmSender.UpdateChannelList;
3539 var
3540   Ch: TChannelListItem;
3541   i: integer;
3542 begin
3543   //\83`\83\83\83\93\83l\83\8b\83S\81[\83X\83g\92è\8b`
3544   ChannelList.Clear;
3545   //\83t\83\89\83O\82ð\8c©\82Ä\94»\92f
3546   if NOT Pref.GhostCh then exit;
3547   //if (Pref.GhostChList.Count mod 2) = 1 then Pref.GhostChList.Add('');
3548   i := 0;
3549   while i < Pref.GhostChList.Count-1 do
3550   begin
3551     Ch := TChannelListItem.Create;
3552     Ch.Name    := Pref.GhostChList.Strings[i];
3553     Ch.Ghost   := Pref.GhostChList.Strings[i+1];
3554     Ch.Info    := '';
3555     Ch.NoPost  := false;
3556     Ch.Members := 0;
3557     Ch.WarnPost:= false;
3558     ChannelList.Add(Ch);
3559     i := i + 2;
3560   end;
3561 end;
3562
3563 procedure TfrmSender.UpdateJoinChannelList;
3564 begin
3565   UpdateChannelList;  //\83`\83\83\83\93\83l\83\8b\90Ý\92è
3566   with tabChannel do
3567   begin
3568     OnChange := nil;
3569     Tabs.BeginUpdate;
3570     Tabs.Clear;
3571     Tabs.EndUpdate;
3572     actSend.Hint := Format('\91\97\90M|%s', [SendButtonLongHint]);
3573     actNextChannel.Enabled := false;
3574     actPrevChannel.Enabled := false;
3575     OnChange := tabChannelChange;
3576   end;
3577 end;
3578
3579 procedure TfrmSender.PerformFileOpen(AFileName: string);
3580 begin
3581   //\8eÀ\8dÛ\82É\83t\83@\83C\83\8b\82ð\8aJ\82­
3582   try
3583     memScript.Lines.LoadFromFile(AFileName);
3584   except
3585     on E: Exception do begin
3586       ShowMessage('\83G\83\89\81[:'#13#10#13#10 + E.Message);
3587       AFileName := NewFileTitle;
3588     end;
3589   end;
3590   SetFileName(AFileName, true);
3591   memScript.SetFocus;
3592   EditerStatusChange;
3593   SetFileModified(false);
3594 end;
3595
3596 procedure TfrmSender.actFileOpenExecute(Sender: TObject);
3597 begin
3598   //\8aJ\82­
3599   if CheckFileSave(Self) = idCancel then exit;
3600   if OpenDialog.Execute then
3601     PerformFileOpen(OpenDialog.FileName);
3602 end;
3603
3604 procedure TfrmSender.SetFileName(const FileName: String; const Value: boolean);
3605 begin
3606   //\83^\83C\83g\83\8b\95Ï\8dX\82Æ\83t\83@\83C\83\8b\83p\83X\83Z\83b\83g
3607   //\82à\82µ\81A\91æ\93ñ\88ø\90\94\82ªfalse\82È\82ç\83^\83C\83g\83\8b\82¾\82¯\95Ï\8dX
3608   if Value then FFileName := FileName;
3609   Self.Caption := Format('%s - %s', [ExtractFileName(FileName), FOriginalCaption]);
3610 end;
3611
3612 function TfrmSender.CheckFileSave(Sender: TObject): integer;
3613 var
3614   Res: integer;
3615 begin
3616   //\83t\83@\83C\83\8b\82Ì\95Ï\8dX\82ð\8am\94F
3617   //Result := idCancel\82Å\8fI\97¹\91j\8e~
3618   if FFileModified then
3619   begin
3620     Res := MessageDlg(Format('\83t\83@\83C\83\8b %s \82Í\95Ï\8dX\82³\82ê\82Ä\82¢\82Ü\82·\81B'#13#10#13#10 +
3621       '\95Û\91\82µ\82Ü\82·\82©\81H', [FFileName]), mtConfirmation, mbYesNoCancel, 0);
3622     if Res = idYes then Res := FileSave(Self);
3623   end else
3624     Res := idNo;
3625   Result := Res;
3626 end;
3627
3628 function TfrmSender.FileSave(Sender: TObject): integer;
3629 var
3630   Res: integer;
3631 begin
3632   //\8fã\8f\91\82«
3633   if FFileName = NewFileTitle then
3634     Res := FileSaveAs(Sender) //\83p\83X\96¼\82ª\8ew\92è\82³\82ê\82Ä\82¢\82È\82¢\82Ì\82Å\8fã\8f\91\82«\82Å\82«\82È\82¢
3635   else
3636   begin
3637     try
3638       memScript.Lines.SaveToFile(FFileName);
3639     except
3640       on E: Exception do
3641         ShowMessage('\83G\83\89\81[:'#13#10#13#10 + E.Message);
3642     end;
3643     SetFileModified(false);
3644     Res := idNo;
3645   end;
3646   Result := Res;
3647 end;
3648
3649 function TfrmSender.FileSaveAs(Sender: TObject): integer;
3650 var
3651   Res: integer;
3652 begin
3653   //\96¼\91O\82ð\95t\82¯\82Ä\95Û\91
3654   Res := idYes;
3655   SaveDialog.InitialDir := ExtractFileDir(Application.ExeName);
3656   if SaveDialog.Execute then
3657   begin
3658     if FileExists(SaveDialog.FileName) then
3659       Res := MessageDlg(Format('%s \82Í\8aù\82É\91\8dÝ\82µ\82Ä\82¢\82Ü\82·\81B'#13#10 + '\8fã\8f\91\82«\82µ\82Ü\82·\82©\81H',
3660         [SaveDialog.FileName]), mtConfirmation, mbYesNoCancel, 0);
3661     if Res = idYes then
3662     begin
3663       //\88È\89º\8fã\8f\91\82«\8f\88\97\9d\82Æ\93¯\82
3664       try
3665         memScript.Lines.SaveToFile(SaveDialog.FileName);
3666       except
3667         on E: Exception do
3668           ShowMessage('\83G\83\89\81[:'#13#10#13#10 + E.Message);
3669       end;
3670       SetFileName(SaveDialog.FileName, true);
3671       SetFileModified(false);
3672     end;
3673   end else
3674     Res := idCancel;
3675   Result := Res;
3676 end;
3677
3678 procedure TfrmSender.actFileSaveAsExecute(Sender: TObject);
3679 begin
3680   //\96¼\91O\82ð\95t\82¯\82Ä\95Û\91\8cÄ\82Ñ\8fo\82µ
3681   FileSaveAs(Self);
3682 end;
3683
3684 procedure TfrmSender.actFileSaveExecute(Sender: TObject);
3685 begin
3686   //\8fã\8f\91\82«\95Û\91\8cÄ\82Ñ\8fo\82µ
3687   FileSave(Self);
3688 end;
3689
3690 procedure TfrmSender.SetFileModified(const Value: boolean);
3691 begin
3692   //\83t\83@\83C\83\8b\95Ï\8dX\83t\83\89\83O\82Æ\95\\8e¦\95Ï\8dX
3693   if Value then
3694     StatusBar.Panels[PanelConnecting].Text := '\95Ï\8dX'
3695   else
3696     StatusBar.Panels[PanelConnecting].Text := '';
3697   FFileModified := Value;
3698 end;
3699
3700 procedure TfrmSender.OpenBrowser(const Url: string);
3701 var
3702   Command: string;
3703 begin
3704   if Pref.BrowserExeName = '' then
3705     begin
3706       ShellExecute(Handle, 'open', PChar(Url), nil, nil, SW_SHOW);
3707     end else
3708     begin
3709       Command := Pref.BrowserExeName + ' ' + Url;
3710       WinExec(PChar(Command), SW_SHOW);
3711     end;
3712 end;
3713
3714 {
3715 procedure TfrmSender.CopyDataMessage(var WMCopyData: TWMCopyData);
3716 var
3717   Param: string;
3718   HeadValue: THeadValue;
3719 begin
3720   // \83e\83X\83g\97p
3721   if WMCopyData.CopyDataStruct.dwData = 1 then
3722   begin
3723     Param := PChar(WMCopyData.CopyDataStruct.lpData);
3724     HeadValue := THeadValue.Create(Param);
3725     try
3726       if HeadValue['Script'] <> '' then
3727         DispatchBottle(HeadValue, Now(), 0, 0)
3728       else if HeadValue['Type'] = 'Vote' then
3729         frmLog.VoteLog(HeadValue['MID'], StrToIntDef(HeadValue['Num'], 0))
3730       else if HeadValue['Type'] = 'Agree' then
3731         frmLog.AgreeLog(HeadValue['MID'], StrToIntDef(HeadValue['Num'], 0))
3732       else if (HeadValue['Num'] <> '') AND (HeadValue['Channel'] = '') AND
3733         (HeadValue['Entry'] = '') then
3734         StatusBar.Panels[PanelMembers].Text := HeadValue['Num'] + '\90l';
3735     finally
3736       HeadValue.Free;
3737     end;
3738   end;
3739 end;
3740 }
3741
3742 end.