OSDN Git Service

ミュート中のユーザーの公式RTが非表示にならない問題を修正 (thx @KishSoup!)
[opentween/open-tween.git] / OpenTween / StatusDictionary.cs
index 3c04689..5560bd8 100644 (file)
@@ -5,6 +5,7 @@
 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
 //           (c) 2011      Egtra (@egtra) <http://dev.activebasic.com/egtra/>
+//           (c) 2012      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
 // All rights reserved.
 //
 // This file is part of OpenTween.
@@ -36,47 +37,61 @@ using System.Xml.Serialization;
 
 namespace OpenTween
 {
-    public sealed class PostClass : ICloneable
+    public class PostClass : ICloneable
     {
         public class StatusGeo
         {
             public double Lng { get; set; }
             public double Lat { get; set; }
+
+            public override bool Equals(object obj)
+            {
+                var geo = obj as StatusGeo;
+                return geo != null && geo.Lng == this.Lng && geo.Lat == this.Lat;
+            }
+
+            public override int GetHashCode()
+            {
+                return this.Lng.GetHashCode() ^ this.Lat.GetHashCode();
+            }
         }
-        private string _Nick;
-        private string _textFromApi;
-        private string _ImageUrl;
-        private string _screenName;
-        private DateTime _createdAt;
-        private long _statusId;
+        public string Nickname { get; set; }
+        public string TextFromApi { get; set; }
+        public string ImageUrl { get; set; }
+        public string ScreenName { get; set; }
+        public DateTime CreatedAt { get; set; }
+        public long StatusId { get; set; }
         private bool _IsFav;
-        private string _text;
-        private bool _IsRead;
-        private bool _IsReply;
-        private bool _IsExcludeReply;
+        public string Text { get; set; }
+        public bool IsRead { get; set; }
+        public bool IsReply { get; set; }
+        public bool IsExcludeReply { get; set; }
         private bool _IsProtect;
-        private bool _IsOWL;
+        public bool IsOwl { get; set; }
         private bool _IsMark;
-        private string _InReplyToUser;
-        private long _InReplyToStatusId;
-        private string _Source;
-        private string _SourceHtml;
-        private List<string> _ReplyToList = new List<string>();
-        private bool _IsMe;
-        private bool _IsDm;
-        private States _states = States.None;
-        private long _UserId;
-        private bool _FilterHit;
-        private string _RetweetedBy = "";
-        private long _RetweetedId = 0;
-        private string _SearchTabName = "";
+        public string InReplyToUser { get; set; }
+        private long? _InReplyToStatusId;
+        public string Source { get; set; }
+        public string SourceHtml { get; set; }
+        public List<string> ReplyToList { get; set; }
+        public bool IsMe { get; set; }
+        public bool IsDm { get; set; }
+        public long UserId { get; set; }
+        public bool FilterHit { get; set; }
+        public string RetweetedBy { get; set; }
+        public long? RetweetedId { get; set; }
         private bool _IsDeleted = false;
-        private long _InReplyToUserId = 0;
         private StatusGeo _postGeo = new StatusGeo();
         public int RetweetedCount { get; set; }
-        public long RetweetedByUserId { get; set; }
+        public long? RetweetedByUserId { get; set; }
+        public long? InReplyToUserId { get; set; }
         public Dictionary<string, string> Media { get; set; }
 
+        public string RelTabName { get; set; }
+        public int FavoritedCount { get; set; }
+
+        private States _states = States.None;
+
         [Flags]
         private enum States
         {
@@ -102,7 +117,7 @@ namespace OpenTween
                 bool IsOwl,
                 bool IsMark,
                 string InReplyToUser,
-                long InReplyToStatusId,
+                long? InReplyToStatusId,
                 string Source,
                 string SourceHtml,
                 List<string> ReplyToList,
@@ -111,177 +126,83 @@ namespace OpenTween
                 long userId,
                 bool FilterHit,
                 string RetweetedBy,
-                long RetweetedId,
+                long? RetweetedId,
                 StatusGeo Geo)
             : this()
         {
-            _Nick = Nickname;
-            _textFromApi = textFromApi;
-            _ImageUrl = ImageUrl;
-            _screenName = screenName;
-            _createdAt = createdAt;
-            _statusId = statusId;
+            this.Nickname = Nickname;
+            this.TextFromApi = textFromApi;
+            this.ImageUrl = ImageUrl;
+            this.ScreenName = screenName;
+            this.CreatedAt = createdAt;
+            this.StatusId = statusId;
             _IsFav = IsFav;
-            _text = text;
-            _IsRead = IsRead;
-            _IsReply = IsReply;
-            _IsExcludeReply = IsExcludeReply;
+            this.Text = text;
+            this.IsRead = IsRead;
+            this.IsReply = IsReply;
+            this.IsExcludeReply = IsExcludeReply;
             _IsProtect = IsProtect;
-            _IsOWL = IsOwl;
+            this.IsOwl = IsOwl;
             _IsMark = IsMark;
-            _InReplyToUser = InReplyToUser;
+            this.InReplyToUser = InReplyToUser;
             _InReplyToStatusId = InReplyToStatusId;
-            _Source = Source;
-            _SourceHtml = SourceHtml;
-            _ReplyToList = ReplyToList;
-            _IsMe = IsMe;
-            _IsDm = IsDm;
-            _UserId = userId;
-            _FilterHit = FilterHit;
-            _RetweetedBy = RetweetedBy;
-            _RetweetedId = RetweetedId;
+            this.Source = Source;
+            this.SourceHtml = SourceHtml;
+            this.ReplyToList = ReplyToList;
+            this.IsMe = IsMe;
+            this.IsDm = IsDm;
+            this.UserId = userId;
+            this.FilterHit = FilterHit;
+            this.RetweetedBy = RetweetedBy;
+            this.RetweetedId = RetweetedId;
             _postGeo = Geo;
         }
 
         public PostClass()
         {
-            RetweetedCount = 0;
-            RetweetedByUserId = 0;
+            RetweetedBy = "";
+            RelTabName = "";
             Media = new Dictionary<string, string>();
+            ReplyToList = new List<string>();
         }
 
-        public string Nickname
-        {
-            get
-            {
-                return _Nick;
-            }
-            set
-            {
-                _Nick = value;
-            }
-        }
-        public string TextFromApi
-        {
-            get
-            {
-                return _textFromApi;
-            }
-            set
-            {
-                _textFromApi = value;
-            }
-        }
-        public string ImageUrl
-        {
-            get
-            {
-                return _ImageUrl;
-            }
-            set
-            {
-                _ImageUrl = value;
-            }
-        }
-        public string ScreenName
-        {
-            get
-            {
-                return _screenName;
-            }
-            set
-            {
-                _screenName = value;
-            }
-        }
-        public DateTime CreatedAt
-        {
-            get
-            {
-                return _createdAt;
-            }
-            set
-            {
-                _createdAt = value;
-            }
-        }
-        public long StatusId
+        public string TextSingleLine
         {
             get
             {
-                return _statusId;
-            }
-            set
-            {
-                _statusId = value;
+                return this.TextFromApi == null ? null : this.TextFromApi.Replace("\n", " ");
             }
         }
+
         public bool IsFav
         {
             get
             {
-                if (this.RetweetedId > 0 && TabInformations.GetInstance().RetweetSource(this.RetweetedId) != null)
-                {
-                    return TabInformations.GetInstance().RetweetSource(this.RetweetedId).IsFav;
-                }
-                else
+                if (this.RetweetedId != null)
                 {
-                    return _IsFav;
+                    var post = this.GetRetweetSource(this.RetweetedId.Value);
+                    if (post != null)
+                    {
+                        return post.IsFav;
+                    }
                 }
+
+                return _IsFav;
             }
             set
             {
                 _IsFav = value;
-                if (this.RetweetedId > 0 && TabInformations.GetInstance().RetweetSource(this.RetweetedId) != null)
+                if (this.RetweetedId != null)
                 {
-                    TabInformations.GetInstance().RetweetSource(this.RetweetedId).IsFav = value;
+                    var post = this.GetRetweetSource(this.RetweetedId.Value);
+                    if (post != null)
+                    {
+                        post.IsFav = value;
+                    }
                 }
             }
         }
-        public string Text
-        {
-            get
-            {
-                return _text;
-            }
-            set
-            {
-                _text = value;
-            }
-        }
-        public bool IsRead
-        {
-            get
-            {
-                return _IsRead;
-            }
-            set
-            {
-                _IsRead = value;
-            }
-        }
-        public bool IsReply
-        {
-            get
-            {
-                return _IsReply;
-            }
-            set
-            {
-                _IsReply = value;
-            }
-        }
-        public bool IsExcludeReply
-        {
-            get
-            {
-                return _IsExcludeReply;
-            }
-            set
-            {
-                _IsExcludeReply = value;
-            }
-        }
+
         public bool IsProtect
         {
             get
@@ -301,17 +222,6 @@ namespace OpenTween
                 _IsProtect = value;
             }
         }
-        public bool IsOwl
-        {
-            get
-            {
-                return _IsOWL;
-            }
-            set
-            {
-                _IsOWL = value;
-            }
-        }
         public bool IsMark
         {
             get
@@ -331,18 +241,7 @@ namespace OpenTween
                 _IsMark = value;
             }
         }
-        public string InReplyToUser
-        {
-            get
-            {
-                return _InReplyToUser;
-            }
-            set
-            {
-                _InReplyToUser = value;
-            }
-        }
-        public long InReplyToStatusId
+        public long? InReplyToStatusId
         {
             get
             {
@@ -350,7 +249,7 @@ namespace OpenTween
             }
             set
             {
-                if (value > 0)
+                if (value != null)
                 {
                     _states = _states | States.Reply;
                 }
@@ -362,134 +261,6 @@ namespace OpenTween
             }
         }
 
