X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=bottleclient%2FMainForm.pas;h=65448ff4aa2b583fa5bff75f785a562dbac9497d;hb=afa74286e4b975f278cb3f95c8725d98095f38c9;hp=09924d9eedc8b117f125daa4b58cd3cd9b8d4a91;hpb=1d7321b5daf0cb8b43745a2ec6d27334d417733d;p=winbottle%2Fwinbottle.git diff --git a/bottleclient/MainForm.pas b/bottleclient/MainForm.pas index 09924d9..65448ff 100755 --- a/bottleclient/MainForm.pas +++ b/bottleclient/MainForm.pas @@ -1,5 +1,10 @@ unit MainForm; +{ +ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚̃ƒCƒ“ƒtƒH[ƒ€B +‘—MEŽóMEƒ{ƒgƒ‹”z‘—ŠÖŒW‚Ì‚¢‚ë‚¢‚ë‚ȏˆ—‚ðs‚¤B +} + interface uses @@ -9,11 +14,12 @@ uses IdSLPP20, SsParser, ImgList, AppEvnts, TaskTray, StdActns, ActnList, MPlayer, MenuBar, ToolWin, IniFiles, ExtCtrls, ShellAPI, Contnrs, - ConstEditor, Buttons, Clipbrd, HeadValue, Logs, - IdException, HttpThread, IdHTTP, IdURI, LogDownload, + ConstEditor, Buttons, Clipbrd, HeadValue, Logs, MultipleChoiceEditor, + IdException, HttpThread, IdHTTP, LogDownload, ScriptConsts, DateUtils, BottleChainRule, BottleChainEvent, - SakuraSeekerInstance, HEditor, heClasses, heFountain, - SakuraScriptFountain, SppTypes, SppList, SurfacePreview; + SakuraSeekerInstance, HEditor, HTSearch, heClasses, heFountain, + SakuraScriptFountain, SppList, SurfacePreview, XDOM_2_3_J3, SsPlayTime, + RegexUtils, StrReplace, StrReplaceDialog, IdAntiFreezeBase, IdAntiFreeze; type TSurfacePreviewType = (spHint, spEditor); @@ -59,7 +65,6 @@ type mnSend: TMenuItem; mnConfirm: TMenuItem; mnClear: TMenuItem; - N9: TMenuItem; imgIcon: TImageList; mnPopupConst: TPopupMenu; actEditConst: TAction; @@ -78,7 +83,6 @@ type ConstMenuBar: TMenuBar; mnGoToHP: TMenuItem; LabelTimer: TTimer; - mnColorScript: TMenuItem; mnCopyAll: TMenuItem; actCopyAll: TAction; actCopyAllNoReturn: TAction; @@ -119,7 +123,6 @@ type mnLeaveThisChannel: TMenuItem; N4: TMenuItem; mnGotoVote: TMenuItem; - mnGotoGLog: TMenuItem; mnGoToHelp: TMenuItem; btnSend: TButton; btnConfirm: TButton; @@ -148,11 +151,32 @@ type actPaste: TAction; actCut: TAction; actSelectAll: TAction; - actEditCopy: TEditCopy; actRecallScriptBuffer: TAction; N5: TMenuItem; mnRecallScriptBuffer: TMenuItem; - ToolButton1: TToolButton; + tbtnEditorPreview: TToolButton; + actEditorPreview: TAction; + mnEditorPreview: TMenuItem; + actResetPlugins: TAction; + N7: TMenuItem; + mnResetPlugins: TMenuItem; + actReplace: TAction; + N10: TMenuItem; + mnReplace: TMenuItem; + actSendToEditor: TAction; + actSendToLogWindow: TAction; + mnSendLogWindow: TMenuItem; + actDeleteLogItem: TAction; + actAbout: TAction; + actEditCopy: TEditCopy; + tbtnSendToLogWindow: TToolButton; + SsPlayTime: TSsPlayTime; + actUndo: TAction; + actRedo: TAction; + mnUndo: TMenuItem; + mnRedo: TMenuItem; + N9: TMenuItem; + AntiFreeze: TIdAntiFreeze; procedure actConfirmExecute(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); @@ -162,7 +186,7 @@ type procedure actStartClick(Sender: TObject); procedure actStopExecute(Sender: TObject); procedure FormShow(Sender: TObject); - procedure mnAboutClick(Sender: TObject); + procedure actAboutClick(Sender: TObject); procedure actExitClientExecute(Sender: TObject); procedure actClearExecute(Sender: TObject); procedure memScriptChange(Sender: TObject); @@ -198,14 +222,12 @@ type procedure actNextChannelExecute(Sender: TObject); procedure cbxTargetGhostDropDown(Sender: TObject); procedure actShowLogExecute(Sender: TObject); - procedure Slpp20Connect(Sender: TObject); procedure actSleepExecute(Sender: TObject); procedure actVoteMessageExecute(Sender: TObject); procedure tabChannelContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure mnLeaveThisChannelClick(Sender: TObject); procedure mnGotoVoteClick(Sender: TObject); - procedure mnGotoGLogClick(Sender: TObject); procedure tabChannelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure mnGoToHelpClick(Sender: TObject); @@ -235,22 +257,34 @@ type procedure memScriptMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure actRecallScriptBufferExecute(Sender: TObject); - procedure ToolButton1Click(Sender: TObject); + procedure actEditorPreviewExecute(Sender: TObject); + procedure actResetPluginsExecute(Sender: TObject); + procedure IdSLPP20Connect(Sender: TObject); + procedure actReplaceExecute(Sender: TObject); + procedure actSendToEditorExecute(Sender: TObject); + procedure actSendToLogWindowExecute(Sender: TObject); + procedure memScriptDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure memScriptDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure actDeleteLogItemExecute(Sender: TObject); + procedure memScriptSelectionChange(Sender: TObject; Selected: Boolean); + procedure actUndoExecute(Sender: TObject); + procedure actRedoExecute(Sender: TObject); private - FSleeping: boolean; + FSleeping: boolean; // ”z‘—ƒXƒŠ[ƒv’†‚©‚Ç‚¤‚© FStatusText: String; FConnecting: boolean; FAdded: boolean; FBooted: boolean; //‰‰ñ‹N“®’ʐM—p + FEndSession: Boolean; // WindowsI—¹‚ðŒŸ’m‚µ‚Ätrue‚É‚È‚é FOriginalCaption: String; - FAutoAddAfterGetChannel: boolean; + FAutoAddAfterGetChannel: boolean; //ƒ`ƒƒƒ“ƒlƒ‹Žæ“¾Œã‚Ƀ_ƒCƒAƒƒO‚È‚µ‚É + //ƒ`ƒƒƒ“ƒlƒ‹‚ÉŽQ‰Á‚·‚é‚©‚Ç‚¤‚© FConstDir: String; FSppDir: String; // - FMutex: THandle; //MutexƒIƒuƒWƒFƒNƒgc“ñd‹N“®–hŽ~—p - // FNowChannel: String; //Œ»Ý‘I‘ð‚³‚ê‚Ä‚¢‚éƒ`ƒƒƒ“ƒlƒ‹ - JoinChannelsBackup: TStringList; // + JoinChannelsBackup: TStringList; //ˆêŽžŽg—p // FScriptModified: boolean; // ƒXƒNƒŠƒvƒg‚ª•ÏX‚³‚ê‚Ä‚¢‚é‚©‚Ç‚¤‚©B // ƒ[ƒJƒ‹Šm”F‹­§—pƒtƒ‰ƒOBTRichEdit.Modified‚Í @@ -259,7 +293,7 @@ type FDragTabIndex: integer; //ƒ^ƒuƒhƒ‰ƒbƒOƒhƒƒbƒvŠÖ˜A FDragTabDest: integer; //ƒhƒƒbƒv‚·‚éˆÊ’u(‚·‚®‰E‚É‚­‚éƒ^ƒu‚̃Cƒ“ƒfƒbƒNƒX) // - FBottleSstp: TBottleSstp; // ƒXƒŒƒbƒh”ōđ—ƒvƒƒOƒ‰ƒ€ + FBottleSstp: TBottleSstp; // Ä‘—ƒvƒƒOƒ‰ƒ€ // FHttp: THTTPDownloadThread; //HTTPƒ_ƒEƒ“ƒ[ƒhƒXƒŒƒbƒh(ƒCƒ“ƒXƒ^ƒ“ƒX‚Í1ŒÂ‚Ì‚Ý) FBeginConnectFailCount: integer; //‰½“x‚àÚ‘±Ž¸”s‚µ‚½‚烊ƒgƒ‰ƒC’†Ž~ @@ -275,8 +309,7 @@ type // FScriptBuffer: TObjectList; //ƒXƒNƒŠƒvƒgƒNƒŠƒAƒoƒbƒtƒ@ // - FLastGhostList: String; //ƒS[ƒXƒgƒŠƒXƒg‚Ì•¶Žš—ñ - FLastGhostListSend: Int64; //‘¨’²¸‚ðÅŒã‚É‘—M‚µ‚½Žž + FWM_TaskBarCreated: WORD; // ƒ^ƒXƒNƒo[“o˜^—pƒEƒBƒ“ƒhƒEƒƒbƒZ[ƒWID // procedure SetStatusText(const Value: String); procedure SetSleeping(const Value: boolean); @@ -311,17 +344,35 @@ type function GetSurfacePreviewPositionHint(w, h: integer): TPoint; function GetSurfacePreviewPositionScriptPoint(w, h: integer): TPoint; procedure EditorPreview; + // ƒ^ƒO‚Ì•¶Žš—ñ‚ð•ÏŠ·‚·‚é + function TagReplace(Script: String; + Before, After: array of String): String; overload; + function TagReplace(Script: String; + Before, After: TStrings): String; overload; + // ƒT[ƒtƒBƒX‚ð•ÏŠ·‚·‚é + function ReplaceSurface(Script: String; Params: TCollection): String; + procedure ClearEditor; + procedure CopyFromLogToEditor(Log: TLogItem); + // + procedure AppendTextLog(const FileName, Line: String); + procedure AppendXMLLog(const FileName: String; Args: THeadValue); + protected + procedure WndProc(var Message: TMessage); override; + procedure WMQueryEndSession(var msg: TWMQueryEndSession); + message WM_QUERYENDSESSION; public function DoTrans(var Script: String; - Options: TScriptTransOptions): String; - function ScriptTransForSSTP(const Script: String): String; + Options: TScriptTransOptions): String; overload; + function DoTrans(var Script: String; + Options: TScriptTransOptions; out FoundURL: boolean): String; overload; + function ScriptTransForSSTP(const Script: String; + out Error: String): String; overload; procedure BeginConnect; procedure RetryBeginConnect; procedure EndConnect; procedure ConstructMenu(Simple: boolean); property Connecting: boolean read FConnecting write SetConnecting; property BottleSstp: TBottleSstp read FBottleSstp; - function SetHWndToFavoriteGhost(const Ghost: String): String; function GhostNameToSetName(const Ghost: String): String; procedure PostCommand(const Command: array of String); overload; procedure PostCommand(Command: TStrings); overload; @@ -337,7 +388,7 @@ const PanelConnecting = 0; //uÚ‘±’†v•\Ž¦—p PanelBytes = 1; //››ƒoƒCƒg PanelCount = 2; //Local ProxyAŒ»Ý›Œ‘Ò‚¿ - PanelMembers = 3; + PanelMembers = 3; //››l PanelStatus = 4; //SSTP BottleƒT[ƒo‚É“o˜^‚³‚ê‚Ä‚¢‚Ü‚·c‚È‚Ç IconConnected = 17; @@ -352,6 +403,8 @@ const function Token(const Str: String; const Delimiter: char; const Index: integer): String; +function StringReplaceEx(const Before: String; List: THeadValue): String; + implementation uses SendConfirm, SettingForm, ChannelListForm, LogForm, @@ -377,43 +430,98 @@ begin end; end; +// •¶Žš—ñ‚ð’u‚«Š·‚¦‚郆[ƒeƒBƒŠƒeƒBŠÖ” +function StringReplaceEx(const Before: String; List: THeadValue): String; +var + i, MinPos, MinKey, p: integer; + Work: String; +begin + Work := Before; + Result := ''; + MinKey := -1; + while Work <> '' do + begin + MinPos := -1; + for i := 0 to List.Count-1 do + begin + p := Pos(List.KeyAt[i], Work); + if (p > 0) and ((p < MinPos) or (MinPos < 0)) then + begin + MinPos := p; + MinKey := i; + end; + end; + if MinPos < 0 then + begin + Result := Result + Work; + Break; + end else + begin + Result := Result + Copy(Work, 1, MinPos-1) + List.ValueAt[MinKey]; + Delete(Work, 1, (MinPos - 1) + Length(List.KeyAt[MinKey])); + end; + end; +end; + {TfrmSender} procedure TfrmSender.actConfirmExecute(Sender: TObject); -var Res: TSstpResult; - Script, Ghost, Err: String; - Opt: TScriptTransOptions; +var + AScript, Err, AGhost: String; + Item: TLogItem; + Choice: integer; begin - if Length(GetScriptText) = 0 then Exit; + // Partial Confirmation + if memScript.SelText <> '' then + begin + Choice := 0; + if not Pref.AutoPartialConfirm then + if not MultipleChoiceEdit('Šm”F', ['‘I‘ð•”•ª‚Ì‚Ý', 'ƒXƒNƒŠƒvƒg‘S‘Ì'], Choice) then + Exit; + if Choice = 0 then + begin + AScript := memScript.SelText; + AScript := StringReplace(Pref.PartialConfirmFormat, '|', AScript, []); + end else + AScript := GetScriptText; + end else + AScript := GetScriptText; + AScript := StringReplace(AScript, #13#10, '', [rfReplaceAll]); + + if Length(AScript) = 0 then Exit; YenETrans; - Script := GetScriptText; - if Pref.IgnoreTimeCritical then - Opt := [toIgnoreTimeCritical, toWarnCheck] - else - Opt := [toWarnCheck]; - if Pref.NoTransUrl then Opt := Opt + [toNoChoice]; - if Pref.HUTagTo01Tag then Opt := Opt + [toHUTagTo01Tag]; - Err := DoTrans(Script, Opt + [toConvertURL, toWarnMessySurface]); - if Err <> '' then begin + AScript := ScriptTransForSSTP(AScript, Err); + if Err <> '' then + begin ShowMessage(Err); Exit; end; - if cbxTargetGhost.ItemIndex > 0 then begin - Ghost := cbxTargetGhost.Text - end else begin - if FNowChannel <> '' then - Ghost := ChannelList.Channel[FNowChannel].Ghost; - end; - Ghost := SetHWndToFavoriteGhost(Ghost); - DirectSstp.SstpSender := 'SSTP Bottle -yŠm”Fz'; - - Res := DirectSstp.SstpSEND(Script, [soNoTranslate], GhostNameToSetName(Ghost)); - if Res <> srOk then begin - ShowHintLabel('‘—MŽ¸”s:' + DirectSstp.RecvLog, WarningColor); - end else begin - ShowHintLabel(''); - FScriptModified := false; + + if cbxTargetGhost.ItemIndex > 0 then + AGhost := cbxTargetGhost.Text + else if FNowChannel <> '' then + AGhost := ChannelList.Channel[FNowChannel].Ghost + else + AGhost := ''; + + if Pref.IgnoreTimeCritical then + AScript := TagReplace(AScript, ['\t'], ['']); + + Item := TLogItem.Create; + try + with Item do + begin + LogType := ltBottle; + Script := AScript; + Channel := 'yŠm”Fz'; + Ghost := AGhost; + end; + BottleSstp.Unshift(Item); + except + Item.Free; end; + + FScriptModified := false; end; procedure TfrmSender.FormCreate(Sender: TObject); @@ -450,20 +558,6 @@ begin FOriginalCaption := Self.Caption; - {$IFDEF NOMUTEX} - ShowMessage('“ñd‹N“®‹–‰Âƒo[ƒWƒ‡ƒ“‚Å‚·B'#13#10 + VersionString); - {$ELSE} - FMutex := CreateMutex(nil, true, 'SSTPBottleClient2'); - if GetLastError = ERROR_ALREADY_EXISTS then begin - Beep; - ShowMessage('SSTP Bottle Client‚Í“ñd‹N“®‚Å‚«‚Ü‚¹‚ñ'); - CloseHandle(FMutex); - Application.Terminate; - Application.ProcessMessages; //WM_QUIT‚𗬂· - Exit; - end; - {$ENDIF} - UpdateLayout; mnShowToolBar.Checked := Pref.ShowToolBar; mnShowConstBar.Checked := Pref.ShowConstBar; @@ -475,13 +569,14 @@ begin mnStayOnTop.Checked := false; end; + // URLƒWƒƒƒ“ƒvæ‚ðƒqƒ“ƒg•¶Žš—ñ‚Æ‚µ‚Đݒè mnGoToHP.Hint := Pref.HomePage; - mnGotoGlog.Hint := Pref.GLogPage; mnGotoVote.Hint := Pref.VotePage; mnGotoHelp.Hint := Pref.HelpPage; mnGetNewId.Enabled := (Pref.LUID = ''); + // ‚³‚­‚çƒXƒNƒŠƒvƒg‰ðÍƒpƒ^[ƒ“‚ð“ǂݍž‚Ý try SsParser.TagPattern.LoadFromFile(ExtractFilePath(Application.Exename) + 'tagpat.txt'); SsParser.MetaPattern.LoadFromFile(ExtractFilePath(Application.ExeName) + 'metapat.txt'); @@ -490,6 +585,10 @@ begin Application.Terminate; end; + // Ä¶ŽžŠÔ„’èƒRƒ“ƒ|[ƒlƒ“ƒg‚Ƀpƒ‰ƒ[ƒ^‚ðŽw’è + SsPlayTime.PlayTimeParams := Pref.PlayTimeParams; + + // ƒƒCƒ“ƒEƒBƒ“ƒhƒE‚̈ʒu‚ƃTƒCƒY‚𕜋A with Pref.SenderWindowPosition do begin Self.Left := Left; Self.Top := Top; @@ -497,8 +596,14 @@ begin Self.Height := Bottom - Top + 1; end; + // ƒ^ƒXƒNƒo[‚̍ċN“®(Explorer‚ª—Ž‚¿‚½‚Æ‚«)‚ðŒŸo‚·‚é + FWM_TaskBarCreated := RegisterWindowMessage('TaskBarCreated'); + + // ƒXƒNƒŠƒvƒg•¶Žš—ñ‚̏‰Šú‰» actClearExecute(Sender); + // ƒ^ƒXƒNƒgƒŒƒC‚ɃAƒCƒRƒ“‚ð’ljÁ ChangeTaskIcon; + // ƒ`ƒƒƒ“ƒlƒ‹ŽQ‰ÁŠÖŒW‚̃^ƒu‚̏ˆ—‚È‚Ç(ƒ`ƒƒƒ“ƒlƒ‹•sŽQ‰Á‚ŏ‰Šú‰») UpdateJoinChannelList(nil); // SSTPÄ‘—ƒIƒuƒWƒFƒNƒg @@ -517,7 +622,6 @@ begin if FBottleSstp <> nil then begin FBottleSstp.Terminate; - FBottleSstp.WaitFor; FBottleSstp.Free; end; @@ -535,9 +639,6 @@ begin SaveChainRuleList; BottleChainRuleList.Free; - {$IFDEF BOTTLEMUTEX} - ReleaseMutex(FMutex); - {$ENDIF} end; @@ -558,14 +659,13 @@ begin actStart.Enabled := true; actStop.Enabled := true; actSend.Enabled := true; - //actVoteMessage.Enabled := true; - //actAgreeMessage.Enabled := true; frmLog.lvwLogChange(Self, nil, ctState); mnGetNewId.Enabled := Pref.LUID = ''; Screen.Cursor := crDefault; end; end; +// ƒƒbƒZ[ƒW‘—M procedure TfrmSender.actSendExecute(Sender: TObject); var Talk, Ghost: String; Command: TStringList; @@ -592,7 +692,16 @@ begin Exit; end; - if Pref.NeedConfirmBeforeSend and FScriptModified then begin + YenETrans; + Talk := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]); + Err := DoTrans(Talk, [toWarnMessySurface, toWarnCheck]); + if Err <> '' then begin + MessageDlg(Err, mtWarning, [mbOk], 0); + Exit; + end; + + if Pref.NeedConfirmBeforeSend and FScriptModified then + begin MessageDlg('‘—M‘O‚Ƀ[ƒJƒ‹Šm”F‚µ‚Ä‚­‚¾‚³‚¢B', mtError, [mbOk], 0); Exit; end; @@ -601,18 +710,10 @@ begin if not SendConfirmDialog(FNowChannel, cbxTargetGhost.Text) then Exit; end; - YenETrans; - Talk := GetScriptText; - Err := DoTrans(Talk, [toWarnMessySurface, toWarnCheck]); - if Err <> '' then begin - MessageDlg(Err, mtWarning, [mbOk], 0); - Exit; - end; - Command := nil; Ghost := ''; if cbxTargetGhost.ItemIndex > 0 then Ghost := cbxTargetGhost.Text; + Command := TStringList.Create; try - Command := TStringList.Create; with Command do begin Add('Command: sendBroadcast'); Add('Channel: ' + FNowChannel); @@ -652,8 +753,8 @@ begin IdSlpp20.Port := Pref.ProxyPort; IdSlpp20.ProxyMode := true; end else begin - IdSlpp20.Host := 'bottle.mikage.to'; - IdSlpp20.Port := 9871; + IdSlpp20.Host := Pref.BottleServer; + IdSlpp20.Port := Pref.BottleServerPort; IdSlpp20.ProxyMode := false; end; IdSlpp20.Connect; @@ -691,7 +792,6 @@ begin if Value then begin StatusText := 'SSTP Bottle ƒT[ƒo‚ɐڑ±‚³‚ê‚Ä‚¢‚Ü‚·'; ChangeTaskIcon; - ShowHintLabel('SSTP BottleƒT[ƒo‚ªŒ©‚‚©‚è‚Ü‚µ‚½'); end else begin StatusText := 'ƒT[ƒo‚Ƃ̐ڑ±‚ªØ‚ê‚Ä‚¢‚Ü‚·!'; ChangeTaskIcon; @@ -745,6 +845,12 @@ begin if ResStr = 'OK' then begin Pref.LUID := HeadValue['NewID']; ShowHintLabel('LUIDŽæ“¾Š®—¹B'); + frmMessageBox.ShowMessage('‰‰ñ‹N“®‚Ì‚½‚߁A' + + 'SSTP BottleƒT[ƒoÚ‘±—p‚ÌID(LUID)‚ðV‹KŽæ“¾‚µ‚Ü‚µ‚½B'#13#10 + + 'LUID: ' + Pref.LUID + #13#10 + + 'Ý’èƒtƒ@ƒCƒ‹‚ðíœ‚·‚邱‚ƂŁALUID‚ÍŽ©—R‚Ɏ擾‚Å‚«‚Ü‚·‚ªA' + + 'LUID‚ÌŽg—pŽÀÑ‚ɉž‚¶‚Ä“Á“T‚ª‚ ‚é‚©‚à‚µ‚ê‚Ü‚¹‚ñ‚̂ŁA' + + 'o—ˆ‚邾‚¯“¯‚¶‚à‚Ì‚ðŽg‚Á‚Ä‚­‚¾‚³‚¢BÚ×‚̓wƒ‹ƒv‚ð‚²——‚­‚¾‚³‚¢B'); mnGetNewId.Enabled := false; BeginConnect; end else begin @@ -773,9 +879,14 @@ begin end; end; end else begin - if frmChannelList.Execute(ChannelList, JoinChannels) then begin - SetChannel := TStringList.Create; - SetChannel.Assign(frmChannelList.JoinList); + Application.CreateForm(TfrmChannelList, frmChannelList); + try + if frmChannelList.Execute(ChannelList, JoinChannels) then begin + SetChannel := TStringList.Create; + SetChannel.Assign(frmChannelList.JoinList); + end; + finally + frmChannelList.Release; end; end; if SetChannel <> nil then PostSetChannel(SetChannel); @@ -833,10 +944,15 @@ begin frmLog.Show; frmSurfacePreview.Show; Self.Show; - SakuraSeekerDetectResultChanged(Self); + SakuraSeeker.BeginDetect; + SakuraSeekerDetectResultChanged(self); + if SakuraSeeker.Count = 0 then + frmMessageBox.ShowMessage('ƒS[ƒXƒg(SSTPƒT[ƒo)‚ª1‚‚à‹N“®‚µ‚Ä‚¢‚Ü‚¹‚ñB'#13#10 + + 'SSTP Bottle‚ð—˜—p‚·‚邽‚߂ɂ́AƒS[ƒXƒg‚𓯎ž‚É‹N“®‚µ‚Ä‚­‚¾‚³‚¢B'#13#10 + + 'Ú×‚̓wƒ‹ƒv‚ð‚²——‰º‚³‚¢B'); end; -procedure TfrmSender.mnAboutClick(Sender: TObject); +procedure TfrmSender.actAboutClick(Sender: TObject); var Str: String; begin Str := VersionString + #13#10 + BottleDisclaimer + #13#10#13#10; @@ -850,48 +966,27 @@ begin end; procedure TfrmSender.actClearExecute(Sender: TObject); -var TmpScript: String; - Position: Integer; - DoSaveBuffer: boolean; - SavedScript: TStringList; +var + Script, Default: String; begin - // ƒXƒNƒŠƒvƒg‚̃NƒŠƒA - // ‚Ü‚¸AƒXƒNƒŠƒvƒgƒNƒŠƒAƒoƒbƒtƒ@‚ÉŒ»Ý‚̃XƒNƒŠƒvƒg‚ð•Û‘¶‚·‚é - DoSaveBuffer := false; - if FScriptBuffer.Count = 0 then - DoSaveBuffer := true - else if (FScriptBuffer[0] as TStringList).Text <> GetScriptText then - DoSaveBuffer := true; - if (GetScriptText = Pref.DefaultScript) or (GetScriptText = '') then - DoSaveBuffer := false; - if DoSaveBuffer then - begin - SavedScript := TStringList.Create; - SavedScript.Text := GetScriptText; - FScriptBuffer.Insert(0, SavedScript); - end; - if FScriptBuffer.Count >= 4 then - FScriptBuffer.Delete(FScriptBuffer.Count-1); - actRecallScriptBuffer.Enabled := FScriptBuffer.Count > 0; - - TmpScript := Pref.DefaultScript; - Position := Pos('|', TmpScript); - if Position < 1 then Position := 1; - TmpScript := StringReplace(TmpScript, '|', '', []); - memScript.Lines.Text := TmpScript; - Sendmessage(memScript.Handle, WM_VSCROLL, SB_LINEUP, 0); - memScript.SelStart := Position-1; + Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]); + Default := StringReplace(Pref.DefaultScript, '|', '', [rfReplaceAll]); + Default := StringReplace(Default, #13#10, '', [rfReplaceAll]); - if Visible then memScript.SetFocus; - FScriptModified := false; - memScriptChange(self); + if (Pref.AutoClip) and (Length(GetScriptText) > 0) and (Script <> Default) then + actSendToLogWindow.Execute + else + ClearEditor; end; procedure TfrmSender.memScriptChange(Sender: TObject); -var Script: String; +var + Script: String; + Text: String; begin Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]); - StatusBar.Panels[PanelBytes].Text := IntToStr(length(Script)) + 'ƒoƒCƒg'; + Text := Format('%dƒoƒCƒg/%d•b', [Length(Script), SsPlayTime.PlayTime(Script) div 1000]); + StatusBar.Panels[PanelBytes].Text := Text; FScriptModified := true; EditorPreview; end; @@ -1105,7 +1200,7 @@ begin SynchronizedColor.Color := Pref.TalkColorS; end; memScript.Ruler.Visible := Pref.ShowRuler; - memScript.Ruler.Color := Pref.TalkColorH; + memScript.Ruler.Color := Pref.TextColor; memScript.Color := Pref.BgColor; ToolBar.Visible := Pref.ShowToolBar; @@ -1118,11 +1213,12 @@ begin tpTop: Align := alTop; tpBottom: Align := alBottom; end; + TabWidth := Pref.TabWidth; end; end; function TfrmSender.DoTrans(var Script: String; - Options: TScriptTransOptions): String; + Options: TScriptTransOptions; out FoundURL: boolean): String; var UrlCancel, Mark: String; Url, UrlName: array[0..6] of String; i, j, u, UrlCount: integer; @@ -1137,6 +1233,8 @@ begin UnyuTalking := false; QuickSection := false; Synchronize := false; + SsParser.LeaveEscape := true; + SsParser.EscapeInvalidMeta := false; SsParser.InputString := Script; Script := ''; Warnings := TStringList.Create; @@ -1213,6 +1311,7 @@ begin end; end; if UrlCount > 0 then begin + FoundUrl := true; Script := Script + '\h\n'; if not (toNoChoice in Options) then begin for i := 0 to UrlCount-1 do begin @@ -1225,10 +1324,11 @@ begin Script := Script + '\h'; for i := 0 to UrlCount-1 do begin Script := Script + Format('\n{%s}(%s)', [UrlName[i], Url[i]]); - Script := Script + Format('\n{%s}', [UrlCancel]); end; + Script := Script + Format('\n{%s}', [UrlCancel]); end; - end; + end else + FoundUrl := false; //ƒXƒNƒŠƒvƒg‚̍Ōã‚ɃEƒFƒCƒg‘}“ü if toWaitScriptEnd in Options then begin i := Pref.WaitScriptEnd; @@ -1269,6 +1369,13 @@ begin end; end; +function TfrmSender.DoTrans(var Script: String; + Options: TScriptTransOptions): String; +var dum: boolean; +begin + Result := DoTrans(Script, Options, dum); +end; + procedure TfrmSender.mnGoToHPClick(Sender: TObject); begin ShellExecute(Handle, 'open', PChar(Pref.HomePage), nil, nil, SW_SHOW); @@ -1330,15 +1437,12 @@ begin end; etConnectOk: begin ShowHintLabel('SSTP BottleƒT[ƒo‚ƒʐMŠm—§B'); + Added := true; FBeginConnectFailCount := 0; //ƒ`ƒƒƒ“ƒlƒ‹Ž©“®“o˜^ if not Connecting then PostCommand(['Command: getChannels']); SakuraSeeker.BeginDetect; - if SakuraSeeker.Count = 0 then - frmMessageBox.ShowMessage('ƒS[ƒXƒg(SSTPƒT[ƒo)‚ª1‚‚à‹N“®‚µ‚Ä‚¢‚Ü‚¹‚ñB'#13#10 + - 'SSTP Bottle‚ð—˜—p‚·‚邽‚߂ɂ́AƒS[ƒXƒg‚𓯎ž‚É‹N“®‚·‚é•K—v‚ª‚ ‚è‚Ü‚·'#13#10 + - 'Ú×‚̓wƒ‹ƒv‚ð‚²——‰º‚³‚¢B'); end; etChannelList: begin UpdateJoinChannelList(HeadValue); @@ -1436,42 +1540,8 @@ begin end; procedure TfrmSender.SakuraSeekerDetectResultChanged(Sender: TObject); -var i: integer; - GhostList: String; - Http: THTTPDownloadThread; - SendOk: boolean; begin UpdateIfGhostBox; // ƒhƒƒbƒvƒ_ƒEƒ“‚Ì’†g‚ð‘‚«Š·‚¦‚é - - if (FLastGhostListSend <> 0) and - (GetTickCount < FLastGhostListSend + 1000*60) then - begin - Exit; - end; - FLastGhostListSend := GetTickCount; - - //‘¨’²¸‚ÉŽQ‰Á - if FBooted and not Pref.NoSendGhostList and (SakuraSeeker.Count > 0) then begin - GhostList := 'CCC=' + TIdURI.ParamsEncode('ˆ¤'); - GhostList := GhostList + '&LUID=' + Pref.LUID; - SendOk := false; - for i := 0 to SakuraSeeker.Count-1 do begin - if SakuraSeeker[i].Name <> '' then begin//‚±‚ꂪ‚È‚¢‚Æ‚½‚Ü‚ÉFMO‰ó‚ê‚Å‹ó‚̃S[ƒXƒg‚ð‘—‚Á‚Ä‚µ‚Ü‚¤ - GhostList := GhostList + '&GHOST=' + TIdURI.ParamsEncode(SakuraSeeker[i].SetName); - SendOk := true; - end; - end; - if SendOk and (FLastGhostList <> GhostList) then begin - FLastGhostList := GhostList; - Http := THTTPDownloadThread.Create(BottleServer, Pref.CgiNameGhost, GhostList); - if Pref.UseHttpProxy then begin - Http.ProxyServer := Pref.ProxyAddress; - Http.ProxyPort := Pref.ProxyPort; - end; - Http.FreeOnTerminate := true; - Http.Resume; - end; - end; end; procedure TfrmSender.UpdateChannelInfo(Dat: THeadValue); @@ -1561,6 +1631,8 @@ begin Tabs.Add(JoinChannels[i]); end; Tabs.EndUpdate; + // Œ³‚©‚çƒ`ƒƒƒ“ƒlƒ‹‚ÉŽQ‰Á‚µ‚Ä‚¢‚½ê‡‚Í + // ‘I‘ð‚³‚ê‚Ä‚¢‚½ƒ`ƒƒƒ“ƒlƒ‹‚ª•Ï‚í‚ç‚È‚¢‚悤‚É‚·‚é(ƒ^ƒu‚ª‚¸‚ê‚È‚¢ˆ—) TabIndex := 0; for i := 0 to Tabs.Count-1 do if Tabs[i] = FNowChannel then TabIndex := i; @@ -1603,11 +1675,6 @@ begin if frmLog.WindowState = wsMinimized then frmLog.WindowState := wsNormal; end; -procedure TfrmSender.Slpp20Connect(Sender: TObject); -begin - Added := true; -end; - procedure TfrmSender.actSleepExecute(Sender: TObject); begin if actSleep.Checked then begin @@ -1626,7 +1693,7 @@ procedure TfrmSender.DispatchBottle(EventType: TIdSlppEventType; Dat: THeadValue); var Opt: TSstpSendOptions; Event: TBottleChainBottleEvent; - Script, Sender, Ghost, Channel: String; + Script, Sender, Ghost, Channel, ErrorMes: String; BreakFlag, NoDispatch: boolean; Sound, LogName: String; i, j, k, SkipCount: integer; @@ -1634,6 +1701,7 @@ var Opt: TSstpSendOptions; Action: TBottleChainAction; LogNameList: TStringList; CueItem: TLogItem; + ReplaceHash: THeadValue; begin Opt := []; if Pref.NoTranslate then Opt := Opt + [soNoTranslate]; @@ -1654,6 +1722,18 @@ begin end; Dat['TargetGhost'] := Ghost; + // ƒƒ^•¶Žš€”õ + ReplaceHash := THeadValue.Create; + ReplaceHash['%channel%'] := SafeFileName(Dat['Channel']); + ReplaceHash['%ghost%'] := SafeFileName(Dat['IfGhost']); + ReplaceHash['%date%'] := FormatDateTime('yy-mm-dd', Now()); + ReplaceHash['%year%'] := FormatDateTime('yyyy', Now()); + ReplaceHash['%yy%'] := FormatDateTime('yy', Now()); + ReplaceHash['%month%'] := FormatDateTime('mm', Now()); + ReplaceHash['%day%'] := FormatDateTime('dd', Now()); + ReplaceHash['%hour%'] := FormatDateTime('hh', Now()); + ReplaceHash['%minute%'] := FormatDateTime('nn', Now()); + Event := TBottleChainBottleEvent.Create; try Event.Data := Dat; @@ -1661,8 +1741,8 @@ begin else Event.LogType := ltSystemLog; //ƒXƒNƒŠƒvƒg•ÏŠ· - Script := ScriptTransForSSTP(Dat['Script']); - if Script = '' then begin + Script := ScriptTransForSSTP(Dat['Script'], ErrorMes); + if ErrorMes <> '' then begin frmLog.AddCurrentSystemLog('SYSTEM', '–â‘è‚Ì‚ ‚é‰Â”\«‚Ì‚ ‚éƒXƒNƒŠƒvƒg‚ª“Í‚¢‚½‚½‚߁A'+ '”z‘—‚³‚ê‚Ü‚¹‚ñ‚Å‚µ‚½@c '+Dat['Script']); Exit; @@ -1684,28 +1764,40 @@ begin if not Rule.Check(Event) then Continue; for j := 0 to Rule.Actions.Count-1 do begin Action := (Rule.Actions[j] as TBottleChainAction); - if Action is TBottleChainAbortRuleAction then BreakFlag := true; + if Action is TBottleChainAbortRuleAction then + BreakFlag := true; if Action is TBottleChainSkipRuleAction then SkipCount := (Action as TBottleChainSkipRuleAction).SkipCount; - if (Action is TBottleChainSoundAction) and (Sound = '') then begin + if (Action is TBottleChainSoundAction) and (Sound = '') then + begin Sound := (Action as TBottleChainSoundAction).SoundFile; - Sound := StringReplace(Sound, '%channel%', Dat['Channel'], [rfReplaceAll]); - Sound := StringReplace(Sound, '%ghost%', Dat['TargetGhost'], [rfReplaceAll]); + Sound := StringReplaceEx(Sound, ReplaceHash); end; - if Action is TBottleChainNoDispatchAction then NoDispatch := true; - if Action is TBottleChainLogAction then begin + if Action is TBottleChainNoDispatchAction then + NoDispatch := true; + if Action is TBottleChainLogAction then + begin for k := 0 to (Action as TBottleChainLogAction).LogNames.Count-1 do begin LogName := (Action as TBottleChainLogAction).LogNames[k]; - LogName := StringReplace(LogName, '%channel%', Dat['Channel'], [rfReplaceAll]); - LogName := StringReplace(LogName, '%ghost%', Dat['TargetGhost'], [rfReplaceAll]); - LogName := StringReplace(LogName, '%date%', FormatDateTime('yy/mm/dd', Now()), [rfReplaceAll]); + LogName := StringReplaceEx(LogName, ReplaceHash); LogNameList.Add(LogName); end; end; - if Action is TBottleChainOverrideGhostAction then begin + if Action is TBottleChainOverrideGhostAction then + begin Dat['TargetGhost'] := (Action as TBottleChainOverrideGhostAction).TargetGhost; end; - if Action is TBottleChainQuitAction then Application.Terminate; + if Action is TBottleChainQuitAction then + Application.Terminate; + if Action is TBottleChainSaveTextLogAction then + AppendTextLog(StringReplaceEx((Action as TBottleChainSaveTextLogAction).FileName, ReplaceHash), + Format('%s,%s,%s,%s', [Dat['Channel'], Dat['IfGhost'], + FormatDateTime('yy/mm/dd hh:nn:ss', Now), Dat['Script']])); + if Action is TBottleChainSaveXMLLogAction then + AppendXMLLog(StringReplaceEx((Action as TBottleChainSaveXMLLogAction).FileName, ReplaceHash), + Dat); + if Action is TBottleChainSurfaceReplaceAction then + Script := ReplaceSurface(Script, (Action as TBottleChainSurfaceReplaceAction).Params); end; if BreakFlag then Break; end; @@ -1743,23 +1835,7 @@ begin end; finally Event.Free; - end; -end; - -function TfrmSender.SetHWndToFavoriteGhost(const Ghost: String): String; -begin - //DirectSstp.TargetHWnd‚ðA„§‚·‚éƒS[ƒXƒg‚ɐݒ肷‚éB - //‚È‚¢ê‡‚́A‚Æ‚è‚ ‚¦‚¸Žè‹ß‚ȃS[ƒXƒg‚ÉŒü‚¯‚Ä‘—M‚Å‚«‚é‚悤‚É‚Í‚·‚éB - SakuraSeeker.BeginDetect; //ÅV‚ÌFMOŽæ“¾ - if SakuraSeeker.ProcessByName[Ghost] <> nil then begin - DirectSstp.TargetHWnd := SakuraSeeker.ProcessByName[Ghost].HWnd; - Result := Ghost; - end else if SakuraSeeker.Count > 0 then begin - DirectSstp.TargetHWnd := SakuraSeeker[0].HWnd; - Result := SakuraSeeker[0].Name; - end else begin - DirectSstp.TargetHwnd := 0; - Result := ''; + ReplaceHash.Free; end; end; @@ -1772,7 +1848,11 @@ begin Orig := GetScriptText; RegExp.Subst('s/(\r\n)+$//kg', Orig); - SsParser.InputString := Orig; + with SsParser do begin + LeaveEscape := true; + EscapeInvalidMeta := false; + InputString := Orig; + end; for i := 0 to SsParser.Count-1 do begin if SsParser[i] <> '\e' then Text := Text + SsParser[i]; end; @@ -1809,9 +1889,9 @@ var PostStr: String; begin Connecting := true; PostStr := Command.Text; - PostStr := TIdURI.ParamsEncode(PostStr); + PostStr := ParamsEncode(PostStr); try - FHttp := THTTPDownloadThread.Create(BottleServer, Pref.CgiName, PostStr); + FHttp := THTTPDownloadThread.Create(Pref.BottleServer, Pref.CgiName, PostStr); if Pref.UseHttpProxy then begin FHttp.ProxyServer := Pref.ProxyAddress; FHttp.ProxyPort := Pref.ProxyPort; @@ -1883,9 +1963,8 @@ procedure TfrmSender.PostSetChannel(Channels: TStrings); var PostStr: TStringList; i: integer; begin - PostStr := nil; + PostStr := TStringList.Create; try - PostStr := TStringList.Create; with PostStr do begin Add('Command: setChannels'); Add('Agent: ' + VersionString); @@ -1905,12 +1984,17 @@ procedure TfrmSender.mnLeaveThisChannelClick(Sender: TObject); var Ch: String; Chs: TStringList; begin - with tabChannel do Ch := Tabs[Tag]; - Chs := nil; + // Žw’肵‚½ƒ`ƒƒƒ“ƒlƒ‹‚©‚甲‚¯‚é + with tabChannel do + Ch := Tabs[Tag]; // ”²‚¯‚½‚¢ƒ`ƒƒƒ“ƒlƒ‹–¼ + Chs := TStringList.Create; + + // Œ»ÝŽQ‰Á’†‚̃`ƒƒƒ“ƒlƒ‹‚©‚çA”²‚¯‚½‚¢ƒ`ƒƒƒ“ƒlƒ‹‚ð + // ŠO‚µ‚½ƒŠƒXƒg‚ŁAV‚½‚Ƀ`ƒƒƒ“ƒlƒ‹ŽQ‰ÁƒRƒ}ƒ“ƒh‚ð‘—‚é try - Chs := TStringList.Create; Chs.Assign(JoinChannels); - while Chs.IndexOf(Ch) >= 0 do Chs.Delete(Chs.IndexOf(Ch)); + while Chs.IndexOf(Ch) >= 0 do + Chs.Delete(Chs.IndexOf(Ch)); PostSetChannel(Chs); finally Chs.Free; @@ -1922,11 +2006,6 @@ begin ShellExecute(Handle, 'open', PChar(Pref.VotePage), nil, nil, SW_SHOW); end; -procedure TfrmSender.mnGotoGLogClick(Sender: TObject); -begin - ShellExecute(Handle, 'open', PChar(Pref.GLogPage), nil, nil, SW_SHOW); -end; - procedure TfrmSender.tabChannelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var Index: integer; @@ -2024,7 +2103,8 @@ begin //ƒS[ƒXƒg‘I‘ðƒ{ƒbƒNƒX‚̃I[ƒi[ƒhƒ[ with cbxTargetGhost do begin AlignRight := false; - if Pref.HideGhosts and not FTargetGhostExpand and (Index = Items.Count-1) then + if Pref.HideGhosts and not FTargetGhostExpand and + (Index = Items.Count-1) and (Index > 0) then begin // u‚·‚ׂĕ\Ž¦v Canvas.Font.Color := clWindowText; @@ -2060,34 +2140,40 @@ end; procedure TfrmSender.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin - if not Pref.ConfirmOnExit then Exit; + if (not Pref.ConfirmOnExit) or FEndSession then + Exit; if MessageDlg('SSTP Bottle Client‚ðI—¹‚µ‚Ü‚·', mtConfirmation, - mbOkCancel, 0) = mrCancel then CanClose := false; + mbOkCancel, 0) = mrCancel then + CanClose := false; end; procedure TfrmSender.UpdateIfGhostBox; var Selected: String; i: integer; + HiddenCount: integer; begin cbxTargetGhost.DropDownCount := Pref.GhostDropDownCount; Selected := cbxTargetGhost.Text; + HiddenCount := 0; with cbxTargetGhost do begin Items.BeginUpdate; Items.Clear; - Items.Add('(CH„§)'); + Items.Add(ChannelDefault); for i := 0 to SakuraSeeker.Count-1 do begin // ”j‘¹FMO‘΍ôBHWND‚Ì’f•Ð‚ªŽc‚Á‚Ä‚¢‚邪Name‚ªÁ‚¦‚Ä‚¢‚éê‡‚ª‚ ‚é if Length(SakuraSeeker[i].Name) = 0 then Continue; if Pref.HideGhosts and not FTargetGhostExpand then if Pref.VisibleGhostsList.IndexOf(SakuraSeeker[i].Name) < 0 then + begin + Inc(HiddenCount); Continue; + end; if cbxTargetGhost.Items.IndexOf(SakuraSeeker[i].Name) < 0 then cbxTargetGhost.Items.Add(SakuraSeeker[i].Name); end; - Items.EndUpdate; cbxTargetGhost.ItemIndex := 0; - if (Length(Selected) > 0) and (Selected <> '(CH„§)') then begin + if (Length(Selected) > 0) and (Selected <> ChannelDefault) then begin with cbxTargetGhost do begin for i := 1 to Items.Count-1 do begin if Items[i] = Selected then @@ -2101,9 +2187,9 @@ begin end; end; if Pref.HideGhosts and not FTargetGhostExpand then - Items.Add('‚·‚ׂĕ\Ž¦...'); + Items.Add(Format('‚·‚ׂÄ(%d)...', [HiddenCount])); + Items.EndUpdate; end; - end; procedure TfrmSender.HTTPFailure(Sender: TObject); @@ -2161,7 +2247,7 @@ end; procedure TfrmSender.timDisconnectCheckTimerTimer(Sender: TObject); begin - if (IdSlpp20.LastReadTimeInterval > BottleServerTimeOut) then begin + if (IdSlpp20.LastReadTimeInterval > Pref.ReconnectWait * 60000) then begin SysUtils.Beep; frmLog.AddCurrentSystemLog('SYSTEM', 'SSTP BottleƒT[ƒo‚Ƃ̐ڑ±‚ªƒ^ƒCƒ€ƒAƒEƒg‚µ‚Ü‚µ‚½'); if IdSlpp20.Connected then IdSlpp20.Disconnect; @@ -2217,9 +2303,9 @@ begin with frmLogDownload do begin if IsRange then begin if CompareDate(DateLo, DateHi) = 0 then - Title := FormatDateTime('yy/mm/dd', DateLo) + Title := FormatDateTime('yy-mm-dd', DateLo) else - Title := FormatDateTime('yy/mm/dd', DateLo) + ' - ' + FormatdateTime('yy/mm/dd', DateHi); + Title := FormatDateTime('yy-mm-dd', DateLo) + ' - ' + FormatdateTime('yy-mm-dd', DateHi); end else begin Title := Format('‰ß‹Ž%s', [TimeStr(RecentCount)]); end; @@ -2356,7 +2442,9 @@ begin begin with cbxTargetGhost do begin - if ItemIndex = Items.Count-1 then + // ˆê”Ô‰º‚̃AƒCƒeƒ€‚ª‘I‘ð‚³‚ê‚½‚Æ‚«B + // ‚½‚¾‚µItemIndex=0‚̏ꍇ(ƒS[ƒXƒg‚ª‹N“®‚µ‚Ä‚¢‚È‚¢ê‡)‚Í—áŠO + if (ItemIndex = Items.Count-1) and (ItemIndex > 0) then begin FTargetGhostExpand := true; UpdateIfGhostBox; @@ -2387,6 +2475,14 @@ end; procedure TfrmSender.actFMOExplorerExecute(Sender: TObject); begin + try + if not Assigned(frmFMOExplorer) then + Application.CreateForm(TfrmFMOExplorer, frmFMOExplorer); + except + on E: Exception do + ShowMessage('FMOƒGƒNƒXƒvƒ[ƒ‰‚ð•\Ž¦‚Å‚«‚Ü‚¹‚ñB'#13#10#13#10 + + E.Message); + end; frmFMOExplorer.Show; end; @@ -2414,8 +2510,9 @@ end; procedure TfrmSender.actInsertCueExecute(Sender: TObject); var InsertItem: TLogItem; - i, errCount: integer; + i, errCount, Res: integer; Log: TBottleLogList; + ErrorMes: String; // ƒXƒNƒŠƒvƒg‚̃Gƒ‰[‚Ì“à—e begin if FBottleSstp.CueCount > 0 then begin if MessageDlg(Format('Œ»ÝÄ‘—ƒLƒ…[‚É“ü‚Á‚Ä‚¢‚é%dŒ‚Ì–¢”z‘—ƒ{ƒgƒ‹‚ðƒNƒŠƒA‚µ‚āA'+ @@ -2434,9 +2531,21 @@ begin if (Log[i] as TLogItem).LogType <> ltBottle then Continue; InsertItem := TLogItem.Create(Log[i] as TLogItem); try - InsertItem.Script := ScriptTransForSSTP(InsertItem.Script); - if InsertItem.Script = '' then begin - raise Exception.Create('Script syntax error'); + InsertItem.Script := ScriptTransForSSTP(InsertItem.Script, ErrorMes); + if ErrorMes <> '' then + begin + Res := MessageDlg('ƒXƒNƒŠƒvƒg‚É–â‘肪‚ ‚é‰Â”\«‚ª‚ ‚è‚Ü‚·B' + + 'Ä¶‚µ‚Ü‚·‚©?'#13#10 + ErrorMes, mtWarning, + mbYesNoCancel, 0); + if Res = mrNo then + raise Exception.Create('Script Syntax Error') + else if Res = mrCancel then + begin + InsertItem.Free; + FBottleSstp.Clear; + frmLog.AllBottleOpened; + Break; + end; end; if InsertItem.Ghost = '' then begin if ChannelList.Channel[InsertItem.Channel] <> nil then @@ -2453,11 +2562,12 @@ begin ShowMessage(Format('%dŒ‚̃{ƒgƒ‹‚É–â‘肪‚ ‚Á‚½‚½‚ߍж‚Å‚«‚Ü‚¹‚ñB', [errCount])); FBottleSSTP.OnResendCountChange := BottleSstpResendCountChange; BottleSstpResendCountChange(self); + frmLog.lvwLog.Invalidate; end; -function TfrmSender.ScriptTransForSSTP(const Script: String): String; +function TfrmSender.ScriptTransForSSTP(const Script: String; + out Error: String): String; var TransOpt: TScriptTransOptions; - Err: String; begin if Pref.NoTransURL then TransOpt := [toConvertURL, toNoChoice, toWaitScriptEnd] @@ -2467,8 +2577,7 @@ begin if Pref.FixMessySurface then TransOpt := TransOpt + [toFixMessySurface]; if Pref.HUTagTo01Tag then TransOpt := TransOpt + [toHUTagTo01Tag]; Result := Script; - Err := DoTrans(Result, TransOpt); - if Length(Err) > 0 then Result := ''; + Error := DoTrans(Result, TransOpt); end; procedure TfrmSender.FormResize(Sender: TObject); @@ -2507,6 +2616,16 @@ begin memScript.SelectAll; end; +procedure TfrmSender.actUndoExecute(Sender: TObject); +begin + memScript.Undo; +end; + +procedure TfrmSender.actRedoExecute(Sender: TObject); +begin + memScript.Redo; +end; + function TfrmSender.IsSurfaceTag(const Script: String; var ID: integer): boolean; begin @@ -2621,14 +2740,10 @@ begin if FScriptBuffer.Count = 0 then Exit; memScript.Lines.Assign(FScriptBuffer[0] as TStringList); + memScriptChange(Self); ShowHintLabel('ƒXƒNƒŠƒvƒg‚ðŒÄ‚яo‚µ‚Ü‚µ‚½'); end; -procedure TfrmSender.ToolButton1Click(Sender: TObject); -begin - frmEditorTalkShow.Show; -end; - procedure TfrmSender.EditorPreview; var Ghost, Script: String; begin @@ -2645,4 +2760,444 @@ begin end; end; +procedure TfrmSender.actEditorPreviewExecute(Sender: TObject); +begin + if frmEditorTalkShow <> nil then + frmEditorTalkShow.Show + else + begin + Application.CreateForm(TfrmEditorTalkShow, frmEditorTalkShow); + frmEditorTalkShow.Show; + end; + EditorPreview; +end; + +// ƒvƒ‰ƒOƒCƒ“ƒŠƒZƒbƒg +procedure TfrmSender.actResetPluginsExecute(Sender: TObject); +begin + Spps.ClearImagePool; + Spps.LoadFromDirectory(FSppDir); +end; + +procedure TfrmSender.IdSLPP20Connect(Sender: TObject); +begin + ShowHintLabel('SSTP BottleƒT[ƒo‚ªŒ©‚‚©‚è‚Ü‚µ‚½'); +end; + +// ƒXƒNƒŠƒvƒg’†‚̃^ƒO‚ð’uŠ·‚·‚é +// ƒTƒCƒY‰Â•Ï‚Ì”z—ñƒpƒ‰ƒ[ƒ^”Å +function TfrmSender.TagReplace(Script: String; Before, + After: array of String): String; +var BeforeList, AfterList: TStringList; + i: integer; +begin + BeforeList := TStringList.Create; + AfterList := TStringList.Create; + try + for i := Low(Before) to High(Before) do + BeforeList.Add(Before[i]); + for i := Low(After) to High(After) do + AfterList.Add(After[i]); + Result := TagReplace(Script, BeforeList, AfterList); + finally + BeforeList.Free; + AfterList.Free; + end; +end; + +// ƒXƒNƒŠƒvƒg’†‚̃^ƒO‚ð’uŠ·‚·‚é +// StringReplace‚ƈá‚Á‚Đ³Šm‚Ƀ^ƒO‚Ƀ}ƒbƒ`‚µA +// ‚Ü‚½ƒpƒ^[ƒ“‚𕡐”Žw’è‚Å‚«‚é(’uŠ·Œã‚ÌŒ‹‰Ê‚ª‚Ü‚½’uŠ·‚³‚ꂽ‚肵‚È‚¢) +function TfrmSender.TagReplace(Script: String; Before, + After: TStrings): String; +var i, j: integer; + Flag, OldLeaveEscape, OldEscapeInvalidMeta: boolean; + OldStr: String; +begin + Result := ''; + with SsParser do + begin + OldStr := InputString; + OldLeaveEscape := LeaveEscape; + OldEscapeInvalidMeta := EscapeInvalidMeta; + LeaveEscape := true; + EscapeInvalidMeta := false; + InputString := Script; + end; + for i := 0 to SsParser.Count-1 do + begin + Flag := false; + for j := 0 to Before.Count-1 do + begin + if (SsParser.MarkUpType[i] = mtTag) and (SsParser[i] = Before[j]) then + begin + Flag := true; + Result := Result + After[j]; + end; + end; + if not Flag then + Result := Result + SsParser[i]; + end; + with SsParser do + begin + LeaveEscape := OldLeaveEscape; + EscapeInvalidMeta := OldEscapeInvalidMeta; + InputString := OldStr; + end; +end; + +// WndProc‚ðƒI[ƒo[ƒ‰ƒCƒh‚µ‚āAFWM_TaskBarCraeted‚É +// ‘Ήž‚·‚é +procedure TfrmSender.WndProc(var Message: TMessage); +begin + if (Message.Msg = FWM_TaskBarCreated) and (FWM_TaskBarCreated <> 0) then + begin + TaskTray.Registered := false; // TTaskTray‚Ƀ^ƒXƒNƒgƒŒƒC‚ªÁ‚¦‚½‚±‚Æ‚ð + // ‹C‚©‚¹‚é + ChangeTaskIcon; + end + else + inherited; +end; + +// ’uŠ· +procedure TfrmSender.actReplaceExecute(Sender: TObject); +var + Form: TfrmStrReplaceDialog; + Lines: String; + Pair: TReplacePairRec; + Options: TReplaceFlags; +begin + Application.CreateForm(TfrmStrReplaceDialog, Form); + try + if Form.Execute then + begin + Pair := Form.PairRec; + with Pair do + begin + Lines := memScript.Lines.Text; + Options := [rfReplaceAll]; + if IgnoreCase then + Options := Options + [rfIgnoreCase]; + if UseRegExp then + Lines := StringReplaceRegExp(Lines, BeforeStr, AfterStr, Options) + else + Lines := StringReplace(Lines, BeforeStr, AfterStr, Options); + end; + if Lines <> memScript.Lines.Text then + begin + memScript.SelectAll; + memScript.SelText := Lines; + end; + end; + finally + Form.Release; + end; +end; + +procedure TfrmSender.actSendToEditorExecute(Sender: TObject); +var Log: TLogItem; +begin + if frmLog.lvwLog.Selected = nil then Exit; + Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem; + if Log = nil then Exit; + CopyFromLogToEditor(Log); +end; + +procedure TfrmSender.actSendToLogWindowExecute(Sender: TObject); +var Ghost, Script: String; +begin + YenETrans; + Script := StringReplace(GetScriptText, #13#10, '', [rfReplaceAll]); + if cbxTargetGhost.ItemIndex > 0 then + Ghost := cbxTargetGhost.Text + else + Ghost := ''; + frmLog.AddCurrentScriptLog('ƒNƒŠƒbƒv', Script, ClipChannel, '', Ghost); + ClearEditor; +end; + +procedure TfrmSender.memScriptDragOver(Sender, Source: TObject; X, + Y: Integer; State: TDragState; var Accept: Boolean); +begin + // ƒƒOƒEƒBƒ“ƒhƒE‚©‚ç‚̃ƒOƒAƒCƒeƒ€‚Ì’¼ÚD&D‚ð‹–‰Â‚·‚é + if Source is TBottleLogDragObject then + Accept := (Source as TBottleLogDragObject).LogItem.LogType = ltBottle +end; + +procedure TfrmSender.memScriptDragDrop(Sender, Source: TObject; X, + Y: Integer); +var Src: TBottleLogDragObject; + Log: TLogItem; +begin + // ƒƒOƒEƒBƒ“ƒhƒE‚©‚烍ƒOƒAƒCƒeƒ€‚ðD&D‚µ‚Ä‚­‚é + if not (Source is TBottleLogDragObject) then + Exit; + if (Source as TBottleLogDragObject).LogItem.LogType <> ltBottle then + Exit; + Src := Source as TBottleLogDragObject; + Log := Src.LogItem; + CopyFromLogToEditor(Log); +end; + +procedure TfrmSender.CopyFromLogToEditor(Log: TLogItem); +begin + if Log.LogType <> ltBottle then Exit; + frmSender.actClear.Execute; // Œ»Ý‚̃XƒNƒŠƒvƒg‚ðƒNƒŠƒbƒv‚·‚é(Ý’è‚É‚æ‚Á‚Ä) + memScript.Lines.Clear; + memScript.Lines.Add(Log.Script); + if Log.Ghost <> '' then + begin + // ƒS[ƒXƒg–¼‚ðƒ{ƒbƒNƒX‚É“ü‚ê‚é + // –³—–ƒS[ƒXƒg–¼‚ð’ljÁ‚µ‚Ä‚©‚çÄ\’z‚·‚邱‚Æ‚Å + // –³—–ƒS[ƒXƒg–¼‚ªƒ{ƒbƒNƒX‚É“ü‚é + cbxTargetGhost.Items.Add(Log.Ghost); + cbxTargetGhost.ItemIndex := cbxTargetGhost.Items.Count-1; + UpdateIfGhostBox; + cbxTargetGhost.Invalidate; + end else + cbxTargetGhost.ItemIndex := 0; // 'CH„§'‚É‚·‚é + memScript.SetFocus; +end; + +procedure TfrmSender.actDeleteLogItemExecute(Sender: TObject); +begin + // ƒƒOƒEƒBƒ“ƒhƒE‚̌•ʃƒO‚ðíœ‚·‚é + if frmLog.SelectedBottleLog = nil then + Exit; + if frmLog.lvwLog.Selected = nil then + Exit; + frmLog.SelectedBottleLog.Delete(frmLog.lvwLog.Selected.Index); + frmLog.UpdateWindow; + frmLog.lvwLogChange(Self, nil, ctState); +end; + +procedure TfrmSender.ClearEditor; +var TmpScript: String; + Position: Integer; + DoSaveBuffer: boolean; + SavedScript: TStringList; +begin + // ƒXƒNƒŠƒvƒg‚̃NƒŠƒA + // ‚Ü‚¸AƒXƒNƒŠƒvƒgƒNƒŠƒAƒoƒbƒtƒ@‚ÉŒ»Ý‚̃XƒNƒŠƒvƒg‚ð•Û‘¶‚·‚é + DoSaveBuffer := false; + if FScriptBuffer.Count = 0 then + DoSaveBuffer := true + else if (FScriptBuffer[0] as TStringList).Text <> GetScriptText then + DoSaveBuffer := true; + if (GetScriptText = Pref.DefaultScript) or (GetScriptText = '') then + DoSaveBuffer := false; + if DoSaveBuffer then + begin + SavedScript := TStringList.Create; + SavedScript.Text := GetScriptText; + FScriptBuffer.Insert(0, SavedScript); + end; + if FScriptBuffer.Count >= 4 then + FScriptBuffer.Delete(FScriptBuffer.Count-1); + actRecallScriptBuffer.Enabled := FScriptBuffer.Count > 0; + + TmpScript := Pref.DefaultScript; + Position := Pos('|', TmpScript); + if Position < 1 then Position := 1; + TmpScript := StringReplace(TmpScript, '|', '', []); + memScript.Lines.Text := TmpScript; + Sendmessage(memScript.Handle, WM_VSCROLL, SB_LINEUP, 0); + memScript.SelStart := Position-1; + + if Visible then memScript.SetFocus; + FScriptModified := false; + memScriptChange(self); +end; + +procedure TfrmSender.AppendTextLog(const FileName, Line: String); +var + F: TextFile; +begin + //‘—MƒƒO•Û‘¶ + try + ForceDirectories(ExtractFileDir(FileName)); + AssignFile(F, FileName); + if FileExists(FileName) then + Append(F) + else + Rewrite(F); + WriteLn(F, Line); + Flush(F); + CloseFile(F); + except + on E: Exception do + frmLog.AddCurrentSystemLog('SYSTEM', 'ƒeƒLƒXƒgƒƒO•Û‘¶‚ÉŽ¸”sF'+E.Message); + end; +end; + +procedure TfrmSender.AppendXMLLog(const FileName: String; Args: THeadValue); +var + F: TFileStream; + Buf: String; + P: integer; + Impl: TDomImplementation; + Parser: TXmlToDomParser; + DOM: TdomDocument; +begin + try // Long try block to handle all kinds of exception in this method + if not FileExists(FileName) then + begin + // Create empty XML log file + Impl := TDomImplementation.create(nil); + try + ForceDirectories(ExtractFileDir(FileName)); + Parser := TXmlToDomParser.create(nil); + Parser.DOMImpl := Impl; + try + try + DOM := Parser.fileToDom(ExtractFilePath(Application.ExeName)+'xbtl.dat'); + with DOM do + begin + documentElement.setAttribute('saved', + FormatDateTime('yy/mm/dd hh:nn:ss', Now)); + documentElement.setAttribute('generator', VersionString); + documentElement.setAttribute('version', '1.0'); + end; + // ‚±‚ê‚Í–¾Ž¦“I‚ÉFree‚µ‚È‚­‚Ä‚æ‚¢ + F := TFileStream.Create(FileName, fmCreate or fmShareExclusive); + try + DOM.writeCodeAsShiftJIS(F); + finally + F.Free; + end; + except + frmLog.AddCurrentSystemLog('SYSTEM', 'XMLƒƒO•Û‘¶‚ÉŽ¸”s‚µ‚Ü‚µ‚½'); + end; + finally + Parser.DOMImpl.freeDocument(DOM); + Parser.Free; + end; + finally; + Impl.Free; + end; + end; + F := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive); + try + P := -11; + SetLength(Buf, 12); + while P > -100 do + begin + F.Seek(P, soFromEnd); + F.Read(Buf[1], 12); + if Buf = '' then + Break; + Dec(P); + end; + if P = -100 then + raise Exception.Create(FileName + ' is not a valid XML bottle log file') + else + begin + F.Seek(P, soFromEnd); + Buf := Format('', [Args['MID']]); + Buf := Buf + Format('%s', [FormatDateTime('yy/mm/dd hh:nn:ss', Now)]); + Buf := Buf + Format('%s', [XMLEntity(Args['Channel'])]); + Buf := Buf + Format('', [XMLEntity(Args['Script'])]); + Buf := Buf + '00'; + Buf := Buf + Format('%s', [XMLEntity(Args['IfGhost'])]); + Buf := Buf + ''; + Buf := Buf + ''; + F.Write(Buf[1], Length(Buf)); + end; + finally + F.Free; + end; + except + on E: Exception do + frmLog.AddCurrentSystemLog('SYSTEM', 'XMLƒƒO•Û‘¶‚ÉŽ¸”s‚µ‚Ü‚µ‚½:'+E.Message); + end; +end; + +procedure TfrmSender.memScriptSelectionChange(Sender: TObject; + Selected: Boolean); +var + SelText: String; +begin + SelText := memScript.SelText; + if SelText <> '' then + begin + StatusBar.Panels[PanelBytes].Text := Format('(%dƒoƒCƒg)', [Length(SelText)]); + end else + begin + memScriptChange(Self); + end; +end; + +function TfrmSender.ReplaceSurface(Script: String; + Params: TCollection): String; +var + Flag, OldLeaveEscape, OldEscapeInvalidMeta: boolean; + OldStr, Tag: String; + i, j, k, Cur: integer; + Item: TSurfaceReplaceItem; + Before: TSurfaceReplaceBeforeItem; +begin + Result := ''; + Cur := 0; + with SsParser do + begin + OldStr := InputString; + OldLeaveEscape := LeaveEscape; + OldEscapeInvalidMeta := EscapeInvalidMeta; + LeaveEscape := true; + EscapeInvalidMeta := false; + InputString := Script; + end; + for i := 0 to SsParser.Count-1 do + begin + if SsParser.MarkUpType[i] <> mtTag then + begin + Result := Result + SsParser.Str[i]; + Continue; + end; + Tag := SsParser.Str[i]; + if SsParser.Match(Tag, '\s%d') = 2 then + Cur := Ord(Tag[3]) - Ord('0') + else if SsParser.Match(Tag, '\s[%D]') > 0 then + Cur := StrToInt(SsParser.GetParam(Tag, 1)) + else + begin + Result := Result + Tag; + Continue; + end; + Flag := false; + for j := 0 to Params.Count-1 do + begin + Item := Params.Items[j] as TSurfaceReplaceItem; + for k := 0 to Item.Before.Count-1 do + begin + Before := Item.Before.Items[k] as TSurfaceReplaceBeforeItem; + if (Cur >= Before.FromNo) and (Cur <= Before.ToNo) then + begin + Flag := true; + Result := Result + Format('\s[%d]', [Item.After]); + Break; + end; + end; + if Flag then + Break; + end; + if not Flag then + Result := Result + Tag; + end; + with SsParser do + begin + LeaveEscape := OldLeaveEscape; + EscapeInvalidMeta := OldEscapeInvalidMeta; + InputString := OldStr; + end; +end; + +procedure TfrmSender.WMQueryEndSession(var msg: TWMQueryEndSession); +begin + // Windows‚ªI—¹‚µ‚悤‚Æ‚µ‚Ä‚¢‚é‚Ì‚ðŠ´’m‚·‚é + FEndSession := true; + inherited; +end; + end.