OSDN Git Service

ログ画面の描画をリストビュー使用から由緒正しきリストボックスに変更。
authornaru <bottle@mikage.to>
Tue, 19 Jul 2005 15:38:59 +0000 (15:38 +0000)
committernaru <bottle@mikage.to>
Tue, 19 Jul 2005 15:38:59 +0000 (15:38 +0000)
スクロール性能が大幅アップ。将来的にはスクリプト2行表示なども可能に。
ただし現在のところログアイテムのドラッグ関連の機能が動かない。

bottleclient/LogForm.dfm
bottleclient/LogForm.pas
bottleclient/MainForm.pas

index 7e5a325..6ab55c2 100755 (executable)
@@ -143,7 +143,6 @@ object frmLog: TfrmLog
         item
           Width = 50
         end>
-      SimplePanel = False
     end
     object pnlPanel: TPanel
       Left = 0
@@ -185,62 +184,67 @@ object frmLog: TfrmLog
           OnEndDrag = tabBottleLogEndDrag
           OnMouseDown = tabBottleLogMouseDown
         end
-        object lvwLog: TListView
+        object Header: THeaderControl
           Left = 1
           Top = 27
           Width = 597
-          Height = 128
-          Align = alClient
-          BevelInner = bvNone
-          BorderStyle = bsNone
-          Columns = <
+          Height = 22
+          Sections = <
             item
-              Caption = #26085#20184
-              Width = 120
+              Alignment = taRightJustify
+              ImageIndex = -1
+              Text = #26085#26178
+              Width = 80
             end
             item
-              Caption = #12481#12515#12531#12493#12523
-              Width = 70
+              ImageIndex = -1
+              Text = #12481#12515#12531#12493#12523
+              Width = 80
             end
             item
-              Caption = #12468#12540#12473#12488
-              Width = 60
+              ImageIndex = -1
+              Text = #12468#12540#12473#12488
+              Width = 80
             end
             item
               Alignment = taRightJustify
-              Caption = #25237#31080
-              Width = 40
+              ImageIndex = -1
+              Text = #25237#31080
+              Width = 50
             end
             item
               Alignment = taRightJustify
-              Caption = #21516#24847
-              Width = 40
+              ImageIndex = -1
+              Text = #21516#24847
+              Width = 50
             end
             item
-              Caption = #12473#12463#12522#12503#12488
-              Width = 400
+              ImageIndex = -1
+              Text = #12473#12463#12522#12503#12488
+              Width = 120
             end>
-          DragMode = dmAutomatic
-          HideSelection = False
-          OwnerData = True
-          OwnerDraw = True
-          ReadOnly = True
-          RowSelect = True
+          OnSectionClick = HeaderSectionClick
+          OnSectionTrack = HeaderSectionTrack
+        end
+        object lvwLog: TListBox
+          Left = 1
+          Top = 49
+          Width = 597
+          Height = 106
+          Style = lbVirtualOwnerDraw
+          Align = alClient
+          ItemHeight = 16
           PopupMenu = PopupMenuListView
-          SmallImages = frmSender.imgIcon
-          TabOrder = 1
-          ViewStyle = vsReport
-          OnChange = lvwLogChange
+          TabOrder = 2
           OnClick = lvwLogClick
-          OnColumnClick = lvwLogColumnClick
-          OnCustomDrawItem = lvwLogCustomDrawItem
           OnData = lvwLogData
           OnDblClick = lvwLogDblClick
-          OnDrawItem = lvwLogDrawItem
-          OnEndDrag = lvwLogEndDrag
           OnDragDrop = lvwLogDragDrop
           OnDragOver = lvwLogDragOver
+          OnDrawItem = lvwLogDrawItem
+          OnEndDrag = lvwLogEndDrag
           OnKeyPress = lvwLogKeyPress
+          OnMouseDown = lvwLogMouseDown
           OnStartDrag = lvwLogStartDrag
         end
       end
index 9bb3696..4030f7c 100755 (executable)
@@ -4,10 +4,10 @@ interface
 
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
-  ComCtrls, ToolWin, StdCtrls, ExtCtrls, SsParser, BottleDef, Menus,
+  ComCtrls, ToolWin, StdCtrls, SsParser, BottleDef, Menus,
   Clipbrd, Logs, ShellAPI, Commctrl, DirectSstp, Contnrs, StrUtils,
   TalkShowFrame, SppList, HtmlOutputConfig, HtmlOutputProgress,
-  SearchLog, IniFiles, BRegExp, RegexUtils;
+  SearchLog, IniFiles, BRegExp, RegexUtils, ExtCtrls;
 
 type
   // \83\8d\83O\82Ì\95Û\91\95û\96@
@@ -49,7 +49,6 @@ type
     mnPreviewStyleScriptWithLineBreak: TMenuItem;
     Panel1: TPanel;
     tabBottleLog: TTabControl;
-    lvwLog: TListView;
     tbtnDownloadLog: TToolButton;
     PopupMenuTab: TPopupMenu;
     mnCloseTab: TMenuItem;
@@ -72,30 +71,26 @@ type
     mnSendEditor: TMenuItem;
     timScrollTimer: TTimer;
     mnChangeTabName: TMenuItem;
+    lvwLog: TListBox;
     N1: TMenuItem;
     N2: TMenuItem;
     mnDeleteLogItem: TMenuItem;
     mnTabSaveXMLLog: TMenuItem;
     mnSaveHTML: TMenuItem;
     mnPopupCopyGhost: TMenuItem;
+    Header: THeaderControl;
     procedure tbtnClearClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
-    procedure lvwLogChange(Sender: TObject; Item: TListItem;
-      Change: TItemChange);
     procedure lvwLogDblClick(Sender: TObject);
     procedure lvwLogKeyPress(Sender: TObject; var Key: Char);
     procedure FormDestroy(Sender: TObject);
     procedure lvwLogClick(Sender: TObject);
     procedure mnSaveLogClick(Sender: TObject);
-    procedure lvwLogColumnClick(Sender: TObject; Column: TListColumn);
     procedure mnPopUpCopyScriptClick(Sender: TObject);
     procedure mnSaveLogChannelClick(Sender: TObject);
     procedure mnSaveLogScriptClick(Sender: TObject);
     procedure mnSaveLogXMLClick(Sender: TObject);
