OSDN Git Service

画像共有サービスに使用するインタフェースを設計し直し
[opentween/open-tween.git] / OpenTween / Tween.cs
index 764d9bf..eb7585a 100644 (file)
@@ -20,7 +20,7 @@
 // for more details. 
 // 
 // You should have received a copy of the GNU General public License along
-// with this program. if (not, see <http://www.gnu.org/licenses/>, or write to
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
@@ -37,13 +37,13 @@ using System.IO;
 using System.Linq;
 using System.Media;
 using System.Net;
+using System.Net.Http;
 using System.Reflection;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows.Forms;
-
 using OpenTween.Api;
 using OpenTween.Connection;
 using OpenTween.OpenTweenCustomControl;
@@ -53,13 +53,14 @@ namespace OpenTween
 {
     public partial class TweenMain : OTBaseForm
     {
+        private readonly HttpClient http;
+
         //各種設定
         private Size _mySize;           //画面サイズ
         private Point _myLoc;           //画面位置
         private int _mySpDis;           //区切り位置
         private int _mySpDis2;          //発言欄区切り位置
         private int _mySpDis3;          //プレビュー区切り位置
-        private int _myAdSpDis;         //Ad区切り位置
         private int _iconSz;            //アイコンサイズ(現在は16、24、48の3種類。将来直接数字指定可能とする 注:24x24の場合に26と指定しているのはMSゴシック系フォントのための仕様)
         private bool _iconCol;          //1列表示の時true(48サイズのとき)
 
@@ -105,7 +106,7 @@ namespace OpenTween
 
         //サブ画面インスタンス
         private AppendSettingDialog SettingDialog = AppendSettingDialog.Instance;       //設定画面インスタンス
-        private SearchWord SearchDialog = new SearchWord();     //検索画面インスタンス
+        private SearchWordDialog SearchDialog = new SearchWordDialog();     //検索画面インスタンス
         private FilterDialog fltDialog = new FilterDialog(); //フィルター編集画面
         private OpenURL UrlDialog = new OpenURL();
         public AtIdSupplement AtIdSupl;     //@id補助
@@ -146,6 +147,8 @@ namespace OpenTween
         private Icon ReplyIcon;               //5g
         private Icon ReplyIconBlink;          //6g
 
+        private ImageList _listViewImageList = new ImageList();    //ListViewItemの高さ変更用
+
         private PostClass _anchorPost;
         private bool _anchorFlag;        //true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
 
@@ -208,7 +211,6 @@ namespace OpenTween
 
         private bool _DoFavRetweetFlags = false;
         private bool osResumed = false;
-        private Dictionary<string, IMultimediaShareService> pictureService;
 
         //////////////////////////////////////////////////////////////////////////////////////////////////////////
         private string _postBrowserStatusText = "";
@@ -293,7 +295,7 @@ namespace OpenTween
             public long? inReplyToId = null;
             public string inReplyToName = null;
             public string imageService = "";      //画像投稿サービス名
-            public string imagePath = "";
+            public string[] imagePath = null;
             public PostingStatus()
             {
             }
@@ -332,6 +334,7 @@ namespace OpenTween
             if (MainIcon != null) MainIcon.Dispose();
             if (ReplyIcon != null) ReplyIcon.Dispose();
             if (ReplyIconBlink != null) ReplyIconBlink.Dispose();
+            _listViewImageList.Dispose();
             _brsHighLight.Dispose();
             if (_brsBackColorMine != null) _brsBackColorMine.Dispose();
             if (_brsBackColorAt != null) _brsBackColorAt.Dispose();
@@ -358,6 +361,9 @@ namespace OpenTween
                 this.IconCache.CancelAsync();
                 this.IconCache.Dispose();
             }
+
+            this.http.Dispose();
+
             // 終了時にRemoveHandlerしておかないとメモリリークする
             // http://msdn.microsoft.com/ja-jp/library/microsoft.win32.systemevents.powermodechanged.aspx
             Microsoft.Win32.SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
@@ -427,6 +433,110 @@ namespace OpenTween
             LoadIcon(ref ReplyIconBlink, "Icons\\ReplyBlink.ico");
         }
 
+        private void InitColumns(ListView list, bool startup)
+        {
+            ColumnHeader _colHd1 = new ColumnHeader();  //アイコン
+            ColumnHeader _colHd2 = new ColumnHeader();  //ニックネーム
+            ColumnHeader _colHd3 = new ColumnHeader();  //本文
+            ColumnHeader _colHd4 = new ColumnHeader();  //日付
+            ColumnHeader _colHd5 = new ColumnHeader();  //ユーザID
+            ColumnHeader _colHd6 = new ColumnHeader();  //未読
+            ColumnHeader _colHd7 = new ColumnHeader();  //マーク&プロテクト
+            ColumnHeader _colHd8 = new ColumnHeader();  //ソース
+
+            if (!_iconCol)
+            {
+                list.Columns.AddRange(new ColumnHeader[] { _colHd1, _colHd2, _colHd3, _colHd4, _colHd5, _colHd6, _colHd7, _colHd8 });
+            }
+            else
+            {
+                list.Columns.AddRange(new ColumnHeader[] { _colHd1, _colHd3 });
+            }
+
+            InitColumnText();
+            _colHd1.Text = ColumnText[0];
+            _colHd1.Width = 48;
+            _colHd2.Text = ColumnText[1];
+            _colHd2.Width = 80;
+            _colHd3.Text = ColumnText[2];
+            _colHd3.Width = 300;
+            _colHd4.Text = ColumnText[3];
+            _colHd4.Width = 50;
+            _colHd5.Text = ColumnText[4];
+            _colHd5.Width = 50;
+            _colHd6.Text = ColumnText[5];
+            _colHd6.Width = 16;
+            _colHd7.Text = ColumnText[6];
+            _colHd7.Width = 16;
+            _colHd8.Text = ColumnText[7];
+            _colHd8.Width = 50;
+
+            int[] dispOrder = new int[8];
+            if (!startup)
+            {
+                for (int i = 0; i < _curList.Columns.Count; i++)
+                {
+                    for (int j = 0; j < _curList.Columns.Count; j++)
+                    {
+                        if (_curList.Columns[j].DisplayIndex == i)
+                        {
+                            dispOrder[i] = j;
+                            break;
+                        }
+                    }
+                }
+                for (int i = 0; i < _curList.Columns.Count; i++)
+                {
+                    list.Columns[i].Width = _curList.Columns[i].Width;
+                    list.Columns[dispOrder[i]].DisplayIndex = i;
+                }
+            }
+            else
+            {
+                if (_iconCol)
+                {
+                    list.Columns[0].Width = _cfgLocal.Width1;
+                    list.Columns[1].Width = _cfgLocal.Width3;
+                    list.Columns[0].DisplayIndex = 0;
+                    list.Columns[1].DisplayIndex = 1;
+                }
+                else
+                {
+                    for (int i = 0; i <= 7; i++)
+                    {
+                        if (_cfgLocal.DisplayIndex1 == i)
+                            dispOrder[i] = 0;
+                        else if (_cfgLocal.DisplayIndex2 == i)
+                            dispOrder[i] = 1;
+                        else if (_cfgLocal.DisplayIndex3 == i)
+                            dispOrder[i] = 2;
+                        else if (_cfgLocal.DisplayIndex4 == i)
+                            dispOrder[i] = 3;
+                        else if (_cfgLocal.DisplayIndex5 == i)
+                            dispOrder[i] = 4;
+                        else if (_cfgLocal.DisplayIndex6 == i)
+                            dispOrder[i] = 5;
+                        else if (_cfgLocal.DisplayIndex7 == i)
+                            dispOrder[i] = 6;
+                        else if (_cfgLocal.DisplayIndex8 == i)
+                            dispOrder[i] = 7;
+                    }
+                    list.Columns[0].Width = _cfgLocal.Width1;
+                    list.Columns[1].Width = _cfgLocal.Width2;
+                    list.Columns[2].Width = _cfgLocal.Width3;
+                    list.Columns[3].Width = _cfgLocal.Width4;
+                    list.Columns[4].Width = _cfgLocal.Width5;
+                    list.Columns[5].Width = _cfgLocal.Width6;
+                    list.Columns[6].Width = _cfgLocal.Width7;
+                    list.Columns[7].Width = _cfgLocal.Width8;
+                    for (int i = 0; i <= 7; i++)
+                    {
+                        list.Columns[dispOrder[i]].DisplayIndex = i;
+                    }
+                }
+            }
+        }
+
         private void InitColumnText()
         {
             ColumnText[0] = "";
@@ -501,7 +611,7 @@ namespace OpenTween
             TraceOutToolStripMenuItem.Checked = true;
             MyCommon.TraceFlag = true;
 #endif
-            if (!MyCommon.fileVersion.EndsWith("0"))
+            if (!MyCommon.FileVersion.EndsWith("0"))
             {
                 TraceOutToolStripMenuItem.Checked = true;
                 MyCommon.TraceFlag = true;
@@ -516,6 +626,7 @@ namespace OpenTween
             //Win32Api.SetProxy(HttpConnection.ProxyType.Specified, "127.0.0.1", 8080, "user", "pass")
 
             SecurityManager = new InternetSecurityManager(PostBrowser);
+            this.PostBrowser.AllowWebBrowserDrop = false;  // COMException を回避するため、ActiveX の初期化が終わってから設定する
 
             MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
             Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
@@ -525,16 +636,9 @@ namespace OpenTween
 
             Regex.CacheSize = 100;
 
-            MyCommon.fileVersion = ((AssemblyFileVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0]).Version;
             InitializeTraceFrag();
             LoadIcons(); // アイコン読み込み
 
-            ThumbnailGenerator.InitializeGenerator();
-
-            Thumbnail.Services.TonTwitterCom.InitializeOAuthToken = x =>
-                x.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
-                    this.tw.AccessToken, this.tw.AccessTokenSecret, "", "");
-
             //発言保持クラス
             _statuses = TabInformations.GetInstance();
 
@@ -560,6 +664,16 @@ namespace OpenTween
             ////設定読み出し
             LoadConfig();
 
+            ThumbnailGenerator.InitializeGenerator(this.http);
+
+            var imgazyobizinet = ThumbnailGenerator.ImgAzyobuziNetInstance;
+            imgazyobizinet.Enabled = this._cfgCommon.EnableImgAzyobuziNet;
+            imgazyobizinet.DisabledInDM = this._cfgCommon.ImgAzyobuziNetDisabledInDM;
+
+            Thumbnail.Services.TonTwitterCom.InitializeOAuthToken = x =>
+                x.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
+                    this.tw.AccessToken, this.tw.AccessTokenSecret, "", "");
+
             //新着バルーン通知のチェック状態設定
             NewPostPopMenuItem.Checked = _cfgCommon.NewAllPop;
             this.NotifyFileMenuItem.Checked = NewPostPopMenuItem.Checked;
@@ -594,15 +708,6 @@ namespace OpenTween
                 this.Font = fontUIGlobal;
             }
 
-            _brsBackColorMine = new SolidBrush(_clSelf);
-            _brsBackColorAt = new SolidBrush(_clAtSelf);
-            _brsBackColorYou = new SolidBrush(_clTarget);
-            _brsBackColorAtYou = new SolidBrush(_clAtTarget);
-            _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
-            _brsBackColorAtTo = new SolidBrush(_clAtTo);
-            //_brsBackColorNone = new SolidBrush(Color.FromKnownColor(KnownColor.Window));
-            _brsBackColorNone = new SolidBrush(_clListBackcolor);
-
             // StringFormatオブジェクトへの事前設定
             //sf.Alignment = StringAlignment.Near;             // Textを近くへ配置(左から右の場合は左寄せ)
             //sf.LineAlignment = StringAlignment.Near;         // Textを近くへ配置(上寄せ)
@@ -740,33 +845,16 @@ namespace OpenTween
             SettingDialog.UseAtIdSupplement = _cfgCommon.UseAtIdSupplement;
             SettingDialog.UseHashSupplement = _cfgCommon.UseHashSupplement;
             SettingDialog.PreviewEnable = _cfgCommon.PreviewEnable;
+            SettingDialog.StatusAreaAtBottom = _cfgCommon.StatusAreaAtBottom;
             AtIdSupl = new AtIdSupplement(SettingAtIdList.Load().AtIdList, "@");
 
             SettingDialog.IsMonospace = _cfgCommon.IsMonospace;
-            if (SettingDialog.IsMonospace)
-            {
-                detailHtmlFormatHeader = detailHtmlFormatMono1;
-                detailHtmlFormatFooter = detailHtmlFormatMono7;
-            }
-            else
-            {
-                detailHtmlFormatHeader = detailHtmlFormat1;
-                detailHtmlFormatFooter = detailHtmlFormat7;
-            }
-            detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
-            if (SettingDialog.IsMonospace)
-            {
-                detailHtmlFormatHeader += detailHtmlFormatMono6;
-            }
-            else
-            {
-                detailHtmlFormatHeader += detailHtmlFormat6;
-            }
+
             this.IdeographicSpaceToSpaceToolStripMenuItem.Checked = _cfgCommon.WideSpaceConvert;
             this.ToolStripFocusLockMenuItem.Checked = _cfgCommon.FocusLockToStatusText;
 
             //Regex statregex = new Regex("^0*");
-            SettingDialog.RecommendStatusText = " [TWNv" + Regex.Replace(MyCommon.fileVersion.Replace(".", ""), "^0*", "") + "]";
+            SettingDialog.RecommendStatusText = " [TWNv" + Regex.Replace(MyCommon.FileVersion.Replace(".", ""), "^0*", "") + "]";
 
             //書式指定文字列エラーチェック
             try
@@ -807,7 +895,8 @@ namespace OpenTween
             SettingDialog.UserAppointUrl = _cfgCommon.UserAppointUrl;
             SettingDialog.HideDuplicatedRetweets = _cfgCommon.HideDuplicatedRetweets;
 
-            SettingDialog.IsPreviewFoursquare = _cfgCommon.IsPreviewFoursquare;
+            SettingDialog.EnableImgAzyobuziNet = _cfgCommon.EnableImgAzyobuziNet;
+            SettingDialog.ImgAzyobuziNetDisabledInDM = _cfgCommon.ImgAzyobuziNetDisabledInDM;
             SettingDialog.MapThumbnailProvider = _cfgCommon.MapThumbnailProvider;
             SettingDialog.MapThumbnailHeight = _cfgCommon.MapThumbnailHeight;
             SettingDialog.MapThumbnailWidth = _cfgCommon.MapThumbnailWidth;
@@ -830,7 +919,7 @@ namespace OpenTween
             _initial = true;
 
             //アイコンリスト作成
-            this.IconCache = new ImageCache();
+            this.IconCache = new ImageCache(this.http);
 
             bool saveRequired = false;
             bool firstRun = false;
@@ -855,6 +944,7 @@ namespace OpenTween
                     return;
                 }
                 SettingDialog.ShowInTaskbar = false;
+
                 //新しい設定を反映
                 //フォント&文字色&背景色保持
                 _fntUnread = SettingDialog.FontUnread;
@@ -878,43 +968,21 @@ namespace OpenTween
                 _clInputBackcolor = SettingDialog.ColorInputBackcolor;
                 _clInputFont = SettingDialog.ColorInputFont;
                 _fntInputFont = SettingDialog.FontInputFont;
-                _brsBackColorMine.Dispose();
-                _brsBackColorAt.Dispose();
-                _brsBackColorYou.Dispose();
-                _brsBackColorAtYou.Dispose();
-                _brsBackColorAtFromTarget.Dispose();
-                _brsBackColorAtTo.Dispose();
-                _brsBackColorNone.Dispose();
-                _brsBackColorMine = new SolidBrush(_clSelf);
-                _brsBackColorAt = new SolidBrush(_clAtSelf);
-                _brsBackColorYou = new SolidBrush(_clTarget);
-                _brsBackColorAtYou = new SolidBrush(_clAtTarget);
-                _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
-                _brsBackColorAtTo = new SolidBrush(_clAtTo);
-                _brsBackColorNone = new SolidBrush(_clListBackcolor);
-
-                if (SettingDialog.IsMonospace)
-                {
-                    detailHtmlFormatHeader = detailHtmlFormatMono1;
-                    detailHtmlFormatFooter = detailHtmlFormatMono7;
-                }
-                else
-                {
-                    detailHtmlFormatHeader = detailHtmlFormat1;
-                    detailHtmlFormatFooter = detailHtmlFormat7;
-                }
-                detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
-                if (SettingDialog.IsMonospace)
-                {
-                    detailHtmlFormatHeader += detailHtmlFormatMono6;
-                }
-                else
-                {
-                    detailHtmlFormatHeader += detailHtmlFormat6;
-                }
+
                 //他の設定項目は、随時設定画面で保持している値を読み出して使用
             }
 
+            _brsBackColorMine = new SolidBrush(_clSelf);
+            _brsBackColorAt = new SolidBrush(_clAtSelf);
+            _brsBackColorYou = new SolidBrush(_clTarget);
+            _brsBackColorAtYou = new SolidBrush(_clAtTarget);
+            _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
+            _brsBackColorAtTo = new SolidBrush(_clAtTo);
+            //_brsBackColorNone = new SolidBrush(Color.FromKnownColor(KnownColor.Window));
+            _brsBackColorNone = new SolidBrush(_clListBackcolor);
+
+            InitDetailHtmlFormat();
+
             if (SettingDialog.HotkeyEnabled)
             {
                 //////グローバルホットキーの登録
@@ -937,9 +1005,9 @@ namespace OpenTween
 
             tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
             tw.ReadOwnPost = SettingDialog.ReadOwnPost;
-            ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
-            ShortUrl.BitlyId = SettingDialog.BitlyUser;
-            ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
+            ShortUrl.Instance.DisableExpanding = !SettingDialog.TinyUrlResolve;
+            ShortUrl.Instance.BitlyId = SettingDialog.BitlyUser;
+            ShortUrl.Instance.BitlyKey = SettingDialog.BitlyPwd;
             HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
             tw.TrackWord = _cfgCommon.TrackWord;
             TrackToolStripMenuItem.Checked = !String.IsNullOrEmpty(tw.TrackWord);
@@ -947,11 +1015,7 @@ namespace OpenTween
             AllrepliesToolStripMenuItem.Checked = tw.AllAtReply;
 
             //画像投稿サービス
-            this.CreatePictureServices();
-            SetImageServiceCombo();
-            ImageSelectionPanel.Enabled = false;
-
-            SelectImageServiceComboItem(_cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
+            ImageSelector.Initialize(tw, SettingDialog.TwitterConfiguration, _cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
 
             //ウィンドウ設定
             this.ClientSize = _cfgLocal.FormSize;
@@ -990,7 +1054,6 @@ namespace OpenTween
                 if (_mySpDis3 < 1) _mySpDis3 = 50;
                 _cfgLocal.PreviewDistance = _mySpDis3;
             }
-            _myAdSpDis = _cfgLocal.AdSplitterDistance;
             MultiLineMenuItem.Checked = _cfgLocal.StatusMultiline;
             //this.Tween_ClientSizeChanged(this, null);
             PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
@@ -1002,6 +1065,9 @@ namespace OpenTween
             // NameLabel のフォントを OTBaseForm.GlobalFont に変更
             this.NameLabel.Font = this.ReplaceToGlobalFont(this.NameLabel.Font);
 
+            // 必要であれば、発言一覧と発言詳細部・入力欄の上下を入れ替える
+            SplitContainer1.IsPanelInverted = !SettingDialog.StatusAreaAtBottom;
+
             //全新着通知のチェック状態により、Reply&DMの新着通知有効無効切り替え(タブ別設定にするため削除予定)
             if (SettingDialog.UnreadManage == false)
             {
@@ -1059,42 +1125,9 @@ namespace OpenTween
             _statuses.SortMode = mode;
             ////////////////////////////////////////////////////////////////////////////////
 
-            switch (SettingDialog.IconSz)
-            {
-                case MyCommon.IconSizes.IconNone:
-                    _iconSz = 0;
-                    break;
-                case MyCommon.IconSizes.Icon16:
-                    _iconSz = 16;
-                    break;
-                case MyCommon.IconSizes.Icon24:
-                    _iconSz = 26;
-                    break;
-                case MyCommon.IconSizes.Icon48:
-                    _iconSz = 48;
-                    break;
-                case MyCommon.IconSizes.Icon48_2:
-                    _iconSz = 48;
-                    _iconCol = true;
-                    break;
-            }
-            if (_iconSz == 0)
-            {
-                tw.GetIcon = false;
-            }
-            else
-            {
-                tw.GetIcon = true;
-                tw.IconSize = _iconSz;
-            }
-            tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
+            ApplyListViewIconSize(SettingDialog.IconSz);
 
-            //発言詳細部アイコンをリストアイコンにサイズ変更
-            int sz = _iconSz;
-            if (_iconSz == 0)
-            {
-                sz = 16;
-            }
+            tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
 
             StatusLabel.Text = Properties.Resources.Form1_LoadText1;       //画面右下の状態表示を変更
             StatusLabelUrl.Text = "";            //画面左下のリンク先URL表示部を初期化
@@ -1106,55 +1139,59 @@ namespace OpenTween
             //デフォルトタブの存在チェック、ない場合には追加
             if (_statuses.GetTabByType(MyCommon.TabUsageType.Home) == null)
             {
-                if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.RECENT))
+                TabClass tab;
+                if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.RECENT, out tab))
                 {
                     _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
                 }
                 else
                 {
-                    _statuses.Tabs[MyCommon.DEFAULTTAB.RECENT].TabType = MyCommon.TabUsageType.Home;
+                    tab.TabType = MyCommon.TabUsageType.Home;
                 }
             }
             if (_statuses.GetTabByType(MyCommon.TabUsageType.Mentions) == null)
             {
-                if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.REPLY))
+                TabClass tab;
+                if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.REPLY, out tab))
                 {
                     _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
                 }
                 else
                 {
-                    _statuses.Tabs[MyCommon.DEFAULTTAB.REPLY].TabType = MyCommon.TabUsageType.Mentions;
+                    tab.TabType = MyCommon.TabUsageType.Mentions;
                 }
             }
             if (_statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage) == null)
             {
-                if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.DM))
+                TabClass tab;
+                if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.DM, out tab))
                 {
                     _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
                 }
                 else
                 {
-                    _statuses.Tabs[MyCommon.DEFAULTTAB.DM].TabType = MyCommon.TabUsageType.DirectMessage;
+                    tab.TabType = MyCommon.TabUsageType.DirectMessage;
                 }
             }
             if (_statuses.GetTabByType(MyCommon.TabUsageType.Favorites) == null)
             {
-                if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.FAV))
+                TabClass tab;
+                if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.FAV, out tab))
                 {
                     _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
                 }
                 else
                 {
-                    _statuses.Tabs[MyCommon.DEFAULTTAB.FAV].TabType = MyCommon.TabUsageType.Favorites;
+                    tab.TabType = MyCommon.TabUsageType.Favorites;
                 }
             }