-        public long InReplyToUserId
-        {
-            get
-            {
-                return _InReplyToUserId;
-            }
-            set
-            {
-                _InReplyToUserId = value;
-            }
-        }
-        public string Source
-        {
-            get
-            {
-                return _Source;
-            }
-            set
-            {
-                _Source = value;
-            }
-        }
-        public string SourceHtml
-        {
-            get
-            {
-                return _SourceHtml;
-            }
-            set
-            {
-                _SourceHtml = value;
-            }
-        }
-        public List<string> ReplyToList
-        {
-            get
-            {
-                return _ReplyToList;
-            }
-            set
-            {
-                _ReplyToList = value;
-            }
-        }
-        public bool IsMe
-        {
-            get
-            {
-                return _IsMe;
-            }
-            set
-            {
-                _IsMe = value;
-            }
-        }
-        public bool IsDm
-        {
-            get
-            {
-                return _IsDm;
-            }
-            set
-            {
-                _IsDm = value;
-            }
-        }
-        //public readonly int StatusIndex
-        //{
-        //    get
-        //    {
-        //        return _statuses;
-        //    }
-        //}
-        public long UserId
-        {
-            get
-            {
-                return _UserId;
-            }
-            set
-            {
-                _UserId = value;
-            }
-        }
-        public bool FilterHit
-        {
-            get
-            {
-                return _FilterHit;
-            }
-            set
-            {
-                _FilterHit = value;
-            }
-        }
-        public string RetweetedBy
-        {
-            get
-            {
-                return _RetweetedBy;
-            }
-            set
-            {
-                _RetweetedBy = value;
-            }
-        }
-        public long RetweetedId
-        {
-            get
-            {
-                return _RetweetedId;
-            }
-            set
-            {
-                _RetweetedId = value;
-            }
-        }
-        public string RelTabName
-        {
-            get
-            {
-                return _SearchTabName;
-            }
-            set
-            {
-                _SearchTabName = value;
-            }
-        }
         public bool IsDeleted
         {
             get
@@ -500,9 +271,9 @@ namespace OpenTween
             {
                 if (value)
                 {
-                    this.InReplyToStatusId = 0;
+                    this.InReplyToStatusId = null;
                     this.InReplyToUser = "";
-                    this.InReplyToUserId = 0;
+                    this.InReplyToUserId = null;
                     this.IsReply = false;
                     this.ReplyToList = new List<string>();
                     this._states = States.None;
@@ -511,8 +282,6 @@ namespace OpenTween
             }
         }
 
-        public int FavoritedCount { get; set; }
-
         public StatusGeo PostGeo
         {
             get
@@ -541,11 +310,20 @@ namespace OpenTween
             }
         }
 
+        protected virtual PostClass GetRetweetSource(long statusId)
+        {
+            return TabInformations.GetInstance().RetweetSource(statusId);
+        }
+
+        [Obsolete("Use PostClass.Clone() instead.")]
         public PostClass Copy()
         {
-            var post = (PostClass)((ICloneable)this).Clone();
-            post.ReplyToList = new List<string>(this.ReplyToList);
-            return post;
+            return this.Clone();
+        }
+
+        public PostClass Clone()
+        {
+            return (PostClass)((ICloneable)this).Clone();
         }
 
         public override bool Equals(object obj)
@@ -575,7 +353,7 @@ namespace OpenTween
                     (this.InReplyToStatusId == other.InReplyToStatusId) &&
                     (this.Source == other.Source) &&
                     (this.SourceHtml == other.SourceHtml) &&
-                    (this.ReplyToList.Equals(other.ReplyToList)) &&
+                    (this.ReplyToList.SequenceEqual(other.ReplyToList)) &&
                     (this.IsMe == other.IsMe) &&
                     (this.IsDm == other.IsDm) &&
                     (this.UserId == other.UserId) &&
@@ -587,10 +365,21 @@ namespace OpenTween
                     (this.InReplyToUserId == other.InReplyToUserId);
 
         }
+
+        public override int GetHashCode()
+        {
+            return this.StatusId.GetHashCode();
+        }
+
 #region "IClonable.Clone"
         object ICloneable.Clone()
         {
-            return this.MemberwiseClone();
+            var clone = (PostClass)this.MemberwiseClone();
+            clone.ReplyToList = new List<string>(this.ReplyToList);
+            clone.PostGeo = new StatusGeo { Lng = this.PostGeo.Lng, Lat = this.PostGeo.Lat };
+            clone.Media = new Dictionary<string, string>(this.Media);
+
+            return clone;
         }
 #endregion
     }
@@ -609,11 +398,12 @@ namespace OpenTween
 
         private class ScrubGeoInfo
         {
-            public long UserId;
-            public long UpToStatusId;
+            public long UserId = 0;
+            public long UpToStatusId = 0;
         }
 
         public List<long> BlockIds = new List<long>();
+        public List<long> MuteUserIds = new List<long>();
 
         //発言の追加
         //AddPost(複数回) -> DistributePosts          -> SubmitUpdate
@@ -633,7 +423,6 @@ namespace OpenTween
         private TabInformations()
         {
             _sorter = new IdComparerClass();
-            RemovedTab = _removedTab;
         }
 
         public static TabInformations GetInstance()
@@ -670,9 +459,10 @@ namespace OpenTween
         public bool AddTab(string TabName, MyCommon.TabUsageType TabType, ListElement List)
         {
             if (_tabs.ContainsKey(TabName)) return false;
-            _tabs.Add(TabName, new TabClass(TabName, TabType, List));
-            _tabs[TabName].Sorter.Mode = _sorter.Mode;
-            _tabs[TabName].Sorter.Order = _sorter.Order;
+            var tb = new TabClass(TabName, TabType, List);
+            _tabs.Add(TabName, tb);
+            tb.Sorter.Mode = _sorter.Mode;
+            tb.Sorter.Order = _sorter.Order;
             return true;
         }
 
@@ -686,21 +476,22 @@ namespace OpenTween
             lock (LockObj)
             {
                 if (IsDefaultTab(TabName)) return; //念のため
-                if (!_tabs[TabName].IsInnerStorageTabType)
+                var tb = _tabs[TabName];
+                if (!tb.IsInnerStorageTabType)
                 {
                     var homeTab = GetTabByType(MyCommon.TabUsageType.Home);
-                    var dmName = GetTabByType(MyCommon.TabUsageType.DirectMessage).TabName;
+                    var dmTab = GetTabByType(MyCommon.TabUsageType.DirectMessage);
 
-                    for (int idx = 0; idx < _tabs[TabName].AllCount; ++idx)
+                    for (int idx = 0; idx < tb.AllCount; ++idx)
                     {
                         var exist = false;
-                        var Id = _tabs[TabName].GetId(idx);
+                        var Id = tb.GetId(idx);
                         if (Id < 0) continue;
-                        foreach (var key in _tabs.Keys)
+                        foreach (var tab in _tabs.Values)
                         {
-                            if (key != TabName && key != dmName)
+                            if (tab != tb && tab != dmTab)
                             {
-                                if (_tabs[key].Contains(Id))
+                                if (tab.Contains(Id))
                                 {
                                     exist = true;
                                     break;
@@ -710,12 +501,15 @@ namespace OpenTween
                         if (!exist) homeTab.Add(Id, _statuses[Id].IsRead, false);
                     }
                 }
-                _removedTab.Push(_tabs[TabName]);
+                _removedTab.Push(tb);
                 _tabs.Remove(TabName);
             }
         }
 
-        public Stack<TabClass> RemovedTab;
+        public Stack<TabClass> RemovedTab
+        {
+            get { return _removedTab; }
+        }
 
         public bool ContainsTab(string TabText)
         {
@@ -727,6 +521,42 @@ namespace OpenTween
             return _tabs.ContainsValue(ts);
         }
 
+        /// <summary>
+        /// 指定されたタブ名を元に、既存のタブ名との重複を避けた名前を生成します
+        /// </summary>
+        /// <param name="baseTabName">作成したいタブ名</param>
+        /// <returns>生成されたタブ名</returns>
+        /// <exception cref="TabException">タブ名の生成を 100 回試行して失敗した場合</exception>
+        public string MakeTabName(string baseTabName)
+        {
+            return this.MakeTabName(baseTabName, 100);
+        }
+
+        /// <summary>
+        /// 指定されたタブ名を元に、既存のタブ名との重複を避けた名前を生成します
+        /// </summary>
+        /// <param name="baseTabName">作成したいタブ名</param>
+        /// <param name="retryCount">重複を避けたタブ名を生成する試行回数</param>
+        /// <returns>生成されたタブ名</returns>
+        /// <exception cref="TabException">retryCount で指定された回数だけタブ名の生成を試行して失敗した場合</exception>
+        public string MakeTabName(string baseTabName, int retryCount)
+        {
+            if (!this.ContainsTab(baseTabName))
+                return baseTabName;
+
+            foreach (var i in Enumerable.Range(2, retryCount - 1))
+            {
+                var tabName = baseTabName + i;
+                if (!this.ContainsTab(tabName))
+                {
+                    return tabName;
+                }
+            }
+
+            var message = string.Format(Properties.Resources.TabNameDuplicate_Text, baseTabName);
+            throw new TabException(message);
+        }
+
         public Dictionary<string, TabClass> Tabs
         {
             get
@@ -749,9 +579,9 @@ namespace OpenTween
 
         public void SortPosts()
         {
-            foreach (var key in _tabs.Keys)
+            foreach (var tab in _tabs.Values)
             {
-                _tabs[key].Sort();
+                tab.Sort();
             }
         }
 
@@ -764,9 +594,9 @@ namespace OpenTween
             set
             {
                 _sorter.Order = value;
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    _tabs[key].Sorter.Order = value;
+                    tab.Sorter.Order = value;
                 }
             }
         }
@@ -780,9 +610,9 @@ namespace OpenTween
             set
             {
                 _sorter.Mode = value;
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    _tabs[key].Sorter.Mode = value;
+                    tab.Sorter.Mode = value;
                 }
             }
         }
@@ -799,19 +629,19 @@ namespace OpenTween
                 {
                     _sorter.Order = SortOrder.Ascending;
                 }
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    _tabs[key].Sorter.Order = _sorter.Order;
+                    tab.Sorter.Order = _sorter.Order;
                 }
             }
             else
             {
                 _sorter.Mode = SortMode;
                 _sorter.Order = SortOrder.Ascending;
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    _tabs[key].Sorter.Mode = SortMode;
-                    _tabs[key].Sorter.Order = SortOrder.Ascending;
+                    tab.Sorter.Mode = SortMode;
+                    tab.Sorter.Order = SortOrder.Ascending;
                 }
             }
             this.SortPosts();