-    procedure lvwLogData(Sender: TObject; Item: TListItem);
     procedure PopupMenuListViewPopup(Sender: TObject);
-    procedure lvwLogCustomDrawItem(Sender: TCustomListView;
-      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
     procedure PopupMenuPreviewStylePopup(Sender: TObject);
     procedure mnPreviewStyleClick(Sender: TObject);
     procedure tbtnPreviewStyleClick(Sender: TObject);
@@ -113,8 +108,6 @@ 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);
@@ -129,6 +122,16 @@ type
     procedure mnTabSaveXMLLogClick(Sender: TObject);
     procedure mnSaveHTMLClick(Sender: TObject);
     procedure mnPopupCopyGhostClick(Sender: TObject);
+    procedure lvwLogDrawItem(Control: TWinControl; Index: Integer;
+      Rect: TRect; State: TOwnerDrawState);
+    procedure lvwLogData(Control: TWinControl; Index: Integer;
+      var Data: String);
+    procedure HeaderSectionClick(HeaderControl: THeaderControl;
+      Section: THeaderSection);
+    procedure HeaderSectionTrack(HeaderControl: THeaderControl;
+      Section: THeaderSection; Width: Integer; State: TSectionTrackState);
+    procedure lvwLogMouseDown(Sender: TObject; Button: TMouseButton;
+      Shift: TShiftState; X, Y: Integer);
   private
     { Private \90é\8c¾ }
     FLastScript: String; //\83X\83N\83\8a\83v\83g\8dÄ\95`\89æ\97}\90§\97p
@@ -149,7 +152,7 @@ type
     function GetDefaultFileName(const Name: String; const Ext: String): String;
     function BottleLogTitled(const LogName: String): TBottleLogList;
     procedure DrawSingleLineScript(LogItem: TLogItem; Rect: TRect;
-      Item: TListItem);
+      State: TOwnerDrawState);
     procedure PreviewStyleChange;
     procedure DrawListViewDragBorder(const Rect: TRect);
     procedure DoSaveLogXML(Log: TBottleLogList);
@@ -157,6 +160,8 @@ type
     function DoSearchLog(Condition: TSearchCond): TBottleLogList;
     procedure SearchLogIndivisual(Condition: TSearchCond;
       LogList, Result: TBottleLogList; UntilIndex: integer = -1);
+    procedure DrawListSection(const SectionIndex, Top: Integer;
+      const Text: string; const LeftMargin: Integer = 0);
   protected
     procedure CreateParams(var Params: TCreateParams); override;
   public
@@ -177,6 +182,7 @@ type
     procedure UpdateTab;
     procedure UpdateWindow;
     procedure SelAndFocusMessage(const MID: String);
+    procedure CheckBottleURL(Bottle: TLogItem);
   end;
 
   TBottleLogDragObject = class(TDragControlObjectEx)
@@ -201,11 +207,12 @@ const
   IconPlaying   = 31;
   IconSystemLog = 26;
   IconURL       = 43;
-  SubChannel    = 0;
-  SubGhost      = 1;
-  SubVotes      = 2;
-  SubAgrees     = 3;
-  SubScript     = 4;
+  SubTime       = 0;
+  SubChannel    = 1;
+  SubGhost      = 2;
+  SubVotes      = 3;
+  SubAgrees     = 4;
+  SubScript     = 5;
 
 implementation
 
@@ -220,17 +227,20 @@ var Sel: integer;
 begin
   BottleLogTitled(LogName).AddScriptLog(Script, Channel, MID, Ghost);
   if SelectedBottleLog <> BottleLogTitled(LogName) then Exit;
-  lvwLog.OnChange := nil; //\83C\83x\83\93\83g\94­\90¶(\82¢\82ë\82¢\82ë\8dÄ\95`\89æ\82ª\8bN\82«\82é)\82Ì\97}\90§
-  if lvwLog.Selected <> nil then Sel := lvwLog.Selected.Index else Sel := -1;
-  lvwLog.Items.Count := SelectedBottleLog.Count;
+  //lvwLog.OnChange := nil; //\83C\83x\83\93\83g\94­\90¶(\82¢\82ë\82¢\82ë\8dÄ\95`\89æ\82ª\8bN\82«\82é)\82Ì\97}\90§
+  if lvwLog.Itemindex <> -1 then
+    Sel := lvwLog.ItemIndex
+  else
+    Sel := -1;
+  lvwLog.Count := SelectedBottleLog.Count;
   UpdateWindow;
   if Sel >= 0 then begin
-    lvwLog.Selected := lvwLog.Items[Sel + 1];
-    lvwLog.Selected.Focused := true;
+    lvwLog.ItemIndex := Sel + 1;
+    lvwLog.SetFocus;
   end;
   if not lvwLog.Focused then
     ListView_Scroll(lvwLog.Handle, 0, High(integer));
-  lvwLog.OnChange := lvwLogChange;
+  //lvwLog.OnChange := lvwLogChange;
 end;
 
 procedure TfrmLog.AddCurrentSystemLog(const LogName, MessageString: String);
@@ -238,17 +248,20 @@ var Sel: integer;
 begin
   BottleLogTitled(LogName).AddSystemLog(MessageString);
   if SelectedBottleLog <> BottleLogTitled(LogName) then Exit;
-  lvwLog.OnChange := nil;
-  if lvwLog.Selected <> nil then Sel := lvwLog.Selected.Index else Sel := -1;
-  lvwLog.Items.Count := SelectedBottleLog.Count;
+  //lvwLog.OnChange := nil;
+  if lvwLog.ItemIndex <> -1 then
+    Sel := lvwLog.ItemIndex
+  else
+    Sel := -1;
+  lvwLog.Count := SelectedBottleLog.Count;
   UpdateWindow;
   if Sel >= 0 then begin
-    lvwLog.Selected := lvwLog.Items[Sel + 1];
-    lvwLog.Selected.Focused := true;
+    lvwLog.ItemIndex := Sel + 1;
+    lvwLog.SetFocus;
   end;
   if not lvwLog.Focused then
     ListView_Scroll(lvwLog.Handle, 0, High(integer));
-  lvwLog.OnChange := lvwLogChange;
+  //lvwLog.OnChange := lvwLogChange;
 end;
 
 
