X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=bottleclient%2FLogForm.pas;h=25cffc890caefd85db365c278be4d3a197b75229;hb=c39df6fec3b966e4a3276c3f193abb4095bab17b;hp=92d38b72d05b062c1a7c0040c68d61b19fa25f82;hpb=3c46a15f99b1222c17d027895eaf25113960e3c3;p=winbottle%2Fwinbottle.git diff --git a/bottleclient/LogForm.pas b/bottleclient/LogForm.pas index 92d38b7..25cffc8 100755 --- a/bottleclient/LogForm.pas +++ b/bottleclient/LogForm.pas @@ -5,12 +5,17 @@ interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ToolWin, StdCtrls, ExtCtrls, SsParser, BottleDef, Menus, - Clipbrd, Logs, ShellAPI, Commctrl, DirectSstp, Contnrs, xmldom, XMLIntf, - msxmldom, XMLDoc, StrUtils; + Clipbrd, Logs, ShellAPI, Commctrl, DirectSstp, Contnrs, StrUtils, + TalkShowFrame, SppList, HtmlOutputConfig, HtmlOutputProgress, + SearchLog, IniFiles, BRegExp; type + // ƒƒO‚Ì•Û‘¶•û–@ TSaveLogType = (stLog, stLogWithChannels, stText, stXML); + // ƒŠƒXƒgƒrƒ…[‚̃XƒNƒ[ƒ‹•ûŒü + TLVScrollDir = (lvScrollUp, lvScrollDown); + TfrmLog = class(TForm) ToolBar: TToolBar; tbtnClear: TToolButton; @@ -26,7 +31,6 @@ type SaveDialog: TSaveDialog; pnlPanel: TPanel; Splitter: TSplitter; - edtScript: TRichEdit; mnPopUpCopyScript: TMenuItem; PopupMenuSaveLog: TPopupMenu; mnSaveLog: TMenuItem; @@ -50,11 +54,30 @@ type PopupMenuTab: TPopupMenu; mnCloseTab: TMenuItem; tbtnFindBottle: TToolButton; - XMLDocument: TXMLDocument; tbtnOpenLog: TToolButton; OpenDialog: TOpenDialog; tbtnInsertCue: TToolButton; mnInsertCue: TMenuItem; + PopupMenuListPreviewStyle: TPopupMenu; + mnListPreviewStyleNormal: TMenuItem; + mnListPreviewStyleTagStripped: TMenuItem; + tbtnListPreviewStyle: TToolButton; + mnListPreviewStyleNoColor: TMenuItem; + SsParserForTalkShow: TSsParser; + mnPreviewStyleConversationImage: TMenuItem; + pnlPreviewArea: TPanel; + TalkShowFrame: TfrmTalkShow; + edtScript: TRichEdit; + tbtnSendEditor: TToolButton; + mnSendEditor: TMenuItem; + timScrollTimer: TTimer; + mnChangeTabName: TMenuItem; + N1: TMenuItem; + N2: TMenuItem; + mnDeleteLogItem: TMenuItem; + mnTabSaveXMLLog: TMenuItem; + mnSaveHTML: TMenuItem; + mnPopupCopyGhost: TMenuItem; procedure tbtnClearClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure lvwLogChange(Sender: TObject; Item: TListItem; @@ -73,9 +96,6 @@ type procedure PopupMenuListViewPopup(Sender: TObject); procedure lvwLogCustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean); - procedure lvwLogCustomDrawSubItem(Sender: TCustomListView; - Item: TListItem; SubItem: Integer; State: TCustomDrawState; - var DefaultDraw: Boolean); procedure PopupMenuPreviewStylePopup(Sender: TObject); procedure mnPreviewStyleClick(Sender: TObject); procedure tbtnPreviewStyleClick(Sender: TObject); @@ -93,6 +113,22 @@ type State: TDragState; var Accept: Boolean); procedure tabBottleLogDragDrop(Sender, Source: TObject; X, Y: Integer); procedure tabBottleLogEndDrag(Sender, Target: TObject; X, Y: Integer); + procedure lvwLogDrawItem(Sender: TCustomListView; Item: TListItem; + Rect: TRect; State: TOwnerDrawState); + procedure mnListPreviewStyleClick(Sender: TObject); + procedure tbtnListPreviewStyleClick(Sender: TObject); + procedure PopupMenuListPreviewStylePopup(Sender: TObject); + procedure lvwLogDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); + procedure lvwLogDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure timScrollTimerTimer(Sender: TObject); + procedure mnChangeTabNameClick(Sender: TObject); + procedure lvwLogStartDrag(Sender: TObject; + var DragObject: TDragObject); + procedure lvwLogEndDrag(Sender, Target: TObject; X, Y: Integer); + procedure mnTabSaveXMLLogClick(Sender: TObject); + procedure mnSaveHTMLClick(Sender: TObject); + procedure mnPopupCopyGhostClick(Sender: TObject); private { Private éŒ¾ } FLastScript: String; //ƒXƒNƒŠƒvƒgÄ•`‰æ—}§—p @@ -100,14 +136,27 @@ type // FDragTabIndex: integer; //ƒ^ƒuƒhƒ‰ƒbƒOƒhƒƒbƒvŠÖ˜A FDragTabDest: integer; //ƒhƒƒbƒv‚·‚éˆÊ’u(‚·‚®‰E‚É‚­‚éƒ^ƒu‚̃Cƒ“ƒfƒbƒNƒX) + // + // ƒŠƒXƒgƒrƒ…[ƒhƒ‰ƒbƒOƒhƒƒbƒvŠÖ˜A + FLVScrollDir: TLVScrollDir; // ƒXƒNƒ[ƒ‹•ûŒü + FLVDragDest: integer; //ƒhƒƒbƒv‚·‚éˆÊ’u(‚·‚®‰º‚É‚­‚éƒAƒCƒeƒ€‚ÌIndex) + // procedure UpdateScript(const Script: String); procedure UpdateScriptConversationColor(const Script: String); - procedure UpdateScriptConversationNoColor(const Script: String); procedure UpdateScriptScript(const Script: String); procedure mnURLClick(Sender: TObject); procedure ExtractURLs(Script: String; Result: TStrings); function GetDefaultFileName(const Name: String; const Ext: String): String; function BottleLogTitled(const LogName: String): TBottleLogList; + procedure DrawSingleLineScript(LogItem: TLogItem; Rect: TRect; + Item: TListItem); + procedure PreviewStyleChange; + procedure DrawListViewDragBorder(const Rect: TRect); + procedure DoSaveLogXML(Log: TBottleLogList); + procedure DoCloseTab(const Index: integer); + function DoSearchLog(Condition: TSearchCond): TBottleLogList; + procedure SearchLogIndivisual(Condition: TSearchCond; + LogList, Result: TBottleLogList; UntilIndex: integer = -1); protected procedure CreateParams(var Params: TCreateParams); override; public @@ -123,11 +172,25 @@ type procedure LogLoaded(Sender: TObject); procedure LogLoadFailure(Sender: TObject; const Message: String); procedure LogLoadWork(Sender: TObject); + procedure HTMLOutputWork(Sender: TObject; const Count: integer; + var Canceled: boolean); procedure UpdateTab; procedure UpdateWindow; procedure SelAndFocusMessage(const MID: String); end; + TBottleLogDragObject = class(TDragControlObjectEx) + private + FBottleLogList: TBottleLogList; + FLogItem: TLogItem; + procedure SetBottleLogList(const Value: TBottleLogList); + procedure SetLogItem(const Value: TLogItem); + protected + function GetDragImages: TDragImageList; override; + public + property BottleLogList: TBottleLogList read FBottleLogList write SetBottleLogList; + property LogItem: TLogItem read FLogItem write SetLogItem; + end; var frmLog: TfrmLog; @@ -137,6 +200,7 @@ const IconOpened = 30; IconPlaying = 31; IconSystemLog = 26; + IconURL = 43; SubChannel = 0; SubGhost = 1; SubVotes = 2; @@ -192,16 +256,13 @@ end; procedure TfrmLog.tbtnClearClick(Sender: TObject); begin if SelectedBottleLog = nil then Exit; - FBottleLogList.Delete(tabBottleLog.TabIndex); - tabBottleLog.TabIndex := 0; - UpdateTab; - UpdateWindow; - lvwLogChange(Self, nil, ctState); + DoCloseTab(tabBottleLog.TabIndex); end; procedure TfrmLog.FormCreate(Sender: TObject); var i: integer; begin + FLVDragDest := -1; // ƒŠƒXƒgƒrƒ…[‚̃hƒ‰ƒbƒO’†‚Å‚Í‚È‚¢ FBottleLogList := TObjectList.Create; SsParser.TagPattern.Assign(frmSender.SsParser.TagPattern); @@ -214,7 +275,7 @@ begin Self.Height := Bottom - Top + 1; end; lvwLog.DoubleBuffered := true; - edtScript.Height := Pref.LogWindowDividerPos; + pnlPreviewArea.Height := Pref.LogWindowDividerPos; i := 0; while Token(Pref.LogWindowColumnWidth, ',', i) <> '' do begin @@ -222,6 +283,16 @@ begin Inc(i); end; + SsParserForTalkShow.TagPattern.Assign(SsParser.TagPattern); + SsParserForTalkShow.MetaPattern.Assign(SsParser.MetaPattern); + SsParserForTalkShow.EscapeInvalidMeta := false; + SsParserForTalkShow.LeaveEscape := false; + TalkShowFrame.SsParser := self.SsParserForTalkShow; + + TalkShowFrame.SetPreviewFont(edtScript.Font); + TalkShowFrame.PrevControl := lvwLog; + + PreviewStyleChange; UpdateWindow; // Reset window color and enabled status of some buttons end; @@ -242,84 +313,91 @@ begin Right := Self.Left + Self.Width - 1; Bottom := Self.Top + Self.Height - 1; end; - Pref.LogWindowDividerPos := edtScript.Height; + Pref.LogWindowDividerPos := pnlPreviewArea.Height; FreeAndNil(FBottleLogList); end; procedure TfrmLog.lvwLogChange(Sender: TObject; Item: TListItem; Change: TItemChange); -var Script: String; +var Script, Text: String; Log: TLogItem; + Selected, IsNormalBottle: boolean; begin + Selected := false; + IsNormalBottle := false; if SelectedBottleLog <> nil then begin - StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + 'Œ'; if Change = ctState then begin Script := ''; if lvwLog.Selected <> nil then begin + Selected := true; + StatusBar.Panels[0].Text := Format('%d/%dŒ', [lvwLog.Selected.Index+1, + SelectedBottleLog.Count]); Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index]; if (Log.LogType = ltBottle) and not frmSender.Connecting then begin + IsNormalBottle := true; Script := Log.Script; - frmSender.actVoteMessage.Enabled := true; - frmSender.actAgreeMessage.Enabled := true; - frmSender.actInsertCue.Enabled := true; - mnPopUpCopyScript.Enabled := true; - StatusBar.Panels[1].Text := Format('%dƒoƒCƒg - ƒ_ƒuƒ‹ƒNƒŠƒbƒN‚ōж', [Length(Log.Script)]); - UpdateScript(Script); + Text := Format('%dƒoƒCƒg/%d•b - ƒ_ƒuƒ‹ƒNƒŠƒbƒN‚ōж', + [Length(Log.Script), frmSender.SsPlayTime.PlayTime(Log.Script) div 1000]); + StatusBar.Panels[1].Text := Text; + if Pref.LogWindowPreviewStyle = psImageConversation then + TalkShowFrame.View(Log) + else + UpdateScript(Script); end else begin - frmSender.actVoteMessage.Enabled := false; - frmSender.actAgreeMessage.Enabled := false; - frmSender.actInsertCue.Enabled := false; - mnPopUpCopyScript.Enabled := false; StatusBar.Panels[1].Text := ''; UpdateScript(''); // ƒƒOƒvƒŒƒrƒ…[•”‚ðƒNƒŠƒA end; end else begin - frmSender.actVoteMessage.Enabled := false; - frmSender.actAgreeMessage.Enabled := false; - frmSender.actInsertCue.Enabled := false; - mnPopUpCopyScript.Enabled := false; + StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + 'Œ'; StatusBar.Panels[1].Text := ''; UpdateScript(Script); // ƒƒOƒvƒŒƒrƒ…[•”ƒNƒŠƒA end; end; tbtnSaveLog.Enabled := lvwLog.Items.Count > 0; end else begin - frmSender.actVoteMessage.Enabled := false; - frmSender.actAgreeMessage.Enabled := false; - frmSender.actInsertCue.Enabled := false; - mnPopUpCopyScript.Enabled := false; StatusBar.Panels[0].Text := ''; UpdateScript(''); // ƒƒOƒvƒŒƒrƒ…[•”ƒNƒŠƒA end; + frmSender.actVoteMessage.Enabled := Selected and IsNormalBottle; + frmSender.actAgreeMessage.Enabled := Selected and IsNormalBottle; + frmSender.actSendToEditor.Enabled := Selected and IsNormalBottle; + frmSender.actInsertCue.Enabled := Selected; + frmSender.actDeleteLogItem.Enabled := Selected; + mnPopUpCopyScript.Enabled := Selected and IsNormalBottle; + mnPopupCopyGhost.Enabled := Selected and IsNormalBottle; end; procedure TfrmLog.lvwLogDblClick(Sender: TObject); -var Script: String; - SOpt: TSstpSendOptions; - Ghost: String; - Log: TLogItem; +var Script, ErrorMes: String; + Log, CueItem: TLogItem; + Res: integer; begin - if lvwLog.Selected = nil then Exit; - //Log := TLogItem(lvwLog.Selected.Data); + if lvwLog.Selected = nil then + Exit; Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index]; if Log = nil then Exit; - if Log.LogType <> ltBottle then Exit; - Script := frmSender.ScriptTransForSSTP(Log.Script); - if Script = '' then begin - ShowMessage('–â‘è‚Ì‚ ‚éƒXƒNƒŠƒvƒg‚Å‚·BÄ¶‚Å‚«‚Ü‚¹‚ñBƒNƒ‰ƒCƒAƒ“ƒg‚ðÅV”Å‚É‚µ‚Ä‚Ý‚Ä‚­‚¾‚³‚¢B'); + if Log.LogType <> ltBottle then Exit; + Script := frmSender.ScriptTransForSSTP(Log.Script, ErrorMes); + if ErrorMes <> '' then + begin + Res := MessageDlg('–â‘è‚Ì‚ ‚éƒXƒNƒŠƒvƒg‚Å‚·BÄ¶‚Å‚«‚Ü‚¹‚ñB'#13#10+ + ErrorMes + #13#10 + + '‹­§“I‚ɍж‚µ‚Ü‚·‚©?'#13#10, + mtWarning, mbOkCancel, 0 + ); + if Res = mrCancel then + Exit; end; - if ChannelList.Channel[Log.Channel] <> nil then - Ghost := ChannelList.Channel[Log.Channel].Ghost; - //–Ú•WƒS[ƒXƒgŒˆ’è - if Log.Ghost <> '' then Ghost := Log.Ghost; - //ƒ^[ƒQƒbƒgƒS[ƒXƒgŠm’è - Ghost := frmSender.SetHWndToFavoriteGhost(Ghost); - frmSender.DirectSstp.SstpSender := 'SSTP Bottle -yƒƒOÄ¶z'; - if Pref.NoTranslate then SOpt := [soNoTranslate] else SOpt := []; - frmSender.DirectSstp.SstpSEND(Script, SOpt, frmSender.GhostNameToSetName(Ghost)); + CueItem := TLogItem.Create(Log); + try + CueItem.Script := Script; + frmSender.BottleSstp.Unshift(CueItem); + except + CueItem.Free; + end; end; procedure TfrmLog.UpdateScriptConversationColor(const Script: String); @@ -331,7 +409,6 @@ begin frmSender.DoTrans(scr, [toConvertURL]); SsParser.LeaveEscape := false; SsParser.InputString := scr; - SsParser.LeaveEscape := true; UnyuTalking := false; Talked := false; //'\h\u\h\u'‚̂悤‚ȃXƒNƒŠƒvƒg‚ŋ󂫍s‚ðì‚ç‚È‚¢‚½‚ß‚Ì‘[’u InSynchronized := false; @@ -383,48 +460,6 @@ begin end; end; -procedure TfrmLog.UpdateScriptConversationNoColor(const Script: String); -var Scr: String; - i: integer; - UnyuTalking, Talked, LastUnyuTalked, InSynchronize, LastInSynchronize: boolean; -begin - Scr := Script; - frmSender.DoTrans(Scr, [toConvertURL]); - SsParser.LeaveEscape := false; - SsParser.InputString := Scr; - SsParser.LeaveEscape := true; - edtScript.Text := ''; - edtScript.Color := clWindow; - edtScript.DefAttributes.Color := clWindowText; - edtScript.SelAttributes.Color := clWindowText; - Talked := false; - UnyuTalking := false; - LastUnyuTalked := false; - InSynchronize := false; - LastInSynchronize := false; - for i := 0 to SsParser.Count-1 do begin - if SsParser[i] = '\u' then UnyuTalking := true; - if SsParser[i] = '\h' then UnyuTalking := false; - if SsParser[i] = '\_s' then InSynchronize := not InSynchronize; - if SsParser.MarkUpType[i] in [mtStr, mtMeta] then begin - if not Talked then begin // ƒXƒNƒŠƒvƒgÅ‰‚̃ZƒŠƒt - if InSynchronize then Scr := '—¼F' - else if UnyuTalking then Scr := '‚¤:' else Scr := '‚³:'; - end; - if Talked and ((UnyuTalking <> LastUnyuTalked) or (InSynchronize <> LastInSynchronize)) then begin - Scr := Scr + #13#10; - if InSynchronize then Scr := Scr + '—¼F' - else if UnyuTalking then Scr := Scr + '‚¤:' else Scr := Scr + '‚³:'; - end; - Scr := Scr + SsParser[i]; - Talked := true; - LastInSynchronize := InSynchronize; - LastUnyuTalked := UnyuTalking; - end; - end; - edtScript.Text := Scr; -end; - procedure TfrmLog.lvwLogKeyPress(Sender: TObject; var Key: Char); begin if Key = #13 then lvwLogDblClick(Sender); @@ -448,8 +483,12 @@ var SortType: TBottleLogSortType; SelectedMID: String; SortColumn: integer; begin + if SelectedBottleLog = nil then + Exit; if lvwLog.Selected <> nil then - SelectedMID := SelectedBottleLog.Bottles[lvwLog.Selected.Index].MID; + SelectedMID := SelectedBottleLog.Bottles[lvwLog.Selected.Index].MID + else + SelectedMID := ''; SortColumn := Column.Index; case SortColumn-1 of @@ -459,12 +498,14 @@ begin subVotes: SortType := stVote; subAgrees: SortType := stAgree; subScript: SortType := stScript; - else SortType := stLogTime; + else + SortType := stLogTime; end; SelectedBottleLog.SortBottles(SortType); lvwLog.Invalidate; - SelAndFocusMessage(SelectedMID); + if Length(SelectedMID) > 0 then + SelAndFocusMessage(SelectedMID); end; @@ -530,12 +571,7 @@ end; procedure TfrmLog.mnSaveLogXMLClick(Sender: TObject); begin if SelectedBottleLog = nil then Exit; - SaveDialog.FileName := GetDefaultFileName(SelectedBottleLog.Title, '.xml'); - SaveDialog.InitialDir := ExtractFileDir(Application.ExeName); - SaveDialog.DefaultExt := 'xml'; - SaveDialog.FilterIndex := 3; - if SaveDialog.Execute then - SelectedBottleLog.SaveToXmlFile(SaveDialog.FileName, XMLDocument); + DoSaveLogXML(SelectedBottleLog); end; procedure TfrmLog.lvwLogData(Sender: TObject; Item: TListItem); @@ -580,13 +616,8 @@ end; procedure TfrmLog.UpdateWindow; var EnabledFlag: boolean; begin - if true then begin // ColorScript - if lvwLog.Color <> Pref.BgColor then lvwLog.Color := Pref.BgColor; - if lvwLog.Font.Color <> Pref.TalkColorH then lvwLog.Font.Color := Pref.TalkColorH; - end else begin - if lvwLog.Color <> clWindow then lvwLog.Color := clWindow; - if lvwLog.Font.Color <> clWindowText then lvwLog.Font.Color := clWindowText; - end; + lvwLog.Color := Pref.BgColor; + lvwLog.Font.Color := Pref.TalkColorH; if SelectedBottleLog <> nil then begin Caption := 'ƒƒO - ' + SelectedBottleLog.Title; StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + 'Œ'; @@ -661,8 +692,11 @@ var i, u, j: integer; begin Result.Clear; SsParser.InputString := Script; + SsParser.LeaveEscape := true; for i := 0 to SsParser.Count-1 do begin - if (SsParser.Match(SsParser[i], '\URL%b') > 0) then begin + if (SsParser.Match(SsParser[i], '\URL%b') > 0) + and (SsParser.MarkUpType[i] = mtTag) then + begin for u := 7 downto 1 do begin if (SsParser.Match(SsParser[i], '\URL%b'+StringReplace(StringOfChar('-', u*2), @@ -702,66 +736,11 @@ begin // end; -procedure TfrmLog.lvwLogCustomDrawSubItem(Sender: TCustomListView; - Item: TListItem; SubItem: Integer; State: TCustomDrawState; - var DefaultDraw: Boolean); -{var - DestRect: TRect; - Script: String; - i, x, w: integer; - SavedDC: integer; - Mark: TSsMarkUpType;} -begin - Exit // !! - {if (SubItem <> SubScript+1) or (not Pref.ColorScript) then Exit; // DefaultDraw = true - // Custom Script Coloring - DefaultDraw := false; - SavedDC := SaveDC(lvwLog.Canvas.Handle); - try - ListView_GetSubItemRect(lvwLog.Handle, Item.Index, SubScript+1, LVIR_BOUNDS, @DestRect); - - lvwLog.Canvas.Brush.Style := bsSolid; - if cdsSelected in State then begin - lvwLog.Canvas.Brush.Color := clHighlight - end else begin - lvwLog.Canvas.Brush.Color := Pref.BgColor; - end; - lvwLog.Canvas.FillRect(DestRect); - lvwLog.Canvas.Brush.Style := bsClear; - - Script := Item.SubItems[SubScript]; - // DrawTextEx(lvwLog.Canvas.Handle, PChar(Script), -1, DestRect, DT_END_ELLIPSIS, nil); - SsParser.InputString := Script; - x := 6; - for i := 0 to SsParser.Count - 1 do begin - Mark := SsParser.MarkUpType[i]; - case Mark of - mtMeta: lvwLog.Canvas.Font.Color := Pref.MetaWordColor; - mtTag: lvwLog.Canvas.Font.Color := Pref.MarkUpColor; - mtTagErr: lvwLog.Canvas.Font.Color := Pref.MarkErrorColor; - else begin - lvwLog.Canvas.Font.Color := Pref.TalkColorH; - end; - end; - w := lvwLog.Canvas.TextWidth(SsParser[i]); - lvwLog.Canvas.TextRect(DestRect, DestRect.Left + x, DestRect.Top + 2, SsParser[i]); - x := x + w; - if DestRect.Right - DestRect.Left < x then Break; - end; - finally - RestoreDC(lvwLog.Canvas.Handle, SavedDC); - end;} -end; - procedure TfrmLog.UpdateScript(const Script: String); begin if Script <> FLastScript then begin if Pref.LogWindowPreviewStyle = psConversation then begin - if true then begin {TODO: ColorScript} - UpdateScriptConversationColor(Script); - end else begin - UpdateScriptConversationNoColor(Script); - end; + UpdateScriptConversationColor(Script); end else begin UpdateScriptScript(Script); end; @@ -785,6 +764,7 @@ begin for i := 0 to Items.Count-1 do Items[i].Checked := (Sender as TMenuItem).Tag = Items[i].Tag; Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle((Sender as TMenuItem).Tag); + PreviewStyleChange; FLastScript := ''; lvwLogChange(self, lvwLog.Selected, ctState); end; @@ -794,13 +774,7 @@ var UnyuTalking, InSynchronized: boolean; i: integer; begin - if true then begin // {TODO: ColorScrpt} - edtScript.Color := Pref.BgColor; - end else begin - edtScript.Color := clWindow; - edtScript.DefAttributes.Color := clWindowText; - edtScript.SelAttributes.Color := clWindowText; - end; + edtScript.Color := Pref.BgColor; SsParser.LeaveEscape := true; SsParser.InputString := Script; edtScript.Text := ''; @@ -808,28 +782,26 @@ begin UnyuTalking := false; InSynchronized := false; for i := 0 to SsParser.Count-1 do begin - if true then begin // {TODO: ColorScript} - case SsParser.MarkUpType[i] of - mtStr: begin - if InSynchronized then - edtScript.SelAttributes.Color := Pref.TalkColorS - else if UnyuTalking then - edtScript.SelAttributes.Color := Pref.TalkColorU - else - edtScript.SelAttributes.Color := Pref.TalkColorH; - end; - mtTag: begin - edtScript.SelAttributes.Color := Pref.MarkUpColor; - if SsParser[i] = '\h' then - UnyuTalking := false - else if SsParser[i] = '\u' then - UnyuTalking := true - else if SsParser[i] = '\_s' then - InSynchronized := not InSynchronized; - end; - mtMeta: edtScript.SelAttributes.Color := Pref.MetaWordColor; - mtTagErr: edtScript.SelAttributes.Color := Pref.MarkErrorColor; + case SsParser.MarkUpType[i] of + mtStr: begin + if InSynchronized then + edtScript.SelAttributes.Color := Pref.TalkColorS + else if UnyuTalking then + edtScript.SelAttributes.Color := Pref.TalkColorU + else + edtScript.SelAttributes.Color := Pref.TalkColorH; + end; + mtTag: begin + edtScript.SelAttributes.Color := Pref.MarkUpColor; + if SsParser[i] = '\h' then + UnyuTalking := false + else if SsParser[i] = '\u' then + UnyuTalking := true + else if SsParser[i] = '\_s' then + InSynchronized := not InSynchronized; end; + mtMeta: edtScript.SelAttributes.Color := Pref.MetaWordColor; + mtTagErr: edtScript.SelAttributes.Color := Pref.MarkErrorColor; end; edtScript.SelText := SsParser[i]; if (SsParser[i] = '\n') and (Pref.LogWindowPreviewStyle = psScriptWithLineBreak) then @@ -845,6 +817,7 @@ begin if sel > Ord(High(TLogWindowPreviewStyle)) then sel := 0; Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle(sel); FLastScript := ''; + PreviewStyleChange; lvwLogChange(self, lvwLog.Selected, ctState); end; @@ -858,11 +831,15 @@ end; procedure TfrmLog.tabBottleLogChange(Sender: TObject); begin + // StatusBar‚ÌŒ”•\Ž¦‚âListView.Items.Count‚ðXV‚·‚é UpdateWindow; - if SelectedBottleLog.SelectedIndex >= 0 then begin - lvwLog.Items[SelectedBottleLog.SelectedIndex].Selected := true; - if lvwLog.Focused then lvwLog.Selected.Focused := true; - end; + // ƒAƒCƒeƒ€‚Ì‘I‘ðó‘Ԃ𕜋A‚·‚é + with SelectedBottleLog do + if (SelectedIndex >= 0) and (Count > SelectedIndex) then + begin + lvwLog.Items[SelectedIndex].Selected := true; + if lvwLog.Focused then lvwLog.Selected.Focused := true; + end; lvwLogChange(Self, nil, ctState); end; @@ -946,46 +923,59 @@ end; procedure TfrmLog.mnCloseTabClick(Sender: TObject); begin - FBottleLogList.Delete(tabBottleLog.Tag); - UpdateTab; - UpdateWindow; - lvwLogChange(Self, nil, ctState); + DoCloseTab(tabBottleLog.Tag); end; procedure TfrmLog.tbtnFindBottleClick(Sender: TObject); -var Query: String; - ResultLog: TBottleLogList; - Item1, Item2: TLogItem; - i, matched: integer; +var ResultLog: TBottleLogList; + Cond: TSearchCond; + i: integer; + CList, GList: THashedStringList; begin - if SelectedBottleLog = nil then Exit; - if SelectedBottleLog.Count = 0 then begin - ShowMessage('ŒŸõ‘Ώۂª‹ó‚Å‚·B'); - Exit; - end; - Query := ''; - matched := 0; - if InputQuery('ƒXƒNƒŠƒvƒg–{•¶‚ðŒŸõ', 'ŒŸõ•¶Žš—ñ', Query) then begin - if Query = '' then Exit; - ResultLog := TBottleLogList.Create('ŒŸõŒ‹‰Ê'); - for i := 0 to SelectedBottleLog.Count-1 do begin - Item1 := SelectedBottleLog.Items[i] as TLogItem; - if AnsiContainsText(Item1.Script, Query) and (Item1.LogType = ltBottle) then begin - matched := matched + 1; - Item2 := TLogItem.Create(ltBottle, Item1.MID, Item1.Channel, - Item1.Script, Item1.Ghost, Item1.LogTime); - Item2.State := lsOpened; - Item2.Votes := Item1.Votes; - Item2.Agrees := Item1.Agrees; - ResultLog.Add(Item2); + Application.CreateForm(TfrmSearchLog, frmSearchLog); + Cond := TSearchCond.Create(nil); + try + try + with frmSearchLog do + begin + // Œ»ÝƒƒO‚É‚ ‚éƒS[ƒXƒg‚ƃ`ƒƒƒ“ƒlƒ‹‚̃ŠƒXƒg‚ðŽæ“¾ + // d‚½‚¢‚©‚à?? + CList := THashedStringList.Create; + GList := THashedStringList.Create; + try + for i := 0 to BottleLogList.Count-1 do + begin + with BottleLogList[i] as TBottleLogList do + begin + ExtractUniqueChannels(CList); + ExtractUniqueGhosts(GList); + end; + end; + CList.Sort; + GList.Sort; + ChannelList := CList; + GhostList := GList; + finally + CList.Free; + GList.Free; + end; + if not Execute then + Exit + else + Cond.Assign(Condition); end; + finally + frmSearchLog.Release; end; - if matched = 0 then - ResultLog.AddSystemLog('Œ©‚‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½'); + // ŒŸõŽÀs + ResultLog := DoSearchLog(Cond); + // Vƒ^ƒu‚ðì¬‚µ‚ĉæ–ʍXV BottleLogList.Add(ResultLog); UpdateTab; tabBottleLog.TabIndex := BottleLogList.Count-1; UpdateWindow; + finally + Cond.Free; end; end; @@ -998,15 +988,17 @@ begin for i := 0 to OpenDialog.Files.Count-1 do begin BottleLog := TBottleLogList.Create(ExtractFileName(OpenDialog.Files[i])); try - BottleLog.LoadFromXMLFile(OpenDialog.Files[i], XMLDocument); - except - on E: EXMLFileOpenException do begin - Beep; - ShowMessage(E.Message); - FreeAndNil(BottleLog); + with BottleLog do + begin + OnLoaded := LogLoaded; + OnLoadFailure := LogLoadFailure; + OnLoadWork := LogLoadWork; + BottleLog.LoadFromXMLFile(OpenDialog.Files[i]); end; + Index := BottleLogList.Add(BottleLog); // ÅŒã‚ÉŠJ‚¢‚½ƒƒO‚̈ʒu‚ð‹L‰¯ + except + BottleLog.Free; end; - if BottleLog <> nil then Index := BottleLogList.Add(BottleLog); // ÅŒã‚ÉŠJ‚¢‚½ƒƒO‚̈ʒu‚ð‹L‰¯ end; UpdateTab; if Index >= 0 then tabBottleLog.TabIndex := Index; @@ -1018,6 +1010,7 @@ function TfrmLog.GetDefaultFileName(const Name, Ext: String): String; begin Result := StringReplace(Name, '/', '', [rfReplaceAll]); Result := StringReplace(Result, ' ', '', [rfReplaceAll]); + Result := SafeFileName(Result); Result := ChangeFileExt(Result, Ext); end; @@ -1067,38 +1060,58 @@ end; procedure TfrmLog.tabBottleLogDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); var TargetRect: TRect; - OldDest: integer; + OldDest, Index: integer; + dummy: boolean; begin - Accept := Source = tabBottleLog; - if not Accept then Exit; - with tabBottleLog do begin - OldDest := FDragTabDest; - FDragTabDest := IndexOfTabAt(X, Y); - if FDragTabDest = -1 then begin - Accept := false; //‚±‚̏ꍇ‚̓hƒƒbƒv‚ð”F‚ß‚È‚¢ - Exit; - end; - with Canvas do begin - Pen.Mode := pmNot; - Pen.Width := 3; - end; - if (OldDest <> FDragTabDest) and (OldDest >= 0) then begin - //ˆÈ‘O‚̘güÁ‹Ž - TargetRect := TabRect(OldDest); - with Canvas do begin - Brush.Style := bsClear; - Rectangle(TargetRect.Left, TargetRect.Top, - TargetRect.Right, TargetRect.Bottom); + // ƒ^ƒu‚̃hƒ‰ƒbƒO(ƒ^ƒu‚̏‡”Ô“ü‚ê‘Ö‚¦)‚Ü‚½‚́A + // ƒƒOƒAƒCƒeƒ€‚̃hƒ‰ƒbƒO(ƒƒO‚ð•Ê‚̃^ƒu‚Ɉړ®)‚Ì + // —¼•û‚̃hƒ‰ƒbƒO‚ðŽó‚¯•t‚¯‚é + Accept := false; + if Source = tabBottleLog then + begin + // ƒ^ƒu‚̏‡”Ô“ü‚ê‘Ö‚¦‚̏ꍇ + Accept := true; + with tabBottleLog do begin + OldDest := FDragTabDest; + FDragTabDest := IndexOfTabAt(X, Y); + if FDragTabDest = -1 then begin + Accept := false; //‚±‚̏ꍇ‚̓hƒƒbƒv‚ð”F‚ß‚È‚¢ + Exit; end; - end; - if (OldDest <> FDragTabDest) then begin - //V‚µ‚¢˜gü•`‰æ - TargetRect := TabRect(FDragTabDest); with Canvas do begin - Brush.Style := bsClear; - Rectangle(TargetRect.Left, TargetRect.Top, - TargetRect.Right, TargetRect.Bottom); + Pen.Mode := pmNot; + Pen.Width := 3; end; + if (OldDest <> FDragTabDest) and (OldDest >= 0) then begin + //ˆÈ‘O‚̘güÁ‹Ž + TargetRect := TabRect(OldDest); + with Canvas do begin + Brush.Style := bsClear; + Rectangle(TargetRect.Left, TargetRect.Top, + TargetRect.Right, TargetRect.Bottom); + end; + end; + if (OldDest <> FDragTabDest) then begin + //V‚µ‚¢˜gü•`‰æ + TargetRect := TabRect(FDragTabDest); + with Canvas do begin + Brush.Style := bsClear; + Rectangle(TargetRect.Left, TargetRect.Top, + TargetRect.Right, TargetRect.Bottom); + end; + end; + end; + end else if Source is TBottleLogDragObject then + begin + // ƒƒO€–ڂ̃hƒ‰ƒbƒO(ƒƒO‚ð•Ê‚̃^ƒu‚Ɉړ®‚·‚é)‚̏ꍇ + Index := tabBottleLog.IndexOfTabAt(X, Y); + if tabBottleLog.TabIndex <> Index then + begin + FLVDragDest := -1; // ˜gü‚Í‚Ü‚¾•\Ž¦‚³‚ê‚È‚¢‚Í‚¸ + // ƒ^ƒu‚ðØ‘Ö‚¦‚é + tabBottleLogChanging(Self, dummy); + tabBottleLog.TabIndex := Index; + UpdateWindow; end; end; end; @@ -1124,7 +1137,656 @@ end; procedure TfrmLog.LogLoadWork(Sender: TObject); begin - if Sender = SelectedBottleLog then lvwLog.Invalidate; + if Sender = SelectedBottleLog then + begin + lvwLog.Invalidate; + lvwLog.Items.Count := SelectedBottleLog.Count; + end; +end; + +procedure TfrmLog.lvwLogDrawItem(Sender: TCustomListView; Item: TListItem; + Rect: TRect; State: TOwnerDrawState); +var + DestRect: TRect; + Script: String; + Ico: TIcon; + sub, Ex: integer; + Bottle: TLogItem; + DummyStr: TStringList; +begin + Bottle := SelectedBottleLog.Bottles[Item.Index]; + if Bottle.HasURL = huUndefined then + begin + DummyStr := TStringList.Create; + try + ExtractURLs(Bottle.Script, DummyStr); + if DummyStr.Count > 0 then + Bottle.HasURL := huYes + else + Bottle.HasURL := huNo; + finally + DummyStr.Free; + end; + end; + + // ”wŒiÁ‹Ž + ListView_GetItemRect(lvwLog.Handle, Item.Index, DestRect, LVIR_BOUNDS); + + // ”wŒi‚̐F‚Í‘I‘ðó‘ԁE‘I‘ð”ñƒAƒNƒeƒBƒuó‘ԁE’ʏíó‘Ô‚Ì3’Ê‚è + lvwLog.Canvas.Brush.Style := bsSolid; + if Item.Selected then begin + if lvwLog.Focused then + lvwLog.Canvas.Brush.Color := clHighlight + else + lvwLog.Canvas.Brush.Color := clBtnFace; + end else begin + lvwLog.Canvas.Brush.Color := Pref.BgColor; + end; + lvwLog.Canvas.FillRect(DestRect); + lvwLog.Canvas.Brush.Style := bsClear; + // ƒtƒH[ƒJƒX‚ª‚ ‚éê‡‚ɂ̓tƒH[ƒJƒX‚̘gü‚ðˆø‚­ + if Item.Focused and lvwLog.Focused then + lvwLog.Canvas.DrawFocusRect(DestRect); + + // ƒhƒ‰ƒbƒO’†‚È‚ç˜gü‚ð•`‰æ‚·‚é + if FLVDragDest = Item.Index then + begin + DestRect := Item.DisplayRect(drBounds); + DrawListViewDragBorder(DestRect); + end; + + if Item.Selected then + begin + if lvwLog.Focused then + lvwLog.Canvas.Font.Color := clHighlightText + else + lvwLog.Canvas.Font.Color := clWindowText; + end else + lvwLog.Canvas.Font.Color := Pref.TalkColorH; + lvwLog.Canvas.Refresh; + + // ƒLƒƒƒvƒVƒ‡ƒ“(“ú•t) + ListView_GetItemRect(lvwLog.Handle, Item.Index, DestRect, LVIR_LABEL); + Inc(DestRect.Left, 2); + Inc(DestRect.Top, 2); + Dec(DestRect.Right, 2); + DrawTextEx(lvwLog.Canvas.Handle, PChar(Item.Caption), -1, DestRect, + DT_SINGLELINE or DT_END_ELLIPSIS, nil); + ListView_GetItemRect(lvwLog.Handle, Item.Index, DestRect, LVIR_ICON); + Ico := TIcon.Create; + try + lvwLog.SmallImages.GetIcon(Item.ImageIndex, Ico); + lvwLog.Canvas.Draw(DestRect.Left, DestRect.Top, Ico); + finally + Ico.Free; + end; + // ƒLƒƒƒvƒVƒ‡ƒ“‚Å‚àƒXƒNƒŠƒvƒg‚Å‚à‚È‚¢‚à‚Ì + for sub := 0 to Item.SubItems.Count-1 do + begin + if sub = SubScript then Continue; + ListView_GetSubItemRect(lvwLog.Handle, Item.Index, sub + 1, + LVIR_BOUNDS, @DestRect); + if DestRect.Right - DestRect.Left <= 16 then + begin + // ‹·‚·‚¬‚éê‡‚Í•¶Žš—ñ‚ð•`‰æ‚µ‚È‚¢B + // 16‚Æ‚¢‚¤”Žš‚ÍŽÀ‘ª’lB‰½‚©‚̃oƒO‚Á‚Û + lvwLog.Canvas.FillRect(DestRect); + Continue; + end; + Inc(DestRect.Left, 2); + Inc(DestRect.Top, 2); + Dec(DestRect.Right, 2); + Ex := DT_NOPREFIX or DT_SINGLELINE or DT_END_ELLIPSIS; + if lvwLog.Columns[sub+1].Alignment = taRightJustify then + Ex := Ex or DT_RIGHT; + DrawTextEx(lvwLog.Canvas.Handle, PChar(Item.SubItems[sub]), -1, DestRect, + Ex, nil); + end; + // ƒXƒNƒŠƒvƒg + ListView_GetSubItemRect(lvwLog.Handle, Item.Index, SubScript + 1, + LVIR_BOUNDS, @DestRect); + Script := Item.SubItems[SubScript]; + DrawSingleLineScript(Bottle, DestRect, Item); + +end; + +procedure TfrmLog.DrawSingleLineScript(LogItem: TLogItem; + Rect: TRect; Item: TListItem); +var + i, x, w: integer; + UnyuTalking, Synchronized, Spaced: boolean; + Mark: TSsMarkUpType; + Script: String; + Ico: TIcon; + procedure ScopeChange; + begin + if (not Spaced) and (Pref.LogListPreviewStyle = psTagStripped) then + begin + Inc(x, 7); + Spaced := true; + end; + end; +begin + Script := LogItem.Script; + x := 3; + + if LogItem.HasURL = huYes then + begin + Ico := TIcon.Create; + try + lvwLog.SmallImages.GetIcon(IconURL, Ico); + lvwLog.Canvas.Draw(Rect.Left + x, Rect.Top, Ico); + Inc(x, 20); + finally + Ico.Free; + end; + end; + + if Pref.LogListPreviewStyle = psNoColor then + begin + Inc(Rect.Left, x); + Inc(Rect.Top, 2); + Dec(Rect.Right, 2); + DrawTextEx(lvwLog.Canvas.Handle, PChar(Script), -1, Rect, + DT_SINGLELINE or DT_END_ELLIPSIS or DT_NOPREFIX, nil); + Exit; + end; + + SsParser.LeaveEscape := Pref.LogListPreviewStyle = psNormal; + SsParser.InputString := Script; + + UnyuTalking := false; + Synchronized := false; + Spaced := true; // ƒ^ƒOÈ—ª•\Ž¦Žž‚É•s•K—v‚ɃXƒR[ƒv•ÏŠ·Žž‚̃Xƒy[ƒX‚ð‹ó‚¯‚È‚¢ + // ‚½‚߂̃tƒ‰ƒO + for i := 0 to SsParser.Count - 1 do begin + if SsParser[i] = '\h' then + begin + UnyuTalking := false; + ScopeChange; + end else if SsParser[i] = '\u' then + begin + UnyuTalking := true; + ScopeChange; + end else if SsParser[i] = '\_s' then + begin + Synchronized := not Synchronized; + ScopeChange; + end else if (Pos('\n', SsParser[i]) = 1) or (SsParser[i] = '\c') then + begin + ScopeChange; + end; + Mark := SsParser.MarkUpType[i]; + case Mark of + mtMeta: + begin + lvwLog.Canvas.Font.Color := Pref.MetaWordColor; + Spaced := false; + end; + mtTag: + if Pref.LogListPreviewStyle = psNormal then + lvwLog.Canvas.Font.Color := Pref.MarkUpColor + else + begin + Continue; + end; + mtTagErr: + lvwLog.Canvas.Font.Color := Pref.MarkErrorColor; + else begin + Spaced := false; + if Synchronized then + lvwLog.Canvas.Font.Color := Pref.TalkColorS + else if UnyuTalking then + lvwLog.Canvas.Font.Color := Pref.TalkColorU + else + lvwLog.Canvas.Font.Color := Pref.TalkColorH; + end; + end; + if Item.Selected then + begin + if lvwLog.Focused then + lvwLog.Canvas.Font.Color := clHighlightText + else + lvwLog.Canvas.Font.Color := clWindowText; + end; + lvwLog.Canvas.Refresh; + w := lvwLog.Canvas.TextWidth(SsParser[i]); + lvwLog.Canvas.TextRect(Rect, Rect.Left + x, Rect.Top + 2, SsParser[i]); + x := x + w; + if Rect.Right - Rect.Left < x then Break; + end; +end; + +procedure TfrmLog.mnListPreviewStyleClick(Sender: TObject); +var i: integer; +begin + with PopupMenuListPreviewStyle do + for i := 0 to Items.Count-1 do + Items[i].Checked := (Sender as TMenuItem).Tag = Items[i].Tag; + Pref.LogListPreviewStyle := TLogListPreviewStyle((Sender as TMenuItem).Tag); + lvwLog.Invalidate; +end; + +procedure TfrmLog.tbtnListPreviewStyleClick(Sender: TObject); +var sel: integer; +begin + sel := Ord(Pref.LogListPreviewStyle); + sel := sel + 1; + if sel > Ord(High(TLogListPreviewStyle)) then sel := 0; + Pref.LogListPreviewStyle := TLogListPreviewStyle(sel); + lvwLog.Invalidate; +end; + +procedure TfrmLog.PopupMenuListPreviewStylePopup(Sender: TObject); +var i: integer; +begin + with PopupMenuListPreviewStyle do + for i := 0 to Items.Count-1 do + Items[i].Checked := Items[i].Tag = Ord(Pref.LogListPreviewStyle) +end; + +procedure TfrmLog.PreviewStyleChange; +begin + if Pref.LogWindowPreviewStyle = psImageConversation then + begin + if Spps.Count = 0 then + ShowMessage('ƒT[ƒtƒBƒXƒvƒŒƒrƒ…[—pƒvƒ‰ƒOƒCƒ“‚ª‘¶Ý‚µ‚Ü‚¹‚ñB'); + edtScript.Visible := false; + TalkShowFrame.Visible := true; + end else + begin + edtScript.Visible := true; + TalkShowFrame.Visible := false; + end; +end; + +procedure TfrmLog.lvwLogDragOver(Sender, Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); +var + Target: TListItem; + OldDest: integer; + Rec: TRect; // ƒ_ƒ~[B +begin + Accept := False; + // ‚Æ‚è‚ ‚¦‚¸Žó‚¯•t‚¯‚é‰Â”\«‚ª‚ ‚é‚Ì‚ÍTBottleLogDragObject‚¾‚¯ + if not (Source is TBottleLogDragObject) then + Exit; + + Target := lvwLog.GetItemAt(X, Y); + + // ‚±‚êˆÈ‘O‚É•`‰æ‚³‚ê‚Ä‚¢‚½˜g‚̃Cƒ“ƒfƒbƒNƒX + OldDest := FLVDragDest; + + // ƒhƒƒbƒvˆÊ’u‚É Item ‚ª‚ ‚ê‚΃hƒƒbƒv‚ð‹–‰Â‚·‚é + if Target <> nil then + begin + Accept := true; + FLVDragDest := Target.Index; + end else + begin + Accept := true; + FLVDragDest := -1; + end; + + // ˆÈ‘O‚̘gü‚ðíœ + if (OldDest > -1) and (FLVDragDest <> OldDest) then + begin + Rec := lvwLog.Items[OldDest].DisplayRect(drBounds); + DrawListViewDragBorder(Rec); + end; + // ƒhƒ‰ƒbƒOæ‚̘gü‚ð•`‰æ + if (Target <> nil) and (FLVDragDest <> OldDest) then + begin + Rec := Target.DisplayRect(drBounds); + DrawListViewDragBorder(Rec); + end; + + // ƒXƒNƒ[ƒ‹ŠÖŒW + if lvwLog.Items.Count > 0 then + begin + if (lvwLog.topItem <> nil) and (Y - lvwLog.TopItem.Top < 10) then + begin + FLVScrollDir := lvScrollDown; + if not timScrollTimer.Enabled then + timScrollTimer.Enabled := true; + end else if (lvwLog.Height - Y) < 10 then + begin + FLVScrollDir := lvScrollUp; + if not timScrollTimer.Enabled then + timScrollTimer.Enabled := true; + end + else + timScrollTimer.Enabled := false; + end else + timScrollTimer.Enabled := false; +end; + +procedure TfrmLog.lvwLogDragDrop(Sender, Source: TObject; X, Y: Integer); +var + TargetItem: integer; + Src: TBottleLogDragObject; + SrcLog: TObject; +begin + timScrollTimer.Enabled := false; + + if not (Source is TBottleLogDragObject) then + Exit; + Src := Source as TBottleLogDragObject; + + if lvwLog.GetItemAt(X, Y) <> nil then + TargetItem := lvwLog.GetItemAt(X, Y).Index + else + TargetItem := -1; + + lvwLog.Items.BeginUpdate; // ƒhƒƒbƒv’†‚Í•\Ž¦‚ð—}Ž~‚·‚é@d—vI + try + // ƒhƒƒbƒvˆÊ’u‚É Item ‚ðˆÚ“®‚·‚é + if (GetAsyncKeyState(VK_CONTROL) and $8000) > 0 then + begin // ƒRƒs[ˆÚ“®‚̏ꍇ + SrcLog := TLogItem.Create(Src.LogItem); + end else // ˆÚ“®‚¾‚¯‚·‚éê‡ + begin + SrcLog := Src.BottleLogList.Extract(Src.LogItem); + end; + if TargetItem >= 0 then + begin + // ‚·‚Å‚É‘¶Ý‚·‚éƒAƒCƒeƒ€‚̏ã‚Ƀhƒƒbƒv‚µ‚½ê‡ + SelectedBottleLog.Insert(TargetItem, SrcLog); + end else + begin + // ListView‚Ì—]”’‚Ƀhƒƒbƒv‚µ‚½ê‡(Insert‚Å‚«‚È‚¢) + TargetItem := SelectedBottleLog.Add(SrcLog); + end; + lvwLog.Items[TargetItem].Selected := true; + lvwLog.Items[TargetItem].Focused := true; + finally + lvwLog.Items.EndUpdate; + UpdateWindow; + end; +end; + +procedure TfrmLog.timScrollTimerTimer(Sender: TObject); +var + ScrollHeight: Integer; +begin + // ƒXƒNƒ[ƒ‹—Ê‚ð‹‚ß‚é + ScrollHeight := 0; + if lvwLog.Items.Count > 2 then + begin + ScrollHeight := lvwLog.Items[1].Top - lvwLog.Items[0].Top; + end; + + case FLVScrollDir of + lvScrollUp: lvwLog.Scroll(0, ScrollHeight); + lvSCrollDown: lvwLog.Scroll(0, -ScrollHeight); + end; + lvwLog.Invalidate; // ÅV‚̏ó‘Ԃɍĕ`‰æ‚·‚é + lvwLog.Update; +end; + +procedure TfrmLog.mnChangeTabNameClick(Sender: TObject); +var Name: String; +begin + Name := (FBottleLogList[tabBottleLog.Tag] as TBottleLogList).Title; + InputQuery('–¼‘O‚̕ύX', 'V‚µ‚¢ƒ^ƒu‚Ì–¼‘O', Name); + (FBottleLogList[tabBottleLog.Tag] as TBottleLogList).Title := Name; + UpdateTab; +end; + +procedure TfrmLog.lvwLogStartDrag(Sender: TObject; + var DragObject: TDragObject); +var Drag: TBottleLogDragObject; +begin + // ’ʏí‚ÌListView—p‚̃hƒ‰ƒbƒOƒIƒuƒWƒFƒNƒg‚Í + // OS‚É‚æ‚Á‚ẮAˆÚ“®‚·‚é‚Æ‚«‚ɃAƒCƒeƒ€‚̃Cƒ[ƒW‚𔼓§–¾‚Å•`‰æ‚µ‚Ä‚µ‚Ü‚¤B + // TDragObject‚©‚ç’¼ÚŒp³‚µ‚½‚¾‚¯‚Ì‚à‚Ì(ƒCƒ[ƒW‚ðŽ‚Á‚Ä‚¢‚È‚¢)‚ðŽg‚¤‚Æ + // ”¼“§–¾ƒCƒ[ƒW‚Ì•`‰æ‚Í—}§‚Å‚«‚éB + Drag := TBottleLogDragObject.Create(lvwLog); + Drag.BottleLogList := SelectedBottleLog; + Drag.LogItem := SelectedBottleLog.Bottles[lvwLog.Selected.Index]; + DragObject := Drag; +end; + +procedure TfrmLog.lvwLogEndDrag(Sender, Target: TObject; X, Y: Integer); +begin + // ˜güÁ‚µ—p‚É‹­§“I‚ɍĕ`‰æ‚³‚¹‚é + timScrollTimer.Enabled := false; + FLVDragDest := -1; + UpdateWindow; +end; + +procedure TfrmLog.DrawListViewDragBorder(const Rect: TRect); +var Rec: TRect; +begin + Rec := Rect; + InflateRect(Rec, -1, -1); + with lvwLog.Canvas do + begin + Pen.Mode := pmNot; + Pen.Width := 3; + Brush.Style := bsClear; + Refresh; // •K—v + Rectangle(Rec); + end; +end; + +procedure TfrmLog.DoSaveLogXML(Log: TBottleLogList); +begin + SaveDialog.FileName := GetDefaultFileName(Log.Title, '.xml'); + SaveDialog.InitialDir := ExtractFileDir(Application.ExeName); + SaveDialog.DefaultExt := 'xml'; + SaveDialog.FilterIndex := 3; + if SaveDialog.Execute then + Log.SaveToXmlFile(SaveDialog.FileName); +end; + +procedure TfrmLog.DoCloseTab(const Index: integer); +var + Confirm: String; + PrevSelection: TBottleLogList; // •Â‚¶‚½‚Æ‚«ƒ^ƒu‚ª‚¸‚ê‚È‚¢‚悤‚É‚·‚鏈——p + i: integer; +begin + if Pref.ConfirmOnTabClose then + begin + Confirm := Format('ƒ^ƒu"%s"‚ð•Â‚¶‚Ü‚·‚©?', [(FBottleLogList[Index] as TBottleLogList).Title]); + if MessageDlg(Confirm, mtConfirmation, mbOkCancel, 0) = mrCancel then + Exit; + end; + PrevSelection := SelectedBottleLog; + FBottleLogList.Delete(Index); + UpdateTab; + // ƒ^ƒu‚¸‚ê–hŽ~ˆ— + for i := 0 to FBottleLogList.Count-1 do + if FBottleLogList[i] = PrevSelection then + tabBottleLog.TabIndex := i; + UpdateWindow; + lvwLogChange(Self, nil, ctState); +end; + +procedure TfrmLog.HTMLOutputWork(Sender: TObject; const Count: integer; + var Canceled: boolean); +begin + frmHTMLOutputProgress.ProgressBar.Position := Count; + Application.ProcessMessages; + if frmHTMLOutputProgress.Canceled then + Canceled := true; +end; + +function TfrmLog.DoSearchLog(Condition: TSearchCond): TBottleLogList; +var i, UntilIndex: integer; +begin + Result := TBottleLogList.Create('ŒŸõŒ‹‰Ê'); + if Condition.SearchLogRange in [srSelectedLogList, srAboveSelectedLog] then + begin + if SelectedBottleLog = nil then + begin + ShowMessage('ŒŸõ‘Ώۂª‚ ‚è‚Ü‚¹‚ñ'); + Result.Free; + Result := nil; + Exit; + end else + begin + if Condition.SearchLogRange = srSelectedLogList then + UntilIndex := -1 + else if lvwLog.Selected = nil then + UntilIndex := -1 + else + UntilIndex := lvwLog.Selected.Index; + SearchLogIndivisual(Condition, SelectedBottleLog, Result, UntilIndex); + end; + end else if Condition.SearchLogRange = srAllLogLists then + begin + for i := 0 to BottleLogList.Count-1 do + begin + SearchLogIndivisual(Condition, BottleLogList[i] as TBottleLogList, + Result); + end; + end; +end; + +procedure TfrmLog.SearchLogIndivisual(Condition: TSearchCond; LogList, + Result: TBottleLogList; UntilIndex: integer = -1); +var + i, Max: integer; + Bottle, New: TLogItem; + Ok: boolean; +begin + // 1ŒÂ‚̃ƒOƒ^ƒu‚ɑ΂µ‚ÄŒŸõ‚ð‚©‚¯‚éBUntilIndex‚Ŕ͈͎w’è(È—ªŽž‚»‚̃^ƒu‘S‘Ì) + if UntilIndex >= 0 then + Max := UntilIndex + else + Max := LogList.Count-1; + for i := 0 to Max do + begin + // ðŒ”»’è + Bottle := LogList.Bottles[i]; + if Bottle.LogType <> ltBottle then + Continue; + Ok := true; + // ƒXƒNƒŠƒvƒgƒpƒ^[ƒ“‚ʼnðÍ + if Condition.ScriptPattern <> '' then + begin + if Condition.ScriptRegExp then + begin + try + if not RegExp.Match(Condition.ScriptPattern, Bottle.Script) then + Ok := false; + except + on EBRegExpError do ; // do nothing + end; + end else + begin + if not AnsiContainsText(Bottle.Script, Condition.ScriptPattern) then + Ok := false; + end; + end; + // ƒ`ƒƒƒ“ƒlƒ‹–¼AƒS[ƒXƒg–¼A“Š•[“¯ˆÓ + if Condition.Channel <> '' then + if not AnsiContainsText(Bottle.Channel, Condition.Channel) then + Ok := false; + if Condition.Ghost <> '' then + if not AnsiContainsText(Bottle.Ghost, Condition.Ghost) then + Ok := false; + if Condition.MinVote > Bottle.Votes then + Ok := false; + if Condition.MinAgree > Bottle.Agrees then + Ok := false; + // ðŒ‚Ɉê’v‚µ‚½‚à‚Ì‚ðŒ‹‰ÊƒŠƒXƒg‚ɒljÁ + if Ok then + begin + New := TLogItem.Create(Bottle); // ƒRƒs[ƒRƒ“ƒXƒgƒ‰ƒNƒ^ + New.State := lsOpened; + Result.Add(New); + end; + end; +end; + +{ TBottleLogDragObject } + +function TBottleLogDragObject.GetDragImages: TDragImageList; +begin + // ’†“r”¼’[‚ȃhƒ‰ƒbƒOƒCƒ[ƒW‚ð•\Ž¦‚µ‚È‚¢‚悤‚É‚·‚é + Result := nil; +end; + +procedure TBottleLogDragObject.SetBottleLogList( + const Value: TBottleLogList); +begin + FBottleLogList := Value; +end; + +procedure TBottleLogDragObject.SetLogItem(const Value: TLogItem); +begin + FLogItem := Value; +end; + +procedure TfrmLog.mnTabSaveXMLLogClick(Sender: TObject); +begin + DoSaveLogXML(FBottleLogList[tabBottleLog.Tag] as TBottleLogList); +end; + +procedure TfrmLog.mnSaveHTMLClick(Sender: TObject); +var + LogList, SB: TBottleLogList; + i: integer; + Options: THTMLOutputOptions; +begin + SB := SelectedBottleLog; + if SB = nil then + Exit; + if SB.Count = 0 then + Exit; + Application.CreateForm(TfrmHTMLOutputConfig, frmHTMLOutputConfig); + with frmHTMLOutputConfig do + try + // Show HTML save option dialog + if not Execute then + Exit; + LogList := TBottleLogList.Create(''); + try + case Range of + orAll: + for i := SB.Count-1 downto 0 do + if SB.Bottles[i].LogType = ltBottle then + LogList.Add(TLogItem.Create(SB.Bottles[i])); + orSelected: + if SB.Bottles[lvwLog.Selected.Index].LogType = ltBottle then + LogList.Add(TLogItem.Create(SB.Bottles[lvwLog.Selected.Index])) + else + ShowMessage('‚±‚̃ƒbƒZ[ƒW‚Í•Û‘¶‚Å‚«‚Ü‚¹‚ñ'); + orUpward: + for i := lvwLog.Selected.Index downto 0 do + if SB.Bottles[i].LogType = ltBottle then + LogList.Add(TLogItem.Create(SB.Bottles[i])); + end; + Options.ImageDir := ImageDir; + Options.UseColor := UseColor; + Options.ImageType := ImageType; + Application.CreateForm(TfrmHTMLOutputProgress, frmHTMLOutputProgress); + try + frmHTMLOutputProgress.Show; + LogList.OnHTMLOutputWork := HTMLOutputWork; + LogList.SaveToHTML(FileName, Options, SsParser); + finally + frmHTMLOutputProgress.Release; + end; + finally + LogList.Free; + end; + finally + Release; + end; +end; + +procedure TfrmLog.mnPopupCopyGhostClick(Sender: TObject); +var + Log: TLogItem; + Clip: TClipBoard; +begin + Log := SelectedBottleLog.Bottles[frmLog.lvwLog.Selected.Index]; + if Log = nil then Exit; + Clip := ClipBoard(); + Clip.SetTextBuf(PChar(Log.Ghost)); end; end.