-            foreach (string tn in _statuses.Tabs.Keys)
+            foreach (var tab in _statuses.Tabs.Values)
             {
-                if (_statuses.Tabs[tn].TabType == MyCommon.TabUsageType.Undefined)
+                if (tab.TabType == MyCommon.TabUsageType.Undefined)
                 {
-                    _statuses.Tabs[tn].TabType = MyCommon.TabUsageType.UserDefined;
+                    tab.TabType = MyCommon.TabUsageType.UserDefined;
                 }
-                if (!AddNewTab(tn, true, _statuses.Tabs[tn].TabType, _statuses.Tabs[tn].ListInfo)) throw new Exception(Properties.Resources.TweenMain_LoadText1);
+                if (!AddNewTab(tab.TabName, true, tab.TabType, tab.ListInfo)) throw new Exception(Properties.Resources.TweenMain_LoadText1);
             }
 
             this.JumpReadOpMenuItem.ShortcutKeyDisplayString = "Space";
@@ -1218,18 +1255,27 @@ namespace OpenTween
             SetTabAlignment();
         }
 
-        private void CreatePictureServices()
+        private void InitDetailHtmlFormat()
         {
-            if (this.pictureService != null) this.pictureService.Clear();
-            this.pictureService = null;
-            this.pictureService = new Dictionary<string, IMultimediaShareService> {
-                {"TwitPic", new TwitPic(tw)},
-                {"img.ly", new imgly(tw)},
-                {"yfrog", new yfrog(tw)},
-                {"Twitter", new TwitterPhoto(tw)},
-                {"ついっぷるフォト", new TwipplePhoto(tw)},
-                {"Imgur", new Imgur(tw)},
-            };
+            if (SettingDialog.IsMonospace)
+            {
+                detailHtmlFormatHeader = detailHtmlFormatMono1;
+                detailHtmlFormatFooter = detailHtmlFormatMono7;
+            }
+            else
+            {
+                detailHtmlFormatHeader = detailHtmlFormat1;
+                detailHtmlFormatFooter = detailHtmlFormat7;
+            }
+            detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
+            if (SettingDialog.IsMonospace)
+            {
+                detailHtmlFormatHeader += detailHtmlFormatMono6;
+            }
+            else
+            {
+                detailHtmlFormatHeader += detailHtmlFormat6;
+            }
         }
 
         private void ListTab_DrawItem(object sender, DrawItemEventArgs e)
@@ -1382,7 +1428,6 @@ namespace OpenTween
                 doGetFollowersMenu();
                 GetTimeline(MyCommon.WORKERTYPE.NoRetweetIds, 0, 0, "");
                 GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
-                if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
             }
             if (osResumed)
             {
@@ -1399,7 +1444,6 @@ namespace OpenTween
                     GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");
                     doGetFollowersMenu();
                     GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
-                    if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
                 }
             }
         }
@@ -1414,7 +1458,7 @@ namespace OpenTween
 
             //現在の選択状態を退避
             Dictionary<string, long[]> selId = new Dictionary<string, long[]>();
-            Dictionary<string, long> focusedId = new Dictionary<string, long>();
+            Dictionary<string, long[]> focusedId = new Dictionary<string, long[]>();
             SaveSelectedStatus(selId, focusedId);
 
             //mentionsの更新前件数を保持
@@ -1437,26 +1481,27 @@ namespace OpenTween
                 {
                     DetailsListView lst = (DetailsListView)tab.Tag;
                     TabClass tabInfo = _statuses.Tabs[tab.Text];
-                    lst.BeginUpdate();
-                    if (isDelete || lst.VirtualListSize != tabInfo.AllCount)
+                    using (ControlTransaction.Update(lst))
                     {
-                        if (lst.Equals(_curList))
-                        {
-                            this.PurgeListViewItemCache();
-                        }
-                        try
-                        {
-                            lst.VirtualListSize = tabInfo.AllCount; //リスト件数更新
-                        }
-                        catch (Exception)
+                        if (isDelete || lst.VirtualListSize != tabInfo.AllCount)
                         {
-                            //アイコン描画不具合あり?
+                            if (lst.Equals(_curList))
+                            {
+                                this.PurgeListViewItemCache();
+                            }
+                            try
+                            {
+                                lst.VirtualListSize = tabInfo.AllCount; //リスト件数更新
+                            }
+                            catch (Exception)
+                            {
+                                //アイコン描画不具合あり?
+                            }
+                            this.SelectListItem(lst,
+                                                _statuses.IndexOf(tab.Text, selId[tab.Text]),
+                                                _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
                         }
-                        this.SelectListItem(lst,
-                                          _statuses.IndexOf(tab.Text, selId[tab.Text]),
-                                          _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
                     }
-                    lst.EndUpdate();
                     if (tabInfo.UnreadCount > 0)
                         if (SettingDialog.TabIconDisp)
                             if (tab.ImageIndex == -1) tab.ImageIndex = 0; //タブアイコン
@@ -1543,8 +1588,8 @@ namespace OpenTween
                             //最下行が表示されていたら、最下行へ強制スクロール。最下行が表示されていなかったら制御しない
                             ListViewItem _item;
                             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);   //一番下
-                            if (_item == null) _item = _curList.Items[_curList.Items.Count - 1];
-                            if (_item.Index == _curList.Items.Count - 1)
+                            if (_item == null) _item = _curList.Items[_curList.VirtualListSize - 1];
+                            if (_item.Index == _curList.VirtualListSize - 1)
                             {
                                 smode = -2;
                             }
@@ -1598,7 +1643,7 @@ namespace OpenTween
             return topId;
         }
 
-        private void SaveSelectedStatus(Dictionary<string, long[]> selId, Dictionary<string, long> focusedId)
+        private void SaveSelectedStatus(Dictionary<string, long[]> selId, Dictionary<string, long[]> focusedId)
         {
             if (MyCommon._endingFlag) return;
             foreach (TabPage tab in ListTab.TabPages)
@@ -1612,10 +1657,13 @@ namespace OpenTween
                 {
                     selId.Add(tab.Text, new long[1] {-2});
                 }
-                if (lst.FocusedItem != null)
-                    focusedId.Add(tab.Text, _statuses.GetId(tab.Text, lst.FocusedItem.Index));
-                else
-                    focusedId.Add(tab.Text, -2);
+
+                var fIds = new long[2];  // 0 = focus, 1 = selection mark
+                var item = lst.FocusedItem;
+                fIds[0] = (item != null) ? _statuses.GetId(tab.Text, item.Index) : -2;
+                var mIdx = lst.SelectionMark;
+                fIds[1] = (mIdx > -1) ? _statuses.GetId(tab.Text, mIdx) : -2;
+                focusedId.Add(tab.Text, fIds);
             }
 
         }
@@ -1897,13 +1945,13 @@ namespace OpenTween
 
             if (SettingDialog.UnreadManage) _statuses.SetReadAllTab(true, _curTab.Text, _curItemIndex);
             //キャッシュの書き換え
-            ChangeCacheStyleRead(true, _curItemIndex, _curTab);   //既読へ(フォント、文字色)
+            ChangeCacheStyleRead(true, _curItemIndex);   //既読へ(フォント、文字色)
 
             ColorizeList();
             _colorize = true;
         }
 
-        private void ChangeCacheStyleRead(bool Read, int Index, TabPage Tab)
+        private void ChangeCacheStyleRead(bool Read, int Index)
         {
             //Read:true=既読 false=未読
             //未読管理していなかったら既読として扱う
@@ -1914,18 +1962,15 @@ namespace OpenTween
             ListViewItem itm = null;
             PostClass post = null;
 
-            if (Tab.Equals(this._curTab))
-            {
-                this.TryGetListViewItemCache(Index, out itm, out post);
-            }
+            this.TryGetListViewItemCache(Index, out itm, out post);
 
             if (itm == null || post == null)
             {
-                itm = ((DetailsListView)Tab.Tag).Items[Index];
-                post = _statuses[Tab.Text, Index];
+                itm = ((DetailsListView)_curTab.Tag).Items[Index];
+                post = _statuses[_curTab.Text, Index];
             }
 
-            ChangeItemStyleRead(Read, itm, post, ((DetailsListView)Tab.Tag));
+            ChangeItemStyleRead(Read, itm, post, ((DetailsListView)_curTab.Tag));
         }
 
         private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView DList)
@@ -2059,11 +2104,11 @@ namespace OpenTween
             return cl;
         }
 
-        private void PostButton_Click(object sender, EventArgs e)
+        private async void PostButton_Click(object sender, EventArgs e)
         {
             if (StatusText.Text.Trim().Length == 0)
             {
-                if (!ImageSelectionPanel.Enabled)
+                if (!ImageSelector.Enabled)
                 {
                     DoRefresh();
                     return;
@@ -2087,12 +2132,12 @@ namespace OpenTween
                 }
             }
 
-            _history[_history.Count - 1] = new PostingStatus(StatusText.Text.Trim(), _reply_to_id, _reply_to_name);
+            _history[_history.Count - 1] = new PostingStatus(StatusText.Text, _reply_to_id, _reply_to_name);
 
             if (SettingDialog.Nicoms)
             {
                 StatusText.SelectionStart = StatusText.Text.Length;
-                UrlConvert(MyCommon.UrlConverter.Nicoms);
+                await UrlConvertAsync(MyCommon.UrlConverter.Nicoms);
             }
             //if (SettingDialog.UrlConvertAuto)
             //{
@@ -2201,7 +2246,7 @@ namespace OpenTween
                         footer += " " + SettingDialog.Status.Trim();
                 }
             }
-            args.status.status = header + StatusText.Text.Trim() + footer;
+            args.status.status = header + StatusText.Text + footer;
 
             if (ToolStripMenuItemApiCommandEvasion.Checked)
             {
@@ -2243,55 +2288,15 @@ namespace OpenTween
 
             args.status.inReplyToId = _reply_to_id;
             args.status.inReplyToName = _reply_to_name;
-            if (ImageSelectionPanel.Visible)
+            if (ImageSelector.Visible)
             {
                 //画像投稿
-                if (ImageSelectedPicture.Image != ImageSelectedPicture.InitialImage &&
-                    ImageServiceCombo.SelectedIndex > -1 &&
-                    !string.IsNullOrEmpty(ImagefilePathText.Text))
-                {
-                    if (MessageBox.Show(Properties.Resources.PostPictureConfirm1,
-                                       Properties.Resources.PostPictureConfirm2,
-                                       MessageBoxButtons.OKCancel,
-                                       MessageBoxIcon.Question,
-                                       MessageBoxDefaultButton.Button1)
-                                   == DialogResult.Cancel)
-                    {
-                        TimelinePanel.Visible = true;
-                        TimelinePanel.Enabled = true;
-                        ImageSelectionPanel.Visible = false;
-                        ImageSelectionPanel.Enabled = false;
-                        if (_curList != null)
-                            _curList.Focus();
-                        return;
-                    }
-                    args.status.imageService = ImageServiceCombo.Text;
-                    args.status.imagePath = ImagefilePathText.Text;
-                    ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                    ImagefilePathText.Text = "";
-                    TimelinePanel.Visible = true;
-                    TimelinePanel.Enabled = true;
-                    ImageSelectionPanel.Visible = false;
-                    ImageSelectionPanel.Enabled = false;
-                    if (_curList != null)
-                        _curList.Focus();
-                }
-                else
-                {
-                    MessageBox.Show(Properties.Resources.PostPictureWarn1, Properties.Resources.PostPictureWarn2);
+                if (!ImageSelector.TryGetSelectedMedia(out args.status.imageService, out args.status.imagePath))
                     return;
-                }
             }
 
             RunAsync(args);
 
-            //Google検索(試験実装)
-            if (StatusText.Text.StartsWith("Google:", StringComparison.OrdinalIgnoreCase) && StatusText.Text.Trim().Length > 7)
-            {
-                string tmp = string.Format(Properties.Resources.SearchItem2Url, Uri.EscapeUriString(StatusText.Text.Substring(7)));
-                OpenUriAsync(tmp);
-            }
-
             _reply_to_id = null;
             _reply_to_name = null;
             StatusText.Text = "";
@@ -2301,6 +2306,13 @@ namespace OpenTween
                 ((Control)ListTab.SelectedTab.Tag).Focus();
             urlUndoBuffer = null;
             UrlUndoToolStripMenuItem.Enabled = false;  //Undoをできないように設定
+
+            //Google検索(試験実装)
+            if (StatusText.Text.StartsWith("Google:", StringComparison.OrdinalIgnoreCase) && StatusText.Text.Trim().Length > 7)
+            {
+                string tmp = string.Format(Properties.Resources.SearchItem2Url, Uri.EscapeUriString(StatusText.Text.Substring(7)));
+                await this.OpenUriAsync(tmp);
+            }
         }
 
         private void EndToolStripMenuItem_Click(object sender, EventArgs e)
