6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ComCtrls, ToolWin, StdCtrls, ExtCtrls, SsParser, BottleDef, Menus,
8 Clipbrd, Logs, ShellAPI, Commctrl, DirectSstp, Contnrs, xmldom, XMLIntf,
9 msxmldom, XMLDoc, StrUtils;
12 TSaveLogType = (stLog, stLogWithChannels, stText, stXML);
14 TfrmLog = class(TForm)
16 tbtnClear: TToolButton;
19 StatusBar: TStatusBar;
20 tbtnSaveLog: TToolButton;
21 PopupMenuPreview: TPopupMenu;
23 tbtnVoteMessage: TToolButton;
24 PopupMenuListView: TPopupMenu;
25 mnPopUpVoteMessage: TMenuItem;
26 SaveDialog: TSaveDialog;
30 mnPopUpCopyScript: TMenuItem;
31 PopupMenuSaveLog: TPopupMenu;
33 mnSaveLogChannel: TMenuItem;
34 mnSaveLogScript: TMenuItem;
35 mnSaveLogXML: TMenuItem;
36 ToolButton1: TToolButton;
38 mnPopUpAgreeMessage: TMenuItem;
39 tbtnAgreeMessage: TToolButton;
40 ToolButton2: TToolButton;
41 tbtnPreviewStyle: TToolButton;
42 PopupMenuPreviewStyle: TPopupMenu;
43 mnPreviewStyleConversation: TMenuItem;
44 mnPreviewStyleScript: TMenuItem;
45 mnPreviewStyleScriptWithLineBreak: TMenuItem;
47 tabBottleLog: TTabControl;
49 tbtnDownloadLog: TToolButton;
50 PopupMenuTab: TPopupMenu;
51 mnCloseTab: TMenuItem;
52 tbtnFindBottle: TToolButton;
53 XMLDocument: TXMLDocument;
54 tbtnOpenLog: TToolButton;
55 OpenDialog: TOpenDialog;
56 tbtnInsertCue: TToolButton;
57 mnInsertCue: TMenuItem;
58 procedure tbtnClearClick(Sender: TObject);
59 procedure FormCreate(Sender: TObject);
60 procedure lvwLogChange(Sender: TObject; Item: TListItem;
62 procedure lvwLogDblClick(Sender: TObject);
63 procedure lvwLogKeyPress(Sender: TObject; var Key: Char);
64 procedure FormDestroy(Sender: TObject);
65 procedure lvwLogClick(Sender: TObject);
66 procedure mnSaveLogClick(Sender: TObject);
67 procedure lvwLogColumnClick(Sender: TObject; Column: TListColumn);
68 procedure mnPopUpCopyScriptClick(Sender: TObject);
69 procedure mnSaveLogChannelClick(Sender: TObject);
70 procedure mnSaveLogScriptClick(Sender: TObject);
71 procedure mnSaveLogXMLClick(Sender: TObject);
72 procedure lvwLogData(Sender: TObject; Item: TListItem);
73 procedure PopupMenuListViewPopup(Sender: TObject);
74 procedure lvwLogCustomDrawItem(Sender: TCustomListView;
75 Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
76 procedure lvwLogCustomDrawSubItem(Sender: TCustomListView;
77 Item: TListItem; SubItem: Integer; State: TCustomDrawState;
78 var DefaultDraw: Boolean);
79 procedure PopupMenuPreviewStylePopup(Sender: TObject);
80 procedure mnPreviewStyleClick(Sender: TObject);
81 procedure tbtnPreviewStyleClick(Sender: TObject);
82 procedure tabBottleLogChange(Sender: TObject);
83 procedure tabBottleLogChanging(Sender: TObject;
84 var AllowChange: Boolean);
85 procedure tabBottleLogContextPopup(Sender: TObject; MousePos: TPoint;
86 var Handled: Boolean);
87 procedure mnCloseTabClick(Sender: TObject);
88 procedure tbtnFindBottleClick(Sender: TObject);
89 procedure tbtnOpenLogClick(Sender: TObject);
90 procedure tabBottleLogMouseDown(Sender: TObject; Button: TMouseButton;
91 Shift: TShiftState; X, Y: Integer);
92 procedure tabBottleLogDragOver(Sender, Source: TObject; X, Y: Integer;
93 State: TDragState; var Accept: Boolean);
94 procedure tabBottleLogDragDrop(Sender, Source: TObject; X, Y: Integer);
95 procedure tabBottleLogEndDrag(Sender, Target: TObject; X, Y: Integer);
98 FLastScript: String; //
\83X
\83N
\83\8a\83v
\83g
\8dÄ
\95`
\89æ
\97}
\90§
\97p
99 FBottleLogList: TObjectList;
101 FDragTabIndex: integer; //
\83^
\83u
\83h
\83\89\83b
\83O
\83h
\83\8d\83b
\83v
\8aÖ
\98A
102 FDragTabDest: integer; //
\83h
\83\8d\83b
\83v
\82·
\82é
\88Ê
\92u(
\82·
\82®
\89E
\82É
\82
\82é
\83^
\83u
\82Ì
\83C
\83\93\83f
\83b
\83N
\83X)
103 procedure UpdateScript(const Script: String);
104 procedure UpdateScriptConversationColor(const Script: String);
105 procedure UpdateScriptConversationNoColor(const Script: String);
106 procedure UpdateScriptScript(const Script: String);
107 procedure mnURLClick(Sender: TObject);
108 procedure ExtractURLs(Script: String; Result: TStrings);
109 function GetDefaultFileName(const Name: String; const Ext: String): String;
110 function BottleLogTitled(const LogName: String): TBottleLogList;
112 procedure CreateParams(var Params: TCreateParams); override;
115 function SelectedBottleLog: TBottleLogList;
116 property BottleLogList: TObjectList read FBottleLogList;
117 procedure AddCurrentScriptLog(const LogName, Script, Channel, MID, Ghost: String);
118 procedure AddCurrentSystemLog(const LogName, MessageString: String);
119 procedure VoteLog(const MID: String; const Vote: integer);
120 procedure AgreeLog(const MID: String; const Agree: integer);
121 procedure SetBottleState(const MID: String; State: TLogState);
122 procedure AllBottleOpened;
123 procedure LogLoaded(Sender: TObject);
124 procedure LogLoadFailure(Sender: TObject; const Message: String);
125 procedure LogLoadWork(Sender: TObject);
127 procedure UpdateWindow;
128 procedure SelAndFocusMessage(const MID: String);
154 procedure TfrmLog.AddCurrentScriptLog(const LogName, Script, Channel, MID, Ghost: String);
157 BottleLogTitled(LogName).AddScriptLog(Script, Channel, MID, Ghost);
158 if SelectedBottleLog <> BottleLogTitled(LogName) then Exit;
159 lvwLog.OnChange := nil; //
\83C
\83x
\83\93\83g
\94
\90¶(
\82¢
\82ë
\82¢
\82ë
\8dÄ
\95`
\89æ
\82ª
\8bN
\82«
\82é)
\82Ì
\97}
\90§
160 if lvwLog.Selected <> nil then Sel := lvwLog.Selected.Index else Sel := -1;
161 lvwLog.Items.Count := SelectedBottleLog.Count;
163 if Sel >= 0 then begin
164 lvwLog.Selected := lvwLog.Items[Sel + 1];
165 lvwLog.Selected.Focused := true;
167 if not lvwLog.Focused then
168 ListView_Scroll(lvwLog.Handle, 0, High(integer));
169 lvwLog.OnChange := lvwLogChange;
172 procedure TfrmLog.AddCurrentSystemLog(const LogName, MessageString: String);
175 BottleLogTitled(LogName).AddSystemLog(MessageString);
176 if SelectedBottleLog <> BottleLogTitled(LogName) then Exit;
177 lvwLog.OnChange := nil;
178 if lvwLog.Selected <> nil then Sel := lvwLog.Selected.Index else Sel := -1;
179 lvwLog.Items.Count := SelectedBottleLog.Count;
181 if Sel >= 0 then begin
182 lvwLog.Selected := lvwLog.Items[Sel + 1];
183 lvwLog.Selected.Focused := true;
185 if not lvwLog.Focused then
186 ListView_Scroll(lvwLog.Handle, 0, High(integer));
187 lvwLog.OnChange := lvwLogChange;
192 procedure TfrmLog.tbtnClearClick(Sender: TObject);
194 if SelectedBottleLog = nil then Exit;
195 FBottleLogList.Delete(tabBottleLog.TabIndex);
196 tabBottleLog.TabIndex := 0;
199 lvwLogChange(Self, nil, ctState);
202 procedure TfrmLog.FormCreate(Sender: TObject);
205 FBottleLogList := TObjectList.Create;
207 SsParser.TagPattern.Assign(frmSender.SsParser.TagPattern);
208 SsParser.MetaPattern.Assign(frmSender.SsParser.MetaPattern);
210 with Pref.LogWindowPosition do begin
213 Self.Width := Right - Left + 1;
214 Self.Height := Bottom - Top + 1;
216 lvwLog.DoubleBuffered := true;
217 edtScript.Height := Pref.LogWindowDividerPos;
220 while Token(Pref.LogWindowColumnWidth, ',', i) <> '' do begin
221 lvwLog.Columns[i].Width := StrToIntDef(Token(Pref.LogWindowColumnWidth, ',', i), 100);
225 UpdateWindow; // Reset window color and enabled status of some buttons
228 procedure TfrmLog.FormDestroy(Sender: TObject);
233 for i := 0 to lvwLog.Columns.Count-1 do begin
234 if i > 0 then WidthStr := WidthStr + ',';
235 WidthStr := WidthStr + IntToStr(lvwLog.Column[i].Width);
237 Pref.LogWindowColumnWidth := WidthStr;
239 with Pref.LogWindowPosition do begin
242 Right := Self.Left + Self.Width - 1;
243 Bottom := Self.Top + Self.Height - 1;
245 Pref.LogWindowDividerPos := edtScript.Height;
247 FreeAndNil(FBottleLogList);
250 procedure TfrmLog.lvwLogChange(Sender: TObject; Item: TListItem;
251 Change: TItemChange);
255 if SelectedBottleLog <> nil then begin
256 StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '
\8c\8f';
257 if Change = ctState then begin
259 if lvwLog.Selected <> nil then begin
260 Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
261 if (Log.LogType = ltBottle) and not frmSender.Connecting then begin
262 Script := Log.Script;
263 frmSender.actVoteMessage.Enabled := true;
264 frmSender.actAgreeMessage.Enabled := true;
265 frmSender.actInsertCue.Enabled := true;
266 mnPopUpCopyScript.Enabled := true;
267 StatusBar.Panels[1].Text := Format('%d
\83o
\83C
\83g -
\83_
\83u
\83\8b\83N
\83\8a\83b
\83N
\82Å
\8dÄ
\90¶', [Length(Log.Script)]);
268 UpdateScript(Script);
270 frmSender.actVoteMessage.Enabled := false;
271 frmSender.actAgreeMessage.Enabled := false;
272 frmSender.actInsertCue.Enabled := false;
273 mnPopUpCopyScript.Enabled := false;
274 StatusBar.Panels[1].Text := '';
275 UpdateScript(''); //
\83\8d\83O
\83v
\83\8c\83r
\83\85\81[
\95\94\82ð
\83N
\83\8a\83A
278 frmSender.actVoteMessage.Enabled := false;
279 frmSender.actAgreeMessage.Enabled := false;
280 frmSender.actInsertCue.Enabled := false;
281 mnPopUpCopyScript.Enabled := false;
282 StatusBar.Panels[1].Text := '';
283 UpdateScript(Script); //
\83\8d\83O
\83v
\83\8c\83r
\83\85\81[
\95\94\83N
\83\8a\83A
286 tbtnSaveLog.Enabled := lvwLog.Items.Count > 0;
288 frmSender.actVoteMessage.Enabled := false;
289 frmSender.actAgreeMessage.Enabled := false;
290 frmSender.actInsertCue.Enabled := false;
291 mnPopUpCopyScript.Enabled := false;
292 StatusBar.Panels[0].Text := '';
293 UpdateScript(''); //
\83\8d\83O
\83v
\83\8c\83r
\83\85\81[
\95\94\83N
\83\8a\83A
297 procedure TfrmLog.lvwLogDblClick(Sender: TObject);
299 SOpt: TSstpSendOptions;
303 if lvwLog.Selected = nil then Exit;
304 //Log := TLogItem(lvwLog.Selected.Data);
305 Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
306 if Log = nil then Exit;
307 if Log.LogType <> ltBottle then Exit;
308 Script := frmSender.ScriptTransForSSTP(Log.Script);
309 if Script = '' then begin
310 ShowMessage('
\96â
\91è
\82Ì
\82 \82é
\83X
\83N
\83\8a\83v
\83g
\82Å
\82·
\81B
\8dÄ
\90¶
\82Å
\82«
\82Ü
\82¹
\82ñ
\81B
\83N
\83\89\83C
\83A
\83\93\83g
\82ð
\8dÅ
\90V
\94Å
\82É
\82µ
\82Ä
\82Ý
\82Ä
\82
\82¾
\82³
\82¢
\81B');
314 if ChannelList.Channel[Log.Channel] <> nil then
315 Ghost := ChannelList.Channel[Log.Channel].Ghost;
316 //
\96Ú
\95W
\83S
\81[
\83X
\83g
\8c\88\92è
317 if Log.Ghost <> '' then Ghost := Log.Ghost;
318 //
\83^
\81[
\83Q
\83b
\83g
\83S
\81[
\83X
\83g
\8am
\92è
319 Ghost := frmSender.SetHWndToFavoriteGhost(Ghost);
320 frmSender.DirectSstp.SstpSender := 'SSTP Bottle -
\81y
\83\8d\83O
\8dÄ
\90¶
\81z';
321 if Pref.NoTranslate then SOpt := [soNoTranslate] else SOpt := [];
322 frmSender.DirectSstp.SstpSEND(Script, SOpt, frmSender.GhostNameToSetName(Ghost));
325 procedure TfrmLog.UpdateScriptConversationColor(const Script: String);
328 UnyuTalking, Talked, InSynchronized: boolean;
331 frmSender.DoTrans(scr, [toConvertURL]);
332 SsParser.LeaveEscape := false;
333 SsParser.InputString := scr;
334 SsParser.LeaveEscape := true;
335 UnyuTalking := false;
336 Talked := false; //'\h\u\h\u'
\82Ì
\82æ
\82¤
\82È
\83X
\83N
\83\8a\83v
\83g
\82Å
\8bó
\82«
\8ds
\82ð
\8dì
\82ç
\82È
\82¢
\82½
\82ß
\82Ì
\91[
\92u
337 InSynchronized := false;
338 edtScript.Text := '';
339 edtScript.Color := Pref.BgColor;
340 for i := 0 to SsParser.Count-1 do begin
341 if (SsParser[i] = '\_s') and not InSynchronized then begin
342 InSynchronized := true;
344 edtScript.SelText := #13#10;
347 end else if (SsParser[i] = '\_s') and InSynchronized then begin
348 InSynchronized := false;
350 edtScript.SelText := #13#10;
354 if (SsParser[i] = '\u') and not UnyuTalking then begin
357 edtScript.SelText := #13#10;
361 if (SsParser[i] = '\h') and UnyuTalking then begin
362 UnyuTalking := false;
364 edtScript.SelText := #13#10;
368 if SsParser.MarkUpType[i] = mtStr then begin
369 if InSynchronized then
370 edtScript.SelAttributes.Color := Pref.TalkColorS
371 else if UnyuTalking then
372 edtScript.SelAttributes.Color := Pref.TalkColorU
374 edtScript.SelAttributes.Color := Pref.TalkColorH;
375 edtScript.SelText := SsParser[i];
378 if SsParser.MarkUpType[i] = mtMeta then begin
379 edtScript.SelAttributes.Color := Pref.MetaWordColor;
380 edtScript.SelText := SsParser[i];
386 procedure TfrmLog.UpdateScriptConversationNoColor(const Script: String);
389 UnyuTalking, Talked, LastUnyuTalked, InSynchronize, LastInSynchronize: boolean;
392 frmSender.DoTrans(Scr, [toConvertURL]);
393 SsParser.LeaveEscape := false;
394 SsParser.InputString := Scr;
395 SsParser.LeaveEscape := true;
396 edtScript.Text := '';
397 edtScript.Color := clWindow;
398 edtScript.DefAttributes.Color := clWindowText;
399 edtScript.SelAttributes.Color := clWindowText;
401 UnyuTalking := false;
402 LastUnyuTalked := false;
403 InSynchronize := false;
404 LastInSynchronize := false;
405 for i := 0 to SsParser.Count-1 do begin
406 if SsParser[i] = '\u' then UnyuTalking := true;
407 if SsParser[i] = '\h' then UnyuTalking := false;
408 if SsParser[i] = '\_s' then InSynchronize := not InSynchronize;
409 if SsParser.MarkUpType[i] in [mtStr, mtMeta] then begin
410 if not Talked then begin //
\83X
\83N
\83\8a\83v
\83g
\8dÅ
\8f\89\82Ì
\83Z
\83\8a\83t
411 if InSynchronize then Scr := '
\97¼
\81F'
412 else if UnyuTalking then Scr := '
\82¤:' else Scr := '
\82³:';
414 if Talked and ((UnyuTalking <> LastUnyuTalked) or (InSynchronize <> LastInSynchronize)) then begin
416 if InSynchronize then Scr := Scr + '
\97¼
\81F'
417 else if UnyuTalking then Scr := Scr + '
\82¤:' else Scr := Scr + '
\82³:';
419 Scr := Scr + SsParser[i];
421 LastInSynchronize := InSynchronize;
422 LastUnyuTalked := UnyuTalking;
425 edtScript.Text := Scr;
428 procedure TfrmLog.lvwLogKeyPress(Sender: TObject; var Key: Char);
430 if Key = #13 then lvwLogDblClick(Sender);
433 procedure TfrmLog.CreateParams(var Params: TCreateParams);
436 Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
439 procedure TfrmLog.lvwLogClick(Sender: TObject);
441 //
\89E
\83N
\83\8a\83b
\83N
\82Å
\83\81\83j
\83\85\81[
\8fo
\82·
\82Æ
\82«
\82É
\94
\90¶
\82·
\82é
\95s
\8bï
\8d\87\91Î
\8dô
443 Selected := Selected;
446 procedure TfrmLog.lvwLogColumnClick(Sender: TObject; Column: TListColumn);
447 var SortType: TBottleLogSortType;
451 if lvwLog.Selected <> nil then
452 SelectedMID := SelectedBottleLog.Bottles[lvwLog.Selected.Index].MID;
454 SortColumn := Column.Index;
456 -1: SortType := stLogTime;
457 subChannel: SortType := stChannel;
458 subGhost: SortType := stGhost;
459 subVotes: SortType := stVote;
460 subAgrees: SortType := stAgree;
461 subScript: SortType := stScript;
462 else SortType := stLogTime;
465 SelectedBottleLog.SortBottles(SortType);
467 SelAndFocusMessage(SelectedMID);
471 procedure TfrmLog.mnPopUpCopyScriptClick(Sender: TObject);
476 Log := SelectedBottleLog.Bottles[frmLog.lvwLog.Selected.Index];
477 if Log = nil then Exit;
479 Clip.SetTextBuf(PChar(Log.Script));
482 procedure TfrmLog.SetBottleState(const MID: String; State: TLogState);
486 for i := 0 to FBottleLogList.Count-1 do begin
487 Bottle := (FBottleLogList[i] as TBottleLogList).Bottle(MID);
488 if Bottle <> nil then begin
489 Bottle.State := State;
490 lvwLog.OnChange := nil;
492 lvwLog.OnChange := lvwLogChange;
497 procedure TfrmLog.mnSaveLogClick(Sender: TObject);
499 if SelectedBottleLog = nil then Exit;
500 SaveDialog.FileName := GetDefaultFileName(SelectedBottleLog.Title, '.log');
501 SaveDialog.InitialDir := ExtractFileDir(Application.ExeName);
502 SaveDialog.DefaultExt := 'log';
503 SaveDialog.FilterIndex := 1;
504 if SaveDialog.Execute then
505 SelectedBottleLog.SaveToSstpLog(SaveDialog.FileName, false);
508 procedure TfrmLog.mnSaveLogChannelClick(Sender: TObject);
510 if SelectedBottleLog = nil then Exit;
511 SaveDialog.FileName := GetDefaultFileName(SelectedBottleLog.Title, '.log');
512 SaveDialog.InitialDir := ExtractFileDir(Application.ExeName);
513 SaveDialog.DefaultExt := 'log';
514 SaveDialog.FilterIndex := 1;
515 if SaveDialog.Execute then
516 SelectedBottleLog.SaveToSstpLog(SaveDialog.FileName, true);
519 procedure TfrmLog.mnSaveLogScriptClick(Sender: TObject);
521 if SelectedBottleLog = nil then Exit;
522 SaveDialog.FileName := GetDefaultFileName(SelectedBottleLog.Title, '.txt');
523 SaveDialog.InitialDir := ExtractFileDir(Application.ExeName);
524 SaveDialog.DefaultExt := 'txt';
525 SaveDialog.FilterIndex := 2;
526 if SaveDialog.Execute then
527 SelectedBottleLog.SaveToText(SaveDialog.FileName);
530 procedure TfrmLog.mnSaveLogXMLClick(Sender: TObject);
532 if SelectedBottleLog = nil then Exit;
533 SaveDialog.FileName := GetDefaultFileName(SelectedBottleLog.Title, '.xml');
534 SaveDialog.InitialDir := ExtractFileDir(Application.ExeName);
535 SaveDialog.DefaultExt := 'xml';
536 SaveDialog.FilterIndex := 3;
537 if SaveDialog.Execute then
538 SelectedBottleLog.SaveToXmlFile(SaveDialog.FileName, XMLDocument);
541 procedure TfrmLog.lvwLogData(Sender: TObject; Item: TListItem);
545 if Item = nil then Exit;
547 Log := SelectedBottleLog.Bottles[i];
549 Caption := FormatDateTime('yy/mm/dd hh:nn:ss', Log.LogTime);
551 SubItems.Add(Log.Channel);
552 SubItems.Add(Log.Ghost);
553 if Log.LogType = ltBottle then begin
554 if Log.Votes > 0 then
555 SubItems.Add(IntToStr(Log.Votes))
558 if Log.Agrees > 0 then
559 SubItems.Add(IntToStr(Log.Agrees))
563 //
\83V
\83X
\83e
\83\80\83\8d\83O
\82È
\82Ç
\82Í
\93\8a\95[
\81E
\93¯
\88Ó
\82ð
\95\
\8e¦
\82µ
\82È
\82¢
567 SubItems.Add(Log.Script);
569 if Log.LogType = ltBottle then begin
571 lsUnopened: ImageIndex := IconBottle;
572 lsPlaying: ImageIndex := IconPlaying;
573 lsOpened: ImageIndex := IconOpened;
576 ImageIndex := IconSystemLog;
580 procedure TfrmLog.UpdateWindow;
581 var EnabledFlag: boolean;
583 if Pref.ColorScript then begin
584 if lvwLog.Color <> Pref.BgColor then lvwLog.Color := Pref.BgColor;
585 if lvwLog.Font.Color <> Pref.TalkColorH then lvwLog.Font.Color := Pref.TalkColorH;
587 if lvwLog.Color <> clWindow then lvwLog.Color := clWindow;
588 if lvwLog.Font.Color <> clWindowText then lvwLog.Font.Color := clWindowText;
590 if SelectedBottleLog <> nil then begin
591 Caption := '
\83\8d\83O - ' + SelectedBottleLog.Title;
592 StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '
\8c\8f';
593 lvwLog.Items.Count := SelectedBottleLog.Count;
595 Caption := '
\83\8d\83O';
596 StatusBar.Panels[0].Text := '';
597 StatusBar.Panels[1].Text := '';
598 lvwLog.Items.Count := 0;
601 EnabledFlag := SelectedBottleLog <> nil;
602 tbtnClear.Enabled := EnabledFlag;
603 tbtnSaveLog.Enabled := EnabledFlag;
604 tbtnFindBottle.Enabled := EnabledFlag;
609 procedure TfrmLog.PopupMenuListViewPopup(Sender: TObject);
615 for i := mnJumpURL.Count-1 downto 0 do begin
616 mnJumpURL.Items[i].Free;
618 mnJumpURL.Enabled := false;
619 if lvwLog.Selected = nil then Exit;
620 Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
621 if Log = nil then Exit;
622 Urls := TStringList.Create;
624 ExtractURLs(Log.Script, Urls);
625 for i := 0 to Urls.Count-1 do begin
626 Child := TMenuItem.Create(Self);
628 Caption := Format('(&%d) %s', [i+1, StringReplace(Urls[i], '&', '&&', [rfReplaceAll])]);
630 OnClick := mnURLClick;
631 AutoHotkeys := maManual;
632 mnJumpURL.Add(Child);
635 mnJumpURL.Enabled := Urls.Count > 0;
641 procedure TfrmLog.mnURLClick(Sender: TObject);
642 var LogItem: TLogItem;
646 if (lvwLog.Selected = nil) or (SelectedBottleLog = nil) then Exit;
647 LogItem := SelectedBottleLog[lvwLog.Selected.Index] as TLogItem;
648 Urls := TStringList.Create;
650 ExtractURLs(LogItem.Script, Urls);
651 URL := Urls[(Sender as TMenuItem).Tag];
652 ShellExecute(Handle, 'open', PChar(URL), nil, nil, SW_SHOW);
658 procedure TfrmLog.ExtractURLs(Script: String; Result: TStrings);
659 var i, u, j: integer;
663 SsParser.InputString := Script;
664 for i := 0 to SsParser.Count-1 do begin
665 if (SsParser.Match(SsParser[i], '\URL%b') > 0) then begin
666 for u := 7 downto 1 do begin
667 if (SsParser.Match(SsParser[i],
668 '\URL%b'+StringReplace(StringOfChar('-', u*2),
669 '-', '%b', [rfReplaceAll]))) > 0 then begin
670 for j := 1 to u do begin
671 s := SsParser.GetParam(SsParser[i], j*2);
672 if Pos('http://', s) > 0 then Result.Add(s);
677 if SsParser.Match(SsParser[i], '\URL%b%b') = 0 then begin //
\8aÈ
\88Õ
\94ÅURL
\95Ï
\8a·
678 //
\8aÈ
\88Õ
\8c`
\8e®\URL
\83^
\83O
\95Ï
\8a·
679 s := SsParser.GetParam(SsParser[i], 1);
680 if Pos('http://', s) > 0 then Result.Add(s);
686 procedure TfrmLog.SelAndFocusMessage(const MID: String);
690 for i := 0 to SelectedBottleLog.Count-1 do begin
691 Log := SelectedBottleLog.Items[i] as TLogItem;
692 if Log.MID = MID then begin
693 lvwLog.Items[i].Selected := true;
694 lvwLog.Items[i].Focused := true;
699 procedure TfrmLog.lvwLogCustomDrawItem(Sender: TCustomListView;
700 Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
705 procedure TfrmLog.lvwLogCustomDrawSubItem(Sender: TCustomListView;
706 Item: TListItem; SubItem: Integer; State: TCustomDrawState;
707 var DefaultDraw: Boolean);
713 Mark: TSsMarkUpType;}
716 {if (SubItem <> SubScript+1) or (not Pref.ColorScript) then Exit; // DefaultDraw = true
717 // Custom Script Coloring
718 DefaultDraw := false;
719 SavedDC := SaveDC(lvwLog.Canvas.Handle);
721 ListView_GetSubItemRect(lvwLog.Handle, Item.Index, SubScript+1, LVIR_BOUNDS, @DestRect);
723 lvwLog.Canvas.Brush.Style := bsSolid;
724 if cdsSelected in State then begin
725 lvwLog.Canvas.Brush.Color := clHighlight
727 lvwLog.Canvas.Brush.Color := Pref.BgColor;
729 lvwLog.Canvas.FillRect(DestRect);
730 lvwLog.Canvas.Brush.Style := bsClear;
732 Script := Item.SubItems[SubScript];
733 // DrawTextEx(lvwLog.Canvas.Handle, PChar(Script), -1, DestRect, DT_END_ELLIPSIS, nil);
734 SsParser.InputString := Script;
736 for i := 0 to SsParser.Count - 1 do begin
737 Mark := SsParser.MarkUpType[i];
739 mtMeta: lvwLog.Canvas.Font.Color := Pref.MetaWordColor;
740 mtTag: lvwLog.Canvas.Font.Color := Pref.MarkUpColor;
741 mtTagErr: lvwLog.Canvas.Font.Color := Pref.MarkErrorColor;
743 lvwLog.Canvas.Font.Color := Pref.TalkColorH;
746 w := lvwLog.Canvas.TextWidth(SsParser[i]);
747 lvwLog.Canvas.TextRect(DestRect, DestRect.Left + x, DestRect.Top + 2, SsParser[i]);
749 if DestRect.Right - DestRect.Left < x then Break;
752 RestoreDC(lvwLog.Canvas.Handle, SavedDC);
756 procedure TfrmLog.UpdateScript(const Script: String);
758 if Script <> FLastScript then begin
759 if Pref.LogWindowPreviewStyle = psConversation then begin
760 if Pref.ColorScript then begin
761 UpdateScriptConversationColor(Script);
763 UpdateScriptConversationNoColor(Script);
766 UpdateScriptScript(Script);
768 SendMessage(edtScript.Handle, EM_LINESCROLL, Low(integer), Low(integer)); //
\83X
\83N
\83\8d\81[
\83\8b\96ß
\82µ
769 FLastScript := Script;
773 procedure TfrmLog.PopupMenuPreviewStylePopup(Sender: TObject);
776 with PopupMenuPreviewStyle do
777 for i := 0 to Items.Count-1 do
778 Items[i].Checked := Items[i].Tag = Ord(Pref.LogWindowPreviewStyle)
781 procedure TfrmLog.mnPreviewStyleClick(Sender: TObject);
784 with PopupMenuPreviewStyle do
785 for i := 0 to Items.Count-1 do
786 Items[i].Checked := (Sender as TMenuItem).Tag = Items[i].Tag;
787 Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle((Sender as TMenuItem).Tag);
789 lvwLogChange(self, lvwLog.Selected, ctState);
792 procedure TfrmLog.UpdateScriptScript(const Script: String);
794 UnyuTalking, InSynchronized: boolean;
797 if Pref.ColorScript then begin
798 edtScript.Color := Pref.BgColor;
800 edtScript.Color := clWindow;
801 edtScript.DefAttributes.Color := clWindowText;
802 edtScript.SelAttributes.Color := clWindowText;
804 SsParser.LeaveEscape := true;
805 SsParser.InputString := Script;
806 edtScript.Text := '';
807 edtScript.SelAttributes.Color := clWindowText;
808 UnyuTalking := false;
809 InSynchronized := false;
810 for i := 0 to SsParser.Count-1 do begin
811 if Pref.ColorScript then begin
812 case SsParser.MarkUpType[i] of
814 if InSynchronized then
815 edtScript.SelAttributes.Color := Pref.TalkColorS
816 else if UnyuTalking then
817 edtScript.SelAttributes.Color := Pref.TalkColorU
819 edtScript.SelAttributes.Color := Pref.TalkColorH;
822 edtScript.SelAttributes.Color := Pref.MarkUpColor;
823 if SsParser[i] = '\h' then
825 else if SsParser[i] = '\u' then
827 else if SsParser[i] = '\_s' then
828 InSynchronized := not InSynchronized;
830 mtMeta: edtScript.SelAttributes.Color := Pref.MetaWordColor;
831 mtTagErr: edtScript.SelAttributes.Color := Pref.MarkErrorColor;
834 edtScript.SelText := SsParser[i];
835 if (SsParser[i] = '\n') and (Pref.LogWindowPreviewStyle = psScriptWithLineBreak) then
836 edtScript.SelText := #13#10;
840 procedure TfrmLog.tbtnPreviewStyleClick(Sender: TObject);
843 sel := Ord(Pref.LogWindowPreviewStyle);
845 if sel > Ord(High(TLogWindowPreviewStyle)) then sel := 0;
846 Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle(sel);
848 lvwLogChange(self, lvwLog.Selected, ctState);
851 function TfrmLog.SelectedBottleLog: TBottleLogList;
853 if tabBottleLog.TabIndex >= 0 then
854 Result := FBottleLogList.Items[tabBottleLog.TabIndex] as TBottleLogList
859 procedure TfrmLog.tabBottleLogChange(Sender: TObject);
862 if SelectedBottleLog.SelectedIndex >= 0 then begin
863 lvwLog.Items[SelectedBottleLog.SelectedIndex].Selected := true;
864 if lvwLog.Focused then lvwLog.Selected.Focused := true;
866 lvwLogChange(Self, nil, ctState);
869 procedure TfrmLog.LogLoaded(Sender: TObject);
871 if SelectedBottleLog = Sender then begin
876 procedure TfrmLog.UpdateTab;
879 cur := tabBottleLog.tabIndex;
880 tabBottleLog.Tabs.Clear;
881 for i := 0 to FBottleLogList.Count - 1 do begin
882 tabBottleLog.Tabs.Add((FBottleLogList[i] as TBottleLogList).Title);
884 if FBottleLogList.Count > 0 then begin
885 if cur < FBottleLogList.Count then
886 tabBottleLog.TabIndex := cur
888 tabBottleLog.TabIndex := FBottleLogList.Count-1;
892 procedure TfrmLog.LogLoadFailure(Sender: TObject; const Message: String);
895 ShowMessage(Message);
896 if Sender = SelectedBottleLog then UpdateWindow;
899 procedure TfrmLog.AgreeLog(const MID: String; const Agree: integer);
904 for i := 0 to FBottleLogList.Count - 1 do begin
905 if (FBottleLogList[i] as TBottleLogList).Bottle(MID) <> nil then begin
906 (FBottleLogList[i] as TBottleLogList).Bottle(MID).Agrees := Agree;
910 if flag then lvwLog.Invalidate;
913 procedure TfrmLog.VoteLog(const MID: String; const Vote: integer);
918 for i := 0 to FBottleLogList.Count - 1 do begin
919 if (FBottleLogList[i] as TBottleLogList).Bottle(MID) <> nil then begin
920 (FBottleLogList[i] as TBottleLogList).Bottle(MID).Votes := Vote;
924 if flag then lvwLog.Invalidate;
927 procedure TfrmLog.tabBottleLogChanging(Sender: TObject;
928 var AllowChange: Boolean);
930 //
\8c»
\8dÝ
\91I
\91ð
\82³
\82ê
\82Ä
\82¢
\82é
\83\8d\83O
\82Ì
\91I
\91ð
\8fó
\91Ô
\82ð
\95Û
\91¶
931 if SelectedBottleLog = nil then Exit;
932 if lvwLog.Selected <> nil then
933 SelectedBottleLog.SelectedIndex := lvwLog.Selected.Index
935 SelectedBottleLog.SelectedIndex := -1;
938 procedure TfrmLog.tabBottleLogContextPopup(Sender: TObject;
939 MousePos: TPoint; var Handled: Boolean);
941 with tabBottleLog do begin
942 Tag := IndexOfTabAt(MousePos.X, MousePos.Y);
943 if Tag < 0 then Handled := true;
947 procedure TfrmLog.mnCloseTabClick(Sender: TObject);
949 FBottleLogList.Delete(tabBottleLog.Tag);
952 lvwLogChange(Self, nil, ctState);
955 procedure TfrmLog.tbtnFindBottleClick(Sender: TObject);
957 ResultLog: TBottleLogList;
958 Item1, Item2: TLogItem;
961 if SelectedBottleLog = nil then Exit;
962 if SelectedBottleLog.Count = 0 then begin
963 ShowMessage('
\8c\9f\8dõ
\91Î
\8fÛ
\82ª
\8bó
\82Å
\82·
\81B');
968 if InputQuery('
\83X
\83N
\83\8a\83v
\83g
\96{
\95¶
\82ð
\8c\9f\8dõ', '
\8c\9f\8dõ
\95¶
\8e\9a\97ñ', Query) then begin
969 if Query = '' then Exit;
970 ResultLog := TBottleLogList.Create('
\8c\9f\8dõ
\8c\8b\89Ê');
971 for i := 0 to SelectedBottleLog.Count-1 do begin
972 Item1 := SelectedBottleLog.Items[i] as TLogItem;
973 if AnsiContainsText(Item1.Script, Query) and (Item1.LogType = ltBottle) then begin
974 matched := matched + 1;
975 Item2 := TLogItem.Create(ltBottle, Item1.MID, Item1.Channel,
976 Item1.Script, Item1.Ghost, Item1.LogTime);
977 Item2.State := lsOpened;
978 Item2.Votes := Item1.Votes;
979 Item2.Agrees := Item1.Agrees;
980 ResultLog.Add(Item2);
984 ResultLog.AddSystemLog('
\8c©
\82Â
\82©
\82è
\82Ü
\82¹
\82ñ
\82Å
\82µ
\82½');
985 BottleLogList.Add(ResultLog);
987 tabBottleLog.TabIndex := BottleLogList.Count-1;
992 procedure TfrmLog.tbtnOpenLogClick(Sender: TObject);
993 var BottleLog: TBottleLogList;
997 if OpenDialog.Execute then begin
998 for i := 0 to OpenDialog.Files.Count-1 do begin
999 BottleLog := TBottleLogList.Create(ExtractFileName(OpenDialog.Files[i]));
1001 BottleLog.LoadFromXMLFile(OpenDialog.Files[i], XMLDocument);
1003 on E: EXMLFileOpenException do begin
1005 ShowMessage(E.Message);
1006 FreeAndNil(BottleLog);
1009 if BottleLog <> nil then Index := BottleLogList.Add(BottleLog); //
\8dÅ
\8cã
\82É
\8aJ
\82¢
\82½
\83\8d\83O
\82Ì
\88Ê
\92u
\82ð
\8bL
\89¯
1012 if Index >= 0 then tabBottleLog.TabIndex := Index;
1017 function TfrmLog.GetDefaultFileName(const Name, Ext: String): String;
1019 Result := StringReplace(Name, '/', '', [rfReplaceAll]);
1020 Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
1021 Result := ChangeFileExt(Result, Ext);
1024 function TfrmLog.BottleLogTitled(const LogName: String): TBottleLogList;
1027 for i := 0 to FBottleLogList.Count-1 do begin
1028 if (FBottleLogList[i] as TBottleLogList).Title = LogName then begin
1029 Result := (FBottleLogList[i] as TBottleLogList);
1033 //
\8c©
\82Â
\82©
\82ç
\82È
\82¢
\8fê
\8d\87
1034 Result := TBottleLogList.Create(LogName); //
\90V
\82µ
\82
\8dì
\82é
1035 FBottleLogList.Add(Result);
1037 if FBottleLogList.Count = 1 then tabBottleLog.TabIndex := 0;
1040 procedure TfrmLog.AllBottleOpened;
1042 Log: TBottleLogList;
1044 for i := 0 to FBottleLogList.Count-1 do begin
1045 Log := FBottleLogList[i] as TBottleLogList;
1046 for j := 0 to Log.Count-1 do begin
1047 Log.Bottles[j].State := lsOpened;
1052 procedure TfrmLog.tabBottleLogMouseDown(Sender: TObject;
1053 Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
1056 with tabBottleLog do begin
1057 Index := IndexOfTabAt(X, Y);
1058 if Index = -1 then Exit; //
\83^
\83u
\82ª
\82È
\82¢
\82Ì
\82Å
\83h
\83\89\83b
\83O
\82Å
\82«
\82È
\82¢
1059 if Button = mbLeft then begin
1060 FDragTabIndex := Index; //
\83h
\83\89\83b
\83O
\82·
\82é
\83^
\83u
\82Ì
\83C
\83\93\83f
\83b
\83N
\83X
\82ð
\95Û
\91¶
1062 FDragTabDest := -1; //
\83h
\83\89\83b
\83O
\98g
\90ü
\95`
\89æ
\83t
\83\89\83O
\83N
\83\8a\83A
\82Ì
\82½
\82ß
1067 procedure TfrmLog.tabBottleLogDragOver(Sender, Source: TObject; X,
1068 Y: Integer; State: TDragState; var Accept: Boolean);
1069 var TargetRect: TRect;
1072 Accept := Source = tabBottleLog;
1073 if not Accept then Exit;
1074 with tabBottleLog do begin
1075 OldDest := FDragTabDest;
1076 FDragTabDest := IndexOfTabAt(X, Y);
1077 if FDragTabDest = -1 then begin
1078 Accept := false; //
\82±
\82Ì
\8fê
\8d\87\82Í
\83h
\83\8d\83b
\83v
\82ð
\94F
\82ß
\82È
\82¢
1081 with Canvas do begin
1085 if (OldDest <> FDragTabDest) and (OldDest >= 0) then begin
1086 //
\88È
\91O
\82Ì
\98g
\90ü
\8fÁ
\8b\8e
1087 TargetRect := TabRect(OldDest);
1088 with Canvas do begin
1089 Brush.Style := bsClear;
1090 Rectangle(TargetRect.Left, TargetRect.Top,
1091 TargetRect.Right, TargetRect.Bottom);
1094 if (OldDest <> FDragTabDest) then begin
1095 //
\90V
\82µ
\82¢
\98g
\90ü
\95`
\89æ
1096 TargetRect := TabRect(FDragTabDest);
1097 with Canvas do begin
1098 Brush.Style := bsClear;
1099 Rectangle(TargetRect.Left, TargetRect.Top,
1100 TargetRect.Right, TargetRect.Bottom);
1106 procedure TfrmLog.tabBottleLogDragDrop(Sender, Source: TObject; X,
1108 var DestIndex: integer;
1110 with tabBottleLog do begin
1111 DestIndex := IndexOfTabAt(X, Y);
1112 Tabs.Move(FDragTabIndex, DestIndex);
1113 FBottleLogList.Move(FDragTabIndex, DestIndex);
1117 procedure TfrmLog.tabBottleLogEndDrag(Sender, Target: TObject; X,
1120 //
\8b
\90§
\93I
\82É
\83^
\83u
\82ð
\8dÄ
\95`
\89æ
\82³
\82¹
\82é
\81B
\98g
\90ü
\8fÁ
\82µ
\91Î
\8dô
1121 tabBottleLog.Tabs.BeginUpdate;
1122 tabBottleLog.Tabs.EndUpdate;
1125 procedure TfrmLog.LogLoadWork(Sender: TObject);
1127 if Sender = SelectedBottleLog then lvwLog.Invalidate;