@@ -279,7 +292,7 @@ begin
 
   i := 0;
   while Token(Pref.LogWindowColumnWidth, ',', i) <> '' do begin
-    lvwLog.Columns[i].Width := StrToIntDef(Token(Pref.LogWindowColumnWidth, ',', i), 100);
+    Header.Sections[i].Width := StrToIntDef(Token(Pref.LogWindowColumnWidth, ',', i), 100);
     Inc(i);
   end;
 
@@ -301,9 +314,9 @@ var i: integer;
     WidthStr: String;
 begin
   WidthStr := '';
-  for i := 0 to lvwLog.Columns.Count-1 do begin
+  for i := 0 to Header.Sections.Count-1 do begin
     if i > 0 then WidthStr := WidthStr + ',';
-    WidthStr := WidthStr + IntToStr(lvwLog.Column[i].Width);
+    WidthStr := WidthStr + IntToStr(Header.Sections[i].Width);
   end;
   Pref.LogWindowColumnWidth := WidthStr;
 
@@ -318,64 +331,14 @@ begin
   FreeAndNil(FBottleLogList);
 end;
 
-procedure TfrmLog.lvwLogChange(Sender: TObject; Item: TListItem;
-  Change: TItemChange);
-var Script, Text: String;
-    Log: TLogItem;
-    Selected, IsNormalBottle: boolean;
-begin
-  Selected := false;
-  IsNormalBottle := false;
-  if SelectedBottleLog <> nil then begin
-    if Change = ctState then begin
-      Script := '';
-      if lvwLog.Selected <> nil then begin
-        Selected := true;
-        StatusBar.Panels[0].Text := Format('%d/%d\8c\8f', [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;
-          Text := Format('%d\83o\83C\83g/%d\95b - \83_\83u\83\8b\83N\83\8a\83b\83N\82Å\8dÄ\90¶',
-            [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
-          StatusBar.Panels[1].Text := '';
-          UpdateScript(''); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\82ð\83N\83\8a\83A
-        end;
-      end else begin
-        StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '\8c\8f';
-        StatusBar.Panels[1].Text := '';
-        UpdateScript(Script); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\83N\83\8a\83A
-      end;
-    end;
-    tbtnSaveLog.Enabled := lvwLog.Items.Count > 0;
-  end else begin
-    StatusBar.Panels[0].Text := '';
-    UpdateScript(''); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\83N\83\8a\83A
-  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, ErrorMes: String;
     Log, CueItem: TLogItem;
     Res: integer;
 begin
-  if lvwLog.Selected = nil then
+  if lvwLog.ItemIndex = -1 then
     Exit;
-  Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
+  Log := SelectedBottleLog.Bottles[lvwLog.ItemIndex];
   if Log = nil then Exit;
   if Log.LogType <> ltBottle then
     Exit;
@@ -472,49 +435,58 @@ begin
 end;
 
 procedure TfrmLog.lvwLogClick(Sender: TObject);
+var Script, Text: String;
+    Log: TLogItem;
+    Selected, IsNormalBottle: boolean;
 begin
-  //\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ô
-  with lvwLog do
-    Selected := Selected;
-end;
-
-procedure TfrmLog.lvwLogColumnClick(Sender: TObject; Column: TListColumn);
-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
-  else
-    SelectedMID := '';
-
-  SortColumn := Column.Index;
-  case SortColumn-1 of
-    -1: SortType := stLogTime;
-    subChannel: SortType := stChannel;
-    subGhost:   SortType := stGhost;
-    subVotes:   SortType := stVote;
-    subAgrees:  SortType := stAgree;
-    subScript:  SortType := stScript;
-  else
-    SortType := stLogTime;
+  Selected := false;
+  IsNormalBottle := false;
+  if SelectedBottleLog <> nil then begin
+    Script := '';
+    if lvwLog.ItemIndex <> -1 then begin
+      Selected := true;
+      StatusBar.Panels[0].Text := Format('%d/%d\8c\8f', [lvwLog.ItemIndex+1,
+        SelectedBottleLog.Count]);
+      Log := SelectedBottleLog.Bottles[lvwLog.ItemIndex];
+      if (Log.LogType = ltBottle) and not frmSender.Connecting then begin
+        IsNormalBottle := true;
+        Script := Log.Script;
+        Text := Format('%d\83o\83C\83g/%d\95b - \83_\83u\83\8b\83N\83\8a\83b\83N\82Å\8dÄ\90¶',
+          [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
+        StatusBar.Panels[1].Text := '';
+        UpdateScript(''); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\82ð\83N\83\8a\83A
+      end;
+    end else begin
+      StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '\8c\8f';
+      StatusBar.Panels[1].Text := '';
+      UpdateScript(Script); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\83N\83\8a\83A
+    end;
+    tbtnSaveLog.Enabled := lvwLog.Items.Count > 0;
+  end else begin
+    StatusBar.Panels[0].Text := '';
+    UpdateScript(''); // \83\8d\83O\83v\83\8c\83r\83\85\81[\95\94\83N\83\8a\83A
   end;
-
-  SelectedBottleLog.SortBottles(SortType);
-  lvwLog.Invalidate;
-  if Length(SelectedMID) > 0 then
-    SelAndFocusMessage(SelectedMID);
+  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.mnPopUpCopyScriptClick(Sender: TObject);
 var
   Log: TLogItem;
   Clip: TClipBoard;
 begin
-  Log := SelectedBottleLog.Bottles[frmLog.lvwLog.Selected.Index];
+  Log := SelectedBottleLog.Bottles[frmLog.lvwLog.ItemIndex];
   if Log = nil then Exit;
   Clip := ClipBoard();
   Clip.SetTextBuf(PChar(Log.Script));
@@ -528,9 +500,9 @@ begin
     Bottle := (FBottleLogList[i] as TBottleLogList).Bottle(MID);
     if Bottle <> nil then begin
       Bottle.State := State;
-      lvwLog.OnChange := nil;
+      // lvwLog.OnChange := nil;
       lvwLog.Invalidate;
-      lvwLog.OnChange := lvwLogChange;
+      // lvwLog.OnChange := lvwLogChange;
     end;
   end;
 end;
@@ -574,45 +546,6 @@ begin
   DoSaveLogXML(SelectedBottleLog);
 end;
 
-procedure TfrmLog.lvwLogData(Sender: TObject; Item: TListItem);
-var i: integer;
-    Log: TLogItem;
-begin
-  if Item = nil then Exit;
-  i := Item.Index;
-  Log := SelectedBottleLog.Bottles[i];
-  with Item do begin
-    Caption := FormatDateTime('yy/mm/dd hh:nn:ss', Log.LogTime);
-    SubItems.Clear;
-    SubItems.Add(Log.Channel);
-    SubItems.Add(Log.Ghost);
-    if Log.LogType = ltBottle then begin
-      if Log.Votes > 0 then
-        SubItems.Add(IntToStr(Log.Votes))
-      else
-        SubItems.Add('');
-      if Log.Agrees > 0 then
-        SubItems.Add(IntToStr(Log.Agrees))
-      else
-        SubItems.Add('');
-    end else begin
-      // \83V\83X\83e\83\80\83\8d\83O\82È\82Ç\82Í\93\8a\95[\81E\93¯\88Ó\82ð\95\\8e¦\82µ\82È\82¢
-      SubItems.Add('');
-      SubItems.Add('');
-    end;
-    SubItems.Add(Log.Script);
-
-    if Log.LogType = ltBottle then begin
-      case Log.State of
-        lsUnopened: ImageIndex := IconBottle;
-        lsPlaying:  ImageIndex := IconPlaying;
-        lsOpened:   ImageIndex := IconOpened;
-      end;
-    end else
-      ImageIndex := IconSystemLog;
-  end;
-end;
-
 procedure TfrmLog.UpdateWindow;
 var EnabledFlag: boolean;
 begin
@@ -621,12 +554,12 @@ begin
   if SelectedBottleLog <> nil then begin
     Caption := '\83\8d\83O - ' + SelectedBottleLog.Title;
     StatusBar.Panels[0].Text := IntToStr(SelectedBottleLog.Count) + '\8c\8f';
-    lvwLog.Items.Count := SelectedBottleLog.Count;
+    lvwLog.Count := SelectedBottleLog.Count;
   end else begin
     Caption := '\83\8d\83O';
     StatusBar.Panels[0].Text := '';
     StatusBar.Panels[1].Text := '';
-    lvwLog.Items.Count := 0;
+    lvwLog.Count := 0;
   end;
 
   EnabledFlag := SelectedBottleLog <> nil;
@@ -644,15 +577,17 @@ var Log: TLogItem;
     Labels: TStringList;
     ProcessedUrl: String;
     ProcessedLabel: String;
-    i: integer;
+    i: Integer;
 begin
   for i := mnJumpURL.Count-1 downto 0 do begin
     mnJumpURL.Items[i].Free;
   end;
   mnJumpURL.Enabled := false;
-  if lvwLog.Selected = nil then Exit;
-  Log := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
-  if Log = nil then Exit;
+  if lvwLog.ItemIndex = -1 then
+    Exit;
+  Log := SelectedBottleLog.Bottles[lvwLog.ItemIndex];
+  if Log = nil then
+    Exit;
   Urls := TStringList.Create;
   Labels := TStringList.Create;
   try
@@ -686,8 +621,8 @@ var LogItem: TLogItem;
     Urls: TStringList;
 
 begin
-  if (lvwLog.Selected = nil) or (SelectedBottleLog = nil) then Exit;
-  LogItem := SelectedBottleLog[lvwLog.Selected.Index] as TLogItem;
+  if (lvwLog.ItemIndex <> -1) or (SelectedBottleLog = nil) then Exit;
+  LogItem := SelectedBottleLog[lvwLog.ItemIndex] as TLogItem;
   Urls := TStringList.Create;
   try
     ExtractURLs(LogItem.Script, Urls, nil);
@@ -754,18 +689,12 @@ begin
   for i := 0 to SelectedBottleLog.Count-1 do begin
     Log := SelectedBottleLog.Items[i] as TLogItem;
     if Log.MID = MID then begin
-      lvwLog.Items[i].Selected := true;
-      lvwLog.Items[i].Focused := true;
+      lvwLog.ItemIndex := i;
+      lvwLog.SetFocus;
     end;
   end;
 end;
 
-procedure TfrmLog.lvwLogCustomDrawItem(Sender: TCustomListView;
-  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
-begin
-  //
-end;
-
 procedure TfrmLog.UpdateScript(const Script: String);
 begin
   if Script <> FLastScript then begin
@@ -796,7 +725,8 @@ begin
   Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle((Sender as TMenuItem).Tag);
   PreviewStyleChange;
   FLastScript := '';
-  lvwLogChange(self, lvwLog.Selected, ctState);
+  {TODO: \82È\82ñ\82Æ\82©\82·\82é}
+  //lvwLogChange(self, lvwLog.Selected, ctState);
 end;
 
 procedure TfrmLog.UpdateScriptScript(const Script: String);
@@ -848,7 +778,8 @@ begin
   Pref.LogWindowPreviewStyle := TLogWindowPreviewStyle(sel);
   FLastScript := '';
   PreviewStyleChange;
-  lvwLogChange(self, lvwLog.Selected, ctState);
+  {TODO: \82È\82ñ\82Æ\82©\82·\82é}
+  //lvwLogChange(self, lvwLog.Selected, ctState);
 end;
 
 function TfrmLog.SelectedBottleLog: TBottleLogList;
@@ -867,10 +798,10 @@ begin
   with SelectedBottleLog do
     if (SelectedIndex >= 0) and (Count > SelectedIndex) then
     begin
-      lvwLog.Items[SelectedIndex].Selected := true;
-      if lvwLog.Focused then lvwLog.Selected.Focused := true;
+      lvwLog.ItemIndex := SelectedIndex;
     end;
-  lvwLogChange(Self, nil, ctState);
+  {TODO: \82È\82ñ\82Æ\82©\82·\82é}
+  //lvwLogChange(Self, nil, ctState);
 end;
 
 procedure TfrmLog.LogLoaded(Sender: TObject);
@@ -935,11 +866,9 @@ procedure TfrmLog.tabBottleLogChanging(Sender: TObject;
   var AllowChange: Boolean);
 begin
   // \8c»\8dÝ\91I\91ð\82³\82ê\82Ä\82¢\82é\83\8d\83O\82Ì\91I\91ð\8fó\91Ô\82ð\95Û\91
-  if SelectedBottleLog = nil then Exit;
-  if lvwLog.Selected <> nil then
-    SelectedBottleLog.SelectedIndex := lvwLog.Selected.Index
-  else
-    SelectedBottleLog.SelectedIndex := -1;
+  if SelectedBottleLog = nil then
+    Exit;
+  SelectedBottleLog.SelectedIndex := lvwLog.ItemIndex
 end;
 
 procedure TfrmLog.tabBottleLogContextPopup(Sender: TObject;
@@ -1177,115 +1106,12 @@ begin
   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;
-begin
-  Bottle := SelectedBottleLog.Bottles[Item.Index];
-  if Bottle.HasURL = huUndefined then
-  begin
-    try
-      if ExtractURLs(Bottle.Script, nil, nil) then
-        Bottle.HasURL := huYes
-      else
-        Bottle.HasURL := huNo;
-    finally
-    
-    end;
-  end;
-
-  // \94w\8ci\8fÁ\8b\8e
-  ListView_GetItemRect(lvwLog.Handle, Item.Index, DestRect, LVIR_BOUNDS);
-
-  // \94w\8ci\82Ì\90F\82Í\91I\91ð\8fó\91Ô\81E\91I\91ð\94ñ\83A\83N\83e\83B\83u\8fó\91Ô\81E\92Ê\8fí\8fó\91Ô\82Ì3\92Ê\82è
-  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;
-  // \83t\83H\81[\83J\83X\82ª\82 \82é\8fê\8d\87\82É\82Í\83t\83H\81[\83J\83X\82Ì\98g\90ü\82ð\88ø\82­
-  if Item.Focused and lvwLog.Focused then
-    lvwLog.Canvas.DrawFocusRect(DestRect);
-
-  // \83h\83\89\83b\83O\92\86\82È\82ç\98g\90ü\82ð\95`\89æ\82·\82é
-  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.TextColor;
-  lvwLog.Canvas.Refresh;
-
-  // \83L\83\83\83v\83V\83\87\83\93(\93ú\95t)
-  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_RIGHT, 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;
-  // \83L\83\83\83v\83V\83\87\83\93\82Å\82à\83X\83N\83\8a\83v\83g\82Å\82à\82È\82¢\82à\82Ì
-  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
-      // \8b·\82·\82¬\82é\8fê\8d\87\82Í\95\8e\9a\97ñ\82ð\95`\89æ\82µ\82È\82¢\81B
-      // 16\82Æ\82¢\82¤\90\94\8e\9a\82Í\8eÀ\91ª\92l\81B\89½\82©\82Ì\83o\83O\82Á\82Û
-      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);
+    lvwLog.Count := SelectedBottleLog.Count;
   end;
-  // \83X\83N\83\8a\83v\83g
-  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);
+  Rect: TRect; State: TOwnerDrawState);
 var
   i, x, w: integer;
   UnyuTalking, Synchronized, Spaced: boolean;
@@ -1308,7 +1134,7 @@ begin
   begin
     Ico := TIcon.Create;
     try
-      lvwLog.SmallImages.GetIcon(IconURL, Ico);
+      frmSender.imgIcon.GetIcon(IconURL, Ico);
       lvwLog.Canvas.Draw(Rect.Left + x, Rect.Top, Ico);
       Inc(x, 20);
     finally
@@ -1376,18 +1202,18 @@ begin
           lvwLog.Canvas.Font.Color := Pref.TalkColorH;
       end;
     end;
-    if Item.Selected then
+    if odSelected in State then
     begin
-      if lvwLog.Focused then
+      if odFocused in State 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;
+    if Rect.Right - Rect.Left < x then
+      Break;
   end;
 end;
 
@@ -1437,8 +1263,7 @@ end;
 procedure TfrmLog.lvwLogDragOver(Sender, Source: TObject; X, Y: Integer;
   State: TDragState; var Accept: Boolean);
 var
-  Target: TListItem;
-  OldDest: integer;
+  OldDest, Target: Integer;
   Rec: TRect; // \83_\83~\81[\81B
 begin
   Accept := False;
@@ -1446,16 +1271,16 @@ begin
   if not (Source is TBottleLogDragObject) then
     Exit;
 
-  Target := lvwLog.GetItemAt(X, Y);
+  Target := lvwLog.ItemAtPos(Point(X, Y), true);
 
   // \82±\82ê\88È\91O\82É\95`\89æ\82³\82ê\82Ä\82¢\82½\98g\82Ì\83C\83\93\83f\83b\83N\83X
   OldDest := FLVDragDest;
 
   // \83h\83\8d\83b\83v\88Ê\92u\82É Item \82ª\82 \82ê\82Î\83h\83\8d\83b\83v\82ð\8b\96\89Â\82·\82é
-  if Target <> nil then
+  if Target <> -1 then
   begin
     Accept := true;
-    FLVDragDest := Target.Index;
+    FLVDragDest := Target;
   end else
   begin
     Accept := true;
@@ -1465,18 +1290,19 @@ begin
   // \88È\91O\82Ì\98g\90ü\82ð\8dí\8f\9c
   if (OldDest > -1) and (FLVDragDest <> OldDest) then
   begin
-    Rec := lvwLog.Items[OldDest].DisplayRect(drBounds);
+    Rec := lvwLog.ItemRect(OldDest);
     DrawListViewDragBorder(Rec);
   end;
   // \83h\83\89\83b\83O\90æ\82Ì\98g\90ü\82ð\95`\89æ
-  if (Target <> nil) and (FLVDragDest <> OldDest) then
+  if (Target <> -1) and (FLVDragDest <> OldDest) then
   begin
-    Rec := Target.DisplayRect(drBounds);
+    Rec := lvwLog.ItemRect(Target);
     DrawListViewDragBorder(Rec);
   end;
 
   // \83X\83N\83\8d\81[\83\8b\8aÖ\8cW
-  if lvwLog.Items.Count > 0 then
+  {TODO: \83X\83N\83\8d\81[\83\8b\95\9c\8a\88\82³\82¹\82é}
+  {if lvwLog.Count > 0 then
   begin
     if (lvwLog.topItem <> nil) and (Y - lvwLog.TopItem.Top < 10) then
     begin
@@ -1492,7 +1318,7 @@ begin
     else
       timScrollTimer.Enabled := false;
   end else
-    timScrollTimer.Enabled := false;
+    timScrollTimer.Enabled := false;}
 end;
 
 procedure TfrmLog.lvwLogDragDrop(Sender, Source: TObject; X, Y: Integer);
@@ -1507,12 +1333,8 @@ begin
     Exit;
   Src := Source as TBottleLogDragObject;
 
-  if lvwLog.GetItemAt(X, Y) <> nil then
-    TargetItem := lvwLog.GetItemAt(X, Y).Index
-  else
-    TargetItem := -1;
+  TargetItem := lvwLog.ItemAtPos(Point(X, Y), true);
 
-  lvwLog.Items.BeginUpdate; // \83h\83\8d\83b\83v\92\86\82Í\95\\8e¦\82ð\97}\8e~\82·\82é\81@\8fd\97v\81I
   try
     // \83h\83\8d\83b\83v\88Ê\92u\82É Item \82ð\88Ú\93®\82·\82é
     if (GetAsyncKeyState(VK_CONTROL) and $8000) > 0 then
@@ -1531,10 +1353,8 @@ begin
       // ListView\82Ì\97]\94\92\82É\83h\83\8d\83b\83v\82µ\82½\8fê\8d\87(Insert\82Å\82«\82È\82¢)
       TargetItem := SelectedBottleLog.Add(SrcLog);
     end;
-    lvwLog.Items[TargetItem].Selected := true;
-    lvwLog.Items[TargetItem].Focused := true;
+    lvwLog.ItemIndex := TargetItem;
   finally
-    lvwLog.Items.EndUpdate;
     UpdateWindow;
   end;
 end;
@@ -1544,15 +1364,12 @@ var
   ScrollHeight: Integer;
 begin
   // \83X\83N\83\8d\81[\83\8b\97Ê\82ð\8b\81\82ß\82é
-  ScrollHeight := 0;
-  if lvwLog.Items.Count > 2 then
-  begin
-    ScrollHeight := lvwLog.Items[1].Top - lvwLog.Items[0].Top;
-  end;
+  ScrollHeight := lvwLog.ItemHeight;
 
+  {TODO: \83X\83N\83\8d\81[\83\8b\95\9c\8a\88}
   case FLVScrollDir of
-    lvScrollUp: lvwLog.Scroll(0, ScrollHeight);
-    lvSCrollDown: lvwLog.Scroll(0, -ScrollHeight);
+    lvScrollUp: ;//lvwLog.Scroll(0, ScrollHeight);
+    lvSCrollDown: ;//lvwLog.Scroll(0, -ScrollHeight);
   end;
   lvwLog.Invalidate;  // \8dÅ\90V\82Ì\8fó\91Ô\82É\8dÄ\95`\89æ\82·\82é
   lvwLog.Update;
@@ -1571,13 +1388,11 @@ procedure TfrmLog.lvwLogStartDrag(Sender: TObject;
   var DragObject: TDragObject);
 var Drag: TBottleLogDragObject;
 begin
-  // \92Ê\8fí\82ÌListView\97p\82Ì\83h\83\89\83b\83O\83I\83u\83W\83F\83N\83g\82Í
-  // OS\82É\82æ\82Á\82Ä\82Í\81A\88Ú\93®\82·\82é\82Æ\82«\82É\83A\83C\83e\83\80\82Ì\83C\83\81\81[\83W\82ð\94¼\93§\96¾\82Å\95`\89æ\82µ\82Ä\82µ\82Ü\82¤\81B
   // TDragObject\82©\82ç\92¼\90Ú\8cp\8f³\82µ\82½\82¾\82¯\82Ì\82à\82Ì(\83C\83\81\81[\83W\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢)\82ð\8eg\82¤\82Æ
-  // \94¼\93§\96¾\83C\83\81\81[\83W\82Ì\95`\89æ\82Í\97}\90§\82Å\82«\82é\81B
+  // \83h\83\89\83b\83O\83C\83\81\81[\83W\82Ì\95`\89æ\82Í\97}\90§\82Å\82«\82é\81B
   Drag := TBottleLogDragObject.Create(lvwLog);
   Drag.BottleLogList := SelectedBottleLog;
-  Drag.LogItem := SelectedBottleLog.Bottles[lvwLog.Selected.Index];
+  Drag.LogItem := SelectedBottleLog.Bottles[lvwLog.ItemIndex];
   DragObject := Drag;
 end;
 
@@ -1634,7 +1449,6 @@ begin
     if FBottleLogList[i] = PrevSelection then
       tabBottleLog.TabIndex := i;
   UpdateWindow;
-  lvwLogChange(Self, nil, ctState);
 end;
 
 procedure TfrmLog.HTMLOutputWork(Sender: TObject; const Count: integer;
@@ -1662,10 +1476,8 @@ begin
     begin
       if Condition.SearchLogRange = srSelectedLogList then
         UntilIndex := -1
-      else if lvwLog.Selected = nil then
-        UntilIndex := -1
       else
-        UntilIndex := lvwLog.Selected.Index;
+        UntilIndex := lvwLog.ItemIndex;
       SearchLogIndivisual(Condition, SelectedBottleLog, Result, UntilIndex);
     end;
   end else if Condition.SearchLogRange = srAllLogLists then
@@ -1739,6 +1551,49 @@ begin
   end;
 end;
 
+procedure TfrmLog.CheckBottleURL(Bottle: TLogItem);
+var
+  DummyStr: TStringList;
+begin
+  if Bottle.HasURL = huUndefined then
+  begin
+    DummyStr := TStringList.Create;
+    try
+      ExtractURLs(Bottle.Script, DummyStr, nil);
+      if DummyStr.Count > 0 then
+        Bottle.HasURL := huYes
+      else
+        Bottle.HasURL := huNo;
+    finally
+      DummyStr.Free;
+    end;
+  end;
+end;
+
+procedure TfrmLog.DrawListSection(const SectionIndex, Top: Integer;
+  const Text: string; const LeftMargin: Integer = 0);
+var
+  Sec: THeaderSection;
+  Ex: Integer;
+  Rec: TRect;
+const
+  MinimumTextWidth = 16; //\82±\82ê\82æ\82è\8b·\82¢\82È\82ç\82»\82à\82»\82à\95`\89æ\82µ\82È\82¢
+begin
+  Sec := Header.Sections[SectionIndex];
+
+  Rec.Left   := Sec.Left + 2 + LeftMargin;
+  Rec.Right  := Sec.Right - 2;
+  if Rec.Right - Rec.Left < MinimumTextWidth then
+    Exit;
+  Rec.Top    := Top + 2;
+  Rec.Bottom := Top + lvwLog.ItemHeight;
+
+  Ex := DT_NOPREFIX or DT_SINGLELINE or DT_END_ELLIPSIS;
+  if Sec.Alignment = taRightJustify then
+    Ex := (Ex or DT_RIGHT) and not (DT_END_ELLIPSIS);
+  DrawTextEx(lvwLog.Canvas.Handle, PChar(Text), -1, Rec, Ex, nil);
+end;
+
 { TBottleLogDragObject }
 
 function TBottleLogDragObject.GetDragImages: TDragImageList;
@@ -1788,12 +1643,12 @@ begin
               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]))
+            if SB.Bottles[lvwLog.ItemIndex].LogType = ltBottle then
+              LogList.Add(TLogItem.Create(SB.Bottles[lvwLog.ItemIndex]))
             else
               ShowMessage('\82±\82Ì\83\81\83b\83Z\81[\83W\82Í\95Û\91\82Å\82«\82Ü\82¹\82ñ');
           orUpward:
-            for i := lvwLog.Selected.Index downto 0 do
+            for i := lvwLog.ItemIndex downto 0 do
               if SB.Bottles[i].LogType = ltBottle then
                 LogList.Add(TLogItem.Create(SB.Bottles[i]));
         end;
@@ -1821,10 +1676,147 @@ var
   Log: TLogItem;
   Clip: TClipBoard;
 begin
-  Log := SelectedBottleLog.Bottles[frmLog.lvwLog.Selected.Index];
+  Log := SelectedBottleLog.Bottles[frmLog.lvwLog.ItemIndex];
   if Log = nil then Exit;
   Clip := ClipBoard();
   Clip.SetTextBuf(PChar(Log.Ghost));
 end;
 
+procedure TfrmLog.lvwLogDrawItem(Control: TWinControl; Index: Integer;
+  Rect: TRect; State: TOwnerDrawState);
+var
+  DestRect: TRect;
+  Ico: TIcon;
+  Bottle: TLogItem;
+begin
+  Bottle := SelectedBottleLog.Bottles[Index];
+  CheckBottleURL(Bottle);
+
+  DestRect := lvwLog.ItemRect(Index);
+
+  // \94w\8ci\82Ì\90F\82Í\91I\91ð\8fó\91Ô\81E\91I\91ð\94ñ\83A\83N\83e\83B\83u\8fó\91Ô\81E\92Ê\8fí\8fó\91Ô\82Ì3\92Ê\82è
+  lvwLog.Canvas.Brush.Style := bsSolid;
+  if odSelected in State then
+  begin
+    if odFocused in State 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;
+  // \83t\83H\81[\83J\83X\82ª\82 \82é\8fê\8d\87\82É\82Í\83t\83H\81[\83J\83X\82Ì\98g\90ü\82ð\88ø\82­
+  //if lvwLog.Focused then
+  //  lvwLog.Canvas.DrawFocusRect(DestRect);
+
+  // \83h\83\89\83b\83O\92\86\82È\82ç\98g\90ü\82ð\95`\89æ\82·\82é
+  if FLVDragDest = Index then
+  begin
+    DrawListViewDragBorder(DestRect);
+  end;
+
+  if odSelected in State then
+  begin
+    if odFocused in State then
+      lvwLog.Canvas.Font.Color := clHighlightText
+    else
+      lvwLog.Canvas.Font.Color := clWindowText;
+  end else
+  lvwLog.Canvas.Font.Color := Pref.TextColor;
+
+  //lvwLog.Canvas.TextOut(DestRect.Left, DestRect.Top, Bottle.Script);
+  // \93ú\95t
+  DrawListSection(SubTime, DestRect.Top,
+    FormatDateTime('yy/mm/dd hh:nn:ss', Bottle.LogTime), 16);
+  // \93ú\95t\97\93\83{\83g\83\8b\83A\83C\83R\83\93
+  Ico := TIcon.Create;
+  try
+    if Bottle.LogType = ltSystemLog then
+      frmSender.imgIcon.GetIcon(IconSystemLog, Ico)
+    else
+      case Bottle.State of
+        lsUnopened:
+          frmSender.imgIcon.GetIcon(IconBottle, Ico);
+        lsOpened:
+          frmSender.imgIcon.GetIcon(IconOpened, Ico);
+        lsPlaying:
+          frmSender.imgIcon.GetIcon(IconPlaying, Ico);
+      end;
+    lvwLog.Canvas.Draw(2, DestRect.Top, Ico);
+  finally
+    Ico.Free;
+  end;
+
+  // \83`\83\83\83\93\83l\83\8b
+  DrawListSection(SubChannel, DestRect.Top, Bottle.Channel);
+  // \83S\81[\83X\83g
+  DrawListSection(SubGhost, DestRect.Top, Bottle.Ghost);
+  // \93\8a\95[\81E\93¯\88Ó
+  DrawListSection(SubVotes, DestRect.Top, IntToStr(Bottle.Votes));
+  DrawListSection(SubAgrees, DestRect.Top, IntToStr(Bottle.Agrees));
+  // \83X\83N\83\8a\83v\83g
+  DestRect.Left := Header.Sections[SubScript].Left;
+  DrawSingleLineScript(Bottle, DestRect, State);
+end;
+
+procedure TfrmLog.lvwLogData(Control: TWinControl; Index: Integer;
+  var Data: String);
+begin
+  Data := '';
+end;
+
+procedure TfrmLog.HeaderSectionClick(HeaderControl: THeaderControl;
+  Section: THeaderSection);
+var SortType: TBottleLogSortType;
+    SelectedMID: String;
+begin
+  if SelectedBottleLog = nil then
+    Exit;
+  if lvwLog.ItemIndex <> -1 then
+    SelectedMID := SelectedBottleLog.Bottles[lvwLog.ItemIndex].MID
+  else
+    SelectedMID := '';
+
+  case Section.Index of
+    SubTime:    SortType := stLogTime;
+    SubChannel: SortType := stChannel;
+    SubGhost:   SortType := stGhost;
+    SubVotes:   SortType := stVote;
+    SubAgrees:  SortType := stAgree;
+    SubScript:  SortType := stScript;
+  else
+    SortType := stLogTime;
+  end;
+
+  SelectedBottleLog.SortBottles(SortType);
+  lvwLog.Invalidate;
+  if Length(SelectedMID) > 0 then
+    SelAndFocusMessage(SelectedMID);
+end;
+
+procedure TfrmLog.HeaderSectionTrack(HeaderControl: THeaderControl;
+  Section: THeaderSection; Width: Integer; State: TSectionTrackState);
+begin
+  lvwLog.Invalidate;
+end;
+
+procedure TfrmLog.lvwLogMouseDown(Sender: TObject; Button: TMouseButton;
+  Shift: TShiftState; X, Y: Integer);
+var
+  Index: Integer;
+begin
+  if Button = mbRight then
+  begin
+    Index := lvwLog.ItemAtPos(Point(X, Y), true);
+    if Index > -1 then
+    begin
+      lvwLog.ItemIndex := Index;
+      lvwLogClick(Self);
+    end;
+  end;
+end;
+
 end.
index 1803fb7..ed1c69f 100755 (executable)
@@ -12,14 +12,15 @@ uses
   Menus, StdCtrls, ComCtrls, BRegExp, BottleDef, BottleSstp,
   DirectSstp, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
   IdSLPP20, SsParser, ImgList, AppEvnts, TaskTray, StdActns,
-  ActnList, MPlayer, MenuBar, ToolWin,
-  IniFiles, ExtCtrls, ShellAPI, Contnrs,      
+  ActnList, MPlayer, MenuBar, ToolWin, SsPlayTime, heClasses, heFountain,
+  SakuraScriptFountain, HEditor,
+  IniFiles, ShellAPI, Contnrs,
   ConstEditor, Buttons, Clipbrd, HeadValue, Logs, MultipleChoiceEditor,
   IdException, HttpThread, IdHTTP, LogDownload,
   ScriptConsts, DateUtils, BottleChainRule, BottleChainEvent,
-  SakuraSeekerInstance, HEditor, HTSearch, heClasses, heFountain,
-  SakuraScriptFountain, SppList, SurfacePreview, XDOM_2_3_J3, SsPlayTime,
-  RegexUtils, StrReplace, StrReplaceDialog, ReplacePresetEditor;
+  SakuraSeekerInstance, HTSearch,
+  SppList, SurfacePreview, XDOM_2_3_J3,
+  RegexUtils, StrReplace, StrReplaceDialog, ReplacePresetEditor, ExtCtrls;
 
 type
   TSurfacePreviewType = (spHint, spEditor);
@@ -677,7 +678,7 @@ begin
     actStart.Enabled := true;
     actStop.Enabled := true;
     actSend.Enabled := true;
-    frmLog.lvwLogChange(Self, nil, ctState);
+    frmLog.lvwLogClick(Self);
     mnGetNewId.Enabled := Pref.LUID = '';
     Screen.Cursor := crDefault;
   end;
@@ -1972,8 +1973,8 @@ end;
 procedure TfrmSender.actVoteMessageExecute(Sender: TObject);
 var Log: TLogItem;
 begin
-  if frmLog.lvwLog.Selected = nil then Exit;
-  Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem;
+  if frmLog.lvwLog.ItemIndex < 0 then Exit;
+  Log := frmLog.SelectedBottleLog[frmLog.lvwLog.ItemIndex] as TLogItem;
   if Log = nil then Exit;
   if Log.LogType <> ltBottle then Exit;
   PostCommand([
@@ -1988,8 +1989,8 @@ end;
 procedure TfrmSender.actAgreeMessageExecute(Sender: TObject);
 var Log: TLogItem;
 begin
-  if frmLog.lvwLog.Selected = nil then Exit;
-  Log := frmLog.SelectedBottleLog[frmLog.lvwLog.Selected.Index] as TLogItem;
+  if frmLog.lvwLog.ItemIndex < 0 then Exit;
+  Log := frmLog.SelectedBottleLog[frmLog.lvwLog.ItemIndex] as TLogItem;
   if Log = nil then Exit;
   if Log.LogType <> ltBottle then Exit;
   PostCommand([
@@ -2586,12 +2587,12 @@ begin
   end;
   FBottleSstp.Clear;
   frmLog.AllBottleOpened;
-  if frmLog.lvwLog.Selected = nil then Exit;
+  if frmLog.lvwLog.ItemIndex < 0 then Exit;
   Log := frmLog.SelectedBottleLog;
   if Log = nil then Exit;
   FBottleSSTP.OnResendCountChange := nil;
   errCount := 0;
-  for i := frmLog.lvwLog.Selected.Index downto 0 do begin
+  for i := frmLog.lvwLog.ItemIndex downto 0 do begin
     if (Log[i] as TLogItem).LogType <> ltBottle then Continue;
     InsertItem := TLogItem.Create(Log[i] as TLogItem);
     try
@@ -2966,8 +2967,8 @@ 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 frmLog.lvwLog.ItemIndex < 0 then Exit;
+  Log := frmLog.SelectedBottleLog[frmLog.lvwLog.ItemIndex] as TLogItem;
   if Log = nil then Exit;
   CopyFromLogToEditor(Log);
 end;
@@ -3033,11 +3034,11 @@ begin
   // \83\8d\83O\83E\83B\83\93\83h\83E\82Ì\8cÂ\95Ê\83\8d\83O\82ð\8dí\8f\9c\82·\82é
   if frmLog.SelectedBottleLog = nil then
     Exit;
-  if frmLog.lvwLog.Selected = nil then
+  if frmLog.lvwLog.ItemIndex = -1 then
     Exit;
-  frmLog.SelectedBottleLog.Delete(frmLog.lvwLog.Selected.Index);
+  frmLog.SelectedBottleLog.Delete(frmLog.lvwLog.ItemIndex);
   frmLog.UpdateWindow;
-  frmLog.lvwLogChange(Self, nil, ctState);
+  frmLog.lvwLogClick(Self);
 end;
 
 procedure TfrmSender.ClearEditor;