@@ -2319,7 +2331,6 @@ namespace OpenTween
             }
             else
             {
-                //Google.GASender.GetInstance().TrackEventWithCategory("post", "end", tw.UserId);
                 _hookGlobalHotkey.UnregisterAllOriginalHotkey();
                 _ignoreConfigSave = true;
                 MyCommon._endingFlag = true;
@@ -2408,18 +2419,16 @@ namespace OpenTween
                     if (string.IsNullOrEmpty(ret)) ret = tw.GetDirectMessageApi(read, MyCommon.WORKERTYPE.DirectMessegeSnt, args.page == -1);
                     rslt.addCount = _statuses.DistributePosts();
                     break;
+
                 case MyCommon.WORKERTYPE.FavAdd:
+                {
                     //スレッド処理はしない
-                    if (_statuses.Tabs.ContainsKey(args.tName))
+                    TabClass tab;
+                    if (_statuses.Tabs.TryGetValue(args.tName, out tab))
                     {
-                        TabClass tbc = _statuses.Tabs[args.tName];
                         for (int i = 0; i <= args.ids.Count - 1; i++)
                         {
-                            PostClass post = null;
-                            if (tbc.IsInnerStorageTabType)
-                                post = tbc.Posts[args.ids[i]];
-                            else
-                                post = _statuses[args.ids[i]];
+                            var post = tab.Posts[args.ids[i]];
 
                             args.page = i + 1;
                             bw.ReportProgress(50, MakeStatusMessage(args, false));
@@ -2461,18 +2470,17 @@ namespace OpenTween
                     }
                     rslt.sIds = args.sIds;
                     break;
+                }
+
                 case MyCommon.WORKERTYPE.FavRemove:
+                {
                     //スレッド処理はしない
-                    if (_statuses.Tabs.ContainsKey(args.tName))
+                    TabClass tab;
+                    if (_statuses.Tabs.TryGetValue(args.tName, out tab))
                     {
-                        TabClass tbc = _statuses.Tabs[args.tName];
                         for (int i = 0; i <= args.ids.Count - 1; i++)
                         {
-                            PostClass post = null;
-                            if (tbc.IsInnerStorageTabType)
-                                post = tbc.Posts[args.ids[i]];
-                            else
-                                post = _statuses[args.ids[i]];
+                            var post = tab.Posts[args.ids[i]];
 
                             args.page = i + 1;
                             bw.ReportProgress(50, MakeStatusMessage(args, false));
@@ -2499,17 +2507,26 @@ namespace OpenTween
                     }
                     rslt.sIds = args.sIds;
                     break;
+                }
+
                 case MyCommon.WORKERTYPE.PostMessage:
                     bw.ReportProgress(200);
-                    if (string.IsNullOrEmpty(args.status.imagePath))
+                    if (args.status.imagePath == null || args.status.imagePath.Length == 0 || string.IsNullOrEmpty(args.status.imagePath[0]))
                     {
                         ret = tw.PostStatus(args.status.status, args.status.inReplyToId);
                     }
                     else
                     {
-                        ret = this.pictureService[args.status.imageService].Upload(ref args.status.imagePath,
-                                                                                   ref args.status.status,
-                                                                                   args.status.inReplyToId);
+                        var service = ImageSelector.GetService(args.status.imageService);
+                        try
+                        {
+                            service.PostStatusAsync(args.status.status, args.status.inReplyToId, args.status.imagePath)
+                                .Wait();
+                        }
+                        catch (AggregateException ex)
+                        {
+                            ret = ex.InnerException.Message;
+                        }
                     }
                     bw.ReportProgress(300);
                     rslt.status = args.status;
@@ -2620,12 +2637,16 @@ namespace OpenTween
                     //振り分け
                     rslt.addCount = _statuses.DistributePosts();
                     break;
+
                 case MyCommon.WORKERTYPE.Related:
+                {
                     bw.ReportProgress(50, MakeStatusMessage(args, false));
                     TabClass tab = _statuses.GetTabByName(args.tName);
                     ret = tw.GetRelatedResult(read, tab);
                     rslt.addCount = _statuses.DistributePosts();
                     break;
+                }
+
                 case MyCommon.WORKERTYPE.BlockIds:
                     bw.ReportProgress(50, Properties.Resources.UpdateBlockUserText1);
                     try
@@ -2908,40 +2929,41 @@ namespace OpenTween
                 case MyCommon.WORKERTYPE.FavRemove:
                     if (_curList != null && _curTab != null)
                     {
-                        _curList.BeginUpdate();
-                        if (rslt.type == MyCommon.WORKERTYPE.FavRemove && _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.Favorites)
-                        {
-                            //色変えは不要
-                        }
-                        else
+                        using (ControlTransaction.Update(this._curList))
                         {
-                            for (int i = 0; i <= rslt.sIds.Count - 1; i++)
+                            if (rslt.type == MyCommon.WORKERTYPE.FavRemove && _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.Favorites)
                             {
-                                if (_curTab.Text.Equals(rslt.tName))
+                                //色変えは不要
+                            }
+                            else
+                            {
+                                for (int i = 0; i <= rslt.sIds.Count - 1; i++)
                                 {
-                                    int idx = _statuses.Tabs[rslt.tName].IndexOf(rslt.sIds[i]);
-                                    if (idx > -1)
+                                    if (_curTab.Text.Equals(rslt.tName))
                                     {
-                                        PostClass post = null;
-                                        TabClass tb = _statuses.Tabs[rslt.tName];
-                                        if (tb != null)
+                                        int idx = _statuses.Tabs[rslt.tName].IndexOf(rslt.sIds[i]);
+                                        if (idx > -1)
                                         {
-                                            if (tb.TabType == MyCommon.TabUsageType.Lists || tb.TabType == MyCommon.TabUsageType.PublicSearch)
+                                            PostClass post = null;
+                                            TabClass tb = _statuses.Tabs[rslt.tName];
+                                            if (tb != null)
                                             {
-                                                post = tb.Posts[rslt.sIds[i]];
+                                                if (tb.TabType == MyCommon.TabUsageType.Lists || tb.TabType == MyCommon.TabUsageType.PublicSearch)
+                                                {
+                                                    post = tb.Posts[rslt.sIds[i]];
+                                                }
+                                                else
+                                                {
+                                                    post = _statuses[rslt.sIds[i]];
+                                                }
+                                                ChangeCacheStyleRead(post.IsRead, idx);
                                             }
-                                            else
-                                            {
-                                                post = _statuses[rslt.sIds[i]];
-                                            }
-                                            ChangeCacheStyleRead(post.IsRead, idx, _curTab);
+                                            if (idx == _curItemIndex) DispSelectedPost(true); //選択アイテム再表示
                                         }
-                                        if (idx == _curItemIndex) DispSelectedPost(true); //選択アイテム再表示
                                     }
                                 }
                             }
                         }
-                        _curList.EndUpdate();
                     }
                     break;
                 case MyCommon.WORKERTYPE.PostMessage:
@@ -3041,7 +3063,10 @@ namespace OpenTween
                     //_waitFollower = false
                     if (SettingDialog.TwitterConfiguration.PhotoSizeLimit != 0)
                     {
-                        pictureService["Twitter"].Configuration("MaxUploadFilesize", SettingDialog.TwitterConfiguration.PhotoSizeLimit);
+                        foreach (var service in this.ImageSelector.GetServices())
+                        {
+                            service.UpdateTwitterConfiguration(this.SettingDialog.TwitterConfiguration);
+                        }
                     }
                     this.PurgeListViewItemCache();
                     if (_curList != null) _curList.Refresh();
@@ -3073,6 +3098,23 @@ namespace OpenTween
             }
         }
 
+        private async Task RefreshMuteUserIdsAsync()
+        {
+            this.StatusLabel.Text = Properties.Resources.UpdateMuteUserIds_Start;
+
+            try
+            {
+                await tw.RefreshMuteUserIdsAsync();
+            }
+            catch (WebApiException ex)
+            {
+                this.StatusLabel.Text = string.Format(Properties.Resources.UpdateMuteUserIds_Error, ex.Message);
+                return;
+            }
+
+            this.StatusLabel.Text = Properties.Resources.UpdateMuteUserIds_Finish;
+        }
+
         private void RemovePostFromFavTab(Int64[] ids)
         {
             string favTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).TabName;
@@ -3697,20 +3739,21 @@ namespace OpenTween
 
         private void ReadedStripMenuItem_Click(object sender, EventArgs e)
         {
-            _curList.BeginUpdate();
-            if (SettingDialog.UnreadManage)
+            using (ControlTransaction.Update(this._curList))
             {
+                if (SettingDialog.UnreadManage)
+                {
+                    foreach (int idx in _curList.SelectedIndices)
+                    {
+                        _statuses.SetReadAllTab(true, _curTab.Text, idx);
+                    }
+                }
                 foreach (int idx in _curList.SelectedIndices)
                 {
-                    _statuses.SetReadAllTab(true, _curTab.Text, idx);
+                    ChangeCacheStyleRead(true, idx);
                 }
+                ColorizeList();
             }
-            foreach (int idx in _curList.SelectedIndices)
-            {
-                ChangeCacheStyleRead(true, idx, _curTab);
-            }
-            ColorizeList();
-            _curList.EndUpdate();
             foreach (TabPage tb in ListTab.TabPages)
             {
                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
@@ -3726,20 +3769,21 @@ namespace OpenTween
 
         private void UnreadStripMenuItem_Click(object sender, EventArgs e)
         {
-            _curList.BeginUpdate();
-            if (SettingDialog.UnreadManage)
+            using (ControlTransaction.Update(this._curList))
             {
+                if (SettingDialog.UnreadManage)
+                {
+                    foreach (int idx in _curList.SelectedIndices)
+                    {
+                        _statuses.SetReadAllTab(false, _curTab.Text, idx);
+                    }
+                }
                 foreach (int idx in _curList.SelectedIndices)
                 {
-                    _statuses.SetReadAllTab(false, _curTab.Text, idx);
+                    ChangeCacheStyleRead(false, idx);
                 }
+                ColorizeList();
             }
-            foreach (int idx in _curList.SelectedIndices)
-            {
-                ChangeCacheStyleRead(false, idx, _curTab);
-            }
-            ColorizeList();
-            _curList.EndUpdate();
             foreach (TabPage tb in ListTab.TabPages)
             {
                 if (_statuses.Tabs[tb.Text].UnreadCount > 0)
@@ -3850,6 +3894,7 @@ namespace OpenTween
         {
             DialogResult result;
             string uid = tw.Username.ToLower();
+            var oldIconSz = SettingDialog.IconSz;
 
             try
             {
@@ -3867,9 +3912,9 @@ namespace OpenTween
                     tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
                     tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
                     tw.ReadOwnPost = SettingDialog.ReadOwnPost;
-                    ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
-                    ShortUrl.BitlyId = SettingDialog.BitlyUser;
-                    ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
+                    ShortUrl.Instance.DisableExpanding = !SettingDialog.TinyUrlResolve;
+                    ShortUrl.Instance.BitlyId = SettingDialog.BitlyUser;
+                    ShortUrl.Instance.BitlyKey = SettingDialog.BitlyPwd;
                     HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
 
                     HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
@@ -3878,12 +3923,9 @@ namespace OpenTween
                                                         SettingDialog.ProxyPort,
                                                         SettingDialog.ProxyUser,
                                                         SettingDialog.ProxyPassword);
-                    this.CreatePictureServices();
-    #if UA
-                    this.SplitContainer4.Panel2.Controls.RemoveAt(0);
-                    this.ab = new AdsBrowser();
-                    this.SplitContainer4.Panel2.Controls.Add(ab);
-    #endif
+
+                    ImageSelector.Reset(tw, SettingDialog.TwitterConfiguration);
+
                     try
                     {
                         if (SettingDialog.TabIconDisp)
@@ -3934,24 +3976,15 @@ namespace OpenTween
                         throw;
                     }
 
-                    try
-                    {
-                        foreach (TabPage mytab in ListTab.TabPages)
-                        {
-                            DetailsListView lst = (DetailsListView)mytab.Tag;
-                            lst.GridLines = SettingDialog.ShowGrid;
-                        }
-                    }
-                    catch (Exception ex)
-                    {
-                        ex.Data["Instance"] = "ListTab(ShowGrid)";
-                        ex.Data["IsTerminatePermission"] = false;
-                        throw;
-                    }
-
                     // タブの表示位置の決定
                     SetTabAlignment();
 
+                    SplitContainer1.IsPanelInverted = !SettingDialog.StatusAreaAtBottom;
+
+                    var imgazyobizinet = ThumbnailGenerator.ImgAzyobuziNetInstance;
+                    imgazyobizinet.Enabled = this.SettingDialog.EnableImgAzyobuziNet;
+                    imgazyobizinet.DisabledInDM = this.SettingDialog.ImgAzyobuziNetDisabledInDM;
+
                     PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
                     this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
                     _fntUnread = SettingDialog.FontUnread;
@@ -3975,17 +4008,6 @@ namespace OpenTween
                     _clInputBackcolor = SettingDialog.ColorInputBackcolor;
                     _clInputFont = SettingDialog.ColorInputFont;
                     _fntInputFont = SettingDialog.FontInputFont;
-                    try
-                    {
-                        if (StatusText.Focused) StatusText.BackColor = _clInputBackcolor;
-                        StatusText.Font = _fntInputFont;
-                        StatusText.ForeColor = _clInputFont;
-                    }
-                    catch (Exception ex)
-                    {
-                        MessageBox.Show(ex.Message);
-                    }
-
                     _brsBackColorMine.Dispose();
                     _brsBackColorAt.Dispose();
                     _brsBackColorYou.Dispose();
@@ -4000,27 +4022,21 @@ namespace OpenTween
                     _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
                     _brsBackColorAtTo = new SolidBrush(_clAtTo);
                     _brsBackColorNone = new SolidBrush(_clListBackcolor);
+
                     try
                     {
-                        if (SettingDialog.IsMonospace)
-                        {
-                            detailHtmlFormatHeader = detailHtmlFormatMono1;
-                            detailHtmlFormatFooter = detailHtmlFormatMono7;
-                        }
-                        else
-                        {
-                            detailHtmlFormatHeader = detailHtmlFormat1;
-                            detailHtmlFormatFooter = detailHtmlFormat7;
-                        }
-                        detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
-                        if (SettingDialog.IsMonospace)
-                        {
-                            detailHtmlFormatHeader += detailHtmlFormatMono6;
-                        }
-                        else
-                        {
-                            detailHtmlFormatHeader += detailHtmlFormat6;
-                        }
+                        if (StatusText.Focused) StatusText.BackColor = _clInputBackcolor;
+                        StatusText.Font = _fntInputFont;
+                        StatusText.ForeColor = _clInputFont;
+                    }
+                    catch (Exception ex)
+                    {
+                        MessageBox.Show(ex.Message);
+                    }
+
+                    try
+                    {
+                        InitDetailHtmlFormat();
                     }
                     catch (Exception ex)
                     {
@@ -4028,6 +4044,7 @@ namespace OpenTween
                         ex.Data["IsTerminatePermission"] = false;
                         throw;
                     }
+
                     try
                     {
                         _statuses.SetUnreadManage(SettingDialog.UnreadManage);
@@ -4050,19 +4067,44 @@ namespace OpenTween
                                 else
                                     tb.ImageIndex = 0;
                             }
-                            if (tb.Tag != null && tb.Controls.Count > 0)
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        ex.Data["Instance"] = "ListTab(TabIconDisp no2)";
+                        ex.Data["IsTerminatePermission"] = false;
+                        throw;
+                    }
+
+                    try
+                    {
+                        var oldIconCol = _iconCol;
+
+                        if (SettingDialog.IconSz != oldIconSz)
+                            ApplyListViewIconSize(SettingDialog.IconSz);
+
+                        foreach (TabPage tp in ListTab.TabPages)
+                        {
+                            DetailsListView lst = (DetailsListView)tp.Tag;
+
+                            using (ControlTransaction.Update(lst))
                             {
-                                ((DetailsListView)tb.Tag).Font = _fntReaded;
-                                ((DetailsListView)tb.Tag).BackColor = _clListBackcolor;
+                                lst.GridLines = SettingDialog.ShowGrid;
+                                lst.Font = _fntReaded;
+                                lst.BackColor = _clListBackcolor;
+
+                                if (_iconCol != oldIconCol)
+                                    ResetColumns(lst);
                             }
                         }
                     }
                     catch (Exception ex)
                     {
-                        ex.Data["Instance"] = "ListTab(TabIconDisp no2)";
+                        ex.Data["Instance"] = "ListView(IconSize)";
                         ex.Data["IsTerminatePermission"] = false;
                         throw;
                     }
+
                     SetMainWindowTitle();
                     SetNotifyIconText();
 
@@ -4085,7 +4127,6 @@ namespace OpenTween
 
                     if (uid != tw.Username) this.doGetFollowersMenu();
 
-                    SetImageServiceCombo();
                     if (SettingDialog.IsNotifyUseGrowl) gh.RegisterGrowl();
                     try
                     {
@@ -4108,7 +4149,89 @@ namespace OpenTween
         /// </summary>
         private void SetTabAlignment()
         {
-            ListTab.Alignment = (SettingDialog.ViewTabBottom ? TabAlignment.Bottom : TabAlignment.Top);
+            var newAlignment = SettingDialog.ViewTabBottom ? TabAlignment.Bottom : TabAlignment.Top;
+            if (ListTab.Alignment == newAlignment) return;
+
+            //現在の選択状態を退避
+            Dictionary<string, long[]> selId = new Dictionary<string, long[]>();
+            Dictionary<string, long[]> focusedId = new Dictionary<string, long[]>();
+            SaveSelectedStatus(selId, focusedId);
+
+            ListTab.Alignment = newAlignment;
+
+            //選択状態を復帰
+            foreach (TabPage tab in ListTab.TabPages)
+            {
+                DetailsListView lst = (DetailsListView)tab.Tag;
+                using (ControlTransaction.Update(lst))
+                {
+                    this.SelectListItem(lst,
+                                        _statuses.IndexOf(tab.Text, selId[tab.Text]),
+                                        _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
+                }
+            }
+        }
+
+        private void ApplyListViewIconSize(MyCommon.IconSizes iconSz)
+        {
+            // アイコンサイズの再設定
+            _iconCol = false;
+            switch (iconSz)
+            {
+                case MyCommon.IconSizes.IconNone:
+                    _iconSz = 0;
+                    break;
+                case MyCommon.IconSizes.Icon16:
+                    _iconSz = 16;
+                    break;
+                case MyCommon.IconSizes.Icon24:
+                    _iconSz = 26;
+                    break;
+                case MyCommon.IconSizes.Icon48:
+                    _iconSz = 48;
+                    break;
+                case MyCommon.IconSizes.Icon48_2:
+                    _iconSz = 48;
+                    _iconCol = true;
+                    break;
+            }
+
+            if (_iconSz > 0)
+            {
+                // ディスプレイの DPI 設定を考慮したサイズを設定する
+                _listViewImageList.ImageSize = new Size(
+                    1,
+                    (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Height));
+            }
+            else
+            {
+                _listViewImageList.ImageSize = new Size(1, 1);
+            }
+        }
+
+        private void ResetColumns(DetailsListView list)
+        {
+            using (ControlTransaction.Update(list))
+            using (ControlTransaction.Layout(list, false))
+            {
+                // カラムヘッダの再設定
+                list.ColumnClick -= MyList_ColumnClick;
+                list.DrawColumnHeader -= MyList_DrawColumnHeader;
+                list.ColumnReordered -= MyList_ColumnReordered;
+                list.ColumnWidthChanged -= MyList_ColumnWidthChanged;
+
+                var cols = list.Columns.Cast<ColumnHeader>().ToList();
+                list.Columns.Clear();
+                cols.ForEach(col => col.Dispose());
+                cols.Clear();
+
+                InitColumns(list, true);
+
+                list.ColumnClick += MyList_ColumnClick;
+                list.DrawColumnHeader += MyList_DrawColumnHeader;
+                list.ColumnReordered += MyList_ColumnReordered;
+                list.ColumnWidthChanged += MyList_ColumnWidthChanged;
+            }
         }
 
         private void PostBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
@@ -4291,307 +4414,188 @@ namespace OpenTween
 
             TabPage _tabPage = new TabPage();
             DetailsListView _listCustom = new DetailsListView();
-            ColumnHeader _colHd1 = new ColumnHeader();  //アイコン
-            ColumnHeader _colHd2 = new ColumnHeader();   //ニックネーム
-            ColumnHeader _colHd3 = new ColumnHeader();   //本文
-            ColumnHeader _colHd4 = new ColumnHeader();   //日付
-            ColumnHeader _colHd5 = new ColumnHeader();   //ユーザID
-            ColumnHeader _colHd6 = new ColumnHeader();   //未読
-            ColumnHeader _colHd7 = new ColumnHeader();   //マーク&プロテクト
-            ColumnHeader _colHd8 = new ColumnHeader();   //ソース
 
             int cnt = ListTab.TabPages.Count;
 
             ///ToDo:Create and set controls follow tabtypes
 
-            this.SplitContainer1.Panel1.SuspendLayout();
-            this.SplitContainer1.Panel2.SuspendLayout();
-            this.SplitContainer1.SuspendLayout();
-            this.ListTab.SuspendLayout();
-            this.SuspendLayout();
-
-            _tabPage.SuspendLayout();
-
-            /// UserTimeline関連
-            Label label = null;
-            if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
-            {
-                label = new Label();
-                label.Dock = DockStyle.Top;
-                label.Name = "labelUser";
-                if (tabType == MyCommon.TabUsageType.Lists)
-                {
-                    label.Text = listInfo.ToString();
-                }
-                else
-                {
-                    label.Text = _statuses.Tabs[tabName].User + "'s Timeline";
-                }
-                label.TextAlign = ContentAlignment.MiddleLeft;
-                using (ComboBox tmpComboBox = new ComboBox())
-                {
-                    label.Height = tmpComboBox.Height;
-                }
-                _tabPage.Controls.Add(label);
-            }
-
-            /// 検索関連の準備
-            Panel pnl = null;
-            if (tabType == MyCommon.TabUsageType.PublicSearch)
-            {
-                pnl = new Panel();
-
-                Label lbl = new Label();
-                ComboBox cmb = new ComboBox();
-                Button btn = new Button();
-                ComboBox cmbLang = new ComboBox();
-
-                pnl.SuspendLayout();
-
-                pnl.Controls.Add(cmb);
-                pnl.Controls.Add(cmbLang);
-                pnl.Controls.Add(btn);
-                pnl.Controls.Add(lbl);
-                pnl.Name = "panelSearch";
-                pnl.Dock = DockStyle.Top;
-                pnl.Height = cmb.Height;
-                pnl.Enter += SearchControls_Enter;
-                pnl.Leave += SearchControls_Leave;
-
-                cmb.Text = "";
-                cmb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
-                cmb.Dock = DockStyle.Fill;
-                cmb.Name = "comboSearch";
-                cmb.DropDownStyle = ComboBoxStyle.DropDown;
-                cmb.ImeMode = ImeMode.NoControl;
-                cmb.TabStop = false;
-                cmb.AutoCompleteMode = AutoCompleteMode.None;
-                cmb.KeyDown += SearchComboBox_KeyDown;
-
-                if (_statuses.ContainsTab(tabName))
-                {
-                    cmb.Items.Add(_statuses.Tabs[tabName].SearchWords);
-                    cmb.Text = _statuses.Tabs[tabName].SearchWords;
-                }
-
-                cmbLang.Text = "";
-                cmbLang.Anchor = AnchorStyles.Left | AnchorStyles.Right;
-                cmbLang.Dock = DockStyle.Right;
-                cmbLang.Width = 50;
-                cmbLang.Name = "comboLang";
-                cmbLang.DropDownStyle = ComboBoxStyle.DropDownList;
-                cmbLang.TabStop = false;
-                cmbLang.Items.Add("");
-                cmbLang.Items.Add("ja");
-                cmbLang.Items.Add("en");
-                cmbLang.Items.Add("ar");
-                cmbLang.Items.Add("da");
-                cmbLang.Items.Add("nl");
-                cmbLang.Items.Add("fa");
-                cmbLang.Items.Add("fi");
-                cmbLang.Items.Add("fr");
-                cmbLang.Items.Add("de");
-                cmbLang.Items.Add("hu");
-                cmbLang.Items.Add("is");
-                cmbLang.Items.Add("it");
-                cmbLang.Items.Add("no");
-                cmbLang.Items.Add("pl");
-                cmbLang.Items.Add("pt");
-                cmbLang.Items.Add("ru");
-                cmbLang.Items.Add("es");
-                cmbLang.Items.Add("sv");
-                cmbLang.Items.Add("th");
-                if (_statuses.ContainsTab(tabName)) cmbLang.Text = _statuses.Tabs[tabName].SearchLang;
-            
-                lbl.Text = "Search(C-S-f)";
-                lbl.Name = "label1";
-                lbl.Dock = DockStyle.Left;
-                lbl.Width = 90;
-                lbl.Height = cmb.Height;
-                lbl.TextAlign = ContentAlignment.MiddleLeft;
-
-                btn.Text = "Search";
-                btn.Name = "buttonSearch";
-                btn.UseVisualStyleBackColor = true;
-                btn.Dock = DockStyle.Right;
-                btn.TabStop = false;
-                btn.Click += SearchButton_Click;
-            }
-
-            this.ListTab.Controls.Add(_tabPage);
-            _tabPage.Controls.Add(_listCustom);
-
-            if (tabType == MyCommon.TabUsageType.PublicSearch) _tabPage.Controls.Add(pnl);
-            if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists) _tabPage.Controls.Add(label);
-
-            _tabPage.Location = new Point(4, 4);
-            _tabPage.Name = "CTab" + cnt.ToString();
-            _tabPage.Size = new Size(380, 260);
-            _tabPage.TabIndex = 2 + cnt;
-            _tabPage.Text = tabName;
-            _tabPage.UseVisualStyleBackColor = true;
-
-            _listCustom.AllowColumnReorder = true;
-            if (!_iconCol)
-            {
-                _listCustom.Columns.AddRange(new ColumnHeader[] {_colHd1, _colHd2, _colHd3, _colHd4, _colHd5, _colHd6, _colHd7, _colHd8});
-            }
-            else
-            {
-                _listCustom.Columns.AddRange(new ColumnHeader[] {_colHd1, _colHd3});
-            }
-            _listCustom.ContextMenuStrip = this.ContextMenuOperate;
-            _listCustom.Dock = DockStyle.Fill;
-            _listCustom.FullRowSelect = true;
-            _listCustom.HideSelection = false;
-            _listCustom.Location = new Point(0, 0);
-            _listCustom.Margin = new Padding(0);
-            _listCustom.Name = "CList" + Environment.TickCount.ToString();
-            _listCustom.ShowItemToolTips = true;
-            _listCustom.Size = new Size(380, 260);
-            _listCustom.UseCompatibleStateImageBehavior = false;
-            _listCustom.View = View.Details;
-            _listCustom.OwnerDraw = true;
-            _listCustom.VirtualMode = true;
-            _listCustom.Font = _fntReaded;
-            _listCustom.BackColor = _clListBackcolor;
-
-            _listCustom.GridLines = SettingDialog.ShowGrid;
-            _listCustom.AllowDrop = true;
-
-            _listCustom.SelectedIndexChanged += MyList_SelectedIndexChanged;
-            _listCustom.MouseDoubleClick += MyList_MouseDoubleClick;
-            _listCustom.ColumnClick += MyList_ColumnClick;
-            _listCustom.DrawColumnHeader += MyList_DrawColumnHeader;
-            _listCustom.DragDrop += TweenMain_DragDrop;
-            _listCustom.DragOver += TweenMain_DragOver;
-            _listCustom.DrawItem += MyList_DrawItem;
-            _listCustom.MouseClick += MyList_MouseClick;
-            _listCustom.ColumnReordered += MyList_ColumnReordered;
-            _listCustom.ColumnWidthChanged += MyList_ColumnWidthChanged;
-            _listCustom.CacheVirtualItems += MyList_CacheVirtualItems;
-            _listCustom.RetrieveVirtualItem += MyList_RetrieveVirtualItem;
-            _listCustom.DrawSubItem += MyList_DrawSubItem;
-            _listCustom.HScrolled += MyList_HScrolled;
-
-            InitColumnText();
-            _colHd1.Text = ColumnText[0];
-            _colHd1.Width = 48;
-            _colHd2.Text = ColumnText[1];
-            _colHd2.Width = 80;
-            _colHd3.Text = ColumnText[2];
-            _colHd3.Width = 300;
-            _colHd4.Text = ColumnText[3];
-            _colHd4.Width = 50;
-            _colHd5.Text = ColumnText[4];
-            _colHd5.Width = 50;
-            _colHd6.Text = ColumnText[5];
-            _colHd6.Width = 16;
-            _colHd7.Text = ColumnText[6];
-            _colHd7.Width = 16;
-            _colHd8.Text = ColumnText[7];
-            _colHd8.Width = 50;
-
-            _listCustom.SmallImageList = new ImageList();
-            if (_iconSz > 0)
+            using (ControlTransaction.Update(_listCustom))
+            using (ControlTransaction.Layout(this.SplitContainer1.Panel1, false))
+            using (ControlTransaction.Layout(this.SplitContainer1.Panel2, false))
+            using (ControlTransaction.Layout(this.SplitContainer1, false))
+            using (ControlTransaction.Layout(this.ListTab, false))
+            using (ControlTransaction.Layout(this))
+            using (ControlTransaction.Layout(_tabPage, false))
             {
-                // ディスプレイの DPI 設定を考慮したサイズを設定する
-                _listCustom.SmallImageList.ImageSize = new Size(
-                    (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Width),
-                    (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Height));
-            }
-            else
-            {
-                _listCustom.SmallImageList.ImageSize = new Size(1, 1);
-            }
-
-            int[] dispOrder = new int[8];
-            if (!startup)
-            {
-                for (int i = 0; i < _curList.Columns.Count; i++)
-                {
-                    for (int j = 0; j < _curList.Columns.Count; j++)
-                    {
-                        if (_curList.Columns[j].DisplayIndex == i)
-                        {
-                            dispOrder[i] = j;
-                            break;
-                        }
-                    }
-                }
-                for (int i = 0; i < _curList.Columns.Count; i++)
-                {
-                    _listCustom.Columns[i].Width = _curList.Columns[i].Width;
-                    _listCustom.Columns[dispOrder[i]].DisplayIndex = i;
-                }
-            }
-            else
-            {
-                if (_iconCol)
+                /// UserTimeline関連
+                Label label = null;
+                if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
                 {
-                    _listCustom.Columns[0].Width = _cfgLocal.Width1;
-                    _listCustom.Columns[1].Width = _cfgLocal.Width3;
-                    _listCustom.Columns[0].DisplayIndex = 0;
-                    _listCustom.Columns[1].DisplayIndex = 1;
-                }
-                else
-                {
-                    for (int i = 0; i <= 7; i++)
+                    label = new Label();
+                    label.Dock = DockStyle.Top;
+                    label.Name = "labelUser";
+                    if (tabType == MyCommon.TabUsageType.Lists)
                     {
-                        if (_cfgLocal.DisplayIndex1 == i)
-                            dispOrder[i] = 0;
-                        else if (_cfgLocal.DisplayIndex2 == i)
-                            dispOrder[i] = 1;
-                        else if (_cfgLocal.DisplayIndex3 == i)
-                            dispOrder[i] = 2;
-                        else if (_cfgLocal.DisplayIndex4 == i)
-                            dispOrder[i] = 3;
-                        else if (_cfgLocal.DisplayIndex5 == i)
-                            dispOrder[i] = 4;
-                        else if (_cfgLocal.DisplayIndex6 == i)
-                            dispOrder[i] = 5;
-                        else if (_cfgLocal.DisplayIndex7 == i)
-                            dispOrder[i] = 6;
-                        else if (_cfgLocal.DisplayIndex8 == i)
-                            dispOrder[i] = 7;
+                        label.Text = listInfo.ToString();
                     }
-                    _listCustom.Columns[0].Width = _cfgLocal.Width1;
-                    _listCustom.Columns[1].Width = _cfgLocal.Width2;
-                    _listCustom.Columns[2].Width = _cfgLocal.Width3;
-                    _listCustom.Columns[3].Width = _cfgLocal.Width4;
-                    _listCustom.Columns[4].Width = _cfgLocal.Width5;
-                    _listCustom.Columns[5].Width = _cfgLocal.Width6;
-                    _listCustom.Columns[6].Width = _cfgLocal.Width7;
-                    _listCustom.Columns[7].Width = _cfgLocal.Width8;
-                    for (int i = 0; i <= 7; i++)
+                    else
                     {
-                        _listCustom.Columns[dispOrder[i]].DisplayIndex = i;
-                    }
-                }
+                        label.Text = _statuses.Tabs[tabName].User + "'s Timeline";
+                    }
+                    label.TextAlign = ContentAlignment.MiddleLeft;
+                    using (ComboBox tmpComboBox = new ComboBox())
+                    {
+                        label.Height = tmpComboBox.Height;
+                    }
+                    _tabPage.Controls.Add(label);
+                }
+
+                /// 検索関連の準備
+                Panel pnl = null;
+                if (tabType == MyCommon.TabUsageType.PublicSearch)
+                {
+                    pnl = new Panel();
+
+                    Label lbl = new Label();
+                    ComboBox cmb = new ComboBox();
+                    Button btn = new Button();
+                    ComboBox cmbLang = new ComboBox();
+
+                    pnl.SuspendLayout();
+
+                    pnl.Controls.Add(cmb);
+                    pnl.Controls.Add(cmbLang);
+                    pnl.Controls.Add(btn);
+                    pnl.Controls.Add(lbl);
+                    pnl.Name = "panelSearch";
+                    pnl.Dock = DockStyle.Top;
+                    pnl.Height = cmb.Height;
+                    pnl.Enter += SearchControls_Enter;
+                    pnl.Leave += SearchControls_Leave;
+
+                    cmb.Text = "";
+                    cmb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
+                    cmb.Dock = DockStyle.Fill;
+                    cmb.Name = "comboSearch";
+                    cmb.DropDownStyle = ComboBoxStyle.DropDown;
+                    cmb.ImeMode = ImeMode.NoControl;
+                    cmb.TabStop = false;
+                    cmb.AutoCompleteMode = AutoCompleteMode.None;
+                    cmb.KeyDown += SearchComboBox_KeyDown;
+
+                    if (_statuses.ContainsTab(tabName))
+                    {
+                        cmb.Items.Add(_statuses.Tabs[tabName].SearchWords);
+                        cmb.Text = _statuses.Tabs[tabName].SearchWords;
+                    }
+
+                    cmbLang.Text = "";
+                    cmbLang.Anchor = AnchorStyles.Left | AnchorStyles.Right;
+                    cmbLang.Dock = DockStyle.Right;
+                    cmbLang.Width = 50;
+                    cmbLang.Name = "comboLang";
+                    cmbLang.DropDownStyle = ComboBoxStyle.DropDownList;
+                    cmbLang.TabStop = false;
+                    cmbLang.Items.Add("");
+                    cmbLang.Items.Add("ja");
+                    cmbLang.Items.Add("en");
+                    cmbLang.Items.Add("ar");
+                    cmbLang.Items.Add("da");
+                    cmbLang.Items.Add("nl");
+                    cmbLang.Items.Add("fa");
+                    cmbLang.Items.Add("fi");
+                    cmbLang.Items.Add("fr");
+                    cmbLang.Items.Add("de");
+                    cmbLang.Items.Add("hu");
+                    cmbLang.Items.Add("is");
+                    cmbLang.Items.Add("it");
+                    cmbLang.Items.Add("no");
+                    cmbLang.Items.Add("pl");
+                    cmbLang.Items.Add("pt");
+                    cmbLang.Items.Add("ru");
+                    cmbLang.Items.Add("es");
+                    cmbLang.Items.Add("sv");
+                    cmbLang.Items.Add("th");
+                    if (_statuses.ContainsTab(tabName)) cmbLang.Text = _statuses.Tabs[tabName].SearchLang;
+
+                    lbl.Text = "Search(C-S-f)";
+                    lbl.Name = "label1";
+                    lbl.Dock = DockStyle.Left;
+                    lbl.Width = 90;
+                    lbl.Height = cmb.Height;
+                    lbl.TextAlign = ContentAlignment.MiddleLeft;
+
+                    btn.Text = "Search";
+                    btn.Name = "buttonSearch";
+                    btn.UseVisualStyleBackColor = true;
+                    btn.Dock = DockStyle.Right;
+                    btn.TabStop = false;
+                    btn.Click += SearchButton_Click;
+                }
+
+                this.ListTab.Controls.Add(_tabPage);
+                _tabPage.Controls.Add(_listCustom);
+
+                if (tabType == MyCommon.TabUsageType.PublicSearch) _tabPage.Controls.Add(pnl);
+                if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists) _tabPage.Controls.Add(label);
+
+                _tabPage.Location = new Point(4, 4);
+                _tabPage.Name = "CTab" + cnt.ToString();
+                _tabPage.Size = new Size(380, 260);
+                _tabPage.TabIndex = 2 + cnt;
+                _tabPage.Text = tabName;
+                _tabPage.UseVisualStyleBackColor = true;
+
+                _listCustom.AllowColumnReorder = true;
+                _listCustom.ContextMenuStrip = this.ContextMenuOperate;
+                _listCustom.ColumnHeaderContextMenuStrip = this.ContextMenuColumnHeader;
+                _listCustom.Dock = DockStyle.Fill;
+                _listCustom.FullRowSelect = true;
+                _listCustom.HideSelection = false;
+                _listCustom.Location = new Point(0, 0);
+                _listCustom.Margin = new Padding(0);
+                _listCustom.Name = "CList" + Environment.TickCount.ToString();
+                _listCustom.ShowItemToolTips = true;
+                _listCustom.Size = new Size(380, 260);
+                _listCustom.UseCompatibleStateImageBehavior = false;
+                _listCustom.View = View.Details;
+                _listCustom.OwnerDraw = true;
+                _listCustom.VirtualMode = true;
+                _listCustom.Font = _fntReaded;
+                _listCustom.BackColor = _clListBackcolor;
+
+                _listCustom.GridLines = SettingDialog.ShowGrid;
+                _listCustom.AllowDrop = true;
+
+                _listCustom.SmallImageList = _listViewImageList;
+
+                InitColumns(_listCustom, startup);
+
+                _listCustom.SelectedIndexChanged += MyList_SelectedIndexChanged;
+                _listCustom.MouseDoubleClick += MyList_MouseDoubleClick;
+                _listCustom.ColumnClick += MyList_ColumnClick;
+                _listCustom.DrawColumnHeader += MyList_DrawColumnHeader;
+                _listCustom.DragDrop += TweenMain_DragDrop;
+                _listCustom.DragEnter += TweenMain_DragEnter;
+                _listCustom.DragOver += TweenMain_DragOver;
+                _listCustom.DrawItem += MyList_DrawItem;
+                _listCustom.MouseClick += MyList_MouseClick;
+                _listCustom.ColumnReordered += MyList_ColumnReordered;
+                _listCustom.ColumnWidthChanged += MyList_ColumnWidthChanged;
+                _listCustom.CacheVirtualItems += MyList_CacheVirtualItems;
+                _listCustom.RetrieveVirtualItem += MyList_RetrieveVirtualItem;
+                _listCustom.DrawSubItem += MyList_DrawSubItem;
+                _listCustom.HScrolled += MyList_HScrolled;
+
+                if (tabType == MyCommon.TabUsageType.PublicSearch) pnl.ResumeLayout(false);
             }
 
-            if (tabType == MyCommon.TabUsageType.PublicSearch) pnl.ResumeLayout(false);
-        
-            _tabPage.ResumeLayout(false);
-
-            this.SplitContainer1.Panel1.ResumeLayout(false);
-            this.SplitContainer1.Panel2.ResumeLayout(false);
-            this.SplitContainer1.ResumeLayout(false);
-            this.ListTab.ResumeLayout(false);
-            this.ResumeLayout(false);
-            this.PerformLayout();
             _tabPage.Tag = _listCustom;
             return true;
         }
 
         public bool RemoveSpecifiedTab(string TabName, bool confirm)
         {
-            int idx = 0;
-            for (idx = 0; idx < ListTab.TabPages.Count; idx++)
-            {
-                if (ListTab.TabPages[idx].Text == TabName) break;
-            }
-
             if (_statuses.IsDefaultTab(TabName) || _statuses.Tabs[TabName].Protected) return false;
 
             if (confirm)
@@ -4604,87 +4608,103 @@ namespace OpenTween
                 }
             }
 
+            var _tabPage = ListTab.TabPages.Cast<TabPage>().FirstOrDefault<TabPage>(tp => tp.Text == TabName);
+            if (_tabPage == null) return false;
+
             SetListProperty();   //他のタブに列幅等を反映
 
             MyCommon.TabUsageType tabType = _statuses.Tabs[TabName].TabType;
 
             //オブジェクトインスタンスの削除
-            this.SplitContainer1.Panel1.SuspendLayout();
-            this.SplitContainer1.Panel2.SuspendLayout();
-            this.SplitContainer1.SuspendLayout();
-            this.ListTab.SuspendLayout();
-            this.SuspendLayout();
-
-            TabPage _tabPage = ListTab.TabPages[idx];
             DetailsListView _listCustom = (DetailsListView)_tabPage.Tag;
             _tabPage.Tag = null;
 
-            _tabPage.SuspendLayout();
-
-            if (this.ListTab.SelectedTab == this.ListTab.TabPages[idx])
+            using (ControlTransaction.Layout(this.SplitContainer1.Panel1, false))
+            using (ControlTransaction.Layout(this.SplitContainer1.Panel2, false))
+            using (ControlTransaction.Layout(this.SplitContainer1, false))
+            using (ControlTransaction.Layout(this.ListTab, false))
+            using (ControlTransaction.Layout(this))
+            using (ControlTransaction.Layout(_tabPage, false))
             {
-                this.ListTab.SelectTab((this._beforeSelectedTab != null && this.ListTab.TabPages.Contains(this._beforeSelectedTab)) ? this._beforeSelectedTab : this.ListTab.TabPages[0]);
-            }
-            this.ListTab.Controls.Remove(_tabPage);
+                if (this.ListTab.SelectedTab == _tabPage)
+                {
+                    this.ListTab.SelectTab((this._beforeSelectedTab != null && this.ListTab.TabPages.Contains(this._beforeSelectedTab)) ? this._beforeSelectedTab : this.ListTab.TabPages[0]);
+                    this._beforeSelectedTab = null;
+                }
+                this.ListTab.Controls.Remove(_tabPage);
 
-            Control pnl = null;
-            if (tabType == MyCommon.TabUsageType.PublicSearch)
-            {
-                pnl = _tabPage.Controls["panelSearch"];
-                foreach (Control ctrl in pnl.Controls)
+                // 後付けのコントロールを破棄
+                if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
                 {
-                    if (ctrl.Name == "buttonSearch")
+                    using (Control label = _tabPage.Controls["labelUser"])
                     {
-                        ctrl.Click -= SearchButton_Click;
+                        _tabPage.Controls.Remove(label);
                     }
-                    ctrl.Enter -= SearchControls_Enter;
-                    ctrl.Leave -= SearchControls_Leave;
-                    pnl.Controls.Remove(ctrl);
-                    ctrl.Dispose();
                 }
-                _tabPage.Controls.Remove(pnl);
-            }
+                else if (tabType == MyCommon.TabUsageType.PublicSearch)
+                {
+                    using (Control pnl = _tabPage.Controls["panelSearch"])
+                    {
+                        pnl.Enter -= SearchControls_Enter;
+                        pnl.Leave -= SearchControls_Leave;
+                        _tabPage.Controls.Remove(pnl);
 
-            _tabPage.Controls.Remove(_listCustom);
-            _listCustom.Columns.Clear();
-            _listCustom.ContextMenuStrip = null;
+                        foreach (Control ctrl in pnl.Controls)
+                        {
+                            if (ctrl.Name == "buttonSearch")
+                            {
+                                ctrl.Click -= SearchButton_Click;
+                            }
+                            else if (ctrl.Name == "comboSearch")
+                            {
+                                ctrl.KeyDown -= SearchComboBox_KeyDown;
+                            }
+                            pnl.Controls.Remove(ctrl);
+                            ctrl.Dispose();
+                        }
+                    }
+                }
 
-            _listCustom.SelectedIndexChanged -= MyList_SelectedIndexChanged;
-            _listCustom.MouseDoubleClick -= MyList_MouseDoubleClick;
-            _listCustom.ColumnClick -= MyList_ColumnClick;
-            _listCustom.DrawColumnHeader -= MyList_DrawColumnHeader;
-            _listCustom.DragDrop -= TweenMain_DragDrop;
-            _listCustom.DragOver -= TweenMain_DragOver;
-            _listCustom.DrawItem -= MyList_DrawItem;
-            _listCustom.MouseClick -= MyList_MouseClick;
-            _listCustom.ColumnReordered -= MyList_ColumnReordered;
-            _listCustom.ColumnWidthChanged -= MyList_ColumnWidthChanged;
-            _listCustom.CacheVirtualItems -= MyList_CacheVirtualItems;
-            _listCustom.RetrieveVirtualItem -= MyList_RetrieveVirtualItem;
-            _listCustom.DrawSubItem -= MyList_DrawSubItem;
-            _listCustom.HScrolled -= MyList_HScrolled;
+                _tabPage.Controls.Remove(_listCustom);
 
-            _listCustom.SmallImageList = null;
-            _listCustom.ListViewItemSorter = null;
+                _listCustom.SelectedIndexChanged -= MyList_SelectedIndexChanged;
+                _listCustom.MouseDoubleClick -= MyList_MouseDoubleClick;
+                _listCustom.ColumnClick -= MyList_ColumnClick;
+                _listCustom.DrawColumnHeader -= MyList_DrawColumnHeader;
+                _listCustom.DragDrop -= TweenMain_DragDrop;
+                _listCustom.DragEnter -= TweenMain_DragEnter;
+                _listCustom.DragOver -= TweenMain_DragOver;
+                _listCustom.DrawItem -= MyList_DrawItem;
+                _listCustom.MouseClick -= MyList_MouseClick;
+                _listCustom.ColumnReordered -= MyList_ColumnReordered;
+                _listCustom.ColumnWidthChanged -= MyList_ColumnWidthChanged;
+                _listCustom.CacheVirtualItems -= MyList_CacheVirtualItems;
+                _listCustom.RetrieveVirtualItem -= MyList_RetrieveVirtualItem;
+                _listCustom.DrawSubItem -= MyList_DrawSubItem;
+                _listCustom.HScrolled -= MyList_HScrolled;
 
-            //キャッシュのクリア
-            if (_curTab.Equals(_tabPage))
-            {
-                _curTab = null;
-                _curItemIndex = -1;
-                _curList = null;
-                _curPost = null;
-            }
-            this.PurgeListViewItemCache();
+                var cols = _listCustom.Columns.Cast<ColumnHeader>().ToList<ColumnHeader>();
+                _listCustom.Columns.Clear();
+                cols.ForEach(col => col.Dispose());
+                cols.Clear();
 
-            _tabPage.ResumeLayout(false);
+                _listCustom.ContextMenuStrip = null;
+                _listCustom.ColumnHeaderContextMenuStrip = null;
+                _listCustom.Font = null;
 
-            this.SplitContainer1.Panel1.ResumeLayout(false);
-            this.SplitContainer1.Panel2.ResumeLayout(false);
-            this.SplitContainer1.ResumeLayout(false);
-            this.ListTab.ResumeLayout(false);
-            this.ResumeLayout(false);
-            this.PerformLayout();
+                _listCustom.SmallImageList = null;
+                _listCustom.ListViewItemSorter = null;
+
+                //キャッシュのクリア
+                if (_curTab.Equals(_tabPage))
+                {
+                    _curTab = null;
+                    _curItemIndex = -1;
+                    _curList = null;
+                    _curPost = null;
+                }
+                this.PurgeListViewItemCache();
+            }
 
             _tabPage.Dispose();
             _listCustom.Dispose();