@@ -834,26 +664,22 @@ namespace OpenTween
     //    }
         public PostClass RetweetSource(long Id)
         {
-            if (_retweets.ContainsKey(Id))
-            {
-                return _retweets[Id];
-            }
-            else
-            {
-                return null;
-            }
+            PostClass status;
+            return _retweets.TryGetValue(Id, out status)
+                ? status
+                : null;
         }
 
         public void RemoveFavPost(long Id)
         {
             lock (LockObj)
             {
-                PostClass post = null;
+                PostClass post;
                 var tab = this.GetTabByType(MyCommon.TabUsageType.Favorites);
                 var tn = tab.TabName;
-                if (_statuses.ContainsKey(Id))
+
+                if (_statuses.TryGetValue(Id, out post))
                 {
-                    post = _statuses[Id];
                     //指定タブから該当ID削除
                     var tType = tab.TabType;
                     if (tab.Contains(Id))
@@ -869,7 +695,7 @@ namespace OpenTween
                         tab.Remove(Id);
                     }
                     //FavタブからRetweet発言を削除する場合は、他の同一参照Retweetも削除
-                    if (tType == MyCommon.TabUsageType.Favorites && post.RetweetedId > 0)
+                    if (tType == MyCommon.TabUsageType.Favorites && post.RetweetedId != null)
                     {
                         for (int i = 0; i < tab.AllCount; i++)
                         {
@@ -882,7 +708,7 @@ namespace OpenTween
                             {
                                 break;
                             }
-                            if (rPost.RetweetedId > 0 && rPost.RetweetedId == post.RetweetedId)
+                            if (rPost.RetweetedId != null && rPost.RetweetedId == post.RetweetedId)
                             {
                                 if (tab.UnreadManage && !rPost.IsRead)    //未読管理
                                 {
@@ -962,35 +788,17 @@ namespace OpenTween
         {
             lock (LockObj)
             {
-                PostClass post = null;
-                //if (_statuses.ContainsKey(Id))
                 //各タブから該当ID削除
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    var tab = _tabs[key];
                     if (tab.Contains(Id))
                     {
-                        if (!tab.IsInnerStorageTabType)
+                        if (tab.UnreadManage && !tab.Posts[Id].IsRead)    //未読管理
                         {
-                            post = _statuses[Id];
-                            if (tab.UnreadManage && !post.IsRead)    //未読管理
+                            lock (LockUnread)
                             {
-                                lock (LockUnread)
-                                {
-                                    tab.UnreadCount--;
-                                    this.SetNextUnreadId(Id, tab);
-                                }
-                            }
-                        }
-                        else //未読数がずれる可能性があるためtab.Postsの未読も確認する
-                        {
-                            if (tab.UnreadManage && !tab.Posts[Id].IsRead)    //未読管理
-                            {
-                                lock (LockUnread)
-                                {
-                                    tab.UnreadCount--;
-                                    this.SetNextUnreadId(Id, tab);
-                                }
+                                tab.UnreadCount--;
+                                this.SetNextUnreadId(Id, tab);
                             }
                         }
                         tab.Remove(Id);
@@ -1004,10 +812,9 @@ namespace OpenTween
         {
             lock (LockObj)
             {
-                PostClass post = null;
-                if (_statuses.ContainsKey(Id))
+                PostClass post;
+                if (_statuses.TryGetValue(Id, out post))
                 {
-                    post = _statuses[Id];
                     post.IsDeleted = true;
                 }
                 foreach (var tb in this.GetTabsInnerStorageType())
@@ -1029,15 +836,7 @@ namespace OpenTween
                 tb.UnreadCount > 0)
             {
                 //未読アイテムへ
-                bool isRead;
-                if (!tb.IsInnerStorageTabType)
-                {
-                    isRead = _statuses[tb.OldestUnreadId].IsRead;
-                }
-                else
-                {
-                    isRead = tb.Posts[tb.OldestUnreadId].IsRead;
-                }
+                bool isRead = tb.Posts[tb.OldestUnreadId].IsRead;
                 if (isRead)
                 {
                     //状態不整合(最古未読IDが実は既読)
@@ -1089,18 +888,12 @@ namespace OpenTween
             //最古未読が設定されていて、既読の場合(1発言以上存在)
             try
             {
-                Dictionary<long, PostClass> posts;
-                if (!Tab.IsInnerStorageTabType)
-                {
-                    posts = _statuses;
-                }
-                else
-                {
-                    posts = Tab.Posts;
-                }
+                Dictionary<long, PostClass> posts = Tab.Posts;
+
+                PostClass oldestUnreadPost;
                 if (Tab.OldestUnreadId > -1 &&
-                    posts.ContainsKey(Tab.OldestUnreadId) &&
-                    posts[Tab.OldestUnreadId].IsRead &&
+                    posts.TryGetValue(Tab.OldestUnreadId, out oldestUnreadPost) &&
+                    oldestUnreadPost.IsRead &&
                     _sorter.Mode == IdComparerClass.ComparerMode.Id)     //次の未読探索
                 {
                     if (Tab.UnreadCount == 0)
@@ -1116,30 +909,17 @@ namespace OpenTween
                         {
                             //続きから探索
                             FindUnreadId(idx, Tab);
+                            return;
                         }
-                        else
-                        {
-                            //頭から探索
-                            FindUnreadId(-1, Tab);
-                        }
-                    }
-                    else
-                    {
-                        //頭から探索
-                        FindUnreadId(-1, Tab);
                     }
                 }
-                else
-                {
-                    //頭から探索
-                    FindUnreadId(-1, Tab);
-                }
             }
             catch (KeyNotFoundException)
             {
-                //頭から探索
-                FindUnreadId(-1, Tab);
             }
+
+            //頭から探索
+            FindUnreadId(-1, Tab);
         }
 
         private void FindUnreadId(int StartIdx, TabClass Tab)
@@ -1183,17 +963,9 @@ namespace OpenTween
                 stp = -1;
             }
 
-            Dictionary<long, PostClass> posts;
-            if (!Tab.IsInnerStorageTabType)
-            {
-                posts = _statuses;
-            }
-            else
-            {
-                posts = Tab.Posts;
-            }
+            Dictionary<long, PostClass> posts = Tab.Posts;
 
-            for (int i = StartIdx; i < toIdx; i+= stp)
+            for (int i = StartIdx; ; i+= stp)
             {
                 var id = Tab.GetId(i);
                 if (id > -1 && !posts[id].IsRead)
@@ -1201,6 +973,8 @@ namespace OpenTween
                     Tab.OldestUnreadId = id;
                     break;
                 }
+
+                if (i == toIdx) break;
             }
         }
 
@@ -1311,27 +1085,27 @@ namespace OpenTween
                 var mv = false;   //移動フラグ(Recent追加有無)
                 var rslt = MyCommon.HITRESULT.None;
                 post.IsExcludeReply = false;
-                foreach (var tn in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    rslt = _tabs[tn].AddFiltered(post);
+                    rslt = tab.AddFiltered(post);
                     if (rslt != MyCommon.HITRESULT.None && rslt != MyCommon.HITRESULT.Exclude)
                     {
                         if (rslt == MyCommon.HITRESULT.CopyAndMark) post.IsMark = true; //マークあり
-                        if (rslt == MyCommon.HITRESULT.Move)
+                        else if (rslt == MyCommon.HITRESULT.Move)
                         {
                             mv = true; //移動
                             post.IsMark = false;
                         }
-                        if (_tabs[tn].Notify) add = true; //通知あり
-                        if (_tabs[tn].SoundFile != "" && _soundFile == "")
+                        if (tab.Notify) add = true; //通知あり
+                        if (!string.IsNullOrEmpty(tab.SoundFile) && string.IsNullOrEmpty(_soundFile))
                         {
-                            _soundFile = _tabs[tn].SoundFile; //wavファイル(未設定の場合のみ)
+                            _soundFile = tab.SoundFile; //wavファイル(未設定の場合のみ)
                         }
                         post.FilterHit = true;
                     }
                     else
                     {
-                        if (rslt == MyCommon.HITRESULT.Exclude && _tabs[tn].TabType == MyCommon.TabUsageType.Mentions)
+                        if (rslt == MyCommon.HITRESULT.Exclude && tab.TabType == MyCommon.TabUsageType.Mentions)
                         {
                             post.IsExcludeReply = true;
                         }
@@ -1341,13 +1115,13 @@ namespace OpenTween
                 if (!mv)  //移動されなかったらRecentに追加
                 {
                     homeTab.Add(post.StatusId, post.IsRead, true);
-                    if (homeTab.SoundFile != "" && _soundFile == "") _soundFile = homeTab.SoundFile;
+                    if (!string.IsNullOrEmpty(homeTab.SoundFile) && string.IsNullOrEmpty(_soundFile)) _soundFile = homeTab.SoundFile;
                     if (homeTab.Notify) add = true;
                 }
                 if (post.IsReply && !post.IsExcludeReply)    //除外ルール適用のないReplyならReplyタブに追加
                 {
                     replyTab.Add(post.StatusId, post.IsRead, true);
-                    if (replyTab.SoundFile != "") _soundFile = replyTab.SoundFile;
+                    if (!string.IsNullOrEmpty(replyTab.SoundFile)) _soundFile = replyTab.SoundFile;
                     if (replyTab.Notify) add = true;
                 }
                 if (post.IsFav)    //Fav済み発言だったらFavoritesタブに追加
@@ -1388,9 +1162,9 @@ namespace OpenTween
                                 }
                                 if (!exist) _notifyPosts.Add(post);
                             }
-                            if (tb.SoundFile != "")
+                            if (!string.IsNullOrEmpty(tb.SoundFile))
                             {
-                                if (tb.TabType == MyCommon.TabUsageType.DirectMessage || _soundFile == "")
+                                if (tb.TabType == MyCommon.TabUsageType.DirectMessage || string.IsNullOrEmpty(_soundFile))
                                 {
                                     _soundFile = tb.SoundFile;
                                 }
@@ -1405,17 +1179,18 @@ namespace OpenTween
         {
             lock (LockObj)
             {
-                if (Item.RelTabName == "")
+                if (string.IsNullOrEmpty(Item.RelTabName))
                 {
                     if (!Item.IsDm)
                     {
-                        if (_statuses.ContainsKey(Item.StatusId))
+                        PostClass status;
+                        if (_statuses.TryGetValue(Item.StatusId, out status))
                         {
                             if (Item.IsFav)
                             {
-                                if (Item.RetweetedId == 0)
+                                if (Item.RetweetedId == null)
                                 {
-                                    _statuses[Item.StatusId].IsFav = true;
+                                    status.IsFav = true;
                                 }
                                 else
                                 {
@@ -1429,16 +1204,23 @@ namespace OpenTween
                         }
                         else
                         {
-                            if (Item.IsFav && Item.RetweetedId > 0) Item.IsFav = false;
+                            if (Item.IsFav && Item.RetweetedId != null) Item.IsFav = false;
                             //既に持っている公式RTは捨てる
                             if (AppendSettingDialog.Instance.HideDuplicatedRetweets &&
                                 !Item.IsMe &&
-                                this._retweets.ContainsKey(Item.RetweetedId) &&
-                                this._retweets[Item.RetweetedId].RetweetedCount > 0) return;
-                            if (BlockIds.Contains(Item.UserId)) return;
+                                Item.RetweetedId != null &&
+                                this._retweets.TryGetValue(Item.RetweetedId.Value, out status) &&
+                                status.RetweetedCount > 0) return;
+
+                            if (BlockIds.Contains(Item.UserId))
+                                return;
+
+                            if (this.IsMuted(Item))
+                                return;
+
                             _statuses.Add(Item.StatusId, Item);
                         }
-                        if (Item.RetweetedId > 0)
+                        if (Item.RetweetedId != null)
                         {
                             this.AddRetweet(Item);
                         }
@@ -1461,14 +1243,7 @@ namespace OpenTween
                 {
                     //公式検索、リスト、関連発言の場合
                     TabClass tb;
-                    if (this.Tabs.ContainsKey(Item.RelTabName))
-                    {
-                        tb = this.Tabs[Item.RelTabName];
-                    }
-                    else
-                    {
-                        return;
-                    }
+                    this.Tabs.TryGetValue(Item.RelTabName, out tb);
                     if (tb == null) return;
                     if (tb.Contains(Item.StatusId)) return;
                     //tb.Add(Item.StatusId, Item.IsRead, true);
@@ -1477,21 +1252,40 @@ namespace OpenTween
             }
         }
 
+        private bool IsMuted(PostClass post)
+        {
+            // Recent以外のツイートと、リプライはミュート対象外
+            // 参照: https://support.twitter.com/articles/20171399-muting-users-on-twitter
+            if (string.IsNullOrEmpty(post.RelTabName) || post.IsReply)
+                return false;
+
+            if (this.MuteUserIds.Contains(post.UserId))
+                return true;
+
+            if (post.RetweetedByUserId != null && this.MuteUserIds.Contains(post.RetweetedByUserId.Value))
+                return true;
+
+            return false;
+        }
+
         private void AddRetweet(PostClass item)
         {
+            var retweetedId = item.RetweetedId.Value;
+
             //true:追加、False:保持済み
-            if (_retweets.ContainsKey(item.RetweetedId))
+            PostClass status;
+            if (_retweets.TryGetValue(retweetedId, out status))
             {
-                _retweets[item.RetweetedId].RetweetedCount++;
-                if (_retweets[item.RetweetedId].RetweetedCount > 10)
+                status.RetweetedCount++;
+                if (status.RetweetedCount > 10)
                 {
-                    _retweets[item.RetweetedId].RetweetedCount = 0;
+                    status.RetweetedCount = 0;
                 }
                 return;
             }
 
             _retweets.Add(
-                        item.RetweetedId,
+                        item.RetweetedId.Value,
                         new PostClass(
                             item.Nickname,
                             item.TextFromApi,
@@ -1499,7 +1293,7 @@ namespace OpenTween
                             item.ImageUrl,
                             item.ScreenName,
                             item.CreatedAt,
-                            item.RetweetedId,
+                            item.RetweetedId.Value,
                             item.IsFav,
                             item.IsRead,
                             item.IsReply,
@@ -1517,11 +1311,11 @@ namespace OpenTween
                             item.UserId,
                             item.FilterHit,
                             "",
-                            0,
+                            null,
                             item.PostGeo
                         )
                     );
-            _retweets[item.RetweetedId].RetweetedCount++;
+            _retweets[retweetedId].RetweetedCount++;
         }
 
         public void SetReadAllTab(bool Read, string TabName, int Index)
@@ -1533,15 +1327,7 @@ namespace OpenTween
 
             var Id = tb.GetId(Index);
             if (Id < 0) return;
-            PostClass post;
-            if (!tb.IsInnerStorageTabType)
-            {
-                post = _statuses[Id];
-            }
-            else
-            {
-                post = tb.Posts[Id];
-            }
+            PostClass post = tb.Posts[Id];
 
             if (post.IsRead == Read) return; //状態変更なければ終了
 
@@ -1557,50 +1343,54 @@ namespace OpenTween
                     if (tb.IsInnerStorageTabType)
                     {
                         //一般タブ
-                        if (_statuses.ContainsKey(Id) && !_statuses[Id].IsRead)
+                        PostClass status;
+                        if (_statuses.TryGetValue(Id, out status) && !status.IsRead)
                         {
-                            foreach (var key in _tabs.Keys)
+                            foreach (var tab in _tabs.Values)
                             {
-                                if (_tabs[key].UnreadManage &&
-                                    _tabs[key].Contains(Id) &&
-                                    !_tabs[key].IsInnerStorageTabType)
+                                if (tab.UnreadManage &&
+                                    !tab.IsInnerStorageTabType &&
+                                    tab.Contains(Id))
                                 {
-                                    _tabs[key].UnreadCount--;
-                                    if (_tabs[key].OldestUnreadId == Id) _tabs[key].OldestUnreadId = -1;
+                                    tab.UnreadCount--;
+                                    if (tab.OldestUnreadId == Id) tab.OldestUnreadId = -1;
                                 }
                             }
-                            _statuses[Id].IsRead = true;
+                            status.IsRead = true;
                         }
                     }
                     else
                     {
                         //一般タブ
-                        foreach (var key in _tabs.Keys)
+                        foreach (var tab in _tabs.Values)
                         {
-                            if (key != TabName &&
-                                _tabs[key].UnreadManage &&
-                                _tabs[key].Contains(Id) &&
-                                !_tabs[key].IsInnerStorageTabType)
+                            if (tab != tb &&
+                                tab.UnreadManage &&
+                                !tab.IsInnerStorageTabType &&
+                                tab.Contains(Id))
                             {
-                                _tabs[key].UnreadCount--;
-                                if (_tabs[key].OldestUnreadId == Id) _tabs[key].OldestUnreadId = -1;
+                                tab.UnreadCount--;
+                                if (tab.OldestUnreadId == Id) tab.OldestUnreadId = -1;
                             }
                         }
                     }
                     //内部保存タブ
-                    foreach (var key in _tabs.Keys)
+                    foreach (var tab in _tabs.Values)
                     {
-                        if (key != TabName &&
-                            _tabs[key].Contains(Id) &&
-                            _tabs[key].IsInnerStorageTabType &&
-                            !_tabs[key].Posts[Id].IsRead)
+                        if (tab != tb &&
+                            tab.IsInnerStorageTabType &&
+                            tab.Contains(Id))
                         {
-                            if (_tabs[key].UnreadManage)
+                            var tPost = tab.Posts[Id];
+                            if (!tPost.IsRead)
                             {
-                                _tabs[key].UnreadCount--;
-                                if (_tabs[key].OldestUnreadId == Id) _tabs[key].OldestUnreadId = -1;
+                                if (tab.UnreadManage)
+                                {
+                                    tab.UnreadCount--;
+                                    if (tab.OldestUnreadId == Id) tab.OldestUnreadId = -1;
+                                }
+                                tPost.IsRead = true;
                             }
-                            _tabs[key].Posts[Id].IsRead = true;
                         }
                     }
                 }
@@ -1612,50 +1402,54 @@ namespace OpenTween
                     if (tb.IsInnerStorageTabType)
                     {
                         //一般タブ
-                        if (_statuses.ContainsKey(Id) && _statuses[Id].IsRead)
+                        PostClass status;
+                        if (_statuses.TryGetValue(Id, out status) && status.IsRead)
                         {
-                            foreach (var key in _tabs.Keys)
+                            foreach (var tab in _tabs.Values)
                             {
-                                if (_tabs[key].UnreadManage &&
-                                   _tabs[key].Contains(Id) &&
-                                   !_tabs[key].IsInnerStorageTabType)
-                                    _tabs[key].UnreadCount++;
+                                if (tab.UnreadManage &&
+                                    !tab.IsInnerStorageTabType &&
+                                    tab.Contains(Id))
                                 {
-                                    if (_tabs[key].OldestUnreadId > Id) _tabs[key].OldestUnreadId = Id;
+                                    tab.UnreadCount++;
+                                    if (tab.OldestUnreadId > Id) tab.OldestUnreadId = Id;
                                 }
                             }
-                            _statuses[Id].IsRead = false;
+                            status.IsRead = false;
                         }
                     }
                     else
                     {
                         //一般タブ
-                        foreach (var key in _tabs.Keys)
+                        foreach (var tab in _tabs.Values)
                         {
-                            if (key != TabName &&
-                               _tabs[key].UnreadManage &&
-                               _tabs[key].Contains(Id) &&
-                               !_tabs[key].IsInnerStorageTabType)
+                            if (tab != tb &&
+                                tab.UnreadManage &&
+                                !tab.IsInnerStorageTabType &&
+                                tab.Contains(Id))
                             {
-                                _tabs[key].UnreadCount++;
-                                if (_tabs[key].OldestUnreadId > Id) _tabs[key].OldestUnreadId = Id;
+                                tab.UnreadCount++;
+                                if (tab.OldestUnreadId > Id) tab.OldestUnreadId = Id;
                             }
                         }
                     }
                     //内部保存タブ
-                    foreach (var key in _tabs.Keys)
+                    foreach (var tab in _tabs.Values)
                     {
-                        if (key != TabName &&
-                            _tabs[key].Contains(Id) &&
-                            _tabs[key].IsInnerStorageTabType &&
-                            _tabs[key].Posts[Id].IsRead)
+                        if (tab != tb &&
+                            tab.IsInnerStorageTabType &&
+                            tab.Contains(Id))
                         {
-                            if (_tabs[key].UnreadManage)
+                            var tPost = tab.Posts[Id];
+                            if (tPost.IsRead)
                             {
-                                _tabs[key].UnreadCount++;
-                                if (_tabs[key].OldestUnreadId > Id) _tabs[key].OldestUnreadId = Id;
+                                if (tab.UnreadManage)
+                                {
+                                    tab.UnreadCount++;
+                                    if (tab.OldestUnreadId > Id) tab.OldestUnreadId = Id;
+                                }
+                                tPost.IsRead = false;
                             }
-                            _tabs[key].Posts[Id].IsRead = false;
                         }
                     }
                 }
@@ -1672,17 +1466,9 @@ namespace OpenTween
 
             var Id = tb.GetId(Index);
             if (Id < 0) return;
-            PostClass post;
-            if (!tb.IsInnerStorageTabType)
-            {
-                post = _statuses[Id];
-            }
-            else
-            {
-                post = tb.Posts[Id];
-            }
+            PostClass post = tb.Posts[Id];
 
-            if (post.IsRead = Read) return; //状態変更なければ終了
+            if (post.IsRead == Read) return; //状態変更なければ終了
 
             post.IsRead = Read; //指定の状態に変更
 
@@ -1694,15 +1480,15 @@ namespace OpenTween
                     this.SetNextUnreadId(Id, tb);  //次の未読セット
                     //他タブの最古未読IDはタブ切り替え時に。
                     if (tb.IsInnerStorageTabType) return;
-                    foreach (var key in _tabs.Keys)
+                    foreach (var tab in _tabs.Values)
                     {
-                        if (key != TabName &&
-                            _tabs[key].UnreadManage &&
-                            _tabs[key].Contains(Id) &&
-                            !_tabs[key].IsInnerStorageTabType)
+                        if (tab != tb &&
+                            tab.UnreadManage &&
+                            !tab.IsInnerStorageTabType &&
+                            tab.Contains(Id))
                         {
-                            _tabs[key].UnreadCount--;
-                            if (_tabs[key].OldestUnreadId == Id) _tabs[key].OldestUnreadId = -1;
+                            tab.UnreadCount--;
+                            if (tab.OldestUnreadId == Id) tab.OldestUnreadId = -1;
                         }
                     }
                 }
@@ -1712,15 +1498,15 @@ namespace OpenTween
                     //if (tb.OldestUnreadId > Id || tb.OldestUnreadId == -1) tb.OldestUnreadId = Id;
                     if (tb.OldestUnreadId > Id) tb.OldestUnreadId = Id;
                     if (tb.IsInnerStorageTabType) return;
-                    foreach (var key in _tabs.Keys)
+                    foreach (var tab in _tabs.Values)
                     {
-                        if (key != TabName &&
-                            _tabs[key].UnreadManage &&
-                            _tabs[key].Contains(Id) &&
-                            !_tabs[key].IsInnerStorageTabType)
+                        if (tab != tb &&
+                            tab.UnreadManage &&
+                            !tab.IsInnerStorageTabType &&
+                            tab.Contains(Id))
                         {
-                            _tabs[key].UnreadCount++;
-                            if (_tabs[key].OldestUnreadId > Id) _tabs[key].OldestUnreadId = Id;
+                            tab.UnreadCount++;
+                            if (tab.OldestUnreadId > Id) tab.OldestUnreadId = Id;
                         }
                     }
                 }
@@ -1738,19 +1524,20 @@ namespace OpenTween
                 {
                     var id = tb.GetId(i);
                     if (id < 0) return;
-                    if (!_statuses[id].IsReply &&
-                        !_statuses[id].IsRead &&
-                        !_statuses[id].FilterHit)
+                    var tPost = _statuses[id];
+                    if (!tPost.IsReply &&
+                        !tPost.IsRead &&
+                        !tPost.FilterHit)
                     {
-                        _statuses[id].IsRead = true;
+                        tPost.IsRead = true;
                         this.SetNextUnreadId(id, tb);  //次の未読セット
-                        foreach (var key in _tabs.Keys)
+                        foreach (var tab in _tabs.Values)
                         {
-                            if (_tabs[key].UnreadManage &&
-                                _tabs[key].Contains(id))
+                            if (tab.UnreadManage &&
+                                tab.Contains(id))
                             {
-                                _tabs[key].UnreadCount--;
-                                if (_tabs[key].OldestUnreadId == id) _tabs[key].OldestUnreadId = -1;
+                                tab.UnreadCount--;
+                                if (tab.OldestUnreadId == id) tab.OldestUnreadId = -1;
                             }
                         }
                     }
@@ -1762,15 +1549,12 @@ namespace OpenTween
         {
             get
             {
-                if (_statuses.ContainsKey(ID)) return _statuses[ID];
-                foreach (var tb in this.GetTabsInnerStorageType())
-                {
-                    if (tb.Contains(ID))
-                    {
-                        return tb.Posts[ID];
-                    }
-                }
-                return null;
+                PostClass status;
+                return _statuses.TryGetValue(ID, out status)
+                    ? status
+                    : this.GetTabsInnerStorageType()
+                          .Where(t => t.Contains(ID))
+                          .Select(t => t.Posts[ID]).FirstOrDefault();
             }
         }
 
@@ -1778,19 +1562,13 @@ namespace OpenTween
         {
             get
             {
-                if (!_tabs.ContainsKey(TabName)) throw new ArgumentException("TabName=" + TabName + " is not contained.");
-                var id = _tabs[TabName].GetId(Index);
-                if (id < 0) throw new ArgumentException("Index can//t find. Index=" + Index.ToString() + "/TabName=" + TabName);
+                TabClass tb;
+                if (!_tabs.TryGetValue(TabName, out tb)) throw new ArgumentException("TabName=" + TabName + " is not contained.");
+                var id = tb.GetId(Index);
+                if (id < 0) throw new ArgumentException("Index can't find. Index=" + Index.ToString() + "/TabName=" + TabName);
                 try
                 {
-                    if (_tabs[TabName].IsInnerStorageTabType)
-                    {
-                        return _tabs[TabName].Posts[_tabs[TabName].GetId(Index)];
-                    }
-                    else
-                    {
-                        return _statuses[_tabs[TabName].GetId(Index)];
-                    }
+                    return tb.Posts[tb.GetId(Index)];
                 }
                 catch (Exception ex)
                 {
@@ -1803,21 +1581,13 @@ namespace OpenTween
         {
             get
             {
+                TabClass tb;
+                if (!_tabs.TryGetValue(TabName, out tb)) throw new ArgumentException("TabName=" + TabName + " is not contained.");
                 var length = EndIndex - StartIndex + 1;
                 var posts = new PostClass[length];
-                if (_tabs[TabName].IsInnerStorageTabType)
-                {
-                    for (int i = 0; i < length; i++)
-                    {
-                        posts[i] = _tabs[TabName].Posts[_tabs[TabName].GetId(StartIndex + i)];
-                    }
-                }
-                else
+                for (int i = 0; i < length; i++)
                 {
-                    for (int i = 0; i < length; i++)
-                    {
-                        posts[i] = _statuses[_tabs[TabName].GetId(StartIndex + i)];
-                    }
+                    posts[i] = tb.Posts[tb.GetId(StartIndex + i)];
                 }
                 return posts;
             }
@@ -1848,14 +1618,8 @@ namespace OpenTween
             //DM,公式検索は対応版
             lock (LockObj)
             {
-                if (_tabs.ContainsKey(TabName))
-                {
-                    return _tabs[TabName].Contains(Id);
-                }
-                else
-                {
-                    return false;
-                }
+                TabClass tab;
+                return _tabs.TryGetValue(TabName, out tab) && tab.Contains(Id);
             }
         }
 
@@ -1863,25 +1627,16 @@ namespace OpenTween
         {
             if (Manage)
             {
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    var tb = _tabs[key];
-                    if (tb.UnreadManage)
+                    if (tab.UnreadManage)
                     {
                         lock (LockUnread)
                         {
                             var cnt = 0;
                             var oldest = long.MaxValue;
-                            Dictionary<long, PostClass> posts;
-                            if (!tb.IsInnerStorageTabType)
-                            {
-                                posts = _statuses;
-                            }
-                            else
-                            {
-                                posts = tb.Posts;
-                            }
-                            foreach (var id in tb.BackupIds)
+                            Dictionary<long, PostClass> posts = tab.Posts;
+                            foreach (var id in tab.BackupIds)
                             {
                                 if (!posts[id].IsRead)
                                 {
@@ -1890,23 +1645,22 @@ namespace OpenTween
                                 }
                             }
                             if (oldest == long.MaxValue) oldest = -1;
-                            tb.OldestUnreadId = oldest;
-                            tb.UnreadCount = cnt;
+                            tab.OldestUnreadId = oldest;
+                            tab.UnreadCount = cnt;
                         }
                     }
                 }
             }
             else
             {
-                foreach (var key in _tabs.Keys)
+                foreach (var tab in _tabs.Values)
                 {
-                    var tb = _tabs[key];
-                    if (tb.UnreadManage && tb.UnreadCount > 0)
+                    if (tab.UnreadManage && tab.UnreadCount > 0)
                     {
                         lock (LockUnread)
                         {
-                            tb.UnreadCount = 0;
-                            tb.OldestUnreadId = -1;
+                            tab.UnreadCount = 0;
+                            tab.OldestUnreadId = -1;
                         }
                     }
                 }
@@ -1936,9 +1690,8 @@ namespace OpenTween
                         tb.ClearIDs();
                         //////////////フィルター前のIDsを退避。どのタブにも含まれないidはrecentへ追加
                         //////////////moveフィルターにヒットした際、recentに該当あればrecentから削除
-                        foreach (var id in _statuses.Keys)
+                        foreach (var post in _statuses.Values)
                         {
-                            var post = _statuses[id];
                             if (post.IsDm) continue;
                             var rslt = MyCommon.HITRESULT.None;
                             rslt = tb.AddFiltered(post);
@@ -2029,14 +1782,15 @@ namespace OpenTween
             //不要なPostを削除
             lock (LockObj)
             {
-                if (!_tabs[TabName].IsInnerStorageTabType)
+                var tb = _tabs[TabName];
+                if (!tb.IsInnerStorageTabType)
                 {
-                    foreach (var Id in _tabs[TabName].BackupIds)
+                    foreach (var Id in tb.BackupIds)
                     {
                         var Hit = false;
-                        foreach (var tb in _tabs.Values)
+                        foreach (var tab in _tabs.Values)
                         {
-                            if (tb.Contains(Id))
+                            if (tab.Contains(Id))
                             {
                                 Hit = true;
                                 break;
@@ -2047,7 +1801,7 @@ namespace OpenTween
                 }
 
                 //指定タブをクリア
-                _tabs[TabName].ClearIDs();
+                tb.ClearIDs();
             }
         }
 
@@ -2060,15 +1814,7 @@ namespace OpenTween
                 {
                     var cnt = 0;
                     var oldest = long.MaxValue;
-                    Dictionary<long, PostClass> posts;
-                    if (!tb.IsInnerStorageTabType)
-                    {
-                        posts = _statuses;
-                    }
-                    else
-                    {
-                        posts = tb.Posts;
-                    }
+                    Dictionary<long, PostClass> posts = tb.Posts;
                     foreach (var id in tb.BackupIds)
                     {
                         if (!posts[id].IsRead)
@@ -2111,9 +1857,9 @@ namespace OpenTween
                 }
                 else
                 {
-                    foreach (var id in _statuses.Keys)
+                    foreach (var post in _statuses.Values)
                     {
-                        _statuses[id].IsOwl = false;
+                        post.IsOwl = false;
                     }
                 }
             }
@@ -2126,9 +1872,9 @@ namespace OpenTween
             //合致しなければnullを返す
             lock (LockObj)
             {
-                foreach (var tb in _tabs.Values)
+                foreach (var tab in _tabs.Values)
                 {
-                    if (tb != null && tb.TabType == tabType) return tb;
+                    if (tab.TabType == tabType) return tab;
                 }
                 return null;
             }
@@ -2168,36 +1914,43 @@ namespace OpenTween
         {
             lock (LockObj)
             {
-                if (_tabs.ContainsKey(tabName)) return _tabs[tabName];
-                return null;
+                TabClass tab;
+                return _tabs.TryGetValue(tabName, out tab)
+                    ? tab
+                    : null;
             }
         }
 
         // デフォルトタブの判定処理
         public bool IsDefaultTab(string tabName)
         {
+            TabClass tab;
             if (tabName != null &&
-               _tabs.ContainsKey(tabName) &&
-               (_tabs[tabName].TabType == MyCommon.TabUsageType.Home ||
-               _tabs[tabName].TabType == MyCommon.TabUsageType.Mentions ||
-               _tabs[tabName].TabType == MyCommon.TabUsageType.DirectMessage ||
-               _tabs[tabName].TabType == MyCommon.TabUsageType.Favorites))
+               _tabs.TryGetValue(tabName, out tab) &&
+               (tab.TabType == MyCommon.TabUsageType.Home ||
+               tab.TabType == MyCommon.TabUsageType.Mentions ||
+               tab.TabType == MyCommon.TabUsageType.DirectMessage ||
+               tab.TabType == MyCommon.TabUsageType.Favorites))
             {
                 return true;
             }
-            else
-            {
-                return false;
-            }
+
+            return false;
         }
 
         //振り分け可能タブの判定処理
         public bool IsDistributableTab(string tabName)
         {
-            return tabName != null &&
-                this._tabs.ContainsKey(tabName) &&
-                (_tabs[tabName].TabType == MyCommon.TabUsageType.Mentions ||
-                 _tabs[tabName].TabType == MyCommon.TabUsageType.UserDefined);
+            TabClass tab;
+            if (tabName != null &&
+                _tabs.TryGetValue(tabName, out tab) &&
+                (tab.TabType == MyCommon.TabUsageType.Mentions ||
+                tab.TabType == MyCommon.TabUsageType.UserDefined))
+            {
+                return true;
+            }
+
+            return false;
         }
 
         public string GetUniqueTabName()
@@ -2230,11 +1983,13 @@ namespace OpenTween
     public sealed class TabClass
     {
         private bool _unreadManage = false;
-        private List<FiltersClass> _filters;
+        private List<PostFilterRule> _filters;
         private int _unreadCount = 0;
         private List<long> _ids;
         private List<TemporaryId> _tmpIds = new List<TemporaryId>();
         private MyCommon.TabUsageType _tabType = MyCommon.TabUsageType.Undefined;
+
+        [NonSerialized]
         private IdComparerClass _sorter = new IdComparerClass();
 
         private readonly object _lockObj = new object();
@@ -2324,6 +2079,7 @@ namespace OpenTween
 #endregion
 
 #region "リスト"
+        [NonSerialized]
         private ListElement _listInfo;
         public ListElement ListInfo
         {
@@ -2348,7 +2104,9 @@ namespace OpenTween
         public long SinceId { get; set; }
 
         [XmlIgnore]
-        public Dictionary<long, PostClass> Posts { get; set; }
+        public Dictionary<long, PostClass> Posts { get; private set; }
+
+        private Dictionary<long, PostClass> _innerPosts;
 
         public PostClass[] GetTemporaryPosts()
         {
@@ -2380,11 +2138,13 @@ namespace OpenTween
 
         public TabClass()
         {
-            Posts = new Dictionary<long, PostClass>();
+            _innerPosts = new Dictionary<long, PostClass>();
+            Posts = _innerPosts;
             SoundFile = "";
             OldestUnreadId = -1;
             TabName = "";
-            _filters = new List<FiltersClass>();
+            _filters = new List<PostFilterRule>();
+            Protected = false;
             Notify = true;
             SoundFile = "";
             _unreadManage = true;
@@ -2394,28 +2154,11 @@ namespace OpenTween
             _listInfo = null;
         }
 
-        public TabClass(string TabName, MyCommon.TabUsageType TabType, ListElement list)
+        public TabClass(string TabName, MyCommon.TabUsageType TabType, ListElement list) : this()
         {
-            Posts = new Dictionary<long, PostClass>();
-            SoundFile = "";
-            OldestUnreadId = -1;
             this.TabName = TabName;
-            _filters = new List<FiltersClass>();
-            Notify = true;
-            SoundFile = "";
-            _unreadManage = true;
-            _ids = new List<long>();
-            this.OldestUnreadId = -1;
-            _tabType = TabType;
+            this.TabType = TabType;
             this.ListInfo = list;
-            if (this.IsInnerStorageTabType)
-            {
-                _sorter.posts = Posts;
-            }
-            else
-            {
-                _sorter.posts = TabInformations.GetInstance().Posts;
-            }
         }
 
         public void Sort()
@@ -2534,7 +2277,7 @@ namespace OpenTween
                 {
                     try
                     {
-                        switch (ft.IsHit(post))   //フィルタクラスでヒット判定
+                        switch (ft.ExecFilter(post))   //フィルタクラスでヒット判定
                         {
                             case MyCommon.HITRESULT.None:
                                 break;
@@ -2554,8 +2297,8 @@ namespace OpenTween
                     }
                     catch (NullReferenceException)
                     {
-                        //IsHitでNullRef出る場合あり。暫定対応
-                        MyCommon.TraceOut("IsHitでNullRef: " + ft.ToString());
+                        // ExecFilterでNullRef出る場合あり。暫定対応
+                        MyCommon.TraceOut("ExecFilterでNullRef: " + ft.ToString());
                         rslt = MyCommon.HITRESULT.None;
                     }
                 }
@@ -2574,8 +2317,8 @@ namespace OpenTween
         //検索結果の追加
         public void AddPostToInnerStorage(PostClass Post)
         {
-            if (Posts.ContainsKey(Post.StatusId)) return;
-            Posts.Add(Post.StatusId, Post);
+            if (_innerPosts.ContainsKey(Post.StatusId)) return;
+            _innerPosts.Add(Post.StatusId, Post);
             _tmpIds.Add(new TemporaryId(Post.StatusId, Post.IsRead));
         }
 
@@ -2601,7 +2344,7 @@ namespace OpenTween
         {
             if (!this._ids.Contains(Id)) return;
             this._ids.Remove(Id);
-            if (this.IsInnerStorageTabType) Posts.Remove(Id);
+            if (this.IsInnerStorageTabType) _innerPosts.Remove(Id);
         }
 
         public void Remove(long Id, bool Read)
@@ -2615,7 +2358,7 @@ namespace OpenTween
             }
 
             this._ids.Remove(Id);
-            if (this.IsInnerStorageTabType) Posts.Remove(Id);
+            if (this.IsInnerStorageTabType) _innerPosts.Remove(Id);
         }
 
         public bool UnreadManage
@@ -2635,6 +2378,10 @@ namespace OpenTween
             }
         }
 
+        // v1.0.5で「タブを固定(Locked)」から「タブを保護(Protected)」に名称変更
+        [XmlElement(ElementName = "Locked")]
+        public bool Protected { get; set; }
+
         public bool Notify { get; set; }
 
         public string SoundFile { get; set; }
@@ -2664,7 +2411,7 @@ namespace OpenTween
             }
         }
 
-        public FiltersClass[] GetFilters()
+        public PostFilterRule[] GetFilters()
         {
             lock (this._lockObj)
             {
@@ -2672,7 +2419,7 @@ namespace OpenTween
             }
         }
 
-        public void RemoveFilter(FiltersClass filter)
+        public void RemoveFilter(PostFilterRule filter)
         {
             lock (this._lockObj)
             {
@@ -2681,7 +2428,7 @@ namespace OpenTween
             }
         }
 
-        public bool AddFilter(FiltersClass filter)
+        public bool AddFilter(PostFilterRule filter)
         {
             lock (this._lockObj)
             {
@@ -2692,33 +2439,33 @@ namespace OpenTween
             }
         }
 
-        public void EditFilter(FiltersClass original, FiltersClass modified)
+        public void EditFilter(PostFilterRule original, PostFilterRule modified)
         {
-            original.BodyFilter = modified.BodyFilter;
-            original.NameFilter = modified.NameFilter;
-            original.SearchBoth = modified.SearchBoth;
-            original.SearchUrl = modified.SearchUrl;
+            original.FilterBody = modified.FilterBody;
+            original.FilterName = modified.FilterName;
+            original.UseNameField = modified.UseNameField;
+            original.FilterByUrl = modified.FilterByUrl;
             original.UseRegex = modified.UseRegex;
             original.CaseSensitive = modified.CaseSensitive;
-            original.IsRt = modified.IsRt;
+            original.FilterRt = modified.FilterRt;
             original.UseLambda = modified.UseLambda;
-            original.Source = modified.Source;
-            original.ExBodyFilter = modified.ExBodyFilter;
-            original.ExNameFilter = modified.ExNameFilter;
-            original.ExSearchBoth = modified.ExSearchBoth;
-            original.ExSearchUrl = modified.ExSearchUrl;
+            original.FilterSource = modified.FilterSource;
+            original.ExFilterBody = modified.ExFilterBody;
+            original.ExFilterName = modified.ExFilterName;
+            original.ExUseNameField = modified.ExUseNameField;
+            original.ExFilterByUrl = modified.ExFilterByUrl;
             original.ExUseRegex = modified.ExUseRegex;
             original.ExCaseSensitive = modified.ExCaseSensitive;
-            original.IsExRt = modified.IsExRt;
+            original.ExFilterRt = modified.ExFilterRt;
             original.ExUseLambda = modified.ExUseLambda;
-            original.ExSource = modified.ExSource;
-            original.MoveFrom = modified.MoveFrom;
-            original.SetMark = modified.SetMark;
+            original.ExFilterSource = modified.ExFilterSource;
+            original.MoveMatches = modified.MoveMatches;
+            original.MarkMatches = modified.MarkMatches;
             this.FilterModified = true;
         }
 
         [XmlIgnore]
-        public List<FiltersClass> Filters
+        public List<PostFilterRule> Filters
         {
             get
             {
@@ -2736,7 +2483,7 @@ namespace OpenTween
             }
         }
 
-        public FiltersClass[] FilterArray
+        public PostFilterRule[] FilterArray
         {
             get
             {
@@ -2767,10 +2514,7 @@ namespace OpenTween
             _tmpIds.Clear();
             _unreadCount = 0;
             this.OldestUnreadId = -1;
-            if (Posts != null)
-            {
-                Posts.Clear();
-            }
+            _innerPosts.Clear();
         }
 
         public long GetId(int Index)
@@ -2807,12 +2551,13 @@ namespace OpenTween
                 _tabType = value;
                 if (this.IsInnerStorageTabType)
                 {
-                    _sorter.posts = Posts;
+                    Posts = _innerPosts;
                 }
                 else
                 {
-                    _sorter.posts = TabInformations.GetInstance().Posts;
+                    Posts = TabInformations.GetInstance().Posts;
                 }
+                _sorter.posts = Posts;
             }
         }
 
@@ -2836,880 +2581,6 @@ namespace OpenTween
         }
     }
 
-    [Serializable]
-    public sealed class FiltersClass : System.IEquatable<FiltersClass>
-    {
-        private string _name = "";
-        private List<string> _body = new List<string>();
-        private bool _searchBoth = true;
-        private bool _searchUrl = false;
-        private bool _caseSensitive = false;
-        private bool _useRegex = false;
-        private bool _isRt = false;
-        private string _source = "";
-        private string _exname = "";
-        private List<string> _exbody = new List<string>();
-        private bool _exsearchBoth = true;
-        private bool _exsearchUrl = false;
-        private bool _exuseRegex = false;
-        private bool _excaseSensitive = false;
-        private bool _isExRt = false;
-        private string _exSource = "";
-        private bool _moveFrom = false;
-        private bool _setMark = true;
-        private bool _useLambda = false;
-        private bool _exuseLambda = false;
-
-        // ラムダ式コンパイルキャッシュ
-        private LambdaExpression _lambdaExp = null;
-        private Delegate _lambdaExpDelegate = null;
-        private LambdaExpression _exlambdaExp = null;
-        private Delegate _exlambdaExpDelegate = null;
-
-        public FiltersClass() {}
-
-        //フィルタ一覧に表示する文言生成
-        private string MakeSummary()
-        {
-            var fs = new StringBuilder();
-            if (!string.IsNullOrEmpty(_name) || _body.Count > 0 || _isRt || !string.IsNullOrEmpty(_source))
-            {
-                if (_searchBoth)
-                {
-                    if (!string.IsNullOrEmpty(_name))
-                    {
-                        fs.AppendFormat(Properties.Resources.SetFiltersText1, _name);
-                    }
-                    else
-                    {
-                        fs.Append(Properties.Resources.SetFiltersText2);
-                    }
-                }
-                if (_body.Count > 0)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText3);
-                    foreach (var bf in _body)
-                    {
-                        fs.Append(bf);
-                        fs.Append(" ");
-                    }
-                    fs.Length--;
-                    fs.Append(Properties.Resources.SetFiltersText4);
-                }
-                fs.Append("(");
-                if (_searchBoth)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText5);
-                }
-                else
-                {
-                    fs.Append(Properties.Resources.SetFiltersText6);
-                }
-                if (_useRegex)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText7);
-                }
-                if (_searchUrl)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText8);
-                }
-                if (_caseSensitive)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText13);
-                }
-                if (_isRt)
-                {
-                    fs.Append("RT/");
-                }
-                if (_useLambda)
-                {
-                    fs.Append("LambdaExp/");
-                }
-                if (!string.IsNullOrEmpty(_source))
-                {
-                    fs.AppendFormat("Src…{0}/", _source);
-                }
-                fs.Length--;
-                fs.Append(")");
-            }
-            if (!string.IsNullOrEmpty(_exname) || _exbody.Count > 0 || _isExRt || !string.IsNullOrEmpty(_exSource))
-            {
-                //除外
-                fs.Append(Properties.Resources.SetFiltersText12);
-                if (_exsearchBoth)
-                {
-                    if (!string.IsNullOrEmpty(_exname))
-                    {
-                        fs.AppendFormat(Properties.Resources.SetFiltersText1, _exname);
-                    }
-                    else
-                    {
-                        fs.Append(Properties.Resources.SetFiltersText2);
-                    }
-                }
-                if (_exbody.Count > 0)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText3);
-                    foreach (var bf in _exbody)
-                    {
-                        fs.Append(bf);
-                        fs.Append(" ");
-                    }
-                    fs.Length--;
-                    fs.Append(Properties.Resources.SetFiltersText4);
-                }
-                fs.Append("(");
-                if (_exsearchBoth)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText5);
-                }
-                else
-                {
-                    fs.Append(Properties.Resources.SetFiltersText6);
-                }
-                if (_exuseRegex)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText7);
-                }
-                if (_exsearchUrl)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText8);
-                }
-                if (_excaseSensitive)
-                {
-                    fs.Append(Properties.Resources.SetFiltersText13);
-                }
-                if (_isExRt)
-                {
-                    fs.Append("RT/");
-                }
-                if (_exuseLambda)
-                {
-                    fs.Append("LambdaExp/");
-                }
-                if (!string.IsNullOrEmpty(_exSource))
-                {
-                    fs.AppendFormat("Src…{0}/", _exSource);
-                }
-                fs.Length--;
-                fs.Append(")");
-            }
-
-            fs.Append("(");
-            if (_moveFrom)
-            {
-                fs.Append(Properties.Resources.SetFiltersText9);
-            }
-            else
-            {
-                fs.Append(Properties.Resources.SetFiltersText11);
-            }
-            if (!_moveFrom && _setMark)
-            {
-                fs.Append(Properties.Resources.SetFiltersText10);
-            }
-            else if (!_moveFrom)
-            {
-                fs.Length--;
-            }
-
-            fs.Append(")");
-
-            return fs.ToString();
-        }
-
-        public string NameFilter
-        {
-            get
-            {
-                return _name;
-            }
-            set
-            {
-                _name = value;
-            }
-        }
-
-        public string ExNameFilter
-        {
-            get
-            {
-                return _exname;
-            }
-            set
-            {
-                _exname = value;
-            }
-        }
-
-        [XmlIgnore]
-        public List<string> BodyFilter
-        {
-            get
-            {
-                return _body;
-            }
-            set
-            {
-                _lambdaExp = null;
-                _lambdaExpDelegate = null;
-                _body = value;
-            }
-        }
-
-        public string[] BodyFilterArray
-        {
-            get
-            {
-                return _body.ToArray();
-            }
-            set
-            {
-                _body = new List<string>();
-                foreach (var filter in value)
-                {
-                    _body.Add(filter);
-                }
-            }
-        }
-
-        [XmlIgnore]
-        public List<string> ExBodyFilter
-        {
-            get
-            {
-                return _exbody;
-            }
-            set
-            {
-                _exlambdaExp = null;
-                _exlambdaExpDelegate = null;
-                _exbody = value;
-            }
-        }
-
-        public string[] ExBodyFilterArray
-        {
-            get
-            {
-                return _exbody.ToArray();
-            }
-            set
-            {
-                _exbody = new List<string>();
-                foreach (var filter in value)
-                {
-                    _exbody.Add(filter);
-                }
-            }
-        }
-
-        public bool SearchBoth
-        {
-            get
-            {
-                return _searchBoth;
-            }
-            set
-            {
-                _searchBoth = value;
-            }
-        }
-
-        public bool ExSearchBoth
-        {
-            get
-            {
-                return _exsearchBoth;
-            }
-            set
-            {
-                _exsearchBoth = value;
-            }
-        }
-
-        public bool MoveFrom
-        {
-            get
-            {
-                return _moveFrom;
-            }
-            set
-            {
-                _moveFrom = value;
-            }
-        }
-
-        public bool SetMark
-        {
-            get
-            {
-                return _setMark;
-            }
-            set
-            {
-                _setMark = value;
-            }
-        }
-
-        public bool SearchUrl
-        {
-            get
-            {
-                return _searchUrl;
-            }
-            set
-            {
-                _searchUrl = value;
-            }
-        }
-
-        public bool ExSearchUrl
-        {
-            get
-            {
-                return _exsearchUrl;
-            }
-            set
-            {
-                _exsearchUrl = value;
-            }
-        }
-
-        public bool CaseSensitive
-        {
-            get
-            {
-                return _caseSensitive;
-            }
-            set
-            {
-                _caseSensitive = value;
-            }
-        }
-
-        public bool ExCaseSensitive
-        {
-            get
-            {
-                return _excaseSensitive;
-            }
-            set
-            {
-                _excaseSensitive = value;
-            }
-        }
-
-        public bool UseLambda
-        {
-            get
-            {
-                return _useLambda;
-            }
-            set
-            {
-                _lambdaExp = null;
-                _lambdaExpDelegate = null;
-                _useLambda = value;
-            }
-        }
-
-        public bool ExUseLambda
-        {
-            get
-            {
-                return _exuseLambda;
-            }
-            set
-            {
-                _exlambdaExp = null;
-                _exlambdaExpDelegate = null;
-                _exuseLambda = value;
-            }
-        }
-
-        public bool UseRegex
-        {
-            get
-            {
-                return _useRegex;
-            }
-            set
-            {
-                _useRegex = value;
-            }
-        }
-
-        public bool ExUseRegex
-        {
-            get
-            {
-                return _exuseRegex;
-            }
-            set
-            {
-                _exuseRegex = value;
-            }
-        }
-
-        public bool IsRt
-        {
-            get
-            {
-                return _isRt;
-            }
-            set
-            {
-                _isRt = value;
-            }
-        }
-
-        public bool IsExRt
-        {
-            get
-            {
-                return _isExRt;
-            }
-            set
-            {
-                _isExRt = value;
-            }
-        }
-
-        public string Source
-        {
-            get
-            {
-                return _source;
-            }
-            set
-            {
-                _source = value;
-            }
-        }
-
-        public string ExSource
-        {
-            get
-            {
-                return _exSource;
-            }
-            set
-            {
-                _exSource = value;
-            }
-        }
-
-        public override string ToString()
-        {
-            return MakeSummary();
-        }
-
-        public bool ExecuteLambdaExpression(string expr, PostClass post)
-        {
-            return false;
-            // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
-        }
-
-        public bool ExecuteExLambdaExpression(string expr, PostClass post)
-        {
-            return false;
-            // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
-        }
-
-        public MyCommon.HITRESULT IsHit(PostClass post)
-        {
-            var bHit = true;
-            string tBody;
-            string tSource;
-            if (_searchUrl)
-            {
-                tBody = post.Text;
-                tSource = post.SourceHtml;
-            }
-            else
-            {
-                tBody = post.TextFromApi;
-                tSource = post.Source;
-            }
-            //検索オプション
-            System.StringComparison compOpt;
-            System.Text.RegularExpressions.RegexOptions rgOpt;
-            if (_caseSensitive)
-            {
-                compOpt = StringComparison.Ordinal;
-                rgOpt = RegexOptions.None;
-            }
-            else
-            {
-                compOpt = StringComparison.OrdinalIgnoreCase;
-                rgOpt = RegexOptions.IgnoreCase;
-            }
-            if (_searchBoth)
-            {
-                if (string.IsNullOrEmpty(_name) ||
-                    (!_useRegex &&
-                     (post.ScreenName.Equals(_name, compOpt) ||
-                      post.RetweetedBy.Equals(_name, compOpt)
-                     )
-                    ) ||
-                    (_useRegex &&
-                     (Regex.IsMatch(post.ScreenName, _name, rgOpt) ||
-                      (!string.IsNullOrEmpty(post.RetweetedBy) && Regex.IsMatch(post.RetweetedBy, _name, rgOpt))
-                     )
-                    ))
-                {
-                    if (_useLambda)
-                    {
-                        if (!ExecuteLambdaExpression(_body[0], post)) bHit = false;
-                    }
-                    else
-                    {
-                        foreach (var fs in _body)
-                        {
-                            if (_useRegex)
-                            {
-                                if (!Regex.IsMatch(tBody, fs, rgOpt)) bHit = false;
-                            }
-                            else
-                            {
-                                if (_caseSensitive)
-                                {
-                                    if (!tBody.Contains(fs)) bHit = false;
-                                }
-                                else
-                                {
-                                    if (!tBody.ToLower().Contains(fs.ToLower())) bHit = false;
-                                }
-                            }
-                            if (!bHit) break;
-                        }
-                    }
-                }
-                else
-                {
-                    bHit = false;
-                }
-            }
-            else
-            {
-                if (_useLambda)
-                {
-                    if (!ExecuteLambdaExpression(_body[0], post)) bHit = false;
-                }
-                else
-                {
-                    foreach (var fs in _body)
-                    {
-                        if (_useRegex)
-                        {
-                            if (!(Regex.IsMatch(post.ScreenName, fs, rgOpt) ||
-                                 (!string.IsNullOrEmpty(post.RetweetedBy) && Regex.IsMatch(post.RetweetedBy, fs, rgOpt)) ||
-                                 Regex.IsMatch(tBody, fs, rgOpt))) bHit = false;
-                        }
-                        else
-                        {
-                            if (_caseSensitive)
-                            {
-                                if (!(post.ScreenName.Contains(fs) ||
-                                    post.RetweetedBy.Contains(fs) ||
-                                    tBody.Contains(fs))) bHit = false;
-                            }
-                            else
-                            {
-                                if (!(post.ScreenName.ToLower().Contains(fs.ToLower()) ||
-                                    post.RetweetedBy.ToLower().Contains(fs.ToLower()) ||
-                                    tBody.ToLower().Contains(fs.ToLower()))) bHit = false;
-                            }
-                        }
-                        if (!bHit) break;
-                    }
-                }
-            }
-            if (_isRt)
-            {
-                if (post.RetweetedId == 0) bHit = false;
-            }
-            if (!string.IsNullOrEmpty(_source))
-            {
-                if (_useRegex)
-                {
-                    if (!Regex.IsMatch(tSource, _source, rgOpt)) bHit = false;
-                }
-                else
-                {
-                    if (!tSource.Equals(_source, compOpt)) bHit = false;
-                }
-            }
-            if (bHit)
-            {
-                //除外判定
-                if (_exsearchUrl)
-                {
-                    tBody = post.Text;
-                    tSource = post.SourceHtml;
-                }
-                else
-                {
-                    tBody = post.TextFromApi;
-                    tSource = post.Source;
-                }
-
-                var exFlag = false;
-                if (!string.IsNullOrEmpty(_exname) || _exbody.Count > 0)
-                {
-                    if (_excaseSensitive)
-                    {
-                        compOpt = StringComparison.Ordinal;
-                        rgOpt = RegexOptions.None;
-                    }
-                    else
-                    {
-                        compOpt = StringComparison.OrdinalIgnoreCase;
-                        rgOpt = RegexOptions.IgnoreCase;
-                    }
-                    if (_exsearchBoth)
-                    {
-                        if (string.IsNullOrEmpty(_exname) ||
-                            (!_exuseRegex &&
-                             (post.ScreenName.Equals(_exname, compOpt) ||
-                              post.RetweetedBy.Equals(_exname, compOpt)
-                             )
-                            ) ||
-                            (_exuseRegex &&
-                                (Regex.IsMatch(post.ScreenName, _exname, rgOpt) ||
-                                 (!string.IsNullOrEmpty(post.RetweetedBy) && Regex.IsMatch(post.RetweetedBy, _exname, rgOpt))
-                                )
-                            ))
-                        {
-                            if (_exbody.Count > 0)
-                            {
-                                if (_exuseLambda)
-                                {
-                                    if (ExecuteExLambdaExpression(_exbody[0], post)) exFlag = true;
-                                }
-                                else
-                                {
-                                    foreach (var fs in _exbody)
-                                    {
-                                        if (_exuseRegex)
-                                        {
-                                            if (Regex.IsMatch(tBody, fs, rgOpt)) exFlag = true;
-                                        }
-                                        else
-                                        {
-                                            if (_excaseSensitive)
-                                            {
-                                                if (tBody.Contains(fs)) exFlag = true;
-                                            }
-                                            else
-                                            {
-                                                if (tBody.ToLower().Contains(fs.ToLower())) exFlag = true;
-                                            }
-                                        }
-                                        if (exFlag) break;
-                                    }
-                                }
-                            }
-                            else
-                            {
-                                exFlag = true;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        if (_exuseLambda)
-                        {
-                            if (ExecuteExLambdaExpression(_exbody[0], post)) exFlag = true;
-                        }
-                        else
-                        {
-                            foreach (var fs in _exbody)
-                            {
-                                if (_exuseRegex)
-                                {
-                                    if (Regex.IsMatch(post.ScreenName, fs, rgOpt) ||
-                                       (!string.IsNullOrEmpty(post.RetweetedBy) && Regex.IsMatch(post.RetweetedBy, fs, rgOpt)) ||
-                                       Regex.IsMatch(tBody, fs, rgOpt)) exFlag = true;
-                                }
-                                else
-                                {
-                                    if (_excaseSensitive)
-                                    {
-                                        if (post.ScreenName.Contains(fs) ||
-                                           post.RetweetedBy.Contains(fs) ||
-                                           tBody.Contains(fs)) exFlag = true;
-                                    }
-                                    else
-                                    {
-                                        if (post.ScreenName.ToLower().Contains(fs.ToLower()) ||
-                                           post.RetweetedBy.ToLower().Contains(fs.ToLower()) ||
-                                           tBody.ToLower().Contains(fs.ToLower())) exFlag = true;
-                                    }
-                                }
-                                if (exFlag) break;
-                            }
-                        }
-                    }
-                }
-                if (_isExRt)
-                {
-                    if (post.RetweetedId > 0) exFlag = true;
-                }
-                if (!string.IsNullOrEmpty(_exSource))
-                {
-                    if (_exuseRegex)
-                    {
-                        if (Regex.IsMatch(tSource, _exSource, rgOpt)) exFlag = true;
-                    }
-                    else
-                    {
-                        if (tSource.Equals(_exSource, compOpt)) exFlag = true;
-                    }
-                }
-
-                if (string.IsNullOrEmpty(_name) && _body.Count == 0 && !_isRt && string.IsNullOrEmpty(_source))
-                {
-                    bHit = false;
-                }
-                if (bHit)
-                {
-                    if (!exFlag)
-                    {
-                        if (_moveFrom)
-                        {
-                            return MyCommon.HITRESULT.Move;
-                        }
-                        else
-                        {
-                            if (_setMark)
-                            {
-                                return MyCommon.HITRESULT.CopyAndMark;
-                            }
-                            return MyCommon.HITRESULT.Copy;
-                        }
-                    }
-                    else
-                    {
-                        return MyCommon.HITRESULT.Exclude;
-                    }
-                }
-                else
-                {
-                    if (exFlag)
-                    {
-                        return MyCommon.HITRESULT.Exclude;
-                    }
-                    else
-                    {
-                        return MyCommon.HITRESULT.None;
-                    }
-                }
-            }
-            else
-            {
-                return MyCommon.HITRESULT.None;
-            }
-        }
-
-        public bool Equals(FiltersClass other)
-        {
-            if (this.BodyFilter.Count != other.BodyFilter.Count) return false;
-            if (this.ExBodyFilter.Count != other.ExBodyFilter.Count) return false;
-            for (int i = 0; i < this.BodyFilter.Count; i++)
-            {
-                if (this.BodyFilter[i] != other.BodyFilter[i]) return false;
-            }
-            for (int i = 0; i < this.ExBodyFilter.Count; i++)
-            {
-                if (this.ExBodyFilter[i] != other.ExBodyFilter[i]) return false;
-            }
-
-            return (this.MoveFrom == other.MoveFrom) &
-                   (this.SetMark == other.SetMark) &
-                   (this.NameFilter == other.NameFilter) &
-                   (this.SearchBoth == other.SearchBoth) &
-                   (this.SearchUrl == other.SearchUrl) &
-                   (this.UseRegex == other.UseRegex) &
-                   (this.ExNameFilter == other.ExNameFilter) &
-                   (this.ExSearchBoth == other.ExSearchBoth) &
-                   (this.ExSearchUrl == other.ExSearchUrl) &
-                   (this.ExUseRegex == other.ExUseRegex) &
-                   (this.IsRt == other.IsRt) &
-                   (this.Source == other.Source) &
-                   (this.IsExRt == other.IsExRt) &
-                   (this.ExSource == other.ExSource) &
-                   (this.UseLambda == other.UseLambda) &
-                   (this.ExUseLambda == other.ExUseLambda);
-        }
-
-        public FiltersClass CopyTo(FiltersClass destination)
-        {
-            if (this.BodyFilter.Count > 0)
-            {
-                foreach (var flt in this.BodyFilter)
-                {
-                    destination.BodyFilter.Add(string.Copy(flt));
-                }
-            }
-
-            if (this.ExBodyFilter.Count > 0)
-            {
-                foreach (var flt in this.ExBodyFilter)
-                {
-                    destination.ExBodyFilter.Add(string.Copy(flt));
-                }
-            }
-
-            destination.MoveFrom = this.MoveFrom;
-            destination.SetMark = this.SetMark;
-            destination.NameFilter = this.NameFilter;
-            destination.SearchBoth = this.SearchBoth;
-            destination.SearchUrl = this.SearchUrl;
-            destination.UseRegex = this.UseRegex;
-            destination.ExNameFilter = this.ExNameFilter;
-            destination.ExSearchBoth = this.ExSearchBoth;
-            destination.ExSearchUrl = this.ExSearchUrl;
-            destination.ExUseRegex = this.ExUseRegex;
-            destination.IsRt = this.IsRt;
-            destination.Source = this.Source;
-            destination.IsExRt = this.IsExRt;
-            destination.ExSource = this.ExSource;
-            destination.UseLambda = this.UseLambda;
-            destination.ExUseLambda = this.ExUseLambda;
-            return destination;
-        }
-
-        public override bool Equals(object obj)
-        {
-            if (obj == null || this.GetType() != obj.GetType()) return false;
-            return this.Equals((FiltersClass)obj);
-        }
-
-        public override int GetHashCode()
-        {
-            return this.MoveFrom.GetHashCode() ^
-                   this.SetMark.GetHashCode() ^
-                   this.BodyFilter.GetHashCode() ^
-                   this.NameFilter.GetHashCode() ^
-                   this.SearchBoth.GetHashCode() ^
-                   this.SearchUrl.GetHashCode() ^
-                   this.UseRegex.GetHashCode() ^
-                   this.ExBodyFilter.GetHashCode() ^
-                   this.ExNameFilter.GetHashCode() ^
-                   this.ExSearchBoth.GetHashCode() ^
-                   this.ExSearchUrl.GetHashCode() ^
-                   this.ExUseRegex.GetHashCode() ^
-                   this.IsRt.GetHashCode() ^
-                   this.Source.GetHashCode() ^
-                   this.IsExRt.GetHashCode() ^
-                   this.ExSource.GetHashCode() ^
-                   this.UseLambda.GetHashCode() ^
-                   this.ExUseLambda.GetHashCode();
-        }
-    }
-
     //ソート比較クラス:ID比較のみ
     public sealed class IdComparerClass : IComparer<long>
     {