@@ -4693,9 +4713,10 @@ namespace OpenTween
             foreach (TabPage tp in ListTab.TabPages)
             {
                 DetailsListView lst = (DetailsListView)tp.Tag;
-                if (lst.VirtualListSize != _statuses.Tabs[tp.Text].AllCount)
+                var count = _statuses.Tabs[tp.Text].AllCount;
+                if (lst.VirtualListSize != count)
                 {
-                    lst.VirtualListSize = _statuses.Tabs[tp.Text].AllCount;
+                    lst.VirtualListSize = count;
                 }
             }
 
@@ -5024,7 +5045,7 @@ namespace OpenTween
                 //    pLen += m.Result("${url}").Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
                 //}
             }
-            if (ImageSelectionPanel.Visible && ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
+            if (ImageSelector.Visible && !string.IsNullOrEmpty(ImageSelector.ServiceName))
             {
                 pLen -= SettingDialog.TwitterConfiguration.CharactersReservedPerMedia;
             }
@@ -5054,34 +5075,34 @@ namespace OpenTween
             finally { this.itemCacheLock.ExitUpgradeableReadLock(); }
         }
 
-        private void MyList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
+        private async void MyList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
         {
-            ListViewItem cacheItem = null;
+            ListViewItem item = null;
             PostClass cacheItemPost = null;
 
-            this.TryGetListViewItemCache(e.ItemIndex, out cacheItem, out cacheItemPost);
+            if (_curList.Equals(sender))
+                this.TryGetListViewItemCache(e.ItemIndex, out item, out cacheItemPost);
 
-            if (cacheItem != null)
-            {
-                e.Item = cacheItem;
-            }
-            else
+            if (item == null)
             {
                 //A cache miss, so create a new ListViewItem and pass it back.
                 TabPage tb = (TabPage)((DetailsListView)sender).Parent;
                 try
                 {
-                    e.Item = CreateItem(tb,
-                                        _statuses[tb.Text, e.ItemIndex],
-                                        e.ItemIndex);
+                    item = this.CreateItem(tb, _statuses[tb.Text, e.ItemIndex], e.ItemIndex);
                 }
                 catch (Exception)
                 {
                     //不正な要求に対する間に合わせの応答
                     string[] sitem = {"", "", "", "", "", "", "", ""};
-                    e.Item = new ImageListViewItem(sitem);
+                    item = new ImageListViewItem(sitem);
                 }
             }
+
+            // e.Item に値をセットする前に await しないこと
+            e.Item = item;
+
+            await ((ImageListViewItem)item).GetImageAsync();
         }
 
         private void CreateCache(int StartIndex, int EndIndex)
@@ -5192,6 +5213,45 @@ namespace OpenTween
             return itm;
         }
 
+        /// <summary>
+        /// 全てのタブの振り分けルールを反映し直します
+        /// </summary>
+        private void ApplyPostFilters()
+        {
+            try
+            {
+                this.Cursor = Cursors.WaitCursor;
+
+                this.PurgeListViewItemCache();
+                this._curPost = null;
+                this._curItemIndex = -1;
+                this._statuses.FilterAll();
+
+                foreach (TabPage tabPage in this.ListTab.TabPages)
+                {
+                    var tab = this._statuses.Tabs[tabPage.Text];
+
+                    var listview = (DetailsListView)tabPage.Tag;
+                    listview.VirtualListSize = tab.AllCount;
+
+                    if (this.SettingDialog.TabIconDisp)
+                    {
+                        if (tab.UnreadCount > 0)
+                            tabPage.ImageIndex = 0;
+                        else
+                            tabPage.ImageIndex = -1;
+                    }
+                }
+
+                if (!this.SettingDialog.TabIconDisp)
+                    this.ListTab.Refresh();
+            }
+            finally
+            {
+                this.Cursor = Cursors.Default;
+            }
+        }
+
         private void MyList_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
         {
             e.DrawDefault = true;
@@ -5207,10 +5267,10 @@ namespace OpenTween
         {
             if (e.State == 0) return;
             e.DrawDefault = false;
+
+            SolidBrush brs2 = null;
             if (!e.Item.Selected)     //e.ItemStateでうまく判定できない???
             {
-                SolidBrush brs2 = null;
-
                 if (e.Item.BackColor == _clSelf)
                     brs2 = _brsBackColorMine;
                 else if (e.Item.BackColor == _clAtSelf)
@@ -5225,18 +5285,17 @@ namespace OpenTween
                     brs2 = _brsBackColorAtTo;
                 else
                     brs2 = _brsBackColorNone;
-
-                e.Graphics.FillRectangle(brs2, e.Bounds);
             }
             else
             {
                 //選択中の行
                 if (((Control)sender).Focused)
-                    e.Graphics.FillRectangle(_brsHighLight, e.Bounds);
+                    brs2 = _brsHighLight;
                 else
-                    e.Graphics.FillRectangle(_brsDeactiveSelection, e.Bounds);
+                    brs2 = _brsDeactiveSelection;
             }
-            if ((e.State & ListViewItemStates.Focused) == ListViewItemStates.Focused) e.DrawFocusRectangle();
+            e.Graphics.FillRectangle(brs2, e.Bounds);
+            e.DrawFocusRectangle();
             this.DrawListViewItemIcon(e);
         }
 
@@ -5249,18 +5308,19 @@ namespace OpenTween
                 //アイコン以外の列
                 RectangleF rct = e.Bounds;
                 rct.Width = e.Header.Width;
+                int fontHeight = e.Item.Font.Height;
                 if (_iconCol)
                 {
-                    rct.Y += e.Item.Font.Height;
-                    rct.Height -= e.Item.Font.Height;
+                    rct.Y += fontHeight;
+                    rct.Height -= fontHeight;
                 }
 
                 int heightDiff;
-                int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, e.Item.Font.Height, out heightDiff));
+                int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, fontHeight, out heightDiff));
 
-                //if (heightDiff > e.Item.Font.Height * 0.7)
+                //if (heightDiff > fontHeight * 0.7)
                 //{
-                //    rct.Height += e.Item.Font.Height;
+                //    rct.Height += fontHeight;
                 //    drawLineCount += 1;
                 //}
 
@@ -5268,13 +5328,13 @@ namespace OpenTween
                 if (!_iconCol && drawLineCount <= 1)
                 {
                     //rct.Inflate(0, heightDiff / -2);
-                    //rct.Height += e.Item.Font.Height / 2;
+                    //rct.Height += fontHeight / 2;
                 }
-                else if (heightDiff < e.Item.Font.Height * 0.7)
+                else if (heightDiff < fontHeight * 0.7)
                 {
                     //最終行が70%以上欠けていたら、最終行は表示しない
-                    //rct.Height = (float)((e.Item.Font.Height * drawLineCount) + (e.Item.Font.Height / 2));
-                    rct.Height = (e.Item.Font.Height * drawLineCount) - 1;
+                    //rct.Height = (float)((fontHeight * drawLineCount) + (fontHeight / 2));
+                    rct.Height = (fontHeight * drawLineCount) - 1;
                 }
                 else
                 {
@@ -5283,8 +5343,8 @@ namespace OpenTween
 
                 //if (!_iconCol && drawLineCount > 1)
                 //{
-                //    rct.Y += e.Item.Font.Height * 0.2;
-                //    if (heightDiff >= e.Item.Font.Height * 0.8) rct.Height -= e.Item.Font.Height * 0.2;
+                //    rct.Y += fontHeight * 0.2;
+                //    if (heightDiff >= fontHeight * 0.8) rct.Height -= fontHeight * 0.2;
                 //}
 
                 if (rct.Width > 0)
@@ -5295,9 +5355,9 @@ namespace OpenTween
 
                     if (_iconCol)
                     {
-                        RectangleF rctB = e.Bounds;
+                        Rectangle rctB = e.Bounds;
                         rctB.Width = e.Header.Width;
-                        rctB.Height = e.Item.Font.Height;
+                        rctB.Height = fontHeight;
 
                         using (Font fnt = new Font(e.Item.Font, FontStyle.Bold))
                         {
@@ -5313,7 +5373,7 @@ namespace OpenTween
                             TextRenderer.DrawText(e.Graphics,
                                                     e.Item.SubItems[4].Text + " / " + e.Item.SubItems[1].Text + " (" + e.Item.SubItems[3].Text + ") " + e.Item.SubItems[5].Text + e.Item.SubItems[6].Text + " [" + e.Item.SubItems[7].Text + "]",
                                                     fnt,
-                                                    Rectangle.Round(rctB),
+                                                    rctB,
                                                     color,
                                                     TextFormatFlags.SingleLine |
                                                     TextFormatFlags.EndEllipsis |
@@ -5353,16 +5413,22 @@ namespace OpenTween
 
         private void DrawListViewItemIcon(DrawListViewItemEventArgs e)
         {
+            if (_iconSz == 0) return;
+
             ImageListViewItem item = (ImageListViewItem)e.Item;
 
             //e.Bounds.Leftが常に0を指すから自前で計算
             Rectangle itemRect = item.Bounds;
-            itemRect.Width = e.Item.ListView.Columns[0].Width;
+            var col0 = e.Item.ListView.Columns[0];
+            itemRect.Width = col0.Width;
 
-            foreach (ColumnHeader clm in e.Item.ListView.Columns)
+            if (col0.DisplayIndex > 0)
             {
-                if (clm.DisplayIndex < e.Item.ListView.Columns[0].DisplayIndex)
-                    itemRect.X += clm.Width;
+                foreach (ColumnHeader clm in e.Item.ListView.Columns)
+                {
+                    if (clm.DisplayIndex < col0.DisplayIndex)
+                        itemRect.X += clm.Width;
+                }
             }
 
             // ディスプレイの DPI 設定を考慮したアイコンサイズ
@@ -5370,37 +5436,35 @@ namespace OpenTween
             var realStateSize = new SizeF(16 * this.currentScaleFactor.Width, 16 * this.currentScaleFactor.Height).ToSize();
 
             Rectangle iconRect;
-            Rectangle stateRect;
-            if (item.Image != null)
+            var img = item.Image;
+            if (img != null)
             {
                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, realIconSize), itemRect);
                 iconRect.Offset(0, Math.Max(0, (itemRect.Height - realIconSize.Height) / 2));
-                stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + iconRect.Width + 2, iconRect.Y), realStateSize), itemRect);
+
+                if (iconRect.Width > 0)
+                {
+                    e.Graphics.FillRectangle(Brushes.White, iconRect);
+                    e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
+                    try
+                    {
+                        e.Graphics.DrawImage(img.Image, iconRect);
+                    }
+                    catch (ArgumentException)
+                    {
+                        item.RefreshImageAsync();
+                    }
+                }
             }
             else
             {
                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(1, 1)), itemRect);
                 //iconRect.Offset(0, Math.Max(0, (itemRect.Height - realIconSize.Height) / 2));
-                stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + iconRect.Width + 2, iconRect.Y), realStateSize), itemRect);
-            }
-
-            var img = item.Image;
-            if (img != null && iconRect.Width > 0)
-            {
-                e.Graphics.FillRectangle(Brushes.White, iconRect);
-                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
-                try
-                {
-                    e.Graphics.DrawImage(img.Image, iconRect);
-                }
-                catch (ArgumentException)
-                {
-                    item.RefreshImage();
-                }
             }
 
             if (item.StateImageIndex > -1)
             {
+                Rectangle stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + realIconSize.Width + 2, iconRect.Y), realStateSize), itemRect);
                 if (stateRect.Width > 0)
                 {
                     //e.Graphics.FillRectangle(Brushes.White, stateRect);
@@ -5587,7 +5651,7 @@ namespace OpenTween
                             break;
                         case SEARCHTYPE.PrevSearch:
                             toIdx = cidx;
-                            cidx = _curList.Items.Count - 1;
+                            cidx = _curList.VirtualListSize - 1;
                             break;
                     }
                     fnd = true;
@@ -5602,69 +5666,113 @@ namespace OpenTween
 
         private void MenuItemSubSearch_Click(object sender, EventArgs e)
         {
-            //検索メニュー
-            SearchDialog.Owner = this;
-            if (SearchDialog.ShowDialog() == DialogResult.Cancel)
+            // 検索メニュー
+            this.ShowSearchDialog();
+        }
+
+        private void MenuItemSearchNext_Click(object sender, EventArgs e)
+        {
+            var previousSearch = this.SearchDialog.ResultOptions;
+            if (previousSearch == null || previousSearch.Type != SearchWordDialog.SearchType.Timeline)
             {
-                this.TopMost = SettingDialog.AlwaysTop;
+                this.SearchDialog.Reset();
+                this.ShowSearchDialog();
                 return;
             }
-            this.TopMost = SettingDialog.AlwaysTop;
 
-            if (!string.IsNullOrEmpty(SearchDialog.SWord))
+            // 次を検索
+            this.DoTabSearch(
+                previousSearch.Query,
+                previousSearch.CaseSensitive,
+                previousSearch.UseRegex,
+                SEARCHTYPE.NextSearch);
+        }
+
+        private void MenuItemSearchPrev_Click(object sender, EventArgs e)
+        {
+            var previousSearch = this.SearchDialog.ResultOptions;
+            if (previousSearch == null || previousSearch.Type != SearchWordDialog.SearchType.Timeline)
+            {
+                this.SearchDialog.Reset();
+                this.ShowSearchDialog();
+                return;
+            }
+
+            // 前を検索
+            this.DoTabSearch(
+                previousSearch.Query,
+                previousSearch.CaseSensitive,
+                previousSearch.UseRegex,
+                SEARCHTYPE.PrevSearch);
+        }
+
+        /// <summary>
+        /// 検索ダイアログを表示し、検索を実行します
+        /// </summary>
+        private void ShowSearchDialog()
+        {
+            // Recentタブの検索時以外では「新規タブに表示」ボタンを無効化する
+            if (this._statuses.Tabs[this._curTab.Text].TabType == MyCommon.TabUsageType.Home)
+                this.SearchDialog.DisableNewTabButton = false;
+            else
+                this.SearchDialog.DisableNewTabButton = true;
+
+            if (this.SearchDialog.ShowDialog(this) != DialogResult.OK)
             {
-                DoTabSearch(SearchDialog.SWord,
-                            SearchDialog.CheckCaseSensitive,
-                            SearchDialog.CheckRegex,
-                            SEARCHTYPE.DialogSearch);
+                this.TopMost = this.SettingDialog.AlwaysTop;
+                return;
             }
-        }
+            this.TopMost = this.SettingDialog.AlwaysTop;
 
-        private void MenuItemSearchNext_Click(object sender, EventArgs e)
-        {
-            //次を検索
-            if (string.IsNullOrEmpty(SearchDialog.SWord))
+            var searchOptions = this.SearchDialog.ResultOptions;
+            if (searchOptions.Type == SearchWordDialog.SearchType.Timeline)
             {
-                if (SearchDialog.ShowDialog() == DialogResult.Cancel)
+                if (searchOptions.NewTab)
                 {
-                    this.TopMost = SettingDialog.AlwaysTop;
-                    return;
-                }
-                this.TopMost = SettingDialog.AlwaysTop;
-                if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
+                    var tabName = searchOptions.Query;
 
-                DoTabSearch(SearchDialog.SWord,
-                            SearchDialog.CheckCaseSensitive,
-                            SearchDialog.CheckRegex,
-                            SEARCHTYPE.DialogSearch);
-            }
-            else
-            {
-                DoTabSearch(SearchDialog.SWord,
-                            SearchDialog.CheckCaseSensitive,
-                            SearchDialog.CheckRegex,
-                            SEARCHTYPE.NextSearch);
-            }
-        }
+                    try
+                    {
+                        tabName = this._statuses.MakeTabName(tabName);
+                    }
+                    catch (TabException ex)
+                    {
+                        MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                    }
 
-        private void MenuItemSearchPrev_Click(object sender, EventArgs e)
-        {
-            //前を検索
-            if (string.IsNullOrEmpty(SearchDialog.SWord))
-            {
-                if (SearchDialog.ShowDialog() == DialogResult.Cancel)
+                    this.AddNewTab(tabName, false, MyCommon.TabUsageType.UserDefined);
+                    this._statuses.AddTab(tabName, MyCommon.TabUsageType.UserDefined, null);
+
+                    var filter = new PostFilterRule
+                    {
+                        FilterBody = new[] { searchOptions.Query },
+                        UseRegex = searchOptions.UseRegex,
+                        CaseSensitive = searchOptions.CaseSensitive,
+                    };
+                    this._statuses.Tabs[tabName].AddFilter(filter);
+
+                    var tabPage = this.ListTab.TabPages.Cast<TabPage>()
+                        .First(x => x.Text == tabName);
+
+                    this.ListTab.SelectedTab = tabPage;
+                    this.ListTabSelect(tabPage);
+
+                    this.ApplyPostFilters();
+                    this.SaveConfigsTabs();
+                }
+                else
                 {
-                    this.TopMost = SettingDialog.AlwaysTop;
-                    return;
+                    this.DoTabSearch(
+                        searchOptions.Query,
+                        searchOptions.CaseSensitive,
+                        searchOptions.UseRegex,
+                        SEARCHTYPE.DialogSearch);
                 }
-                this.TopMost = SettingDialog.AlwaysTop;
-                if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
             }
-
-            DoTabSearch(SearchDialog.SWord,
-                        SearchDialog.CheckCaseSensitive,
-                        SearchDialog.CheckRegex,
-                        SEARCHTYPE.PrevSearch);
+            else if (searchOptions.Type == SearchWordDialog.SearchType.Public)
+            {
+                this.AddNewTabForSearch(searchOptions.Query);
+            }
         }
 
         private void AboutMenuItem_Click(object sender, EventArgs e)
@@ -5682,7 +5790,7 @@ namespace OpenTween
             int idx = -1;
             DetailsListView lst = null;
 
-            if (ImageSelectionPanel.Enabled)
+            if (ImageSelector.Enabled)
                 return;
 
             //現在タブから最終タブまで探索
@@ -5768,9 +5876,9 @@ namespace OpenTween
             }
         }
 
-        private void VerUpMenuItem_Click(object sender, EventArgs e)
+        private async void VerUpMenuItem_Click(object sender, EventArgs e)
         {
-            CheckNewVersion();
+            await this.CheckNewVersion(false);
         }
 
         private void RunTweenUp()
@@ -5790,62 +5898,85 @@ namespace OpenTween
             }
         }
 
-        private void CheckNewVersion(bool startup = false)
+        public class VersionInfo
         {
-            if (ApplicationSettings.VersionInfoUrl == null)
-                return; // 更新チェック無効化
-
-            if (string.IsNullOrEmpty(MyCommon.fileVersion))
-            {
-                return;
-            }
+            public Version Version { get; set; }
+            public Uri DownloadUri { get; set; }
+            public string ReleaseNote { get; set; }
+        }
 
-            string retMsg;
-            try
-            {
-                retMsg = tw.GetVersionInfo();
-            }
-            catch
-            {
-                retMsg = "";
-            }
+        /// <summary>
+        /// OpenTween の最新バージョンの情報を取得します
+        /// </summary>
+        public async Task<VersionInfo> GetVersionInfoAsync()
+        {
+            var versionInfoUrl = new Uri(ApplicationSettings.VersionInfoUrl + "?" +
+                DateTime.Now.ToString("yyMMddHHmmss") + Environment.TickCount);
 
-            if (string.IsNullOrEmpty(retMsg))
-            {
-                StatusLabel.Text = Properties.Resources.CheckNewVersionText9;
-                if (!startup) MessageBox.Show(Properties.Resources.CheckNewVersionText10, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
-                return;
-            }
+            var responseText = await this.http.GetStringAsync(versionInfoUrl)
+                .ConfigureAwait(false);
 
             // 改行2つで前後パートを分割(前半がバージョン番号など、後半が詳細テキスト)
-            string[] msgPart = retMsg.Split(new string[] {"\n\n", "\r\n\r\n"}, 2, StringSplitOptions.None);
+            var msgPart = responseText.Split(new[] { "\n\n", "\r\n\r\n" }, 2, StringSplitOptions.None);
 
-            string[] msgHeader = msgPart[0].Split(new string[] {"\n", "\r\n"}, StringSplitOptions.None);
-            string msgBody = msgPart.Length == 2 ? msgPart[1] : "";
+            var msgHeader = msgPart[0].Split(new[] { "\n", "\r\n" }, StringSplitOptions.None);
+            var msgBody = msgPart.Length == 2 ? msgPart[1] : "";
 
             msgBody = Regex.Replace(msgBody, "(?<!\r)\n", "\r\n"); // LF -> CRLF
 
-            string currentVersion = msgHeader[0];
-            string downloadUrl = msgHeader[1];
+            return new VersionInfo
+            {
+                Version = Version.Parse(msgHeader[0]),
+                DownloadUri = new Uri(msgHeader[1]),
+                ReleaseNote = msgBody,
+            };
+        }
+
+        private async Task CheckNewVersion(bool startup = false)
+        {
+            if (ApplicationSettings.VersionInfoUrl == null)
+                return; // 更新チェック無効化
 
-            if (currentVersion.Replace(".", "").CompareTo(MyCommon.fileVersion.Replace(".", "")) > 0)
+            try
             {
+                var versionInfo = await this.GetVersionInfoAsync();
+
+                if (versionInfo.Version <= Version.Parse(MyCommon.FileVersion))
+                {
+                    // 更新不要
+                    if (!startup)
+                    {
+                        var msgtext = string.Format(Properties.Resources.CheckNewVersionText7,
+                            MyCommon.GetReadableVersion(), MyCommon.GetReadableVersion(versionInfo.Version));
+                        msgtext = MyCommon.ReplaceAppName(msgtext);
+
+                        MessageBox.Show(msgtext,
+                            MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2),
+                            MessageBoxButtons.OK, MessageBoxIcon.Information);
+                    }
+                    return;
+                }
+
                 using (var dialog = new UpdateDialog())
                 {
-                    dialog.SummaryText = string.Format(Properties.Resources.CheckNewVersionText3, MyCommon.GetReadableVersion(currentVersion));
-                    dialog.DetailsText = msgBody;
+                    dialog.SummaryText = string.Format(Properties.Resources.CheckNewVersionText3,
+                        MyCommon.GetReadableVersion(versionInfo.Version));
+                    dialog.DetailsText = versionInfo.ReleaseNote;
+
                     if (dialog.ShowDialog(this) == DialogResult.Yes)
                     {
-                        this.OpenUriAsync(downloadUrl);
+                        await this.OpenUriAsync(versionInfo.DownloadUri.OriginalString);
                     }
                 }
             }
-            else
+            catch (Exception)
             {
+                this.StatusLabel.Text = Properties.Resources.CheckNewVersionText9;
                 if (!startup)
                 {
-                    var msgtext = MyCommon.ReplaceAppName(string.Format(Properties.Resources.CheckNewVersionText7, MyCommon.GetReadableVersion(), MyCommon.GetReadableVersion(currentVersion)));
-                    MessageBox.Show(msgtext, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Information);
+                    MessageBox.Show(Properties.Resources.CheckNewVersionText10,
+                        MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2),
+                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
                 }
             }
         }
@@ -5881,7 +6012,7 @@ namespace OpenTween
             return detailHtmlFormatHeader + orgdata + detailHtmlFormatFooter;
         }
 
-        private void DisplayItemImage_Downloaded(object sender, EventArgs e)
+        private async void DisplayItemImage_Downloaded(object sender, EventArgs e)
         {
             if (sender.Equals(displayItem))
             {
@@ -5890,7 +6021,10 @@ namespace OpenTween
                 var img = displayItem.Image;
                 try
                 {
-                    UserPicture.Image = img != null ? img.Clone() : null;
+                    if (img != null)
+                        img = await img.CloneAsync();
+
+                    UserPicture.Image = img;
                 }
                 catch (Exception)
                 {
@@ -5906,6 +6040,16 @@ namespace OpenTween
 
         private static PostClass displaypost = new PostClass();
 
+        /// <summary>
+        /// サムネイルの表示処理を表すタスク
+        /// </summary>
+        private Task thumbnailTask = null;
+
+        /// <summary>
+        /// サムネイル表示に使用する CancellationToken の生成元
+        /// </summary>
+        private CancellationTokenSource thumbnailTokenSource = null;
+
         private void DispSelectedPost(bool forceupdate)
         {
             if (_curList.SelectedIndices.Count == 0 || _curPost == null)
@@ -6055,7 +6199,22 @@ namespace OpenTween
                         this.SplitContainer3.Panel2Collapsed = true;
 
                         if (this.IsPreviewEnable)
-                            this.tweetThumbnail1.ShowThumbnailAsync(_curPost);
+                        {
+                            if (this.thumbnailTokenSource != null)
+                            {
+                                var oldTokenSource = this.thumbnailTokenSource;
+
+                                // TODO: キャンセルを行うとUIスレッドが阻害される問題を調査
+                                //oldTokenSource.Cancel();
+
+                                this.thumbnailTask.ContinueWith(_ => oldTokenSource.Dispose());
+                            }
+
+                            this.thumbnailTokenSource = new CancellationTokenSource();
+
+                            var token = this.thumbnailTokenSource.Token;
+                            this.thumbnailTask = this.tweetThumbnail1.ShowThumbnailAsync(_curPost, token);
+                        }
                     }
                 }
                 catch (System.Runtime.InteropServices.COMException)
@@ -6289,6 +6448,17 @@ namespace OpenTween
                                 break;
                         }
                     }
+                    else if (Focused == FocusedControl.PostBrowser)
+                    {
+                        //フォーカスPostBrowser
+                        switch (KeyCode)
+                        {
+                            case Keys.Up:
+                            case Keys.Down:
+                                //スクロールを発生させるため、true を返す
+                                return true;
+                        }
+                    }
                     break;
                 case ModifierState.Ctrl:
                     //フォーカス関係なし
@@ -6628,7 +6798,7 @@ namespace OpenTween
                         switch (KeyCode)
                         {
                             case Keys.Up:
-                                if (_curList != null && _curList.Items.Count != 0 &&
+                                if (_curList != null && _curList.VirtualListSize != 0 &&
                                             _curList.SelectedIndices.Count > 0 && _curList.SelectedIndices[0] > 0)
                                 {
                                     idx = _curList.SelectedIndices[0] - 1;
@@ -6638,8 +6808,8 @@ namespace OpenTween
                                 }
                                 break;
                             case Keys.Down:
-                                if (_curList != null && _curList.Items.Count != 0 && _curList.SelectedIndices.Count > 0
-                                            && _curList.SelectedIndices[0] < _curList.Items.Count - 1)
+                                if (_curList != null && _curList.VirtualListSize != 0 && _curList.SelectedIndices.Count > 0
+                                            && _curList.SelectedIndices[0] < _curList.VirtualListSize - 1)
                                 {
                                     idx = _curList.SelectedIndices[0] + 1;
                                     SelectListItem(_curList, idx);
@@ -6773,26 +6943,32 @@ namespace OpenTween
 
         private void ScrollDownPostBrowser(bool forward)
         {
-            HtmlDocument doc = PostBrowser.Document;
+            var doc = PostBrowser.Document;
             if (doc == null) return;
-            if (doc.Body == null) return;
 
-            if (forward)
-                doc.Body.ScrollTop += SettingDialog.FontDetail.Height;
-            else
-                doc.Body.ScrollTop -= SettingDialog.FontDetail.Height;
+            var tags = doc.GetElementsByTagName("html");
+            if (tags.Count > 0)
+            {
+                if (forward)
+                    tags[0].ScrollTop += SettingDialog.FontDetail.Height;
+                else
+                    tags[0].ScrollTop -= SettingDialog.FontDetail.Height;
+            }
         }
 
         private void PageDownPostBrowser(bool forward)
         {
-            HtmlDocument doc = PostBrowser.Document;
+            var doc = PostBrowser.Document;
             if (doc == null) return;
-            if (doc.Body == null) return;
 
-            if (forward)
-                doc.Body.ScrollTop += PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
-            else
-                doc.Body.ScrollTop -= PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
+            var tags = doc.GetElementsByTagName("html");
+            if (tags.Count > 0)
+            {
+                if (forward)
+                    tags[0].ScrollTop += PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
+                else
+                    tags[0].ScrollTop -= PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
+            }
         }
 
         private void GoNextTab(bool forward)
@@ -7232,16 +7408,11 @@ namespace OpenTween
             string inReplyToTabName;
             long inReplyToId = _curPost.InReplyToStatusId.Value;
             string inReplyToUser = _curPost.InReplyToUser;
-            Dictionary<long, PostClass> curTabPosts;
-
-            if (_statuses.Tabs[_curTab.Text].IsInnerStorageTabType)
-                curTabPosts = curTabClass.Posts;
-            else
-                curTabPosts = _statuses.Posts;
+            //Dictionary<long, PostClass> curTabPosts = curTabClass.Posts;
 
             var inReplyToPosts = from tab in _statuses.Tabs.Values
                                  orderby tab != curTabClass
-                                 from post in ((Dictionary<long, PostClass>)(tab.IsInnerStorageTabType ? tab.Posts : _statuses.Posts)).Values
+                                 from post in tab.Posts.Values
                                  where post.StatusId == inReplyToId
                                  let index = tab.IndexOf(post.StatusId)
                                  where index != -1
@@ -7301,14 +7472,14 @@ namespace OpenTween
             if (_curPost == null) return;
 
             TabClass curTabClass = _statuses.Tabs[_curTab.Text];
-            Dictionary<long, PostClass> curTabPosts = curTabClass.IsInnerStorageTabType ? curTabClass.Posts : _statuses.Posts;
+            //Dictionary<long, PostClass> curTabPosts = curTabClass.Posts;
 
             if (parallel)
             {
                 if (_curPost.InReplyToStatusId != null)
                 {
                     var posts = from t in _statuses.Tabs
-                                from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
+                                from p in t.Value.Posts
                                 where p.Value.StatusId != _curPost.StatusId && p.Value.InReplyToStatusId == _curPost.InReplyToStatusId
                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
                                 where indexOf > -1
@@ -7345,7 +7516,7 @@ namespace OpenTween
                 if (replyChains == null || replyChains.Count < 1)
                 {
                     var posts = from t in _statuses.Tabs
-                                from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
+                                from p in t.Value.Posts
                                 where p.Value.InReplyToStatusId == _curPost.StatusId
                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
                                 where indexOf > -1
@@ -7400,35 +7571,78 @@ namespace OpenTween
 
         private void GoBackSelectPostChain()
         {
-            try
+            if (this.selectPostChains.Count > 1)
             {
-                this.selectPostChains.Pop();
-                Tuple<TabPage, PostClass> tabPostPair = this.selectPostChains.Pop();
-                if (!this.ListTab.TabPages.Contains(tabPostPair.Item1)) return;
-                this.ListTab.SelectedTab = tabPostPair.Item1;
-                if (tabPostPair.Item2 != null && this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId) > -1)
+                var idx = -1;
+                TabPage tp = null;
+
+                do
                 {
-                    this.SelectListItem(this._curList, this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
-                    this._curList.EnsureVisible(this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
+                    try
+                    {
+                        this.selectPostChains.Pop();
+                        var tabPostPair = this.selectPostChains.Peek();
+
+                        if (!this.ListTab.TabPages.Contains(tabPostPair.Item1)) continue;  //該当タブが存在しないので無視
+
+                        if (tabPostPair.Item2 != null)
+                        {
+                            idx = this._statuses.Tabs[tabPostPair.Item1.Text].IndexOf(tabPostPair.Item2.StatusId);
+                            if (idx == -1) continue;  //該当ポストが存在しないので無視
+                        }
+
+                        tp = tabPostPair.Item1;
+
+                        this.selectPostChains.Pop();
+                    }
+                    catch (InvalidOperationException)
+                    {
+                    }
+
+                    break;
                 }
-            }
-            catch (InvalidOperationException)
-            {
+                while (this.selectPostChains.Count > 1);
+
+                if (tp == null)
+                {
+                    //状態がおかしいので処理を中断
+                    //履歴が残り1つであればクリアしておく
+                    if (this.selectPostChains.Count == 1)
+                        this.selectPostChains.Clear();
+                    return;
+                }
+
+                DetailsListView lst = (DetailsListView)tp.Tag;
+                this.ListTab.SelectedTab = tp;
+                if (idx > -1)
+                {
+                    SelectListItem(lst, idx);
+                    lst.EnsureVisible(idx);
+                }
+                lst.Focus();
             }
         }
 
         private void PushSelectPostChain()
         {
-            if (this.selectPostChains.Count == 0 || (this.selectPostChains.Peek().Item1.Text != this._curTab.Text || this._curPost != this.selectPostChains.Peek().Item2))
+            int count = this.selectPostChains.Count;
+            if (count > 0)
             {
-                this.selectPostChains.Push(Tuple.Create(this._curTab, _curPost));
+                var p = this.selectPostChains.Peek();
+                if (p.Item1 == this._curTab)
+                {
+                    if (p.Item2 == this._curPost) return;  //最新の履歴と同一
+                    if (p.Item2 == null) this.selectPostChains.Pop();  //置き換えるため削除
+                }
             }
+            if (count >= 2500) TrimPostChain();
+            this.selectPostChains.Push(Tuple.Create(this._curTab, this._curPost));
         }
 
         private void TrimPostChain()
         {
-            if (this.selectPostChains.Count < 2000) return;
-            Stack<Tuple<TabPage, PostClass>> p = new Stack<Tuple<TabPage, PostClass>>();
+            if (this.selectPostChains.Count <= 2000) return;
+            var p = new Stack<Tuple<TabPage, PostClass>>(2000);
             for (int i = 0; i < 2000; i++)
             {
                 p.Push(this.selectPostChains.Pop());
@@ -7615,6 +7829,7 @@ namespace OpenTween
                 _cfgCommon.UseAtIdSupplement = SettingDialog.UseAtIdSupplement;
                 _cfgCommon.UseHashSupplement = SettingDialog.UseHashSupplement;
                 _cfgCommon.PreviewEnable = SettingDialog.PreviewEnable;
+                _cfgCommon.StatusAreaAtBottom = SettingDialog.StatusAreaAtBottom;
                 _cfgCommon.Language = SettingDialog.Language;
 
                 _cfgCommon.SortOrder = (int)_statuses.SortOrder;
@@ -7671,12 +7886,13 @@ namespace OpenTween
                 _cfgCommon.AllAtReply = tw.AllAtReply;
                 _cfgCommon.OpenUserTimeline = SettingDialog.OpenUserTimeline;
                 _cfgCommon.ListCountApi = SettingDialog.ListCountApi;
-                _cfgCommon.UseImageService = ImageServiceCombo.SelectedIndex;
-                _cfgCommon.UseImageServiceName = this.ImageService;
+                _cfgCommon.UseImageService = ImageSelector.ServiceIndex;
+                _cfgCommon.UseImageServiceName = ImageSelector.ServiceName;
                 _cfgCommon.ListDoubleClickAction = SettingDialog.ListDoubleClickAction;
                 _cfgCommon.UserAppointUrl = SettingDialog.UserAppointUrl;
                 _cfgCommon.HideDuplicatedRetweets = SettingDialog.HideDuplicatedRetweets;
-                _cfgCommon.IsPreviewFoursquare = SettingDialog.IsPreviewFoursquare;
+                _cfgCommon.EnableImgAzyobuziNet = SettingDialog.EnableImgAzyobuziNet;
+                _cfgCommon.ImgAzyobuziNetDisabledInDM = SettingDialog.ImgAzyobuziNetDisabledInDM;
                 _cfgCommon.MapThumbnailProvider = SettingDialog.MapThumbnailProvider;
                 _cfgCommon.MapThumbnailHeight = SettingDialog.MapThumbnailHeight;
                 _cfgCommon.MapThumbnailWidth = SettingDialog.MapThumbnailWidth;
@@ -7702,7 +7918,6 @@ namespace OpenTween
                 _cfgLocal.PreviewDistance = _mySpDis3;
                 _cfgLocal.StatusMultiline = StatusText.Multiline;
                 _cfgLocal.StatusTextHeight = _mySpDis2;
-                _cfgLocal.AdSplitterDistance = _myAdSpDis;
                 _cfgLocal.StatusText = SettingDialog.Status;
 
                 _cfgLocal.FontUnread = _fntUnread;
@@ -7749,7 +7964,7 @@ namespace OpenTween
             tabSetting.Save();
         }
 
-        private /* async */ void OpenURLFileMenuItem_Click(object sender, EventArgs e)
+        private async void OpenURLFileMenuItem_Click(object sender, EventArgs e)
         {
             string inputText;
             var ret = InputDialog.Show(this, Properties.Resources.OpenURL_InputText, Properties.Resources.OpenURL_Caption, out inputText);
@@ -7765,40 +7980,40 @@ namespace OpenTween
             }
 
             var statusId = long.Parse(match.Groups["StatusId"].Value);
-            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
 
-            Task.Factory.StartNew(() =>
+            var post = this._statuses[statusId];
+            if (post == null)
+            {
+                try
                 {
-                    var post = this._statuses[statusId];
-                    if (post == null)
+                    post = await Task.Run(() =>
                     {
-                        var err = this.tw.GetStatusApi(false, statusId, ref post);
+                        PostClass newPost = null;
+
+                        var err = this.tw.GetStatusApi(false, statusId, ref newPost);
                         if (!string.IsNullOrEmpty(err))
                             throw new WebApiException(err);
-                    }
-                    return post;
-                }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
-                .ContinueWith(t =>
-                {
-                    if (t.IsFaulted)
-                    {
-                        t.Exception.Flatten().Handle(x => x is WebApiException);
 
-                        var message = t.Exception.InnerException.Message;
-                        MessageBox.Show(this, string.Format(Properties.Resources.OpenURL_LoadFailed, message),
-                            Properties.Resources.OpenURL_Caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                        return newPost;
+                    });
+                }
+                catch (WebApiException ex)
+                {
+                    var message = ex.Message;
+                    MessageBox.Show(this, string.Format(Properties.Resources.OpenURL_LoadFailed, message),
+                        Properties.Resources.OpenURL_Caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
+                    return;
+                }
+            }
 
-                        return;
-                    }
-                    try
-                    {
-                        this.OpenRelatedTab(t.Result);
-                    }
-                    catch (TabException ex)
-                    {
-                        MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
-                    }
-                }, uiScheduler);
+            try
+            {
+                this.OpenRelatedTab(post);
+            }
+            catch (TabException ex)
+            {
+                MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
         }
 
         private void SaveLogMenuItem_Click(object sender, EventArgs e)
@@ -8026,25 +8241,24 @@ namespace OpenTween
                 if (ListTab.TabPages[baseIndex].Text == baseTabText) break;
             }
 
-            ListTab.SuspendLayout();
-
-            TabPage mTp = null;
-            for (int j = 0; j < ListTab.TabPages.Count; j++)
+            using (ControlTransaction.Layout(this.ListTab))
             {
-                if (ListTab.TabPages[j].Text == targetTabText)
+                TabPage mTp = null;
+                for (int j = 0; j < ListTab.TabPages.Count; j++)
                 {
-                    mTp = ListTab.TabPages[j];
-                    ListTab.TabPages.Remove(mTp);
-                    if (j < baseIndex) baseIndex -= 1;
-                    break;
+                    if (ListTab.TabPages[j].Text == targetTabText)
+                    {
+                        mTp = ListTab.TabPages[j];
+                        ListTab.TabPages.Remove(mTp);
+                        if (j < baseIndex) baseIndex -= 1;
+                        break;
+                    }
                 }
+                if (isBeforeBaseTab)
+                    ListTab.TabPages.Insert(baseIndex, mTp);
+                else
+                    ListTab.TabPages.Insert(baseIndex + 1, mTp);
             }
-            if (isBeforeBaseTab)
-                ListTab.TabPages.Insert(baseIndex, mTp);
-            else
-                ListTab.TabPages.Insert(baseIndex + 1, mTp);
-
-            ListTab.ResumeLayout();
 
             SaveConfigsTabs();
         }
@@ -8635,33 +8849,7 @@ namespace OpenTween
             fltDialog.ShowDialog(this);
             this.TopMost = SettingDialog.AlwaysTop;
 
-            try
-            {
-                this.Cursor = Cursors.WaitCursor;
-                this.PurgeListViewItemCache();
-                _curPost = null;
-                _curItemIndex = -1;
-                _statuses.FilterAll();
-                foreach (TabPage tb in ListTab.TabPages)
-                {
-                    ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
-                    if (_statuses.Tabs[tb.Text].UnreadCount > 0)
-                    {
-                        if (SettingDialog.TabIconDisp)
-                            tb.ImageIndex = 0;
-                    }
-                    else
-                    {
-                        if (SettingDialog.TabIconDisp)
-                            tb.ImageIndex = -1;
-                    }
-                }
-                if (!SettingDialog.TabIconDisp) ListTab.Refresh();
-            }
-            finally
-            {
-                this.Cursor = Cursors.Default;
-            }
+            this.ApplyPostFilters();
             SaveConfigsTabs();
         }
 
@@ -8739,33 +8927,7 @@ namespace OpenTween
                 this.TopMost = SettingDialog.AlwaysTop;
             }
 
-            try
-            {
-                this.Cursor = Cursors.WaitCursor;
-                this.PurgeListViewItemCache();
-                _curPost = null;
-                _curItemIndex = -1;
-                _statuses.FilterAll();
-                foreach (TabPage tb in ListTab.TabPages)
-                {
-                    ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
-                    if (_statuses.Tabs[tb.Text].UnreadCount > 0)
-                    {
-                        if (SettingDialog.TabIconDisp)
-                            tb.ImageIndex = 0;
-                    }
-                    else
-                    {
-                        if (SettingDialog.TabIconDisp)
-                            tb.ImageIndex = -1;
-                    }
-                }
-                if (!SettingDialog.TabIconDisp) ListTab.Refresh();
-            }
-            finally
-            {
-                this.Cursor = Cursors.Default;
-            }
+            this.ApplyPostFilters();
             SaveConfigsTabs();
             if (this.ListTab.SelectedTab != null &&
                 ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices.Count > 0)
@@ -8913,36 +9075,7 @@ namespace OpenTween
                 if (AtIdSupl.ItemCount != cnt) _modifySettingAtId = true;
             }
 
-            try
-            {
-                this.Cursor = Cursors.WaitCursor;
-                this.PurgeListViewItemCache();
-                _curPost = null;
-                _curItemIndex = -1;
-                _statuses.FilterAll();
-                foreach (TabPage tb in ListTab.TabPages)
-                {
-                    ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
-                    if (_statuses.ContainsTab(tb.Text))
-                    {
-                        if (_statuses.Tabs[tb.Text].UnreadCount > 0)
-                        {
-                            if (SettingDialog.TabIconDisp)
-                                tb.ImageIndex = 0;
-                        }
-                        else
-                        {
-                            if (SettingDialog.TabIconDisp)
-                                tb.ImageIndex = -1;
-                        }
-                    }
-                }
-                if (!SettingDialog.TabIconDisp) ListTab.Refresh();
-            }
-            finally
-            {
-                this.Cursor = Cursors.Default;
-            }
+            this.ApplyPostFilters();
             SaveConfigsTabs();
         }
 
@@ -9221,10 +9354,10 @@ namespace OpenTween
                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
             {
-                foreach (string key in _statuses.Tabs.Keys)
+                foreach (var tab in _statuses.Tabs.Values)
                 {
-                    ur += _statuses.Tabs[key].UnreadCount;
-                    al += _statuses.Tabs[key].AllCount;
+                    ur += tab.UnreadCount;
+                    al += tab.AllCount;
                 }
             }
 
@@ -9284,14 +9417,14 @@ namespace OpenTween
             StringBuilder slbl = new StringBuilder(256);
             try
             {
-                foreach (string key in _statuses.Tabs.Keys)
+                foreach (var tab in _statuses.Tabs.Values)
                 {
-                    ur += _statuses.Tabs[key].UnreadCount;
-                    al += _statuses.Tabs[key].AllCount;
-                    if (key.Equals(_curTab.Text))
+                    ur += tab.UnreadCount;
+                    al += tab.AllCount;
+                    if (_curTab != null && tab.TabName.Equals(_curTab.Text))
                     {
-                        tur = _statuses.Tabs[key].UnreadCount;
-                        tal = _statuses.Tabs[key].AllCount;
+                        tur = tab.UnreadCount;
+                        tal = tab.AllCount;
                     }
                 }
             }
@@ -9460,11 +9593,6 @@ namespace OpenTween
                 //_mySize = this.ClientSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
                 this.DesktopLocation = _cfgLocal.FormLocation;
                 //_myLoc = this.DesktopLocation;                        //位置保持(最小化・最大化されたまま終了した場合の対応用)
-                //if (_cfgLocal.AdSplitterDistance > this.SplitContainer4.Panel1MinSize &&
-                //    _cfgLocal.AdSplitterDistance < this.SplitContainer4.Height - this.SplitContainer4.Panel2MinSize - this.SplitContainer4.SplitterWidth)
-                //{
-                //    this.SplitContainer4.SplitterDistance = _cfgLocal.AdSplitterDistance; //Splitterの位置設定
-                //}
                 if (_cfgLocal.SplitterDistance > this.SplitContainer1.Panel1MinSize &&
                     _cfgLocal.SplitterDistance < this.SplitContainer1.Height - this.SplitContainer1.Panel2MinSize - this.SplitContainer1.SplitterWidth)
                 {
@@ -9670,28 +9798,20 @@ namespace OpenTween
             OpenUriAsync(name.Remove(name.LastIndexOf("_normal"), 7)); // "_normal".Length
         }
 
-        private /* async */ void ReloadIconToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void ReloadIconToolStripMenuItem_Click(object sender, EventArgs e)
         {
             if (this._curPost == null) return;
 
-            var imageUrl = this._curPost.ImageUrl;
-            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
+            await this.UserPicture.SetImageFromTask(async () =>
+            {
+                var imageUrl = this._curPost.ImageUrl;
 
-            this.IconCache.DownloadImageAsync(imageUrl, force: true)
-                .ContinueWith(t =>
-                {
-                    this.ClearUserPicture();
+                var image = await this.IconCache.DownloadImageAsync(imageUrl, force: true)
+                    .ConfigureAwait(false);
 
-                    if (t.IsFaulted)
-                    {
-                        t.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
-                        this.UserPicture.ShowErrorImage();
-                    }
-                    else
-                    {
-                        this.UserPicture.Image = t.Result.Clone() ;
-                    }
-                }, uiScheduler);
+                return await image.CloneAsync()
+                    .ConfigureAwait(false);
+            });
         }
 
         private void SaveOriginalSizeIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
@@ -9775,7 +9895,7 @@ namespace OpenTween
             _modifySettingLocal = true;
         }
 
-        private bool UrlConvert(MyCommon.UrlConverter Converter_Type)
+        private async Task<bool> UrlConvertAsync(MyCommon.UrlConverter Converter_Type)
         {
             //t.coで投稿時自動短縮する場合は、外部サービスでの短縮禁止
             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco) return;
@@ -9805,10 +9925,20 @@ namespace OpenTween
                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
                     {
                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
-                        result = ShortUrl.Make(Converter_Type, tmp);
-                        if (result.Equals("Can't convert"))
+                        try
+                        {
+                            var srcUri = new Uri(MyCommon.urlEncodeMultibyteChar(tmp));
+                            var resultUri = await ShortUrl.Instance.ShortenUrlAsync(Converter_Type, srcUri);
+                            result = resultUri.ToString();
+                        }
+                        catch (WebApiException e)
+                        {
+                            this.StatusLabel.Text = Converter_Type + ":" + e.Message;
+                            return false;
+                        }
+                        catch (UriFormatException e)
                         {
-                            StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
+                            this.StatusLabel.Text = Converter_Type + ":" + e.Message;
                             return false;
                         }
                     }
@@ -9864,10 +9994,20 @@ namespace OpenTween
                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
                     {
                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
-                        result = ShortUrl.Make(Converter_Type, tmp);
-                        if (result.Equals("Can't convert"))
+                        try
+                        {
+                            var srcUri = new Uri(MyCommon.urlEncodeMultibyteChar(tmp));
+                            var resultUri = await ShortUrl.Instance.ShortenUrlAsync(Converter_Type, srcUri);
+                            result = resultUri.ToString();
+                        }
+                        catch (WebApiException e)
+                        {
+                            this.StatusLabel.Text = Converter_Type + ":" + e.Message;
+                            continue;
+                        }
+                        catch (UriFormatException e)
                         {
-                            StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
+                            this.StatusLabel.Text = Converter_Type + ":" + e.Message;
                             continue;
                         }
                     }
@@ -9915,29 +10055,29 @@ namespace OpenTween
             }
         }
 
-        private void TinyURLToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void TinyURLToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.TinyUrl);
+            await UrlConvertAsync(MyCommon.UrlConverter.TinyUrl);
         }
 
-        private void IsgdToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void IsgdToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.Isgd);
+            await UrlConvertAsync(MyCommon.UrlConverter.Isgd);
         }
 
-        private void TwurlnlToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void TwurlnlToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.Twurl);
+            await UrlConvertAsync(MyCommon.UrlConverter.Twurl);
         }
 
-        private void UxnuMenuItem_Click(object sender, EventArgs e)
+        private async void UxnuMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.Uxnu);
+            await UrlConvertAsync(MyCommon.UrlConverter.Uxnu);
         }
 
-        private void UrlConvertAutoToolStripMenuItem_Click(object sender, EventArgs e) 
+        private async void UrlConvertAutoToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (!UrlConvert(SettingDialog.AutoShortUrlFirst))
+            if (!await UrlConvertAsync(SettingDialog.AutoShortUrlFirst))
             {
                 MyCommon.UrlConverter svc = SettingDialog.AutoShortUrlFirst;
                 Random rnd = new Random();
@@ -9947,7 +10087,7 @@ namespace OpenTween
                     svc = (MyCommon.UrlConverter)rnd.Next(System.Enum.GetNames(typeof(MyCommon.UrlConverter)).Length);
                 }
                 while (svc == SettingDialog.AutoShortUrlFirst || svc == MyCommon.UrlConverter.Nicoms || svc == MyCommon.UrlConverter.Unu);
-                UrlConvert(svc);
+                await UrlConvertAsync(svc);
             }
         }
 
@@ -10320,14 +10460,20 @@ namespace OpenTween
 
             if (_selText != null)
             {
-                SearchDialog.SWord = _selText;
-                SearchDialog.CheckCaseSensitive = false;
-                SearchDialog.CheckRegex = false;
+                var searchOptions = new SearchWordDialog.SearchOptions(
+                    SearchWordDialog.SearchType.Timeline,
+                    _selText,
+                    newTab: false,
+                    caseSensitive: false,
+                    useRegex: false);
 
-                DoTabSearch(SearchDialog.SWord,
-                            SearchDialog.CheckCaseSensitive,
-                            SearchDialog.CheckRegex,
-                            SEARCHTYPE.NextSearch);
+                this.SearchDialog.ResultOptions = searchOptions;
+
+                this.DoTabSearch(
+                    searchOptions.Query,
+                    searchOptions.CaseSensitive,
+                    searchOptions.UseRegex,
+                    SEARCHTYPE.NextSearch);
             }
         }
 
@@ -10341,15 +10487,22 @@ namespace OpenTween
         {
             if (e.Data.GetDataPresent(DataFormats.FileDrop))
             {
-                ImageSelectionPanel.Visible = true;
-                ImageSelectionPanel.Enabled = true;
-                TimelinePanel.Visible = false;
-                TimelinePanel.Enabled = false;
-                ImagefilePathText.Text = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
-                ImageFromSelectedFile();
-                this.Activate();
-                this.BringToFront();
-                StatusText.Focus();
+                SelectMedia_DragDrop(e);
+            }
+            else if (e.Data.GetDataPresent("UniformResourceLocatorW"))
+            {
+                var url = GetUrlFromDataObject(e.Data);
+
+                string appendText;
+                if (url.Item2 == null)
+                    appendText = url.Item1;
+                else
+                    appendText = url.Item2 + " " + url.Item1;
+
+                if (this.StatusText.TextLength == 0)
+                    this.StatusText.Text = appendText;
+                else
+                    this.StatusText.Text += " " + appendText;
             }
             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
             {
@@ -10358,30 +10511,75 @@ namespace OpenTween
             }
         }
 
-        private void TweenMain_DragOver(object sender, DragEventArgs e)
+        /// <summary>
+        /// IDataObject から URL とタイトルの対を取得します
+        /// </summary>
+        /// <remarks>
+        /// タイトルのみ取得できなかった場合は Value2 が null のタプルを返すことがあります。
+        /// </remarks>
+        /// <exception cref="ArgumentException">不正なフォーマットが入力された場合</exception>
+        /// <exception cref="NotSupportedException">サポートされていないデータが入力された場合</exception>
+        internal static Tuple<string, string> GetUrlFromDataObject(IDataObject data)
         {
-            if (e.Data.GetDataPresent(DataFormats.FileDrop))
+            if (data.GetDataPresent("text/x-moz-url"))
             {
-                string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
-                FileInfo fl = new FileInfo(filename);
-                string ext = fl.Extension;
+                // Firefox, Google Chrome で利用可能
+                // 参照: https://developer.mozilla.org/ja/docs/DragDrop/Recommended_Drag_Types
 
-                if (!string.IsNullOrEmpty(this.ImageService) && this.pictureService[this.ImageService].CheckValidFilesize(ext, fl.Length))
+                using (var stream = (MemoryStream)data.GetData("text/x-moz-url"))
                 {
-                    e.Effect = DragDropEffects.Copy;
-                    return;
+                    var lines = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0').Split('\n');
+                    if (lines.Length < 2)
+                        throw new ArgumentException("不正な text/x-moz-url フォーマットです", "data");
+
+                    return new Tuple<string, string>(lines[0], lines[1]);
                 }
-                foreach (string svc in ImageServiceCombo.Items)
+            }
+            else if (data.GetDataPresent("IESiteModeToUrl"))
+            {
+                // Internet Exproler 用
+                // 保護モードが有効なデフォルトの IE では DragDrop イベントが発火しないため使えない
+
+                using (var stream = (MemoryStream)data.GetData("IESiteModeToUrl"))
                 {
-                    if (string.IsNullOrEmpty(svc)) continue;
-                    if (this.pictureService[svc].CheckValidFilesize(ext, fl.Length))
-                    {
-                        ImageServiceCombo.SelectedItem = svc;
-                        e.Effect = DragDropEffects.Copy;
-                        return;
-                    }
+                    var lines = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0').Split('\0');
+                    if (lines.Length < 2)
+                        throw new ArgumentException("不正な IESiteModeToUrl フォーマットです", "data");
+
+                    return new Tuple<string, string>(lines[0], lines[1]);
                 }
-                e.Effect = DragDropEffects.None;
+            }
+            else if (data.GetDataPresent("UniformResourceLocatorW"))
+            {
+                // それ以外のブラウザ向け
+
+                using (var stream = (MemoryStream)data.GetData("UniformResourceLocatorW"))
+                {
+                    var url = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0');
+                    return new Tuple<string, string>(url, null);
+                }
+            }
+
+            throw new NotSupportedException("サポートされていないデータ形式です: " + data.GetFormats()[0]);
+        }
+
+        private void TweenMain_DragEnter(object sender, DragEventArgs e)
+        {
+            if (e.Data.GetDataPresent(DataFormats.FileDrop))
+            {
+                SelectMedia_DragEnter(e);
+            }
+        }
+
+        private void TweenMain_DragOver(object sender, DragEventArgs e)
+        {
+            if (e.Data.GetDataPresent(DataFormats.FileDrop))
+            {
+                SelectMedia_DragOver(e);
+            }
+            else if (e.Data.GetDataPresent("UniformResourceLocatorW"))
+            {
+                e.Effect = DragDropEffects.Copy;
             }
             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
             {
@@ -10403,7 +10601,7 @@ namespace OpenTween
 
         public Task OpenUriAsync(string UriString)
         {
-            return Task.Factory.StartNew(() =>
+            return Task.Run(() =>
             {
                 string myPath = UriString;
 
@@ -10486,9 +10684,10 @@ namespace OpenTween
             //単一
             Rectangle bnd = new Rectangle();
             bool flg = false;
-            if (LView.FocusedItem != null)
+            var item = LView.FocusedItem;
+            if (item != null)
             {
-                bnd = LView.FocusedItem.Bounds;
+                bnd = item.Bounds;
                 flg = true;
             }
 
@@ -10497,21 +10696,22 @@ namespace OpenTween
                 LView.SelectedIndices.Clear();
             }
             while (LView.SelectedIndices.Count > 0);
-            LView.Items[Index].Selected = true;
-            //LView.SelectedIndices.Add(Index);
-            LView.Items[Index].Focused = true;
+            item = LView.Items[Index];
+            item.Selected = true;
+            item.Focused = true;
 
             if (flg) LView.Invalidate(bnd);
         }
 
-        private void SelectListItem(DetailsListView LView , int[] Index, int FocusedIndex)
+        private void SelectListItem(DetailsListView LView , int[] Index, int[] FocusedIndex)
         {
             //複数
             Rectangle bnd = new Rectangle();
             bool flg = false;
-            if (LView.FocusedItem != null)
+            var item = LView.FocusedItem;
+            if (item != null)
             {
-                bnd = LView.FocusedItem.Bounds;
+                bnd = item.Bounds;
                 flg = true;
             }
 
@@ -10532,14 +10732,19 @@ namespace OpenTween
                     }
                 }
             }
-            if (FocusedIndex > -1 && LView.VirtualListSize > FocusedIndex)
+            if (FocusedIndex[1] > -1 && LView.VirtualListSize > FocusedIndex[1])
+            {
+                LView.SelectionMark = FocusedIndex[1];
+            }
+            if (FocusedIndex[0] > -1 && LView.VirtualListSize > FocusedIndex[0])
             {
-                LView.Items[FocusedIndex].Focused = true;
+                LView.Items[FocusedIndex[0]].Focused = true;
             }
             else if (fIdx > -1)
             {
                 LView.Items[fIdx].Focused = true;
             }
+
             if (flg) LView.Invalidate(bnd);
         }
 
@@ -10612,7 +10817,7 @@ namespace OpenTween
             if (SettingDialog.UserstreamStartup) tw.StartUserStream();
         }
 
-        private void TweenMain_Shown(object sender, EventArgs e)
+        private async void TweenMain_Shown(object sender, EventArgs e)
         {
             try
             {
@@ -10627,6 +10832,7 @@ namespace OpenTween
 
             if (this.IsNetworkAvailable())
             {
+                this.RefreshMuteUserIdsAsync();
                 GetTimeline(MyCommon.WORKERTYPE.BlockIds, 0, 0, "");
                 GetTimeline(MyCommon.WORKERTYPE.NoRetweetIds, 0, 0, "");
                 if (SettingDialog.StartupFollowers)
@@ -10652,21 +10858,17 @@ namespace OpenTween
                 GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");  //tabname="":全タブ
                 _waitLists = true;
                 GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");  //tabname="":全タブ
-                int i = 0;
-                int j = 0;
-                while (IsInitialRead() && !MyCommon._endingFlag)
+
+                var i = 0;
+                while (this.IsInitialRead())
                 {
-                    System.Threading.Thread.Sleep(100);
-                    Application.DoEvents();
+                    await Task.Delay(5000);
+
                     i += 1;
-                    j += 1;
-                    if (j > 1200) break; // 120秒間初期処理が終了しなかったら強制的に打ち切る
-                    if (i > 50)
-                    {
-                        if (MyCommon._endingFlag)
-                            return;
-                        i = 0;
-                    }
+                    if (i > 24) break; // 120秒間初期処理が終了しなかったら強制的に打ち切る
+
+                    if (MyCommon._endingFlag)
+                        return;
                 }
 
                 if (MyCommon._endingFlag) return;
@@ -10675,7 +10877,7 @@ namespace OpenTween
                 {
                     //バージョンチェック(引数:起動時チェックの場合はtrue・・・チェック結果のメッセージを表示しない)
                     if (SettingDialog.StartupVersion)
-                        CheckNewVersion(true);
+                        await this.CheckNewVersion(true);
                 }
                 else
                 {
@@ -10741,9 +10943,12 @@ namespace OpenTween
                     return;
                 }
                 string rtdata = _curPost.Text;
-                rtdata = CreateRetweetUnofficial(rtdata);
+                rtdata = CreateRetweetUnofficial(rtdata, this.StatusText.Multiline);
 
-                StatusText.Text = "RT @" + _curPost.ScreenName + ": " + WebUtility.HtmlDecode(rtdata);
+                this._reply_to_id = null;
+                this._reply_to_name = null;
+
+                StatusText.Text = "RT @" + _curPost.ScreenName + ": " + rtdata;
 
                 StatusText.SelectionStart = 0;
                 StatusText.Focus();
@@ -10847,26 +11052,34 @@ namespace OpenTween
             }
         }
 
-        private string CreateRetweetUnofficial(string status)
-        {
-            // Twitterにより省略されているURLを含むaタグをキャプチャしてリンク先URLへ置き換える
-            status = Regex.Replace(status, @"<a target=""_self"" href=""(?<url>[^""]+)"" title=""(?<title>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${title}");
-
-            //その他のリンク(@IDなど)を置き換える
-            status = Regex.Replace(status, @"@<a target=""_self"" href=""https?://twitter.com/(#!/)?(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "@${url}");
-            //ハッシュタグ
-            status = Regex.Replace(status, @"<a target=""_self"" href=""(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${link}");
-            //<br>タグ除去
-            if (StatusText.Multiline)
-                status = Regex.Replace(status, @"(\r\n|\n|\r)?<br>", "\r\n", RegexOptions.IgnoreCase | RegexOptions.Multiline);
+        /// <summary>
+        /// TweetFormatterクラスによって整形された状態のHTMLを、非公式RT用に元のツイートに復元します
+        /// </summary>
+        /// <param name="statusHtml">TweetFormatterによって整形された状態のHTML</param>
+        /// <param name="multiline">trueであればBRタグを改行に、falseであればスペースに変換します</param>
+        /// <returns>復元されたツイート本文</returns>
+        internal static string CreateRetweetUnofficial(string statusHtml, bool multiline)
+        {
+            // TweetFormatterクラスによって整形された状態のHTMLを元のツイートに復元します
+
+            // 通常の URL
+            statusHtml = Regex.Replace(statusHtml, "<a href=\"(?<href>.+?)\" title=\"(?<title>.+?)\">(?<text>.+?)</a>", "${title}");
+            // メンション
+            statusHtml = Regex.Replace(statusHtml, "<a class=\"mention\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
+            // ハッシュタグ
+            statusHtml = Regex.Replace(statusHtml, "<a class=\"hashtag\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
+
+            // <br> 除去
+            if (multiline)
+                statusHtml = statusHtml.Replace("<br>", Environment.NewLine);
             else
-                status = Regex.Replace(status, @"(\r\n|\n|\r)?<br>", " ", RegexOptions.IgnoreCase | RegexOptions.Multiline);
+                statusHtml = statusHtml.Replace("<br>", " ");
 
-            _reply_to_id = null;
-            _reply_to_name = null;
-            status = status.Replace("&nbsp;", " ");
+            // &nbsp; は本来であれば U+00A0 (NON-BREAK SPACE) に置換すべきですが、
+            // 現状では半角スペースの代用として &nbsp; を使用しているため U+0020 に置換します
+            statusHtml = statusHtml.Replace("&nbsp;", " ");
 
-            return status;
+            return WebUtility.HtmlDecode(statusHtml);
         }
 
         private void DumpPostClassToolStripMenuItem_Click(object sender, EventArgs e)
@@ -10913,14 +11126,14 @@ namespace OpenTween
             TabRename(ref _rclickTabName);
         }
 
-        private void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.Bitly);
+            await UrlConvertAsync(MyCommon.UrlConverter.Bitly);
         }
 
-        private void JmpToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void JmpToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            UrlConvert(MyCommon.UrlConverter.Jmp);
+            await UrlConvertAsync(MyCommon.UrlConverter.Jmp);
         }
 
 
@@ -11335,9 +11548,9 @@ namespace OpenTween
                     return;
                 }
                 string rtdata = _curPost.Text;
-                rtdata = CreateRetweetUnofficial(rtdata);
+                rtdata = CreateRetweetUnofficial(rtdata, this.StatusText.Multiline);
 
-                StatusText.Text = " QT @" + _curPost.ScreenName + ": " + WebUtility.HtmlDecode(rtdata);
+                StatusText.Text = " QT @" + _curPost.ScreenName + ": " + rtdata;
                 if (_curPost.RetweetedId == null)
                 {
                     _reply_to_id = _curPost.StatusId;
@@ -11413,8 +11626,8 @@ namespace OpenTween
                 cmb.Text = tb.SearchWords;
                 cmb.SelectAll();
                 DetailsListView lst = (DetailsListView)pnl.Parent.Tag;
+                this.PurgeListViewItemCache();
                 lst.VirtualListSize = 0;
-                lst.Items.Clear();
                 _statuses.ClearTabIds(tbName);
                 SaveConfigsTabs();   //検索条件の保存
             }
@@ -11535,33 +11748,7 @@ namespace OpenTween
                 fc.FilterByUrl = false;
                 _statuses.Tabs[tabName].AddFilter(fc);
 
-                try
-                {
-                    this.Cursor = Cursors.WaitCursor;
-                    this.PurgeListViewItemCache();
-                    _curPost = null;
-                    _curItemIndex = -1;
-                    _statuses.FilterAll();
-                    foreach (TabPage tb in ListTab.TabPages)
-                    {
-                        ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
-                        if (_statuses.Tabs[tb.Text].UnreadCount > 0)
-                        {
-                            if (SettingDialog.TabIconDisp)
-                                tb.ImageIndex = 0;
-                        }
-                        else
-                        {
-                            if (SettingDialog.TabIconDisp)
-                                tb.ImageIndex = -1;
-                        }
-                    }
-                    if (!SettingDialog.TabIconDisp) ListTab.Refresh();
-                }
-                finally
-                {
-                    this.Cursor = Cursors.Default;
-                }
+                this.ApplyPostFilters();
                 SaveConfigsTabs();
             }
         }
@@ -11635,7 +11822,7 @@ namespace OpenTween
             Match m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/search\?q=%23(?<hash>.+)$");
             if (m.Success)
             {
-                HashMgr.SetPermanentHash("#" + m.Result("${hash}"));
+                HashMgr.SetPermanentHash("#" + Uri.UnescapeDataString(m.Result("${hash}")));
                 HashStripSplitButton.Text = HashMgr.UseHash;
                 HashToggleMenuItem.Checked = true;
                 HashToggleToolStripMenuItem.Checked = true;
@@ -11901,7 +12088,7 @@ namespace OpenTween
         {
             public Twitter tw;
             public string id;
-            public TwitterDataModel.User user;
+            public TwitterUser user;
         }
 
         private void GetUserInfo_DoWork(object sender, DoWorkEventArgs e)
@@ -11912,7 +12099,7 @@ namespace OpenTween
 
         private void doShowUserStatus(string id, bool ShowInputDialog)
         {
-            TwitterDataModel.User user = null;
+            TwitterUser user = null;
             GetUserInfoArgs args = new GetUserInfoArgs();
             if (ShowInputDialog)
             {
@@ -11967,15 +12154,18 @@ namespace OpenTween
             }
         }
 
-        private void doShowUserStatus(TwitterDataModel.User user)
+        private async void doShowUserStatus(TwitterUser user)
         {
-            using (ShowUserInfo userinfo = new ShowUserInfo())
+            using (var userDialog = new UserInfoDialog(this, this.tw))
             {
-                userinfo.Owner = this;
-                userinfo.User = user;
-                userinfo.ShowDialog(this);
+                var showUserTask = userDialog.ShowUserAsync(user);
+                userDialog.ShowDialog(this);
+
                 this.Activate();
                 this.BringToFront();
+
+                // ユーザー情報の表示が完了するまで userDialog を破棄しない
+                await showUserTask;
             }
         }
 
@@ -12105,7 +12295,9 @@ namespace OpenTween
         private HookGlobalHotkey _hookGlobalHotkey;
         public TweenMain()
         {
+            this.http = MyCommon.CreateHttpClient();
             _hookGlobalHotkey = new HookGlobalHotkey(this);
+
             // この呼び出しは、Windows フォーム デザイナで必要です。
             InitializeComponent();
 
@@ -12120,8 +12312,13 @@ namespace OpenTween
             this.ListTab.HandleCreated += (s, e) => Win32Api.SetMinTabWidth((TabControl)s, 40);
 
             this._apiGauge = new ToolStripAPIGauge();
+            this._apiGauge.BorderSides = ToolStripStatusLabelBorderSides.Right;
             this.StatusStrip1.Items.Insert(2, this._apiGauge);
 
+            this.ImageSelector.Visible = false;
+            this.ImageSelector.Enabled = false;
+            this.ImageSelector.FilePickDialog = OpenFileDialog1;
+
             this.ReplaceAppName();
         }
 
@@ -12178,254 +12375,73 @@ namespace OpenTween
 #region "画像投稿"
         private void ImageSelectMenuItem_Click(object sender, EventArgs e)
         {
-            if (ImageSelectionPanel.Visible == true)
-            {
-                ImagefilePathText.CausesValidation = false;
-                TimelinePanel.Visible = true;
-                TimelinePanel.Enabled = true;
-                ImageSelectionPanel.Visible = false;
-                ImageSelectionPanel.Enabled = false;
-                ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
-                ImagefilePathText.CausesValidation = true;
-            }
+            if (ImageSelector.Visible)
+                ImageSelector.EndSelection();
             else
-            {
-                ImageSelectionPanel.Visible = true;
-                ImageSelectionPanel.Enabled = true;
-                TimelinePanel.Visible = false;
-                TimelinePanel.Enabled = false;
-                ImagefilePathText.Focus();
-            }
+                ImageSelector.BeginSelection();
         }
 
-        private void FilePickButton_Click(object sender, EventArgs e)
+        private void SelectMedia_DragEnter(DragEventArgs e)
         {
-            if (string.IsNullOrEmpty(this.ImageService)) return;
-            OpenFileDialog1.Filter = this.pictureService[this.ImageService].GetFileOpenDialogFilter();
-            OpenFileDialog1.Title = Properties.Resources.PickPictureDialog1;
-            OpenFileDialog1.FileName = "";
-
-            try
-            {
-                this.AllowDrop = false;
-                if (OpenFileDialog1.ShowDialog() == DialogResult.Cancel) return;
-            }
-            finally
+            if (ImageSelector.HasUploadableService(((string[])e.Data.GetData(DataFormats.FileDrop, false))[0]))
             {
-                this.AllowDrop = true;
+                e.Effect = DragDropEffects.Copy;
+                return;
             }
-
-            ImagefilePathText.Text = OpenFileDialog1.FileName;
-            ImageFromSelectedFile();
+            e.Effect = DragDropEffects.None;
         }
 
-        private void ImagefilePathText_Validating(object sender, CancelEventArgs e)
+        private void SelectMedia_DragOver(DragEventArgs e)
         {
-            if (ImageCancelButton.Focused)
-            {
-                ImagefilePathText.CausesValidation = false;
-                return;
-            }
-            ImagefilePathText.Text = ImagefilePathText.Text.Trim();
-            if (string.IsNullOrEmpty(ImagefilePathText.Text))
-            {
-                ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-            }
-            else
-            {
-                ImageFromSelectedFile();
-            }
+            //何も触らない
         }
 
-        private void ImageFromSelectedFile()
+        private void SelectMedia_DragDrop(DragEventArgs e)
         {
-            try
-            {
-                if (string.IsNullOrEmpty(ImagefilePathText.Text.Trim()) || string.IsNullOrEmpty(this.ImageService))
-                {
-                    ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                    ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                    ImagefilePathText.Text = "";
-                    return;
-                }
-
-                FileInfo fl = new FileInfo(ImagefilePathText.Text.Trim());
-                if (!this.pictureService[this.ImageService].CheckValidExtension(fl.Extension))
-                {
-                    //画像以外の形式
-                    ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                    ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                    ImagefilePathText.Text = "";
-                    return;
-                }
-
-                if (!this.pictureService[this.ImageService].CheckValidFilesize(fl.Extension, fl.Length))
-                {
-                    // ファイルサイズが大きすぎる
-                    ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                    ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                    ImagefilePathText.Text = "";
-                    MessageBox.Show("File is too large.");
-                    return;
-                }
-
-                switch (this.pictureService[this.ImageService].GetFileType(fl.Extension))
-                {
-                    case MyCommon.UploadFileType.Invalid:
-                        ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                        ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                        ImagefilePathText.Text = "";
-                        break;
-                    case MyCommon.UploadFileType.Picture:
-                        Image img = null;
-                        using (FileStream fs = new FileStream(ImagefilePathText.Text, FileMode.Open, FileAccess.Read))
-                        {
-                            img = Image.FromStream(fs);
-                        }
-                        ImageSelectedPicture.Image = (new HttpVarious()).CheckValidImage(
-                                    img,
-                                    img.Width,
-                                    img.Height);
-                        ImageSelectedPicture.Tag = MyCommon.UploadFileType.Picture;
-                        break;
-                    case MyCommon.UploadFileType.MultiMedia:
-                        ImageSelectedPicture.Image = Properties.Resources.MultiMediaImage;
-                        ImageSelectedPicture.Tag = MyCommon.UploadFileType.MultiMedia;
-                        break;
-                    default:
-                        ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                        ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                        ImagefilePathText.Text = "";
-                        break;
-                }
-            }
-            catch (FileNotFoundException)
-            {
-                ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                ImagefilePathText.Text = "";
-                MessageBox.Show("File not found.");
-            }
-            catch (Exception)
-            {
-                ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                ImagefilePathText.Text = "";
-                MessageBox.Show("The type of this file is not image.");
-            }
+            this.Activate();
+            this.BringToFront();
+            ImageSelector.BeginSelection(((string[])e.Data.GetData(DataFormats.FileDrop, false))[0]);
+            StatusText.Focus();
         }
 
-        private void ImageSelection_KeyDown(object sender, KeyEventArgs e)
+        private void ImageSelector_BeginSelecting(object sender, EventArgs e)
         {
-            if (e.KeyCode == Keys.Escape)
-            {
-                ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                TimelinePanel.Visible = true;
-                TimelinePanel.Enabled = true;
-                ImageSelectionPanel.Visible = false;
-                ImageSelectionPanel.Enabled = false;
-                ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
-                ImagefilePathText.CausesValidation = true;
-            }
+            TimelinePanel.Visible = false;
+            TimelinePanel.Enabled = false;
         }
 
-        private void ImageSelection_KeyPress(object sender, KeyPressEventArgs e)
+        private void ImageSelector_EndSelecting(object sender, EventArgs e)
         {
-            if (Convert.ToInt32(e.KeyChar) == 0x1B)
-            {
-                ImagefilePathText.CausesValidation = false;
-                e.Handled = true;
-            }
+            TimelinePanel.Visible = true;
+            TimelinePanel.Enabled = true;
+            ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
         }
 
-        private void ImageSelection_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
+        private void ImageSelector_FilePickDialogOpening(object sender, EventArgs e)
         {
-            if (e.KeyCode == Keys.Escape)
-            {
-                ImagefilePathText.CausesValidation = false;
-            }
+            this.AllowDrop = false;
         }
 
-        private void SetImageServiceCombo()
+        private void ImageSelector_FilePickDialogClosed(object sender, EventArgs e)
         {
-            string svc = "";
-            if (ImageServiceCombo.SelectedIndex > -1) svc = ImageServiceCombo.SelectedItem.ToString();
-            ImageServiceCombo.Items.Clear();
-            
-            // Add service names to combobox
-            foreach (var key in pictureService.Keys)
-            {
-                ImageServiceCombo.Items.Add(key);
-            }
-
-            SelectImageServiceComboItem(svc);
+            this.AllowDrop = true;
         }
 
-        private void SelectImageServiceComboItem(string svc, int? index = null)
+        private void ImageSelector_SelectedServiceChanged(object sender, EventArgs e)
         {
-            int idx;
-            if (string.IsNullOrEmpty(svc))
+            if (ImageSelector.Visible)
             {
-                idx = index ?? 0;
-            }
-            else
-            {
-                idx = ImageServiceCombo.Items.IndexOf(svc);
-                if (idx == -1) idx = index ?? 0;
-            }
+                _modifySettingCommon = true;
+                SaveConfigsAll(true);
 
-            try
-            {
-                ImageServiceCombo.SelectedIndex = idx;
-            }
-            catch (ArgumentOutOfRangeException)
-            {
-                ImageServiceCombo.SelectedIndex = 0;
+                if (ImageSelector.ServiceName.Equals("Twitter"))
+                    this.StatusText_TextChanged(null, null);
             }
         }
 
-        private string ImageService
-        {
-            get { return ImageServiceCombo.SelectedItem.ToString(); }
-        }
-
-        private void ImageCancelButton_Click(object sender, EventArgs e)
-        {
-            ImagefilePathText.CausesValidation = false;
-            TimelinePanel.Visible = true;
-            TimelinePanel.Enabled = true;
-            ImageSelectionPanel.Visible = false;
-            ImageSelectionPanel.Enabled = false;
-            ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
-            ImagefilePathText.CausesValidation = true;
-        }
-
-        private void ImageServiceCombo_SelectedIndexChanged(object sender, EventArgs e)
+        private void ImageSelector_VisibleChanged(object sender, EventArgs e)
         {
-            if (ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
-            {
-                try
-                {
-                    FileInfo fi = new FileInfo(ImagefilePathText.Text.Trim());
-                    if (!this.pictureService[this.ImageService].CheckValidFilesize(fi.Extension, fi.Length))
-                    {
-                        ImagefilePathText.Text = "";
-                        ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
-                        ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
-                    }
-                }
-                catch (Exception)
-                {
-                }
-                _modifySettingCommon = true;
-                SaveConfigsAll(false);
-                if (this.ImageService == "Twitter")
-                {
-                    this.StatusText_TextChanged(null, null);
-                }
-            }
+            this.StatusText_TextChanged(null, null);
         }
 #endregion
 
@@ -12956,34 +12972,38 @@ namespace OpenTween
             OpenUriAsync(MyCommon.TwitterUrl + tw.Username);
         }
 
-        private void doTranslation(string str)
+        private async Task doTranslation(string str)
         {
-            Bing _bing = new Bing();
-            string buf = "";
-            if (string.IsNullOrEmpty(str)) return;
-            string srclng = "";
-            string dstlng = SettingDialog.TranslateLanguage;
-            string msg = "";
-            if (srclng != dstlng && _bing.Translate("", dstlng, str, out buf))
+            if (string.IsNullOrEmpty(str))
+                return;
+
+            var bing = new Bing(this.http);
+            try
             {
-                PostBrowser.DocumentText = createDetailHtml(buf);
+                var translatedText = await bing.TranslateAsync(str,
+                    langFrom: null,
+                    langTo: this.SettingDialog.TranslateLanguage);
+
+                this.PostBrowser.DocumentText = translatedText;
             }
-            else
+            catch (HttpRequestException e)
             {
-                if (msg.StartsWith("Err:"))
-                    StatusLabel.Text = msg;
+                this.StatusLabel.Text = "Err:" + e.Message;
             }
         }
 
-        private void TranslationToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void TranslationToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (!this.ExistCurrentPost) return;
-            doTranslation(_curPost.TextFromApi);
+            if (!this.ExistCurrentPost)
+                return;
+
+            await this.doTranslation(this._curPost.TextFromApi);
         }
 
-        private void SelectionTranslationToolStripMenuItem_Click(object sender, EventArgs e)
+        private async void SelectionTranslationToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            doTranslation(WebBrowser_GetSelectionText(ref PostBrowser));
+            var text = this.WebBrowser_GetSelectionText(ref this.PostBrowser);
+            await this.doTranslation(text);
         }
 
         private bool ExistCurrentPost
@@ -13105,11 +13125,6 @@ namespace OpenTween
             OpenUserAppointUrl();
         }
 
-        private void ImageSelectionPanel_VisibleChanged(object sender, EventArgs e)
-        {
-            this.StatusText_TextChanged(null, null);
-        }
-
         private void SourceCopyMenuItem_Click(object sender, EventArgs e)
         {
             string selText = SourceLinkLabel.Text;
@@ -13181,6 +13196,12 @@ namespace OpenTween
         private void tweetThumbnail1_ThumbnailLoading(object sender, EventArgs e)
         {
             this.SplitContainer3.Panel2Collapsed = false;
+
+            // PreviewDistance が起動のたびに広がっていく問題の回避策
+            // FixedPanel が Panel2 に設定された状態で Panel2 を開くと、初回だけ SplitterDistance が再計算されておかしくなるため、
+            // None で開いた後に設定するようにする
+            if (this.SplitContainer3.FixedPanel == FixedPanel.None)
+                this.SplitContainer3.FixedPanel = FixedPanel.Panel2;
         }
 
         private void tweetThumbnail1_ThumbnailDoubleClick(object sender, ThumbnailDoubleClickEventArgs e)
@@ -13212,5 +13233,73 @@ namespace OpenTween
                 e.SuppressKeyPress = true;
             }
         }
+
+        private void ContextMenuColumnHeader_Opening(object sender, CancelEventArgs e)
+        {
+            this.IconSizeNoneToolStripMenuItem.Checked = SettingDialog.IconSz == MyCommon.IconSizes.IconNone;
+            this.IconSize16ToolStripMenuItem.Checked = SettingDialog.IconSz == MyCommon.IconSizes.Icon16;
+            this.IconSize24ToolStripMenuItem.Checked = SettingDialog.IconSz == MyCommon.IconSizes.Icon24;
+            this.IconSize48ToolStripMenuItem.Checked = SettingDialog.IconSz == MyCommon.IconSizes.Icon48;
+            this.IconSize48_2ToolStripMenuItem.Checked = SettingDialog.IconSz == MyCommon.IconSizes.Icon48_2;
+
+            this.LockListSortOrderToolStripMenuItem.Checked = SettingDialog.SortOrderLock;
+        }
+
+        private void IconSizeNoneToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ChangeListViewIconSize(MyCommon.IconSizes.IconNone);
+        }
+
+        private void IconSize16ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ChangeListViewIconSize(MyCommon.IconSizes.Icon16);
+        }
+
+        private void IconSize24ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ChangeListViewIconSize(MyCommon.IconSizes.Icon24);
+        }
+
+        private void IconSize48ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ChangeListViewIconSize(MyCommon.IconSizes.Icon48);
+        }
+
+        private void IconSize48_2ToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ChangeListViewIconSize(MyCommon.IconSizes.Icon48_2);
+        }
+
+        private void ChangeListViewIconSize(MyCommon.IconSizes iconSize)
+        {
+            if (SettingDialog.IconSz == iconSize) return;
+
+            var oldIconCol = _iconCol;
+
+            SettingDialog.IconSz = iconSize;
+            ApplyListViewIconSize(iconSize);
+
+            if (_iconCol != oldIconCol)
+            {
+                foreach (TabPage tp in ListTab.TabPages)
+                {
+                    ResetColumns((DetailsListView)tp.Tag);
+                }
+            }
+
+            if (_curList != null) _curList.Refresh();
+
+            _modifySettingCommon = true;
+        }
+
+        private void LockListSortToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            var state = this.LockListSortOrderToolStripMenuItem.Checked;
+            if (SettingDialog.SortOrderLock == state) return;
+
+            SettingDialog.SortOrderLock = state;
+
+            _modifySettingCommon = true;
+        }
     }
 }