OSDN Git Service

アイコンサイズの再設定を微調整
[opentween/open-tween.git] / OpenTween / Tween.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General public License along
23 // with this program. if (not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 //コンパイル後コマンド
28 //"c:\Program Files\Microsoft.NET\SDK\v2.0\Bin\sgen.exe" /f /a:"$(TargetPath)"
29 //"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sgen.exe" /f /a:"$(TargetPath)"
30
31 using System;
32 using System.Collections.Generic;
33 using System.ComponentModel;
34 using System.Diagnostics;
35 using System.Drawing;
36 using System.IO;
37 using System.Linq;
38 using System.Media;
39 using System.Net;
40 using System.Reflection;
41 using System.Text;
42 using System.Text.RegularExpressions;
43 using System.Threading;
44 using System.Threading.Tasks;
45 using System.Windows.Forms;
46
47 using OpenTween.Api;
48 using OpenTween.Connection;
49 using OpenTween.OpenTweenCustomControl;
50 using OpenTween.Thumbnail;
51
52 namespace OpenTween
53 {
54     public partial class TweenMain : OTBaseForm
55     {
56         //各種設定
57         private Size _mySize;           //画面サイズ
58         private Point _myLoc;           //画面位置
59         private int _mySpDis;           //区切り位置
60         private int _mySpDis2;          //発言欄区切り位置
61         private int _mySpDis3;          //プレビュー区切り位置
62         private int _myAdSpDis;         //Ad区切り位置
63         private int _iconSz;            //アイコンサイズ(現在は16、24、48の3種類。将来直接数字指定可能とする 注:24x24の場合に26と指定しているのはMSゴシック系フォントのための仕様)
64         private bool _iconCol;          //1列表示の時true(48サイズのとき)
65
66         //雑多なフラグ類
67         private bool _initial;         //true:起動時処理中
68         private bool _initialLayout = true;
69         private bool _ignoreConfigSave;         //true:起動時処理中
70         private bool _tabDrag;           //タブドラッグ中フラグ(DoDragDropを実行するかの判定用)
71         private TabPage _beforeSelectedTab; //タブが削除されたときに前回選択されていたときのタブを選択する為に保持
72         private Point _tabMouseDownPoint;
73         private string _rclickTabName;      //右クリックしたタブの名前(Tabコントロール機能不足対応)
74         private readonly object _syncObject = new object();    //ロック用
75         private const string detailHtmlFormatMono1 = "<html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=8\"><style type=\"text/css\"><!-- pre {font-family: \"";
76         private const string detailHtmlFormat2 = "\", sans-serif; font-size: ";
77         private const string detailHtmlFormat3 = "pt; margin: 0; word-wrap: break-word; white-space: pre-wrap; color:rgb(";
78         private const string detailHtmlFormat4 = ");} a:link, a:visited, a:active, a:hover {color:rgb(";
79         private const string detailHtmlFormat5 = "); } --></style></head><body style=\"margin:0px; background-color:rgb(";
80         private const string detailHtmlFormatMono6 = ");\"><pre>";
81         private const string detailHtmlFormatMono7 = "</pre></body></html>";
82         private const string detailHtmlFormat1 = "<html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=8\"><style type=\"text/css\"><!-- p {font-family: \"";
83         private const string detailHtmlFormat6 = ");\"><p><span style=\"vertical-align:text-bottom\">";
84         private const string detailHtmlFormat7 = "</span></p></body></html>";
85         private string detailHtmlFormatHeader;
86         private string detailHtmlFormatFooter;
87         private bool _myStatusError = false;
88         private bool _myStatusOnline = false;
89         private bool soundfileListup = false;
90         private FormWindowState _formWindowState = FormWindowState.Normal; // フォームの状態保存用 通知領域からアイコンをクリックして復帰した際に使用する
91
92         //設定ファイル関連
93         //private SettingToConfig _cfg; //旧
94         private SettingLocal _cfgLocal;
95         private SettingCommon _cfgCommon;
96         private bool _modifySettingLocal = false;
97         private bool _modifySettingCommon = false;
98         private bool _modifySettingAtId = false;
99
100         //twitter解析部
101         private Twitter tw = new Twitter();
102
103         //Growl呼び出し部
104         private GrowlHelper gh = new GrowlHelper(Application.ProductName);
105
106         //サブ画面インスタンス
107         private AppendSettingDialog SettingDialog = AppendSettingDialog.Instance;       //設定画面インスタンス
108         private SearchWord SearchDialog = new SearchWord();     //検索画面インスタンス
109         private FilterDialog fltDialog = new FilterDialog(); //フィルター編集画面
110         private OpenURL UrlDialog = new OpenURL();
111         public AtIdSupplement AtIdSupl;     //@id補助
112         public AtIdSupplement HashSupl;    //Hashtag補助
113         public HashtagManage HashMgr;
114         private EventViewerDialog evtDialog;
115
116         //表示フォント、色、アイコン
117         private Font _fntUnread;            //未読用フォント
118         private Color _clUnread;            //未読用文字色
119         private Font _fntReaded;            //既読用フォント
120         private Color _clReaded;            //既読用文字色
121         private Color _clFav;               //Fav用文字色
122         private Color _clOWL;               //片思い用文字色
123         private Color _clRetweet;               //Retweet用文字色
124         private Color _clHighLight = Color.FromKnownColor(KnownColor.HighlightText);         //選択中の行用文字色
125         private Font _fntDetail;            //発言詳細部用フォント
126         private Color _clDetail;              //発言詳細部用色
127         private Color _clDetailLink;          //発言詳細部用リンク文字色
128         private Color _clDetailBackcolor;     //発言詳細部用背景色
129         private Color _clSelf;              //自分の発言用背景色
130         private Color _clAtSelf;            //自分宛返信用背景色
131         private Color _clTarget;            //選択発言者の他の発言用背景色
132         private Color _clAtTarget;          //選択発言中の返信先用背景色
133         private Color _clAtFromTarget;      //選択発言者への返信発言用背景色
134         private Color _clAtTo;              //選択発言の唯一@先
135         private Color _clListBackcolor;       //リスト部通常発言背景色
136         private Color _clInputBackcolor;      //入力欄背景色
137         private Color _clInputFont;           //入力欄文字色
138         private Font _fntInputFont;           //入力欄フォント
139         private ImageCache IconCache;        //アイコン画像リスト
140         private Icon NIconAt;               //At.ico             タスクトレイアイコン:通常時
141         private Icon NIconAtRed;            //AtRed.ico          タスクトレイアイコン:通信エラー時
142         private Icon NIconAtSmoke;          //AtSmoke.ico        タスクトレイアイコン:オフライン時
143         private Icon[] NIconRefresh = new Icon[4];       //Refresh.ico        タスクトレイアイコン:更新中(アニメーション用に4種類を保持するリスト)
144         private Icon TabIcon;               //Tab.ico            未読のあるタブ用アイコン
145         private Icon MainIcon;              //Main.ico           画面左上のアイコン
146         private Icon ReplyIcon;               //5g
147         private Icon ReplyIconBlink;          //6g
148
149         private PostClass _anchorPost;
150         private bool _anchorFlag;        //true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
151
152         private List<PostingStatus> _history = new List<PostingStatus>();   //発言履歴
153         private int _hisIdx;                  //発言履歴カレントインデックス
154
155         //発言投稿時のAPI引数(発言編集時に設定。手書きreplyでは設定されない)
156         private long? _reply_to_id;     // リプライ先のステータスID 0の場合はリプライではない 注:複数あてのものはリプライではない
157         private string _reply_to_name;    // リプライ先ステータスの書き込み者の名前
158
159         //時速表示用
160         private List<DateTime> _postTimestamps = new List<DateTime>();
161         private List<DateTime> _favTimestamps = new List<DateTime>();
162         private Dictionary<DateTime, int> _tlTimestamps = new Dictionary<DateTime, int>();
163         private int _tlCount;
164
165         // 以下DrawItem関連
166         private SolidBrush _brsHighLight = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
167         private SolidBrush _brsBackColorMine;
168         private SolidBrush _brsBackColorAt;
169         private SolidBrush _brsBackColorYou;
170         private SolidBrush _brsBackColorAtYou;
171         private SolidBrush _brsBackColorAtFromTarget;
172         private SolidBrush _brsBackColorAtTo;
173         private SolidBrush _brsBackColorNone;
174         private SolidBrush _brsDeactiveSelection = new SolidBrush(Color.FromKnownColor(KnownColor.ButtonFace)); //Listにフォーカスないときの選択行の背景色
175         private StringFormat sfTab = new StringFormat();
176
177         //////////////////////////////////////////////////////////////////////////////////////////////////////////
178         private ToolStripAPIGauge _apiGauge;
179         private TabInformations _statuses;
180
181         // ListViewItem のキャッシュ関連
182         private int _itemCacheIndex;
183         private ListViewItem[] _itemCache;
184         private PostClass[] _postCache;
185         private ReaderWriterLockSlim itemCacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
186
187         private TabPage _curTab;
188         private int _curItemIndex;
189         private DetailsListView _curList;
190         private PostClass _curPost;
191         private bool _isColumnChanged = false;
192         private bool _waitTimeline = false;
193         private bool _waitReply = false;
194         private bool _waitDm = false;
195         private bool _waitFav = false;
196         private bool _waitPubSearch = false;
197         private bool _waitUserTimeline = false;
198         private bool _waitLists = false;
199         private BackgroundWorker[] _bw = new BackgroundWorker[20];
200         private BackgroundWorker _bwFollower;
201         private InternetSecurityManager SecurityManager;
202
203         private int UnreadCounter = -1;
204         private int UnreadAtCounter = -1;
205
206         private string[] ColumnOrgText = new string[9];
207         private string[] ColumnText = new string[9];
208
209         private bool _DoFavRetweetFlags = false;
210         private bool osResumed = false;
211         private Dictionary<string, IMultimediaShareService> pictureService;
212
213         //////////////////////////////////////////////////////////////////////////////////////////////////////////
214         private string _postBrowserStatusText = "";
215
216         private bool _colorize = false;
217
218         private System.Timers.Timer TimerTimeline = new System.Timers.Timer();
219
220         private ImageListViewItem displayItem;
221
222         /// <summary>
223         /// デザイン時の DPI (96dpi) と実際の表示時の DPI との比を表します
224         /// </summary>
225         protected SizeF currentScaleFactor = new SizeF();
226
227         //URL短縮のUndo用
228         private struct urlUndo
229         {
230             public string Before;
231             public string After;
232         }
233
234         private List<urlUndo> urlUndoBuffer = null;
235
236         private struct ReplyChain
237         {
238             public long OriginalId;
239             public long InReplyToId;
240             public TabPage OriginalTab;
241
242             public ReplyChain(long originalId, long inReplyToId, TabPage originalTab)
243             {
244                 this.OriginalId = originalId;
245                 this.InReplyToId = inReplyToId;
246                 this.OriginalTab = originalTab;
247             }
248         }
249
250         private Stack<ReplyChain> replyChains; //[, ]でのリプライ移動の履歴
251         private Stack<Tuple<TabPage, PostClass>> selectPostChains = new Stack<Tuple<TabPage, PostClass>>(); //ポスト選択履歴
252
253         //Backgroundworkerの処理結果通知用引数構造体
254         private class GetWorkerResult
255         {
256             public string retMsg = "";                     //処理結果詳細メッセージ。エラー時に値がセットされる
257             public int page;                      //取得対象ページ番号
258             public int endPage = 0;                   //取得終了ページ番号(継続可能ならインクリメントされて返る。pageと比較して継続判定)
259             public MyCommon.WORKERTYPE type;                   //処理種別
260             public Dictionary<string, Image> imgs = null;                    //新規取得したアイコンイメージ
261             public string tName = "";                  //Fav追加・削除時のタブ名
262             public List<long> ids = null;               //Fav追加・削除時のID
263             public List<long> sIds = null;                  //Fav追加・削除成功分のID
264             public bool newDM = false;
265             public int addCount;
266             public PostingStatus status;
267         }
268
269         //Backgroundworkerへ処理内容を通知するための引数用構造体
270         private class GetWorkerArg
271         {
272             public int page;                      //処理対象ページ番号
273             public int endPage;                   //処理終了ページ番号(起動時の読み込みページ数。通常時はpageと同じ値をセット)
274             public MyCommon.WORKERTYPE type;                   //処理種別
275             public string url = "";            //URLをブラウザで開くときのアドレス
276             public PostingStatus status = new PostingStatus();          //発言POST時の発言内容
277             public List<long> ids;               //Fav追加・削除時のItemIndex
278             public List<long> sIds;              //Fav追加・削除成功分のItemIndex
279             public string tName = "";            //Fav追加・削除時のタブ名
280         }
281
282         //検索処理タイプ
283         private enum SEARCHTYPE
284         {
285             DialogSearch,
286             NextSearch,
287             PrevSearch,
288         }
289
290         private class PostingStatus
291         {
292             public string status = "";
293             public long? inReplyToId = null;
294             public string inReplyToName = null;
295             public string imageService = "";      //画像投稿サービス名
296             public string imagePath = "";
297             public PostingStatus()
298             {
299             }
300             public PostingStatus(string status, long? replyToId, string replyToName)
301             {
302                 this.status = status;
303                 this.inReplyToId = replyToId;
304                 this.inReplyToName = replyToName;
305             }
306         }
307
308         private void TweenMain_Activated(object sender, EventArgs e)
309         {
310             //画面がアクティブになったら、発言欄の背景色戻す
311             if (StatusText.Focused)
312             {
313                 this.StatusText_Enter(this.StatusText, System.EventArgs.Empty);
314             }
315         }
316
317         private void TweenMain_Disposed(object sender, EventArgs e)
318         {
319             //後始末
320             SettingDialog.Dispose();
321             SearchDialog.Dispose();
322             fltDialog.Dispose();
323             UrlDialog.Dispose();
324             if (NIconAt != null) NIconAt.Dispose();
325             if (NIconAtRed != null) NIconAtRed.Dispose();
326             if (NIconAtSmoke != null) NIconAtSmoke.Dispose();
327             if (NIconRefresh[0] != null) NIconRefresh[0].Dispose();
328             if (NIconRefresh[1] != null) NIconRefresh[1].Dispose();
329             if (NIconRefresh[2] != null) NIconRefresh[2].Dispose();
330             if (NIconRefresh[3] != null) NIconRefresh[3].Dispose();
331             if (TabIcon != null) TabIcon.Dispose();
332             if (MainIcon != null) MainIcon.Dispose();
333             if (ReplyIcon != null) ReplyIcon.Dispose();
334             if (ReplyIconBlink != null) ReplyIconBlink.Dispose();
335             _brsHighLight.Dispose();
336             if (_brsBackColorMine != null) _brsBackColorMine.Dispose();
337             if (_brsBackColorAt != null) _brsBackColorAt.Dispose();
338             if (_brsBackColorYou != null) _brsBackColorYou.Dispose();
339             if (_brsBackColorAtYou != null) _brsBackColorAtYou.Dispose();
340             if (_brsBackColorAtFromTarget != null) _brsBackColorAtFromTarget.Dispose();
341             if (_brsBackColorAtTo != null) _brsBackColorAtTo.Dispose();
342             if (_brsBackColorNone != null) _brsBackColorNone.Dispose();
343             if (_brsDeactiveSelection != null) _brsDeactiveSelection.Dispose();
344             //sf.Dispose();
345             sfTab.Dispose();
346             foreach (BackgroundWorker bw in _bw)
347             {
348                 if (bw != null)
349                     bw.Dispose();
350             }
351             if (_bwFollower != null)
352             {
353                 _bwFollower.Dispose();
354             }
355             this._apiGauge.Dispose();
356             if (IconCache != null)
357             {
358                 this.IconCache.CancelAsync();
359                 this.IconCache.Dispose();
360             }
361             // 終了時にRemoveHandlerしておかないとメモリリークする
362             // http://msdn.microsoft.com/ja-jp/library/microsoft.win32.systemevents.powermodechanged.aspx
363             Microsoft.Win32.SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
364         }
365
366         private void LoadIcon(ref Icon IconInstance, string FileName)
367         {
368             string dir = Application.StartupPath;
369             if (File.Exists(Path.Combine(dir, FileName)))
370             {
371                 try
372                 {
373                     IconInstance = new Icon(Path.Combine(dir, FileName));
374                 }
375                 catch (Exception)
376                 {
377                 }
378             }
379         }
380
381         private void LoadIcons()
382         {
383             //着せ替えアイコン対応
384             //タスクトレイ通常時アイコン
385             string dir = Application.StartupPath;
386
387             NIconAt = Properties.Resources.At;
388             NIconAtRed = Properties.Resources.AtRed;
389             NIconAtSmoke = Properties.Resources.AtSmoke;
390             NIconRefresh[0] = Properties.Resources.Refresh;
391             NIconRefresh[1] = Properties.Resources.Refresh2;
392             NIconRefresh[2] = Properties.Resources.Refresh3;
393             NIconRefresh[3] = Properties.Resources.Refresh4;
394             TabIcon = Properties.Resources.TabIcon;
395             MainIcon = Properties.Resources.MIcon;
396             ReplyIcon = Properties.Resources.Reply;
397             ReplyIconBlink = Properties.Resources.ReplyBlink;
398
399             if (!Directory.Exists(Path.Combine(dir, "Icons")))
400                 return;
401
402             LoadIcon(ref NIconAt, "Icons\\At.ico");
403
404             //タスクトレイエラー時アイコン
405             LoadIcon(ref NIconAtRed, "Icons\\AtRed.ico");
406
407             //タスクトレイオフライン時アイコン
408             LoadIcon(ref NIconAtSmoke, "Icons\\AtSmoke.ico");
409
410             //タスクトレイ更新中アイコン
411             //アニメーション対応により4種類読み込み
412             LoadIcon(ref NIconRefresh[0], "Icons\\Refresh.ico");
413             LoadIcon(ref NIconRefresh[1], "Icons\\Refresh2.ico");
414             LoadIcon(ref NIconRefresh[2], "Icons\\Refresh3.ico");
415             LoadIcon(ref NIconRefresh[3], "Icons\\Refresh4.ico");
416
417             //タブ見出し未読表示アイコン
418             LoadIcon(ref TabIcon, "Icons\\Tab.ico");
419
420             //画面のアイコン
421             LoadIcon(ref MainIcon, "Icons\\MIcon.ico");
422
423             //Replyのアイコン
424             LoadIcon(ref ReplyIcon, "Icons\\Reply.ico");
425
426             //Reply点滅のアイコン
427             LoadIcon(ref ReplyIconBlink, "Icons\\ReplyBlink.ico");
428         }
429
430         private void InitColumns(ListView list, bool startup)
431         {
432             ColumnHeader _colHd1 = new ColumnHeader();  //アイコン
433             ColumnHeader _colHd2 = new ColumnHeader();  //ニックネーム
434             ColumnHeader _colHd3 = new ColumnHeader();  //本文
435             ColumnHeader _colHd4 = new ColumnHeader();  //日付
436             ColumnHeader _colHd5 = new ColumnHeader();  //ユーザID
437             ColumnHeader _colHd6 = new ColumnHeader();  //未読
438             ColumnHeader _colHd7 = new ColumnHeader();  //マーク&プロテクト
439             ColumnHeader _colHd8 = new ColumnHeader();  //ソース
440
441             if (!_iconCol)
442             {
443                 list.Columns.AddRange(new ColumnHeader[] { _colHd1, _colHd2, _colHd3, _colHd4, _colHd5, _colHd6, _colHd7, _colHd8 });
444             }
445             else
446             {
447                 list.Columns.AddRange(new ColumnHeader[] { _colHd1, _colHd3 });
448             }
449
450             InitColumnText();
451             _colHd1.Text = ColumnText[0];
452             _colHd1.Width = 48;
453             _colHd2.Text = ColumnText[1];
454             _colHd2.Width = 80;
455             _colHd3.Text = ColumnText[2];
456             _colHd3.Width = 300;
457             _colHd4.Text = ColumnText[3];
458             _colHd4.Width = 50;
459             _colHd5.Text = ColumnText[4];
460             _colHd5.Width = 50;
461             _colHd6.Text = ColumnText[5];
462             _colHd6.Width = 16;
463             _colHd7.Text = ColumnText[6];
464             _colHd7.Width = 16;
465             _colHd8.Text = ColumnText[7];
466             _colHd8.Width = 50;
467
468             int[] dispOrder = new int[8];
469             if (!startup)
470             {
471                 for (int i = 0; i < _curList.Columns.Count; i++)
472                 {
473                     for (int j = 0; j < _curList.Columns.Count; j++)
474                     {
475                         if (_curList.Columns[j].DisplayIndex == i)
476                         {
477                             dispOrder[i] = j;
478                             break;
479                         }
480                     }
481                 }
482                 for (int i = 0; i < _curList.Columns.Count; i++)
483                 {
484                     list.Columns[i].Width = _curList.Columns[i].Width;
485                     list.Columns[dispOrder[i]].DisplayIndex = i;
486                 }
487             }
488             else
489             {
490                 if (_iconCol)
491                 {
492                     list.Columns[0].Width = _cfgLocal.Width1;
493                     list.Columns[1].Width = _cfgLocal.Width3;
494                     list.Columns[0].DisplayIndex = 0;
495                     list.Columns[1].DisplayIndex = 1;
496                 }
497                 else
498                 {
499                     for (int i = 0; i <= 7; i++)
500                     {
501                         if (_cfgLocal.DisplayIndex1 == i)
502                             dispOrder[i] = 0;
503                         else if (_cfgLocal.DisplayIndex2 == i)
504                             dispOrder[i] = 1;
505                         else if (_cfgLocal.DisplayIndex3 == i)
506                             dispOrder[i] = 2;
507                         else if (_cfgLocal.DisplayIndex4 == i)
508                             dispOrder[i] = 3;
509                         else if (_cfgLocal.DisplayIndex5 == i)
510                             dispOrder[i] = 4;
511                         else if (_cfgLocal.DisplayIndex6 == i)
512                             dispOrder[i] = 5;
513                         else if (_cfgLocal.DisplayIndex7 == i)
514                             dispOrder[i] = 6;
515                         else if (_cfgLocal.DisplayIndex8 == i)
516                             dispOrder[i] = 7;
517                     }
518                     list.Columns[0].Width = _cfgLocal.Width1;
519                     list.Columns[1].Width = _cfgLocal.Width2;
520                     list.Columns[2].Width = _cfgLocal.Width3;
521                     list.Columns[3].Width = _cfgLocal.Width4;
522                     list.Columns[4].Width = _cfgLocal.Width5;
523                     list.Columns[5].Width = _cfgLocal.Width6;
524                     list.Columns[6].Width = _cfgLocal.Width7;
525                     list.Columns[7].Width = _cfgLocal.Width8;
526                     for (int i = 0; i <= 7; i++)
527                     {
528                         list.Columns[dispOrder[i]].DisplayIndex = i;
529                     }
530                 }
531             }
532         }
533
534         private void InitColumnText()
535         {
536             ColumnText[0] = "";
537             ColumnText[1] = Properties.Resources.AddNewTabText2;
538             ColumnText[2] = Properties.Resources.AddNewTabText3;
539             ColumnText[3] = Properties.Resources.AddNewTabText4_2;
540             ColumnText[4] = Properties.Resources.AddNewTabText5;
541             ColumnText[5] = "";
542             ColumnText[6] = "";
543             ColumnText[7] = "Source";
544
545             ColumnOrgText[0] = "";
546             ColumnOrgText[1] = Properties.Resources.AddNewTabText2;
547             ColumnOrgText[2] = Properties.Resources.AddNewTabText3;
548             ColumnOrgText[3] = Properties.Resources.AddNewTabText4_2;
549             ColumnOrgText[4] = Properties.Resources.AddNewTabText5;
550             ColumnOrgText[5] = "";
551             ColumnOrgText[6] = "";
552             ColumnOrgText[7] = "Source";
553
554             int c = 0;
555             switch (_statuses.SortMode)
556             {
557                 case IdComparerClass.ComparerMode.Nickname:  //ニックネーム
558                     c = 1;
559                     break;
560                 case IdComparerClass.ComparerMode.Data:  //本文
561                     c = 2;
562                     break;
563                 case IdComparerClass.ComparerMode.Id:  //時刻=発言Id
564                     c = 3;
565                     break;
566                 case IdComparerClass.ComparerMode.Name:  //名前
567                     c = 4;
568                     break;
569                 case IdComparerClass.ComparerMode.Source:  //Source
570                     c = 7;
571                     break;
572             }
573
574             if (_iconCol)
575             {
576                 if (_statuses.SortOrder == SortOrder.Descending)
577                 {
578                     // U+25BE BLACK DOWN-POINTING SMALL TRIANGLE
579                     ColumnText[2] = ColumnOrgText[2] + "▾";
580                 }
581                 else
582                 {
583                     // U+25B4 BLACK UP-POINTING SMALL TRIANGLE
584                     ColumnText[2] = ColumnOrgText[2] + "▴";
585                 }
586             }
587             else
588             {
589                 if (_statuses.SortOrder == SortOrder.Descending)
590                 {
591                     // U+25BE BLACK DOWN-POINTING SMALL TRIANGLE
592                     ColumnText[c] = ColumnOrgText[c] + "▾";
593                 }
594                 else
595                 {
596                     // U+25B4 BLACK UP-POINTING SMALL TRIANGLE
597                     ColumnText[c] = ColumnOrgText[c] + "▴";
598                 }
599             }
600         }
601
602         private void InitializeTraceFrag()
603         {
604 #if DEBUG
605             TraceOutToolStripMenuItem.Checked = true;
606             MyCommon.TraceFlag = true;
607 #endif
608             if (!MyCommon.fileVersion.EndsWith("0"))
609             {
610                 TraceOutToolStripMenuItem.Checked = true;
611                 MyCommon.TraceFlag = true;
612             }
613         }
614
615         private void TweenMain_Load(object sender, EventArgs e)
616         {
617             _ignoreConfigSave = true;
618             this.Visible = false;
619
620             //Win32Api.SetProxy(HttpConnection.ProxyType.Specified, "127.0.0.1", 8080, "user", "pass")
621
622             SecurityManager = new InternetSecurityManager(PostBrowser);
623             this.PostBrowser.AllowWebBrowserDrop = false;  // COMException を回避するため、ActiveX の初期化が終わってから設定する
624
625             MyCommon.TwitterApiInfo.AccessLimitUpdated += TwitterApiStatus_AccessLimitUpdated;
626             Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
627
628             if (MyApplication.StartupOptions.ContainsKey("d"))
629                 MyCommon.TraceFlag = true;
630
631             Regex.CacheSize = 100;
632
633             MyCommon.fileVersion = ((AssemblyFileVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0]).Version;
634             InitializeTraceFrag();
635             LoadIcons(); // アイコン読み込み
636
637             ThumbnailGenerator.InitializeGenerator();
638
639             Thumbnail.Services.TonTwitterCom.InitializeOAuthToken = x =>
640                 x.Initialize(ApplicationSettings.TwitterConsumerKey, ApplicationSettings.TwitterConsumerSecret,
641                     this.tw.AccessToken, this.tw.AccessTokenSecret, "", "");
642
643             //発言保持クラス
644             _statuses = TabInformations.GetInstance();
645
646             //アイコン設定
647             this.Icon = MainIcon;              //メインフォーム(TweenMain)
648             NotifyIcon1.Icon = NIconAt;      //タスクトレイ
649             TabImage.Images.Add(TabIcon);    //タブ見出し
650
651             SettingDialog.Owner = this;;
652             SearchDialog.Owner = this;
653             fltDialog.Owner = this;
654             UrlDialog.Owner = this;
655
656             _history.Add(new PostingStatus());
657             _hisIdx = 0;
658             _reply_to_id = null;
659             _reply_to_name = null;
660
661             //<<<<<<<<<設定関連>>>>>>>>>
662             //設定コンバージョン
663             //ConvertConfig();
664
665             ////設定読み出し
666             LoadConfig();
667
668             //新着バルーン通知のチェック状態設定
669             NewPostPopMenuItem.Checked = _cfgCommon.NewAllPop;
670             this.NotifyFileMenuItem.Checked = NewPostPopMenuItem.Checked;
671
672             //フォント&文字色&背景色保持
673             _fntUnread = _cfgLocal.FontUnread;
674             _clUnread = _cfgLocal.ColorUnread;
675             _fntReaded = _cfgLocal.FontRead;
676             _clReaded = _cfgLocal.ColorRead;
677             _clFav = _cfgLocal.ColorFav;
678             _clOWL = _cfgLocal.ColorOWL;
679             _clRetweet = _cfgLocal.ColorRetweet;
680             _fntDetail = _cfgLocal.FontDetail;
681             _clDetail = _cfgLocal.ColorDetail;
682             _clDetailLink = _cfgLocal.ColorDetailLink;
683             _clDetailBackcolor = _cfgLocal.ColorDetailBackcolor;
684             _clSelf = _cfgLocal.ColorSelf;
685             _clAtSelf = _cfgLocal.ColorAtSelf;
686             _clTarget = _cfgLocal.ColorTarget;
687             _clAtTarget = _cfgLocal.ColorAtTarget;
688             _clAtFromTarget = _cfgLocal.ColorAtFromTarget;
689             _clAtTo = _cfgLocal.ColorAtTo;
690             _clListBackcolor = _cfgLocal.ColorListBackcolor;
691             _clInputBackcolor = _cfgLocal.ColorInputBackcolor;
692             _clInputFont = _cfgLocal.ColorInputFont;
693             _fntInputFont = _cfgLocal.FontInputFont;
694
695             var fontUIGlobal = this._cfgLocal.FontUIGlobal;
696             if (fontUIGlobal != null)
697             {
698                 OTBaseForm.GlobalFont = fontUIGlobal;
699                 this.Font = fontUIGlobal;
700             }
701
702             _brsBackColorMine = new SolidBrush(_clSelf);
703             _brsBackColorAt = new SolidBrush(_clAtSelf);
704             _brsBackColorYou = new SolidBrush(_clTarget);
705             _brsBackColorAtYou = new SolidBrush(_clAtTarget);
706             _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
707             _brsBackColorAtTo = new SolidBrush(_clAtTo);
708             //_brsBackColorNone = new SolidBrush(Color.FromKnownColor(KnownColor.Window));
709             _brsBackColorNone = new SolidBrush(_clListBackcolor);
710
711             // StringFormatオブジェクトへの事前設定
712             //sf.Alignment = StringAlignment.Near;             // Textを近くへ配置(左から右の場合は左寄せ)
713             //sf.LineAlignment = StringAlignment.Near;         // Textを近くへ配置(上寄せ)
714             //sf.FormatFlags = StringFormatFlags.LineLimit;    // 
715             sfTab.Alignment = StringAlignment.Center;
716             sfTab.LineAlignment = StringAlignment.Center;
717
718             //設定画面への反映
719             HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
720             SettingDialog.TwitterApiUrl = _cfgCommon.TwitterUrl;
721
722             //認証関連
723             if (string.IsNullOrEmpty(_cfgCommon.Token)) _cfgCommon.UserName = "";
724             tw.Initialize(_cfgCommon.Token, _cfgCommon.TokenSecret, _cfgCommon.UserName, _cfgCommon.UserId);
725
726             SettingDialog.UserAccounts = _cfgCommon.UserAccounts;
727
728             SettingDialog.TimelinePeriodInt = _cfgCommon.TimelinePeriod;
729             SettingDialog.ReplyPeriodInt = _cfgCommon.ReplyPeriod;
730             SettingDialog.DMPeriodInt = _cfgCommon.DMPeriod;
731             SettingDialog.PubSearchPeriodInt = _cfgCommon.PubSearchPeriod;
732             SettingDialog.UserTimelinePeriodInt = _cfgCommon.UserTimelinePeriod;
733             SettingDialog.ListsPeriodInt = _cfgCommon.ListsPeriod;
734             //不正値チェック
735             if (!MyApplication.StartupOptions.ContainsKey("nolimit"))
736             {
737                 if (SettingDialog.TimelinePeriodInt < 15 && SettingDialog.TimelinePeriodInt > 0) SettingDialog.TimelinePeriodInt = 15;
738                 if (SettingDialog.ReplyPeriodInt < 15 && SettingDialog.ReplyPeriodInt > 0) SettingDialog.ReplyPeriodInt = 15;
739                 if (SettingDialog.DMPeriodInt < 15 && SettingDialog.DMPeriodInt > 0) SettingDialog.DMPeriodInt = 15;
740                 if (SettingDialog.PubSearchPeriodInt < 30 && SettingDialog.PubSearchPeriodInt > 0) SettingDialog.PubSearchPeriodInt = 30;
741                 if (SettingDialog.UserTimelinePeriodInt < 15 && SettingDialog.UserTimelinePeriodInt > 0) SettingDialog.UserTimelinePeriodInt = 15;
742                 if (SettingDialog.ListsPeriodInt < 15 && SettingDialog.ListsPeriodInt > 0) SettingDialog.ListsPeriodInt = 15;
743             }
744
745             //起動時読み込み分を既読にするか。trueなら既読として処理
746             SettingDialog.Readed = _cfgCommon.Read;
747             //新着取得時のリストスクロールをするか。trueならスクロールしない
748             ListLockMenuItem.Checked = _cfgCommon.ListLock;
749             this.LockListFileMenuItem.Checked = _cfgCommon.ListLock;
750             SettingDialog.IconSz = _cfgCommon.IconSize;
751             //文末ステータス
752             SettingDialog.Status = _cfgLocal.StatusText;
753             //未読管理。trueなら未読管理する
754             SettingDialog.UnreadManage = _cfgCommon.UnreadManage;
755             //サウンド再生(タブ別設定より優先)
756             SettingDialog.PlaySound = _cfgCommon.PlaySound;
757             PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
758             this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
759             //片思い表示。trueなら片思い表示する
760             SettingDialog.OneWayLove = _cfgCommon.OneWayLove;
761             //フォント&文字色&背景色
762             SettingDialog.FontUnread = _fntUnread;
763             SettingDialog.ColorUnread = _clUnread;
764             SettingDialog.FontReaded = _fntReaded;
765             SettingDialog.ColorReaded = _clReaded;
766             SettingDialog.ColorFav = _clFav;
767             SettingDialog.ColorOWL = _clOWL;
768             SettingDialog.ColorRetweet = _clRetweet;
769             SettingDialog.FontDetail = _fntDetail;
770             SettingDialog.ColorDetail = _clDetail;
771             SettingDialog.ColorDetailLink = _clDetailLink;
772             SettingDialog.ColorDetailBackcolor = _clDetailBackcolor;
773             SettingDialog.ColorSelf = _clSelf;
774             SettingDialog.ColorAtSelf = _clAtSelf;
775             SettingDialog.ColorTarget = _clTarget;
776             SettingDialog.ColorAtTarget = _clAtTarget;
777             SettingDialog.ColorAtFromTarget = _clAtFromTarget;
778             SettingDialog.ColorAtTo = _clAtTo;
779             SettingDialog.ColorListBackcolor = _clListBackcolor;
780             SettingDialog.ColorInputBackcolor = _clInputBackcolor;
781             SettingDialog.ColorInputFont = _clInputFont;
782             SettingDialog.FontInputFont = _fntInputFont;
783
784             SettingDialog.NameBalloon = _cfgCommon.NameBalloon;
785             SettingDialog.PostCtrlEnter = _cfgCommon.PostCtrlEnter;
786             SettingDialog.PostShiftEnter = _cfgCommon.PostShiftEnter;
787
788             SettingDialog.CountApi = _cfgCommon.CountApi;
789             SettingDialog.CountApiReply = _cfgCommon.CountApiReply;
790             if (SettingDialog.CountApi < 20 || SettingDialog.CountApi > 200) SettingDialog.CountApi = 60;
791             if (SettingDialog.CountApiReply < 20 || SettingDialog.CountApiReply > 200) SettingDialog.CountApiReply = 40;
792
793             SettingDialog.BrowserPath = _cfgLocal.BrowserPath;
794             SettingDialog.PostAndGet = _cfgCommon.PostAndGet;
795             SettingDialog.UseRecommendStatus = _cfgLocal.UseRecommendStatus;
796             SettingDialog.DispUsername = _cfgCommon.DispUsername;
797             SettingDialog.CloseToExit = _cfgCommon.CloseToExit;
798             SettingDialog.MinimizeToTray = _cfgCommon.MinimizeToTray;
799             SettingDialog.DispLatestPost = _cfgCommon.DispLatestPost;
800             SettingDialog.SortOrderLock = _cfgCommon.SortOrderLock;
801             SettingDialog.ViewTabBottom = _cfgCommon.ViewTabBottom;
802             SettingDialog.TinyUrlResolve = _cfgCommon.TinyUrlResolve;
803
804             SettingDialog.SelectedProxyType = _cfgLocal.ProxyType;
805             SettingDialog.ProxyAddress = _cfgLocal.ProxyAddress;
806             SettingDialog.ProxyPort = _cfgLocal.ProxyPort;
807             SettingDialog.ProxyUser = _cfgLocal.ProxyUser;
808             SettingDialog.ProxyPassword = _cfgLocal.ProxyPassword;
809
810             SettingDialog.StartupVersion = _cfgCommon.StartupVersion;
811             SettingDialog.StartupFollowers = _cfgCommon.StartupFollowers;
812             SettingDialog.RestrictFavCheck = _cfgCommon.RestrictFavCheck;
813             SettingDialog.AlwaysTop = _cfgCommon.AlwaysTop;
814             SettingDialog.UrlConvertAuto = false;
815             //SettingDialog.UrlConvertAuto = _cfgCommon.UrlConvertAuto;
816
817             SettingDialog.UseUnreadStyle = _cfgCommon.UseUnreadStyle;
818             SettingDialog.DefaultTimeOut = _cfgCommon.DefaultTimeOut;
819             SettingDialog.RetweetNoConfirm = _cfgCommon.RetweetNoConfirm;
820             SettingDialog.PlaySound = _cfgCommon.PlaySound;
821             SettingDialog.DateTimeFormat = _cfgCommon.DateTimeFormat;
822             SettingDialog.LimitBalloon = _cfgCommon.LimitBalloon;
823             SettingDialog.EventNotifyEnabled = _cfgCommon.EventNotifyEnabled;
824             SettingDialog.EventNotifyFlag = _cfgCommon.EventNotifyFlag;
825             SettingDialog.IsMyEventNotifyFlag = _cfgCommon.IsMyEventNotifyFlag;
826             SettingDialog.ForceEventNotify = _cfgCommon.ForceEventNotify;
827             SettingDialog.FavEventUnread = _cfgCommon.FavEventUnread;
828             SettingDialog.TranslateLanguage = _cfgCommon.TranslateLanguage;
829             SettingDialog.EventSoundFile = _cfgCommon.EventSoundFile;
830
831             //廃止サービスが選択されていた場合bit.lyへ読み替え
832             if (_cfgCommon.AutoShortUrlFirst < 0)
833                 _cfgCommon.AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
834
835             SettingDialog.AutoShortUrlFirst = _cfgCommon.AutoShortUrlFirst;
836             SettingDialog.TabIconDisp = _cfgCommon.TabIconDisp;
837             SettingDialog.ReplyIconState = _cfgCommon.ReplyIconState;
838             SettingDialog.ReadOwnPost = _cfgCommon.ReadOwnPost;
839             SettingDialog.GetFav = _cfgCommon.GetFav;
840             SettingDialog.ReadOldPosts = _cfgCommon.ReadOldPosts;
841             SettingDialog.BitlyUser = _cfgCommon.BilyUser;
842             SettingDialog.BitlyPwd = _cfgCommon.BitlyPwd;
843             SettingDialog.ShowGrid = _cfgCommon.ShowGrid;
844             SettingDialog.Language = _cfgCommon.Language;
845             SettingDialog.UseAtIdSupplement = _cfgCommon.UseAtIdSupplement;
846             SettingDialog.UseHashSupplement = _cfgCommon.UseHashSupplement;
847             SettingDialog.PreviewEnable = _cfgCommon.PreviewEnable;
848             AtIdSupl = new AtIdSupplement(SettingAtIdList.Load().AtIdList, "@");
849
850             SettingDialog.IsMonospace = _cfgCommon.IsMonospace;
851             if (SettingDialog.IsMonospace)
852             {
853                 detailHtmlFormatHeader = detailHtmlFormatMono1;
854                 detailHtmlFormatFooter = detailHtmlFormatMono7;
855             }
856             else
857             {
858                 detailHtmlFormatHeader = detailHtmlFormat1;
859                 detailHtmlFormatFooter = detailHtmlFormat7;
860             }
861             detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
862             if (SettingDialog.IsMonospace)
863             {
864                 detailHtmlFormatHeader += detailHtmlFormatMono6;
865             }
866             else
867             {
868                 detailHtmlFormatHeader += detailHtmlFormat6;
869             }
870             this.IdeographicSpaceToSpaceToolStripMenuItem.Checked = _cfgCommon.WideSpaceConvert;
871             this.ToolStripFocusLockMenuItem.Checked = _cfgCommon.FocusLockToStatusText;
872
873             //Regex statregex = new Regex("^0*");
874             SettingDialog.RecommendStatusText = " [TWNv" + Regex.Replace(MyCommon.fileVersion.Replace(".", ""), "^0*", "") + "]";
875
876             //書式指定文字列エラーチェック
877             try
878             {
879                 if (DateTime.Now.ToString(SettingDialog.DateTimeFormat).Length == 0)
880                 {
881                     // このブロックは絶対に実行されないはず
882                     // 変換が成功した場合にLengthが0にならない
883                     SettingDialog.DateTimeFormat = "yyyy/MM/dd H:mm:ss";
884                 }
885             }
886             catch (FormatException)
887             {
888                 // FormatExceptionが発生したら初期値を設定 (=yyyy/MM/dd H:mm:ssとみなされる)
889                 SettingDialog.DateTimeFormat = "yyyy/MM/dd H:mm:ss";
890             }
891
892             SettingDialog.Nicoms = _cfgCommon.Nicoms;
893             SettingDialog.HotkeyEnabled = _cfgCommon.HotkeyEnabled;
894             SettingDialog.HotkeyMod = _cfgCommon.HotkeyModifier;
895             SettingDialog.HotkeyKey = _cfgCommon.HotkeyKey;
896             SettingDialog.HotkeyValue = _cfgCommon.HotkeyValue;
897
898             SettingDialog.BlinkNewMentions = _cfgCommon.BlinkNewMentions;
899
900             SettingDialog.UseAdditionalCount = _cfgCommon.UseAdditionalCount;
901             SettingDialog.MoreCountApi = _cfgCommon.MoreCountApi;
902             SettingDialog.FirstCountApi = _cfgCommon.FirstCountApi;
903             SettingDialog.SearchCountApi = _cfgCommon.SearchCountApi;
904             SettingDialog.FavoritesCountApi = _cfgCommon.FavoritesCountApi;
905             SettingDialog.UserTimelineCountApi = _cfgCommon.UserTimelineCountApi;
906             SettingDialog.ListCountApi = _cfgCommon.ListCountApi;
907
908             SettingDialog.UserstreamStartup = _cfgCommon.UserstreamStartup;
909             SettingDialog.UserstreamPeriodInt = _cfgCommon.UserstreamPeriod;
910             SettingDialog.OpenUserTimeline = _cfgCommon.OpenUserTimeline;
911             SettingDialog.ListDoubleClickAction = _cfgCommon.ListDoubleClickAction;
912             SettingDialog.UserAppointUrl = _cfgCommon.UserAppointUrl;
913             SettingDialog.HideDuplicatedRetweets = _cfgCommon.HideDuplicatedRetweets;
914
915             SettingDialog.IsPreviewFoursquare = _cfgCommon.IsPreviewFoursquare;
916             SettingDialog.MapThumbnailProvider = _cfgCommon.MapThumbnailProvider;
917             SettingDialog.MapThumbnailHeight = _cfgCommon.MapThumbnailHeight;
918             SettingDialog.MapThumbnailWidth = _cfgCommon.MapThumbnailWidth;
919             SettingDialog.MapThumbnailZoom = _cfgCommon.MapThumbnailZoom;
920             SettingDialog.IsListStatusesIncludeRts = _cfgCommon.IsListsIncludeRts;
921             SettingDialog.TabMouseLock = _cfgCommon.TabMouseLock;
922             SettingDialog.IsRemoveSameEvent = _cfgCommon.IsRemoveSameEvent;
923             SettingDialog.IsNotifyUseGrowl = _cfgCommon.IsUseNotifyGrowl;
924
925             //ハッシュタグ関連
926             HashSupl = new AtIdSupplement(_cfgCommon.HashTags, "#");
927             HashMgr = new HashtagManage(HashSupl,
928                                     _cfgCommon.HashTags.ToArray(),
929                                     _cfgCommon.HashSelected,
930                                     _cfgCommon.HashIsPermanent,
931                                     _cfgCommon.HashIsHead,
932                                     _cfgCommon.HashIsNotAddToAtReply);
933             if (!string.IsNullOrEmpty(HashMgr.UseHash) && HashMgr.IsPermanent) HashStripSplitButton.Text = HashMgr.UseHash;
934
935             _initial = true;
936
937             //アイコンリスト作成
938             this.IconCache = new ImageCache();
939
940             bool saveRequired = false;
941             bool firstRun = false;
942
943             //ユーザー名、パスワードが未設定なら設定画面を表示(初回起動時など)
944             if (string.IsNullOrEmpty(tw.Username))
945             {
946                 saveRequired = true;
947                 firstRun = true;
948                 SettingDialog.ShowInTaskbar = true;
949
950                 //設定せずにキャンセルされた場合はプログラム終了
951                 if (SettingDialog.ShowDialog(this) == DialogResult.Cancel)
952                 {
953                     Application.Exit();  //強制終了
954                     return;
955                 }
956                 //設定されたが、依然ユーザー名とパスワードが未設定ならプログラム終了
957                 if (string.IsNullOrEmpty(tw.Username))
958                 {
959                     Application.Exit();  //強制終了
960                     return;
961                 }
962                 SettingDialog.ShowInTaskbar = false;
963                 //新しい設定を反映
964                 //フォント&文字色&背景色保持
965                 _fntUnread = SettingDialog.FontUnread;
966                 _clUnread = SettingDialog.ColorUnread;
967                 _fntReaded = SettingDialog.FontReaded;
968                 _clReaded = SettingDialog.ColorReaded;
969                 _clFav = SettingDialog.ColorFav;
970                 _clOWL = SettingDialog.ColorOWL;
971                 _clRetweet = SettingDialog.ColorRetweet;
972                 _fntDetail = SettingDialog.FontDetail;
973                 _clDetail = SettingDialog.ColorDetail;
974                 _clDetailLink = SettingDialog.ColorDetailLink;
975                 _clDetailBackcolor = SettingDialog.ColorDetailBackcolor;
976                 _clSelf = SettingDialog.ColorSelf;
977                 _clAtSelf = SettingDialog.ColorAtSelf;
978                 _clTarget = SettingDialog.ColorTarget;
979                 _clAtTarget = SettingDialog.ColorAtTarget;
980                 _clAtFromTarget = SettingDialog.ColorAtFromTarget;
981                 _clAtTo = SettingDialog.ColorAtTo;
982                 _clListBackcolor = SettingDialog.ColorListBackcolor;
983                 _clInputBackcolor = SettingDialog.ColorInputBackcolor;
984                 _clInputFont = SettingDialog.ColorInputFont;
985                 _fntInputFont = SettingDialog.FontInputFont;
986                 _brsBackColorMine.Dispose();
987                 _brsBackColorAt.Dispose();
988                 _brsBackColorYou.Dispose();
989                 _brsBackColorAtYou.Dispose();
990                 _brsBackColorAtFromTarget.Dispose();
991                 _brsBackColorAtTo.Dispose();
992                 _brsBackColorNone.Dispose();
993                 _brsBackColorMine = new SolidBrush(_clSelf);
994                 _brsBackColorAt = new SolidBrush(_clAtSelf);
995                 _brsBackColorYou = new SolidBrush(_clTarget);
996                 _brsBackColorAtYou = new SolidBrush(_clAtTarget);
997                 _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
998                 _brsBackColorAtTo = new SolidBrush(_clAtTo);
999                 _brsBackColorNone = new SolidBrush(_clListBackcolor);
1000
1001                 if (SettingDialog.IsMonospace)
1002                 {
1003                     detailHtmlFormatHeader = detailHtmlFormatMono1;
1004                     detailHtmlFormatFooter = detailHtmlFormatMono7;
1005                 }
1006                 else
1007                 {
1008                     detailHtmlFormatHeader = detailHtmlFormat1;
1009                     detailHtmlFormatFooter = detailHtmlFormat7;
1010                 }
1011                 detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
1012                 if (SettingDialog.IsMonospace)
1013                 {
1014                     detailHtmlFormatHeader += detailHtmlFormatMono6;
1015                 }
1016                 else
1017                 {
1018                     detailHtmlFormatHeader += detailHtmlFormat6;
1019                 }
1020                 //他の設定項目は、随時設定画面で保持している値を読み出して使用
1021             }
1022
1023             if (SettingDialog.HotkeyEnabled)
1024             {
1025                 //////グローバルホットキーの登録
1026                 HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
1027                 if ((SettingDialog.HotkeyMod & Keys.Alt) == Keys.Alt) modKey = modKey | HookGlobalHotkey.ModKeys.Alt;
1028                 if ((SettingDialog.HotkeyMod & Keys.Control) == Keys.Control) modKey = modKey | HookGlobalHotkey.ModKeys.Ctrl;
1029                 if ((SettingDialog.HotkeyMod & Keys.Shift) == Keys.Shift) modKey = modKey | HookGlobalHotkey.ModKeys.Shift;
1030                 if ((SettingDialog.HotkeyMod & Keys.LWin) == Keys.LWin) modKey = modKey | HookGlobalHotkey.ModKeys.Win;
1031
1032                 _hookGlobalHotkey.RegisterOriginalHotkey(SettingDialog.HotkeyKey, SettingDialog.HotkeyValue, modKey);
1033             }
1034
1035             //Twitter用通信クラス初期化
1036             HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
1037                                                 SettingDialog.SelectedProxyType,
1038                                                 SettingDialog.ProxyAddress,
1039                                                 SettingDialog.ProxyPort,
1040                                                 SettingDialog.ProxyUser,
1041                                                 SettingDialog.ProxyPassword);
1042
1043             tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
1044             tw.ReadOwnPost = SettingDialog.ReadOwnPost;
1045             ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
1046             ShortUrl.BitlyId = SettingDialog.BitlyUser;
1047             ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
1048             HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
1049             tw.TrackWord = _cfgCommon.TrackWord;
1050             TrackToolStripMenuItem.Checked = !String.IsNullOrEmpty(tw.TrackWord);
1051             tw.AllAtReply = _cfgCommon.AllAtReply;
1052             AllrepliesToolStripMenuItem.Checked = tw.AllAtReply;
1053
1054             //画像投稿サービス
1055             this.CreatePictureServices();
1056             SetImageServiceCombo();
1057             ImageSelectionPanel.Enabled = false;
1058
1059             SelectImageServiceComboItem(_cfgCommon.UseImageServiceName, _cfgCommon.UseImageService);
1060
1061             //ウィンドウ設定
1062             this.ClientSize = _cfgLocal.FormSize;
1063             _mySize = _cfgLocal.FormSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
1064             _myLoc = _cfgLocal.FormLocation;
1065             //タイトルバー領域
1066             if (this.WindowState != FormWindowState.Minimized)
1067             {
1068                 this.DesktopLocation = _cfgLocal.FormLocation;
1069                 Rectangle tbarRect = new Rectangle(this.Location, new Size(_mySize.Width, SystemInformation.CaptionHeight));
1070                 bool outOfScreen = true;
1071                 if (Screen.AllScreens.Length == 1)    //ハングするとの報告
1072                 {
1073                     foreach (Screen scr in Screen.AllScreens)
1074                     {
1075                         if (!Rectangle.Intersect(tbarRect, scr.Bounds).IsEmpty)
1076                         {
1077                             outOfScreen = false;
1078                             break;
1079                         }
1080                     }
1081                     if (outOfScreen)
1082                     {
1083                         this.DesktopLocation = new Point(0, 0);
1084                         _myLoc = this.DesktopLocation;
1085                     }
1086                 }
1087             }
1088             this.TopMost = SettingDialog.AlwaysTop;
1089             _mySpDis = _cfgLocal.SplitterDistance;
1090             _mySpDis2 = _cfgLocal.StatusTextHeight;
1091             _mySpDis3 = _cfgLocal.PreviewDistance;
1092             if (_mySpDis3 == -1)
1093             {
1094                 _mySpDis3 = _mySize.Width - 150;
1095                 if (_mySpDis3 < 1) _mySpDis3 = 50;
1096                 _cfgLocal.PreviewDistance = _mySpDis3;
1097             }
1098             _myAdSpDis = _cfgLocal.AdSplitterDistance;
1099             MultiLineMenuItem.Checked = _cfgLocal.StatusMultiline;
1100             //this.Tween_ClientSizeChanged(this, null);
1101             PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
1102             this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
1103             //入力欄
1104             StatusText.Font = _fntInputFont;
1105             StatusText.ForeColor = _clInputFont;
1106
1107             // NameLabel のフォントを OTBaseForm.GlobalFont に変更
1108             this.NameLabel.Font = this.ReplaceToGlobalFont(this.NameLabel.Font);
1109
1110             //全新着通知のチェック状態により、Reply&DMの新着通知有効無効切り替え(タブ別設定にするため削除予定)
1111             if (SettingDialog.UnreadManage == false)
1112             {
1113                 ReadedStripMenuItem.Enabled = false;
1114                 UnreadStripMenuItem.Enabled = false;
1115             }
1116
1117             if (SettingDialog.IsNotifyUseGrowl) gh.RegisterGrowl();
1118
1119             //タイマー設定
1120             TimerTimeline.AutoReset = true;
1121             TimerTimeline.SynchronizingObject = this;
1122             //Recent取得間隔
1123             TimerTimeline.Interval = 1000;
1124             TimerTimeline.Enabled = true;
1125
1126             //更新中アイコンアニメーション間隔
1127             TimerRefreshIcon.Interval = 200;
1128             TimerRefreshIcon.Enabled = true;
1129
1130             //状態表示部の初期化(画面右下)
1131             StatusLabel.Text = "";
1132             StatusLabel.AutoToolTip = false;
1133             StatusLabel.ToolTipText = "";
1134             //文字カウンタ初期化
1135             lblLen.Text = GetRestStatusCount(true, false).ToString();
1136
1137             ////////////////////////////////////////////////////////////////////////////////
1138             _statuses.SortOrder = (SortOrder)_cfgCommon.SortOrder;
1139             IdComparerClass.ComparerMode mode = IdComparerClass.ComparerMode.Id;
1140             switch (_cfgCommon.SortColumn)
1141             {
1142                 case 0:    //0:アイコン,5:未読マーク,6:プロテクト・フィルターマーク
1143                 case 5:
1144                 case 6:
1145                     //ソートしない
1146                     mode = IdComparerClass.ComparerMode.Id;  //Idソートに読み替え
1147                     break;
1148                 case 1:  //ニックネーム
1149                     mode = IdComparerClass.ComparerMode.Nickname;
1150                     break;
1151                 case 2:  //本文
1152                     mode = IdComparerClass.ComparerMode.Data;
1153                     break;
1154                 case 3:  //時刻=発言Id
1155                     mode = IdComparerClass.ComparerMode.Id;
1156                     break;
1157                 case 4:  //名前
1158                     mode = IdComparerClass.ComparerMode.Name;
1159                     break;
1160                 case 7:  //Source
1161                     mode = IdComparerClass.ComparerMode.Source;
1162                     break;
1163             }
1164             _statuses.SortMode = mode;
1165             ////////////////////////////////////////////////////////////////////////////////
1166
1167             switch (SettingDialog.IconSz)
1168             {
1169                 case MyCommon.IconSizes.IconNone:
1170                     _iconSz = 0;
1171                     break;
1172                 case MyCommon.IconSizes.Icon16:
1173                     _iconSz = 16;
1174                     break;
1175                 case MyCommon.IconSizes.Icon24:
1176                     _iconSz = 26;
1177                     break;
1178                 case MyCommon.IconSizes.Icon48:
1179                     _iconSz = 48;
1180                     break;
1181                 case MyCommon.IconSizes.Icon48_2:
1182                     _iconSz = 48;
1183                     _iconCol = true;
1184                     break;
1185             }
1186             if (_iconSz == 0)
1187             {
1188                 tw.GetIcon = false;
1189             }
1190             else
1191             {
1192                 tw.GetIcon = true;
1193                 tw.IconSize = _iconSz;
1194             }
1195             tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
1196
1197             //発言詳細部アイコンをリストアイコンにサイズ変更
1198             int sz = _iconSz;
1199             if (_iconSz == 0)
1200             {
1201                 sz = 16;
1202             }
1203
1204             StatusLabel.Text = Properties.Resources.Form1_LoadText1;       //画面右下の状態表示を変更
1205             StatusLabelUrl.Text = "";            //画面左下のリンク先URL表示部を初期化
1206             NameLabel.Text = "";                 //発言詳細部名前ラベル初期化
1207             DateTimeLabel.Text = "";             //発言詳細部日時ラベル初期化
1208             SourceLinkLabel.Text = "";           //Source部分初期化
1209
1210             //<<<<<<<<タブ関連>>>>>>>
1211             //デフォルトタブの存在チェック、ない場合には追加
1212             if (_statuses.GetTabByType(MyCommon.TabUsageType.Home) == null)
1213             {
1214                 TabClass tab;
1215                 if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.RECENT, out tab))
1216                 {
1217                     _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
1218                 }
1219                 else
1220                 {
1221                     tab.TabType = MyCommon.TabUsageType.Home;
1222                 }
1223             }
1224             if (_statuses.GetTabByType(MyCommon.TabUsageType.Mentions) == null)
1225             {
1226                 TabClass tab;
1227                 if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.REPLY, out tab))
1228                 {
1229                     _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
1230                 }
1231                 else
1232                 {
1233                     tab.TabType = MyCommon.TabUsageType.Mentions;
1234                 }
1235             }
1236             if (_statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage) == null)
1237             {
1238                 TabClass tab;
1239                 if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.DM, out tab))
1240                 {
1241                     _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
1242                 }
1243                 else
1244                 {
1245                     tab.TabType = MyCommon.TabUsageType.DirectMessage;
1246                 }
1247             }
1248             if (_statuses.GetTabByType(MyCommon.TabUsageType.Favorites) == null)
1249             {
1250                 TabClass tab;
1251                 if (!_statuses.Tabs.TryGetValue(MyCommon.DEFAULTTAB.FAV, out tab))
1252                 {
1253                     _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
1254                 }
1255                 else
1256                 {
1257                     tab.TabType = MyCommon.TabUsageType.Favorites;
1258                 }
1259             }
1260             foreach (string tn in _statuses.Tabs.Keys)
1261             {
1262                 if (_statuses.Tabs[tn].TabType == MyCommon.TabUsageType.Undefined)
1263                 {
1264                     _statuses.Tabs[tn].TabType = MyCommon.TabUsageType.UserDefined;
1265                 }
1266                 if (!AddNewTab(tn, true, _statuses.Tabs[tn].TabType, _statuses.Tabs[tn].ListInfo)) throw new Exception(Properties.Resources.TweenMain_LoadText1);
1267             }
1268
1269             this.JumpReadOpMenuItem.ShortcutKeyDisplayString = "Space";
1270             CopySTOTMenuItem.ShortcutKeyDisplayString = "Ctrl+C";
1271             CopyURLMenuItem.ShortcutKeyDisplayString = "Ctrl+Shift+C";
1272             CopyUserIdStripMenuItem.ShortcutKeyDisplayString = "Shift+Alt+C";
1273
1274             if (SettingDialog.MinimizeToTray == false || this.WindowState != FormWindowState.Minimized)
1275             {
1276                 this.Visible = true;
1277             }
1278             _curTab = ListTab.SelectedTab;
1279             _curItemIndex = -1;
1280             _curList = (DetailsListView)_curTab.Tag;
1281             SetMainWindowTitle();
1282             SetNotifyIconText();
1283
1284             if (SettingDialog.TabIconDisp)
1285             {
1286                 ListTab.DrawMode = TabDrawMode.Normal;
1287             }
1288             else
1289             {
1290                 ListTab.DrawMode = TabDrawMode.OwnerDrawFixed;
1291                 ListTab.DrawItem += ListTab_DrawItem;
1292                 ListTab.ImageList = null;
1293             }
1294
1295             _ignoreConfigSave = false;
1296             this.TweenMain_Resize(null, null);
1297             if (saveRequired) SaveConfigsAll(false);
1298
1299             if (tw.UserId == 0)
1300             {
1301                 tw.VerifyCredentials();
1302                 foreach (UserAccount ua in _cfgCommon.UserAccounts)
1303                 {
1304                     if (ua.Username.ToLower() == tw.Username.ToLower())
1305                     {
1306                         ua.UserId = tw.UserId;
1307                         break;
1308                     }
1309                 }
1310             }
1311             foreach (UserAccount ua in SettingDialog.UserAccounts)
1312             {
1313                 if (ua.UserId == 0 && ua.Username.ToLower() == tw.Username.ToLower())
1314                 {
1315                     ua.UserId = tw.UserId;
1316                     break;
1317                 }
1318             }
1319
1320             if (firstRun)
1321             {
1322                 // 初回起動時だけ右下のメニューを目立たせる
1323                 HashStripSplitButton.ShowDropDown();
1324             }
1325
1326             // タブの位置を調整する
1327             SetTabAlignment();
1328         }
1329
1330         private void CreatePictureServices()
1331         {
1332             if (this.pictureService != null) this.pictureService.Clear();
1333             this.pictureService = null;
1334             this.pictureService = new Dictionary<string, IMultimediaShareService> {
1335                 {"TwitPic", new TwitPic(tw)},
1336                 {"img.ly", new imgly(tw)},
1337                 {"yfrog", new yfrog(tw)},
1338                 {"Twitter", new TwitterPhoto(tw)},
1339                 {"ついっぷるフォト", new TwipplePhoto(tw)},
1340                 {"Imgur", new Imgur(tw)},
1341             };
1342         }
1343
1344         private void ListTab_DrawItem(object sender, DrawItemEventArgs e)
1345         {
1346             string txt;
1347             try
1348             {
1349                 txt = ListTab.TabPages[e.Index].Text;
1350             }
1351             catch (Exception)
1352             {
1353                 return;
1354             }
1355
1356             e.Graphics.FillRectangle(System.Drawing.SystemBrushes.Control, e.Bounds);
1357             if (e.State == DrawItemState.Selected)
1358             {
1359                 e.DrawFocusRectangle();
1360             }
1361             Brush fore;
1362             try
1363             {
1364                 if (_statuses.Tabs[txt].UnreadCount > 0)
1365                     fore = Brushes.Red;
1366                 else
1367                     fore = System.Drawing.SystemBrushes.ControlText;
1368             }
1369             catch (Exception)
1370             {
1371                 fore = System.Drawing.SystemBrushes.ControlText;
1372             }
1373             e.Graphics.DrawString(txt, e.Font, fore, e.Bounds, sfTab);
1374         }
1375
1376         private void LoadConfig()
1377         {
1378             _cfgCommon = SettingCommon.Load();
1379             if (_cfgCommon.UserAccounts == null || _cfgCommon.UserAccounts.Count == 0)
1380             {
1381                 _cfgCommon.UserAccounts = new List<UserAccount>();
1382                 if (!string.IsNullOrEmpty(_cfgCommon.UserName))
1383                 {
1384                     UserAccount account = new UserAccount();
1385                     account.Username = _cfgCommon.UserName;
1386                     account.UserId = _cfgCommon.UserId;
1387                     account.Token = _cfgCommon.Token;
1388                     account.TokenSecret = _cfgCommon.TokenSecret;
1389
1390                     _cfgCommon.UserAccounts.Add(account);
1391                 }
1392             }
1393             _cfgLocal = SettingLocal.Load();
1394             List<TabClass> tabs = SettingTabs.Load().Tabs;
1395             foreach (TabClass tb in tabs)
1396             {
1397                 try
1398                 {
1399                     _statuses.Tabs.Add(tb.TabName, tb);
1400                 }
1401                 catch (Exception)
1402                 {
1403                     tb.TabName = _statuses.GetUniqueTabName();
1404                     _statuses.Tabs.Add(tb.TabName, tb);
1405                 }
1406             }
1407             if (_statuses.Tabs.Count == 0)
1408             {
1409                 _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
1410                 _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
1411                 _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
1412                 _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
1413             }
1414         }
1415
1416         private void TimerInterval_Changed(object sender, AppendSettingDialog.IntervalChangedEventArgs e) //Handles SettingDialog.IntervalChanged
1417         {
1418             if (!TimerTimeline.Enabled) return;
1419             ResetTimers = e;
1420         }
1421
1422         private AppendSettingDialog.IntervalChangedEventArgs ResetTimers = new AppendSettingDialog.IntervalChangedEventArgs();
1423
1424         private static int homeCounter = 0;
1425         private static int mentionCounter = 0;
1426         private static int dmCounter = 0;
1427         private static int pubSearchCounter = 0;
1428         private static int userTimelineCounter = 0;
1429         private static int listsCounter = 0;
1430         private static int usCounter = 0;
1431         private static int ResumeWait = 0;
1432         private static int refreshFollowers = 0;
1433
1434         private void TimerTimeline_Elapsed(object sender, EventArgs e)
1435         {
1436             if (homeCounter > 0) Interlocked.Decrement(ref homeCounter);
1437             if (mentionCounter > 0) Interlocked.Decrement(ref mentionCounter);
1438             if (dmCounter > 0) Interlocked.Decrement(ref dmCounter);
1439             if (pubSearchCounter > 0) Interlocked.Decrement(ref pubSearchCounter);
1440             if (userTimelineCounter > 0) Interlocked.Decrement(ref userTimelineCounter);
1441             if (listsCounter > 0) Interlocked.Decrement(ref listsCounter);
1442             if (usCounter > 0) Interlocked.Decrement(ref usCounter);
1443             Interlocked.Increment(ref refreshFollowers);
1444
1445             ////タイマー初期化
1446             if (ResetTimers.Timeline || homeCounter <= 0 && SettingDialog.TimelinePeriodInt > 0)
1447             {
1448                 Interlocked.Exchange(ref homeCounter, SettingDialog.TimelinePeriodInt);
1449                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Timeline) GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
1450                 ResetTimers.Timeline = false;
1451             }
1452             if (ResetTimers.Reply || mentionCounter <= 0 && SettingDialog.ReplyPeriodInt > 0)
1453             {
1454                 Interlocked.Exchange(ref mentionCounter, SettingDialog.ReplyPeriodInt);
1455                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Reply) GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
1456                 ResetTimers.Reply = false;
1457             }
1458             if (ResetTimers.DirectMessage || dmCounter <= 0 && SettingDialog.DMPeriodInt > 0)
1459             {
1460                 Interlocked.Exchange(ref dmCounter, SettingDialog.DMPeriodInt);
1461                 if (!tw.IsUserstreamDataReceived && !ResetTimers.DirectMessage) GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
1462                 ResetTimers.DirectMessage = false;
1463             }
1464             if (ResetTimers.PublicSearch || pubSearchCounter <= 0 && SettingDialog.PubSearchPeriodInt > 0)
1465             {
1466                 Interlocked.Exchange(ref pubSearchCounter, SettingDialog.PubSearchPeriodInt);
1467                 if (!ResetTimers.PublicSearch) GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");
1468                 ResetTimers.PublicSearch = false;
1469             }
1470             if (ResetTimers.UserTimeline || userTimelineCounter <= 0 && SettingDialog.UserTimelinePeriodInt > 0)
1471             {
1472                 Interlocked.Exchange(ref userTimelineCounter, SettingDialog.UserTimelinePeriodInt);
1473                 if (!ResetTimers.UserTimeline) GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");
1474                 ResetTimers.UserTimeline = false;
1475             }
1476             if (ResetTimers.Lists || listsCounter <= 0 && SettingDialog.ListsPeriodInt > 0)
1477             {
1478                 Interlocked.Exchange(ref listsCounter, SettingDialog.ListsPeriodInt);
1479                 if (!ResetTimers.Lists) GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");
1480                 ResetTimers.Lists = false;
1481             }
1482             if (ResetTimers.UserStream || usCounter <= 0 && SettingDialog.UserstreamPeriodInt > 0)
1483             {
1484                 Interlocked.Exchange(ref usCounter, SettingDialog.UserstreamPeriodInt);
1485                 if (this._isActiveUserstream) RefreshTimeline(true);
1486                 ResetTimers.UserStream = false;
1487             }
1488             if (refreshFollowers > 6 * 3600)
1489             {
1490                 Interlocked.Exchange(ref refreshFollowers, 0);
1491                 doGetFollowersMenu();
1492                 GetTimeline(MyCommon.WORKERTYPE.NoRetweetIds, 0, 0, "");
1493                 GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
1494                 if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
1495             }
1496             if (osResumed)
1497             {
1498                 Interlocked.Increment(ref ResumeWait);
1499                 if (ResumeWait > 30)
1500                 {
1501                     osResumed = false;
1502                     Interlocked.Exchange(ref ResumeWait, 0);
1503                     GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
1504                     GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
1505                     GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
1506                     GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");
1507                     GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");
1508                     GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");
1509                     doGetFollowersMenu();
1510                     GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
1511                     if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
1512                 }
1513             }
1514         }
1515
1516         private void RefreshTimeline(bool isUserStream)
1517         {
1518             if (isUserStream) this.RefreshTasktrayIcon(true);
1519             //スクロール制御準備
1520             int smode = -1;    //-1:制御しない,-2:最新へ,その他:topitem使用
1521             long topId = GetScrollPos(ref smode);
1522             int befCnt = _curList.VirtualListSize;
1523
1524             //現在の選択状態を退避
1525             Dictionary<string, long[]> selId = new Dictionary<string, long[]>();
1526             Dictionary<string, long> focusedId = new Dictionary<string, long>();
1527             SaveSelectedStatus(selId, focusedId);
1528
1529             //mentionsの更新前件数を保持
1530             int dmCount = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).AllCount;
1531
1532             //更新確定
1533             PostClass[] notifyPosts = null;
1534             string soundFile = "";
1535             int addCount = 0;
1536             bool isMention = false;
1537             bool isDelete = false;
1538             addCount = _statuses.SubmitUpdate(ref soundFile, ref notifyPosts, ref isMention, ref isDelete, isUserStream);
1539
1540             if (MyCommon._endingFlag) return;
1541
1542             //リストに反映&選択状態復元
1543             try
1544             {
1545                 foreach (TabPage tab in ListTab.TabPages)
1546                 {
1547                     DetailsListView lst = (DetailsListView)tab.Tag;
1548                     TabClass tabInfo = _statuses.Tabs[tab.Text];
1549                     lst.BeginUpdate();
1550                     if (isDelete || lst.VirtualListSize != tabInfo.AllCount)
1551                     {
1552                         if (lst.Equals(_curList))
1553                         {
1554                             this.PurgeListViewItemCache();
1555                         }
1556                         try
1557                         {
1558                             lst.VirtualListSize = tabInfo.AllCount; //リスト件数更新
1559                         }
1560                         catch (Exception)
1561                         {
1562                             //アイコン描画不具合あり?
1563                         }
1564                         this.SelectListItem(lst,
1565                                           _statuses.IndexOf(tab.Text, selId[tab.Text]),
1566                                           _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
1567                     }
1568                     lst.EndUpdate();
1569                     if (tabInfo.UnreadCount > 0)
1570                         if (SettingDialog.TabIconDisp)
1571                             if (tab.ImageIndex == -1) tab.ImageIndex = 0; //タブアイコン
1572                 }
1573                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
1574             }
1575             catch (Exception)
1576             {
1577                 //ex.Data["Msg"] = "Ref1, UseAPI=" + SettingDialog.UseAPI.ToString();
1578                 //throw;
1579             }
1580
1581             //スクロール制御後処理
1582             if (smode != -1)
1583             {
1584                 try
1585                 {
1586                     if (befCnt != _curList.VirtualListSize)
1587                     {
1588                         switch (smode)
1589                         {
1590                             case -3:
1591                                 //最上行
1592                                 if (_curList.VirtualListSize > 0) _curList.EnsureVisible(0);
1593                                 break;
1594                             case -2:
1595                                 //最下行へ
1596                                 if (_curList.VirtualListSize > 0) _curList.EnsureVisible(_curList.VirtualListSize - 1);
1597                                 break;
1598                             case -1:
1599                                 //制御しない
1600                                 break;
1601                             default:
1602                                 //表示位置キープ
1603                                 if (_curList.VirtualListSize > 0 && _statuses.IndexOf(_curTab.Text, topId) > -1)
1604                                 {
1605                                     _curList.EnsureVisible(_curList.VirtualListSize - 1);
1606                                     _curList.EnsureVisible(_statuses.IndexOf(_curTab.Text, topId));
1607                                 }
1608                                 break;
1609                         }
1610                     }
1611                 }
1612                 catch (Exception ex)
1613                 {
1614                     ex.Data["Msg"] = "Ref2";
1615                     throw;
1616                 }
1617             }
1618
1619             //新着通知
1620             NotifyNewPosts(notifyPosts,
1621                            soundFile,
1622                            addCount,
1623                            isMention || dmCount != _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).AllCount);
1624
1625             SetMainWindowTitle();
1626             if (!StatusLabelUrl.Text.StartsWith("http")) SetStatusLabelUrl();
1627
1628             HashSupl.AddRangeItem(tw.GetHashList());
1629
1630         }
1631
1632         private long GetScrollPos(ref int smode)
1633         {
1634             long topId = -1;
1635             if (_curList != null && _curTab != null && _curList.VirtualListSize > 0)
1636             {
1637                 if (_statuses.SortMode == IdComparerClass.ComparerMode.Id)
1638                 {
1639                     if (_statuses.SortOrder == SortOrder.Ascending)
1640                     {
1641                         //Id昇順
1642                         if (ListLockMenuItem.Checked)
1643                         {
1644                             //制御しない
1645                             smode = -1;
1646                             ////現在表示位置へ強制スクロール
1647                             //if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1648                             //smode = 0;
1649                         }
1650                         else
1651                         {
1652                             //最下行が表示されていたら、最下行へ強制スクロール。最下行が表示されていなかったら制御しない
1653                             ListViewItem _item;
1654                             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);   //一番下
1655                             if (_item == null) _item = _curList.Items[_curList.VirtualListSize - 1];
1656                             if (_item.Index == _curList.VirtualListSize - 1)
1657                             {
1658                                 smode = -2;
1659                             }
1660                             else
1661                             {
1662                                 smode = -1;
1663                                 //if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1664                                 //smode = 0;
1665                             }
1666                         }
1667                     }
1668                     else
1669                     {
1670                         //Id降順
1671                         if (ListLockMenuItem.Checked)
1672                         {
1673                             //現在表示位置へ強制スクロール
1674                             if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1675                             smode = 0;
1676                         }
1677                         else
1678                         {
1679                             //最上行が表示されていたら、制御しない。最上行が表示されていなかったら、現在表示位置へ強制スクロール
1680                             ListViewItem _item;
1681
1682                             _item = _curList.GetItemAt(0, 10);     //一番上
1683                             if (_item == null) _item = _curList.Items[0];
1684                             if (_item.Index == 0)
1685                             {
1686                                 smode = -3;  //最上行
1687                             }
1688                             else
1689                             {
1690                                 if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1691                                 smode = 0;
1692                             }
1693                         }
1694                     }
1695                 }
1696                 else
1697                 {
1698                     //現在表示位置へ強制スクロール
1699                     if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1700                     smode = 0;
1701                 }
1702             }
1703             else
1704             {
1705                 smode = -1;
1706             }
1707             return topId;
1708         }
1709
1710         private void SaveSelectedStatus(Dictionary<string, long[]> selId, Dictionary<string, long> focusedId)
1711         {
1712             if (MyCommon._endingFlag) return;
1713             foreach (TabPage tab in ListTab.TabPages)
1714             {
1715                 DetailsListView lst = (DetailsListView)tab.Tag;
1716                 if (lst.SelectedIndices.Count > 0 && lst.SelectedIndices.Count < 61)
1717                 {
1718                     selId.Add(tab.Text, _statuses.GetId(tab.Text, lst.SelectedIndices));
1719                 }
1720                 else
1721                 {
1722                     selId.Add(tab.Text, new long[1] {-2});
1723                 }
1724                 if (lst.FocusedItem != null)
1725                     focusedId.Add(tab.Text, _statuses.GetId(tab.Text, lst.FocusedItem.Index));
1726                 else
1727                     focusedId.Add(tab.Text, -2);
1728             }
1729
1730         }
1731
1732         private bool BalloonRequired()
1733         {
1734             Twitter.FormattedEvent ev = new Twitter.FormattedEvent();
1735             ev.Eventtype = MyCommon.EVENTTYPE.None;
1736
1737             return BalloonRequired(ev);
1738         }
1739
1740         private bool IsEventNotifyAsEventType(MyCommon.EVENTTYPE type)
1741         {
1742             return SettingDialog.EventNotifyEnabled && (type & SettingDialog.EventNotifyFlag) != 0 || type == MyCommon.EVENTTYPE.None;
1743         }
1744
1745         private bool IsMyEventNotityAsEventType(Twitter.FormattedEvent ev)
1746         {
1747             return (ev.Eventtype & SettingDialog.IsMyEventNotifyFlag) != 0 ? true : !ev.IsMe;
1748         }
1749
1750         private bool BalloonRequired(Twitter.FormattedEvent ev)
1751         {
1752             if ((
1753                 IsEventNotifyAsEventType(ev.Eventtype) && IsMyEventNotityAsEventType(ev) &&
1754                 (NewPostPopMenuItem.Checked || (SettingDialog.ForceEventNotify && ev.Eventtype != MyCommon.EVENTTYPE.None)) &&
1755                 !_initial &&
1756                 (
1757                     (
1758                         SettingDialog.LimitBalloon &&
1759                         (
1760                             this.WindowState == FormWindowState.Minimized ||
1761                             !this.Visible ||
1762                             Form.ActiveForm == null
1763                             )
1764                         ) ||
1765                     !SettingDialog.LimitBalloon
1766                     )
1767                 ) &&
1768                 !Win32Api.IsScreenSaverRunning())
1769             {
1770                 return true;
1771             }
1772             else
1773             {
1774                 return false;
1775             }
1776         }
1777
1778         private void NotifyNewPosts(PostClass[] notifyPosts, string soundFile, int addCount, bool newMentions)
1779         {
1780             if (notifyPosts != null &&
1781                 notifyPosts.Length > 0 &&
1782                 this.SettingDialog.ReadOwnPost &&
1783                 notifyPosts.All((post) => { return post.UserId == tw.UserId || post.ScreenName == tw.Username; }))
1784             {
1785                 return;
1786             }
1787
1788             //新着通知
1789             if (BalloonRequired())
1790             {
1791                 if (notifyPosts != null && notifyPosts.Length > 0)
1792                 {
1793                     //Growlは一個ずつばらして通知。ただし、3ポスト以上あるときはまとめる
1794                     if (SettingDialog.IsNotifyUseGrowl)
1795                     {
1796                         StringBuilder sb = new StringBuilder();
1797                         bool reply = false;
1798                         bool dm = false;
1799
1800                         foreach (PostClass post in notifyPosts)
1801                         {
1802                             if (!(notifyPosts.Length > 3))
1803                             {
1804                                 sb.Clear();
1805                                 reply = false;
1806                                 dm = false;
1807                             }
1808                             if (post.IsReply && !post.IsExcludeReply) reply = true;
1809                             if (post.IsDm) dm = true;
1810                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
1811                             switch (SettingDialog.NameBalloon)
1812                             {
1813                                 case MyCommon.NameBalloonEnum.UserID:
1814                                     sb.Append(post.ScreenName).Append(" : ");
1815                                     break;
1816                                 case MyCommon.NameBalloonEnum.NickName:
1817                                     sb.Append(post.Nickname).Append(" : ");
1818                                     break;
1819                             }
1820                             sb.Append(post.TextFromApi);
1821                             if (notifyPosts.Length > 3)
1822                             {
1823                                 if (notifyPosts.Last() != post) continue;
1824                             }
1825
1826                             StringBuilder title = new StringBuilder();
1827                             GrowlHelper.NotifyType nt;
1828                             if (SettingDialog.DispUsername)
1829                             {
1830                                 title.Append(tw.Username);
1831                                 title.Append(" - ");
1832                             }
1833                             else
1834                             {
1835                                 //title.Clear();
1836                             }
1837                             if (dm)
1838                             {
1839                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1840                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
1841                                 title.Append(Application.ProductName);
1842                                 title.Append(" [DM] ");
1843                                 title.Append(Properties.Resources.RefreshDirectMessageText1);
1844                                 title.Append(" ");
1845                                 title.Append(addCount);
1846                                 title.Append(Properties.Resources.RefreshDirectMessageText2);
1847                                 nt = GrowlHelper.NotifyType.DirectMessage;
1848                             }
1849                             else if (reply)
1850                             {
1851                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1852                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1853                                 title.Append(Application.ProductName);
1854                                 title.Append(" [Reply!] ");
1855                                 title.Append(Properties.Resources.RefreshTimelineText1);
1856                                 title.Append(" ");
1857                                 title.Append(addCount);
1858                                 title.Append(Properties.Resources.RefreshTimelineText2);
1859                                 nt = GrowlHelper.NotifyType.Reply;
1860                             }
1861                             else
1862                             {
1863                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
1864                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1865                                 title.Append(Application.ProductName);
1866                                 title.Append(" ");
1867                                 title.Append(Properties.Resources.RefreshTimelineText1);
1868                                 title.Append(" ");
1869                                 title.Append(addCount);
1870                                 title.Append(Properties.Resources.RefreshTimelineText2);
1871                                 nt = GrowlHelper.NotifyType.Notify;
1872                             }
1873                             string bText = sb.ToString();
1874                             if (string.IsNullOrEmpty(bText)) return;
1875
1876                             var image = this.IconCache.TryGetFromCache(post.ImageUrl);
1877                             gh.Notify(nt, post.StatusId.ToString(), title.ToString(), bText, image == null ? null : image.Image, post.ImageUrl);
1878                         }
1879                     }
1880                     else
1881                     {
1882                         StringBuilder sb = new StringBuilder();
1883                         bool reply = false;
1884                         bool dm = false;
1885                         foreach (PostClass post in notifyPosts)
1886                         {
1887                             if (post.IsReply && !post.IsExcludeReply) reply = true;
1888                             if (post.IsDm) dm = true;
1889                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
1890                             switch (SettingDialog.NameBalloon)
1891                             {
1892                                 case MyCommon.NameBalloonEnum.UserID:
1893                                     sb.Append(post.ScreenName).Append(" : ");
1894                                     break;
1895                                 case MyCommon.NameBalloonEnum.NickName:
1896                                     sb.Append(post.Nickname).Append(" : ");
1897                                     break;
1898                             }
1899                             sb.Append(post.TextFromApi);
1900
1901                         }
1902                         //if (SettingDialog.DispUsername) { NotifyIcon1.BalloonTipTitle = tw.Username + " - "; } else { NotifyIcon1.BalloonTipTitle = ""; }
1903                         StringBuilder title = new StringBuilder();
1904                         ToolTipIcon ntIcon;
1905                         if (SettingDialog.DispUsername)
1906                         {
1907                             title.Append(tw.Username);
1908                             title.Append(" - ");
1909                         }
1910                         else
1911                         {
1912                             //title.Clear();
1913                         }
1914                         if (dm)
1915                         {
1916                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1917                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
1918                             ntIcon = ToolTipIcon.Warning;
1919                             title.Append(Application.ProductName);
1920                             title.Append(" [DM] ");
1921                             title.Append(Properties.Resources.RefreshDirectMessageText1);
1922                             title.Append(" ");
1923                             title.Append(addCount);
1924                             title.Append(Properties.Resources.RefreshDirectMessageText2);
1925                         }
1926                         else if (reply)
1927                         {
1928                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1929                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1930                             ntIcon = ToolTipIcon.Warning;
1931                             title.Append(Application.ProductName);
1932                             title.Append(" [Reply!] ");
1933                             title.Append(Properties.Resources.RefreshTimelineText1);
1934                             title.Append(" ");
1935                             title.Append(addCount);
1936                             title.Append(Properties.Resources.RefreshTimelineText2);
1937                         }
1938                         else
1939                         {
1940                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
1941                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1942                             ntIcon = ToolTipIcon.Info;
1943                             title.Append(Application.ProductName);
1944                             title.Append(" ");
1945                             title.Append(Properties.Resources.RefreshTimelineText1);
1946                             title.Append(" ");
1947                             title.Append(addCount);
1948                             title.Append(Properties.Resources.RefreshTimelineText2);
1949                         }
1950                         string bText = sb.ToString();
1951                         if (string.IsNullOrEmpty(bText)) return;
1952                         //NotifyIcon1.BalloonTipText = sb.ToString();
1953                         //NotifyIcon1.ShowBalloonTip(500);
1954                         NotifyIcon1.BalloonTipTitle = title.ToString();
1955                         NotifyIcon1.BalloonTipText = bText;
1956                         NotifyIcon1.BalloonTipIcon = ntIcon;
1957                         NotifyIcon1.ShowBalloonTip(500);
1958                     }
1959                 }
1960             }
1961
1962             //サウンド再生
1963             if (!_initial && SettingDialog.PlaySound && !string.IsNullOrEmpty(soundFile))
1964             {
1965                 try
1966                 {
1967                     string dir = Application.StartupPath;
1968                     if (Directory.Exists(Path.Combine(dir, "Sounds")))
1969                     {
1970                         dir = Path.Combine(dir, "Sounds");
1971                     }
1972                     using (SoundPlayer player = new SoundPlayer(Path.Combine(dir, soundFile)))
1973                     {
1974                         player.Play();
1975                     }
1976                 }
1977                 catch (Exception)
1978                 {
1979                 }
1980             }
1981
1982             //mentions新着時に画面ブリンク
1983             if (!_initial && SettingDialog.BlinkNewMentions && newMentions && Form.ActiveForm == null)
1984             {
1985                 Win32Api.FlashMyWindow(this.Handle, Win32Api.FlashSpecification.FlashTray, 3);
1986             }
1987         }
1988
1989         private void MyList_SelectedIndexChanged(object sender, EventArgs e)
1990         {
1991             if (_curList == null || !_curList.Equals(sender) || _curList.SelectedIndices.Count != 1) return;
1992
1993             _curItemIndex = _curList.SelectedIndices[0];
1994             if (_curItemIndex > _curList.VirtualListSize - 1) return;
1995
1996             try
1997             {
1998                 _curPost = GetCurTabPost(_curItemIndex);
1999             }
2000             catch (ArgumentException)
2001             {
2002                 return;
2003             }
2004
2005             this.PushSelectPostChain();
2006
2007             if (SettingDialog.UnreadManage) _statuses.SetReadAllTab(true, _curTab.Text, _curItemIndex);
2008             //キャッシュの書き換え
2009             ChangeCacheStyleRead(true, _curItemIndex, _curTab);   //既読へ(フォント、文字色)
2010
2011             ColorizeList();
2012             _colorize = true;
2013         }
2014
2015         private void ChangeCacheStyleRead(bool Read, int Index, TabPage Tab)
2016         {
2017             //Read:true=既読 false=未読
2018             //未読管理していなかったら既読として扱う
2019             if (!_statuses.Tabs[_curTab.Text].UnreadManage ||
2020                !SettingDialog.UnreadManage) Read = true;
2021
2022             //対象の特定
2023             ListViewItem itm = null;
2024             PostClass post = null;
2025
2026             if (Tab.Equals(this._curTab))
2027             {
2028                 this.TryGetListViewItemCache(Index, out itm, out post);
2029             }
2030
2031             if (itm == null || post == null)
2032             {
2033                 itm = ((DetailsListView)Tab.Tag).Items[Index];
2034                 post = _statuses[Tab.Text, Index];
2035             }
2036
2037             ChangeItemStyleRead(Read, itm, post, ((DetailsListView)Tab.Tag));
2038         }
2039
2040         private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView DList)
2041         {
2042             Font fnt;
2043             //フォント
2044             if (Read)
2045             {
2046                 fnt = _fntReaded;
2047                 Item.SubItems[5].Text = "";
2048             }
2049             else
2050             {
2051                 fnt = _fntUnread;
2052                 Item.SubItems[5].Text = "★";
2053             }
2054             //文字色
2055             Color cl;
2056             if (Post.IsFav)
2057                 cl = _clFav;
2058             else if (Post.RetweetedId != null)
2059                 cl = _clRetweet;
2060             else if (Post.IsOwl && (Post.IsDm || SettingDialog.OneWayLove))
2061                 cl = _clOWL;
2062             else if (Read || !SettingDialog.UseUnreadStyle)
2063                 cl = _clReaded;
2064             else
2065                 cl = _clUnread;
2066
2067             if (DList == null || Item.Index == -1)
2068             {
2069                 Item.ForeColor = cl;
2070                 if (SettingDialog.UseUnreadStyle)
2071                     Item.Font = fnt;
2072             }
2073             else
2074             {
2075                 DList.Update();
2076                 if (SettingDialog.UseUnreadStyle)
2077                     DList.ChangeItemFontAndColor(Item.Index, cl, fnt);
2078                 else
2079                     DList.ChangeItemForeColor(Item.Index, cl);
2080                 //if (_itemCache != null) DList.RedrawItems(_itemCacheIndex, _itemCacheIndex + _itemCache.Length - 1, false);
2081             }
2082         }
2083
2084         private void ColorizeList()
2085         {
2086             //Index:更新対象のListviewItem.Index。Colorを返す。
2087             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
2088             PostClass _post;
2089             if (_anchorFlag)
2090                 _post = _anchorPost;
2091             else
2092                 _post = _curPost;
2093
2094             if (_post == null) return;
2095
2096             var itemColors = new Color[] { };
2097             int itemIndex = -1;
2098
2099             this.itemCacheLock.EnterReadLock();
2100             try
2101             {
2102                 if (this._itemCache == null) return;
2103
2104                 var query = 
2105                     from i in Enumerable.Range(0, this._itemCache.Length)
2106                     select this.JudgeColor(_post, this._postCache[i]);
2107                 
2108                 itemColors = query.ToArray();
2109                 itemIndex = _itemCacheIndex;
2110             }
2111             finally { this.itemCacheLock.ExitReadLock(); }
2112
2113             if (itemIndex < 0) return;
2114
2115             foreach (var backColor in itemColors)
2116             {
2117                 // この処理中に MyList_CacheVirtualItems が呼ばれることがあるため、
2118                 // 同一スレッド内での二重ロックを避けるためにロックの外で実行する必要がある
2119                 _curList.ChangeItemBackColor(itemIndex++, backColor);
2120             }
2121         }
2122
2123         private void ColorizeList(ListViewItem Item, int Index)
2124         {
2125             //Index:更新対象のListviewItem.Index。Colorを返す。
2126             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
2127             PostClass _post;
2128             if (_anchorFlag)
2129                 _post = _anchorPost;
2130             else
2131                 _post = _curPost;
2132
2133             PostClass tPost = GetCurTabPost(Index);
2134
2135             if (_post == null) return;
2136
2137             if (Item.Index == -1)
2138                 Item.BackColor = JudgeColor(_post, tPost);
2139             else
2140                 _curList.ChangeItemBackColor(Item.Index, JudgeColor(_post, tPost));
2141         }
2142
2143         private Color JudgeColor(PostClass BasePost, PostClass TargetPost)
2144         {
2145             Color cl;
2146             if (TargetPost.StatusId == BasePost.InReplyToStatusId)
2147                 //@先
2148                 cl = _clAtTo;
2149             else if (TargetPost.IsMe)
2150                 //自分=発言者
2151                 cl = _clSelf;
2152             else if (TargetPost.IsReply)
2153                 //自分宛返信
2154                 cl = _clAtSelf;
2155             else if (BasePost.ReplyToList.Contains(TargetPost.ScreenName.ToLower()))
2156                 //返信先
2157                 cl = _clAtFromTarget;
2158             else if (TargetPost.ReplyToList.Contains(BasePost.ScreenName.ToLower()))
2159                 //その人への返信
2160                 cl = _clAtTarget;
2161             else if (TargetPost.ScreenName.Equals(BasePost.ScreenName, StringComparison.OrdinalIgnoreCase))
2162                 //発言者
2163                 cl = _clTarget;
2164             else
2165                 //その他
2166                 cl = _clListBackcolor;
2167
2168             return cl;
2169         }
2170
2171         private void PostButton_Click(object sender, EventArgs e)
2172         {
2173             if (StatusText.Text.Trim().Length == 0)
2174             {
2175                 if (!ImageSelectionPanel.Enabled)
2176                 {
2177                     DoRefresh();
2178                     return;
2179                 }
2180             }
2181
2182             if (this.ExistCurrentPost && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", _curPost.ScreenName, _curPost.TextFromApi))
2183             {
2184                 DialogResult rtResult = MessageBox.Show(string.Format(Properties.Resources.PostButton_Click1, Environment.NewLine),
2185                                                                "Retweet",
2186                                                                MessageBoxButtons.YesNoCancel,
2187                                                                MessageBoxIcon.Question);
2188                 switch (rtResult)
2189                 {
2190                     case DialogResult.Yes:
2191                         doReTweetOfficial(false);
2192                         StatusText.Text = "";
2193                         return;
2194                     case DialogResult.Cancel:
2195                         return;
2196                 }
2197             }
2198
2199             _history[_history.Count - 1] = new PostingStatus(StatusText.Text, _reply_to_id, _reply_to_name);
2200
2201             if (SettingDialog.Nicoms)
2202             {
2203                 StatusText.SelectionStart = StatusText.Text.Length;
2204                 UrlConvert(MyCommon.UrlConverter.Nicoms);
2205             }
2206             //if (SettingDialog.UrlConvertAuto)
2207             //{
2208             //    StatusText.SelectionStart = StatusText.Text.Length;
2209             //    UrlConvertAutoToolStripMenuItem_Click(null, null);
2210             //}
2211             //else if (SettingDialog.Nicoms)
2212             //{
2213             //    StatusText.SelectionStart = StatusText.Text.Length;
2214             //    UrlConvert(UrlConverter.Nicoms);
2215             //}
2216             StatusText.SelectionStart = StatusText.Text.Length;
2217             GetWorkerArg args = new GetWorkerArg();
2218             args.page = 0;
2219             args.endPage = 0;
2220             args.type = MyCommon.WORKERTYPE.PostMessage;
2221             CheckReplyTo(StatusText.Text);
2222
2223             //整形によって増加する文字数を取得
2224             int adjustCount = 0;
2225             string tmpStatus = StatusText.Text.Trim();
2226             if (ToolStripMenuItemApiCommandEvasion.Checked)
2227             {
2228                 // APIコマンド回避
2229                 if (Regex.IsMatch(tmpStatus,
2230                     @"^[+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]*(get|g|fav|follow|f|on|off|stop|quit|leave|l|whois|w|nudge|n|stats|invite|track|untrack|tracks|tracking|\*)([+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]+|$)",
2231                     RegexOptions.IgnoreCase)
2232                    && tmpStatus.EndsWith(" .") == false) adjustCount += 2;
2233             }
2234
2235             if (ToolStripMenuItemUrlMultibyteSplit.Checked)
2236             {
2237                 // URLと全角文字の切り離し
2238                 adjustCount += Regex.Matches(tmpStatus, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+").Count;
2239             }
2240
2241             bool isCutOff = false;
2242             bool isRemoveFooter = MyCommon.IsKeyDown(Keys.Shift);
2243             if (StatusText.Multiline && !SettingDialog.PostCtrlEnter)
2244             {
2245                 //複数行でEnter投稿の場合、Ctrlも押されていたらフッタ付加しない
2246                 isRemoveFooter = MyCommon.IsKeyDown(Keys.Control);
2247             }
2248             if (SettingDialog.PostShiftEnter)
2249             {
2250                 isRemoveFooter = MyCommon.IsKeyDown(Keys.Control);
2251             }
2252             if (!isRemoveFooter && (StatusText.Text.Contains("RT @") || StatusText.Text.Contains("QT @")))
2253             {
2254                 isRemoveFooter = true;
2255             }
2256             if (GetRestStatusCount(false, !isRemoveFooter) - adjustCount < 0)
2257             {
2258                 if (MessageBox.Show(Properties.Resources.PostLengthOverMessage1, Properties.Resources.PostLengthOverMessage2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK)
2259                 {
2260                     isCutOff = true;
2261                     //if (!SettingDialog.UrlConvertAuto) UrlConvertAutoToolStripMenuItem_Click(null, null);
2262                     if (GetRestStatusCount(false, !isRemoveFooter) - adjustCount < 0)
2263                     {
2264                         isRemoveFooter = true;
2265                     }
2266                 }
2267                 else
2268                 {
2269                     return;
2270                 }
2271             }
2272
2273             string footer = "";
2274             string header = "";
2275             if (StatusText.Text.StartsWith("D ") || StatusText.Text.StartsWith("d "))
2276             {
2277                 //DM時は何もつけない
2278                 footer = "";
2279             }
2280             else
2281             {
2282                 //ハッシュタグ
2283                 if (HashMgr.IsNotAddToAtReply)
2284                 {
2285                     if (!string.IsNullOrEmpty(HashMgr.UseHash) && _reply_to_id == null && string.IsNullOrEmpty(_reply_to_name))
2286                     {
2287                         if (HashMgr.IsHead)
2288                             header = HashMgr.UseHash + " ";
2289                         else
2290                             footer = " " + HashMgr.UseHash;
2291                     }
2292                 }
2293                 else
2294                 {
2295                     if (!string.IsNullOrEmpty(HashMgr.UseHash))
2296                     {
2297                         if (HashMgr.IsHead)
2298                             header = HashMgr.UseHash + " ";
2299                         else
2300                             footer = " " + HashMgr.UseHash;
2301                     }
2302                 }
2303                 if (!isRemoveFooter)
2304                 {
2305                     if (SettingDialog.UseRecommendStatus)
2306                         // 推奨ステータスを使用する
2307                         footer += SettingDialog.RecommendStatusText;
2308                     else
2309                         // テキストボックスに入力されている文字列を使用する
2310                         footer += " " + SettingDialog.Status.Trim();
2311                 }
2312             }
2313             args.status.status = header + StatusText.Text + footer;
2314
2315             if (ToolStripMenuItemApiCommandEvasion.Checked)
2316             {
2317                 // APIコマンド回避
2318                 if (Regex.IsMatch(args.status.status,
2319                     @"^[+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]*(get|g|fav|follow|f|on|off|stop|quit|leave|l|whois|w|nudge|n|stats|invite|track|untrack|tracks|tracking|\*)([+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]+|$)",
2320                     RegexOptions.IgnoreCase)
2321                    && args.status.status.EndsWith(" .") == false) args.status.status += " .";
2322             }
2323
2324             if (ToolStripMenuItemUrlMultibyteSplit.Checked)
2325             {
2326                 // URLと全角文字の切り離し
2327                 Match mc2 = Regex.Match(args.status.status, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+");
2328                 if (mc2.Success) args.status.status = Regex.Replace(args.status.status, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+", "$& ");
2329             }
2330
2331             if (IdeographicSpaceToSpaceToolStripMenuItem.Checked)
2332             {
2333                 // 文中の全角スペースを半角スペース1個にする
2334                 args.status.status = args.status.status.Replace(" ", " ");
2335             }
2336
2337             if (isCutOff && args.status.status.Length > 140)
2338             {
2339                 args.status.status = args.status.status.Substring(0, 140);
2340                 string AtId = @"(@|@)[a-z0-9_/]+$";
2341                 string HashTag = @"(^|[^0-9A-Z&\/\?]+)(#|#)([0-9A-Z_]*[A-Z_]+)$";
2342                 string Url = @"https?:\/\/[a-z0-9!\*'\(\);:&=\+\$\/%#\[\]\-_\.,~?]+$"; //簡易判定
2343                 string pattern = string.Format("({0})|({1})|({2})", AtId, HashTag, Url);
2344                 Match mc = Regex.Match(args.status.status, pattern, RegexOptions.IgnoreCase);
2345                 if (mc.Success)
2346                 {
2347                     //さらに@ID、ハッシュタグ、URLと推測される文字列をカットする
2348                     args.status.status = args.status.status.Substring(0, 140 - mc.Value.Length);
2349                 }
2350                 if (MessageBox.Show(args.status.status, "Post or Cancel?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel) return;
2351             }
2352
2353             args.status.inReplyToId = _reply_to_id;
2354             args.status.inReplyToName = _reply_to_name;
2355             if (ImageSelectionPanel.Visible)
2356             {
2357                 //画像投稿
2358                 if (ImageSelectedPicture.Image != ImageSelectedPicture.InitialImage &&
2359                     ImageServiceCombo.SelectedIndex > -1 &&
2360                     !string.IsNullOrEmpty(ImagefilePathText.Text))
2361                 {
2362                     if (MessageBox.Show(Properties.Resources.PostPictureConfirm1,
2363                                        Properties.Resources.PostPictureConfirm2,
2364                                        MessageBoxButtons.OKCancel,
2365                                        MessageBoxIcon.Question,
2366                                        MessageBoxDefaultButton.Button1)
2367                                    == DialogResult.Cancel)
2368                     {
2369                         TimelinePanel.Visible = true;
2370                         TimelinePanel.Enabled = true;
2371                         ImageSelectionPanel.Visible = false;
2372                         ImageSelectionPanel.Enabled = false;
2373                         if (_curList != null)
2374                             _curList.Focus();
2375                         return;
2376                     }
2377                     args.status.imageService = ImageServiceCombo.Text;
2378                     args.status.imagePath = ImagefilePathText.Text;
2379                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
2380                     ImagefilePathText.Text = "";
2381                     TimelinePanel.Visible = true;
2382                     TimelinePanel.Enabled = true;
2383                     ImageSelectionPanel.Visible = false;
2384                     ImageSelectionPanel.Enabled = false;
2385                     if (_curList != null)
2386                         _curList.Focus();
2387                 }
2388                 else
2389                 {
2390                     MessageBox.Show(Properties.Resources.PostPictureWarn1, Properties.Resources.PostPictureWarn2);
2391                     return;
2392                 }
2393             }
2394
2395             RunAsync(args);
2396
2397             //Google検索(試験実装)
2398             if (StatusText.Text.StartsWith("Google:", StringComparison.OrdinalIgnoreCase) && StatusText.Text.Trim().Length > 7)
2399             {
2400                 string tmp = string.Format(Properties.Resources.SearchItem2Url, Uri.EscapeUriString(StatusText.Text.Substring(7)));
2401                 OpenUriAsync(tmp);
2402             }
2403
2404             _reply_to_id = null;
2405             _reply_to_name = null;
2406             StatusText.Text = "";
2407             _history.Add(new PostingStatus());
2408             _hisIdx = _history.Count - 1;
2409             if (!ToolStripFocusLockMenuItem.Checked)
2410                 ((Control)ListTab.SelectedTab.Tag).Focus();
2411             urlUndoBuffer = null;
2412             UrlUndoToolStripMenuItem.Enabled = false;  //Undoをできないように設定
2413         }
2414
2415         private void EndToolStripMenuItem_Click(object sender, EventArgs e)
2416         {
2417             MyCommon._endingFlag = true;
2418             this.Close();
2419         }
2420
2421         private void TweenMain_FormClosing(object sender, FormClosingEventArgs e)
2422         {
2423             if (!SettingDialog.CloseToExit && e.CloseReason == CloseReason.UserClosing && MyCommon._endingFlag == false)
2424             {
2425                 //_endingFlag=false:フォームの×ボタン
2426                 e.Cancel = true;
2427                 this.Visible = false;
2428             }
2429             else
2430             {
2431                 _hookGlobalHotkey.UnregisterAllOriginalHotkey();
2432                 _ignoreConfigSave = true;
2433                 MyCommon._endingFlag = true;
2434                 TimerTimeline.Enabled = false;
2435                 TimerRefreshIcon.Enabled = false;
2436             }
2437         }
2438
2439         private void NotifyIcon1_BalloonTipClicked(object sender, EventArgs e)
2440         {
2441             this.Visible = true;
2442             if (this.WindowState == FormWindowState.Minimized)
2443             {
2444                 this.WindowState = FormWindowState.Normal;
2445             }
2446             this.Activate();
2447             this.BringToFront();
2448         }
2449
2450         private static int errorCount = 0;
2451
2452         private static bool CheckAccountValid()
2453         {
2454             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid)
2455             {
2456                 errorCount += 1;
2457                 if (errorCount > 5)
2458                 {
2459                     errorCount = 0;
2460                     Twitter.AccountState = MyCommon.ACCOUNT_STATE.Valid;
2461                     return true;
2462                 }
2463                 return false;
2464             }
2465             errorCount = 0;
2466             return true;
2467         }
2468
2469         private void GetTimelineWorker_DoWork(object sender, DoWorkEventArgs e)
2470         {
2471             BackgroundWorker bw = (BackgroundWorker)sender;
2472             if (bw.CancellationPending || MyCommon._endingFlag)
2473             {
2474                 e.Cancel = true;
2475                 return;
2476             }
2477
2478             Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
2479
2480             MyApplication.InitCulture();
2481
2482             string ret = "";
2483             GetWorkerResult rslt = new GetWorkerResult();
2484
2485             bool read = !SettingDialog.UnreadManage;
2486             if (_initial && SettingDialog.UnreadManage) read = SettingDialog.Readed;
2487
2488             GetWorkerArg args = (GetWorkerArg)e.Argument;
2489
2490             if (!CheckAccountValid())
2491             {
2492                 rslt.retMsg = "Auth error. Check your account";
2493                 rslt.type = MyCommon.WORKERTYPE.ErrorState;  //エラー表示のみ行ない、後処理キャンセル
2494                 rslt.tName = args.tName;
2495                 e.Result = rslt;
2496                 return;
2497             }
2498
2499             bw.ReportProgress(0, ""); //Notifyアイコンアニメーション開始
2500
2501             switch (args.type)
2502             {
2503                 case MyCommon.WORKERTYPE.Timeline:
2504                 case MyCommon.WORKERTYPE.Reply:
2505                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2506                     ret = tw.GetTimelineApi(read, args.type, args.page == -1, _initial);
2507                     //新着時未読クリア
2508                     if (string.IsNullOrEmpty(ret) && args.type == MyCommon.WORKERTYPE.Timeline && SettingDialog.ReadOldPosts)
2509                         _statuses.SetRead();
2510                     //振り分け
2511                     rslt.addCount = _statuses.DistributePosts();
2512                     break;
2513                 case MyCommon.WORKERTYPE.DirectMessegeRcv:    //送信分もまとめて取得
2514                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2515                     ret = tw.GetDirectMessageApi(read, MyCommon.WORKERTYPE.DirectMessegeRcv, args.page == -1);
2516                     if (string.IsNullOrEmpty(ret)) ret = tw.GetDirectMessageApi(read, MyCommon.WORKERTYPE.DirectMessegeSnt, args.page == -1);
2517                     rslt.addCount = _statuses.DistributePosts();
2518                     break;
2519
2520                 case MyCommon.WORKERTYPE.FavAdd:
2521                 {
2522                     //スレッド処理はしない
2523                     TabClass tab;
2524                     if (_statuses.Tabs.TryGetValue(args.tName, out tab))
2525                     {
2526                         for (int i = 0; i <= args.ids.Count - 1; i++)
2527                         {
2528                             var post = tab.IsInnerStorageTabType
2529                                 ? tab.Posts[args.ids[i]]
2530                                 : _statuses[args.ids[i]];
2531
2532                             args.page = i + 1;
2533                             bw.ReportProgress(50, MakeStatusMessage(args, false));
2534                             if (!post.IsFav)
2535                             {
2536                                 if (post.RetweetedId == null)
2537                                     ret = tw.PostFavAdd(post.StatusId);
2538                                 else
2539                                     ret = tw.PostFavAdd(post.RetweetedId.Value);
2540
2541                                 if (ret.Length == 0)
2542                                 {
2543                                     args.sIds.Add(post.StatusId);
2544                                     post.IsFav = true;    //リスト再描画必要
2545                                     _favTimestamps.Add(DateTime.Now);
2546                                     if (string.IsNullOrEmpty(post.RelTabName))
2547                                     {
2548                                         //検索,リストUserTimeline.Relatedタブからのfavは、favタブへ追加せず。それ以外は追加
2549                                         _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).Add(post.StatusId, post.IsRead, false);
2550                                     }
2551                                     else
2552                                     {
2553                                         //検索,リスト,UserTimeline.Relatedタブからのfavで、TLでも取得済みならfav反映
2554                                         if (_statuses.ContainsKey(post.StatusId))
2555                                         {
2556                                             PostClass postTl = _statuses[post.StatusId];
2557                                             postTl.IsFav = true;
2558                                             _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).Add(postTl.StatusId, postTl.IsRead, false);
2559                                         }
2560                                     }
2561                                     //検索,リスト,UserTimeline,Relatedの各タブに反映
2562                                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch | MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.UserTimeline | MyCommon.TabUsageType.Related))
2563                                     {
2564                                         if (tb.Contains(post.StatusId)) tb.Posts[post.StatusId].IsFav = true;
2565                                     }
2566                                 }
2567                             }
2568                         }
2569                     }
2570                     rslt.sIds = args.sIds;
2571                     break;
2572                 }
2573
2574                 case MyCommon.WORKERTYPE.FavRemove:
2575                 {
2576                     //スレッド処理はしない
2577                     TabClass tab;
2578                     if (_statuses.Tabs.TryGetValue(args.tName, out tab))
2579                     {
2580                         for (int i = 0; i <= args.ids.Count - 1; i++)
2581                         {
2582                             var post = tab.IsInnerStorageTabType
2583                                 ? tab.Posts[args.ids[i]]
2584                                 : _statuses[args.ids[i]];
2585
2586                             args.page = i + 1;
2587                             bw.ReportProgress(50, MakeStatusMessage(args, false));
2588                             if (post.IsFav)
2589                             {
2590                                 if (post.RetweetedId == null)
2591                                     ret = tw.PostFavRemove(post.StatusId);
2592                                 else
2593                                     ret = tw.PostFavRemove(post.RetweetedId.Value);
2594
2595                                 if (ret.Length == 0)
2596                                 {
2597                                     args.sIds.Add(post.StatusId);
2598                                     post.IsFav = false;    //リスト再描画必要
2599                                     if (_statuses.ContainsKey(post.StatusId)) _statuses[post.StatusId].IsFav = false;
2600                                     //検索,リスト,UserTimeline,Relatedの各タブに反映
2601                                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch | MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.UserTimeline | MyCommon.TabUsageType.Related))
2602                                     {
2603                                         if (tb.Contains(post.StatusId)) tb.Posts[post.StatusId].IsFav = false;
2604                                     }
2605                                 }
2606                             }
2607                         }
2608                     }
2609                     rslt.sIds = args.sIds;
2610                     break;
2611                 }
2612
2613                 case MyCommon.WORKERTYPE.PostMessage:
2614                     bw.ReportProgress(200);
2615                     if (string.IsNullOrEmpty(args.status.imagePath))
2616                     {
2617                         ret = tw.PostStatus(args.status.status, args.status.inReplyToId);
2618                     }
2619                     else
2620                     {
2621                         ret = this.pictureService[args.status.imageService].Upload(ref args.status.imagePath,
2622                                                                                    ref args.status.status,
2623                                                                                    args.status.inReplyToId);
2624                     }
2625                     bw.ReportProgress(300);
2626                     rslt.status = args.status;
2627                     break;
2628                 case MyCommon.WORKERTYPE.Retweet:
2629                     bw.ReportProgress(200);
2630                     for (int i = 0; i <= args.ids.Count - 1; i++)
2631                     {
2632                         ret = tw.PostRetweet(args.ids[i], read);
2633                     }
2634                     bw.ReportProgress(300);
2635                     break;
2636                 case MyCommon.WORKERTYPE.Follower:
2637                     bw.ReportProgress(50, Properties.Resources.UpdateFollowersMenuItem1_ClickText1);
2638                     try
2639                     {
2640                         tw.RefreshFollowerIds();
2641                     }
2642                     catch (WebApiException ex) { ret = ex.Message; }
2643                     break;
2644                 case MyCommon.WORKERTYPE.NoRetweetIds:
2645                     try
2646                     {
2647                         tw.RefreshNoRetweetIds();
2648                     }
2649                     catch (WebApiException ex) { ret = ex.Message; }
2650                     break;
2651                 case MyCommon.WORKERTYPE.Configuration:
2652                     try
2653                     {
2654                         this.SettingDialog.TwitterConfiguration = tw.ConfigurationApi();
2655                     }
2656                     catch (WebApiException ex) { ret = ex.Message; }
2657                     break;
2658                 case MyCommon.WORKERTYPE.Favorites:
2659                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2660                     ret = tw.GetFavoritesApi(read, args.type, args.page == -1);
2661                     rslt.addCount = _statuses.DistributePosts();
2662                     break;
2663                 case MyCommon.WORKERTYPE.PublicSearch:
2664                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2665                     if (string.IsNullOrEmpty(args.tName))
2666                     {
2667                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch))
2668                         {
2669                             //if (!string.IsNullOrEmpty(tb.SearchWords)) ret = tw.GetPhoenixSearch(read, tb, false);
2670                             if (!string.IsNullOrEmpty(tb.SearchWords)) ret = tw.GetSearch(read, tb, false);
2671                         }
2672                     }
2673                     else
2674                     {
2675                         TabClass tb = _statuses.GetTabByName(args.tName);
2676                         if (tb != null)
2677                         {
2678                             //ret = tw.GetPhoenixSearch(read, tb, false);
2679                             ret = tw.GetSearch(read, tb, false);
2680                             if (string.IsNullOrEmpty(ret) && args.page == -1)
2681                             {
2682                                 //ret = tw.GetPhoenixSearch(read, tb, true)
2683                                 ret = tw.GetSearch(read, tb, true);
2684                             }
2685                         }
2686                     }
2687                     //振り分け
2688                     rslt.addCount = _statuses.DistributePosts();
2689                     break;
2690                 case MyCommon.WORKERTYPE.UserTimeline:
2691                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2692                     int count = 20;
2693                     if (SettingDialog.UseAdditionalCount) count = SettingDialog.UserTimelineCountApi;
2694                     if (string.IsNullOrEmpty(args.tName))
2695                     {
2696                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline))
2697                         {
2698                             if (!string.IsNullOrEmpty(tb.User)) ret = tw.GetUserTimelineApi(read, count, tb.User, tb, false);
2699                         }
2700                     }
2701                     else
2702                     {
2703                         TabClass tb = _statuses.GetTabByName(args.tName);
2704                         if (tb != null)
2705                         {
2706                             ret = tw.GetUserTimelineApi(read, count, tb.User, tb, args.page == -1);
2707                         }
2708                     }
2709                     //振り分け
2710                     rslt.addCount = _statuses.DistributePosts();
2711                     break;
2712                 case MyCommon.WORKERTYPE.List:
2713                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2714                     if (string.IsNullOrEmpty(args.tName))
2715                     {
2716                         //定期更新
2717                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists))
2718                         {
2719                             if (tb.ListInfo != null && tb.ListInfo.Id != 0) ret = tw.GetListStatus(read, tb, false, _initial);
2720                         }
2721                     }
2722                     else
2723                     {
2724                         //手動更新(特定タブのみ更新)
2725                         TabClass tb = _statuses.GetTabByName(args.tName);
2726                         if (tb != null)
2727                         {
2728                             ret = tw.GetListStatus(read, tb, args.page == -1, _initial);
2729                         }
2730                     }
2731                     //振り分け
2732                     rslt.addCount = _statuses.DistributePosts();
2733                     break;
2734
2735                 case MyCommon.WORKERTYPE.Related:
2736                 {
2737                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2738                     TabClass tab = _statuses.GetTabByName(args.tName);
2739                     ret = tw.GetRelatedResult(read, tab);
2740                     rslt.addCount = _statuses.DistributePosts();
2741                     break;
2742                 }
2743
2744                 case MyCommon.WORKERTYPE.BlockIds:
2745                     bw.ReportProgress(50, Properties.Resources.UpdateBlockUserText1);
2746                     try
2747                     {
2748                         tw.RefreshBlockIds();
2749                     }
2750                     catch (WebApiException ex) { ret = ex.Message; }
2751                     break;
2752             }
2753             //キャンセル要求
2754             if (bw.CancellationPending)
2755             {
2756                 e.Cancel = true;
2757                 return;
2758             }
2759
2760             //時速表示用
2761             if (args.type == MyCommon.WORKERTYPE.FavAdd)
2762             {
2763                 DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
2764                 for (int i = _favTimestamps.Count - 1; i >= 0; i--)
2765                 {
2766                     if (_favTimestamps[i].CompareTo(oneHour) < 0)
2767                     {
2768                         _favTimestamps.RemoveAt(i);
2769                     }
2770                 }
2771             }
2772             if (args.type == MyCommon.WORKERTYPE.Timeline && !_initial)
2773             {
2774                 lock (_syncObject)
2775                 {
2776                     DateTime tm = DateTime.Now;
2777                     if (_tlTimestamps.ContainsKey(tm))
2778                         _tlTimestamps[tm] += rslt.addCount;
2779                     else
2780                         _tlTimestamps.Add(tm, rslt.addCount);
2781
2782                     DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
2783                     List<DateTime> keys = new List<DateTime>();
2784                     _tlCount = 0;
2785                     foreach (DateTime key in _tlTimestamps.Keys)
2786                     {
2787                         if (key.CompareTo(oneHour) < 0)
2788                         {
2789                             keys.Add(key);
2790                         }
2791                         else
2792                         {
2793                             _tlCount += _tlTimestamps[key];
2794                         }
2795                     }
2796                     foreach (DateTime key in keys)
2797                     {
2798                         _tlTimestamps.Remove(key);
2799                     }
2800                     keys.Clear();
2801                 }
2802             }
2803
2804             //終了ステータス
2805             bw.ReportProgress(100, MakeStatusMessage(args, true)); //ステータス書き換え、Notifyアイコンアニメーション開始
2806
2807             rslt.retMsg = ret;
2808             rslt.type = args.type;
2809             rslt.tName = args.tName;
2810             if (args.type == MyCommon.WORKERTYPE.DirectMessegeRcv ||
2811                 args.type == MyCommon.WORKERTYPE.DirectMessegeSnt ||
2812                 args.type == MyCommon.WORKERTYPE.Reply ||
2813                 args.type == MyCommon.WORKERTYPE.Timeline ||
2814                 args.type == MyCommon.WORKERTYPE.Favorites)
2815             {
2816                 rslt.page = args.page - 1;   //値が正しいか後でチェック。10ページ毎の継続確認
2817             }
2818
2819             e.Result = rslt;
2820         }
2821
2822         private string MakeStatusMessage(GetWorkerArg AsyncArg, bool Finish)
2823         {
2824             string smsg = "";
2825             if (!Finish)
2826             {
2827                 //継続中メッセージ
2828                 switch (AsyncArg.type)
2829                 {
2830                     case MyCommon.WORKERTYPE.Timeline:
2831                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText5 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2832                         break;
2833                     case MyCommon.WORKERTYPE.Reply:
2834                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText4 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2835                         break;
2836                     case MyCommon.WORKERTYPE.DirectMessegeRcv:
2837                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText8 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2838                         break;
2839                     case MyCommon.WORKERTYPE.FavAdd:
2840                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15 + AsyncArg.page.ToString() + "/" + AsyncArg.ids.Count.ToString() +
2841                                             Properties.Resources.GetTimelineWorker_RunWorkerCompletedText16 + (AsyncArg.page - AsyncArg.sIds.Count - 1).ToString();
2842                         break;
2843                     case MyCommon.WORKERTYPE.FavRemove:
2844                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText17 + AsyncArg.page.ToString() + "/" + AsyncArg.ids.Count.ToString() +
2845                                             Properties.Resources.GetTimelineWorker_RunWorkerCompletedText18 + (AsyncArg.page - AsyncArg.sIds.Count - 1).ToString();
2846                         break;
2847                     case MyCommon.WORKERTYPE.Favorites:
2848                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText19;
2849                         break;
2850                     case MyCommon.WORKERTYPE.PublicSearch:
2851                         smsg = "Search refreshing...";
2852                         break;
2853                     case MyCommon.WORKERTYPE.List:
2854                         smsg = "List refreshing...";
2855                         break;
2856                     case MyCommon.WORKERTYPE.Related:
2857                         smsg = "Related refreshing...";
2858                         break;
2859                     case MyCommon.WORKERTYPE.UserTimeline:
2860                         smsg = "UserTimeline refreshing...";
2861                         break;
2862                 }
2863             }
2864             else
2865             {
2866                 //完了メッセージ
2867                 switch (AsyncArg.type)
2868                 {
2869                     case MyCommon.WORKERTYPE.Timeline:
2870                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText1;
2871                         break;
2872                     case MyCommon.WORKERTYPE.Reply:
2873                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText9;
2874                         break;
2875                     case MyCommon.WORKERTYPE.DirectMessegeRcv:
2876                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText11;
2877                         break;
2878                     case MyCommon.WORKERTYPE.DirectMessegeSnt:
2879                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText13;
2880                         break;
2881                     case MyCommon.WORKERTYPE.FavAdd:
2882                         //進捗メッセージ残す
2883                         break;
2884                     case MyCommon.WORKERTYPE.FavRemove:
2885                         //進捗メッセージ残す
2886                         break;
2887                     case MyCommon.WORKERTYPE.Favorites:
2888                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText20;
2889                         break;
2890                     case MyCommon.WORKERTYPE.Follower:
2891                         smsg = Properties.Resources.UpdateFollowersMenuItem1_ClickText3;
2892                         break;
2893                     case MyCommon.WORKERTYPE.NoRetweetIds:
2894                         smsg = "NoRetweetIds refreshed";
2895                         break;
2896                     case MyCommon.WORKERTYPE.Configuration:
2897                         //進捗メッセージ残す
2898                         break;
2899                     case MyCommon.WORKERTYPE.PublicSearch:
2900                         smsg = "Search refreshed";
2901                         break;
2902                     case MyCommon.WORKERTYPE.List:
2903                         smsg = "List refreshed";
2904                         break;
2905                     case MyCommon.WORKERTYPE.Related:
2906                         smsg = "Related refreshed";
2907                         break;
2908                     case MyCommon.WORKERTYPE.UserTimeline:
2909                         smsg = "UserTimeline refreshed";
2910                         break;
2911                     case MyCommon.WORKERTYPE.BlockIds:
2912                         smsg = Properties.Resources.UpdateBlockUserText3;
2913                         break;
2914                 }
2915             }
2916             return smsg;
2917         }
2918
2919         private void GetTimelineWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
2920         {
2921             if (MyCommon._endingFlag) return;
2922             if (e.ProgressPercentage > 100)
2923             {
2924                 //発言投稿
2925                 if (e.ProgressPercentage == 200)    //開始
2926                     StatusLabel.Text = "Posting...";
2927                 if (e.ProgressPercentage == 300)  //終了
2928                     StatusLabel.Text = Properties.Resources.PostWorker_RunWorkerCompletedText4;
2929             }
2930             else
2931             {
2932                 string smsg = (string)e.UserState;
2933                 if (smsg.Length > 0) StatusLabel.Text = smsg;
2934             }
2935         }
2936
2937         private void GetTimelineWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
2938         {
2939             if (MyCommon._endingFlag || e.Cancelled) return; //キャンセル
2940
2941             if (e.Error != null)
2942             {
2943                 _myStatusError = true;
2944                 _waitTimeline = false;
2945                 _waitReply = false;
2946                 _waitDm = false;
2947                 _waitFav = false;
2948                 _waitPubSearch = false;
2949                 _waitUserTimeline = false;
2950                 _waitLists = false;
2951                 throw new Exception("BackgroundWorker Exception", e.Error);
2952             }
2953
2954             GetWorkerResult rslt = (GetWorkerResult)e.Result;
2955
2956             //エラー
2957             if (rslt.retMsg.Length > 0)
2958             {
2959                 _myStatusError = true;
2960                 StatusLabel.Text = rslt.retMsg;
2961             }
2962
2963             if (rslt.type == MyCommon.WORKERTYPE.ErrorState) return;
2964
2965             if (rslt.type == MyCommon.WORKERTYPE.FavRemove)
2966             {
2967                 this.RemovePostFromFavTab(rslt.sIds.ToArray());
2968             }
2969
2970             //リストに反映
2971             //bool busy = false;
2972             //foreach (BackgroundWorker bw in _bw)
2973             //{
2974             //    if (bw != null && bw.IsBusy)
2975             //    {
2976             //        busy = true;
2977             //        break;
2978             //    }
2979             //}
2980             //if (!busy) RefreshTimeline(); //background処理なければ、リスト反映
2981             if (rslt.type == MyCommon.WORKERTYPE.Timeline ||
2982                 rslt.type == MyCommon.WORKERTYPE.Reply ||
2983                 rslt.type == MyCommon.WORKERTYPE.List ||
2984                 rslt.type == MyCommon.WORKERTYPE.PublicSearch ||
2985                 rslt.type == MyCommon.WORKERTYPE.DirectMessegeRcv ||
2986                 rslt.type == MyCommon.WORKERTYPE.DirectMessegeSnt ||
2987                 rslt.type == MyCommon.WORKERTYPE.Favorites ||
2988                 rslt.type == MyCommon.WORKERTYPE.Follower ||
2989                 rslt.type == MyCommon.WORKERTYPE.NoRetweetIds ||
2990                 rslt.type == MyCommon.WORKERTYPE.FavAdd ||
2991                 rslt.type == MyCommon.WORKERTYPE.FavRemove ||
2992                 rslt.type == MyCommon.WORKERTYPE.Related ||
2993                 rslt.type == MyCommon.WORKERTYPE.UserTimeline ||
2994                 rslt.type == MyCommon.WORKERTYPE.BlockIds ||
2995                 rslt.type == MyCommon.WORKERTYPE.Configuration)
2996             {
2997                 RefreshTimeline(false); //リスト反映
2998             }
2999
3000             switch (rslt.type)
3001             {
3002                 case MyCommon.WORKERTYPE.Timeline:
3003                     _waitTimeline = false;
3004                     if (!_initial)
3005                     {
3006                         //    //API使用時の取得調整は別途考える(カウント調整?)
3007                     }
3008                     break;
3009                 case MyCommon.WORKERTYPE.Reply:
3010                     _waitReply = false;
3011                     if (rslt.newDM && !_initial)
3012                     {
3013                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
3014                     }
3015                     break;
3016                 case MyCommon.WORKERTYPE.Favorites:
3017                     _waitFav = false;
3018                     break;
3019                 case MyCommon.WORKERTYPE.DirectMessegeRcv:
3020                     _waitDm = false;
3021                     break;
3022                 case MyCommon.WORKERTYPE.FavAdd:
3023                 case MyCommon.WORKERTYPE.FavRemove:
3024                     if (_curList != null && _curTab != null)
3025                     {
3026                         _curList.BeginUpdate();
3027                         if (rslt.type == MyCommon.WORKERTYPE.FavRemove && _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.Favorites)
3028                         {
3029                             //色変えは不要
3030                         }
3031                         else
3032                         {
3033                             for (int i = 0; i <= rslt.sIds.Count - 1; i++)
3034                             {
3035                                 if (_curTab.Text.Equals(rslt.tName))
3036                                 {
3037                                     int idx = _statuses.Tabs[rslt.tName].IndexOf(rslt.sIds[i]);
3038                                     if (idx > -1)
3039                                     {
3040                                         PostClass post = null;
3041                                         TabClass tb = _statuses.Tabs[rslt.tName];
3042                                         if (tb != null)
3043                                         {
3044                                             if (tb.TabType == MyCommon.TabUsageType.Lists || tb.TabType == MyCommon.TabUsageType.PublicSearch)
3045                                             {
3046                                                 post = tb.Posts[rslt.sIds[i]];
3047                                             }
3048                                             else
3049                                             {
3050                                                 post = _statuses[rslt.sIds[i]];
3051                                             }
3052                                             ChangeCacheStyleRead(post.IsRead, idx, _curTab);
3053                                         }
3054                                         if (idx == _curItemIndex) DispSelectedPost(true); //選択アイテム再表示
3055                                     }
3056                                 }
3057                             }
3058                         }
3059                         _curList.EndUpdate();
3060                     }
3061                     break;
3062                 case MyCommon.WORKERTYPE.PostMessage:
3063                     if (string.IsNullOrEmpty(rslt.retMsg) ||
3064                         rslt.retMsg.StartsWith("OK:") ||
3065                         rslt.retMsg == "Warn:Status is a duplicate.")
3066                     {
3067                         _postTimestamps.Add(DateTime.Now);
3068                         DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
3069                         for (int i = _postTimestamps.Count - 1; i >= 0; i--)
3070                         {
3071                             if (_postTimestamps[i].CompareTo(oneHour) < 0)
3072                             {
3073                                 _postTimestamps.RemoveAt(i);
3074                             }
3075                         }
3076
3077                         if (!HashMgr.IsPermanent && !string.IsNullOrEmpty(HashMgr.UseHash))
3078                         {
3079                             HashMgr.ClearHashtag();
3080                             this.HashStripSplitButton.Text = "#[-]";
3081                             this.HashToggleMenuItem.Checked = false;
3082                             this.HashToggleToolStripMenuItem.Checked = false;
3083                         }
3084                         SetMainWindowTitle();
3085                         rslt.retMsg = "";
3086                     }
3087                     else
3088                     {
3089                         DialogResult retry;
3090                         try
3091                         {
3092                             retry = MessageBox.Show(string.Format("{0}   --->   [ " + rslt.retMsg + " ]" + Environment.NewLine + "\"" + rslt.status.status + "\"" + Environment.NewLine + "{1}",
3093                                                                 Properties.Resources.StatusUpdateFailed1,
3094                                                                 Properties.Resources.StatusUpdateFailed2),
3095                                                             "Failed to update status",
3096                                                             MessageBoxButtons.RetryCancel,
3097                                                             MessageBoxIcon.Question);
3098                         }
3099                         catch (Exception)
3100                         {
3101                             retry = DialogResult.Abort;
3102                         }
3103                         if (retry == DialogResult.Retry)
3104                         {
3105                             GetWorkerArg args = new GetWorkerArg();
3106                             args.page = 0;
3107                             args.endPage = 0;
3108                             args.type = MyCommon.WORKERTYPE.PostMessage;
3109                             args.status = rslt.status;
3110                             RunAsync(args);
3111                         }
3112                         else
3113                         {
3114                             if (ToolStripFocusLockMenuItem.Checked)
3115                             {
3116                                 //連投モードのときだけEnterイベントが起きないので強制的に背景色を戻す
3117                                 StatusText_Enter(StatusText, new EventArgs());
3118                             }
3119                         }
3120                     }
3121                     if (rslt.retMsg.Length == 0 && SettingDialog.PostAndGet)
3122                     {
3123                         if (_isActiveUserstream)
3124                         {
3125                             RefreshTimeline(true);
3126                         }
3127                         else
3128                         {
3129                             GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3130                         }
3131                     }
3132                     break;
3133                 case MyCommon.WORKERTYPE.Retweet:
3134                     if (rslt.retMsg.Length == 0)
3135                     {
3136                         _postTimestamps.Add(DateTime.Now);
3137                         DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
3138                         for (int i = _postTimestamps.Count - 1; i >= 0; i--)
3139                         {
3140                             if (_postTimestamps[i].CompareTo(oneHour) < 0)
3141                             {
3142                                 _postTimestamps.RemoveAt(i);
3143                             }
3144                         }
3145                         if (!_isActiveUserstream && SettingDialog.PostAndGet) GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3146                     }
3147                     break;
3148                 case MyCommon.WORKERTYPE.Follower:
3149                     //_waitFollower = false;
3150                     this.PurgeListViewItemCache();
3151                     if (_curList != null) _curList.Refresh();
3152                     break;
3153                 case MyCommon.WORKERTYPE.NoRetweetIds:
3154                     break;
3155                 case MyCommon.WORKERTYPE.Configuration:
3156                     //_waitFollower = false
3157                     if (SettingDialog.TwitterConfiguration.PhotoSizeLimit != 0)
3158                     {
3159                         pictureService["Twitter"].Configuration("MaxUploadFilesize", SettingDialog.TwitterConfiguration.PhotoSizeLimit);
3160                     }
3161                     this.PurgeListViewItemCache();
3162                     if (_curList != null) _curList.Refresh();
3163                     break;
3164                 case MyCommon.WORKERTYPE.PublicSearch:
3165                     _waitPubSearch = false;
3166                     break;
3167                 case MyCommon.WORKERTYPE.UserTimeline:
3168                     _waitUserTimeline = false;
3169                     break;
3170                 case MyCommon.WORKERTYPE.List:
3171                     _waitLists = false;
3172                     break;
3173                 case MyCommon.WORKERTYPE.Related:
3174                     TabClass tab = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
3175                     if (tab != null && tab.RelationTargetPost != null && tab.Contains(tab.RelationTargetPost.StatusId))
3176                     {
3177                         foreach (TabPage tp in ListTab.TabPages)
3178                         {
3179                             if (tp.Text == tab.TabName)
3180                             {
3181                                 ((DetailsListView)tp.Tag).SelectedIndices.Add(tab.IndexOf(tab.RelationTargetPost.StatusId));
3182                                 ((DetailsListView)tp.Tag).Items[tab.IndexOf(tab.RelationTargetPost.StatusId)].Focused = true;
3183                                 break;
3184                             }
3185                         }
3186                     }
3187                     break;
3188             }
3189         }
3190
3191         private void RemovePostFromFavTab(Int64[] ids)
3192         {
3193             string favTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).TabName;
3194             int fidx = 0;
3195             if (_curTab.Text.Equals(favTabName))
3196             {
3197                 if (_curList.FocusedItem != null)
3198                     fidx = _curList.FocusedItem.Index;
3199                 else if (_curList.TopItem != null)
3200                     fidx = _curList.TopItem.Index;
3201                 else
3202                     fidx = 0;
3203             }
3204
3205             foreach (long i in ids)
3206             {
3207                 try
3208                 {
3209                     _statuses.RemoveFavPost(i);
3210                 }
3211                 catch (Exception)
3212                 {
3213                     continue;
3214                 }
3215             }
3216             if (_curTab != null && _curTab.Text.Equals(favTabName))
3217             {
3218                 this.PurgeListViewItemCache();
3219                 _curPost = null;
3220                 //_curItemIndex = -1;
3221             }
3222             foreach (TabPage tp in ListTab.TabPages)
3223             {
3224                 if (tp.Text == favTabName)
3225                 {
3226                     ((DetailsListView)tp.Tag).VirtualListSize = _statuses.Tabs[favTabName].AllCount;
3227                     break;
3228                 }
3229             }
3230             if (_curTab.Text.Equals(favTabName))
3231             {
3232                 do
3233                 {
3234                     _curList.SelectedIndices.Clear();
3235                 }
3236                 while (_curList.SelectedIndices.Count > 0);
3237
3238                 if (_statuses.Tabs[favTabName].AllCount > 0)
3239                 {
3240                     if (_statuses.Tabs[favTabName].AllCount - 1 > fidx && fidx > -1)
3241                     {
3242                         _curList.SelectedIndices.Add(fidx);
3243                     }
3244                     else
3245                     {
3246                         _curList.SelectedIndices.Add(_statuses.Tabs[favTabName].AllCount - 1);
3247                     }
3248                     if (_curList.SelectedIndices.Count > 0)
3249                     {
3250                         _curList.EnsureVisible(_curList.SelectedIndices[0]);
3251                         _curList.FocusedItem = _curList.Items[_curList.SelectedIndices[0]];
3252                     }
3253                 }
3254             }
3255         }
3256
3257         private static Dictionary<MyCommon.WORKERTYPE, DateTime> lastTime = new Dictionary<MyCommon.WORKERTYPE, DateTime>();
3258
3259         private void GetTimeline(MyCommon.WORKERTYPE WkType, int fromPage, int toPage, string tabName)
3260         {
3261             if (!this.IsNetworkAvailable()) return;
3262
3263             //非同期実行引数設定
3264             GetWorkerArg args = new GetWorkerArg();
3265             args.page = fromPage;
3266             args.endPage = toPage;
3267             args.type = WkType;
3268             args.tName = tabName;
3269
3270             if (!lastTime.ContainsKey(WkType)) lastTime.Add(WkType, new DateTime());
3271             double period = DateTime.Now.Subtract(lastTime[WkType]).TotalSeconds;
3272             if (period > 1 || period < -1)
3273             {
3274                 lastTime[WkType] = DateTime.Now;
3275                 RunAsync(args);
3276             }
3277
3278             //Timeline取得モードの場合はReplyも同時に取得
3279             //if (!SettingDialog.UseAPI &&
3280             //   !_initial &&
3281             //   WkType == MyCommon.WORKERTYPE.Timeline &&
3282             //   SettingDialog.CheckReply)
3283             //{
3284             //    //TimerReply.Enabled = false;
3285             //    _mentionCounter = SettingDialog.ReplyPeriodInt;
3286             //    GetWorkerArg _args = new GetWorkerArg();
3287             //    _args.page = fromPage;
3288             //    _args.endPage = toPage;
3289             //    _args.type = MyCommon.WORKERTYPE.Reply;
3290             //    RunAsync(_args);
3291             //}
3292         }
3293
3294         private void NotifyIcon1_MouseClick(object sender, MouseEventArgs e)
3295         {
3296             if (e.Button == MouseButtons.Left)
3297             {
3298                 this.Visible = true;
3299                 if (this.WindowState == FormWindowState.Minimized)
3300                 {
3301                     this.WindowState = _formWindowState;
3302                 }
3303                 this.Activate();
3304                 this.BringToFront();
3305             }
3306         }
3307
3308         private void MyList_MouseDoubleClick(object sender, MouseEventArgs e)
3309         {
3310             switch (SettingDialog.ListDoubleClickAction)
3311             {
3312                 case 0:
3313                     MakeReplyOrDirectStatus();
3314                     break;
3315                 case 1:
3316                     FavoriteChange(true);
3317                     break;
3318                 case 2:
3319                     if (_curPost != null)
3320                         ShowUserStatus(_curPost.ScreenName, false);
3321                     break;
3322                 case 3:
3323                     ShowUserTimeline();
3324                     break;
3325                 case 4:
3326                     ShowRelatedStatusesMenuItem_Click(null, null);
3327                     break;
3328                 case 5:
3329                     MoveToHomeToolStripMenuItem_Click(null, null);
3330                     break;
3331                 case 6:
3332                     StatusOpenMenuItem_Click(null, null);
3333                     break;
3334                 case 7:
3335                     //動作なし
3336                     break;
3337             }
3338         }
3339
3340         private void FavAddToolStripMenuItem_Click(object sender, EventArgs e)
3341         {
3342             FavoriteChange(true);
3343         }
3344
3345         private void FavRemoveToolStripMenuItem_Click(object sender, EventArgs e)
3346         {
3347             FavoriteChange(false);
3348         }
3349
3350
3351         private void FavoriteRetweetMenuItem_Click(object sender, EventArgs e)
3352         {
3353             FavoritesRetweetOriginal();
3354         }
3355
3356         private void FavoriteRetweetUnofficialMenuItem_Click(object sender, EventArgs e)
3357         {
3358             FavoritesRetweetUnofficial();
3359         }
3360
3361         private void FavoriteChange(bool FavAdd , bool multiFavoriteChangeDialogEnable = true)
3362         {
3363             //trueでFavAdd,falseでFavRemove
3364             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || _curList.SelectedIndices.Count == 0
3365                 || !this.ExistCurrentPost) return;
3366
3367             //複数fav確認msg
3368             if (_curList.SelectedIndices.Count > 250 && FavAdd)
3369             {
3370                 MessageBox.Show(Properties.Resources.FavoriteLimitCountText);
3371                 _DoFavRetweetFlags = false;
3372                 return;
3373             }
3374             else if (multiFavoriteChangeDialogEnable && _curList.SelectedIndices.Count > 1)
3375             {
3376                 if (FavAdd)
3377                 {
3378                     string QuestionText = Properties.Resources.FavAddToolStripMenuItem_ClickText1;
3379                     if (_DoFavRetweetFlags) QuestionText = Properties.Resources.FavoriteRetweetQuestionText3;
3380                     if (MessageBox.Show(QuestionText, Properties.Resources.FavAddToolStripMenuItem_ClickText2,
3381                                        MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
3382                     {
3383                         _DoFavRetweetFlags = false;
3384                         return;
3385                     }
3386                 }
3387                 else
3388                 {
3389                     if (MessageBox.Show(Properties.Resources.FavRemoveToolStripMenuItem_ClickText1, Properties.Resources.FavRemoveToolStripMenuItem_ClickText2,
3390                                     MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
3391                     {
3392                         return;
3393                     }
3394                 }
3395             }
3396
3397             GetWorkerArg args = new GetWorkerArg();
3398             args.ids = new List<long>();
3399             args.sIds = new List<long>();
3400             args.tName = _curTab.Text;
3401             if (FavAdd)
3402             {
3403                 args.type = MyCommon.WORKERTYPE.FavAdd;
3404             }
3405             else
3406             {
3407                 args.type = MyCommon.WORKERTYPE.FavRemove;
3408             }
3409             foreach (int idx in _curList.SelectedIndices)
3410             {
3411                 PostClass post = GetCurTabPost(idx);
3412                 if (FavAdd)
3413                 {
3414                     if (!post.IsFav) args.ids.Add(post.StatusId);
3415                 }
3416                 else
3417                 {
3418                     if (post.IsFav) args.ids.Add(post.StatusId);
3419                 }
3420             }
3421             if (args.ids.Count == 0)
3422             {
3423                 if (FavAdd)
3424                     StatusLabel.Text = Properties.Resources.FavAddToolStripMenuItem_ClickText4;
3425                 else
3426                     StatusLabel.Text = Properties.Resources.FavRemoveToolStripMenuItem_ClickText4;
3427
3428                 return;
3429             }
3430
3431             RunAsync(args);
3432         }
3433
3434         private PostClass GetCurTabPost(int Index)
3435         {
3436             this.itemCacheLock.EnterReadLock();
3437             try
3438             {
3439                 if (_postCache != null && Index >= _itemCacheIndex && Index < _itemCacheIndex + _postCache.Length)
3440                     return _postCache[Index - _itemCacheIndex];
3441             }
3442             finally { this.itemCacheLock.ExitReadLock(); }
3443
3444             return _statuses[_curTab.Text, Index];
3445         }
3446
3447
3448         private void MoveToHomeToolStripMenuItem_Click(object sender, EventArgs e)
3449         {
3450             if (_curList.SelectedIndices.Count > 0)
3451                 OpenUriAsync(MyCommon.TwitterUrl + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName);
3452             else if (_curList.SelectedIndices.Count == 0)
3453                 OpenUriAsync(MyCommon.TwitterUrl);
3454         }
3455
3456         private void MoveToFavToolStripMenuItem_Click(object sender, EventArgs e)
3457         {
3458             if (_curList.SelectedIndices.Count > 0)
3459                 OpenUriAsync(MyCommon.TwitterUrl + "#!/" + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName + "/favorites");
3460         }
3461
3462         private void TweenMain_ClientSizeChanged(object sender, EventArgs e)
3463         {
3464             if ((!_initialLayout) && this.Visible)
3465             {
3466                 if (this.WindowState == FormWindowState.Normal)
3467                 {
3468                     _mySize = this.ClientSize;
3469                     _mySpDis = this.SplitContainer1.SplitterDistance;
3470                     _mySpDis3 = this.SplitContainer3.SplitterDistance;
3471                     if (StatusText.Multiline) _mySpDis2 = this.StatusText.Height;
3472                     _modifySettingLocal = true;
3473                 }
3474             }
3475         }
3476
3477         private void MyList_ColumnClick(object sender, ColumnClickEventArgs e)
3478         {
3479             if (SettingDialog.SortOrderLock) return;
3480             IdComparerClass.ComparerMode mode = IdComparerClass.ComparerMode.Id;
3481             if (_iconCol)
3482             {
3483                 mode = IdComparerClass.ComparerMode.Id;
3484             }
3485             else
3486             {
3487                 switch (e.Column)
3488                 {
3489                     case 0:
3490                     case 5:
3491                     case 6:    //0:アイコン,5:未読マーク,6:プロテクト・フィルターマーク
3492                         //ソートしない
3493                         return;
3494                     case 1:  //ニックネーム
3495                         mode = IdComparerClass.ComparerMode.Nickname;
3496                         break;
3497                     case 2:  //本文
3498                         mode = IdComparerClass.ComparerMode.Data;
3499                         break;
3500                     case 3:  //時刻=発言Id
3501                         mode = IdComparerClass.ComparerMode.Id;
3502                         break;
3503                     case 4:  //名前
3504                         mode = IdComparerClass.ComparerMode.Name;
3505                         break;
3506                     case 7:  //Source
3507                         mode = IdComparerClass.ComparerMode.Source;
3508                         break;
3509                 }
3510             }
3511             _statuses.ToggleSortOrder(mode);
3512             InitColumnText();
3513
3514             DetailsListView list = (DetailsListView)sender;
3515             if (_iconCol)
3516             {
3517                 list.Columns[0].Text = ColumnOrgText[0];
3518                 list.Columns[1].Text = ColumnText[2];
3519             }
3520             else
3521             {
3522                 for (int i = 0; i <= 7; i++)
3523                 {
3524                     list.Columns[i].Text = ColumnOrgText[i];
3525                 }
3526                 list.Columns[e.Column].Text = ColumnText[e.Column];
3527             }
3528
3529             this.PurgeListViewItemCache();
3530
3531             if (_statuses.Tabs[_curTab.Text].AllCount > 0 && _curPost != null)
3532             {
3533                 int idx = _statuses.Tabs[_curTab.Text].IndexOf(_curPost.StatusId);
3534                 if (idx > -1)
3535                 {
3536                     SelectListItem(_curList, idx);
3537                     _curList.EnsureVisible(idx);
3538                 }
3539             }
3540             _curList.Refresh();
3541             _modifySettingCommon = true;
3542         }
3543
3544         private void TweenMain_LocationChanged(object sender, EventArgs e)
3545         {
3546             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
3547             {
3548                 _myLoc = this.DesktopLocation;
3549                 _modifySettingLocal = true;
3550             }
3551         }
3552
3553         private void ContextMenuOperate_Opening(object sender, CancelEventArgs e)
3554         {
3555             if (ListTab.SelectedTab == null) return;
3556             if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
3557             if (!this.ExistCurrentPost)
3558             {
3559                 ReplyStripMenuItem.Enabled = false;
3560                 ReplyAllStripMenuItem.Enabled = false;
3561                 DMStripMenuItem.Enabled = false;
3562                 ShowProfileMenuItem.Enabled = false;
3563                 ShowUserTimelineContextMenuItem.Enabled = false;
3564                 ListManageUserContextToolStripMenuItem2.Enabled = false;
3565                 MoveToFavToolStripMenuItem.Enabled = false;
3566                 TabMenuItem.Enabled = false;
3567                 IDRuleMenuItem.Enabled = false;
3568                 ReadedStripMenuItem.Enabled = false;
3569                 UnreadStripMenuItem.Enabled = false;
3570             }
3571             else
3572             {
3573                 ShowProfileMenuItem.Enabled = true;
3574                 ListManageUserContextToolStripMenuItem2.Enabled = true;
3575                 ReplyStripMenuItem.Enabled = true;
3576                 ReplyAllStripMenuItem.Enabled = true;
3577                 DMStripMenuItem.Enabled = true;
3578                 ShowUserTimelineContextMenuItem.Enabled = true;
3579                 MoveToFavToolStripMenuItem.Enabled = true;
3580                 TabMenuItem.Enabled = true;
3581                 IDRuleMenuItem.Enabled = true;
3582                 ReadedStripMenuItem.Enabled = true;
3583                 UnreadStripMenuItem.Enabled = true;
3584             }
3585             DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3586             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
3587             {
3588                 FavAddToolStripMenuItem.Enabled = false;
3589                 FavRemoveToolStripMenuItem.Enabled = false;
3590                 StatusOpenMenuItem.Enabled = false;
3591                 FavorareMenuItem.Enabled = false;
3592                 ShowRelatedStatusesMenuItem.Enabled = false;
3593
3594                 ReTweetStripMenuItem.Enabled = false;
3595                 ReTweetOriginalStripMenuItem.Enabled = false;
3596                 QuoteStripMenuItem.Enabled = false;
3597                 FavoriteRetweetContextMenu.Enabled = false;
3598                 FavoriteRetweetUnofficialContextMenu.Enabled = false;
3599                 if (this.ExistCurrentPost && _curPost.IsDm)
3600                     DeleteStripMenuItem.Enabled = true;
3601                 else
3602                     DeleteStripMenuItem.Enabled = false;
3603             }
3604             else
3605             {
3606                 FavAddToolStripMenuItem.Enabled = true;
3607                 FavRemoveToolStripMenuItem.Enabled = true;
3608                 StatusOpenMenuItem.Enabled = true;
3609                 FavorareMenuItem.Enabled = true;
3610                 ShowRelatedStatusesMenuItem.Enabled = true;  //PublicSearchの時問題出るかも
3611
3612                 if (_curPost.IsMe)
3613                 {
3614                     ReTweetOriginalStripMenuItem.Enabled = false;
3615                     FavoriteRetweetContextMenu.Enabled = false;
3616                     if (string.IsNullOrEmpty(_curPost.RetweetedBy))
3617                     {
3618                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3619                     }
3620                     else
3621                     {
3622                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText2;
3623                     }
3624                     DeleteStripMenuItem.Enabled = true;
3625                 }
3626                 else
3627                 {
3628                     if (string.IsNullOrEmpty(_curPost.RetweetedBy))
3629                     {
3630                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3631                     }
3632                     else
3633                     {
3634                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText2;
3635                     }
3636                     DeleteStripMenuItem.Enabled = false;
3637                     if (_curPost.IsProtect)
3638                     {
3639                         ReTweetOriginalStripMenuItem.Enabled = false;
3640                         ReTweetStripMenuItem.Enabled = false;
3641                         QuoteStripMenuItem.Enabled = false;
3642                         FavoriteRetweetContextMenu.Enabled = false;
3643                         FavoriteRetweetUnofficialContextMenu.Enabled = false;
3644                     }
3645                     else
3646                     {
3647                         ReTweetOriginalStripMenuItem.Enabled = true;
3648                         ReTweetStripMenuItem.Enabled = true;
3649                         QuoteStripMenuItem.Enabled = true;
3650                         FavoriteRetweetContextMenu.Enabled = true;
3651                         FavoriteRetweetUnofficialContextMenu.Enabled = true;
3652                     }
3653                 }
3654             }
3655             //if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.Favorites)
3656             //{
3657             //    RefreshMoreStripMenuItem.Enabled = true;
3658             //}
3659             //else
3660             //{
3661             //    RefreshMoreStripMenuItem.Enabled = false;
3662             //}
3663             if (!this.ExistCurrentPost
3664                 || _curPost.InReplyToStatusId == null)
3665             {
3666                 RepliedStatusOpenMenuItem.Enabled = false;
3667             }
3668             else
3669             {
3670                 RepliedStatusOpenMenuItem.Enabled = true;
3671             }
3672             if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
3673             {
3674                 MoveToRTHomeMenuItem.Enabled = false;
3675             }
3676             else
3677             {
3678                 MoveToRTHomeMenuItem.Enabled = true;
3679             }
3680         }
3681
3682         private void ReplyStripMenuItem_Click(object sender, EventArgs e)
3683         {
3684             MakeReplyOrDirectStatus(false, true);
3685         }
3686
3687         private void DMStripMenuItem_Click(object sender, EventArgs e)
3688         {
3689             MakeReplyOrDirectStatus(false, false);
3690         }
3691
3692         private void doStatusDelete()
3693         {
3694             if (_curTab == null || _curList == null) return;
3695             if (_statuses.Tabs[_curTab.Text].TabType != MyCommon.TabUsageType.DirectMessage)
3696             {
3697                 bool myPost = false;
3698                 foreach (int idx in _curList.SelectedIndices)
3699                 {
3700                     if (GetCurTabPost(idx).IsMe ||
3701                        GetCurTabPost(idx).RetweetedBy.ToLower() == tw.Username.ToLower())
3702                     {
3703                         myPost = true;
3704                         break;
3705                     }
3706                 }
3707                 if (!myPost) return;
3708             }
3709             else
3710             {
3711                 if (_curList.SelectedIndices.Count == 0)
3712                     return;
3713             }
3714
3715             string tmp = string.Format(Properties.Resources.DeleteStripMenuItem_ClickText1, Environment.NewLine);
3716
3717             if (MessageBox.Show(tmp, Properties.Resources.DeleteStripMenuItem_ClickText2,
3718                   MessageBoxButtons.OKCancel,
3719                   MessageBoxIcon.Question) == DialogResult.Cancel) return;
3720
3721             int fidx;
3722             if (_curList.FocusedItem != null)
3723                 fidx = _curList.FocusedItem.Index;
3724             else if (_curList.TopItem != null)
3725                 fidx = _curList.TopItem.Index;
3726             else
3727                 fidx = 0;
3728
3729             try
3730             {
3731                 this.Cursor = Cursors.WaitCursor;
3732
3733                 bool rslt = true;
3734                 foreach (long Id in _statuses.GetId(_curTab.Text, _curList.SelectedIndices))
3735                 {
3736                     string rtn = "";
3737                     if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)
3738                     {
3739                         rtn = tw.RemoveDirectMessage(Id, _statuses[Id]);
3740                     }
3741                     else
3742                     {
3743                         if (_statuses[Id].IsMe || _statuses[Id].RetweetedBy.ToLower() == tw.Username.ToLower())
3744                             rtn = tw.RemoveStatus(Id);
3745                         else
3746                             continue;
3747                     }
3748                     if (rtn.Length > 0)
3749                     {
3750                         //エラー
3751                         rslt = false;
3752                     }
3753                     else
3754                     {
3755                         _statuses.RemovePost(Id);
3756                     }
3757                 }
3758
3759                 if (!rslt)
3760                     StatusLabel.Text = Properties.Resources.DeleteStripMenuItem_ClickText3;  //失敗
3761                 else
3762                     StatusLabel.Text = Properties.Resources.DeleteStripMenuItem_ClickText4;  //成功
3763
3764                 this.PurgeListViewItemCache();
3765                 _curPost = null;
3766                 _curItemIndex = -1;
3767                 foreach (TabPage tb in ListTab.TabPages)
3768                 {
3769                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
3770                     if (_curTab.Equals(tb))
3771                     {
3772                         do
3773                         {
3774                             _curList.SelectedIndices.Clear();
3775                         }
3776                         while (_curList.SelectedIndices.Count > 0);
3777
3778                         if (_statuses.Tabs[tb.Text].AllCount > 0)
3779                         {
3780                             if (_statuses.Tabs[tb.Text].AllCount - 1 > fidx && fidx > -1)
3781                                 _curList.SelectedIndices.Add(fidx);
3782                             else
3783                                 _curList.SelectedIndices.Add(_statuses.Tabs[tb.Text].AllCount - 1);
3784
3785                             if (_curList.SelectedIndices.Count > 0)
3786                             {
3787                                 _curList.EnsureVisible(_curList.SelectedIndices[0]);
3788                                 _curList.FocusedItem = _curList.Items[_curList.SelectedIndices[0]];
3789                             }
3790                         }
3791                     }
3792                     if (_statuses.Tabs[tb.Text].UnreadCount == 0)
3793                     {
3794                         if (SettingDialog.TabIconDisp)
3795                         {
3796                             if (tb.ImageIndex == 0) tb.ImageIndex = -1; //タブアイコン
3797                         }
3798                     }
3799                 }
3800                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3801             }
3802             finally
3803             {
3804                 this.Cursor = Cursors.Default;
3805             }
3806         }
3807
3808         private void DeleteStripMenuItem_Click(object sender, EventArgs e)
3809         {
3810             doStatusDelete();
3811         }
3812
3813         private void ReadedStripMenuItem_Click(object sender, EventArgs e)
3814         {
3815             _curList.BeginUpdate();
3816             if (SettingDialog.UnreadManage)
3817             {
3818                 foreach (int idx in _curList.SelectedIndices)
3819                 {
3820                     _statuses.SetReadAllTab(true, _curTab.Text, idx);
3821                 }
3822             }
3823             foreach (int idx in _curList.SelectedIndices)
3824             {
3825                 ChangeCacheStyleRead(true, idx, _curTab);
3826             }
3827             ColorizeList();
3828             _curList.EndUpdate();
3829             foreach (TabPage tb in ListTab.TabPages)
3830             {
3831                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
3832                 {
3833                     if (SettingDialog.TabIconDisp)
3834                     {
3835                         if (tb.ImageIndex == 0) tb.ImageIndex = -1; //タブアイコン
3836                     }
3837                 }
3838             }
3839             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3840         }
3841
3842         private void UnreadStripMenuItem_Click(object sender, EventArgs e)
3843         {
3844             _curList.BeginUpdate();
3845             if (SettingDialog.UnreadManage)
3846             {
3847                 foreach (int idx in _curList.SelectedIndices)
3848                 {
3849                     _statuses.SetReadAllTab(false, _curTab.Text, idx);
3850                 }
3851             }
3852             foreach (int idx in _curList.SelectedIndices)
3853             {
3854                 ChangeCacheStyleRead(false, idx, _curTab);
3855             }
3856             ColorizeList();
3857             _curList.EndUpdate();
3858             foreach (TabPage tb in ListTab.TabPages)
3859             {
3860                 if (_statuses.Tabs[tb.Text].UnreadCount > 0)
3861                 {
3862                     if (SettingDialog.TabIconDisp)
3863                     {
3864                         if (tb.ImageIndex == -1) tb.ImageIndex = 0; //タブアイコン
3865                     }
3866                 }
3867             }
3868             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3869         }
3870
3871         private void RefreshStripMenuItem_Click(object sender, EventArgs e)
3872         {
3873             DoRefresh();
3874         }
3875
3876         private void DoRefresh()
3877         {
3878             if (_curTab != null)
3879             {
3880                 switch (_statuses.Tabs[_curTab.Text].TabType)
3881                 {
3882                     case MyCommon.TabUsageType.Mentions:
3883                         GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
3884                         break;
3885                     case MyCommon.TabUsageType.DirectMessage:
3886                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
3887                         break;
3888                     case MyCommon.TabUsageType.Favorites:
3889                         GetTimeline(MyCommon.WORKERTYPE.Favorites, 1, 0, "");
3890                         break;
3891                     //case MyCommon.TabUsageType.Profile:
3892                         //// TODO
3893                     case MyCommon.TabUsageType.PublicSearch:
3894                         //// TODO
3895                         TabClass tb = _statuses.Tabs[_curTab.Text];
3896                         if (string.IsNullOrEmpty(tb.SearchWords)) return;
3897                         GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, _curTab.Text);
3898                         break;
3899                     case MyCommon.TabUsageType.UserTimeline:
3900                         GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, _curTab.Text);
3901                         break;
3902                     case MyCommon.TabUsageType.Lists:
3903                         //// TODO
3904                         TabClass tab = _statuses.Tabs[_curTab.Text];
3905                         if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
3906                         GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, _curTab.Text);
3907                         break;
3908                     default:
3909                         GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3910                         break;
3911                 }
3912             }
3913             else
3914             {
3915                 GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3916             }
3917         }
3918
3919         private void DoRefreshMore()
3920         {
3921             //ページ指定をマイナス1に
3922             if (_curTab != null)
3923             {
3924                 switch (_statuses.Tabs[_curTab.Text].TabType)
3925                 {
3926                     case MyCommon.TabUsageType.Mentions:
3927                         GetTimeline(MyCommon.WORKERTYPE.Reply, -1, 0, "");
3928                         break;
3929                     case MyCommon.TabUsageType.DirectMessage:
3930                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, -1, 0, "");
3931                         break;
3932                     case MyCommon.TabUsageType.Favorites:
3933                         GetTimeline(MyCommon.WORKERTYPE.Favorites, -1, 0, "");
3934                         break;
3935                     case MyCommon.TabUsageType.Profile:
3936                         //// TODO
3937                         break;
3938                     case MyCommon.TabUsageType.PublicSearch:
3939                         // TODO
3940                         TabClass tb = _statuses.Tabs[_curTab.Text];
3941                         if (string.IsNullOrEmpty(tb.SearchWords)) return;
3942                         GetTimeline(MyCommon.WORKERTYPE.PublicSearch, -1, 0, _curTab.Text);
3943                         break;
3944                     case MyCommon.TabUsageType.UserTimeline:
3945                         GetTimeline(MyCommon.WORKERTYPE.UserTimeline, -1, 0, _curTab.Text);
3946                         break;
3947                     case MyCommon.TabUsageType.Lists:
3948                         //// TODO
3949                         TabClass tab = _statuses.Tabs[_curTab.Text];
3950                         if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
3951                         GetTimeline(MyCommon.WORKERTYPE.List, -1, 0, _curTab.Text);
3952                         break;
3953                     default:
3954                         GetTimeline(MyCommon.WORKERTYPE.Timeline, -1, 0, "");
3955                         break;
3956                 }
3957             }
3958             else
3959             {
3960                 GetTimeline(MyCommon.WORKERTYPE.Timeline, -1, 0, "");
3961             }
3962         }
3963
3964         private void SettingStripMenuItem_Click(object sender, EventArgs e)
3965         {
3966             DialogResult result;
3967             string uid = tw.Username.ToLower();
3968             var oldIconSz = SettingDialog.IconSz;
3969
3970             try
3971             {
3972                 result = SettingDialog.ShowDialog(this);
3973             }
3974             catch (Exception)
3975             {
3976                 return;
3977             }
3978
3979             if (result == DialogResult.OK)
3980             {
3981                 lock (_syncObject)
3982                 {
3983                     tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
3984                     tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
3985                     tw.ReadOwnPost = SettingDialog.ReadOwnPost;
3986                     ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
3987                     ShortUrl.BitlyId = SettingDialog.BitlyUser;
3988                     ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
3989                     HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
3990
3991                     HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
3992                                                         SettingDialog.SelectedProxyType,
3993                                                         SettingDialog.ProxyAddress,
3994                                                         SettingDialog.ProxyPort,
3995                                                         SettingDialog.ProxyUser,
3996                                                         SettingDialog.ProxyPassword);
3997                     this.CreatePictureServices();
3998
3999                     try
4000                     {
4001                         if (SettingDialog.TabIconDisp)
4002                         {
4003                             ListTab.DrawItem -= ListTab_DrawItem;
4004                             ListTab.DrawMode = TabDrawMode.Normal;
4005                             ListTab.ImageList = this.TabImage;
4006                         }
4007                         else
4008                         {
4009                             ListTab.DrawItem -= ListTab_DrawItem;
4010                             ListTab.DrawItem += ListTab_DrawItem;
4011                             ListTab.DrawMode = TabDrawMode.OwnerDrawFixed;
4012                             ListTab.ImageList = null;
4013                         }
4014                     }
4015                     catch (Exception ex)
4016                     {
4017                         ex.Data["Instance"] = "ListTab(TabIconDisp)";
4018                         ex.Data["IsTerminatePermission"] = false;
4019                         throw;
4020                     }
4021
4022                     try
4023                     {
4024                         if (!SettingDialog.UnreadManage)
4025                         {
4026                             ReadedStripMenuItem.Enabled = false;
4027                             UnreadStripMenuItem.Enabled = false;
4028                             if (SettingDialog.TabIconDisp)
4029                             {
4030                                 foreach (TabPage myTab in ListTab.TabPages)
4031                                 {
4032                                     myTab.ImageIndex = -1;
4033                                 }
4034                             }
4035                         }
4036                         else
4037                         {
4038                             ReadedStripMenuItem.Enabled = true;
4039                             UnreadStripMenuItem.Enabled = true;
4040                         }
4041                     }
4042                     catch (Exception ex)
4043                     {
4044                         ex.Data["Instance"] = "ListTab(UnreadManage)";
4045                         ex.Data["IsTerminatePermission"] = false;
4046                         throw;
4047                     }
4048
4049                     // タブの表示位置の決定
4050                     SetTabAlignment();
4051
4052                     PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
4053                     this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
4054                     _fntUnread = SettingDialog.FontUnread;
4055                     _clUnread = SettingDialog.ColorUnread;
4056                     _fntReaded = SettingDialog.FontReaded;
4057                     _clReaded = SettingDialog.ColorReaded;
4058                     _clFav = SettingDialog.ColorFav;
4059                     _clOWL = SettingDialog.ColorOWL;
4060                     _clRetweet = SettingDialog.ColorRetweet;
4061                     _fntDetail = SettingDialog.FontDetail;
4062                     _clDetail = SettingDialog.ColorDetail;
4063                     _clDetailLink = SettingDialog.ColorDetailLink;
4064                     _clDetailBackcolor = SettingDialog.ColorDetailBackcolor;
4065                     _clSelf = SettingDialog.ColorSelf;
4066                     _clAtSelf = SettingDialog.ColorAtSelf;
4067                     _clTarget = SettingDialog.ColorTarget;
4068                     _clAtTarget = SettingDialog.ColorAtTarget;
4069                     _clAtFromTarget = SettingDialog.ColorAtFromTarget;
4070                     _clAtTo = SettingDialog.ColorAtTo;
4071                     _clListBackcolor = SettingDialog.ColorListBackcolor;
4072                     _clInputBackcolor = SettingDialog.ColorInputBackcolor;
4073                     _clInputFont = SettingDialog.ColorInputFont;
4074                     _fntInputFont = SettingDialog.FontInputFont;
4075                     _brsBackColorMine.Dispose();
4076                     _brsBackColorAt.Dispose();
4077                     _brsBackColorYou.Dispose();
4078                     _brsBackColorAtYou.Dispose();
4079                     _brsBackColorAtFromTarget.Dispose();
4080                     _brsBackColorAtTo.Dispose();
4081                     _brsBackColorNone.Dispose();
4082                     _brsBackColorMine = new SolidBrush(_clSelf);
4083                     _brsBackColorAt = new SolidBrush(_clAtSelf);
4084                     _brsBackColorYou = new SolidBrush(_clTarget);
4085                     _brsBackColorAtYou = new SolidBrush(_clAtTarget);
4086                     _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
4087                     _brsBackColorAtTo = new SolidBrush(_clAtTo);
4088                     _brsBackColorNone = new SolidBrush(_clListBackcolor);
4089
4090                     try
4091                     {
4092                         if (StatusText.Focused) StatusText.BackColor = _clInputBackcolor;
4093                         StatusText.Font = _fntInputFont;
4094                         StatusText.ForeColor = _clInputFont;
4095                     }
4096                     catch (Exception ex)
4097                     {
4098                         MessageBox.Show(ex.Message);
4099                     }
4100
4101                     try
4102                     {
4103                         if (SettingDialog.IsMonospace)
4104                         {
4105                             detailHtmlFormatHeader = detailHtmlFormatMono1;
4106                             detailHtmlFormatFooter = detailHtmlFormatMono7;
4107                         }
4108                         else
4109                         {
4110                             detailHtmlFormatHeader = detailHtmlFormat1;
4111                             detailHtmlFormatFooter = detailHtmlFormat7;
4112                         }
4113                         detailHtmlFormatHeader += _fntDetail.Name + detailHtmlFormat2 + _fntDetail.Size.ToString() + detailHtmlFormat3 + _clDetail.R.ToString() + "," + _clDetail.G.ToString() + "," + _clDetail.B.ToString() + detailHtmlFormat4 + _clDetailLink.R.ToString() + "," + _clDetailLink.G.ToString() + "," + _clDetailLink.B.ToString() + detailHtmlFormat5 + _clDetailBackcolor.R.ToString() + "," + _clDetailBackcolor.G.ToString() + "," + _clDetailBackcolor.B.ToString();
4114                         if (SettingDialog.IsMonospace)
4115                         {
4116                             detailHtmlFormatHeader += detailHtmlFormatMono6;
4117                         }
4118                         else
4119                         {
4120                             detailHtmlFormatHeader += detailHtmlFormat6;
4121                         }
4122                     }
4123                     catch (Exception ex)
4124                     {
4125                         ex.Data["Instance"] = "Font";
4126                         ex.Data["IsTerminatePermission"] = false;
4127                         throw;
4128                     }
4129
4130                     try
4131                     {
4132                         _statuses.SetUnreadManage(SettingDialog.UnreadManage);
4133                     }
4134                     catch (Exception ex)
4135                     {
4136                         ex.Data["Instance"] = "_statuses";
4137                         ex.Data["IsTerminatePermission"] = false;
4138                         throw;
4139                     }
4140
4141                     try
4142                     {
4143                         foreach (TabPage tb in ListTab.TabPages)
4144                         {
4145                             if (SettingDialog.TabIconDisp)
4146                             {
4147                                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
4148                                     tb.ImageIndex = -1;
4149                                 else
4150                                     tb.ImageIndex = 0;
4151                             }
4152                         }
4153                     }
4154                     catch (Exception ex)
4155                     {
4156                         ex.Data["Instance"] = "ListTab(TabIconDisp no2)";
4157                         ex.Data["IsTerminatePermission"] = false;
4158                         throw;
4159                     }
4160
4161                     try
4162                     {
4163                         foreach (TabPage tp in ListTab.TabPages)
4164                         {
4165                             DetailsListView lst = (DetailsListView)tp.Tag;
4166
4167                             lst.BeginUpdate();
4168
4169                             lst.GridLines = SettingDialog.ShowGrid;
4170                             lst.Font = _fntReaded;
4171                             lst.BackColor = _clListBackcolor;
4172
4173                             if (SettingDialog.IconSz != oldIconSz)
4174                                 ApplyListViewIconSize(lst);
4175
4176                             lst.EndUpdate();
4177                         }
4178                     }
4179                     catch (Exception ex)
4180                     {
4181                         ex.Data["Instance"] = "ListView(IconSize)";
4182                         ex.Data["IsTerminatePermission"] = false;
4183                         throw;
4184                     }
4185
4186                     SetMainWindowTitle();
4187                     SetNotifyIconText();
4188
4189                     this.PurgeListViewItemCache();
4190                     if (_curList != null) _curList.Refresh();
4191                     ListTab.Refresh();
4192
4193                     _hookGlobalHotkey.UnregisterAllOriginalHotkey();
4194                     if (SettingDialog.HotkeyEnabled)
4195                     {
4196                         ///グローバルホットキーの登録。設定で変更可能にするかも
4197                         HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
4198                         if ((SettingDialog.HotkeyMod & Keys.Alt) == Keys.Alt) modKey = modKey | HookGlobalHotkey.ModKeys.Alt;
4199                         if ((SettingDialog.HotkeyMod & Keys.Control) == Keys.Control) modKey = modKey | HookGlobalHotkey.ModKeys.Ctrl;
4200                         if ((SettingDialog.HotkeyMod & Keys.Shift) == Keys.Shift) modKey = modKey | HookGlobalHotkey.ModKeys.Shift;
4201                         if ((SettingDialog.HotkeyMod & Keys.LWin) == Keys.LWin) modKey = modKey | HookGlobalHotkey.ModKeys.Win;
4202
4203                         _hookGlobalHotkey.RegisterOriginalHotkey(SettingDialog.HotkeyKey, SettingDialog.HotkeyValue, modKey);
4204                     }
4205
4206                     if (uid != tw.Username) this.doGetFollowersMenu();
4207
4208                     SetImageServiceCombo();
4209                     if (SettingDialog.IsNotifyUseGrowl) gh.RegisterGrowl();
4210                     try
4211                     {
4212                         StatusText_TextChanged(null, null);
4213                     }
4214                     catch (Exception)
4215                     {
4216                     }
4217                 }
4218             }
4219
4220             Twitter.AccountState = MyCommon.ACCOUNT_STATE.Valid;
4221
4222             this.TopMost = SettingDialog.AlwaysTop;
4223             SaveConfigsAll(false);
4224         }
4225
4226         /// <summary>
4227         /// タブの表示位置を設定する
4228         /// </summary>
4229         private void SetTabAlignment()
4230         {
4231             ListTab.Alignment = (SettingDialog.ViewTabBottom ? TabAlignment.Bottom : TabAlignment.Top);
4232         }
4233
4234         private void ApplyListViewIconSize(DetailsListView list)
4235         {
4236             list.BeginUpdate();
4237             list.SuspendLayout();
4238
4239             // アイコンサイズの再設定
4240             _iconCol = false;
4241             switch (SettingDialog.IconSz)
4242             {
4243                 case MyCommon.IconSizes.IconNone:
4244                     _iconSz = 0;
4245                     break;
4246                 case MyCommon.IconSizes.Icon16:
4247                     _iconSz = 16;
4248                     break;
4249                 case MyCommon.IconSizes.Icon24:
4250                     _iconSz = 26;
4251                     break;
4252                 case MyCommon.IconSizes.Icon48:
4253                     _iconSz = 48;
4254                     break;
4255                 case MyCommon.IconSizes.Icon48_2:
4256                     _iconSz = 48;
4257                     _iconCol = true;
4258                     break;
4259             }
4260             if (_iconSz == 0)
4261             {
4262                 tw.GetIcon = false;
4263             }
4264             else
4265             {
4266                 tw.GetIcon = true;
4267                 tw.IconSize = _iconSz;
4268             }
4269
4270             if (_iconSz > 0)
4271             {
4272                 // ディスプレイの DPI 設定を考慮したサイズを設定する
4273                 list.SmallImageList.ImageSize = new Size(
4274                     (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Width),
4275                     (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Height));
4276             }
4277             else
4278             {
4279                 list.SmallImageList.ImageSize = new Size(1, 1);
4280             }
4281
4282             // カラムヘッダの再設定
4283             list.ColumnClick -= MyList_ColumnClick;
4284             list.DrawColumnHeader -= MyList_DrawColumnHeader;
4285             list.ColumnReordered -= MyList_ColumnReordered;
4286             list.ColumnWidthChanged -= MyList_ColumnWidthChanged;
4287
4288             var cols = list.Columns.Cast<ColumnHeader>().ToList();
4289             list.Columns.Clear();
4290             cols.ForEach(col => col.Dispose());
4291             cols.Clear();
4292
4293             InitColumns(list, true);
4294
4295             list.ColumnClick += MyList_ColumnClick;
4296             list.DrawColumnHeader += MyList_DrawColumnHeader;
4297             list.ColumnReordered += MyList_ColumnReordered;
4298             list.ColumnWidthChanged += MyList_ColumnWidthChanged;
4299
4300             list.ResumeLayout(false);
4301             list.EndUpdate();
4302         }
4303
4304         private void PostBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
4305         {
4306             if (e.Url.AbsoluteUri != "about:blank")
4307             {
4308                 DispSelectedPost();
4309                 OpenUriAsync(e.Url.OriginalString);
4310             }
4311         }
4312
4313         private void PostBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
4314         {
4315             if (e.Url.Scheme == "data")
4316             {
4317                 StatusLabelUrl.Text = PostBrowser.StatusText.Replace("&", "&&");
4318             }
4319             else if (e.Url.AbsoluteUri != "about:blank")
4320             {
4321                 e.Cancel = true;
4322
4323                 if (e.Url.AbsoluteUri.StartsWith("http://twitter.com/search?q=%23") ||
4324                    e.Url.AbsoluteUri.StartsWith("https://twitter.com/search?q=%23"))
4325                 {
4326                     //ハッシュタグの場合は、タブで開く
4327                     string urlStr = Uri.UnescapeDataString(e.Url.AbsoluteUri);
4328                     int i = urlStr.IndexOf('#');
4329                     if (i == -1) return;
4330
4331                     string hash = urlStr.Substring(i);
4332                     HashSupl.AddItem(hash);
4333                     HashMgr.AddHashToHistory(hash.Trim(), false);
4334                     AddNewTabForSearch(hash);
4335                     return;
4336                 }
4337                 else
4338                 {
4339                     Match m = Regex.Match(e.Url.AbsoluteUri, "^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
4340                     if (m.Success && IsTwitterId(m.Result("${ScreenName}")))
4341                     {
4342                         // Ctrlを押しながらリンクをクリックした場合は設定と逆の動作をする
4343                         if (SettingDialog.OpenUserTimeline)
4344                         {
4345                             if (MyCommon.IsKeyDown(Keys.Control))
4346                                 OpenUriAsync(e.Url.OriginalString);
4347                             else
4348                                 this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
4349                         }
4350                         else
4351                         {
4352                             if (MyCommon.IsKeyDown(Keys.Control))
4353                                 this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
4354                             else
4355                                 OpenUriAsync(e.Url.OriginalString);
4356                         }
4357                     }
4358                     else
4359                     {
4360                         OpenUriAsync(e.Url.OriginalString);
4361                     }
4362                 }
4363             }
4364         }
4365
4366         public void AddNewTabForSearch(string searchWord)
4367         {
4368             //同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
4369             foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch))
4370             {
4371                 if (tb.SearchWords == searchWord && string.IsNullOrEmpty(tb.SearchLang))
4372                 {
4373                     foreach (TabPage tp in ListTab.TabPages)
4374                     {
4375                         if (tb.TabName == tp.Text)
4376                         {
4377                             ListTab.SelectedTab = tp;
4378                             return;
4379                         }
4380                     }
4381                 }
4382             }
4383             //ユニークなタブ名生成
4384             string tabName = searchWord;
4385             for (int i = 0; i <= 100; i++)
4386             {
4387                 if (_statuses.ContainsTab(tabName))
4388                     tabName += "_";
4389                 else
4390                     break;
4391             }
4392             //タブ追加
4393             _statuses.AddTab(tabName, MyCommon.TabUsageType.PublicSearch, null);
4394             AddNewTab(tabName, false, MyCommon.TabUsageType.PublicSearch);
4395             //追加したタブをアクティブに
4396             ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
4397             //検索条件の設定
4398             ComboBox cmb = (ComboBox)ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"];
4399             cmb.Items.Add(searchWord);
4400             cmb.Text = searchWord;
4401             SaveConfigsTabs();
4402             //検索実行
4403             this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
4404         }
4405
4406         private void ShowUserTimeline()
4407         {
4408             if (!this.ExistCurrentPost) return;
4409             AddNewTabForUserTimeline(_curPost.ScreenName);
4410         }
4411
4412         private void SearchComboBox_KeyDown(object sender, KeyEventArgs e)
4413         {
4414             if (e.KeyCode == Keys.Escape)
4415             {
4416                 TabPage relTp = ListTab.SelectedTab;
4417                 RemoveSpecifiedTab(relTp.Text, false);
4418                 SaveConfigsTabs();
4419                 e.SuppressKeyPress = true;
4420             }
4421         }
4422
4423         public void AddNewTabForUserTimeline(string user)
4424         {
4425             //同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
4426             foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline))
4427             {
4428                 if (tb.User == user)
4429                 {
4430                     foreach (TabPage tp in ListTab.TabPages)
4431                     {
4432                         if (tb.TabName == tp.Text)
4433                         {
4434                             ListTab.SelectedTab = tp;
4435                             return;
4436                         }
4437                     }
4438                 }
4439             }
4440             //ユニークなタブ名生成
4441             string tabName = "user:" + user;
4442             while (_statuses.ContainsTab(tabName))
4443             {
4444                 tabName += "_";
4445             }
4446             //タブ追加
4447             _statuses.AddTab(tabName, MyCommon.TabUsageType.UserTimeline, null);
4448             _statuses.Tabs[tabName].User = user;
4449             AddNewTab(tabName, false, MyCommon.TabUsageType.UserTimeline);
4450             //追加したタブをアクティブに
4451             ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
4452             SaveConfigsTabs();
4453             //検索実行
4454
4455             GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, tabName);
4456         }
4457
4458         public bool AddNewTab(string tabName, bool startup, MyCommon.TabUsageType tabType, ListElement listInfo = null)
4459         {
4460             //重複チェック
4461             foreach (TabPage tb in ListTab.TabPages)
4462             {
4463                 if (tb.Text == tabName) return false;
4464             }
4465
4466             //新規タブ名チェック
4467             if (tabName == Properties.Resources.AddNewTabText1) return false;
4468
4469             //タブタイプ重複チェック
4470             if (!startup)
4471             {
4472                 if (tabType == MyCommon.TabUsageType.DirectMessage ||
4473                    tabType == MyCommon.TabUsageType.Favorites ||
4474                    tabType == MyCommon.TabUsageType.Home ||
4475                    tabType == MyCommon.TabUsageType.Mentions ||
4476                    tabType == MyCommon.TabUsageType.Related)
4477                 {
4478                     if (_statuses.GetTabByType(tabType) != null) return false;
4479                 }
4480             }
4481
4482             TabPage _tabPage = new TabPage();
4483             DetailsListView _listCustom = new DetailsListView();
4484
4485             int cnt = ListTab.TabPages.Count;
4486
4487             ///ToDo:Create and set controls follow tabtypes
4488
4489             _listCustom.BeginUpdate();
4490             this.SplitContainer1.Panel1.SuspendLayout();
4491             this.SplitContainer1.Panel2.SuspendLayout();
4492             this.SplitContainer1.SuspendLayout();
4493             this.ListTab.SuspendLayout();
4494             this.SuspendLayout();
4495
4496             _tabPage.SuspendLayout();
4497
4498             /// UserTimeline関連
4499             Label label = null;
4500             if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
4501             {
4502                 label = new Label();
4503                 label.Dock = DockStyle.Top;
4504                 label.Name = "labelUser";
4505                 if (tabType == MyCommon.TabUsageType.Lists)
4506                 {
4507                     label.Text = listInfo.ToString();
4508                 }
4509                 else
4510                 {
4511                     label.Text = _statuses.Tabs[tabName].User + "'s Timeline";
4512                 }
4513                 label.TextAlign = ContentAlignment.MiddleLeft;
4514                 using (ComboBox tmpComboBox = new ComboBox())
4515                 {
4516                     label.Height = tmpComboBox.Height;
4517                 }
4518                 _tabPage.Controls.Add(label);
4519             }
4520
4521             /// 検索関連の準備
4522             Panel pnl = null;
4523             if (tabType == MyCommon.TabUsageType.PublicSearch)
4524             {
4525                 pnl = new Panel();
4526
4527                 Label lbl = new Label();
4528                 ComboBox cmb = new ComboBox();
4529                 Button btn = new Button();
4530                 ComboBox cmbLang = new ComboBox();
4531
4532                 pnl.SuspendLayout();
4533
4534                 pnl.Controls.Add(cmb);
4535                 pnl.Controls.Add(cmbLang);
4536                 pnl.Controls.Add(btn);
4537                 pnl.Controls.Add(lbl);
4538                 pnl.Name = "panelSearch";
4539                 pnl.Dock = DockStyle.Top;
4540                 pnl.Height = cmb.Height;
4541                 pnl.Enter += SearchControls_Enter;
4542                 pnl.Leave += SearchControls_Leave;
4543
4544                 cmb.Text = "";
4545                 cmb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
4546                 cmb.Dock = DockStyle.Fill;
4547                 cmb.Name = "comboSearch";
4548                 cmb.DropDownStyle = ComboBoxStyle.DropDown;
4549                 cmb.ImeMode = ImeMode.NoControl;
4550                 cmb.TabStop = false;
4551                 cmb.AutoCompleteMode = AutoCompleteMode.None;
4552                 cmb.KeyDown += SearchComboBox_KeyDown;
4553
4554                 if (_statuses.ContainsTab(tabName))
4555                 {
4556                     cmb.Items.Add(_statuses.Tabs[tabName].SearchWords);
4557                     cmb.Text = _statuses.Tabs[tabName].SearchWords;
4558                 }
4559
4560                 cmbLang.Text = "";
4561                 cmbLang.Anchor = AnchorStyles.Left | AnchorStyles.Right;
4562                 cmbLang.Dock = DockStyle.Right;
4563                 cmbLang.Width = 50;
4564                 cmbLang.Name = "comboLang";
4565                 cmbLang.DropDownStyle = ComboBoxStyle.DropDownList;
4566                 cmbLang.TabStop = false;
4567                 cmbLang.Items.Add("");
4568                 cmbLang.Items.Add("ja");
4569                 cmbLang.Items.Add("en");
4570                 cmbLang.Items.Add("ar");
4571                 cmbLang.Items.Add("da");
4572                 cmbLang.Items.Add("nl");
4573                 cmbLang.Items.Add("fa");
4574                 cmbLang.Items.Add("fi");
4575                 cmbLang.Items.Add("fr");
4576                 cmbLang.Items.Add("de");
4577                 cmbLang.Items.Add("hu");
4578                 cmbLang.Items.Add("is");
4579                 cmbLang.Items.Add("it");
4580                 cmbLang.Items.Add("no");
4581                 cmbLang.Items.Add("pl");
4582                 cmbLang.Items.Add("pt");
4583                 cmbLang.Items.Add("ru");
4584                 cmbLang.Items.Add("es");
4585                 cmbLang.Items.Add("sv");
4586                 cmbLang.Items.Add("th");
4587                 if (_statuses.ContainsTab(tabName)) cmbLang.Text = _statuses.Tabs[tabName].SearchLang;
4588             
4589                 lbl.Text = "Search(C-S-f)";
4590                 lbl.Name = "label1";
4591                 lbl.Dock = DockStyle.Left;
4592                 lbl.Width = 90;
4593                 lbl.Height = cmb.Height;
4594                 lbl.TextAlign = ContentAlignment.MiddleLeft;
4595
4596                 btn.Text = "Search";
4597                 btn.Name = "buttonSearch";
4598                 btn.UseVisualStyleBackColor = true;
4599                 btn.Dock = DockStyle.Right;
4600                 btn.TabStop = false;
4601                 btn.Click += SearchButton_Click;
4602             }
4603
4604             this.ListTab.Controls.Add(_tabPage);
4605             _tabPage.Controls.Add(_listCustom);
4606
4607             if (tabType == MyCommon.TabUsageType.PublicSearch) _tabPage.Controls.Add(pnl);
4608             if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists) _tabPage.Controls.Add(label);
4609
4610             _tabPage.Location = new Point(4, 4);
4611             _tabPage.Name = "CTab" + cnt.ToString();
4612             _tabPage.Size = new Size(380, 260);
4613             _tabPage.TabIndex = 2 + cnt;
4614             _tabPage.Text = tabName;
4615             _tabPage.UseVisualStyleBackColor = true;
4616
4617             _listCustom.AllowColumnReorder = true;
4618             _listCustom.ContextMenuStrip = this.ContextMenuOperate;
4619             _listCustom.Dock = DockStyle.Fill;
4620             _listCustom.FullRowSelect = true;
4621             _listCustom.HideSelection = false;
4622             _listCustom.Location = new Point(0, 0);
4623             _listCustom.Margin = new Padding(0);
4624             _listCustom.Name = "CList" + Environment.TickCount.ToString();
4625             _listCustom.ShowItemToolTips = true;
4626             _listCustom.Size = new Size(380, 260);
4627             _listCustom.UseCompatibleStateImageBehavior = false;
4628             _listCustom.View = View.Details;
4629             _listCustom.OwnerDraw = true;
4630             _listCustom.VirtualMode = true;
4631             _listCustom.Font = _fntReaded;
4632             _listCustom.BackColor = _clListBackcolor;
4633
4634             _listCustom.GridLines = SettingDialog.ShowGrid;
4635             _listCustom.AllowDrop = true;
4636
4637             _listCustom.SmallImageList = new ImageList();
4638             if (_iconSz > 0)
4639             {
4640                 // ディスプレイの DPI 設定を考慮したサイズを設定する
4641                 _listCustom.SmallImageList.ImageSize = new Size(
4642                     (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Width),
4643                     (int)Math.Ceiling(this._iconSz * this.currentScaleFactor.Height));
4644             }
4645             else
4646             {
4647                 _listCustom.SmallImageList.ImageSize = new Size(1, 1);
4648             }
4649
4650             InitColumns(_listCustom, startup);
4651
4652             _listCustom.SelectedIndexChanged += MyList_SelectedIndexChanged;
4653             _listCustom.MouseDoubleClick += MyList_MouseDoubleClick;
4654             _listCustom.ColumnClick += MyList_ColumnClick;
4655             _listCustom.DrawColumnHeader += MyList_DrawColumnHeader;
4656             _listCustom.DragDrop += TweenMain_DragDrop;
4657             _listCustom.DragOver += TweenMain_DragOver;
4658             _listCustom.DrawItem += MyList_DrawItem;
4659             _listCustom.MouseClick += MyList_MouseClick;
4660             _listCustom.ColumnReordered += MyList_ColumnReordered;
4661             _listCustom.ColumnWidthChanged += MyList_ColumnWidthChanged;
4662             _listCustom.CacheVirtualItems += MyList_CacheVirtualItems;
4663             _listCustom.RetrieveVirtualItem += MyList_RetrieveVirtualItem;
4664             _listCustom.DrawSubItem += MyList_DrawSubItem;
4665             _listCustom.HScrolled += MyList_HScrolled;
4666
4667             if (tabType == MyCommon.TabUsageType.PublicSearch) pnl.ResumeLayout(false);
4668         
4669             _tabPage.ResumeLayout(false);
4670
4671             this.SplitContainer1.Panel1.ResumeLayout(false);
4672             this.SplitContainer1.Panel2.ResumeLayout(false);
4673             this.SplitContainer1.ResumeLayout(false);
4674             this.ListTab.ResumeLayout(false);
4675             this.ResumeLayout(false);
4676             this.PerformLayout();
4677             _listCustom.EndUpdate();
4678             _tabPage.Tag = _listCustom;
4679             return true;
4680         }
4681
4682         public bool RemoveSpecifiedTab(string TabName, bool confirm)
4683         {
4684             if (_statuses.IsDefaultTab(TabName) || _statuses.Tabs[TabName].Protected) return false;
4685
4686             if (confirm)
4687             {
4688                 string tmp = string.Format(Properties.Resources.RemoveSpecifiedTabText1, Environment.NewLine);
4689                 if (MessageBox.Show(tmp, TabName + " " + Properties.Resources.RemoveSpecifiedTabText2,
4690                                  MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Cancel)
4691                 {
4692                     return false;
4693                 }
4694             }
4695
4696             var _tabPage = ListTab.TabPages.Cast<TabPage>().FirstOrDefault<TabPage>(tp => tp.Text == TabName);
4697             if (_tabPage == null) return false;
4698
4699             SetListProperty();   //他のタブに列幅等を反映
4700
4701             MyCommon.TabUsageType tabType = _statuses.Tabs[TabName].TabType;
4702
4703             //オブジェクトインスタンスの削除
4704             this.SplitContainer1.Panel1.SuspendLayout();
4705             this.SplitContainer1.Panel2.SuspendLayout();
4706             this.SplitContainer1.SuspendLayout();
4707             this.ListTab.SuspendLayout();
4708             this.SuspendLayout();
4709
4710             DetailsListView _listCustom = (DetailsListView)_tabPage.Tag;
4711             _tabPage.Tag = null;
4712
4713             _tabPage.SuspendLayout();
4714
4715             if (this.ListTab.SelectedTab == _tabPage)
4716             {
4717                 this.ListTab.SelectTab((this._beforeSelectedTab != null && this.ListTab.TabPages.Contains(this._beforeSelectedTab)) ? this._beforeSelectedTab : this.ListTab.TabPages[0]);
4718                 this._beforeSelectedTab = null;
4719             }
4720             this.ListTab.Controls.Remove(_tabPage);
4721
4722             // 後付けのコントロールを破棄
4723             if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
4724             {
4725                 using (Control label = _tabPage.Controls["labelUser"])
4726                 {
4727                     _tabPage.Controls.Remove(label);
4728                 }
4729             }
4730             else if (tabType == MyCommon.TabUsageType.PublicSearch)
4731             {
4732                 using (Control pnl = _tabPage.Controls["panelSearch"])
4733                 {
4734                     pnl.Enter -= SearchControls_Enter;
4735                     pnl.Leave -= SearchControls_Leave;
4736                     _tabPage.Controls.Remove(pnl);
4737
4738                     foreach (Control ctrl in pnl.Controls)
4739                     {
4740                         if (ctrl.Name == "buttonSearch")
4741                         {
4742                             ctrl.Click -= SearchButton_Click;
4743                         }
4744                         else if (ctrl.Name == "comboSearch")
4745                         {
4746                             ctrl.KeyDown -= SearchComboBox_KeyDown;
4747                         }
4748                         pnl.Controls.Remove(ctrl);
4749                         ctrl.Dispose();
4750                     }
4751                 }
4752             }
4753
4754             _tabPage.Controls.Remove(_listCustom);
4755
4756             _listCustom.SelectedIndexChanged -= MyList_SelectedIndexChanged;
4757             _listCustom.MouseDoubleClick -= MyList_MouseDoubleClick;
4758             _listCustom.ColumnClick -= MyList_ColumnClick;
4759             _listCustom.DrawColumnHeader -= MyList_DrawColumnHeader;
4760             _listCustom.DragDrop -= TweenMain_DragDrop;
4761             _listCustom.DragOver -= TweenMain_DragOver;
4762             _listCustom.DrawItem -= MyList_DrawItem;
4763             _listCustom.MouseClick -= MyList_MouseClick;
4764             _listCustom.ColumnReordered -= MyList_ColumnReordered;
4765             _listCustom.ColumnWidthChanged -= MyList_ColumnWidthChanged;
4766             _listCustom.CacheVirtualItems -= MyList_CacheVirtualItems;
4767             _listCustom.RetrieveVirtualItem -= MyList_RetrieveVirtualItem;
4768             _listCustom.DrawSubItem -= MyList_DrawSubItem;
4769             _listCustom.HScrolled -= MyList_HScrolled;
4770
4771             var cols = _listCustom.Columns.Cast<ColumnHeader>().ToList<ColumnHeader>();
4772             _listCustom.Columns.Clear();
4773             cols.ForEach(col => col.Dispose());
4774             cols.Clear();
4775
4776             _listCustom.ContextMenuStrip = null;
4777             _listCustom.Font = null;
4778
4779             _listCustom.SmallImageList.Dispose();
4780             _listCustom.SmallImageList = null;
4781             _listCustom.ListViewItemSorter = null;
4782
4783             //キャッシュのクリア
4784             if (_curTab.Equals(_tabPage))
4785             {
4786                 _curTab = null;
4787                 _curItemIndex = -1;
4788                 _curList = null;
4789                 _curPost = null;
4790             }
4791             this.PurgeListViewItemCache();
4792
4793             _tabPage.ResumeLayout(false);
4794
4795             this.SplitContainer1.Panel1.ResumeLayout(false);
4796             this.SplitContainer1.Panel2.ResumeLayout(false);
4797             this.SplitContainer1.ResumeLayout(false);
4798             this.ListTab.ResumeLayout(false);
4799             this.ResumeLayout(false);
4800             this.PerformLayout();
4801
4802             _tabPage.Dispose();
4803             _listCustom.Dispose();
4804             _statuses.RemoveTab(TabName);
4805
4806             foreach (TabPage tp in ListTab.TabPages)
4807             {
4808                 DetailsListView lst = (DetailsListView)tp.Tag;
4809                 var count = _statuses.Tabs[tp.Text].AllCount;
4810                 if (lst.VirtualListSize != count)
4811                 {
4812                     lst.VirtualListSize = count;
4813                 }
4814             }
4815
4816             return true;
4817         }
4818
4819         private void ListTab_Deselected(object sender, TabControlEventArgs e)
4820         {
4821             this.PurgeListViewItemCache();
4822             _beforeSelectedTab = e.TabPage;
4823         }
4824
4825         private void ListTab_MouseMove(object sender, MouseEventArgs e)
4826         {
4827             //タブのD&D
4828
4829             if (!SettingDialog.TabMouseLock && e.Button == MouseButtons.Left && _tabDrag)
4830             {
4831                 string tn = "";
4832                 Rectangle dragEnableRectangle = new Rectangle((int)(_tabMouseDownPoint.X - (SystemInformation.DragSize.Width / 2)), (int)(_tabMouseDownPoint.Y - (SystemInformation.DragSize.Height / 2)), SystemInformation.DragSize.Width, SystemInformation.DragSize.Height);
4833                 if (!dragEnableRectangle.Contains(e.Location))
4834                 {
4835                     //タブが多段の場合にはMouseDownの前の段階で選択されたタブの段が変わっているので、このタイミングでカーソルの位置からタブを判定出来ない。
4836                     tn = ListTab.SelectedTab.Text;
4837                 }
4838
4839                 if (string.IsNullOrEmpty(tn)) return;
4840
4841                 foreach (TabPage tb in ListTab.TabPages)
4842                 {
4843                     if (tb.Text == tn)
4844                     {
4845                         ListTab.DoDragDrop(tb, DragDropEffects.All);
4846                         break;
4847                     }
4848                 }
4849             }
4850             else
4851             {
4852                 _tabDrag = false;
4853             }
4854
4855             Point cpos = new Point(e.X, e.Y);
4856             for (int i = 0; i < ListTab.TabPages.Count; i++)
4857             {
4858                 Rectangle rect = ListTab.GetTabRect(i);
4859                 if (rect.Left <= cpos.X & cpos.X <= rect.Right &
4860                    rect.Top <= cpos.Y & cpos.Y <= rect.Bottom)
4861                 {
4862                     _rclickTabName = ListTab.TabPages[i].Text;
4863                     break;
4864                 }
4865             }
4866         }
4867
4868         private void ListTab_SelectedIndexChanged(object sender, EventArgs e)
4869         {
4870             //_curList.Refresh();
4871             DispSelectedPost();
4872             SetMainWindowTitle();
4873             SetStatusLabelUrl();
4874             if (ListTab.Focused || ((Control)ListTab.SelectedTab.Tag).Focused) this.Tag = ListTab.Tag;
4875             TabMenuControl(ListTab.SelectedTab.Text);
4876             this.PushSelectPostChain();
4877         }
4878
4879         private void SetListProperty()
4880         {
4881             //削除などで見つからない場合は処理せず
4882             if (_curList == null) return;
4883             if (!_isColumnChanged) return;
4884
4885             int[] dispOrder = new int[_curList.Columns.Count];
4886             for (int i = 0; i < _curList.Columns.Count; i++)
4887             {
4888                 for (int j = 0; j < _curList.Columns.Count; j++)
4889                 {
4890                     if (_curList.Columns[j].DisplayIndex == i)
4891                     {
4892                         dispOrder[i] = j;
4893                         break;
4894                     }
4895                 }
4896             }
4897
4898             //列幅、列並びを他のタブに設定
4899             foreach (TabPage tb in ListTab.TabPages)
4900             {
4901                 if (!tb.Equals(_curTab))
4902                 {
4903                     if (tb.Tag != null && tb.Controls.Count > 0)
4904                     {
4905                         DetailsListView lst = (DetailsListView)tb.Tag;
4906                         for (int i = 0; i < lst.Columns.Count; i++)
4907                         {
4908                             lst.Columns[dispOrder[i]].DisplayIndex = i;
4909                             lst.Columns[i].Width = _curList.Columns[i].Width;
4910                         }
4911                     }
4912                 }
4913             }
4914
4915             _isColumnChanged = false;
4916         }
4917
4918         private void PostBrowser_StatusTextChanged(object sender, EventArgs e)
4919         {
4920             try
4921             {
4922                 if (PostBrowser.StatusText.StartsWith("http") || PostBrowser.StatusText.StartsWith("ftp")
4923                         || PostBrowser.StatusText.StartsWith("data"))
4924                 {
4925                     StatusLabelUrl.Text = PostBrowser.StatusText.Replace("&", "&&");
4926                 }
4927                 if (string.IsNullOrEmpty(PostBrowser.StatusText))
4928                 {
4929                     SetStatusLabelUrl();
4930                 }
4931             }
4932             catch (Exception)
4933             {
4934             }
4935         }
4936
4937         private void StatusText_KeyPress(object sender, KeyPressEventArgs e)
4938         {
4939             if (e.KeyChar == '@')
4940             {
4941                 if (!SettingDialog.UseAtIdSupplement) return;
4942                 //@マーク
4943                 int cnt = AtIdSupl.ItemCount;
4944                 ShowSuplDialog(StatusText, AtIdSupl);
4945                 if (cnt != AtIdSupl.ItemCount) _modifySettingAtId = true;
4946                 e.Handled = true;
4947             }
4948             else if (e.KeyChar == '#')
4949             {
4950                 if (!SettingDialog.UseHashSupplement) return;
4951                 ShowSuplDialog(StatusText, HashSupl);
4952                 e.Handled = true;
4953             }
4954         }
4955
4956         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog)
4957         {
4958             ShowSuplDialog(owner, dialog, 0, "");
4959         }
4960
4961         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset)
4962         {
4963             ShowSuplDialog(owner, dialog, offset, "");
4964         }
4965
4966         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset, string startswith)
4967         {
4968             dialog.StartsWith = startswith;
4969             if (dialog.Visible)
4970             {
4971                 dialog.Focus();
4972             }
4973             else
4974             {
4975                 dialog.ShowDialog();
4976             }
4977             this.TopMost = SettingDialog.AlwaysTop;
4978             int selStart = owner.SelectionStart;
4979             string fHalf = "";
4980             string eHalf = "";
4981             if (dialog.DialogResult == DialogResult.OK)
4982             {
4983                 if (!string.IsNullOrEmpty(dialog.inputText))
4984                 {
4985                     if (selStart > 0)
4986                     {
4987                         fHalf = owner.Text.Substring(0, selStart - offset);
4988                     }
4989                     if (selStart < owner.Text.Length)
4990                     {
4991                         eHalf = owner.Text.Substring(selStart);
4992                     }
4993                     owner.Text = fHalf + dialog.inputText + eHalf;
4994                     owner.SelectionStart = selStart + dialog.inputText.Length;
4995                 }
4996             }
4997             else
4998             {
4999                 if (selStart > 0)
5000                 {
5001                     fHalf = owner.Text.Substring(0, selStart);
5002                 }
5003                 if (selStart < owner.Text.Length)
5004                 {
5005                     eHalf = owner.Text.Substring(selStart);
5006                 }
5007                 owner.Text = fHalf + eHalf;
5008                 if (selStart > 0)
5009                 {
5010                     owner.SelectionStart = selStart;
5011                 }
5012             }
5013             owner.Focus();
5014         }
5015
5016         private void StatusText_KeyUp(object sender, KeyEventArgs e)
5017         {
5018             //スペースキーで未読ジャンプ
5019             if (!e.Alt && !e.Control && !e.Shift)
5020             {
5021                 if (e.KeyCode == Keys.Space || e.KeyCode == Keys.ProcessKey)
5022                 {
5023                     bool isSpace = false;
5024                     foreach (char c in StatusText.Text.ToCharArray())
5025                     {
5026                         if (c == ' ' || c == ' ')
5027                         {
5028                             isSpace = true;
5029                         }
5030                         else
5031                         {
5032                             isSpace = false;
5033                             break;
5034                         }
5035                     }
5036                     if (isSpace)
5037                     {
5038                         e.Handled = true;
5039                         StatusText.Text = "";
5040                         JumpUnreadMenuItem_Click(null, null);
5041                     }
5042                 }
5043             }
5044             this.StatusText_TextChanged(null, null);
5045         }
5046
5047         private void StatusText_TextChanged(object sender, EventArgs e)
5048         {
5049             //文字数カウント
5050             int pLen = GetRestStatusCount(true, false);
5051             lblLen.Text = pLen.ToString();
5052             if (pLen < 0)
5053             {
5054                 StatusText.ForeColor = Color.Red;
5055             }
5056             else
5057             {
5058                 StatusText.ForeColor = _clInputFont;
5059             }
5060             if (string.IsNullOrEmpty(StatusText.Text))
5061             {
5062                 _reply_to_id = null;
5063                 _reply_to_name = null;
5064             }
5065         }
5066
5067         private int GetRestStatusCount(bool isAuto, bool isAddFooter)
5068         {
5069             //文字数カウント
5070             var statusText = this.StatusText.Text;
5071             statusText = statusText.Replace("\r\n", "\n");
5072
5073             int pLen = 140 - statusText.Length;
5074             if (this.NotifyIcon1 == null || !this.NotifyIcon1.Visible) return pLen;
5075             if ((isAuto && !MyCommon.IsKeyDown(Keys.Control) && SettingDialog.PostShiftEnter) ||
5076                 (isAuto && !MyCommon.IsKeyDown(Keys.Shift) && !SettingDialog.PostShiftEnter) ||
5077                 (!isAuto && isAddFooter))
5078             {
5079                 if (SettingDialog.UseRecommendStatus)
5080                     pLen -= SettingDialog.RecommendStatusText.Length;
5081                 else if (SettingDialog.Status.Length > 0)
5082                     pLen -= SettingDialog.Status.Length + 1;
5083             }
5084             if (!string.IsNullOrEmpty(HashMgr.UseHash))
5085             {
5086                 pLen -= HashMgr.UseHash.Length + 1;
5087             }
5088             //foreach (Match m in Regex.Matches(statusText, "https?:\/\/[-_.!~*//()a-zA-Z0-9;\/?:\@&=+\$,%#^]+"))
5089             //{
5090             //    pLen += m.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5091             //}
5092             foreach (Match m in Regex.Matches(statusText, Twitter.rgUrl, RegexOptions.IgnoreCase))
5093             {
5094                 string before = m.Result("${before}");
5095                 string url = m.Result("${url}");
5096                 string protocol = m.Result("${protocol}");
5097                 string domain = m.Result("${domain}");
5098                 string path = m.Result("${path}");
5099                 if (protocol.Length == 0)
5100                 {
5101                     if (Regex.IsMatch(before, Twitter.url_invalid_without_protocol_preceding_chars))
5102                     {
5103                         continue;
5104                     }
5105
5106                     bool last_url_invalid_match = false;
5107                     string lasturl = null;
5108                     foreach (Match mm in Regex.Matches(domain, Twitter.url_valid_ascii_domain, RegexOptions.IgnoreCase))
5109                     {
5110                         lasturl = mm.ToString();
5111                         last_url_invalid_match = Regex.IsMatch(lasturl, Twitter.url_invalid_short_domain, RegexOptions.IgnoreCase);
5112                         if (!last_url_invalid_match)
5113                         {
5114                             pLen += lasturl.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5115                         }
5116                     }
5117
5118                     if (path.Length != 0)
5119                     {
5120                         if (last_url_invalid_match)
5121                         {
5122                             pLen += lasturl.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5123                         }
5124                         pLen += path.Length;
5125                     }
5126                 }
5127                 else
5128                 {
5129                     int shortUrlLength = protocol == "https://"
5130                         ? SettingDialog.TwitterConfiguration.ShortUrlLengthHttps
5131                         : SettingDialog.TwitterConfiguration.ShortUrlLength;
5132
5133                     pLen += url.Length - shortUrlLength;
5134                 }
5135                 
5136                 //if (m.Result("${url}").Length > SettingDialog.TwitterConfiguration.ShortUrlLength)
5137                 //{
5138                 //    pLen += m.Result("${url}").Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5139                 //}
5140             }
5141             if (ImageSelectionPanel.Visible && ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
5142             {
5143                 pLen -= SettingDialog.TwitterConfiguration.CharactersReservedPerMedia;
5144             }
5145             return pLen;
5146         }
5147
5148         private void MyList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
5149         {
5150             this.itemCacheLock.EnterUpgradeableReadLock();
5151             try
5152             {
5153                 if (_curList.Equals(sender))
5154                 {
5155                     if (_itemCache != null &&
5156                        e.StartIndex >= _itemCacheIndex &&
5157                        e.EndIndex < _itemCacheIndex + _itemCache.Length)
5158                     {
5159                         //If the newly requested cache is a subset of the old cache, 
5160                         //no need to rebuild everything, so do nothing.
5161                         return;
5162                     }
5163
5164                     //Now we need to rebuild the cache.
5165                     CreateCache(e.StartIndex, e.EndIndex);
5166                 }
5167             }
5168             finally { this.itemCacheLock.ExitUpgradeableReadLock(); }
5169         }
5170
5171         private void MyList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
5172         {
5173             ListViewItem cacheItem = null;
5174             PostClass cacheItemPost = null;
5175
5176             this.TryGetListViewItemCache(e.ItemIndex, out cacheItem, out cacheItemPost);
5177
5178             if (cacheItem != null)
5179             {
5180                 e.Item = cacheItem;
5181             }
5182             else
5183             {
5184                 //A cache miss, so create a new ListViewItem and pass it back.
5185                 TabPage tb = (TabPage)((DetailsListView)sender).Parent;
5186                 try
5187                 {
5188                     e.Item = CreateItem(tb,
5189                                         _statuses[tb.Text, e.ItemIndex],
5190                                         e.ItemIndex);
5191                 }
5192                 catch (Exception)
5193                 {
5194                     //不正な要求に対する間に合わせの応答
5195                     string[] sitem = {"", "", "", "", "", "", "", ""};
5196                     e.Item = new ImageListViewItem(sitem);
5197                 }
5198             }
5199         }
5200
5201         private void CreateCache(int StartIndex, int EndIndex)
5202         {
5203             this.itemCacheLock.EnterWriteLock();
5204             try
5205             {
5206                 //キャッシュ要求(要求範囲±30を作成)
5207                 StartIndex -= 30;
5208                 if (StartIndex < 0) StartIndex = 0;
5209                 EndIndex += 30;
5210                 if (EndIndex >= _statuses.Tabs[_curTab.Text].AllCount) EndIndex = _statuses.Tabs[_curTab.Text].AllCount - 1;
5211                 _postCache = _statuses[_curTab.Text, StartIndex, EndIndex]; //配列で取得
5212                 _itemCacheIndex = StartIndex;
5213
5214                 _itemCache = new ListViewItem[0] {};
5215                 Array.Resize(ref _itemCache, _postCache.Length);
5216
5217                 for (int i = 0; i < _postCache.Length; i++)
5218                 {
5219                     _itemCache[i] = CreateItem(_curTab, _postCache[i], StartIndex + i);
5220                 }
5221             }
5222             catch (Exception)
5223             {
5224                 //キャッシュ要求が実データとずれるため(イベントの遅延?)
5225                 _postCache = null;
5226                 _itemCacheIndex = -1;
5227                 _itemCache = null;
5228             }
5229             finally { this.itemCacheLock.ExitWriteLock(); }
5230         }
5231
5232         /// <summary>
5233         /// DetailsListView のための ListViewItem のキャッシュを消去する
5234         /// </summary>
5235         private void PurgeListViewItemCache()
5236         {
5237             this.itemCacheLock.EnterWriteLock();
5238             try
5239             {
5240                 this._itemCache = null;
5241                 this._itemCacheIndex = -1;
5242                 this._postCache = null;
5243             }
5244             finally { this.itemCacheLock.ExitWriteLock(); }
5245         }
5246
5247         private bool TryGetListViewItemCache(int index, out ListViewItem item, out PostClass post)
5248         {
5249             this.itemCacheLock.EnterReadLock();
5250             try
5251             {
5252                 if (this._itemCache != null && index >= this._itemCacheIndex && index < this._itemCacheIndex + this._itemCache.Length)
5253                 {
5254                     item = this._itemCache[index - _itemCacheIndex];
5255                     post = this._postCache[index - _itemCacheIndex];
5256                     return true;
5257                 }
5258             }
5259             finally { this.itemCacheLock.ExitReadLock(); }
5260
5261             item = null;
5262             post = null;
5263             return false;
5264         }
5265
5266         private ListViewItem CreateItem(TabPage Tab, PostClass Post, int Index)
5267         {
5268             StringBuilder mk = new StringBuilder();
5269             //if (Post.IsDeleted) mk.Append("×");
5270             //if (Post.IsMark) mk.Append("♪");
5271             //if (Post.IsProtect) mk.Append("Ю");
5272             //if (Post.InReplyToStatusId != null) mk.Append("⇒");
5273             if (Post.FavoritedCount > 0) mk.Append("+" + Post.FavoritedCount.ToString());
5274             ImageListViewItem itm;
5275             if (Post.RetweetedId == null)
5276             {
5277                 string[] sitem= {"",
5278                                  Post.Nickname,
5279                                  Post.IsDeleted ? "(DELETED)" : Post.TextSingleLine,
5280                                  Post.CreatedAt.ToString(SettingDialog.DateTimeFormat),
5281                                  Post.ScreenName,
5282                                  "",
5283                                  mk.ToString(),
5284                                  Post.Source};
5285                 itm = new ImageListViewItem(sitem, this.IconCache, Post.ImageUrl);
5286             }
5287             else
5288             {
5289                 string[] sitem = {"",
5290                                   Post.Nickname,
5291                                   Post.IsDeleted ? "(DELETED)" : Post.TextSingleLine,
5292                                   Post.CreatedAt.ToString(SettingDialog.DateTimeFormat),
5293                                   Post.ScreenName + Environment.NewLine + "(RT:" + Post.RetweetedBy + ")",
5294                                   "",
5295                                   mk.ToString(),
5296                                   Post.Source};
5297                 itm = new ImageListViewItem(sitem, this.IconCache, Post.ImageUrl);
5298             }
5299             itm.StateImageIndex = Post.StateIndex;
5300
5301             bool read = Post.IsRead;
5302             //未読管理していなかったら既読として扱う
5303             if (!_statuses.Tabs[Tab.Text].UnreadManage || !SettingDialog.UnreadManage) read = true;
5304             ChangeItemStyleRead(read, itm, Post, null);
5305             if (Tab.Equals(_curTab)) ColorizeList(itm, Index);
5306             return itm;
5307         }
5308
5309         private void MyList_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
5310         {
5311             e.DrawDefault = true;
5312         }
5313
5314         private void MyList_HScrolled(object sender, EventArgs e)
5315         {
5316             DetailsListView listView = (DetailsListView)sender;
5317             listView.Refresh();
5318         }
5319
5320         private void MyList_DrawItem(object sender, DrawListViewItemEventArgs e)
5321         {
5322             if (e.State == 0) return;
5323             e.DrawDefault = false;
5324             if (!e.Item.Selected)     //e.ItemStateでうまく判定できない???
5325             {
5326                 SolidBrush brs2 = null;
5327
5328                 if (e.Item.BackColor == _clSelf)
5329                     brs2 = _brsBackColorMine;
5330                 else if (e.Item.BackColor == _clAtSelf)
5331                     brs2 = _brsBackColorAt;
5332                 else if (e.Item.BackColor == _clTarget)
5333                     brs2 = _brsBackColorYou;
5334                 else if (e.Item.BackColor == _clAtTarget)
5335                     brs2 = _brsBackColorAtYou;
5336                 else if (e.Item.BackColor == _clAtFromTarget)
5337                     brs2 = _brsBackColorAtFromTarget;
5338                 else if (e.Item.BackColor == _clAtTo)
5339                     brs2 = _brsBackColorAtTo;
5340                 else
5341                     brs2 = _brsBackColorNone;
5342
5343                 e.Graphics.FillRectangle(brs2, e.Bounds);
5344             }
5345             else
5346             {
5347                 //選択中の行
5348                 if (((Control)sender).Focused)
5349                     e.Graphics.FillRectangle(_brsHighLight, e.Bounds);
5350                 else
5351                     e.Graphics.FillRectangle(_brsDeactiveSelection, e.Bounds);
5352             }
5353             if ((e.State & ListViewItemStates.Focused) == ListViewItemStates.Focused) e.DrawFocusRectangle();
5354             this.DrawListViewItemIcon(e);
5355         }
5356
5357         private void MyList_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
5358         {
5359             if (e.ItemState == 0) return;
5360
5361             if (e.ColumnIndex > 0)
5362             {
5363                 //アイコン以外の列
5364                 RectangleF rct = e.Bounds;
5365                 rct.Width = e.Header.Width;
5366                 if (_iconCol)
5367                 {
5368                     rct.Y += e.Item.Font.Height;
5369                     rct.Height -= e.Item.Font.Height;
5370                 }
5371
5372                 int heightDiff;
5373                 int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, e.Item.Font.Height, out heightDiff));
5374
5375                 //if (heightDiff > e.Item.Font.Height * 0.7)
5376                 //{
5377                 //    rct.Height += e.Item.Font.Height;
5378                 //    drawLineCount += 1;
5379                 //}
5380
5381                 //フォントの高さの半分を足してるのは保険。無くてもいいかも。
5382                 if (!_iconCol && drawLineCount <= 1)
5383                 {
5384                     //rct.Inflate(0, heightDiff / -2);
5385                     //rct.Height += e.Item.Font.Height / 2;
5386                 }
5387                 else if (heightDiff < e.Item.Font.Height * 0.7)
5388                 {
5389                     //最終行が70%以上欠けていたら、最終行は表示しない
5390                     //rct.Height = (float)((e.Item.Font.Height * drawLineCount) + (e.Item.Font.Height / 2));
5391                     rct.Height = (e.Item.Font.Height * drawLineCount) - 1;
5392                 }
5393                 else
5394                 {
5395                     drawLineCount += 1;
5396                 }
5397
5398                 //if (!_iconCol && drawLineCount > 1)
5399                 //{
5400                 //    rct.Y += e.Item.Font.Height * 0.2;
5401                 //    if (heightDiff >= e.Item.Font.Height * 0.8) rct.Height -= e.Item.Font.Height * 0.2;
5402                 //}
5403
5404                 if (rct.Width > 0)
5405                 {
5406                     Color color = (!e.Item.Selected) ? e.Item.ForeColor :   //選択されていない行
5407                         (((Control)sender).Focused) ? _clHighLight :        //選択中の行
5408                         _clUnread;
5409
5410                     if (_iconCol)
5411                     {
5412                         RectangleF rctB = e.Bounds;
5413                         rctB.Width = e.Header.Width;
5414                         rctB.Height = e.Item.Font.Height;
5415
5416                         using (Font fnt = new Font(e.Item.Font, FontStyle.Bold))
5417                         {
5418                             TextRenderer.DrawText(e.Graphics,
5419                                                     e.Item.SubItems[2].Text,
5420                                                     e.Item.Font,
5421                                                     Rectangle.Round(rct),
5422                                                     color,
5423                                                     TextFormatFlags.WordBreak |
5424                                                     TextFormatFlags.EndEllipsis |
5425                                                     TextFormatFlags.GlyphOverhangPadding |
5426                                                     TextFormatFlags.NoPrefix);
5427                             TextRenderer.DrawText(e.Graphics,
5428                                                     e.Item.SubItems[4].Text + " / " + e.Item.SubItems[1].Text + " (" + e.Item.SubItems[3].Text + ") " + e.Item.SubItems[5].Text + e.Item.SubItems[6].Text + " [" + e.Item.SubItems[7].Text + "]",
5429                                                     fnt,
5430                                                     Rectangle.Round(rctB),
5431                                                     color,
5432                                                     TextFormatFlags.SingleLine |
5433                                                     TextFormatFlags.EndEllipsis |
5434                                                     TextFormatFlags.GlyphOverhangPadding |
5435                                                     TextFormatFlags.NoPrefix);
5436                         }
5437                     }
5438                     else if (drawLineCount == 1)
5439                     {
5440                         TextRenderer.DrawText(e.Graphics,
5441                                                 e.SubItem.Text,
5442                                                 e.Item.Font,
5443                                                 Rectangle.Round(rct),
5444                                                 color,
5445                                                 TextFormatFlags.SingleLine |
5446                                                 TextFormatFlags.EndEllipsis |
5447                                                 TextFormatFlags.GlyphOverhangPadding |
5448                                                 TextFormatFlags.NoPrefix |
5449                                                 TextFormatFlags.VerticalCenter);
5450                     }
5451                     else
5452                     {
5453                         TextRenderer.DrawText(e.Graphics,
5454                                                 e.SubItem.Text,
5455                                                 e.Item.Font,
5456                                                 Rectangle.Round(rct),
5457                                                 color,
5458                                                 TextFormatFlags.WordBreak |
5459                                                 TextFormatFlags.EndEllipsis |
5460                                                 TextFormatFlags.GlyphOverhangPadding |
5461                                                 TextFormatFlags.NoPrefix);
5462                     }
5463                     //if (e.ColumnIndex == 6) this.DrawListViewItemStateIcon(e, rct);
5464                 }
5465             }
5466         }
5467
5468         private void DrawListViewItemIcon(DrawListViewItemEventArgs e)
5469         {
5470             ImageListViewItem item = (ImageListViewItem)e.Item;
5471
5472             //e.Bounds.Leftが常に0を指すから自前で計算
5473             Rectangle itemRect = item.Bounds;
5474             itemRect.Width = e.Item.ListView.Columns[0].Width;
5475
5476             foreach (ColumnHeader clm in e.Item.ListView.Columns)
5477             {
5478                 if (clm.DisplayIndex < e.Item.ListView.Columns[0].DisplayIndex)
5479                     itemRect.X += clm.Width;
5480             }
5481
5482             // ディスプレイの DPI 設定を考慮したアイコンサイズ
5483             var realIconSize = new SizeF(this._iconSz * this.currentScaleFactor.Width, this._iconSz * this.currentScaleFactor.Height).ToSize();
5484             var realStateSize = new SizeF(16 * this.currentScaleFactor.Width, 16 * this.currentScaleFactor.Height).ToSize();
5485
5486             Rectangle iconRect;
5487             Rectangle stateRect;
5488             if (item.Image != null)
5489             {
5490                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, realIconSize), itemRect);
5491                 iconRect.Offset(0, Math.Max(0, (itemRect.Height - realIconSize.Height) / 2));
5492                 stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + iconRect.Width + 2, iconRect.Y), realStateSize), itemRect);
5493             }
5494             else
5495             {
5496                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(1, 1)), itemRect);
5497                 //iconRect.Offset(0, Math.Max(0, (itemRect.Height - realIconSize.Height) / 2));
5498                 stateRect = Rectangle.Intersect(new Rectangle(new Point(iconRect.X + iconRect.Width + 2, iconRect.Y), realStateSize), itemRect);
5499             }
5500
5501             var img = item.Image;
5502             if (img != null && iconRect.Width > 0)
5503             {
5504                 e.Graphics.FillRectangle(Brushes.White, iconRect);
5505                 e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
5506                 try
5507                 {
5508                     e.Graphics.DrawImage(img.Image, iconRect);
5509                 }
5510                 catch (ArgumentException)
5511                 {
5512                     item.RefreshImage();
5513                 }
5514             }
5515
5516             if (item.StateImageIndex > -1)
5517             {
5518                 if (stateRect.Width > 0)
5519                 {
5520                     //e.Graphics.FillRectangle(Brushes.White, stateRect);
5521                     //e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High;
5522                     e.Graphics.DrawImage(this.PostStateImageList.Images[item.StateImageIndex], stateRect);
5523                 }
5524             }
5525         }
5526
5527         protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
5528         {
5529             base.ScaleControl(factor, specified);
5530
5531             const int baseDpi = 96;
5532
5533             // デザイン時の DPI (96dpi) との比を更新する
5534             this.currentScaleFactor = new SizeF(
5535                 this.CurrentAutoScaleDimensions.Width / baseDpi,
5536                 this.CurrentAutoScaleDimensions.Height / baseDpi);
5537         }
5538
5539         //private void DrawListViewItemStateIcon(DrawListViewSubItemEventArgs e, RectangleF rct)
5540         //{
5541         //    ImageListViewItem item = (ImageListViewItem)e.Item;
5542         //    if (item.StateImageIndex > -1)
5543         //    {
5544         //        ////e.Bounds.Leftが常に0を指すから自前で計算
5545         //        //Rectangle itemRect = item.Bounds;
5546         //        //itemRect.Width = e.Item.ListView.Columns[4].Width;
5547
5548         //        //foreach (ColumnHeader clm in e.Item.ListView.Columns)
5549         //        //{
5550         //        //    if (clm.DisplayIndex < e.Item.ListView.Columns[4].DisplayIndex)
5551         //        //    {
5552         //        //        itemRect.X += clm.Width;
5553         //        //    }
5554         //        //}
5555
5556         //        //Rectangle iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(_iconSz, _iconSz)), itemRect);
5557         //        //iconRect.Offset(0, Math.Max(0, (itemRect.Height - _iconSz) / 2));
5558
5559         //        if (rct.Width > 0)
5560         //        {
5561         //            RectangleF stateRect = RectangleF.Intersect(rct, new RectangleF(rct.Location, new Size(18, 16)));
5562         //            //e.Graphics.FillRectangle(Brushes.White, rct);
5563         //            //e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High;
5564         //            e.Graphics.DrawImage(this.PostStateImageList.Images(item.StateImageIndex), stateRect);
5565         //        }
5566         //    }
5567         //}
5568
5569         private void DoTabSearch(string _word,
5570                                  bool CaseSensitive,
5571                                  bool UseRegex,
5572                                  SEARCHTYPE SType)
5573         {
5574             int cidx = 0;
5575             bool fnd = false;
5576             int toIdx;
5577             int stp = 1;
5578
5579             if (_curList.VirtualListSize == 0)
5580             {
5581                 MessageBox.Show(Properties.Resources.DoTabSearchText2, Properties.Resources.DoTabSearchText3, MessageBoxButtons.OK, MessageBoxIcon.Information);
5582             }
5583
5584             if (_curList.SelectedIndices.Count > 0)
5585             {
5586                 cidx = _curList.SelectedIndices[0];
5587             }
5588             toIdx = _curList.VirtualListSize;
5589
5590             switch (SType)
5591             {
5592                 case SEARCHTYPE.DialogSearch:    //ダイアログからの検索
5593                     if (_curList.SelectedIndices.Count > 0)
5594                         cidx = _curList.SelectedIndices[0];
5595                     else
5596                         cidx = 0;
5597                     break;
5598                 case SEARCHTYPE.NextSearch:      //次を検索
5599                     if (_curList.SelectedIndices.Count > 0)
5600                     {
5601                         cidx = _curList.SelectedIndices[0] + 1;
5602                         if (cidx > toIdx) cidx = toIdx;
5603                     }
5604                     else
5605                     {
5606                         cidx = 0;
5607                     }
5608                     break;
5609                 case SEARCHTYPE.PrevSearch:      //前を検索
5610                     if (_curList.SelectedIndices.Count > 0)
5611                     {
5612                         cidx = _curList.SelectedIndices[0] - 1;
5613                         if (cidx < 0) cidx = 0;
5614                     }
5615                     else
5616                     {
5617                         cidx = toIdx;
5618                     }
5619                     toIdx = -1;
5620                     stp = -1;
5621                     break;
5622             }
5623
5624             RegexOptions regOpt = RegexOptions.None;
5625             StringComparison fndOpt = StringComparison.Ordinal;
5626             if (!CaseSensitive)
5627             {
5628                 regOpt = RegexOptions.IgnoreCase;
5629                 fndOpt = StringComparison.OrdinalIgnoreCase;
5630             }
5631             try
5632             {
5633     RETRY:
5634                 if (UseRegex)
5635                 {
5636                     // 正規表現検索
5637                     Regex _search;
5638                     try
5639                     {
5640                         _search = new Regex(_word, regOpt);
5641                         for (int idx = cidx; idx != toIdx; idx += stp)
5642                         {
5643                             PostClass post;
5644                             try
5645                             {
5646                                 post = _statuses[_curTab.Text, idx];
5647                             }
5648                             catch (Exception)
5649                             {
5650                                 continue;
5651                             }
5652                             if (_search.IsMatch(post.Nickname)
5653                                 || _search.IsMatch(post.TextFromApi)
5654                                 || _search.IsMatch(post.ScreenName))
5655                             {
5656                                 SelectListItem(_curList, idx);
5657                                 _curList.EnsureVisible(idx);
5658                                 return;
5659                             }
5660                         }
5661                     }
5662                     catch (ArgumentException)
5663                     {
5664                         MessageBox.Show(Properties.Resources.DoTabSearchText1, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
5665                         return;
5666                     }
5667                 }
5668                 else
5669                 {
5670                     // 通常検索
5671                     for (int idx = cidx; idx != toIdx; idx += stp)
5672                     {
5673                         PostClass post;
5674                         try
5675                         {
5676                             post = _statuses[_curTab.Text, idx];
5677                         }
5678                         catch (Exception)
5679                         {
5680                             continue;
5681                         }
5682                         if (post.Nickname.IndexOf(_word, fndOpt) > -1
5683                             || post.TextFromApi.IndexOf(_word, fndOpt) > -1
5684                             || post.ScreenName.IndexOf(_word, fndOpt) > -1)
5685                         {
5686                             SelectListItem(_curList, idx);
5687                             _curList.EnsureVisible(idx);
5688                             return;
5689                         }
5690                     }
5691                 }
5692
5693                 if (!fnd)
5694                 {
5695                     switch (SType)
5696                     {
5697                         case SEARCHTYPE.DialogSearch:
5698                         case SEARCHTYPE.NextSearch:
5699                             toIdx = cidx;
5700                             cidx = 0;
5701                             break;
5702                         case SEARCHTYPE.PrevSearch:
5703                             toIdx = cidx;
5704                             cidx = _curList.VirtualListSize - 1;
5705                             break;
5706                     }
5707                     fnd = true;
5708                     goto RETRY;
5709                 }
5710             }
5711             catch (ArgumentOutOfRangeException)
5712             {
5713             }
5714             MessageBox.Show(Properties.Resources.DoTabSearchText2, Properties.Resources.DoTabSearchText3, MessageBoxButtons.OK, MessageBoxIcon.Information);
5715         }
5716
5717         private void MenuItemSubSearch_Click(object sender, EventArgs e)
5718         {
5719             //検索メニュー
5720             SearchDialog.Owner = this;
5721             if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5722             {
5723                 this.TopMost = SettingDialog.AlwaysTop;
5724                 return;
5725             }
5726             this.TopMost = SettingDialog.AlwaysTop;
5727
5728             if (!string.IsNullOrEmpty(SearchDialog.SWord))
5729             {
5730                 DoTabSearch(SearchDialog.SWord,
5731                             SearchDialog.CheckCaseSensitive,
5732                             SearchDialog.CheckRegex,
5733                             SEARCHTYPE.DialogSearch);
5734             }
5735         }
5736
5737         private void MenuItemSearchNext_Click(object sender, EventArgs e)
5738         {
5739             //次を検索
5740             if (string.IsNullOrEmpty(SearchDialog.SWord))
5741             {
5742                 if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5743                 {
5744                     this.TopMost = SettingDialog.AlwaysTop;
5745                     return;
5746                 }
5747                 this.TopMost = SettingDialog.AlwaysTop;
5748                 if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
5749
5750                 DoTabSearch(SearchDialog.SWord,
5751                             SearchDialog.CheckCaseSensitive,
5752                             SearchDialog.CheckRegex,
5753                             SEARCHTYPE.DialogSearch);
5754             }
5755             else
5756             {
5757                 DoTabSearch(SearchDialog.SWord,
5758                             SearchDialog.CheckCaseSensitive,
5759                             SearchDialog.CheckRegex,
5760                             SEARCHTYPE.NextSearch);
5761             }
5762         }
5763
5764         private void MenuItemSearchPrev_Click(object sender, EventArgs e)
5765         {
5766             //前を検索
5767             if (string.IsNullOrEmpty(SearchDialog.SWord))
5768             {
5769                 if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5770                 {
5771                     this.TopMost = SettingDialog.AlwaysTop;
5772                     return;
5773                 }
5774                 this.TopMost = SettingDialog.AlwaysTop;
5775                 if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
5776             }
5777
5778             DoTabSearch(SearchDialog.SWord,
5779                         SearchDialog.CheckCaseSensitive,
5780                         SearchDialog.CheckRegex,
5781                         SEARCHTYPE.PrevSearch);
5782         }
5783
5784         private void AboutMenuItem_Click(object sender, EventArgs e)
5785         {
5786             using (TweenAboutBox about = new TweenAboutBox())
5787             {
5788                 about.ShowDialog(this);
5789             }
5790             this.TopMost = SettingDialog.AlwaysTop;
5791         }
5792
5793         private void JumpUnreadMenuItem_Click(object sender, EventArgs e)
5794         {
5795             int bgnIdx = ListTab.TabPages.IndexOf(_curTab);
5796             int idx = -1;
5797             DetailsListView lst = null;
5798
5799             if (ImageSelectionPanel.Enabled)
5800                 return;
5801
5802             //現在タブから最終タブまで探索
5803             for (int i = bgnIdx; i < ListTab.TabPages.Count; i++)
5804             {
5805                 //未読Index取得
5806                 idx = _statuses.GetOldestUnreadIndex(ListTab.TabPages[i].Text);
5807                 if (idx > -1)
5808                 {
5809                     ListTab.SelectedIndex = i;
5810                     lst = (DetailsListView)ListTab.TabPages[i].Tag;
5811                     //_curTab = ListTab.TabPages[i];
5812                     break;
5813                 }
5814             }
5815
5816             //未読みつからず&現在タブが先頭ではなかったら、先頭タブから現在タブの手前まで探索
5817             if (idx == -1 && bgnIdx > 0)
5818             {
5819                 for (int i = 0; i < bgnIdx; i++)
5820                 {
5821                     idx = _statuses.GetOldestUnreadIndex(ListTab.TabPages[i].Text);
5822                     if (idx > -1)
5823                     {
5824                         ListTab.SelectedIndex = i;
5825                         lst = (DetailsListView)ListTab.TabPages[i].Tag;
5826                         //_curTab = ListTab.TabPages[i];
5827                         break;
5828                     }
5829                 }
5830             }
5831
5832             //全部調べたが未読見つからず→先頭タブの最新発言へ
5833             if (idx == -1)
5834             {
5835                 ListTab.SelectedIndex = 0;
5836                 lst = (DetailsListView)ListTab.TabPages[0].Tag;
5837                 //_curTab = ListTab.TabPages[0];
5838                 if (_statuses.SortOrder == SortOrder.Ascending)
5839                     idx = lst.VirtualListSize - 1;
5840                 else
5841                     idx = 0;
5842             }
5843
5844             if (lst.VirtualListSize > 0 && idx > -1 && lst.VirtualListSize > idx)
5845             {
5846                 SelectListItem(lst, idx);
5847                 if (_statuses.SortMode == IdComparerClass.ComparerMode.Id)
5848                 {
5849                     if (_statuses.SortOrder == SortOrder.Ascending && lst.Items[idx].Position.Y > lst.ClientSize.Height - _iconSz - 10 ||
5850                        _statuses.SortOrder == SortOrder.Descending && lst.Items[idx].Position.Y < _iconSz + 10)
5851                     {
5852                         MoveTop();
5853                     }
5854                     else
5855                     {
5856                         lst.EnsureVisible(idx);
5857                     }
5858                 }
5859                 else
5860                 {
5861                     lst.EnsureVisible(idx);
5862                 }
5863             }
5864             lst.Focus();
5865         }
5866
5867         private void StatusOpenMenuItem_Click(object sender, EventArgs e)
5868         {
5869             if (_curList.SelectedIndices.Count > 0 && _statuses.Tabs[_curTab.Text].TabType != MyCommon.TabUsageType.DirectMessage)
5870             {
5871                 var post = _statuses[_curTab.Text, _curList.SelectedIndices[0]];
5872                 OpenUriAsync(MyCommon.GetStatusUrl(post));
5873             }
5874         }
5875
5876         private void FavorareMenuItem_Click(object sender, EventArgs e)
5877         {
5878             if (_curList.SelectedIndices.Count > 0)
5879             {
5880                 PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[0]];
5881                 OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + post.ScreenName + "/recent");
5882             }
5883         }
5884
5885         private void VerUpMenuItem_Click(object sender, EventArgs e)
5886         {
5887             CheckNewVersion();
5888         }
5889
5890         private void RunTweenUp()
5891         {
5892             ProcessStartInfo pinfo = new ProcessStartInfo();
5893             pinfo.UseShellExecute = true;
5894             pinfo.WorkingDirectory = MyCommon.settingPath;
5895             pinfo.FileName = Path.Combine(MyCommon.settingPath, "TweenUp3.exe");
5896             pinfo.Arguments = "\"" + Application.StartupPath + "\"";
5897             try
5898             {
5899                 Process.Start(pinfo);
5900             }
5901             catch (Exception)
5902             {
5903                 MessageBox.Show("Failed to execute TweenUp3.exe.");
5904             }
5905         }
5906
5907         private void CheckNewVersion(bool startup = false)
5908         {
5909             if (ApplicationSettings.VersionInfoUrl == null)
5910                 return; // 更新チェック無効化
5911
5912             if (string.IsNullOrEmpty(MyCommon.fileVersion))
5913             {
5914                 return;
5915             }
5916
5917             string retMsg;
5918             try
5919             {
5920                 retMsg = tw.GetVersionInfo();
5921             }
5922             catch
5923             {
5924                 retMsg = "";
5925             }
5926
5927             if (string.IsNullOrEmpty(retMsg))
5928             {
5929                 StatusLabel.Text = Properties.Resources.CheckNewVersionText9;
5930                 if (!startup) MessageBox.Show(Properties.Resources.CheckNewVersionText10, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
5931                 return;
5932             }
5933
5934             // 改行2つで前後パートを分割(前半がバージョン番号など、後半が詳細テキスト)
5935             string[] msgPart = retMsg.Split(new string[] {"\n\n", "\r\n\r\n"}, 2, StringSplitOptions.None);
5936
5937             string[] msgHeader = msgPart[0].Split(new string[] {"\n", "\r\n"}, StringSplitOptions.None);
5938             string msgBody = msgPart.Length == 2 ? msgPart[1] : "";
5939
5940             msgBody = Regex.Replace(msgBody, "(?<!\r)\n", "\r\n"); // LF -> CRLF
5941
5942             string currentVersion = msgHeader[0];
5943             string downloadUrl = msgHeader[1];
5944
5945             if (currentVersion.Replace(".", "").CompareTo(MyCommon.fileVersion.Replace(".", "")) > 0)
5946             {
5947                 using (var dialog = new UpdateDialog())
5948                 {
5949                     dialog.SummaryText = string.Format(Properties.Resources.CheckNewVersionText3, MyCommon.GetReadableVersion(currentVersion));
5950                     dialog.DetailsText = msgBody;
5951                     if (dialog.ShowDialog(this) == DialogResult.Yes)
5952                     {
5953                         this.OpenUriAsync(downloadUrl);
5954                     }
5955                 }
5956             }
5957             else
5958             {
5959                 if (!startup)
5960                 {
5961                     var msgtext = MyCommon.ReplaceAppName(string.Format(Properties.Resources.CheckNewVersionText7, MyCommon.GetReadableVersion(), MyCommon.GetReadableVersion(currentVersion)));
5962                     MessageBox.Show(msgtext, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Information);
5963                 }
5964             }
5965         }
5966
5967         private void Colorize()
5968         {
5969             _colorize = false;
5970             DispSelectedPost();
5971             //件数関連の場合、タイトル即時書き換え
5972             if (SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.None &&
5973                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Post &&
5974                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
5975                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
5976             {
5977                 SetMainWindowTitle();
5978             }
5979             if (!StatusLabelUrl.Text.StartsWith("http")) SetStatusLabelUrl();
5980             foreach (TabPage tb in ListTab.TabPages)
5981             {
5982                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
5983                 {
5984                     if (SettingDialog.TabIconDisp)
5985                     {
5986                         if (tb.ImageIndex == 0) tb.ImageIndex = -1;
5987                     }
5988                 }
5989             }
5990             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
5991         }
5992
5993         public string createDetailHtml(string orgdata)
5994         {
5995             return detailHtmlFormatHeader + orgdata + detailHtmlFormatFooter;
5996         }
5997
5998         private void DisplayItemImage_Downloaded(object sender, EventArgs e)
5999         {
6000             if (sender.Equals(displayItem))
6001             {
6002                 this.ClearUserPicture();
6003
6004                 var img = displayItem.Image;
6005                 try
6006                 {
6007                     UserPicture.Image = img != null ? img.Clone() : null;
6008                 }
6009                 catch (Exception)
6010                 {
6011                     UserPicture.ShowErrorImage();
6012                 }
6013             }
6014         }
6015
6016         private void DispSelectedPost()
6017         {
6018             DispSelectedPost(false);
6019         }
6020
6021         private static PostClass displaypost = new PostClass();
6022
6023         private void DispSelectedPost(bool forceupdate)
6024         {
6025             if (_curList.SelectedIndices.Count == 0 || _curPost == null)
6026                 return;
6027
6028             if (!forceupdate && _curPost.Equals(displaypost))
6029                 return;
6030
6031             displaypost = _curPost;
6032             if (displayItem != null)
6033             {
6034                 displayItem.ImageDownloaded -= this.DisplayItemImage_Downloaded;
6035                 displayItem = null;
6036             }
6037             displayItem = (ImageListViewItem)_curList.Items[_curList.SelectedIndices[0]];
6038             displayItem.ImageDownloaded += this.DisplayItemImage_Downloaded;
6039
6040             string dTxt = createDetailHtml(_curPost.IsDeleted ? "(DELETED)" : _curPost.Text);
6041             if (_curPost.IsDm)
6042             {
6043                 SourceLinkLabel.Tag = null;
6044                 SourceLinkLabel.Text = "";
6045             }
6046             else
6047             {
6048                 Match mc = Regex.Match(_curPost.SourceHtml, "<a href=\"(?<sourceurl>.+?)\"");
6049                 if (mc.Success)
6050                 {
6051                     string src = mc.Groups["sourceurl"].Value;
6052                     SourceLinkLabel.Tag = mc.Groups["sourceurl"].Value;
6053                     mc = Regex.Match(src, "^https?://");
6054                     if (!mc.Success)
6055                     {
6056                         src = src.Insert(0, "https://twitter.com");
6057                     }
6058                     SourceLinkLabel.Tag = src;
6059                 }
6060                 else
6061                 {
6062                     SourceLinkLabel.Tag = null;
6063                 }
6064                 if (string.IsNullOrEmpty(_curPost.Source))
6065                 {
6066                     SourceLinkLabel.Text = "";
6067                     //SourceLinkLabel.Visible = false;
6068                 }
6069                 else
6070                 {
6071                     SourceLinkLabel.Text = _curPost.Source;
6072                     //SourceLinkLabel.Visible = true;
6073                 }
6074             }
6075             SourceLinkLabel.TabStop = false;
6076
6077             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && !_curPost.IsOwl)
6078             {
6079                 NameLabel.Text = "DM TO -> ";
6080             }
6081             else if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)
6082             {
6083                 NameLabel.Text = "DM FROM <- ";
6084             }
6085             else
6086             {
6087                 NameLabel.Text = "";
6088             }
6089             NameLabel.Text += _curPost.ScreenName + "/" + _curPost.Nickname;
6090             NameLabel.Tag = _curPost.ScreenName;
6091             if (!string.IsNullOrEmpty(_curPost.RetweetedBy))
6092             {
6093                 NameLabel.Text += " (RT:" + _curPost.RetweetedBy + ")";
6094             }
6095
6096             this.ClearUserPicture();
6097
6098             if (!string.IsNullOrEmpty(_curPost.ImageUrl))
6099             {
6100                 var image = IconCache.TryGetFromCache(_curPost.ImageUrl);
6101                 try
6102                 {
6103                     UserPicture.Image = image != null ? image.Clone() : null;
6104                 }
6105                 catch (Exception)
6106                 {
6107                     UserPicture.ShowErrorImage();
6108                 }
6109             }
6110
6111             NameLabel.ForeColor = System.Drawing.SystemColors.ControlText;
6112             DateTimeLabel.Text = _curPost.CreatedAt.ToString();
6113             if (_curPost.IsOwl && (SettingDialog.OneWayLove || _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)) NameLabel.ForeColor = _clOWL;
6114             if (_curPost.RetweetedId != null) NameLabel.ForeColor = _clRetweet;
6115             if (_curPost.IsFav) NameLabel.ForeColor = _clFav;
6116
6117             if (DumpPostClassToolStripMenuItem.Checked)
6118             {
6119                 StringBuilder sb = new StringBuilder(512);
6120
6121                 sb.Append("-----Start PostClass Dump<br>");
6122                 sb.AppendFormat("TextFromApi           : {0}<br>", _curPost.TextFromApi);
6123                 sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.TextFromApi);
6124                 sb.AppendFormat("StatusId             : {0}<br>", _curPost.StatusId.ToString());
6125                 //sb.AppendFormat("ImageIndex     : {0}<br>", _curPost.ImageIndex.ToString());
6126                 sb.AppendFormat("ImageUrl       : {0}<br>", _curPost.ImageUrl);
6127                 sb.AppendFormat("InReplyToStatusId    : {0}<br>", _curPost.InReplyToStatusId.ToString());
6128                 sb.AppendFormat("InReplyToUser  : {0}<br>", _curPost.InReplyToUser);
6129                 sb.AppendFormat("IsDM           : {0}<br>", _curPost.IsDm.ToString());
6130                 sb.AppendFormat("IsFav          : {0}<br>", _curPost.IsFav.ToString());
6131                 sb.AppendFormat("IsMark         : {0}<br>", _curPost.IsMark.ToString());
6132                 sb.AppendFormat("IsMe           : {0}<br>", _curPost.IsMe.ToString());
6133                 sb.AppendFormat("IsOwl          : {0}<br>", _curPost.IsOwl.ToString());
6134                 sb.AppendFormat("IsProtect      : {0}<br>", _curPost.IsProtect.ToString());
6135                 sb.AppendFormat("IsRead         : {0}<br>", _curPost.IsRead.ToString());
6136                 sb.AppendFormat("IsReply        : {0}<br>", _curPost.IsReply.ToString());
6137             
6138                 foreach (string nm in _curPost.ReplyToList)
6139                 {
6140                     sb.AppendFormat("ReplyToList    : {0}<br>", nm);
6141                 }
6142
6143                 sb.AppendFormat("ScreenName           : {0}<br>", _curPost.ScreenName);
6144                 sb.AppendFormat("NickName       : {0}<br>", _curPost.Nickname);
6145                 sb.AppendFormat("Text   : {0}<br>", _curPost.Text);
6146                 sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.Text);
6147                 sb.AppendFormat("CreatedAt          : {0}<br>", _curPost.CreatedAt.ToString());
6148                 sb.AppendFormat("Source         : {0}<br>", _curPost.Source);
6149                 sb.AppendFormat("UserId            : {0}<br>", _curPost.UserId);
6150                 sb.AppendFormat("FilterHit      : {0}<br>", _curPost.FilterHit);
6151                 sb.AppendFormat("RetweetedBy    : {0}<br>", _curPost.RetweetedBy);
6152                 sb.AppendFormat("RetweetedId    : {0}<br>", _curPost.RetweetedId);
6153                 sb.AppendFormat("SearchTabName  : {0}<br>", _curPost.RelTabName);
6154                 sb.Append("-----End PostClass Dump<br>");
6155
6156                 PostBrowser.Visible = false;
6157                 PostBrowser.DocumentText = detailHtmlFormatHeader + sb.ToString() + detailHtmlFormatFooter;
6158                 PostBrowser.Visible = true;
6159             }
6160             else
6161             {
6162                 try
6163                 {
6164                     if (PostBrowser.DocumentText != dTxt)
6165                     {
6166                         PostBrowser.Visible = false;
6167                         PostBrowser.DocumentText = dTxt;
6168
6169                         this.SplitContainer3.Panel2Collapsed = true;
6170
6171                         if (this.IsPreviewEnable)
6172                             this.tweetThumbnail1.ShowThumbnailAsync(_curPost);
6173                     }
6174                 }
6175                 catch (System.Runtime.InteropServices.COMException)
6176                 {
6177                     //原因不明
6178                 }
6179                 catch (UriFormatException)
6180                 {
6181                     PostBrowser.DocumentText = dTxt;
6182                 }
6183                 finally
6184                 {
6185                     PostBrowser.Visible = true;
6186                 }
6187             }
6188         }
6189
6190         private void MatomeMenuItem_Click(object sender, EventArgs e)
6191         {
6192             OpenApplicationWebsite();
6193         }
6194
6195         private void OpenApplicationWebsite()
6196         {
6197             OpenUriAsync(ApplicationSettings.WebsiteUrl);
6198         }
6199
6200         private void ShortcutKeyListMenuItem_Click(object sender, EventArgs e)
6201         {
6202             OpenUriAsync(ApplicationSettings.ShortcutKeyUrl);
6203         }
6204
6205         private void ListTab_KeyDown(object sender, KeyEventArgs e)
6206         {
6207             if (ListTab.SelectedTab != null)
6208             {
6209                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
6210                 {
6211                     Control pnl = ListTab.SelectedTab.Controls["panelSearch"];
6212                     if (pnl.Controls["comboSearch"].Focused ||
6213                         pnl.Controls["comboLang"].Focused ||
6214                         pnl.Controls["buttonSearch"].Focused) return;
6215                 }
6216                 ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
6217                 if (State == ModifierState.NotFlags) return;
6218                 if (State != ModifierState.None) _anchorFlag = false;
6219                 if (CommonKeyDown(e.KeyCode, FocusedControl.ListTab, State))
6220                 {
6221                     e.Handled = true;
6222                     e.SuppressKeyPress = true;
6223                 }
6224             }
6225         }
6226
6227         private ModifierState GetModifierState(bool sControl, bool sShift, bool sAlt)
6228         {
6229             ModifierState state = ModifierState.None;
6230             if (sControl) state = state | ModifierState.Ctrl;
6231             if (sShift) state = state | ModifierState.Shift;
6232             if (sAlt) state = state | ModifierState.Alt;
6233             return state;
6234         }
6235
6236         [FlagsAttribute]
6237         private enum ModifierState
6238         {
6239             None = 0,
6240             Alt = 1,
6241             Shift = 2,
6242             Ctrl = 4,
6243             //CShift = 11,
6244             //CAlt = 12,
6245             //AShift = 13,
6246             NotFlags = 8,
6247
6248             //ListTab = 101,
6249             //PostBrowser = 102,
6250             //StatusText = 103,
6251         }
6252
6253         private enum FocusedControl : int
6254         {
6255             None,
6256             ListTab,
6257             StatusText,
6258             PostBrowser,
6259         }
6260
6261         private bool CommonKeyDown(Keys KeyCode, FocusedControl Focused, ModifierState Modifier)
6262         {
6263             //リストのカーソル移動関係(上下キー、PageUp/Downに該当)
6264             if (Focused == FocusedControl.ListTab)
6265             {
6266                 if (Modifier == (ModifierState.Ctrl | ModifierState.Shift) ||
6267                     Modifier == ModifierState.Ctrl ||
6268                     Modifier == ModifierState.None ||
6269                     Modifier == ModifierState.Shift)
6270                 {
6271                     if (KeyCode == Keys.J)
6272                     {
6273                         SendKeys.Send("{DOWN}");
6274                         return true;
6275                     }
6276                     else if (KeyCode == Keys.K)
6277                     {
6278                         SendKeys.Send("{UP}");
6279                         return true;
6280                     }
6281                 }
6282                 if (Modifier == ModifierState.Shift ||
6283                     Modifier == ModifierState.None)
6284                 {
6285                     if (KeyCode == Keys.F)
6286                     {
6287                         SendKeys.Send("{PGDN}");
6288                         return true;
6289                     }
6290                     else if (KeyCode == Keys.B)
6291                     {
6292                         SendKeys.Send("{PGUP}");
6293                         return true;
6294                     }
6295                 }
6296             }
6297
6298             //修飾キーなし
6299             switch (Modifier)
6300             {
6301                 case ModifierState.None:
6302                     //フォーカス関係なし
6303                     switch (KeyCode)
6304                     {
6305                         case Keys.F1:
6306                             OpenApplicationWebsite();
6307                             return true;
6308                         case Keys.F3:
6309                             MenuItemSearchNext_Click(null, null);
6310                             return true;
6311                         case Keys.F5:
6312                             DoRefresh();
6313                             return true;
6314                         case Keys.F6:
6315                             GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
6316                             return true;
6317                         case Keys.F7:
6318                             GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
6319                             return true;
6320                     }
6321                     if (Focused != FocusedControl.StatusText)
6322                     {
6323                         //フォーカスStatusText以外
6324                         switch (KeyCode)
6325                         {
6326                             case Keys.Space:
6327                             case Keys.ProcessKey:
6328                                 if (Focused == FocusedControl.ListTab) _anchorFlag = false;
6329                                 JumpUnreadMenuItem_Click(null, null);
6330                                 return true;
6331                             case Keys.G:
6332                                 if (Focused == FocusedControl.ListTab) _anchorFlag = false;
6333                                 ShowRelatedStatusesMenuItem_Click(null, null);
6334                                 return true;
6335                         }
6336                     }
6337                     if (Focused == FocusedControl.ListTab)
6338                     {
6339                         //フォーカスList
6340                         switch (KeyCode)
6341                         {
6342                             case Keys.N:
6343                             case Keys.Right:
6344                                 GoRelPost(true);
6345                                 return true;
6346                             case Keys.P:
6347                             case Keys.Left:
6348                                 GoRelPost(false);
6349                                 return true;
6350                             case Keys.OemPeriod:
6351                                 GoAnchor();
6352                                 return true;
6353                             case Keys.I:
6354                                 if (this.StatusText.Enabled) this.StatusText.Focus();
6355                                 return true;
6356                             case Keys.Enter:
6357                                 MakeReplyOrDirectStatus();
6358                                 return true;
6359                             case Keys.R:
6360                                 DoRefresh();
6361                                 return true;
6362                         }
6363                         //以下、アンカー初期化
6364                         _anchorFlag = false;
6365                         switch (KeyCode)
6366                         {
6367                             case Keys.L:
6368                                 GoPost(true);
6369                                 return true;
6370                             case Keys.H:
6371                                 GoPost(false);
6372                                 return true;
6373                             case Keys.Z:
6374                             case Keys.Oemcomma:
6375                                 MoveTop();
6376                                 return true;
6377                             case Keys.S:
6378                                 GoNextTab(true);
6379                                 return true;
6380                             case Keys.A:
6381                                 GoNextTab(false);
6382                                 return true;
6383                             case Keys.Oem4:
6384                                 // ] in_reply_to参照元へ戻る
6385                                 GoInReplyToPostTree();
6386                                 return true;
6387                             case Keys.Oem6:
6388                                 // [ in_reply_toへジャンプ
6389                                 GoBackInReplyToPostTree();
6390                                 return true;
6391                             case Keys.Escape:
6392                                 if (ListTab.SelectedTab != null)
6393                                 {
6394                                     MyCommon.TabUsageType tabtype = _statuses.Tabs[ListTab.SelectedTab.Text].TabType;
6395                                     if (tabtype == MyCommon.TabUsageType.Related || tabtype == MyCommon.TabUsageType.UserTimeline || tabtype == MyCommon.TabUsageType.PublicSearch)
6396                                     {
6397                                         TabPage relTp = ListTab.SelectedTab;
6398                                         RemoveSpecifiedTab(relTp.Text, false);
6399                                         SaveConfigsTabs();
6400                                         return true;
6401                                     }
6402                                 }
6403                                 break;
6404                         }
6405                     }
6406                     else if (Focused == FocusedControl.PostBrowser)
6407                     {
6408                         //フォーカスPostBrowser
6409                         switch (KeyCode)
6410                         {
6411                             case Keys.Up:
6412                             case Keys.Down:
6413                                 //スクロールを発生させるため、true を返す
6414                                 return true;
6415                         }
6416                     }
6417                     break;
6418                 case ModifierState.Ctrl:
6419                     //フォーカス関係なし
6420                     switch (KeyCode)
6421                     {
6422                         case Keys.R:
6423                             MakeReplyOrDirectStatus(false, true);
6424                             return true;
6425                         case Keys.D:
6426                             doStatusDelete();
6427                             return true;
6428                         case Keys.M:
6429                             MakeReplyOrDirectStatus(false, false);
6430                             return true;
6431                         case Keys.S:
6432                             FavoriteChange(true);
6433                             return true;
6434                         case Keys.I:
6435                             doRepliedStatusOpen();
6436                             return true;
6437                         case Keys.Q:
6438                             doQuote();
6439                             return true;
6440                         case Keys.B:
6441                             ReadedStripMenuItem_Click(null, null);
6442                             return true;
6443                         case Keys.T:
6444                             HashManageMenuItem_Click(null, null);
6445                             return true;
6446                         case Keys.L:
6447                             UrlConvertAutoToolStripMenuItem_Click(null, null);
6448                             return true;
6449                         case Keys.Y:
6450                             if (Focused != FocusedControl.PostBrowser)
6451                             {
6452                                 MultiLineMenuItem_Click(null, null);
6453                                 return true;
6454                             }
6455                             break;
6456                         case Keys.F:
6457                             MenuItemSubSearch_Click(null, null);
6458                             return true;
6459                         case Keys.U:
6460                             ShowUserTimeline();
6461                             return true;
6462                         case Keys.H:
6463                             // Webページを開く動作
6464                             MoveToHomeToolStripMenuItem_Click(null, null);
6465                             return true;
6466                         case Keys.G:
6467                             // Webページを開く動作
6468                             MoveToFavToolStripMenuItem_Click(null, null);
6469                             return true;
6470                         case Keys.O:
6471                             // Webページを開く動作
6472                             StatusOpenMenuItem_Click(null, null);
6473                             return true;
6474                         case Keys.E:
6475                             // Webページを開く動作
6476                             OpenURLMenuItem_Click(null, null);
6477                             return true;
6478                     }
6479                     //フォーカスList
6480                     if (Focused == FocusedControl.ListTab)
6481                     {
6482                         switch (KeyCode)
6483                         {
6484                             case Keys.Home:
6485                             case Keys.End:
6486                                 _colorize = true;
6487                                 return false;            //スルーする
6488                             case Keys.N:
6489                                 GoNextTab(true);
6490                                 return true;
6491                             case Keys.P:
6492                                 GoNextTab(false);
6493                                 return true;
6494                             case Keys.C:
6495                                 CopyStot();
6496                                 return true;
6497                             case Keys.D1:
6498                             case Keys.D2:
6499                             case Keys.D3:
6500                             case Keys.D4:
6501                             case Keys.D5:
6502                             case Keys.D6:
6503                             case Keys.D7:
6504                             case Keys.D8:
6505                                 // タブダイレクト選択(Ctrl+1~8,Ctrl+9)
6506                                 int tabNo = KeyCode - Keys.D1;
6507                                 if (ListTab.TabPages.Count < tabNo)
6508                                     return false;
6509                                 ListTab.SelectedIndex = tabNo;
6510                                 ListTabSelect(ListTab.TabPages[tabNo]);
6511                                 return true;
6512                             case Keys.D9:
6513                                 ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
6514                                 ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
6515                                 return true;
6516                         }
6517                     }
6518                     else if (Focused == FocusedControl.StatusText)
6519                     {
6520                         //フォーカスStatusText
6521                         switch (KeyCode)
6522                         {
6523                             case Keys.A:
6524                                 StatusText.SelectAll();
6525                                 return true;
6526                             case Keys.Up:
6527                             case Keys.Down:
6528                                 if (!string.IsNullOrWhiteSpace(StatusText.Text))
6529                                 {
6530                                     _history[_hisIdx] = new PostingStatus(StatusText.Text, _reply_to_id, _reply_to_name);
6531                                 }
6532                                 if (KeyCode == Keys.Up)
6533                                 {
6534                                     _hisIdx -= 1;
6535                                     if (_hisIdx < 0) _hisIdx = 0;
6536                                 }
6537                                 else
6538                                 {
6539                                     _hisIdx += 1;
6540                                     if (_hisIdx > _history.Count - 1) _hisIdx = _history.Count - 1;
6541                                 }
6542                                 StatusText.Text = _history[_hisIdx].status;
6543                                 _reply_to_id = _history[_hisIdx].inReplyToId;
6544                                 _reply_to_name = _history[_hisIdx].inReplyToName;
6545                                 StatusText.SelectionStart = StatusText.Text.Length;
6546                                 return true;
6547                             case Keys.PageUp:
6548                             case Keys.P:
6549                                 if (ListTab.SelectedIndex == 0)
6550                                 {
6551                                     ListTab.SelectedIndex = ListTab.TabCount - 1;
6552                                 }
6553                                 else
6554                                 {
6555                                     ListTab.SelectedIndex -= 1;
6556                                 }
6557                                 StatusText.Focus();
6558                                 return true;
6559                             case Keys.PageDown:
6560                             case Keys.N:
6561                                 if (ListTab.SelectedIndex == ListTab.TabCount - 1)
6562                                 {
6563                                     ListTab.SelectedIndex = 0;
6564                                 }
6565                                 else
6566                                 {
6567                                     ListTab.SelectedIndex += 1;
6568                                 }
6569                                 StatusText.Focus();
6570                                 return true;
6571                         }
6572                     }
6573                     else
6574                     {
6575                         //フォーカスPostBrowserもしくは関係なし
6576                         switch (KeyCode)
6577                         {
6578                             case Keys.A:
6579                                 PostBrowser.Document.ExecCommand("SelectAll", false, null);
6580                                 return true;
6581                             case Keys.C:
6582                             case Keys.Insert:
6583                                 string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
6584                                 if (!string.IsNullOrEmpty(_selText))
6585                                 {
6586                                     try
6587                                     {
6588                                         Clipboard.SetDataObject(_selText, false, 5, 100);
6589                                     }
6590                                     catch (Exception ex)
6591                                     {
6592                                         MessageBox.Show(ex.Message);
6593                                     }
6594                                 }
6595                                 return true;
6596                             case Keys.Y:
6597                                 MultiLineMenuItem.Checked = !MultiLineMenuItem.Checked;
6598                                 MultiLineMenuItem_Click(null, null);
6599                                 return true;
6600                         }
6601                     }
6602                     break;
6603                 case ModifierState.Shift:
6604                     //フォーカス関係なし
6605                     switch (KeyCode)
6606                     {
6607                         case Keys.F3:
6608                             MenuItemSearchPrev_Click(null, null);
6609                             return true;
6610                         case Keys.F5:
6611                             DoRefreshMore();
6612                             return true;
6613                         case Keys.F6:
6614                             GetTimeline(MyCommon.WORKERTYPE.Reply, -1, 0, "");
6615                             return true;
6616                         case Keys.F7:
6617                             GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, -1, 0, "");
6618                             return true;
6619                     }
6620                     //フォーカスStatusText以外
6621                     if (Focused != FocusedControl.StatusText)
6622                     {
6623                         if (KeyCode == Keys.R)
6624                         {
6625                             DoRefreshMore();
6626                             return true;
6627                         }
6628                     }
6629                     //フォーカスリスト
6630                     if (Focused == FocusedControl.ListTab)
6631                     {
6632                         switch (KeyCode)
6633                         {
6634                             case Keys.H:
6635                                 GoTopEnd(true);
6636                                 return true;
6637                             case Keys.L:
6638                                 GoTopEnd(false);
6639                                 return true;
6640                             case Keys.M:
6641                                 GoMiddle();
6642                                 return true;
6643                             case Keys.G:
6644                                 GoLast();
6645                                 return true;
6646                             case Keys.Z:
6647                                 MoveMiddle();
6648                                 return true;
6649                             case Keys.Oem4:
6650                                 GoBackInReplyToPostTree(true, false);
6651                                 return true;
6652                             case Keys.Oem6:
6653                                 GoBackInReplyToPostTree(true, true);
6654                                 return true;
6655                             case Keys.N:
6656                             case Keys.Right:
6657                                 // お気に入り前後ジャンプ(SHIFT+N←/P→)
6658                                 GoFav(true);
6659                                 return true;
6660                             case Keys.P:
6661                             case Keys.Left:
6662                                 // お気に入り前後ジャンプ(SHIFT+N←/P→)
6663                                 GoFav(false);
6664                                 return true;
6665                             case Keys.Space:
6666                                 this.GoBackSelectPostChain();
6667                                 return true;
6668                         }
6669                     }
6670                     break;
6671                 case ModifierState.Alt:
6672                     switch (KeyCode)
6673                     {
6674                         case Keys.R:
6675                             doReTweetOfficial(true);
6676                             return true;
6677                         case Keys.P:
6678                             if (_curPost != null)
6679                             {
6680                                 doShowUserStatus(_curPost.ScreenName, false);
6681                                 return true;
6682                             }
6683                             break;
6684                         case Keys.Up:
6685                             ScrollDownPostBrowser(false);
6686                             return true;
6687                         case Keys.Down:
6688                             ScrollDownPostBrowser(true);
6689                             return true;
6690                         case Keys.PageUp:
6691                             PageDownPostBrowser(false);
6692                             return true;
6693                         case Keys.PageDown:
6694                             PageDownPostBrowser(true);
6695                             return true;
6696                     }
6697                     if (Focused == FocusedControl.ListTab)
6698                     {
6699                         // 別タブの同じ書き込みへ(ALT+←/→)
6700                         if (KeyCode == Keys.Right)
6701                         {
6702                             GoSamePostToAnotherTab(false);
6703                             return true;
6704                         }
6705                         else if (KeyCode == Keys.Left)
6706                         {
6707                             GoSamePostToAnotherTab(true);
6708                             return true;
6709                         }
6710                     }
6711                     break;
6712                 case ModifierState.Ctrl | ModifierState.Shift:
6713                     switch (KeyCode)
6714                     {
6715                         case Keys.R:
6716                             MakeReplyOrDirectStatus(false, true, true);
6717                             return true;
6718                         case Keys.C:
6719                             CopyIdUri();
6720                             return true;
6721                         case Keys.F:
6722                             if (ListTab.SelectedTab != null)
6723                             {
6724                                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
6725                                 {
6726                                     ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
6727                                     return true;
6728                                 }
6729                             }
6730                             break;
6731                         case Keys.S:
6732                             FavoriteChange(false);
6733                             return true;
6734                         case Keys.B:
6735                             UnreadStripMenuItem_Click(null, null);
6736                             return true;
6737                         case Keys.T:
6738                             HashToggleMenuItem_Click(null, null);
6739                             return true;
6740                         case Keys.P:
6741                             ImageSelectMenuItem_Click(null, null);
6742                             return true;
6743                         case Keys.H:
6744                             doMoveToRTHome();
6745                             return true;
6746                         case Keys.O:
6747                             FavorareMenuItem_Click(null, null);
6748                             return true;
6749                     }
6750                     if (Focused == FocusedControl.StatusText)
6751                     {
6752                         int idx = 0;
6753                         switch (KeyCode)
6754                         {
6755                             case Keys.Up:
6756                                 if (_curList != null && _curList.VirtualListSize != 0 &&
6757                                             _curList.SelectedIndices.Count > 0 && _curList.SelectedIndices[0] > 0)
6758                                 {
6759                                     idx = _curList.SelectedIndices[0] - 1;
6760                                     SelectListItem(_curList, idx);
6761                                     _curList.EnsureVisible(idx);
6762                                     return true;
6763                                 }
6764                                 break;
6765                             case Keys.Down:
6766                                 if (_curList != null && _curList.VirtualListSize != 0 && _curList.SelectedIndices.Count > 0
6767                                             && _curList.SelectedIndices[0] < _curList.VirtualListSize - 1)
6768                                 {
6769                                     idx = _curList.SelectedIndices[0] + 1;
6770                                     SelectListItem(_curList, idx);
6771                                     _curList.EnsureVisible(idx);
6772                                     return true;
6773                                 }
6774                                 break;
6775                             case Keys.Space:
6776                                 if (StatusText.SelectionStart > 0)
6777                                 {
6778                                     int endidx = StatusText.SelectionStart - 1;
6779                                     string startstr = "";
6780                                     bool pressed = false;
6781                                     for (int i = StatusText.SelectionStart - 1; i >= 0; i--)
6782                                     {
6783                                         char c = StatusText.Text[i];
6784                                         if (Char.IsLetterOrDigit(c) || c == '_')
6785                                         {
6786                                             continue;
6787                                         }
6788                                         if (c == '@')
6789                                         {
6790                                             pressed = true;
6791                                             startstr = StatusText.Text.Substring(i + 1, endidx - i);
6792                                             int cnt = AtIdSupl.ItemCount;
6793                                             ShowSuplDialog(StatusText, AtIdSupl, startstr.Length + 1, startstr);
6794                                             if (AtIdSupl.ItemCount != cnt) _modifySettingAtId = true;
6795                                         }
6796                                         else if (c == '#')
6797                                         {
6798                                             pressed = true;
6799                                             startstr = StatusText.Text.Substring(i + 1, endidx - i);
6800                                             ShowSuplDialog(StatusText, HashSupl, startstr.Length + 1, startstr);
6801                                         }
6802                                         else
6803                                         {
6804                                             break;
6805                                         }
6806                                     }
6807                                     return pressed;
6808                                 }
6809                                 break;
6810                         }
6811                     }
6812                     else if (Focused == FocusedControl.ListTab)
6813                     {
6814                         DetailsListView lst = (DetailsListView)ListTab.SelectedTab.Tag;
6815                         ColumnHeader col;
6816                         switch (KeyCode)
6817                         {
6818                             case Keys.D1:
6819                             case Keys.D2:
6820                             case Keys.D3:
6821                             case Keys.D4:
6822                             case Keys.D5:
6823                             case Keys.D6:
6824                             case Keys.D7:
6825                             case Keys.D8:
6826                                 // ソートダイレクト選択(Ctrl+Shift+1~8,Ctrl+Shift+9)
6827                                 int colNo = KeyCode - Keys.D1;
6828                                 if (lst.Columns.Count < colNo) return false;
6829                                 col = lst.Columns.Cast<ColumnHeader>().Where((x) => { return x.DisplayIndex == colNo; }).FirstOrDefault();
6830                                 if (col == null) return false;
6831                                 MyList_ColumnClick(lst, new ColumnClickEventArgs(col.Index));
6832                                 return true;
6833                             case Keys.D9:
6834                                 col = lst.Columns.Cast<ColumnHeader>().OrderByDescending((x) => { return x.DisplayIndex; }).First();
6835                                 MyList_ColumnClick(lst, new ColumnClickEventArgs(col.Index));
6836                                 return true;
6837                         }
6838                     }
6839                     break;
6840                 case ModifierState.Ctrl | ModifierState.Alt:
6841                     if (KeyCode == Keys.S)
6842                     {
6843                         FavoritesRetweetOriginal();
6844                         return true;
6845                     }
6846                     else if (KeyCode == Keys.R)
6847                     {
6848                         FavoritesRetweetUnofficial();
6849                         return true;
6850                     }
6851                     else if (KeyCode == Keys.H)
6852                     {
6853                         OpenUserAppointUrl();
6854                         return true;
6855                     }
6856                     break;
6857                 case ModifierState.Alt | ModifierState.Shift:
6858                     if (Focused == FocusedControl.PostBrowser)
6859                     {
6860                         if (KeyCode == Keys.R)
6861                             doReTweetUnofficial();
6862                         else if (KeyCode == Keys.C)
6863                             CopyUserId();
6864                         return true;
6865                     }
6866                     switch (KeyCode)
6867                     {
6868                         case Keys.T:
6869                             if (!this.ExistCurrentPost) return false;
6870                             doTranslation(_curPost.TextFromApi);
6871                             return true;
6872                         case Keys.R:
6873                             doReTweetUnofficial();
6874                             return true;
6875                         case Keys.C:
6876                             CopyUserId();
6877                             return true;
6878                         case Keys.Up:
6879                             this.tweetThumbnail1.ScrollUp();
6880                             return true;
6881                         case Keys.Down:
6882                             this.tweetThumbnail1.ScrollDown();
6883                             return true;
6884                     }
6885                     if (Focused == FocusedControl.ListTab && KeyCode == Keys.Enter)
6886                     {
6887                         if (!this.SplitContainer3.Panel2Collapsed)
6888                         {
6889                             OpenThumbnailPicture(this.tweetThumbnail1.Thumbnail);
6890                         }
6891                         return true;
6892                     }
6893                     break;
6894             }
6895
6896             return false;
6897         }
6898
6899         private void ScrollDownPostBrowser(bool forward)
6900         {
6901             var doc = PostBrowser.Document;
6902             if (doc == null) return;
6903
6904             var tags = doc.GetElementsByTagName("html");
6905             if (tags.Count > 0)
6906             {
6907                 if (forward)
6908                     tags[0].ScrollTop += SettingDialog.FontDetail.Height;
6909                 else
6910                     tags[0].ScrollTop -= SettingDialog.FontDetail.Height;
6911             }
6912         }
6913
6914         private void PageDownPostBrowser(bool forward)
6915         {
6916             var doc = PostBrowser.Document;
6917             if (doc == null) return;
6918
6919             var tags = doc.GetElementsByTagName("html");
6920             if (tags.Count > 0)
6921             {
6922                 if (forward)
6923                     tags[0].ScrollTop += PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
6924                 else
6925                     tags[0].ScrollTop -= PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
6926             }
6927         }
6928
6929         private void GoNextTab(bool forward)
6930         {
6931             int idx = ListTab.SelectedIndex;
6932             if (forward)
6933             {
6934                 idx += 1;
6935                 if (idx > ListTab.TabPages.Count - 1) idx = 0;
6936             }
6937             else
6938             {
6939                 idx -= 1;
6940                 if (idx < 0) idx = ListTab.TabPages.Count - 1;
6941             }
6942             ListTab.SelectedIndex = idx;
6943             ListTabSelect(ListTab.TabPages[idx]);
6944         }
6945
6946         private void CopyStot()
6947         {
6948             string clstr = "";
6949             StringBuilder sb = new StringBuilder();
6950             bool IsProtected = false;
6951             bool isDm = false;
6952             if (this._curTab != null && this._statuses.GetTabByName(this._curTab.Text) != null) isDm = this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage;
6953             foreach (int idx in _curList.SelectedIndices)
6954             {
6955                 PostClass post = _statuses[_curTab.Text, idx];
6956                 if (post.IsProtect)
6957                 {
6958                     IsProtected = true;
6959                     continue;
6960                 }
6961                 if (post.IsDeleted) continue;
6962                 if (!isDm)
6963                 {
6964                     if (post.RetweetedId != null)
6965                         sb.AppendFormat("{0}:{1} [https://twitter.com/{0}/status/{2}]{3}", post.ScreenName, post.TextSingleLine, post.RetweetedId, Environment.NewLine);
6966                     else
6967                         sb.AppendFormat("{0}:{1} [https://twitter.com/{0}/status/{2}]{3}", post.ScreenName, post.TextSingleLine, post.StatusId, Environment.NewLine);
6968                 }
6969                 else
6970                 {
6971                     sb.AppendFormat("{0}:{1} [{2}]{3}", post.ScreenName, post.TextSingleLine, post.StatusId, Environment.NewLine);
6972                 }
6973             }
6974             if (IsProtected)
6975             {
6976                 MessageBox.Show(Properties.Resources.CopyStotText1);
6977             }
6978             if (sb.Length > 0)
6979             {
6980                 clstr = sb.ToString();
6981                 try
6982                 {
6983                     Clipboard.SetDataObject(clstr, false, 5, 100);
6984                 }
6985                 catch (Exception ex)
6986                 {
6987                     MessageBox.Show(ex.Message);
6988                 }
6989             }
6990         }
6991
6992         private void CopyIdUri()
6993         {
6994             string clstr = "";
6995             StringBuilder sb = new StringBuilder();
6996             if (this._curTab == null) return;
6997             if (this._statuses.GetTabByName(this._curTab.Text) == null) return;
6998             if (this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage) return;
6999             foreach (int idx in _curList.SelectedIndices)
7000             {
7001                 var post = _statuses[_curTab.Text, idx];
7002                 sb.Append(MyCommon.GetStatusUrl(post));
7003                 sb.Append(Environment.NewLine);
7004             }
7005             if (sb.Length > 0)
7006             {
7007                 clstr = sb.ToString();
7008                 try
7009                 {
7010                     Clipboard.SetDataObject(clstr, false, 5, 100);
7011                 }
7012                 catch (Exception ex)
7013                 {
7014                     MessageBox.Show(ex.Message);
7015                 }
7016             }
7017         }
7018
7019         private void GoFav(bool forward)
7020         {
7021             if (_curList.VirtualListSize == 0) return;
7022             int fIdx = 0;
7023             int toIdx = 0;
7024             int stp = 1;
7025
7026             if (forward)
7027             {
7028                 if (_curList.SelectedIndices.Count == 0)
7029                 {
7030                     fIdx = 0;
7031                 }
7032                 else
7033                 {
7034                     fIdx = _curList.SelectedIndices[0] + 1;
7035                     if (fIdx > _curList.VirtualListSize - 1) return;
7036                 }
7037                 toIdx = _curList.VirtualListSize;
7038                 stp = 1;
7039             }
7040             else
7041             {
7042                 if (_curList.SelectedIndices.Count == 0)
7043                 {
7044                     fIdx = _curList.VirtualListSize - 1;
7045                 }
7046                 else
7047                 {
7048                     fIdx = _curList.SelectedIndices[0] - 1;
7049                     if (fIdx < 0) return;
7050                 }
7051                 toIdx = -1;
7052                 stp = -1;
7053             }
7054
7055             for (int idx = fIdx; idx != toIdx; idx += stp)
7056             {
7057                 if (_statuses[_curTab.Text, idx].IsFav)
7058                 {
7059                     SelectListItem(_curList, idx);
7060                     _curList.EnsureVisible(idx);
7061                     break;
7062                 }
7063             }
7064         }
7065
7066         private void GoSamePostToAnotherTab(bool left)
7067         {
7068             if (_curList.VirtualListSize == 0) return;
7069             int fIdx = 0;
7070             int toIdx = 0;
7071             int stp = 1;
7072             long targetId = 0;
7073
7074             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage) return; // Directタブは対象外(見つかるはずがない)
7075             if (_curList.SelectedIndices.Count == 0) return; //未選択も処理しない
7076
7077             targetId = GetCurTabPost(_curList.SelectedIndices[0]).StatusId;
7078
7079             if (left)
7080             {
7081                 // 左のタブへ
7082                 if (ListTab.SelectedIndex == 0)
7083                 {
7084                     return;
7085                 }
7086                 else
7087                 {
7088                     fIdx = ListTab.SelectedIndex - 1;
7089                 }
7090                 toIdx = -1;
7091                 stp = -1;
7092             }
7093             else
7094             {
7095                 // 右のタブへ
7096                 if (ListTab.SelectedIndex == ListTab.TabCount - 1)
7097                 {
7098                     return;
7099                 }
7100                 else
7101                 {
7102                     fIdx = ListTab.SelectedIndex + 1;
7103                 }
7104                 toIdx = ListTab.TabCount;
7105                 stp = 1;
7106             }
7107
7108             bool found = false;
7109             for (int tabidx = fIdx; tabidx != toIdx; tabidx += stp)
7110             {
7111                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage) continue; // Directタブは対象外
7112                 for (int idx = 0; idx < ((DetailsListView)ListTab.TabPages[tabidx].Tag).VirtualListSize; idx++)
7113                 {
7114                     if (_statuses[ListTab.TabPages[tabidx].Text, idx].StatusId == targetId)
7115                     {
7116                         ListTab.SelectedIndex = tabidx;
7117                         ListTabSelect(ListTab.TabPages[tabidx]);
7118                         SelectListItem(_curList, idx);
7119                         _curList.EnsureVisible(idx);
7120                         found = true;
7121                         break;
7122                     }
7123                 }
7124                 if (found) break;
7125             }
7126         }
7127
7128         private void GoPost(bool forward)
7129         {
7130             if (_curList.SelectedIndices.Count == 0 || _curPost == null) return;
7131             int fIdx = 0;
7132             int toIdx = 0;
7133             int stp = 1;
7134
7135             if (forward)
7136             {
7137                 fIdx = _curList.SelectedIndices[0] + 1;
7138                 if (fIdx > _curList.VirtualListSize - 1) return;
7139                 toIdx = _curList.VirtualListSize;
7140                 stp = 1;
7141             }
7142             else
7143             {
7144                 fIdx = _curList.SelectedIndices[0] - 1;
7145                 if (fIdx < 0) return;
7146                 toIdx = -1;
7147                 stp = -1;
7148             }
7149
7150             string name = "";
7151             if (_curPost.RetweetedId == null)
7152             {
7153                 name = _curPost.ScreenName;
7154             }
7155             else
7156             {
7157                 name = _curPost.RetweetedBy;
7158             }
7159             for (int idx = fIdx; idx != toIdx; idx += stp)
7160             {
7161                 if (_statuses[_curTab.Text, idx].RetweetedId == null)
7162                 {
7163                     if (_statuses[_curTab.Text, idx].ScreenName == name)
7164                     {
7165                         SelectListItem(_curList, idx);
7166                         _curList.EnsureVisible(idx);
7167                         break;
7168                     }
7169                 }
7170                 else
7171                 {
7172                     if (_statuses[_curTab.Text, idx].RetweetedBy == name)
7173                     {
7174                         SelectListItem(_curList, idx);
7175                         _curList.EnsureVisible(idx);
7176                         break;
7177                     }
7178                 }
7179             }
7180         }
7181
7182         private void GoRelPost(bool forward)
7183         {
7184             if (_curList.SelectedIndices.Count == 0) return;
7185
7186             int fIdx = 0;
7187             int toIdx = 0;
7188             int stp = 1;
7189             if (forward)
7190             {
7191                 fIdx = _curList.SelectedIndices[0] + 1;
7192                 if (fIdx > _curList.VirtualListSize - 1) return;
7193                 toIdx = _curList.VirtualListSize;
7194                 stp = 1;
7195             }
7196             else
7197             {
7198                 fIdx = _curList.SelectedIndices[0] - 1;
7199                 if (fIdx < 0) return;
7200                 toIdx = -1;
7201                 stp = -1;
7202             }
7203
7204             if (!_anchorFlag)
7205             {
7206                 if (_curPost == null) return;
7207                 _anchorPost = _curPost;
7208                 _anchorFlag = true;
7209             }
7210             else
7211             {
7212                 if (_anchorPost == null) return;
7213             }
7214
7215             for (int idx = fIdx; idx != toIdx; idx += stp)
7216             {
7217                 PostClass post = _statuses[_curTab.Text, idx];
7218                 if (post.ScreenName == _anchorPost.ScreenName ||
7219                     post.RetweetedBy == _anchorPost.ScreenName ||
7220                     post.ScreenName == _anchorPost.RetweetedBy ||
7221                     (!string.IsNullOrEmpty(post.RetweetedBy) && post.RetweetedBy == _anchorPost.RetweetedBy) ||
7222                     _anchorPost.ReplyToList.Contains(post.ScreenName.ToLower()) ||
7223                     _anchorPost.ReplyToList.Contains(post.RetweetedBy.ToLower()) ||
7224                     post.ReplyToList.Contains(_anchorPost.ScreenName.ToLower()) ||
7225                     post.ReplyToList.Contains(_anchorPost.RetweetedBy.ToLower()))
7226                 {
7227                     SelectListItem(_curList, idx);
7228                     _curList.EnsureVisible(idx);
7229                     break;
7230                 }
7231             }
7232         }
7233
7234         private void GoAnchor()
7235         {
7236             if (_anchorPost == null) return;
7237             int idx = _statuses.Tabs[_curTab.Text].IndexOf(_anchorPost.StatusId);
7238             if (idx == -1) return;
7239
7240             SelectListItem(_curList, idx);
7241             _curList.EnsureVisible(idx);
7242         }
7243
7244         private void GoTopEnd(bool GoTop)
7245         {
7246             ListViewItem _item;
7247             int idx;
7248
7249             if (GoTop)
7250             {
7251                 _item = _curList.GetItemAt(0, 25);
7252                 if (_item == null)
7253                     idx = 0;
7254                 else
7255                     idx = _item.Index;
7256             }
7257             else
7258             {
7259                 _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
7260                 if (_item == null)
7261                     idx = _curList.VirtualListSize - 1;
7262                 else
7263                     idx = _item.Index;
7264             }
7265             SelectListItem(_curList, idx);
7266         }
7267
7268         private void GoMiddle()
7269         {
7270             ListViewItem _item;
7271             int idx1;
7272             int idx2;
7273             int idx3;
7274
7275             _item = _curList.GetItemAt(0, 0);
7276             if (_item == null)
7277             {
7278                 idx1 = 0;
7279             }
7280             else
7281             {
7282                 idx1 = _item.Index;
7283             }
7284
7285             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
7286             if (_item == null)
7287             {
7288                 idx2 = _curList.VirtualListSize - 1;
7289             }
7290             else
7291             {
7292                 idx2 = _item.Index;
7293             }
7294             idx3 = (idx1 + idx2) / 2;
7295
7296             SelectListItem(_curList, idx3);
7297         }
7298
7299         private void GoLast()
7300         {
7301             if (_curList.VirtualListSize == 0) return;
7302
7303             if (_statuses.SortOrder == SortOrder.Ascending)
7304             {
7305                 SelectListItem(_curList, _curList.VirtualListSize - 1);
7306                 _curList.EnsureVisible(_curList.VirtualListSize - 1);
7307             }
7308             else
7309             {
7310                 SelectListItem(_curList, 0);
7311                 _curList.EnsureVisible(0);
7312             }
7313         }
7314
7315         private void MoveTop()
7316         {
7317             if (_curList.SelectedIndices.Count == 0) return;
7318             int idx = _curList.SelectedIndices[0];
7319             if (_statuses.SortOrder == SortOrder.Ascending)
7320             {
7321                 _curList.EnsureVisible(_curList.VirtualListSize - 1);
7322             }
7323             else
7324             {
7325                 _curList.EnsureVisible(0);
7326             }
7327             _curList.EnsureVisible(idx);
7328         }
7329
7330         private void GoInReplyToPostTree()
7331         {
7332             if (_curPost == null) return;
7333
7334             TabClass curTabClass = _statuses.Tabs[_curTab.Text];
7335
7336             if (curTabClass.TabType == MyCommon.TabUsageType.PublicSearch && _curPost.InReplyToStatusId == null && _curPost.TextFromApi.Contains("@"))
7337             {
7338                 PostClass post = null;
7339                 string r = tw.GetStatusApi(false, _curPost.StatusId, ref post);
7340                 if (string.IsNullOrEmpty(r) && post != null)
7341                 {
7342                     _curPost.InReplyToStatusId = post.InReplyToStatusId;
7343                     _curPost.InReplyToUser = post.InReplyToUser;
7344                     _curPost.IsReply = post.IsReply;
7345                     this.PurgeListViewItemCache();
7346                     _curList.RedrawItems(_curItemIndex, _curItemIndex, false);
7347                 }
7348                 else
7349                 {
7350                     this.StatusLabel.Text = r;
7351                 }
7352             }
7353
7354             if (!(this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId != null)) return;
7355
7356             if (replyChains == null || (replyChains.Count > 0 && replyChains.Peek().InReplyToId != _curPost.StatusId))
7357             {
7358                 replyChains = new Stack<ReplyChain>();
7359             }
7360             replyChains.Push(new ReplyChain(_curPost.StatusId, _curPost.InReplyToStatusId.Value, _curTab));
7361
7362             int inReplyToIndex;
7363             string inReplyToTabName;
7364             long inReplyToId = _curPost.InReplyToStatusId.Value;
7365             string inReplyToUser = _curPost.InReplyToUser;
7366             Dictionary<long, PostClass> curTabPosts;
7367
7368             if (_statuses.Tabs[_curTab.Text].IsInnerStorageTabType)
7369                 curTabPosts = curTabClass.Posts;
7370             else
7371                 curTabPosts = _statuses.Posts;
7372
7373             var inReplyToPosts = from tab in _statuses.Tabs.Values
7374                                  orderby tab != curTabClass
7375                                  from post in ((Dictionary<long, PostClass>)(tab.IsInnerStorageTabType ? tab.Posts : _statuses.Posts)).Values
7376                                  where post.StatusId == inReplyToId
7377                                  let index = tab.IndexOf(post.StatusId)
7378                                  where index != -1
7379                                  select new {Tab = tab, Index = index};
7380
7381             try
7382             {
7383                 var inReplyPost = inReplyToPosts.First();
7384                 inReplyToTabName = inReplyPost.Tab.TabName;
7385                 inReplyToIndex = inReplyPost.Index;
7386             }
7387             catch (InvalidOperationException)
7388             {
7389                 PostClass post = null;
7390                 string r = tw.GetStatusApi(false, _curPost.InReplyToStatusId.Value, ref post);
7391                 if (string.IsNullOrEmpty(r) && post != null)
7392                 {
7393                     post.IsRead = true;
7394                     _statuses.AddPost(post);
7395                     _statuses.DistributePosts();
7396                     //_statuses.SubmitUpdate(null, null, null, false);
7397                     this.RefreshTimeline(false);
7398                     try
7399                     {
7400                         var inReplyPost = inReplyToPosts.First();
7401                         inReplyToTabName = inReplyPost.Tab.TabName;
7402                         inReplyToIndex = inReplyPost.Index;
7403                     }
7404                     catch (InvalidOperationException)
7405                     {
7406                         OpenUriAsync("https://twitter.com/" + inReplyToUser + "/statuses/" + inReplyToId.ToString());
7407                         return;
7408                     }
7409                 }
7410                 else
7411                 {
7412                     this.StatusLabel.Text = r;
7413                     OpenUriAsync("https://twitter.com/" + inReplyToUser + "/statuses/" + inReplyToId.ToString());
7414                     return;
7415                 }
7416             }
7417
7418             TabPage tabPage = this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == inReplyToTabName; });
7419             DetailsListView listView = (DetailsListView)tabPage.Tag;
7420
7421             if (_curTab != tabPage)
7422             {
7423                 this.ListTab.SelectTab(tabPage);
7424             }
7425
7426             this.SelectListItem(listView, inReplyToIndex);
7427             listView.EnsureVisible(inReplyToIndex);
7428         }
7429
7430         private void GoBackInReplyToPostTree(bool parallel = false, bool isForward = true)
7431         {
7432             if (_curPost == null) return;
7433
7434             TabClass curTabClass = _statuses.Tabs[_curTab.Text];
7435             Dictionary<long, PostClass> curTabPosts = curTabClass.IsInnerStorageTabType ? curTabClass.Posts : _statuses.Posts;
7436
7437             if (parallel)
7438             {
7439                 if (_curPost.InReplyToStatusId != null)
7440                 {
7441                     var posts = from t in _statuses.Tabs
7442                                 from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
7443                                 where p.Value.StatusId != _curPost.StatusId && p.Value.InReplyToStatusId == _curPost.InReplyToStatusId
7444                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
7445                                 where indexOf > -1
7446                                 orderby isForward ? indexOf : indexOf * -1
7447                                 orderby t.Value != curTabClass
7448                                 select new {Tab = t.Value, Post = p.Value, Index = indexOf};
7449                     try
7450                     {
7451                         var postList = posts.ToList();
7452                         for (int i = postList.Count - 1; i >= 0; i--)
7453                         {
7454                             int index = i;
7455                             if (postList.FindIndex((pst) => { return pst.Post.StatusId == postList[index].Post.StatusId; }) != index)
7456                             {
7457                                 postList.RemoveAt(index);
7458                             }
7459                         }
7460                         var post = postList.FirstOrDefault((pst) => { return pst.Tab == curTabClass && isForward ? pst.Index > _curItemIndex : pst.Index < _curItemIndex; });
7461                         if (post == null) post = postList.FirstOrDefault((pst) => { return pst.Tab != curTabClass; });
7462                         if (post == null) post = postList.First();
7463                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
7464                         DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
7465                         SelectListItem(listView, post.Index);
7466                         listView.EnsureVisible(post.Index);
7467                     }
7468                     catch (InvalidOperationException)
7469                     {
7470                         return;
7471                     }
7472                 }
7473             }
7474             else
7475             {
7476                 if (replyChains == null || replyChains.Count < 1)
7477                 {
7478                     var posts = from t in _statuses.Tabs
7479                                 from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
7480                                 where p.Value.InReplyToStatusId == _curPost.StatusId
7481                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
7482                                 where indexOf > -1
7483                                 orderby indexOf
7484                                 orderby t.Value != curTabClass
7485                                 select new {Tab = t.Value, Index = indexOf};
7486                     try
7487                     {
7488                         var post = posts.First();
7489                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
7490                         DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
7491                         SelectListItem(listView, post.Index);
7492                         listView.EnsureVisible(post.Index);
7493                     }
7494                     catch (InvalidOperationException)
7495                     {
7496                         return;
7497                     }
7498                 }
7499                 else
7500                 {
7501                     ReplyChain chainHead = replyChains.Pop();
7502                     if (chainHead.InReplyToId == _curPost.StatusId)
7503                     {
7504                         int idx = _statuses.Tabs[chainHead.OriginalTab.Text].IndexOf(chainHead.OriginalId);
7505                         if (idx == -1)
7506                         {
7507                             replyChains = null;
7508                         }
7509                         else
7510                         {
7511                             try
7512                             {
7513                                 ListTab.SelectTab(chainHead.OriginalTab);
7514                             }
7515                             catch (Exception)
7516                             {
7517                                 replyChains = null;
7518                             }
7519                             SelectListItem(_curList, idx);
7520                             _curList.EnsureVisible(idx);
7521                         }
7522                     }
7523                     else
7524                     {
7525                         replyChains = null;
7526                         this.GoBackInReplyToPostTree(parallel);
7527                     }
7528                 }
7529             }
7530         }
7531
7532         private void GoBackSelectPostChain()
7533         {
7534             try
7535             {
7536                 this.selectPostChains.Pop();
7537                 Tuple<TabPage, PostClass> tabPostPair = this.selectPostChains.Pop();
7538                 if (!this.ListTab.TabPages.Contains(tabPostPair.Item1)) return;
7539                 this.ListTab.SelectedTab = tabPostPair.Item1;
7540                 if (tabPostPair.Item2 != null && this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId) > -1)
7541                 {
7542                     this.SelectListItem(this._curList, this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
7543                     this._curList.EnsureVisible(this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
7544                 }
7545             }
7546             catch (InvalidOperationException)
7547             {
7548             }
7549         }
7550
7551         private void PushSelectPostChain()
7552         {
7553             if (this.selectPostChains.Count == 0 || (this.selectPostChains.Peek().Item1.Text != this._curTab.Text || this._curPost != this.selectPostChains.Peek().Item2))
7554             {
7555                 this.selectPostChains.Push(Tuple.Create(this._curTab, _curPost));
7556             }
7557         }
7558
7559         private void TrimPostChain()
7560         {
7561             if (this.selectPostChains.Count < 2000) return;
7562             Stack<Tuple<TabPage, PostClass>> p = new Stack<Tuple<TabPage, PostClass>>();
7563             for (int i = 0; i < 2000; i++)
7564             {
7565                 p.Push(this.selectPostChains.Pop());
7566             }
7567             this.selectPostChains.Clear();
7568             for (int i = 0; i < 2000; i++)
7569             {
7570                 this.selectPostChains.Push(p.Pop());
7571             }
7572         }
7573
7574         private bool GoStatus(long statusId)
7575         {
7576             if (statusId == 0) return false;
7577             for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
7578             {
7579                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType != MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
7580                 {
7581                     int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
7582                     ListTab.SelectedIndex = tabidx;
7583                     ListTabSelect(ListTab.TabPages[tabidx]);
7584                     SelectListItem(_curList, idx);
7585                     _curList.EnsureVisible(idx);
7586                     return true;
7587                 }
7588             }
7589             return false;
7590         }
7591
7592         private bool GoDirectMessage(long statusId)
7593         {
7594             if (statusId == 0) return false;
7595             for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
7596             {
7597                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
7598                 {
7599                     int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
7600                     ListTab.SelectedIndex = tabidx;
7601                     ListTabSelect(ListTab.TabPages[tabidx]);
7602                     SelectListItem(_curList, idx);
7603                     _curList.EnsureVisible(idx);
7604                     return true;
7605                 }
7606             }
7607             return false;
7608         }
7609
7610         private void MyList_MouseClick(object sender, MouseEventArgs e)
7611         {
7612             _anchorFlag = false;
7613         }
7614
7615         private void StatusText_Enter(object sender, EventArgs e)
7616         {
7617             // フォーカスの戻り先を StatusText に設定
7618             this.Tag = StatusText;
7619             StatusText.BackColor = _clInputBackcolor;
7620         }
7621
7622         public Color InputBackColor
7623         {
7624             get { return _clInputBackcolor; }
7625             set { _clInputBackcolor = value; }
7626         }
7627
7628         private void StatusText_Leave(object sender, EventArgs e)
7629         {
7630             // フォーカスがメニューに遷移しないならばフォーカスはタブに移ることを期待
7631             if (ListTab.SelectedTab != null && MenuStrip1.Tag == null) this.Tag = ListTab.SelectedTab.Tag;
7632             StatusText.BackColor = Color.FromKnownColor(KnownColor.Window);
7633         }
7634
7635         private void StatusText_KeyDown(object sender, KeyEventArgs e)
7636         {
7637             ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
7638             if (State == ModifierState.NotFlags) return;
7639             if (CommonKeyDown(e.KeyCode, FocusedControl.StatusText, State))
7640             {
7641                 e.Handled = true;
7642                 e.SuppressKeyPress = true;
7643             }
7644
7645             this.StatusText_TextChanged(null, null);
7646         }
7647
7648         private void SaveConfigsAll(bool ifModified)
7649         {
7650             if (!ifModified)
7651             {
7652                 SaveConfigsCommon();
7653                 SaveConfigsLocal();
7654                 SaveConfigsTabs();
7655                 SaveConfigsAtId();
7656             }
7657             else
7658             {
7659                 if (_modifySettingCommon) SaveConfigsCommon();
7660                 if (_modifySettingLocal) SaveConfigsLocal();
7661                 if (_modifySettingAtId) SaveConfigsAtId();
7662             }
7663         }
7664
7665         private void SaveConfigsAtId()
7666         {
7667             if (_ignoreConfigSave || !SettingDialog.UseAtIdSupplement && AtIdSupl == null) return;
7668
7669             _modifySettingAtId = false;
7670             SettingAtIdList cfgAtId = new SettingAtIdList(AtIdSupl.GetItemList());
7671             cfgAtId.Save();
7672         }
7673
7674         private void SaveConfigsCommon()
7675         {
7676             if (_ignoreConfigSave) return;
7677
7678             _modifySettingCommon = false;
7679             lock (_syncObject)
7680             {
7681                 _cfgCommon.UserName = tw.Username;
7682                 _cfgCommon.UserId = tw.UserId;
7683                 _cfgCommon.Password = tw.Password;
7684                 _cfgCommon.Token = tw.AccessToken;
7685                 _cfgCommon.TokenSecret = tw.AccessTokenSecret;
7686                 _cfgCommon.UserAccounts = SettingDialog.UserAccounts;
7687                 _cfgCommon.UserstreamStartup = SettingDialog.UserstreamStartup;
7688                 _cfgCommon.UserstreamPeriod = SettingDialog.UserstreamPeriodInt;
7689                 _cfgCommon.TimelinePeriod = SettingDialog.TimelinePeriodInt;
7690                 _cfgCommon.ReplyPeriod = SettingDialog.ReplyPeriodInt;
7691                 _cfgCommon.DMPeriod = SettingDialog.DMPeriodInt;
7692                 _cfgCommon.PubSearchPeriod = SettingDialog.PubSearchPeriodInt;
7693                 _cfgCommon.ListsPeriod = SettingDialog.ListsPeriodInt;
7694                 _cfgCommon.UserTimelinePeriod = SettingDialog.UserTimelinePeriodInt;
7695                 _cfgCommon.Read = SettingDialog.Readed;
7696                 _cfgCommon.IconSize = SettingDialog.IconSz;
7697                 _cfgCommon.UnreadManage = SettingDialog.UnreadManage;
7698                 _cfgCommon.PlaySound = SettingDialog.PlaySound;
7699                 _cfgCommon.OneWayLove = SettingDialog.OneWayLove;
7700
7701                 _cfgCommon.NameBalloon = SettingDialog.NameBalloon;
7702                 _cfgCommon.PostCtrlEnter = SettingDialog.PostCtrlEnter;
7703                 _cfgCommon.PostShiftEnter = SettingDialog.PostShiftEnter;
7704                 _cfgCommon.CountApi = SettingDialog.CountApi;
7705                 _cfgCommon.CountApiReply = SettingDialog.CountApiReply;
7706                 _cfgCommon.PostAndGet = SettingDialog.PostAndGet;
7707                 _cfgCommon.DispUsername = SettingDialog.DispUsername;
7708                 _cfgCommon.MinimizeToTray = SettingDialog.MinimizeToTray;
7709                 _cfgCommon.CloseToExit = SettingDialog.CloseToExit;
7710                 _cfgCommon.DispLatestPost = SettingDialog.DispLatestPost;
7711                 _cfgCommon.SortOrderLock = SettingDialog.SortOrderLock;
7712                 _cfgCommon.ViewTabBottom = SettingDialog.ViewTabBottom;
7713                 _cfgCommon.TinyUrlResolve = SettingDialog.TinyUrlResolve;
7714                 _cfgCommon.StartupVersion = SettingDialog.StartupVersion;
7715                 _cfgCommon.StartupFollowers = SettingDialog.StartupFollowers;
7716                 _cfgCommon.RestrictFavCheck = SettingDialog.RestrictFavCheck;
7717                 _cfgCommon.AlwaysTop = SettingDialog.AlwaysTop;
7718                 _cfgCommon.UrlConvertAuto = SettingDialog.UrlConvertAuto;
7719                 _cfgCommon.UseUnreadStyle = SettingDialog.UseUnreadStyle;
7720                 _cfgCommon.DateTimeFormat = SettingDialog.DateTimeFormat;
7721                 _cfgCommon.DefaultTimeOut = SettingDialog.DefaultTimeOut;
7722                 _cfgCommon.RetweetNoConfirm = SettingDialog.RetweetNoConfirm;
7723                 _cfgCommon.LimitBalloon = SettingDialog.LimitBalloon;
7724                 _cfgCommon.EventNotifyEnabled = SettingDialog.EventNotifyEnabled;
7725                 _cfgCommon.EventNotifyFlag = SettingDialog.EventNotifyFlag;
7726                 _cfgCommon.IsMyEventNotifyFlag = SettingDialog.IsMyEventNotifyFlag;
7727                 _cfgCommon.ForceEventNotify = SettingDialog.ForceEventNotify;
7728                 _cfgCommon.FavEventUnread = SettingDialog.FavEventUnread;
7729                 _cfgCommon.TranslateLanguage = SettingDialog.TranslateLanguage;
7730                 _cfgCommon.EventSoundFile = SettingDialog.EventSoundFile;
7731                 _cfgCommon.AutoShortUrlFirst = SettingDialog.AutoShortUrlFirst;
7732                 _cfgCommon.TabIconDisp = SettingDialog.TabIconDisp;
7733                 _cfgCommon.ReplyIconState = SettingDialog.ReplyIconState;
7734                 _cfgCommon.ReadOwnPost = SettingDialog.ReadOwnPost;
7735                 _cfgCommon.GetFav = SettingDialog.GetFav;
7736                 _cfgCommon.IsMonospace = SettingDialog.IsMonospace;
7737                 if (IdeographicSpaceToSpaceToolStripMenuItem != null &&
7738                    IdeographicSpaceToSpaceToolStripMenuItem.IsDisposed == false)
7739                 {
7740                     _cfgCommon.WideSpaceConvert = this.IdeographicSpaceToSpaceToolStripMenuItem.Checked;
7741                 }
7742                 _cfgCommon.ReadOldPosts = SettingDialog.ReadOldPosts;
7743                 _cfgCommon.BilyUser = SettingDialog.BitlyUser;
7744                 _cfgCommon.BitlyPwd = SettingDialog.BitlyPwd;
7745                 _cfgCommon.ShowGrid = SettingDialog.ShowGrid;
7746                 _cfgCommon.UseAtIdSupplement = SettingDialog.UseAtIdSupplement;
7747                 _cfgCommon.UseHashSupplement = SettingDialog.UseHashSupplement;
7748                 _cfgCommon.PreviewEnable = SettingDialog.PreviewEnable;
7749                 _cfgCommon.Language = SettingDialog.Language;
7750
7751                 _cfgCommon.SortOrder = (int)_statuses.SortOrder;
7752                 switch (_statuses.SortMode)
7753                 {
7754                     case IdComparerClass.ComparerMode.Nickname:  //ニックネーム
7755                         _cfgCommon.SortColumn = 1;
7756                         break;
7757                     case IdComparerClass.ComparerMode.Data:  //本文
7758                         _cfgCommon.SortColumn = 2;
7759                         break;
7760                     case IdComparerClass.ComparerMode.Id:  //時刻=発言Id
7761                         _cfgCommon.SortColumn = 3;
7762                         break;
7763                     case IdComparerClass.ComparerMode.Name:  //名前
7764                         _cfgCommon.SortColumn = 4;
7765                         break;
7766                     case IdComparerClass.ComparerMode.Source:  //Source
7767                         _cfgCommon.SortColumn = 7;
7768                         break;
7769                 }
7770
7771                 _cfgCommon.Nicoms = SettingDialog.Nicoms;
7772                 _cfgCommon.HashTags = HashMgr.HashHistories;
7773                 if (HashMgr.IsPermanent)
7774                 {
7775                     _cfgCommon.HashSelected = HashMgr.UseHash;
7776                 }
7777                 else
7778                 {
7779                     _cfgCommon.HashSelected = "";
7780                 }
7781                 _cfgCommon.HashIsHead = HashMgr.IsHead;
7782                 _cfgCommon.HashIsPermanent = HashMgr.IsPermanent;
7783                 _cfgCommon.HashIsNotAddToAtReply = HashMgr.IsNotAddToAtReply;
7784                 _cfgCommon.TwitterUrl = SettingDialog.TwitterApiUrl;
7785                 _cfgCommon.HotkeyEnabled = SettingDialog.HotkeyEnabled;
7786                 _cfgCommon.HotkeyModifier = SettingDialog.HotkeyMod;
7787                 _cfgCommon.HotkeyKey = SettingDialog.HotkeyKey;
7788                 _cfgCommon.HotkeyValue = SettingDialog.HotkeyValue;
7789                 _cfgCommon.BlinkNewMentions = SettingDialog.BlinkNewMentions;
7790                 if (ToolStripFocusLockMenuItem != null &&
7791                         ToolStripFocusLockMenuItem.IsDisposed == false)
7792                 {
7793                     _cfgCommon.FocusLockToStatusText = this.ToolStripFocusLockMenuItem.Checked;
7794                 }
7795                 _cfgCommon.UseAdditionalCount = SettingDialog.UseAdditionalCount;
7796                 _cfgCommon.MoreCountApi = SettingDialog.MoreCountApi;
7797                 _cfgCommon.FirstCountApi = SettingDialog.FirstCountApi;
7798                 _cfgCommon.SearchCountApi = SettingDialog.SearchCountApi;
7799                 _cfgCommon.FavoritesCountApi = SettingDialog.FavoritesCountApi;
7800                 _cfgCommon.UserTimelineCountApi = SettingDialog.UserTimelineCountApi;
7801                 _cfgCommon.TrackWord = tw.TrackWord;
7802                 _cfgCommon.AllAtReply = tw.AllAtReply;
7803                 _cfgCommon.OpenUserTimeline = SettingDialog.OpenUserTimeline;
7804                 _cfgCommon.ListCountApi = SettingDialog.ListCountApi;
7805                 _cfgCommon.UseImageService = ImageServiceCombo.SelectedIndex;
7806                 _cfgCommon.UseImageServiceName = this.ImageService;
7807                 _cfgCommon.ListDoubleClickAction = SettingDialog.ListDoubleClickAction;
7808                 _cfgCommon.UserAppointUrl = SettingDialog.UserAppointUrl;
7809                 _cfgCommon.HideDuplicatedRetweets = SettingDialog.HideDuplicatedRetweets;
7810                 _cfgCommon.IsPreviewFoursquare = SettingDialog.IsPreviewFoursquare;
7811                 _cfgCommon.MapThumbnailProvider = SettingDialog.MapThumbnailProvider;
7812                 _cfgCommon.MapThumbnailHeight = SettingDialog.MapThumbnailHeight;
7813                 _cfgCommon.MapThumbnailWidth = SettingDialog.MapThumbnailWidth;
7814                 _cfgCommon.MapThumbnailZoom = SettingDialog.MapThumbnailZoom;
7815                 _cfgCommon.IsListsIncludeRts = SettingDialog.IsListStatusesIncludeRts;
7816                 _cfgCommon.TabMouseLock = SettingDialog.TabMouseLock;
7817                 _cfgCommon.IsRemoveSameEvent = SettingDialog.IsRemoveSameEvent;
7818                 _cfgCommon.IsUseNotifyGrowl = SettingDialog.IsNotifyUseGrowl;
7819
7820                 _cfgCommon.Save();
7821             }
7822         }
7823
7824         private void SaveConfigsLocal()
7825         {
7826             if (_ignoreConfigSave) return;
7827             lock (_syncObject)
7828             {
7829                 _modifySettingLocal = false;
7830                 _cfgLocal.FormSize = _mySize;
7831                 _cfgLocal.FormLocation = _myLoc;
7832                 _cfgLocal.SplitterDistance = _mySpDis;
7833                 _cfgLocal.PreviewDistance = _mySpDis3;
7834                 _cfgLocal.StatusMultiline = StatusText.Multiline;
7835                 _cfgLocal.StatusTextHeight = _mySpDis2;
7836                 _cfgLocal.AdSplitterDistance = _myAdSpDis;
7837                 _cfgLocal.StatusText = SettingDialog.Status;
7838
7839                 _cfgLocal.FontUnread = _fntUnread;
7840                 _cfgLocal.ColorUnread = _clUnread;
7841                 _cfgLocal.FontRead = _fntReaded;
7842                 _cfgLocal.ColorRead = _clReaded;
7843                 _cfgLocal.FontDetail = _fntDetail;
7844                 _cfgLocal.ColorDetail = _clDetail;
7845                 _cfgLocal.ColorDetailBackcolor = _clDetailBackcolor;
7846                 _cfgLocal.ColorDetailLink = _clDetailLink;
7847                 _cfgLocal.ColorFav = _clFav;
7848                 _cfgLocal.ColorOWL = _clOWL;
7849                 _cfgLocal.ColorRetweet = _clRetweet;
7850                 _cfgLocal.ColorSelf = _clSelf;
7851                 _cfgLocal.ColorAtSelf = _clAtSelf;
7852                 _cfgLocal.ColorTarget = _clTarget;
7853                 _cfgLocal.ColorAtTarget = _clAtTarget;
7854                 _cfgLocal.ColorAtFromTarget = _clAtFromTarget;
7855                 _cfgLocal.ColorAtTo = _clAtTo;
7856                 _cfgLocal.ColorListBackcolor = _clListBackcolor;
7857                 _cfgLocal.ColorInputBackcolor = _clInputBackcolor;
7858                 _cfgLocal.ColorInputFont = _clInputFont;
7859                 _cfgLocal.FontInputFont = _fntInputFont;
7860
7861                 _cfgLocal.BrowserPath = SettingDialog.BrowserPath;
7862                 _cfgLocal.UseRecommendStatus = SettingDialog.UseRecommendStatus;
7863                 _cfgLocal.ProxyType = SettingDialog.SelectedProxyType;
7864                 _cfgLocal.ProxyAddress = SettingDialog.ProxyAddress;
7865                 _cfgLocal.ProxyPort = SettingDialog.ProxyPort;
7866                 _cfgLocal.ProxyUser = SettingDialog.ProxyUser;
7867                 _cfgLocal.ProxyPassword = SettingDialog.ProxyPassword;
7868                 if (_ignoreConfigSave) return;
7869                 _cfgLocal.Save();
7870             }
7871         }
7872
7873         private void SaveConfigsTabs()
7874         {
7875             SettingTabs tabSetting = new SettingTabs();
7876             for (int i = 0; i < ListTab.TabPages.Count; i++)
7877             {
7878                 if (_statuses.Tabs[ListTab.TabPages[i].Text].TabType != MyCommon.TabUsageType.Related) tabSetting.Tabs.Add(_statuses.Tabs[ListTab.TabPages[i].Text]);
7879             }
7880             tabSetting.Save();
7881         }
7882
7883         private /* async */ void OpenURLFileMenuItem_Click(object sender, EventArgs e)
7884         {
7885             string inputText;
7886             var ret = InputDialog.Show(this, Properties.Resources.OpenURL_InputText, Properties.Resources.OpenURL_Caption, out inputText);
7887             if (ret != DialogResult.OK)
7888                 return;
7889
7890             var match = Twitter.StatusUrlRegex.Match(inputText);
7891             if (!match.Success)
7892             {
7893                 MessageBox.Show(this, Properties.Resources.OpenURL_InvalidFormat,
7894                     Properties.Resources.OpenURL_Caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
7895                 return;
7896             }
7897
7898             var statusId = long.Parse(match.Groups["StatusId"].Value);
7899             var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
7900
7901             Task.Factory.StartNew(() =>
7902                 {
7903                     var post = this._statuses[statusId];
7904                     if (post == null)
7905                     {
7906                         var err = this.tw.GetStatusApi(false, statusId, ref post);
7907                         if (!string.IsNullOrEmpty(err))
7908                             throw new WebApiException(err);
7909                     }
7910                     return post;
7911                 }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
7912                 .ContinueWith(t =>
7913                 {
7914                     if (t.IsFaulted)
7915                     {
7916                         t.Exception.Flatten().Handle(x => x is WebApiException);
7917
7918                         var message = t.Exception.InnerException.Message;
7919                         MessageBox.Show(this, string.Format(Properties.Resources.OpenURL_LoadFailed, message),
7920                             Properties.Resources.OpenURL_Caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
7921
7922                         return;
7923                     }
7924                     try
7925                     {
7926                         this.OpenRelatedTab(t.Result);
7927                     }
7928                     catch (TabException ex)
7929                     {
7930                         MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
7931                     }
7932                 }, uiScheduler);
7933         }
7934
7935         private void SaveLogMenuItem_Click(object sender, EventArgs e)
7936         {
7937             DialogResult rslt = MessageBox.Show(string.Format(Properties.Resources.SaveLogMenuItem_ClickText1, Environment.NewLine),
7938                     Properties.Resources.SaveLogMenuItem_ClickText2,
7939                     MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
7940             if (rslt == DialogResult.Cancel) return;
7941
7942             SaveFileDialog1.FileName = MyCommon.GetAssemblyName() + "Posts" + DateTime.Now.ToString("yyMMdd-HHmmss") + ".tsv";
7943             SaveFileDialog1.InitialDirectory = Application.ExecutablePath;
7944             SaveFileDialog1.Filter = Properties.Resources.SaveLogMenuItem_ClickText3;
7945             SaveFileDialog1.FilterIndex = 0;
7946             SaveFileDialog1.Title = Properties.Resources.SaveLogMenuItem_ClickText4;
7947             SaveFileDialog1.RestoreDirectory = true;
7948
7949             if (SaveFileDialog1.ShowDialog() == DialogResult.OK)
7950             {
7951                 if (!SaveFileDialog1.ValidateNames) return;
7952                 using (StreamWriter sw = new StreamWriter(SaveFileDialog1.FileName, false, Encoding.UTF8))
7953                 {
7954                     if (rslt == DialogResult.Yes)
7955                     {
7956                         //All
7957                         for (int idx = 0; idx < _curList.VirtualListSize; idx++)
7958                         {
7959                             PostClass post = _statuses[_curTab.Text, idx];
7960                             string protect = "";
7961                             if (post.IsProtect) protect = "Protect";
7962                             sw.WriteLine(post.Nickname + "\t" +
7963                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7964                                      post.CreatedAt.ToString() + "\t" +
7965                                      post.ScreenName + "\t" +
7966                                      post.StatusId.ToString() + "\t" +
7967                                      post.ImageUrl + "\t" +
7968                                      "\"" + post.Text.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7969                                      protect);
7970                         }
7971                     }
7972                     else
7973                     {
7974                         foreach (int idx in _curList.SelectedIndices)
7975                         {
7976                             PostClass post = _statuses[_curTab.Text, idx];
7977                             string protect = "";
7978                             if (post.IsProtect) protect = "Protect";
7979                             sw.WriteLine(post.Nickname + "\t" +
7980                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7981                                      post.CreatedAt.ToString() + "\t" +
7982                                      post.ScreenName + "\t" +
7983                                      post.StatusId.ToString() + "\t" +
7984                                      post.ImageUrl + "\t" +
7985                                      "\"" + post.Text.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7986                                      protect);
7987                         }
7988                     }
7989                 }
7990             }
7991             this.TopMost = SettingDialog.AlwaysTop;
7992         }
7993
7994         private void PostBrowser_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
7995         {
7996             ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
7997             if (State == ModifierState.NotFlags) return;
7998             bool KeyRes = CommonKeyDown(e.KeyCode, FocusedControl.PostBrowser, State);
7999             if (KeyRes)
8000             {
8001                 e.IsInputKey = true;
8002             }
8003         }
8004         public bool TabRename(ref string tabName)
8005         {
8006             //タブ名変更
8007             string newTabText = null;
8008             using (InputTabName inputName = new InputTabName())
8009             {
8010                 inputName.TabName = tabName;
8011                 inputName.ShowDialog();
8012                 if (inputName.DialogResult == DialogResult.Cancel) return false;
8013                 newTabText = inputName.TabName;
8014             }
8015             this.TopMost = SettingDialog.AlwaysTop;
8016             if (!string.IsNullOrEmpty(newTabText))
8017             {
8018                 //新タブ名存在チェック
8019                 for (int i = 0; i < ListTab.TabCount; i++)
8020                 {
8021                     if (ListTab.TabPages[i].Text == newTabText)
8022                     {
8023                         string tmp = string.Format(Properties.Resources.Tabs_DoubleClickText1, newTabText);
8024                         MessageBox.Show(tmp, Properties.Resources.Tabs_DoubleClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
8025                         return false;
8026                     }
8027                 }
8028                 //タブ名のリスト作り直し(デフォルトタブ以外は再作成)
8029                 for (int i = 0; i < ListTab.TabCount; i++)
8030                 {
8031                     if (ListTab.TabPages[i].Text == tabName)
8032                     {
8033                         ListTab.TabPages[i].Text = newTabText;
8034                     }
8035                 }
8036                 _statuses.RenameTab(tabName, newTabText);
8037
8038                 for (int i = 0; i < ListTab.TabCount; i++)
8039                 {
8040                     if (_statuses.IsDistributableTab(ListTab.TabPages[i].Text))
8041                     {
8042                         if (ListTab.TabPages[i].Text == tabName)
8043                         {
8044                             ListTab.TabPages[i].Text = newTabText;
8045                         }
8046                     }
8047                 }
8048                 SaveConfigsCommon();
8049                 SaveConfigsTabs();
8050                 _rclickTabName = newTabText;
8051                 tabName = newTabText;
8052                 return true;
8053             }
8054             else
8055             {
8056                 return false;
8057             }
8058         }
8059
8060         private void ListTab_MouseClick(object sender, MouseEventArgs e)
8061         {
8062             if (e.Button == MouseButtons.Middle)
8063             {
8064                 for (int i = 0; i < this.ListTab.TabPages.Count; i++)
8065                 {
8066                     if (this.ListTab.GetTabRect(i).Contains(e.Location))
8067                     {
8068                         this.RemoveSpecifiedTab(this.ListTab.TabPages[i].Text, true);
8069                         this.SaveConfigsTabs();
8070                         break;
8071                     }
8072                 }
8073             }
8074         }
8075
8076         private void ListTab_DoubleClick(object sender, MouseEventArgs e)
8077         {
8078             string tn = ListTab.SelectedTab.Text;
8079             TabRename(ref tn);
8080         }
8081
8082         private void ListTab_MouseDown(object sender, MouseEventArgs e)
8083         {
8084             if (SettingDialog.TabMouseLock) return;
8085             Point cpos = new Point(e.X, e.Y);
8086             if (e.Button == MouseButtons.Left)
8087             {
8088                 for (int i = 0; i < ListTab.TabPages.Count; i++)
8089                 {
8090                     if (this.ListTab.GetTabRect(i).Contains(e.Location))
8091                     {
8092                         _tabDrag = true;
8093                         _tabMouseDownPoint = e.Location;
8094                         break;
8095                     }
8096                 }
8097             }
8098             else
8099             {
8100                 _tabDrag = false;
8101             }
8102         }
8103
8104         private void ListTab_DragEnter(object sender, DragEventArgs e)
8105         {
8106             if (e.Data.GetDataPresent(typeof(TabPage)))
8107                 e.Effect = DragDropEffects.Move;
8108             else
8109                 e.Effect = DragDropEffects.None;
8110         }
8111
8112         private void ListTab_DragDrop(object sender, DragEventArgs e)
8113         {
8114             if (!e.Data.GetDataPresent(typeof(TabPage))) return;
8115
8116             _tabDrag = false;
8117             string tn = "";
8118             bool bef = false;
8119             Point cpos = new Point(e.X, e.Y);
8120             Point spos = ListTab.PointToClient(cpos);
8121             int i;
8122             for (i = 0; i < ListTab.TabPages.Count; i++)
8123             {
8124                 Rectangle rect = ListTab.GetTabRect(i);
8125                 if (rect.Left <= spos.X && spos.X <= rect.Right &&
8126                     rect.Top <= spos.Y && spos.Y <= rect.Bottom)
8127                 {
8128                     tn = ListTab.TabPages[i].Text;
8129                     if (spos.X <= (rect.Left + rect.Right) / 2)
8130                         bef = true;
8131                     else
8132                         bef = false;
8133
8134                     break;
8135                 }
8136             }
8137
8138             //タブのないところにドロップ->最後尾へ移動
8139             if (string.IsNullOrEmpty(tn))
8140             {
8141                 tn = ListTab.TabPages[ListTab.TabPages.Count - 1].Text;
8142                 bef = false;
8143                 i = ListTab.TabPages.Count - 1;
8144             }
8145
8146             TabPage tp = (TabPage)e.Data.GetData(typeof(TabPage));
8147             if (tp.Text == tn) return;
8148
8149             ReOrderTab(tp.Text, tn, bef);
8150         }
8151
8152         public void ReOrderTab(string targetTabText, string baseTabText, bool isBeforeBaseTab)
8153         {
8154             int baseIndex = 0;
8155             for (baseIndex = 0; baseIndex < ListTab.TabPages.Count; baseIndex++)
8156             {
8157                 if (ListTab.TabPages[baseIndex].Text == baseTabText) break;
8158             }
8159
8160             ListTab.SuspendLayout();
8161
8162             TabPage mTp = null;
8163             for (int j = 0; j < ListTab.TabPages.Count; j++)
8164             {
8165                 if (ListTab.TabPages[j].Text == targetTabText)
8166                 {
8167                     mTp = ListTab.TabPages[j];
8168                     ListTab.TabPages.Remove(mTp);
8169                     if (j < baseIndex) baseIndex -= 1;
8170                     break;
8171                 }
8172             }
8173             if (isBeforeBaseTab)
8174                 ListTab.TabPages.Insert(baseIndex, mTp);
8175             else
8176                 ListTab.TabPages.Insert(baseIndex + 1, mTp);
8177
8178             ListTab.ResumeLayout();
8179
8180             SaveConfigsTabs();
8181         }
8182
8183         private void MakeReplyOrDirectStatus(bool isAuto = true, bool isReply = true, bool isAll = false)
8184         {
8185             //isAuto:true=先頭に挿入、false=カーソル位置に挿入
8186             //isReply:true=@,false=DM
8187             if (!StatusText.Enabled) return;
8188             if (_curList == null) return;
8189             if (_curTab == null) return;
8190             if (!this.ExistCurrentPost) return;
8191
8192             // 複数あてリプライはReplyではなく通常ポスト
8193             //↑仕様変更で全部リプライ扱いでOK(先頭ドット付加しない)
8194             //090403暫定でドットを付加しないようにだけ修正。単独と複数の処理は統合できると思われる。
8195             //090513 all @ replies 廃止の仕様変更によりドット付加に戻し(syo68k)
8196
8197             if (_curList.SelectedIndices.Count > 0)
8198             {
8199                 // アイテムが1件以上選択されている
8200                 if (_curList.SelectedIndices.Count == 1 && !isAll && this.ExistCurrentPost)
8201                 {
8202                     // 単独ユーザー宛リプライまたはDM
8203                     if ((_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && isAuto) || (!isAuto && !isReply))
8204                     {
8205                         // ダイレクトメッセージ
8206                         StatusText.Text = "D " + _curPost.ScreenName + " " + StatusText.Text;
8207                         StatusText.SelectionStart = StatusText.Text.Length;
8208                         StatusText.Focus();
8209                         _reply_to_id = null;
8210                         _reply_to_name = null;
8211                         return;
8212                     }
8213                     if (string.IsNullOrEmpty(StatusText.Text))
8214                     {
8215                         //空の場合
8216
8217                         // ステータステキストが入力されていない場合先頭に@ユーザー名を追加する
8218                         StatusText.Text = "@" + _curPost.ScreenName + " ";
8219                         if (_curPost.RetweetedId != null)
8220                         {
8221                             _reply_to_id = _curPost.RetweetedId.Value;
8222                         }
8223                         else
8224                         {
8225                             _reply_to_id = _curPost.StatusId;
8226                         }
8227                         _reply_to_name = _curPost.ScreenName;
8228                     }
8229                     else
8230                     {
8231                         //何か入力済の場合
8232
8233                         if (isAuto)
8234                         {
8235                             //1件選んでEnter or DoubleClick
8236                             if (StatusText.Text.Contains("@" + _curPost.ScreenName + " "))
8237                             {
8238                                 if (_reply_to_id != null && _reply_to_name == _curPost.ScreenName)
8239                                 {
8240                                     //返信先書き換え
8241                                     if (_curPost.RetweetedId != null)
8242                                     {
8243                                         _reply_to_id = _curPost.RetweetedId.Value;
8244                                     }
8245                                     else
8246                                     {
8247                                         _reply_to_id = _curPost.StatusId;
8248                                     }
8249                                     _reply_to_name = _curPost.ScreenName;
8250                                 }
8251                                 return;
8252                             }
8253                             if (!StatusText.Text.StartsWith("@"))
8254                             {
8255                                 //文頭@以外
8256                                 if (StatusText.Text.StartsWith(". "))
8257                                 {
8258                                     // 複数リプライ
8259                                     StatusText.Text = StatusText.Text.Insert(2, "@" + _curPost.ScreenName + " ");
8260                                     _reply_to_id = null;
8261                                     _reply_to_name = null;
8262                                 }
8263                                 else
8264                                 {
8265                                     // 単独リプライ
8266                                     StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
8267                                     if (_curPost.RetweetedId != null)
8268                                     {
8269                                         _reply_to_id = _curPost.RetweetedId.Value;
8270                                     }
8271                                     else
8272                                     {
8273                                         _reply_to_id = _curPost.StatusId;
8274                                     }
8275                                     _reply_to_name = _curPost.ScreenName;
8276                                 }
8277                             }
8278                             else
8279                             {
8280                                 //文頭@
8281                                 // 複数リプライ
8282                                 StatusText.Text = ". @" + _curPost.ScreenName + " " + StatusText.Text;
8283                                 //StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
8284                                 _reply_to_id = null;
8285                                 _reply_to_name = null;
8286                             }
8287                         }
8288                         else
8289                         {
8290                             //1件選んでCtrl-Rの場合(返信先操作せず)
8291                             int sidx = StatusText.SelectionStart;
8292                             string id = "@" + _curPost.ScreenName + " ";
8293                             if (sidx > 0)
8294                             {
8295                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8296                                 {
8297                                     id = " " + id;
8298                                 }
8299                             }
8300                             StatusText.Text = StatusText.Text.Insert(sidx, id);
8301                             sidx += id.Length;
8302                             //if (StatusText.Text.StartsWith("@"))
8303                             //{
8304                             //    //複数リプライ
8305                             //    StatusText.Text = ". " + StatusText.Text.Insert(sidx, " @" + _curPost.ScreenName + " ");
8306                             //    sidx += 5 + _curPost.ScreenName.Length;
8307                             //}
8308                             //else
8309                             //{
8310                             //    // 複数リプライ
8311                             //    StatusText.Text = StatusText.Text.Insert(sidx, " @" + _curPost.ScreenName + " ");
8312                             //    sidx += 3 + _curPost.ScreenName.Length;
8313                             //}
8314                             StatusText.SelectionStart = sidx;
8315                             StatusText.Focus();
8316                             //_reply_to_id = 0;
8317                             //_reply_to_name = null;
8318                             return;
8319                         }
8320                     }
8321                 }
8322                 else
8323                 {
8324                     // 複数リプライ
8325                     if (!isAuto && !isReply) return;
8326
8327                     //C-S-rか、複数の宛先を選択中にEnter/DoubleClick/C-r/C-S-r
8328
8329                     if (isAuto)
8330                     {
8331                         //Enter or DoubleClick
8332
8333                         string sTxt = StatusText.Text;
8334                         if (!sTxt.StartsWith(". "))
8335                         {
8336                             sTxt = ". " + sTxt;
8337                             _reply_to_id = null;
8338                             _reply_to_name = null;
8339                         }
8340                         for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
8341                         {
8342                             PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[cnt]];
8343                             if (!sTxt.Contains("@" + post.ScreenName + " "))
8344                             {
8345                                 sTxt = sTxt.Insert(2, "@" + post.ScreenName + " ");
8346                                 //sTxt = "@" + post.ScreenName + " " + sTxt;
8347                             }
8348                         }
8349                         StatusText.Text = sTxt;
8350                     }
8351                     else
8352                     {
8353                         //C-S-r or C-r
8354                         if (_curList.SelectedIndices.Count > 1)
8355                         {
8356                             //複数ポスト選択
8357
8358                             string ids = "";
8359                             int sidx = StatusText.SelectionStart;
8360                             for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
8361                             {
8362                                 PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[cnt]];
8363                                 if (!ids.Contains("@" + post.ScreenName + " ") &&
8364                                     !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8365                                 {
8366                                     ids += "@" + post.ScreenName + " ";
8367                                 }
8368                                 if (isAll)
8369                                 {
8370                                     foreach (string nm in post.ReplyToList)
8371                                     {
8372                                         if (!ids.Contains("@" + nm + " ") &&
8373                                             !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8374                                         {
8375                                             Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
8376                                             if (m.Success)
8377                                                 ids += "@" + m.Result("${id}") + " ";
8378                                             else
8379                                                 ids += "@" + nm + " ";
8380                                         }
8381                                     }
8382                                 }
8383                             }
8384                             if (ids.Length == 0) return;
8385                             if (!StatusText.Text.StartsWith(". "))
8386                             {
8387                                 StatusText.Text = ". " + StatusText.Text;
8388                                 sidx += 2;
8389                                 _reply_to_id = null;
8390                                 _reply_to_name = null;
8391                             }
8392                             if (sidx > 0)
8393                             {
8394                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8395                                 {
8396                                     ids = " " + ids;
8397                                 }
8398                             }
8399                             StatusText.Text = StatusText.Text.Insert(sidx, ids);
8400                             sidx += ids.Length;
8401                             //if (StatusText.Text.StartsWith("@"))
8402                             //{
8403                             //    StatusText.Text = ". " + StatusText.Text.Insert(sidx, ids);
8404                             //    sidx += 2 + ids.Length;
8405                             //}
8406                             //else
8407                             //{
8408                             //    StatusText.Text = StatusText.Text.Insert(sidx, ids);
8409                             //    sidx += 1 + ids.Length;
8410                             //}
8411                             StatusText.SelectionStart = sidx;
8412                             StatusText.Focus();
8413                             return;
8414                         }
8415                         else
8416                         {
8417                             //1件のみ選択のC-S-r(返信元付加する可能性あり)
8418
8419                             string ids = "";
8420                             int sidx = StatusText.SelectionStart;
8421                             PostClass post = _curPost;
8422                             if (!ids.Contains("@" + post.ScreenName + " ") &&
8423                                 !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8424                             {
8425                                 ids += "@" + post.ScreenName + " ";
8426                             }
8427                             foreach (string nm in post.ReplyToList)
8428                             {
8429                                 if (!ids.Contains("@" + nm + " ") &&
8430                                     !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8431                                 {
8432                                     Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
8433                                     if (m.Success)
8434                                         ids += "@" + m.Result("${id}") + " ";
8435                                     else
8436                                         ids += "@" + nm + " ";
8437                                 }
8438                             }
8439                             if (!string.IsNullOrEmpty(post.RetweetedBy))
8440                             {
8441                                 if (!ids.Contains("@" + post.RetweetedBy + " ") &&
8442                                    !post.RetweetedBy.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8443                                 {
8444                                     ids += "@" + post.RetweetedBy + " ";
8445                                 }
8446                             }
8447                             if (ids.Length == 0) return;
8448                             if (string.IsNullOrEmpty(StatusText.Text))
8449                             {
8450                                 //未入力の場合のみ返信先付加
8451                                 StatusText.Text = ids;
8452                                 StatusText.SelectionStart = ids.Length;
8453                                 StatusText.Focus();
8454                                 if (post.RetweetedId != null)
8455                                 {
8456                                     _reply_to_id = post.RetweetedId.Value;
8457                                 }
8458                                 else
8459                                 {
8460                                     _reply_to_id = post.StatusId;
8461                                 }
8462                                 _reply_to_name = post.ScreenName;
8463                                 return;
8464                             }
8465
8466                             if (sidx > 0)
8467                             {
8468                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8469                                 {
8470                                     ids = " " + ids;
8471                                 }
8472                             }
8473                             StatusText.Text = StatusText.Text.Insert(sidx, ids);
8474                             sidx += ids.Length;
8475                             StatusText.SelectionStart = sidx;
8476                             StatusText.Focus();
8477                             return;
8478                         }
8479                     }
8480                 }
8481                 StatusText.SelectionStart = StatusText.Text.Length;
8482                 StatusText.Focus();
8483             }
8484         }
8485
8486         private void ListTab_MouseUp(object sender, MouseEventArgs e)
8487         {
8488             _tabDrag = false;
8489         }
8490
8491         private static int iconCnt = 0;
8492         private static int blinkCnt = 0;
8493         private static bool blink = false;
8494         private static bool idle = false;
8495
8496         private void RefreshTasktrayIcon(bool forceRefresh)
8497         {
8498             if (_colorize) Colorize();
8499             if (!TimerRefreshIcon.Enabled) return;
8500             //Static usCheckCnt As int = 0
8501
8502             //Static iconDlListTopItem As ListViewItem = null
8503
8504             if (forceRefresh) idle = false;
8505
8506             //if (((ListView)ListTab.SelectedTab.Tag).TopItem == iconDlListTopItem)
8507             //    ((ImageDictionary)this.TIconDic).PauseGetImage = false;
8508             //else
8509             //    ((ImageDictionary)this.TIconDic).PauseGetImage = true;
8510             //
8511             //iconDlListTopItem = ((ListView)ListTab.SelectedTab.Tag).TopItem;
8512
8513             iconCnt += 1;
8514             blinkCnt += 1;
8515             //usCheckCnt += 1;
8516
8517             //if (usCheckCnt > 300)    //1min
8518             //{
8519             //    usCheckCnt = 0;
8520             //    if (!this.IsReceivedUserStream)
8521             //    {
8522             //        TraceOut("ReconnectUserStream");
8523             //        tw.ReconnectUserStream();
8524             //    }
8525             //}
8526
8527             bool busy = false;
8528             foreach (BackgroundWorker bw in this._bw)
8529             {
8530                 if (bw != null && bw.IsBusy)
8531                 {
8532                     busy = true;
8533                     break;
8534                 }
8535             }
8536
8537             if (iconCnt > 3)
8538             {
8539                 iconCnt = 0;
8540             }
8541             if (blinkCnt > 10)
8542             {
8543                 blinkCnt = 0;
8544                 //未保存の変更を保存
8545                 SaveConfigsAll(true);
8546             }
8547
8548             if (busy)
8549             {
8550                 NotifyIcon1.Icon = NIconRefresh[iconCnt];
8551                 idle = false;
8552                 _myStatusError = false;
8553                 return;
8554             }
8555
8556             TabClass tb = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
8557             if (SettingDialog.ReplyIconState != MyCommon.REPLY_ICONSTATE.None && tb != null && tb.UnreadCount > 0)
8558             {
8559                 if (blinkCnt > 0) return;
8560                 blink = !blink;
8561                 if (blink || SettingDialog.ReplyIconState == MyCommon.REPLY_ICONSTATE.StaticIcon)
8562                 {
8563                     NotifyIcon1.Icon = ReplyIcon;
8564                 }
8565                 else
8566                 {
8567                     NotifyIcon1.Icon = ReplyIconBlink;
8568                 }
8569                 idle = false;
8570                 return;
8571             }
8572
8573             if (idle) return;
8574             idle = true;
8575             //優先度:エラー→オフライン→アイドル
8576             //エラーは更新アイコンでクリアされる
8577             if (_myStatusError)
8578             {
8579                 NotifyIcon1.Icon = NIconAtRed;
8580                 return;
8581             }
8582             if (_myStatusOnline)
8583             {
8584                 NotifyIcon1.Icon = NIconAt;
8585             }
8586             else
8587             {
8588                 NotifyIcon1.Icon = NIconAtSmoke;
8589             }
8590         }
8591
8592         private void TimerRefreshIcon_Tick(object sender, EventArgs e)
8593         {
8594             //200ms
8595             this.RefreshTasktrayIcon(false);
8596         }
8597
8598         private void ContextMenuTabProperty_Opening(object sender, CancelEventArgs e)
8599         {
8600             //右クリックの場合はタブ名が設定済。アプリケーションキーの場合は現在のタブを対象とする
8601             if (string.IsNullOrEmpty(_rclickTabName) || sender != ContextMenuTabProperty)
8602             {
8603                 if (ListTab != null && ListTab.SelectedTab != null)
8604                     _rclickTabName = ListTab.SelectedTab.Text;
8605                 else
8606                     return;
8607             }
8608
8609             if (_statuses == null) return;
8610             if (_statuses.Tabs == null) return;
8611
8612             TabClass tb = _statuses.Tabs[_rclickTabName];
8613             if (tb == null) return;
8614
8615             NotifyDispMenuItem.Checked = tb.Notify;
8616             this.NotifyTbMenuItem.Checked = tb.Notify;
8617
8618             soundfileListup = true;
8619             SoundFileComboBox.Items.Clear();
8620             this.SoundFileTbComboBox.Items.Clear();
8621             SoundFileComboBox.Items.Add("");
8622             this.SoundFileTbComboBox.Items.Add("");
8623             DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
8624             if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
8625             {
8626                 oDir = oDir.GetDirectories("Sounds")[0];
8627             }
8628             foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
8629             {
8630                 SoundFileComboBox.Items.Add(oFile.Name);
8631                 this.SoundFileTbComboBox.Items.Add(oFile.Name);
8632             }
8633             int idx = SoundFileComboBox.Items.IndexOf(tb.SoundFile);
8634             if (idx == -1) idx = 0;
8635             SoundFileComboBox.SelectedIndex = idx;
8636             this.SoundFileTbComboBox.SelectedIndex = idx;
8637             soundfileListup = false;
8638             UreadManageMenuItem.Checked = tb.UnreadManage;
8639             this.UnreadMngTbMenuItem.Checked = tb.UnreadManage;
8640
8641             TabMenuControl(_rclickTabName);
8642         }
8643
8644         private void TabMenuControl(string tabName)
8645         {
8646             this.FilterEditMenuItem.Enabled = true;
8647             this.EditRuleTbMenuItem.Enabled = true;
8648
8649             if (_statuses.IsDefaultTab(tabName))
8650             {
8651                 this.ProtectTabMenuItem.Enabled = false;
8652                 this.ProtectTbMenuItem.Enabled = false;
8653             }
8654             else
8655             {
8656                 this.ProtectTabMenuItem.Enabled = true;
8657                 this.ProtectTbMenuItem.Enabled = true;
8658             }
8659
8660             if (_statuses.IsDefaultTab(tabName) || _statuses.Tabs[tabName].Protected)
8661             {
8662                 this.ProtectTabMenuItem.Checked = true;
8663                 this.ProtectTbMenuItem.Checked = true;
8664                 this.DeleteTabMenuItem.Enabled = false;
8665                 this.DeleteTbMenuItem.Enabled = false;
8666             }
8667             else
8668             {
8669                 this.ProtectTabMenuItem.Checked = false;
8670                 this.ProtectTbMenuItem.Checked = false;
8671                 this.DeleteTabMenuItem.Enabled = true;
8672                 this.DeleteTbMenuItem.Enabled = true;
8673             }
8674         }
8675
8676         private void ProtectTabMenuItem_Click(object sender, EventArgs e)
8677         {
8678             var checkState = ((ToolStripMenuItem)sender).Checked;
8679
8680             // チェック状態を同期
8681             this.ProtectTbMenuItem.Checked = checkState;
8682             this.ProtectTabMenuItem.Checked = checkState;
8683
8684             // ロック中はタブの削除を無効化
8685             this.DeleteTabMenuItem.Enabled = !checkState;
8686             this.DeleteTbMenuItem.Enabled = !checkState;
8687
8688             if (string.IsNullOrEmpty(_rclickTabName)) return;
8689             _statuses.Tabs[_rclickTabName].Protected = checkState;
8690
8691             SaveConfigsTabs();
8692         }
8693
8694         private void UreadManageMenuItem_Click(object sender, EventArgs e)
8695         {
8696             UreadManageMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
8697             this.UnreadMngTbMenuItem.Checked = UreadManageMenuItem.Checked;
8698
8699             if (string.IsNullOrEmpty(_rclickTabName)) return;
8700             ChangeTabUnreadManage(_rclickTabName, UreadManageMenuItem.Checked);
8701
8702             SaveConfigsTabs();
8703         }
8704
8705         public void ChangeTabUnreadManage(string tabName, bool isManage)
8706         {
8707             int idx;
8708             for (idx = 0; idx < ListTab.TabCount; idx++)
8709             {
8710                 if (ListTab.TabPages[idx].Text == tabName) break;
8711             }
8712
8713             _statuses.SetTabUnreadManage(tabName, isManage);
8714             if (SettingDialog.TabIconDisp)
8715             {
8716                 if (_statuses.Tabs[tabName].UnreadCount > 0)
8717                     ListTab.TabPages[idx].ImageIndex = 0;
8718                 else
8719                     ListTab.TabPages[idx].ImageIndex = -1;
8720             }
8721
8722             if (_curTab.Text == tabName)
8723             {
8724                 this.PurgeListViewItemCache();
8725                 _curList.Refresh();
8726             }
8727
8728             SetMainWindowTitle();
8729             SetStatusLabelUrl();
8730             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8731         }
8732
8733         private void NotifyDispMenuItem_Click(object sender, EventArgs e)
8734         {
8735             NotifyDispMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
8736             this.NotifyTbMenuItem.Checked = NotifyDispMenuItem.Checked;
8737
8738             if (string.IsNullOrEmpty(_rclickTabName)) return;
8739
8740             _statuses.Tabs[_rclickTabName].Notify = NotifyDispMenuItem.Checked;
8741
8742             SaveConfigsTabs();
8743         }
8744
8745         private void SoundFileComboBox_SelectedIndexChanged(object sender, EventArgs e)
8746         {
8747             if (soundfileListup || string.IsNullOrEmpty(_rclickTabName)) return;
8748
8749             _statuses.Tabs[_rclickTabName].SoundFile = (string)((ToolStripComboBox)sender).SelectedItem;
8750
8751             SaveConfigsTabs();
8752         }
8753
8754         private void DeleteTabMenuItem_Click(object sender, EventArgs e)
8755         {
8756             if (string.IsNullOrEmpty(_rclickTabName) || sender == this.DeleteTbMenuItem) _rclickTabName = ListTab.SelectedTab.Text;
8757
8758             RemoveSpecifiedTab(_rclickTabName, true);
8759             SaveConfigsTabs();
8760         }
8761
8762         private void FilterEditMenuItem_Click(object sender, EventArgs e)
8763         {
8764             if (string.IsNullOrEmpty(_rclickTabName)) _rclickTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Home).TabName;
8765             fltDialog.SetCurrent(_rclickTabName);
8766             fltDialog.ShowDialog(this);
8767             this.TopMost = SettingDialog.AlwaysTop;
8768
8769             try
8770             {
8771                 this.Cursor = Cursors.WaitCursor;
8772                 this.PurgeListViewItemCache();
8773                 _curPost = null;
8774                 _curItemIndex = -1;
8775                 _statuses.FilterAll();
8776                 foreach (TabPage tb in ListTab.TabPages)
8777                 {
8778                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
8779                     if (_statuses.Tabs[tb.Text].UnreadCount > 0)
8780                     {
8781                         if (SettingDialog.TabIconDisp)
8782                             tb.ImageIndex = 0;
8783                     }
8784                     else
8785                     {
8786                         if (SettingDialog.TabIconDisp)
8787                             tb.ImageIndex = -1;
8788                     }
8789                 }
8790                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8791             }
8792             finally
8793             {
8794                 this.Cursor = Cursors.Default;
8795             }
8796             SaveConfigsTabs();
8797         }
8798
8799         private void AddTabMenuItem_Click(object sender, EventArgs e)
8800         {
8801             string tabName = null;
8802             MyCommon.TabUsageType tabUsage;
8803             using (InputTabName inputName = new InputTabName())
8804             {
8805                 inputName.TabName = _statuses.GetUniqueTabName();
8806                 inputName.IsShowUsage = true;
8807                 inputName.ShowDialog();
8808                 if (inputName.DialogResult == DialogResult.Cancel) return;
8809                 tabName = inputName.TabName;
8810                 tabUsage = inputName.Usage;
8811             }
8812             this.TopMost = SettingDialog.AlwaysTop;
8813             if (!string.IsNullOrEmpty(tabName))
8814             {
8815                 //List対応
8816                 ListElement list = null;
8817                 if (tabUsage == MyCommon.TabUsageType.Lists)
8818                 {
8819                     using (ListAvailable listAvail = new ListAvailable())
8820                     {
8821                         if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
8822                         if (listAvail.SelectedList == null) return;
8823                         list = listAvail.SelectedList;
8824                     }
8825                 }
8826                 if (!_statuses.AddTab(tabName, tabUsage, list) || !AddNewTab(tabName, false, tabUsage, list))
8827                 {
8828                     string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
8829                     MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
8830                 }
8831                 else
8832                 {
8833                     //成功
8834                     SaveConfigsTabs();
8835                     if (tabUsage == MyCommon.TabUsageType.PublicSearch)
8836                     {
8837                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
8838                         ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
8839                         ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
8840                     }
8841                     if (tabUsage == MyCommon.TabUsageType.Lists)
8842                     {
8843                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
8844                         ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
8845                         GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, tabName);
8846                     }
8847                 }
8848             }
8849         }
8850
8851         private void TabMenuItem_Click(object sender, EventArgs e)
8852         {
8853             //選択発言を元にフィルタ追加
8854             foreach (int idx in _curList.SelectedIndices)
8855             {
8856                 string tabName;
8857                 //タブ選択(or追加)
8858                 if (!SelectTab(out tabName)) return;
8859
8860                 fltDialog.SetCurrent(tabName);
8861                 if (_statuses[_curTab.Text, idx].RetweetedId == null)
8862                 {
8863                     fltDialog.AddNewFilter(_statuses[_curTab.Text, idx].ScreenName, _statuses[_curTab.Text, idx].TextFromApi);
8864                 }
8865                 else
8866                 {
8867                     fltDialog.AddNewFilter(_statuses[_curTab.Text, idx].RetweetedBy, _statuses[_curTab.Text, idx].TextFromApi);
8868                 }
8869                 fltDialog.ShowDialog(this);
8870                 this.TopMost = SettingDialog.AlwaysTop;
8871             }
8872
8873             try
8874             {
8875                 this.Cursor = Cursors.WaitCursor;
8876                 this.PurgeListViewItemCache();
8877                 _curPost = null;
8878                 _curItemIndex = -1;
8879                 _statuses.FilterAll();
8880                 foreach (TabPage tb in ListTab.TabPages)
8881                 {
8882                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
8883                     if (_statuses.Tabs[tb.Text].UnreadCount > 0)
8884                     {
8885                         if (SettingDialog.TabIconDisp)
8886                             tb.ImageIndex = 0;
8887                     }
8888                     else
8889                     {
8890                         if (SettingDialog.TabIconDisp)
8891                             tb.ImageIndex = -1;
8892                     }
8893                 }
8894                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8895             }
8896             finally
8897             {
8898                 this.Cursor = Cursors.Default;
8899             }
8900             SaveConfigsTabs();
8901             if (this.ListTab.SelectedTab != null &&
8902                 ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices.Count > 0)
8903             {
8904                 _curPost = _statuses[this.ListTab.SelectedTab.Text, ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices[0]];
8905             }
8906         }
8907
8908         protected override bool ProcessDialogKey(Keys keyData)
8909         {
8910             //TextBox1でEnterを押してもビープ音が鳴らないようにする
8911             if ((keyData & Keys.KeyCode) == Keys.Enter)
8912             {
8913                 if (StatusText.Focused)
8914                 {
8915                     bool _NewLine = false;
8916                     bool _Post = false;
8917
8918                     if (SettingDialog.PostCtrlEnter) //Ctrl+Enter投稿時
8919                     {
8920                         if (StatusText.Multiline)
8921                         {
8922                             if ((keyData & Keys.Shift) == Keys.Shift && (keyData & Keys.Control) != Keys.Control) _NewLine = true;
8923
8924                             if ((keyData & Keys.Control) == Keys.Control) _Post = true;
8925                         }
8926                         else
8927                         {
8928                             if (((keyData & Keys.Control) == Keys.Control)) _Post = true;
8929                         }
8930
8931                     }
8932                     else if (SettingDialog.PostShiftEnter) //SHift+Enter投稿時
8933                     {
8934                         if (StatusText.Multiline)
8935                         {
8936                             if ((keyData & Keys.Control) == Keys.Control && (keyData & Keys.Shift) != Keys.Shift) _NewLine = true;
8937
8938                             if ((keyData & Keys.Shift) == Keys.Shift) _Post = true;
8939                         }
8940                         else
8941                         {
8942                             if (((keyData & Keys.Shift) == Keys.Shift)) _Post = true;
8943                         }
8944
8945                     }
8946                     else //Enter投稿時
8947                     {
8948                         if (StatusText.Multiline)
8949                         {
8950                             if ((keyData & Keys.Shift) == Keys.Shift && (keyData & Keys.Control) != Keys.Control) _NewLine = true;
8951
8952                             if (((keyData & Keys.Control) != Keys.Control && (keyData & Keys.Shift) != Keys.Shift) ||
8953                                 ((keyData & Keys.Control) == Keys.Control && (keyData & Keys.Shift) == Keys.Shift)) _Post = true;
8954                         }
8955                         else
8956                         {
8957                             if (((keyData & Keys.Shift) == Keys.Shift) ||
8958                                 (((keyData & Keys.Control) != Keys.Control) &&
8959                                 ((keyData & Keys.Shift) != Keys.Shift))) _Post = true;
8960                         }
8961                     }
8962
8963                     if (_NewLine)
8964                     {
8965                         int pos1 = StatusText.SelectionStart;
8966                         if (StatusText.SelectionLength > 0)
8967                         {
8968                             StatusText.Text = StatusText.Text.Remove(pos1, StatusText.SelectionLength);  //選択状態文字列削除
8969                         }
8970                         StatusText.Text = StatusText.Text.Insert(pos1, Environment.NewLine);  //改行挿入
8971                         StatusText.SelectionStart = pos1 + Environment.NewLine.Length;    //カーソルを改行の次の文字へ移動
8972                         return true;
8973                     }
8974                     else if (_Post)
8975                     {
8976                         PostButton_Click(null, null);
8977                         return true;
8978                     }
8979                 }
8980                 else if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch &&
8981                          (ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focused ||
8982                          ListTab.SelectedTab.Controls["panelSearch"].Controls["comboLang"].Focused))
8983                 {
8984                     this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
8985                     return true;
8986                 }
8987             }
8988
8989             return base.ProcessDialogKey(keyData);
8990         }
8991
8992         private void ReplyAllStripMenuItem_Click(object sender, EventArgs e)
8993         {
8994             MakeReplyOrDirectStatus(false, true, true);
8995         }
8996
8997         private void IDRuleMenuItem_Click(object sender, EventArgs e)
8998         {
8999             string tabName;
9000
9001             //未選択なら処理終了
9002             if (_curList.SelectedIndices.Count == 0) return;
9003
9004             //タブ選択(or追加)
9005             if (!SelectTab(out tabName)) return;
9006
9007             bool mv = false;
9008             bool mk = false;
9009             MoveOrCopy(ref mv, ref mk);
9010
9011             List<string> ids = new List<string>();
9012             foreach (int idx in _curList.SelectedIndices)
9013             {
9014                 PostClass post = _statuses[_curTab.Text, idx];
9015                 if (!ids.Contains(post.ScreenName))
9016                 {
9017                     PostFilterRule fc = new PostFilterRule();
9018                     ids.Add(post.ScreenName);
9019                     if (post.RetweetedId == null)
9020                     {
9021                         fc.FilterName = post.ScreenName;
9022                     }
9023                     else
9024                     {
9025                         fc.FilterName = post.RetweetedBy;
9026                     }
9027                     fc.UseNameField = true;
9028                     fc.MoveMatches = mv;
9029                     fc.MarkMatches = mk;
9030                     fc.UseRegex = false;
9031                     fc.FilterByUrl = false;
9032                     _statuses.Tabs[tabName].AddFilter(fc);
9033                 }
9034             }
9035             if (ids.Count != 0)
9036             {
9037                 List<string> atids = new List<string>();
9038                 foreach (string id in ids)
9039                 {
9040                     atids.Add("@" + id);
9041                 }
9042                 int cnt = AtIdSupl.ItemCount;
9043                 AtIdSupl.AddRangeItem(atids.ToArray());
9044                 if (AtIdSupl.ItemCount != cnt) _modifySettingAtId = true;
9045             }
9046
9047             try
9048             {
9049                 this.Cursor = Cursors.WaitCursor;
9050                 this.PurgeListViewItemCache();
9051                 _curPost = null;
9052                 _curItemIndex = -1;
9053                 _statuses.FilterAll();
9054                 foreach (TabPage tb in ListTab.TabPages)
9055                 {
9056                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
9057                     if (_statuses.ContainsTab(tb.Text))
9058                     {
9059                         if (_statuses.Tabs[tb.Text].UnreadCount > 0)
9060                         {
9061                             if (SettingDialog.TabIconDisp)
9062                                 tb.ImageIndex = 0;
9063                         }
9064                         else
9065                         {
9066                             if (SettingDialog.TabIconDisp)
9067                                 tb.ImageIndex = -1;
9068                         }
9069                     }
9070                 }
9071                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
9072             }
9073             finally
9074             {
9075                 this.Cursor = Cursors.Default;
9076             }
9077             SaveConfigsTabs();
9078         }
9079
9080         private bool SelectTab(out string tabName)
9081         {
9082             do
9083             {
9084                 tabName = null;
9085
9086                 //振り分け先タブ選択
9087                 using (var dialog = new TabsDialog(_statuses))
9088                 {
9089                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return false;
9090
9091                     var selectedTab = dialog.SelectedTab;
9092                     tabName = selectedTab == null ? null : selectedTab.TabName;
9093                 }
9094
9095                 ListTab.SelectedTab.Focus();
9096                 //新規タブを選択→タブ作成
9097                 if (tabName == null)
9098                 {
9099                     using (InputTabName inputName = new InputTabName())
9100                     {
9101                         inputName.TabName = _statuses.GetUniqueTabName();
9102                         inputName.ShowDialog();
9103                         if (inputName.DialogResult == DialogResult.Cancel) return false;
9104                         tabName = inputName.TabName;
9105                     }
9106                     this.TopMost = SettingDialog.AlwaysTop;
9107                     if (!string.IsNullOrEmpty(tabName))
9108                     {
9109                         if (!_statuses.AddTab(tabName, MyCommon.TabUsageType.UserDefined, null) || !AddNewTab(tabName, false, MyCommon.TabUsageType.UserDefined))
9110                         {
9111                             string tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText2, tabName);
9112                             MessageBox.Show(tmp, Properties.Resources.IDRuleMenuItem_ClickText3, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
9113                             //もう一度タブ名入力
9114                         }
9115                         else
9116                         {
9117                             return true;
9118                         }
9119                     }
9120                 }
9121                 else
9122                 {
9123                     //既存タブを選択
9124                     return true;
9125                 }
9126             }
9127             while (true);
9128         }
9129
9130         private void MoveOrCopy(ref bool move, ref bool mark)
9131         {
9132             {
9133                 //移動するか?
9134                 string _tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText4, Environment.NewLine);
9135                 if (MessageBox.Show(_tmp, Properties.Resources.IDRuleMenuItem_ClickText5, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
9136                     move = false;
9137                 else
9138                     move = true;
9139             }
9140             if (!move)
9141             {
9142                 //マークするか?
9143                 string _tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText6, Environment.NewLine);
9144                 if (MessageBox.Show(_tmp, Properties.Resources.IDRuleMenuItem_ClickText7, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
9145                     mark = true;
9146                 else
9147                     mark = false;
9148             }
9149         }
9150         private void CopySTOTMenuItem_Click(object sender, EventArgs e)
9151         {
9152             this.CopyStot();
9153         }
9154
9155         private void CopyURLMenuItem_Click(object sender, EventArgs e)
9156         {
9157             this.CopyIdUri();
9158         }
9159
9160         private void SelectAllMenuItem_Click(object sender, EventArgs e)
9161         {
9162             if (StatusText.Focused)
9163             {
9164                 // 発言欄でのCtrl+A
9165                 StatusText.SelectAll();
9166             }
9167             else
9168             {
9169                 // ListView上でのCtrl+A
9170                 for (int i = 0; i < _curList.VirtualListSize; i++)
9171                 {
9172                     _curList.SelectedIndices.Add(i);
9173                 }
9174             }
9175         }
9176
9177         private void MoveMiddle()
9178         {
9179             ListViewItem _item;
9180             int idx1;
9181             int idx2;
9182
9183             if (_curList.SelectedIndices.Count == 0) return;
9184
9185             int idx = _curList.SelectedIndices[0];
9186
9187             _item = _curList.GetItemAt(0, 25);
9188             if (_item == null)
9189                 idx1 = 0;
9190             else
9191                 idx1 = _item.Index;
9192
9193             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
9194             if (_item == null)
9195                 idx2 = _curList.VirtualListSize - 1;
9196             else
9197                 idx2 = _item.Index;
9198
9199             idx -= Math.Abs(idx1 - idx2) / 2;
9200             if (idx < 0) idx = 0;
9201
9202             _curList.EnsureVisible(_curList.VirtualListSize - 1);
9203             _curList.EnsureVisible(idx);
9204         }
9205
9206         private void OpenURLMenuItem_Click(object sender, EventArgs e)
9207         {
9208             if (PostBrowser.Document.Links.Count > 0)
9209             {
9210                 UrlDialog.ClearUrl();
9211
9212                 string openUrlStr = "";
9213
9214                 if (PostBrowser.Document.Links.Count == 1)
9215                 {
9216                     string urlStr = "";
9217                     try
9218                     {
9219                         urlStr = MyCommon.IDNEncode(PostBrowser.Document.Links[0].GetAttribute("href"));
9220                     }
9221                     catch (ArgumentException)
9222                     {
9223                         //変なHTML?
9224                         return;
9225                     }
9226                     catch (Exception)
9227                     {
9228                         return;
9229                     }
9230                     if (string.IsNullOrEmpty(urlStr)) return;
9231                     openUrlStr = MyCommon.urlEncodeMultibyteChar(urlStr);
9232                 }
9233                 else
9234                 {
9235                     foreach (HtmlElement linkElm in PostBrowser.Document.Links)
9236                     {
9237                         string urlStr = "";
9238                         string linkText = "";
9239                         string href = "";
9240                         try
9241                         {
9242                             urlStr = linkElm.GetAttribute("title");
9243                             href = MyCommon.IDNEncode(linkElm.GetAttribute("href"));
9244                             if (string.IsNullOrEmpty(urlStr)) urlStr = href;
9245                             linkText = linkElm.InnerText;
9246                             if (!linkText.StartsWith("http") && !linkText.StartsWith("#") && !linkText.Contains("."))
9247                             {
9248                                 linkText = "@" + linkText;
9249                             }
9250                         }
9251                         catch (ArgumentException)
9252                         {
9253                             //変なHTML?
9254                             return;
9255                         }
9256                         catch (Exception)
9257                         {
9258                             return;
9259                         }
9260                         if (string.IsNullOrEmpty(urlStr)) continue;
9261                         UrlDialog.AddUrl(new OpenUrlItem(linkText, MyCommon.urlEncodeMultibyteChar(urlStr), href));
9262                     }
9263                     try
9264                     {
9265                         if (UrlDialog.ShowDialog() == DialogResult.OK)
9266                         {
9267                             openUrlStr = UrlDialog.SelectedUrl;
9268                         }
9269                     }
9270                     catch (Exception)
9271                     {
9272                         return;
9273                     }
9274                     this.TopMost = SettingDialog.AlwaysTop;
9275                 }
9276                 if (string.IsNullOrEmpty(openUrlStr)) return;
9277
9278                 if (openUrlStr.StartsWith("http://twitter.com/search?q=") ||
9279                     openUrlStr.StartsWith("https://twitter.com/search?q="))
9280                 {
9281                     //ハッシュタグの場合は、タブで開く
9282                     string urlStr = Uri.UnescapeDataString(openUrlStr);
9283                     string hash = urlStr.Substring(urlStr.IndexOf("#"));
9284                     HashSupl.AddItem(hash);
9285                     HashMgr.AddHashToHistory(hash.Trim(), false);
9286                     AddNewTabForSearch(hash);
9287                     return;
9288                 }
9289                 else
9290                 {
9291                     Match m = Regex.Match(openUrlStr, "^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
9292                     if (SettingDialog.OpenUserTimeline && m.Success && IsTwitterId(m.Result("${ScreenName}")))
9293                         this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
9294                     else
9295                         OpenUriAsync(openUrlStr);
9296                     return;
9297                 }
9298             }
9299         }
9300
9301         private void ClearTabMenuItem_Click(object sender, EventArgs e)
9302         {
9303             if (string.IsNullOrEmpty(_rclickTabName)) return;
9304             ClearTab(_rclickTabName, true);
9305         }
9306
9307         private void ClearTab(string tabName, bool showWarning)
9308         {
9309             if (showWarning)
9310             {
9311                 string tmp = string.Format(Properties.Resources.ClearTabMenuItem_ClickText1, Environment.NewLine);
9312                 if (MessageBox.Show(tmp, tabName + " " + Properties.Resources.ClearTabMenuItem_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
9313                 {
9314                     return;
9315                 }
9316             }
9317
9318             _statuses.ClearTabIds(tabName);
9319             if (ListTab.SelectedTab.Text == tabName)
9320             {
9321                 _anchorPost = null;
9322                 _anchorFlag = false;
9323                 this.PurgeListViewItemCache();
9324                 _curItemIndex = -1;
9325                 _curPost = null;
9326             }
9327             foreach (TabPage tb in ListTab.TabPages)
9328             {
9329                 if (tb.Text == tabName)
9330                 {
9331                     tb.ImageIndex = -1;
9332                     ((DetailsListView)tb.Tag).VirtualListSize = 0;
9333                     break;
9334                 }
9335             }
9336             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
9337
9338             SetMainWindowTitle();
9339             SetStatusLabelUrl();
9340         }
9341
9342         private static long followers = 0;
9343
9344         private void SetMainWindowTitle()
9345         {
9346             //メインウインドウタイトルの書き換え
9347             StringBuilder ttl = new StringBuilder(256);
9348             int ur = 0;
9349             int al = 0;
9350             if (SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.None &&
9351                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Post &&
9352                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
9353                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
9354             {
9355                 foreach (string key in _statuses.Tabs.Keys)
9356                 {
9357                     ur += _statuses.Tabs[key].UnreadCount;
9358                     al += _statuses.Tabs[key].AllCount;
9359                 }
9360             }
9361
9362             if (SettingDialog.DispUsername) ttl.Append(tw.Username).Append(" - ");
9363             ttl.Append(Application.ProductName);
9364             ttl.Append("  ");
9365             switch (SettingDialog.DispLatestPost)
9366             {
9367                 case MyCommon.DispTitleEnum.Ver:
9368                     ttl.Append("Ver:").Append(MyCommon.GetReadableVersion());
9369                     break;
9370                 case MyCommon.DispTitleEnum.Post:
9371                     if (_history != null && _history.Count > 1)
9372                         ttl.Append(_history[_history.Count - 2].status.Replace("\r\n", " "));
9373                     break;
9374                 case MyCommon.DispTitleEnum.UnreadRepCount:
9375                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText1, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
9376                     break;
9377                 case MyCommon.DispTitleEnum.UnreadAllCount:
9378                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText2, ur);
9379                     break;
9380                 case MyCommon.DispTitleEnum.UnreadAllRepCount:
9381                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText3, ur, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
9382                     break;
9383                 case MyCommon.DispTitleEnum.UnreadCountAllCount:
9384                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText4, ur, al);
9385                     break;
9386                 case MyCommon.DispTitleEnum.OwnStatus:
9387                     if (followers == 0 && tw.FollowersCount > 0) followers = tw.FollowersCount;
9388                     ttl.AppendFormat(Properties.Resources.OwnStatusTitle, tw.StatusesCount, tw.FriendsCount, tw.FollowersCount, tw.FollowersCount - followers);
9389                     break;
9390             }
9391
9392             try
9393             {
9394                 this.Text = ttl.ToString();
9395             }
9396             catch (AccessViolationException)
9397             {
9398                 //原因不明。ポスト内容に依存か?たまーに発生するが再現せず。
9399             }
9400         }
9401
9402         private string GetStatusLabelText()
9403         {
9404             //ステータス欄にカウント表示
9405             //タブ未読数/タブ発言数 全未読数/総発言数 (未読@+未読DM数)
9406             if (_statuses == null) return "";
9407             TabClass tbRep = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
9408             TabClass tbDm = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage);
9409             if (tbRep == null || tbDm == null) return "";
9410             int urat = tbRep.UnreadCount + tbDm.UnreadCount;
9411             int ur = 0;
9412             int al = 0;
9413             int tur = 0;
9414             int tal = 0;
9415             StringBuilder slbl = new StringBuilder(256);
9416             try
9417             {
9418                 foreach (string key in _statuses.Tabs.Keys)
9419                 {
9420                     ur += _statuses.Tabs[key].UnreadCount;
9421                     al += _statuses.Tabs[key].AllCount;
9422                     if (key.Equals(_curTab.Text))
9423                     {
9424                         tur = _statuses.Tabs[key].UnreadCount;
9425                         tal = _statuses.Tabs[key].AllCount;
9426                     }
9427                 }
9428             }
9429             catch (Exception)
9430             {
9431                 return "";
9432             }
9433
9434             UnreadCounter = ur;
9435             UnreadAtCounter = urat;
9436
9437             slbl.AppendFormat(Properties.Resources.SetStatusLabelText1, tur, tal, ur, al, urat, _postTimestamps.Count, _favTimestamps.Count, _tlCount);
9438             if (SettingDialog.TimelinePeriodInt == 0)
9439             {
9440                 slbl.Append(Properties.Resources.SetStatusLabelText2);
9441             }
9442             else
9443             {
9444                 slbl.Append(SettingDialog.TimelinePeriodInt.ToString() + Properties.Resources.SetStatusLabelText3);
9445             }
9446             return slbl.ToString();
9447         }
9448
9449         private void TwitterApiStatus_AccessLimitUpdated(object sender, EventArgs e)
9450         {
9451             try
9452             {
9453                 if (this.InvokeRequired && !this.IsDisposed)
9454                 {
9455                     this.Invoke((MethodInvoker)(() => this.TwitterApiStatus_AccessLimitUpdated(sender, e)));
9456                 }
9457                 else
9458                 {
9459                     var endpointName = (e as TwitterApiStatus.AccessLimitUpdatedEventArgs).EndpointName;
9460                     if (endpointName == "/statuses/home_timeline" || endpointName == null)
9461                     {
9462                         this._apiGauge.ApiLimit = MyCommon.TwitterApiInfo.AccessLimit["/statuses/home_timeline"];
9463                     }
9464                 }
9465             }
9466             catch (ObjectDisposedException)
9467             {
9468                 return;
9469             }
9470             catch (InvalidOperationException)
9471             {
9472                 return;
9473             }
9474         }
9475
9476         private void SetStatusLabelUrl()
9477         {
9478             StatusLabelUrl.Text = GetStatusLabelText();
9479         }
9480
9481         public void SetStatusLabel(string text)
9482         {
9483             StatusLabel.Text = text;
9484         }
9485
9486         private static StringBuilder ur = new StringBuilder(64);
9487
9488         private void SetNotifyIconText()
9489         {
9490             // タスクトレイアイコンのツールチップテキスト書き換え
9491             // Tween [未読/@]
9492             ur.Remove(0, ur.Length);
9493             if (SettingDialog.DispUsername)
9494             {
9495                 ur.Append(tw.Username);
9496                 ur.Append(" - ");
9497             }
9498             ur.Append(Application.ProductName);
9499 #if DEBUG
9500             ur.Append("(Debug Build)");
9501 #endif
9502             if (UnreadCounter != -1 && UnreadAtCounter != -1)
9503             {
9504                 ur.Append(" [");
9505                 ur.Append(UnreadCounter);
9506                 ur.Append("/@");
9507                 ur.Append(UnreadAtCounter);
9508                 ur.Append("]");
9509             }
9510             NotifyIcon1.Text = ur.ToString();
9511         }
9512
9513         internal void CheckReplyTo(string StatusText)
9514         {
9515             MatchCollection m;
9516             //ハッシュタグの保存
9517             m = Regex.Matches(StatusText, Twitter.HASHTAG, RegexOptions.IgnoreCase);
9518             string hstr = "";
9519             foreach (Match hm in m)
9520             {
9521                 if (!hstr.Contains("#" + hm.Result("$3") + " "))
9522                 {
9523                     hstr += "#" + hm.Result("$3") + " ";
9524                     HashSupl.AddItem("#" + hm.Result("$3"));
9525                 }
9526             }
9527             if (!string.IsNullOrEmpty(HashMgr.UseHash) && !hstr.Contains(HashMgr.UseHash + " "))
9528             {
9529                 hstr += HashMgr.UseHash;
9530             }
9531             if (!string.IsNullOrEmpty(hstr)) HashMgr.AddHashToHistory(hstr.Trim(), false);
9532
9533             // 本当にリプライ先指定すべきかどうかの判定
9534             m = Regex.Matches(StatusText, "(^|[ -/:-@[-^`{-~])(?<id>@[a-zA-Z0-9_]+)");
9535
9536             if (SettingDialog.UseAtIdSupplement)
9537             {
9538                 int bCnt = AtIdSupl.ItemCount;
9539                 foreach (Match mid in m)
9540                 {
9541                     AtIdSupl.AddItem(mid.Result("${id}"));
9542                 }
9543                 if (bCnt != AtIdSupl.ItemCount) _modifySettingAtId = true;
9544             }
9545
9546             // リプライ先ステータスIDの指定がない場合は指定しない
9547             if (_reply_to_id == null) return;
9548
9549             // リプライ先ユーザー名がない場合も指定しない
9550             if (string.IsNullOrEmpty(_reply_to_name))
9551             {
9552                 _reply_to_id = null;
9553                 return;
9554             }
9555
9556             // 通常Reply
9557             // 次の条件を満たす場合に in_reply_to_status_id 指定
9558             // 1. Twitterによりリンクと判定される @idが文中に1つ含まれる (2009/5/28 リンク化される@IDのみカウントするように修正)
9559             // 2. リプライ先ステータスIDが設定されている(リストをダブルクリックで返信している)
9560             // 3. 文中に含まれた@idがリプライ先のポスト者のIDと一致する
9561
9562             if (m != null)
9563             {
9564                 if (StatusText.StartsWith("@"))
9565                 {
9566                     if (StatusText.StartsWith("@" + _reply_to_name)) return;
9567                 }
9568                 else
9569                 {
9570                     foreach (Match mid in m)
9571                     {
9572                         if (StatusText.Contains("QT " + mid.Result("${id}") + ":") && mid.Result("${id}") == "@" + _reply_to_name) return;
9573                     }
9574                 }
9575             }
9576
9577             _reply_to_id = null;
9578             _reply_to_name = null;
9579
9580         }
9581
9582         private void TweenMain_Resize(object sender, EventArgs e)
9583         {
9584             if (!_initialLayout && SettingDialog.MinimizeToTray && WindowState == FormWindowState.Minimized)
9585             {
9586                 this.Visible = false;
9587             }
9588             if (_initialLayout && _cfgLocal != null && this.WindowState == FormWindowState.Normal && this.Visible)
9589             {
9590                 this.ClientSize = _cfgLocal.FormSize;
9591                 //_mySize = this.ClientSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
9592                 this.DesktopLocation = _cfgLocal.FormLocation;
9593                 //_myLoc = this.DesktopLocation;                        //位置保持(最小化・最大化されたまま終了した場合の対応用)
9594                 //if (_cfgLocal.AdSplitterDistance > this.SplitContainer4.Panel1MinSize &&
9595                 //    _cfgLocal.AdSplitterDistance < this.SplitContainer4.Height - this.SplitContainer4.Panel2MinSize - this.SplitContainer4.SplitterWidth)
9596                 //{
9597                 //    this.SplitContainer4.SplitterDistance = _cfgLocal.AdSplitterDistance; //Splitterの位置設定
9598                 //}
9599                 if (_cfgLocal.SplitterDistance > this.SplitContainer1.Panel1MinSize &&
9600                     _cfgLocal.SplitterDistance < this.SplitContainer1.Height - this.SplitContainer1.Panel2MinSize - this.SplitContainer1.SplitterWidth)
9601                 {
9602                     this.SplitContainer1.SplitterDistance = _cfgLocal.SplitterDistance; //Splitterの位置設定
9603                 }
9604                 //発言欄複数行
9605                 StatusText.Multiline = _cfgLocal.StatusMultiline;
9606                 if (StatusText.Multiline)
9607                 {
9608                     int dis = SplitContainer2.Height - _cfgLocal.StatusTextHeight - SplitContainer2.SplitterWidth;
9609                     if (dis > SplitContainer2.Panel1MinSize && dis < SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth)
9610                     {
9611                         SplitContainer2.SplitterDistance = SplitContainer2.Height - _cfgLocal.StatusTextHeight - SplitContainer2.SplitterWidth;
9612                     }
9613                     StatusText.Height = _cfgLocal.StatusTextHeight;
9614                 }
9615                 else
9616                 {
9617                     if (SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth > 0)
9618                     {
9619                         SplitContainer2.SplitterDistance = SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth;
9620                     }
9621                 }
9622                 if (_cfgLocal.PreviewDistance > this.SplitContainer3.Panel1MinSize && _cfgLocal.PreviewDistance < this.SplitContainer3.Width - this.SplitContainer3.Panel2MinSize - this.SplitContainer3.SplitterWidth)
9623                 {
9624                     this.SplitContainer3.SplitterDistance = _cfgLocal.PreviewDistance;
9625                 }
9626                 _initialLayout = false;
9627             }
9628             if (this.WindowState != FormWindowState.Minimized)
9629             {
9630                 _formWindowState = this.WindowState;
9631             }
9632         }
9633
9634         private void PlaySoundMenuItem_CheckedChanged(object sender, EventArgs e)
9635         {
9636             PlaySoundMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
9637             this.PlaySoundFileMenuItem.Checked = PlaySoundMenuItem.Checked;
9638             if (PlaySoundMenuItem.Checked)
9639             {
9640                 SettingDialog.PlaySound = true;
9641             }
9642             else
9643             {
9644                 SettingDialog.PlaySound = false;
9645             }
9646             _modifySettingCommon = true;
9647         }
9648
9649         private void SplitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
9650         {
9651             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
9652             {
9653                 _mySpDis = SplitContainer1.SplitterDistance;
9654                 if (StatusText.Multiline) _mySpDis2 = StatusText.Height;
9655                 _modifySettingLocal = true;
9656             }
9657         }
9658
9659         private void doRepliedStatusOpen()
9660         {
9661             if (this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId != null)
9662             {
9663                 if (MyCommon.IsKeyDown(Keys.Shift))
9664                 {
9665                     OpenUriAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId.Value));
9666                     return;
9667                 }
9668                 if (_statuses.ContainsKey(_curPost.InReplyToStatusId.Value))
9669                 {
9670                     PostClass repPost = _statuses[_curPost.InReplyToStatusId.Value];
9671                     MessageBox.Show(repPost.ScreenName + " / " + repPost.Nickname + "   (" + repPost.CreatedAt.ToString() + ")" + Environment.NewLine + repPost.TextFromApi);
9672                 }
9673                 else
9674                 {
9675                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
9676                     {
9677                         if (tb == null || !tb.Contains(_curPost.InReplyToStatusId.Value)) break;
9678                         PostClass repPost = _statuses[_curPost.InReplyToStatusId.Value];
9679                         MessageBox.Show(repPost.ScreenName + " / " + repPost.Nickname + "   (" + repPost.CreatedAt.ToString() + ")" + Environment.NewLine + repPost.TextFromApi);
9680                         return;
9681                     }
9682                     OpenUriAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId.Value));
9683                 }
9684             }
9685         }
9686
9687         private void RepliedStatusOpenMenuItem_Click(object sender, EventArgs e)
9688         {
9689             doRepliedStatusOpen();
9690         }
9691
9692         /// <summary>
9693         /// UserPicture.Image に設定されている画像を破棄します。
9694         /// </summary>
9695         private void ClearUserPicture()
9696         {
9697             if (this.UserPicture.Image != null)
9698             {
9699                 var oldImage = this.UserPicture.Image;
9700                 this.UserPicture.Image = null;
9701                 oldImage.Dispose();
9702             }
9703         }
9704
9705         private void ContextMenuUserPicture_Opening(object sender, CancelEventArgs e)
9706         {
9707             //発言詳細のアイコン右クリック時のメニュー制御
9708             if (_curList.SelectedIndices.Count > 0 && _curPost != null)
9709             {
9710                 string name = _curPost.ImageUrl;
9711                 if (name != null && name.Length > 0)
9712                 {
9713                     int idx = name.LastIndexOf('/');
9714                     if (idx != -1)
9715                     {
9716                         name = Path.GetFileName(name.Substring(idx));
9717                         if (name.Contains("_normal.") || name.EndsWith("_normal"))
9718                         {
9719                             name = name.Replace("_normal", "");
9720                             this.IconNameToolStripMenuItem.Text = name;
9721                             this.IconNameToolStripMenuItem.Enabled = true;
9722                         }
9723                         else
9724                         {
9725                             this.IconNameToolStripMenuItem.Enabled = false;
9726                             this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9727                         }
9728                     }
9729                     else
9730                     {
9731                         this.IconNameToolStripMenuItem.Enabled = false;
9732                         this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9733                     }
9734
9735                     this.ReloadIconToolStripMenuItem.Enabled = true;
9736
9737                     if (this.IconCache.TryGetFromCache(_curPost.ImageUrl) != null)
9738                     {
9739                         this.SaveIconPictureToolStripMenuItem.Enabled = true;
9740                     }
9741                     else
9742                     {
9743                         this.SaveIconPictureToolStripMenuItem.Enabled = false;
9744                     }
9745                 }
9746                 else
9747                 {
9748                     this.IconNameToolStripMenuItem.Enabled = false;
9749                     this.ReloadIconToolStripMenuItem.Enabled = false;
9750                     this.SaveIconPictureToolStripMenuItem.Enabled = false;
9751                     this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9752                 }
9753             }
9754             else
9755             {
9756                 this.IconNameToolStripMenuItem.Enabled = false;
9757                 this.ReloadIconToolStripMenuItem.Enabled = false;
9758                 this.SaveIconPictureToolStripMenuItem.Enabled = false;
9759                 this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText2;
9760             }
9761             if (NameLabel.Tag != null)
9762             {
9763                 string id = (string)NameLabel.Tag;
9764                 if (id == tw.Username)
9765                 {
9766                     FollowToolStripMenuItem.Enabled = false;
9767                     UnFollowToolStripMenuItem.Enabled = false;
9768                     ShowFriendShipToolStripMenuItem.Enabled = false;
9769                     ShowUserStatusToolStripMenuItem.Enabled = true;
9770                     SearchPostsDetailNameToolStripMenuItem.Enabled = true;
9771                     SearchAtPostsDetailNameToolStripMenuItem.Enabled = false;
9772                     ListManageUserContextToolStripMenuItem3.Enabled = true;
9773                 }
9774                 else
9775                 {
9776                     FollowToolStripMenuItem.Enabled = true;
9777                     UnFollowToolStripMenuItem.Enabled = true;
9778                     ShowFriendShipToolStripMenuItem.Enabled = true;
9779                     ShowUserStatusToolStripMenuItem.Enabled = true;
9780                     SearchPostsDetailNameToolStripMenuItem.Enabled = true;
9781                     SearchAtPostsDetailNameToolStripMenuItem.Enabled = true;
9782                     ListManageUserContextToolStripMenuItem3.Enabled = true;
9783                 }
9784             }
9785             else
9786             {
9787                 FollowToolStripMenuItem.Enabled = false;
9788                 UnFollowToolStripMenuItem.Enabled = false;
9789                 ShowFriendShipToolStripMenuItem.Enabled = false;
9790                 ShowUserStatusToolStripMenuItem.Enabled = false;
9791                 SearchPostsDetailNameToolStripMenuItem.Enabled = false;
9792                 SearchAtPostsDetailNameToolStripMenuItem.Enabled = false;
9793                 ListManageUserContextToolStripMenuItem3.Enabled = false;
9794             }
9795         }
9796
9797         private void IconNameToolStripMenuItem_Click(object sender, EventArgs e)
9798         {
9799             if (_curPost == null) return;
9800             string name = _curPost.ImageUrl;
9801             OpenUriAsync(name.Remove(name.LastIndexOf("_normal"), 7)); // "_normal".Length
9802         }
9803
9804         private /* async */ void ReloadIconToolStripMenuItem_Click(object sender, EventArgs e)
9805         {
9806             if (this._curPost == null) return;
9807
9808             var imageUrl = this._curPost.ImageUrl;
9809             var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
9810
9811             this.IconCache.DownloadImageAsync(imageUrl, force: true)
9812                 .ContinueWith(t =>
9813                 {
9814                     this.ClearUserPicture();
9815
9816                     if (t.IsFaulted)
9817                     {
9818                         t.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
9819                         this.UserPicture.ShowErrorImage();
9820                     }
9821                     else
9822                     {
9823                         this.UserPicture.Image = t.Result.Clone() ;
9824                     }
9825                 }, uiScheduler);
9826         }
9827
9828         private void SaveOriginalSizeIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
9829         {
9830             if (_curPost == null) return;
9831             string name = _curPost.ImageUrl;
9832             name = Path.GetFileNameWithoutExtension(name.Substring(name.LastIndexOf('/')));
9833
9834             this.SaveFileDialog1.FileName = name.Substring(0, name.Length - 8); // "_normal".Length + 1
9835
9836             if (this.SaveFileDialog1.ShowDialog() == DialogResult.OK)
9837             {
9838                 // STUB
9839             }
9840         }
9841
9842         private void SaveIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
9843         {
9844             if (_curPost == null) return;
9845             string name = _curPost.ImageUrl;
9846
9847             this.SaveFileDialog1.FileName = name.Substring(name.LastIndexOf('/') + 1);
9848
9849             if (this.SaveFileDialog1.ShowDialog() == DialogResult.OK)
9850             {
9851                 try
9852                 {
9853                     using (Image orgBmp = new Bitmap(IconCache.TryGetFromCache(name).Image))
9854                     {
9855                         using (Bitmap bmp2 = new Bitmap(orgBmp.Size.Width, orgBmp.Size.Height))
9856                         {
9857                             using (Graphics g = Graphics.FromImage(bmp2))
9858                             {
9859                                 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
9860                                 g.DrawImage(orgBmp, 0, 0, orgBmp.Size.Width, orgBmp.Size.Height);
9861                             }
9862                             bmp2.Save(this.SaveFileDialog1.FileName);
9863                         }
9864                     }
9865                 }
9866                 catch (Exception)
9867                 {
9868                     //処理中にキャッシュアウトする可能性あり
9869                 }
9870             }
9871         }
9872
9873         private void SplitContainer2_Panel2_Resize(object sender, EventArgs e)
9874         {
9875             this.StatusText.Multiline = this.SplitContainer2.Panel2.Height > this.SplitContainer2.Panel2MinSize + 2;
9876             MultiLineMenuItem.Checked = this.StatusText.Multiline;
9877             _modifySettingLocal = true;
9878         }
9879
9880         private void StatusText_MultilineChanged(object sender, EventArgs e)
9881         {
9882             if (this.StatusText.Multiline)
9883                 this.StatusText.ScrollBars = ScrollBars.Vertical;
9884             else
9885                 this.StatusText.ScrollBars = ScrollBars.None;
9886
9887             _modifySettingLocal = true;
9888         }
9889
9890         private void MultiLineMenuItem_Click(object sender, EventArgs e)
9891         {
9892             //発言欄複数行
9893             StatusText.Multiline = MultiLineMenuItem.Checked;
9894             _cfgLocal.StatusMultiline = MultiLineMenuItem.Checked;
9895             if (MultiLineMenuItem.Checked)
9896             {
9897                 if (SplitContainer2.Height - _mySpDis2 - SplitContainer2.SplitterWidth < 0)
9898                     SplitContainer2.SplitterDistance = 0;
9899                 else
9900                     SplitContainer2.SplitterDistance = SplitContainer2.Height - _mySpDis2 - SplitContainer2.SplitterWidth;
9901             }
9902             else
9903             {
9904                 SplitContainer2.SplitterDistance = SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth;
9905             }
9906             _modifySettingLocal = true;
9907         }
9908
9909         private bool UrlConvert(MyCommon.UrlConverter Converter_Type)
9910         {
9911             //t.coで投稿時自動短縮する場合は、外部サービスでの短縮禁止
9912             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco) return;
9913
9914             //Converter_Type=Nicomsの場合は、nicovideoのみ短縮する
9915             //参考資料 RFC3986 Uniform Resource Identifier (URI): Generic Syntax
9916             //Appendix A.  Collected ABNF for URI
9917             //http://www.ietf.org/rfc/rfc3986.txt
9918
9919             string result = "";
9920
9921             const string nico = @"^https?://[a-z]+\.(nicovideo|niconicommons|nicolive)\.jp/[a-z]+/[a-z0-9]+$";
9922
9923             if (StatusText.SelectionLength > 0)
9924             {
9925                 string tmp = StatusText.SelectedText;
9926                 // httpから始まらない場合、ExcludeStringで指定された文字列で始まる場合は対象としない
9927                 if (tmp.StartsWith("http"))
9928                 {
9929                     // 文字列が選択されている場合はその文字列について処理
9930
9931                     //nico.ms使用、nicovideoにマッチしたら変換
9932                     if (SettingDialog.Nicoms && Regex.IsMatch(tmp, nico))
9933                     {
9934                         result = nicoms.Shorten(tmp);
9935                     }
9936                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
9937                     {
9938                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
9939                         result = ShortUrl.Make(Converter_Type, tmp);
9940                         if (result.Equals("Can't convert"))
9941                         {
9942                             StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
9943                             return false;
9944                         }
9945                     }
9946                     else
9947                     {
9948                         return true;
9949                     }
9950
9951                     if (!string.IsNullOrEmpty(result))
9952                     {
9953                         urlUndo undotmp = new urlUndo();
9954
9955                         StatusText.Select(StatusText.Text.IndexOf(tmp, StringComparison.Ordinal), tmp.Length);
9956                         StatusText.SelectedText = result;
9957
9958                         //undoバッファにセット
9959                         undotmp.Before = tmp;
9960                         undotmp.After = result;
9961
9962                         if (urlUndoBuffer == null)
9963                         {
9964                             urlUndoBuffer = new List<urlUndo>();
9965                             UrlUndoToolStripMenuItem.Enabled = true;
9966                         }
9967
9968                         urlUndoBuffer.Add(undotmp);
9969                     }
9970                 }
9971             }
9972             else
9973             {
9974                 const string url = @"(?<before>(?:[^\""':!=]|^|\:))" +
9975                                    @"(?<url>(?<protocol>https?://)" +
9976                                    @"(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" +
9977                                    @"(?<path>/[a-z0-9!*//();:&=+$/%#\-_.,~@]*[a-z0-9)=#/]?)?" +
9978                                    @"(?<query>\?[a-z0-9!*//();:&=+$/%#\-_.,~@?]*[a-z0-9_&=#/])?)";
9979                 // 正規表現にマッチしたURL文字列をtinyurl化
9980                 foreach (Match mt in Regex.Matches(StatusText.Text, url, RegexOptions.IgnoreCase))
9981                 {
9982                     if (StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal) == -1) continue;
9983                     string tmp = mt.Result("${url}");
9984                     if (tmp.StartsWith("w", StringComparison.OrdinalIgnoreCase)) tmp = "http://" + tmp;
9985                     urlUndo undotmp = new urlUndo();
9986
9987                     //選んだURLを選択(?)
9988                     StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
9989
9990                     //nico.ms使用、nicovideoにマッチしたら変換
9991                     if (SettingDialog.Nicoms && Regex.IsMatch(tmp, nico))
9992                     {
9993                         result = nicoms.Shorten(tmp);
9994                     }
9995                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
9996                     {
9997                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
9998                         result = ShortUrl.Make(Converter_Type, tmp);
9999                         if (result.Equals("Can't convert"))
10000                         {
10001                             StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
10002                             continue;
10003                         }
10004                     }
10005                     else
10006                     {
10007                         continue;
10008                     }
10009
10010                     if (!string.IsNullOrEmpty(result))
10011                     {
10012                         StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
10013                         StatusText.SelectedText = result;
10014                         //undoバッファにセット
10015                         undotmp.Before = mt.Result("${url}");
10016                         undotmp.After = result;
10017
10018                         if (urlUndoBuffer == null)
10019                         {
10020                             urlUndoBuffer = new List<urlUndo>();
10021                             UrlUndoToolStripMenuItem.Enabled = true;
10022                         }
10023
10024                         urlUndoBuffer.Add(undotmp);
10025                     }
10026                 }
10027             }
10028
10029             return true;
10030         }
10031
10032         private void doUrlUndo()
10033         {
10034             if (urlUndoBuffer != null)
10035             {
10036                 string tmp = StatusText.Text;
10037                 foreach (urlUndo data in urlUndoBuffer)
10038                 {
10039                     tmp = tmp.Replace(data.After, data.Before);
10040                 }
10041                 StatusText.Text = tmp;
10042                 urlUndoBuffer = null;
10043                 UrlUndoToolStripMenuItem.Enabled = false;
10044                 StatusText.SelectionStart = 0;
10045                 StatusText.SelectionLength = 0;
10046             }
10047         }
10048
10049         private void TinyURLToolStripMenuItem_Click(object sender, EventArgs e)
10050         {
10051             UrlConvert(MyCommon.UrlConverter.TinyUrl);
10052         }
10053
10054         private void IsgdToolStripMenuItem_Click(object sender, EventArgs e)
10055         {
10056             UrlConvert(MyCommon.UrlConverter.Isgd);
10057         }
10058
10059         private void TwurlnlToolStripMenuItem_Click(object sender, EventArgs e)
10060         {
10061             UrlConvert(MyCommon.UrlConverter.Twurl);
10062         }
10063
10064         private void UxnuMenuItem_Click(object sender, EventArgs e)
10065         {
10066             UrlConvert(MyCommon.UrlConverter.Uxnu);
10067         }
10068
10069         private void UrlConvertAutoToolStripMenuItem_Click(object sender, EventArgs e) 
10070         {
10071             if (!UrlConvert(SettingDialog.AutoShortUrlFirst))
10072             {
10073                 MyCommon.UrlConverter svc = SettingDialog.AutoShortUrlFirst;
10074                 Random rnd = new Random();
10075                 // 前回使用した短縮URLサービス以外を選択する
10076                 do
10077                 {
10078                     svc = (MyCommon.UrlConverter)rnd.Next(System.Enum.GetNames(typeof(MyCommon.UrlConverter)).Length);
10079                 }
10080                 while (svc == SettingDialog.AutoShortUrlFirst || svc == MyCommon.UrlConverter.Nicoms || svc == MyCommon.UrlConverter.Unu);
10081                 UrlConvert(svc);
10082             }
10083         }
10084
10085         private void UrlUndoToolStripMenuItem_Click(object sender, EventArgs e)
10086         {
10087             doUrlUndo();
10088         }
10089
10090         private void NewPostPopMenuItem_CheckStateChanged(object sender, EventArgs e)
10091         {
10092             this.NotifyFileMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
10093             this.NewPostPopMenuItem.Checked = this.NotifyFileMenuItem.Checked;
10094             _cfgCommon.NewAllPop = NewPostPopMenuItem.Checked;
10095             _modifySettingCommon = true;
10096         }
10097
10098         private void ListLockMenuItem_CheckStateChanged(object sender, EventArgs e)
10099         {
10100             ListLockMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
10101             this.LockListFileMenuItem.Checked = ListLockMenuItem.Checked;
10102             _cfgCommon.ListLock = ListLockMenuItem.Checked;
10103             _modifySettingCommon = true;
10104         }
10105
10106         private void MenuStrip1_MenuActivate(object sender, EventArgs e)
10107         {
10108             // フォーカスがメニューに移る (MenuStrip1.Tag フラグを立てる)
10109             MenuStrip1.Tag = new Object();
10110             MenuStrip1.Select(); // StatusText がフォーカスを持っている場合 Leave が発生
10111         }
10112
10113         private void MenuStrip1_MenuDeactivate(object sender, EventArgs e)
10114         {
10115             if (this.Tag != null) // 設定された戻り先へ遷移
10116             {
10117                 if (this.Tag == this.ListTab.SelectedTab)
10118                     ((Control)this.ListTab.SelectedTab.Tag).Select();
10119                 else
10120                     ((Control)this.Tag).Select();
10121             }
10122             else // 戻り先が指定されていない (初期状態) 場合はタブに遷移
10123             {
10124                 if (ListTab.SelectedIndex > -1 && ListTab.SelectedTab.HasChildren)
10125                 {
10126                     this.Tag = ListTab.SelectedTab.Tag;
10127                     ((Control)this.Tag).Select();
10128                 }
10129             }
10130             // フォーカスがメニューに遷移したかどうかを表すフラグを降ろす
10131             MenuStrip1.Tag = null;
10132         }
10133
10134         private void MyList_ColumnReordered(object sender, ColumnReorderedEventArgs e)
10135         {
10136             DetailsListView lst = (DetailsListView)sender;
10137             if (_cfgLocal == null) return;
10138
10139             if (_iconCol)
10140             {
10141                 _cfgLocal.Width1 = lst.Columns[0].Width;
10142                 _cfgLocal.Width3 = lst.Columns[1].Width;
10143             }
10144             else
10145             {
10146                 int[] darr = new int[lst.Columns.Count];
10147                 for (int i = 0; i < lst.Columns.Count; i++)
10148                 {
10149                     darr[lst.Columns[i].DisplayIndex] = i;
10150                 }
10151                 MyCommon.MoveArrayItem(darr, e.OldDisplayIndex, e.NewDisplayIndex);
10152
10153                 for (int i = 0; i < lst.Columns.Count; i++)
10154                 {
10155                     switch (darr[i])
10156                     {
10157                         case 0:
10158                             _cfgLocal.DisplayIndex1 = i;
10159                             break;
10160                         case 1:
10161                             _cfgLocal.DisplayIndex2 = i;
10162                             break;
10163                         case 2:
10164                             _cfgLocal.DisplayIndex3 = i;
10165                             break;
10166                         case 3:
10167                             _cfgLocal.DisplayIndex4 = i;
10168                             break;
10169                         case 4:
10170                             _cfgLocal.DisplayIndex5 = i;
10171                             break;
10172                         case 5:
10173                             _cfgLocal.DisplayIndex6 = i;
10174                             break;
10175                         case 6:
10176                             _cfgLocal.DisplayIndex7 = i;
10177                             break;
10178                         case 7:
10179                             _cfgLocal.DisplayIndex8 = i;
10180                             break;
10181                     }
10182                 }
10183                 _cfgLocal.Width1 = lst.Columns[0].Width;
10184                 _cfgLocal.Width2 = lst.Columns[1].Width;
10185                 _cfgLocal.Width3 = lst.Columns[2].Width;
10186                 _cfgLocal.Width4 = lst.Columns[3].Width;
10187                 _cfgLocal.Width5 = lst.Columns[4].Width;
10188                 _cfgLocal.Width6 = lst.Columns[5].Width;
10189                 _cfgLocal.Width7 = lst.Columns[6].Width;
10190                 _cfgLocal.Width8 = lst.Columns[7].Width;
10191             }
10192             _modifySettingLocal = true;
10193             _isColumnChanged = true;
10194         }
10195
10196         private void MyList_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
10197         {
10198             DetailsListView lst = (DetailsListView)sender;
10199             if (_cfgLocal == null) return;
10200             if (_iconCol)
10201             {
10202                 if (_cfgLocal.Width1 != lst.Columns[0].Width)
10203                 {
10204                     _cfgLocal.Width1 = lst.Columns[0].Width;
10205                     _modifySettingLocal = true;
10206                     _isColumnChanged = true;
10207                 }
10208                 if (_cfgLocal.Width3 != lst.Columns[1].Width)
10209                 {
10210                     _cfgLocal.Width3 = lst.Columns[1].Width;
10211                     _modifySettingLocal = true;
10212                     _isColumnChanged = true;
10213                 }
10214             }
10215             else
10216             {
10217                 if (_cfgLocal.Width1 != lst.Columns[0].Width)
10218                 {
10219                     _cfgLocal.Width1 = lst.Columns[0].Width;
10220                     _modifySettingLocal = true;
10221                     _isColumnChanged = true;
10222                 }
10223                 if (_cfgLocal.Width2 != lst.Columns[1].Width)
10224                 {
10225                     _cfgLocal.Width2 = lst.Columns[1].Width;
10226                     _modifySettingLocal = true;
10227                     _isColumnChanged = true;
10228                 }
10229                 if (_cfgLocal.Width3 != lst.Columns[2].Width)
10230                 {
10231                     _cfgLocal.Width3 = lst.Columns[2].Width;
10232                     _modifySettingLocal = true;
10233                     _isColumnChanged = true;
10234                 }
10235                 if (_cfgLocal.Width4 != lst.Columns[3].Width)
10236                 {
10237                     _cfgLocal.Width4 = lst.Columns[3].Width;
10238                     _modifySettingLocal = true;
10239                     _isColumnChanged = true;
10240                 }
10241                 if (_cfgLocal.Width5 != lst.Columns[4].Width)
10242                 {
10243                     _cfgLocal.Width5 = lst.Columns[4].Width;
10244                     _modifySettingLocal = true;
10245                     _isColumnChanged = true;
10246                 }
10247                 if (_cfgLocal.Width6 != lst.Columns[5].Width)
10248                 {
10249                     _cfgLocal.Width6 = lst.Columns[5].Width;
10250                     _modifySettingLocal = true;
10251                     _isColumnChanged = true;
10252                 }
10253                 if (_cfgLocal.Width7 != lst.Columns[6].Width)
10254                 {
10255                     _cfgLocal.Width7 = lst.Columns[6].Width;
10256                     _modifySettingLocal = true;
10257                     _isColumnChanged = true;
10258                 }
10259                 if (_cfgLocal.Width8 != lst.Columns[7].Width)
10260                 {
10261                     _cfgLocal.Width8 = lst.Columns[7].Width;
10262                     _modifySettingLocal = true;
10263                     _isColumnChanged = true;
10264                 }
10265             }
10266             // 非表示の時にColumnChangedが呼ばれた場合はForm初期化処理中なので保存しない
10267             //if (changed)
10268             //{
10269             //    SaveConfigsLocal();
10270             //}
10271         }
10272
10273         public string WebBrowser_GetSelectionText(ref WebBrowser ComponentInstance)
10274         {
10275             //発言詳細で「選択文字列をコピー」を行う
10276             //WebBrowserコンポーネントのインスタンスを渡す
10277             Type typ = ComponentInstance.ActiveXInstance.GetType();
10278             object _SelObj = typ.InvokeMember("selection", BindingFlags.GetProperty, null, ComponentInstance.Document.DomDocument, null);
10279             object _objRange = _SelObj.GetType().InvokeMember("createRange", BindingFlags.InvokeMethod, null, _SelObj, null);
10280             return (string)_objRange.GetType().InvokeMember("text", BindingFlags.GetProperty, null, _objRange, null);
10281         }
10282
10283         private void SelectionCopyContextMenuItem_Click(object sender, EventArgs e)
10284         {
10285             //発言詳細で「選択文字列をコピー」
10286             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10287             try
10288             {
10289                 Clipboard.SetDataObject(_selText, false, 5, 100);
10290             }
10291             catch (Exception ex)
10292             {
10293                 MessageBox.Show(ex.Message);
10294             }
10295         }
10296
10297         private void doSearchToolStrip(string url)
10298         {
10299             //発言詳細で「選択文字列で検索」(選択文字列取得)
10300             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10301
10302             if (_selText != null)
10303             {
10304                 if (url == Properties.Resources.SearchItem4Url)
10305                 {
10306                     //公式検索
10307                     AddNewTabForSearch(_selText);
10308                     return;
10309                 }
10310
10311                 string tmp = string.Format(url, Uri.EscapeUriString(_selText));
10312                 OpenUriAsync(tmp);
10313             }
10314         }
10315
10316         private void SelectionAllContextMenuItem_Click(object sender, EventArgs e)
10317         {
10318             //発言詳細ですべて選択
10319             PostBrowser.Document.ExecCommand("SelectAll", false, null);
10320         }
10321
10322         private void SearchWikipediaContextMenuItem_Click(object sender, EventArgs e)
10323         {
10324             doSearchToolStrip(Properties.Resources.SearchItem1Url);
10325         }
10326
10327         private void SearchGoogleContextMenuItem_Click(object sender, EventArgs e)
10328         {
10329             doSearchToolStrip(Properties.Resources.SearchItem2Url);
10330         }
10331
10332         private void SearchPublicSearchContextMenuItem_Click(object sender, EventArgs e)
10333         {
10334             doSearchToolStrip(Properties.Resources.SearchItem4Url);
10335         }
10336
10337         private void UrlCopyContextMenuItem_Click(object sender, EventArgs e)
10338         {
10339             try
10340             {
10341                 MatchCollection mc = Regex.Matches(this.PostBrowser.DocumentText, @"<a[^>]*href=""(?<url>" + this._postBrowserStatusText.Replace(".", @"\.") + @")""[^>]*title=""(?<title>https?://[^""]+)""", RegexOptions.IgnoreCase);
10342                 foreach (Match m in mc)
10343                 {
10344                     if (m.Groups["url"].Value == this._postBrowserStatusText)
10345                     {
10346                         Clipboard.SetDataObject(m.Groups["title"].Value, false, 5, 100);
10347                         break;
10348                     }
10349                 }
10350                 if (mc.Count == 0)
10351                 {
10352                     Clipboard.SetDataObject(this._postBrowserStatusText, false, 5, 100);
10353                 }
10354                 //Clipboard.SetDataObject(this._postBrowserStatusText, false, 5, 100);
10355             }
10356             catch (Exception ex)
10357             {
10358                 MessageBox.Show(ex.Message);
10359             }
10360         }
10361
10362         private void ContextMenuPostBrowser_Opening(object ender, CancelEventArgs e)
10363         {
10364             // URLコピーの項目の表示/非表示
10365             if (PostBrowser.StatusText.StartsWith("http"))
10366             {
10367                 this._postBrowserStatusText = PostBrowser.StatusText;
10368                 string name = GetUserId();
10369                 UrlCopyContextMenuItem.Enabled = true;
10370                 if (name != null)
10371                 {
10372                     FollowContextMenuItem.Enabled = true;
10373                     RemoveContextMenuItem.Enabled = true;
10374                     FriendshipContextMenuItem.Enabled = true;
10375                     ShowUserStatusContextMenuItem.Enabled = true;
10376                     SearchPostsDetailToolStripMenuItem.Enabled = true;
10377                     IdFilterAddMenuItem.Enabled = true;
10378                     ListManageUserContextToolStripMenuItem.Enabled = true;
10379                     SearchAtPostsDetailToolStripMenuItem.Enabled = true;
10380                 }
10381                 else
10382                 {
10383                     FollowContextMenuItem.Enabled = false;
10384                     RemoveContextMenuItem.Enabled = false;
10385                     FriendshipContextMenuItem.Enabled = false;
10386                     ShowUserStatusContextMenuItem.Enabled = false;
10387                     SearchPostsDetailToolStripMenuItem.Enabled = false;
10388                     IdFilterAddMenuItem.Enabled = false;
10389                     ListManageUserContextToolStripMenuItem.Enabled = false;
10390                     SearchAtPostsDetailToolStripMenuItem.Enabled = false;
10391                 }
10392
10393                 if (Regex.IsMatch(this._postBrowserStatusText, @"^https?://twitter.com/search\?q=%23"))
10394                     UseHashtagMenuItem.Enabled = true;
10395                 else
10396                     UseHashtagMenuItem.Enabled = false;
10397             }
10398             else
10399             {
10400                 this._postBrowserStatusText = "";
10401                 UrlCopyContextMenuItem.Enabled = false;
10402                 FollowContextMenuItem.Enabled = false;
10403                 RemoveContextMenuItem.Enabled = false;
10404                 FriendshipContextMenuItem.Enabled = false;
10405                 ShowUserStatusContextMenuItem.Enabled = false;
10406                 SearchPostsDetailToolStripMenuItem.Enabled = false;
10407                 SearchAtPostsDetailToolStripMenuItem.Enabled = false;
10408                 UseHashtagMenuItem.Enabled = false;
10409                 IdFilterAddMenuItem.Enabled = false;
10410                 ListManageUserContextToolStripMenuItem.Enabled = false;
10411             }
10412             // 文字列選択されていないときは選択文字列関係の項目を非表示に
10413             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10414             if (_selText == null)
10415             {
10416                 SelectionSearchContextMenuItem.Enabled = false;
10417                 SelectionCopyContextMenuItem.Enabled = false;
10418                 SelectionTranslationToolStripMenuItem.Enabled = false;
10419             }
10420             else
10421             {
10422                 SelectionSearchContextMenuItem.Enabled = true;
10423                 SelectionCopyContextMenuItem.Enabled = true;
10424                 SelectionTranslationToolStripMenuItem.Enabled = true;
10425             }
10426             //発言内に自分以外のユーザーが含まれてればフォロー状態全表示を有効に
10427             MatchCollection ma = Regex.Matches(this.PostBrowser.DocumentText, @"href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?""");
10428             bool fAllFlag = false;
10429             foreach (Match mu in ma)
10430             {
10431                 if (mu.Result("${ScreenName}").ToLower() != tw.Username.ToLower())
10432                 {
10433                     fAllFlag = true;
10434                     break;
10435                 }
10436             }
10437             this.FriendshipAllMenuItem.Enabled = fAllFlag;
10438
10439             if (_curPost == null)
10440                 TranslationToolStripMenuItem.Enabled = false;
10441             else
10442                 TranslationToolStripMenuItem.Enabled = true;
10443
10444             e.Cancel = false;
10445         }
10446
10447         private void CurrentTabToolStripMenuItem_Click(object sender, EventArgs e)
10448         {
10449             //発言詳細の選択文字列で現在のタブを検索
10450             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10451
10452             if (_selText != null)
10453             {
10454                 SearchDialog.SWord = _selText;
10455                 SearchDialog.CheckCaseSensitive = false;
10456                 SearchDialog.CheckRegex = false;
10457
10458                 DoTabSearch(SearchDialog.SWord,
10459                             SearchDialog.CheckCaseSensitive,
10460                             SearchDialog.CheckRegex,
10461                             SEARCHTYPE.NextSearch);
10462             }
10463         }
10464
10465         private void SplitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
10466         {
10467             if (StatusText.Multiline) _mySpDis2 = StatusText.Height;
10468             _modifySettingLocal = true;
10469         }
10470
10471         private void TweenMain_DragDrop(object sender, DragEventArgs e)
10472         {
10473             if (e.Data.GetDataPresent(DataFormats.FileDrop))
10474             {
10475                 ImageSelectionPanel.Visible = true;
10476                 ImageSelectionPanel.Enabled = true;
10477                 TimelinePanel.Visible = false;
10478                 TimelinePanel.Enabled = false;
10479                 ImagefilePathText.Text = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
10480                 ImageFromSelectedFile();
10481                 this.Activate();
10482                 this.BringToFront();
10483                 StatusText.Focus();
10484             }
10485             else if (e.Data.GetDataPresent("UniformResourceLocatorW"))
10486             {
10487                 var url = GetUrlFromDataObject(e.Data);
10488
10489                 string appendText;
10490                 if (url.Item2 == null)
10491                     appendText = url.Item1;
10492                 else
10493                     appendText = url.Item2 + " " + url.Item1;
10494
10495                 if (this.StatusText.TextLength == 0)
10496                     this.StatusText.Text = appendText;
10497                 else
10498                     this.StatusText.Text += " " + appendText;
10499             }
10500             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
10501             {
10502                 string data = (string)e.Data.GetData(DataFormats.StringFormat, true);
10503                 if (data != null) StatusText.Text += data;
10504             }
10505         }
10506
10507         /// <summary>
10508         /// IDataObject から URL とタイトルの対を取得します
10509         /// </summary>
10510         /// <remarks>
10511         /// タイトルのみ取得できなかった場合は Value2 が null のタプルを返すことがあります。
10512         /// </remarks>
10513         /// <exception cref="ArgumentException">不正なフォーマットが入力された場合</exception>
10514         /// <exception cref="NotSupportedException">サポートされていないデータが入力された場合</exception>
10515         internal static Tuple<string, string> GetUrlFromDataObject(IDataObject data)
10516         {
10517             if (data.GetDataPresent("text/x-moz-url"))
10518             {
10519                 // Firefox, Google Chrome で利用可能
10520                 // 参照: https://developer.mozilla.org/ja/docs/DragDrop/Recommended_Drag_Types
10521
10522                 using (var stream = (MemoryStream)data.GetData("text/x-moz-url"))
10523                 {
10524                     var lines = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0').Split('\n');
10525                     if (lines.Length < 2)
10526                         throw new ArgumentException("不正な text/x-moz-url フォーマットです", "data");
10527
10528                     return new Tuple<string, string>(lines[0], lines[1]);
10529                 }
10530             }
10531             else if (data.GetDataPresent("IESiteModeToUrl"))
10532             {
10533                 // Internet Exproler 用
10534                 // 保護モードが有効なデフォルトの IE では DragDrop イベントが発火しないため使えない
10535
10536                 using (var stream = (MemoryStream)data.GetData("IESiteModeToUrl"))
10537                 {
10538                     var lines = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0').Split('\0');
10539                     if (lines.Length < 2)
10540                         throw new ArgumentException("不正な IESiteModeToUrl フォーマットです", "data");
10541
10542                     return new Tuple<string, string>(lines[0], lines[1]);
10543                 }
10544             }
10545             else if (data.GetDataPresent("UniformResourceLocatorW"))
10546             {
10547                 // それ以外のブラウザ向け
10548
10549                 using (var stream = (MemoryStream)data.GetData("UniformResourceLocatorW"))
10550                 {
10551                     var url = Encoding.Unicode.GetString(stream.ToArray()).TrimEnd('\0');
10552                     return new Tuple<string, string>(url, null);
10553                 }
10554             }
10555
10556             throw new NotSupportedException("サポートされていないデータ形式です: " + data.GetFormats()[0]);
10557         }
10558
10559         private void TweenMain_DragOver(object sender, DragEventArgs e)
10560         {
10561             if (e.Data.GetDataPresent(DataFormats.FileDrop))
10562             {
10563                 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
10564                 FileInfo fl = new FileInfo(filename);
10565                 string ext = fl.Extension;
10566
10567                 if (!string.IsNullOrEmpty(this.ImageService) && this.pictureService[this.ImageService].CheckValidFilesize(ext, fl.Length))
10568                 {
10569                     e.Effect = DragDropEffects.Copy;
10570                     return;
10571                 }
10572                 foreach (string svc in ImageServiceCombo.Items)
10573                 {
10574                     if (string.IsNullOrEmpty(svc)) continue;
10575                     if (this.pictureService[svc].CheckValidFilesize(ext, fl.Length))
10576                     {
10577                         ImageServiceCombo.SelectedItem = svc;
10578                         e.Effect = DragDropEffects.Copy;
10579                         return;
10580                     }
10581                 }
10582                 e.Effect = DragDropEffects.None;
10583             }
10584             else if (e.Data.GetDataPresent("UniformResourceLocatorW"))
10585             {
10586                 e.Effect = DragDropEffects.Copy;
10587             }
10588             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
10589             {
10590                 e.Effect = DragDropEffects.Copy;
10591             }
10592             else
10593             {
10594                 e.Effect = DragDropEffects.None;
10595             }
10596         }
10597
10598         public bool IsNetworkAvailable()
10599         {
10600             bool nw = true;
10601             nw = MyCommon.IsNetworkAvailable();
10602             _myStatusOnline = nw;
10603             return nw;
10604         }
10605
10606         public Task OpenUriAsync(string UriString)
10607         {
10608             return Task.Factory.StartNew(() =>
10609             {
10610                 string myPath = UriString;
10611
10612                 try
10613                 {
10614                     var configBrowserPath = SettingDialog.BrowserPath;
10615                     if (!string.IsNullOrEmpty(configBrowserPath))
10616                     {
10617                         if (configBrowserPath.StartsWith("\"") && configBrowserPath.Length > 2 && configBrowserPath.IndexOf("\"", 2) > -1)
10618                         {
10619                             int sep = configBrowserPath.IndexOf("\"", 2);
10620                             string browserPath = configBrowserPath.Substring(1, sep - 1);
10621                             string arg = "";
10622                             if (sep < configBrowserPath.Length - 1)
10623                             {
10624                                 arg = configBrowserPath.Substring(sep + 1);
10625                             }
10626                             myPath = arg + " " + myPath;
10627                             System.Diagnostics.Process.Start(browserPath, myPath);
10628                         }
10629                         else
10630                         {
10631                             System.Diagnostics.Process.Start(configBrowserPath, myPath);
10632                         }
10633                     }
10634                     else
10635                     {
10636                         System.Diagnostics.Process.Start(myPath);
10637                     }
10638                 }
10639                 catch (Exception)
10640                 {
10641                     //MessageBox.Show("ブラウザの起動に失敗、またはタイムアウトしました。" + ex.ToString());
10642                 }
10643             });
10644         }
10645
10646         private void ListTabSelect(TabPage _tab)
10647         {
10648             SetListProperty();
10649
10650             this.PurgeListViewItemCache();
10651
10652             _curTab = _tab;
10653             _curList = (DetailsListView)_tab.Tag;
10654             if (_curList.SelectedIndices.Count > 0)
10655             {
10656                 _curItemIndex = _curList.SelectedIndices[0];
10657                 _curPost = GetCurTabPost(_curItemIndex);
10658             }
10659             else
10660             {
10661                 _curItemIndex = -1;
10662                 _curPost = null;
10663             }
10664
10665             _anchorPost = null;
10666             _anchorFlag = false;
10667
10668             if (_iconCol)
10669             {
10670                 ((DetailsListView)_tab.Tag).Columns[1].Text = ColumnText[2];
10671             }
10672             else
10673             {
10674                 for (int i = 0; i < _curList.Columns.Count; i++)
10675                 {
10676                     ((DetailsListView)_tab.Tag).Columns[i].Text = ColumnText[i];
10677                 }
10678             }
10679         }
10680
10681         private void ListTab_Selecting(object sender, TabControlCancelEventArgs e)
10682         {
10683             ListTabSelect(e.TabPage);
10684         }
10685
10686         private void SelectListItem(DetailsListView LView, int Index)
10687         {
10688             //単一
10689             Rectangle bnd = new Rectangle();
10690             bool flg = false;
10691             if (LView.FocusedItem != null)
10692             {
10693                 bnd = LView.FocusedItem.Bounds;
10694                 flg = true;
10695             }
10696
10697             do
10698             {
10699                 LView.SelectedIndices.Clear();
10700             }
10701             while (LView.SelectedIndices.Count > 0);
10702             LView.Items[Index].Selected = true;
10703             //LView.SelectedIndices.Add(Index);
10704             LView.Items[Index].Focused = true;
10705
10706             if (flg) LView.Invalidate(bnd);
10707         }
10708
10709         private void SelectListItem(DetailsListView LView , int[] Index, int FocusedIndex)
10710         {
10711             //複数
10712             Rectangle bnd = new Rectangle();
10713             bool flg = false;
10714             if (LView.FocusedItem != null)
10715             {
10716                 bnd = LView.FocusedItem.Bounds;
10717                 flg = true;
10718             }
10719
10720             int fIdx = -1;
10721             if (Index != null && !(Index.Length == 1 && Index[0] == -1))
10722             {
10723                 do
10724                 {
10725                     LView.SelectedIndices.Clear();
10726                 }
10727                 while (LView.SelectedIndices.Count > 0);
10728                 foreach (int idx in Index)
10729                 {
10730                     if (idx > -1 && LView.VirtualListSize > idx)
10731                     {
10732                         LView.SelectedIndices.Add(idx);
10733                         if (fIdx == -1) fIdx = idx;
10734                     }
10735                 }
10736             }
10737             if (FocusedIndex > -1 && LView.VirtualListSize > FocusedIndex)
10738             {
10739                 LView.Items[FocusedIndex].Focused = true;
10740             }
10741             else if (fIdx > -1)
10742             {
10743                 LView.Items[fIdx].Focused = true;
10744             }
10745             if (flg) LView.Invalidate(bnd);
10746         }
10747
10748         private void RunAsync(GetWorkerArg args)
10749         {
10750             BackgroundWorker bw = null;
10751             if (args.type != MyCommon.WORKERTYPE.Follower)
10752             {
10753                 for (int i = 0; i < _bw.Length; i++)
10754                 {
10755                     if (_bw[i] != null && !_bw[i].IsBusy)
10756                     {
10757                         bw = _bw[i];
10758                         break;
10759                     }
10760                 }
10761                 if (bw == null)
10762                 {
10763                     for (int i = 0; i < _bw.Length; i++)
10764                     {
10765                         if (_bw[i] == null)
10766                         {
10767                             _bw[i] = new BackgroundWorker();
10768                             bw = _bw[i];
10769                             bw.WorkerReportsProgress = true;
10770                             bw.WorkerSupportsCancellation = true;
10771                             bw.DoWork += GetTimelineWorker_DoWork;
10772                             bw.ProgressChanged += GetTimelineWorker_ProgressChanged;
10773                             bw.RunWorkerCompleted += GetTimelineWorker_RunWorkerCompleted;
10774                             break;
10775                         }
10776                     }
10777                 }
10778             }
10779             else
10780             {
10781                 if (_bwFollower == null)
10782                 {
10783                     _bwFollower = new BackgroundWorker();
10784                     bw = _bwFollower;
10785                     bw.WorkerReportsProgress = true;
10786                     bw.WorkerSupportsCancellation = true;
10787                     bw.DoWork += GetTimelineWorker_DoWork;
10788                     bw.ProgressChanged += GetTimelineWorker_ProgressChanged;
10789                     bw.RunWorkerCompleted += GetTimelineWorker_RunWorkerCompleted;
10790                 }
10791                 else
10792                 {
10793                     if (_bwFollower.IsBusy == false)
10794                         bw = _bwFollower;
10795                 }
10796             }
10797             if (bw == null) return;
10798
10799             bw.RunWorkerAsync(args);
10800         }
10801
10802         private void StartUserStream()
10803         {
10804             tw.NewPostFromStream += tw_NewPostFromStream;
10805             tw.UserStreamStarted += tw_UserStreamStarted;
10806             tw.UserStreamStopped += tw_UserStreamStopped;
10807             tw.PostDeleted += tw_PostDeleted;
10808             tw.UserStreamEventReceived += tw_UserStreamEventArrived;
10809
10810             MenuItemUserStream.Text = "&UserStream ■";
10811             MenuItemUserStream.Enabled = true;
10812             StopToolStripMenuItem.Text = "&Start";
10813             StopToolStripMenuItem.Enabled = true;
10814             if (SettingDialog.UserstreamStartup) tw.StartUserStream();
10815         }
10816
10817         private void TweenMain_Shown(object sender, EventArgs e)
10818         {
10819             try
10820             {
10821                 PostBrowser.Url = new Uri("about:blank");
10822                 PostBrowser.DocumentText = "";       //発言詳細部初期化
10823             }
10824             catch (Exception)
10825             {
10826             }
10827
10828             NotifyIcon1.Visible = true;
10829
10830             if (this.IsNetworkAvailable())
10831             {
10832                 GetTimeline(MyCommon.WORKERTYPE.BlockIds, 0, 0, "");
10833                 GetTimeline(MyCommon.WORKERTYPE.NoRetweetIds, 0, 0, "");
10834                 if (SettingDialog.StartupFollowers)
10835                 {
10836                     GetTimeline(MyCommon.WORKERTYPE.Follower, 0, 0, "");
10837                 }
10838                 GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
10839                 StartUserStream();
10840                 _waitTimeline = true;
10841                 GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 1, "");
10842                 _waitReply = true;
10843                 GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 1, "");
10844                 _waitDm = true;
10845                 GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 1, "");
10846                 if (SettingDialog.GetFav)
10847                 {
10848                     _waitFav = true;
10849                     GetTimeline(MyCommon.WORKERTYPE.Favorites, 1, 1, "");
10850                 }
10851                 _waitPubSearch = true;
10852                 GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");  //tabname="":全タブ
10853                 _waitUserTimeline = true;
10854                 GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");  //tabname="":全タブ
10855                 _waitLists = true;
10856                 GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");  //tabname="":全タブ
10857                 int i = 0;
10858                 int j = 0;
10859                 while (IsInitialRead() && !MyCommon._endingFlag)
10860                 {
10861                     System.Threading.Thread.Sleep(100);
10862                     Application.DoEvents();
10863                     i += 1;
10864                     j += 1;
10865                     if (j > 1200) break; // 120秒間初期処理が終了しなかったら強制的に打ち切る
10866                     if (i > 50)
10867                     {
10868                         if (MyCommon._endingFlag)
10869                             return;
10870                         i = 0;
10871                     }
10872                 }
10873
10874                 if (MyCommon._endingFlag) return;
10875
10876                 if (ApplicationSettings.VersionInfoUrl != null)
10877                 {
10878                     //バージョンチェック(引数:起動時チェックの場合はtrue・・・チェック結果のメッセージを表示しない)
10879                     if (SettingDialog.StartupVersion)
10880                         CheckNewVersion(true);
10881                 }
10882                 else
10883                 {
10884                     // ApplicationSetting.cs の設定により更新チェックが無効化されている場合
10885                     this.VerUpMenuItem.Enabled = false;
10886                     this.VerUpMenuItem.Available = false;
10887                     this.ToolStripSeparator16.Available = false; // VerUpMenuItem の一つ上にあるセパレータ
10888                 }
10889
10890                 // 取得失敗の場合は再試行する
10891                 if (!tw.GetFollowersSuccess && SettingDialog.StartupFollowers)
10892                     GetTimeline(MyCommon.WORKERTYPE.Follower, 0, 0, "");
10893
10894                 // 取得失敗の場合は再試行する
10895                 if (!tw.GetNoRetweetSuccess)
10896                     GetTimeline(MyCommon.WORKERTYPE.NoRetweetIds, 0, 0, "");
10897
10898                 // 取得失敗の場合は再試行する
10899                 if (SettingDialog.TwitterConfiguration.PhotoSizeLimit == 0)
10900                     GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
10901
10902                 // 権限チェック read/write権限(xAuthで取得したトークン)の場合は再認証を促す
10903                 if (MyCommon.TwitterApiInfo.AccessLevel == TwitterApiAccessLevel.ReadWrite)
10904                 {
10905                     MessageBox.Show(Properties.Resources.ReAuthorizeText);
10906                     SettingStripMenuItem_Click(null, null);
10907                 }
10908
10909                 //
10910             }
10911             _initial = false;
10912
10913             TimerTimeline.Enabled = true;
10914         }
10915
10916         private bool IsInitialRead()
10917         {
10918             return _waitTimeline || _waitReply || _waitDm || _waitFav || _waitPubSearch || _waitUserTimeline || _waitLists;
10919         }
10920
10921         private void doGetFollowersMenu()
10922         {
10923             GetTimeline(MyCommon.WORKERTYPE.Follower, 1, 0, "");
10924             DispSelectedPost(true);
10925         }
10926
10927         private void GetFollowersAllToolStripMenuItem_Click(object sender, EventArgs e)
10928         {
10929             doGetFollowersMenu();
10930         }
10931
10932         private void doReTweetUnofficial()
10933         {
10934             //RT @id:内容
10935             if (this.ExistCurrentPost)
10936             {
10937                 if (_curPost.IsDm ||
10938                     !StatusText.Enabled) return;
10939
10940                 if (_curPost.IsProtect)
10941                 {
10942                     MessageBox.Show("Protected.");
10943                     return;
10944                 }
10945                 string rtdata = _curPost.Text;
10946                 rtdata = CreateRetweetUnofficial(rtdata, this.StatusText.Multiline);
10947
10948                 this._reply_to_id = null;
10949                 this._reply_to_name = null;
10950
10951                 StatusText.Text = "RT @" + _curPost.ScreenName + ": " + rtdata;
10952
10953                 StatusText.SelectionStart = 0;
10954                 StatusText.Focus();
10955             }
10956         }
10957
10958         private void ReTweetStripMenuItem_Click(object sender, EventArgs e)
10959         {
10960             doReTweetUnofficial();
10961         }
10962
10963         private void doReTweetOfficial(bool isConfirm)
10964         {
10965             //公式RT
10966             if (this.ExistCurrentPost)
10967             {
10968                 if (_curPost.IsProtect)
10969                 {
10970                     MessageBox.Show("Protected.");
10971                     _DoFavRetweetFlags = false;
10972                     return;
10973                 }
10974                 if (_curList.SelectedIndices.Count > 15)
10975                 {
10976                     MessageBox.Show(Properties.Resources.RetweetLimitText);
10977                     _DoFavRetweetFlags = false;
10978                     return;
10979                 }
10980                 else if (_curList.SelectedIndices.Count > 1)
10981                 {
10982                     string QuestionText = Properties.Resources.RetweetQuestion2;
10983                     if (_DoFavRetweetFlags) QuestionText = Properties.Resources.FavoriteRetweetQuestionText1;
10984                     switch (MessageBox.Show(QuestionText, "Retweet", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
10985                     {
10986                         case DialogResult.Cancel:
10987                         case DialogResult.No:
10988                             _DoFavRetweetFlags = false;
10989                             return;
10990                     }
10991                 }
10992                 else
10993                 {
10994                     if (_curPost.IsDm || _curPost.IsMe)
10995                     {
10996                         _DoFavRetweetFlags = false;
10997                         return;
10998                     }
10999                     if (!SettingDialog.RetweetNoConfirm)
11000                     {
11001                         string Questiontext = Properties.Resources.RetweetQuestion1;
11002                         if (_DoFavRetweetFlags) Questiontext = Properties.Resources.FavoritesRetweetQuestionText2;
11003                         if (isConfirm && MessageBox.Show(Questiontext, "Retweet", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
11004                         {
11005                             _DoFavRetweetFlags = false;
11006                             return;
11007                         }
11008                     }
11009                 }
11010                 GetWorkerArg args = new GetWorkerArg();
11011                 args.ids = new List<long>();
11012                 args.sIds = new List<long>();
11013                 args.tName = _curTab.Text;
11014                 args.type = MyCommon.WORKERTYPE.Retweet;
11015                 foreach (int idx in _curList.SelectedIndices)
11016                 {
11017                     PostClass post = GetCurTabPost(idx);
11018                     if (!post.IsMe && !post.IsProtect && !post.IsDm) args.ids.Add(post.StatusId);
11019                 }
11020                 RunAsync(args);
11021             }
11022         }
11023
11024         private void ReTweetOriginalStripMenuItem_Click(object sender, EventArgs e)
11025         {
11026             doReTweetOfficial(true);
11027         }
11028
11029         private void FavoritesRetweetOriginal()
11030         {
11031             if (!this.ExistCurrentPost) return;
11032             _DoFavRetweetFlags = true;
11033             doReTweetOfficial(true);
11034             if (_DoFavRetweetFlags)
11035             {
11036                 _DoFavRetweetFlags = false;
11037                 FavoriteChange(true, false);
11038             }
11039         }
11040
11041         private void FavoritesRetweetUnofficial()
11042         {
11043             if (this.ExistCurrentPost && !_curPost.IsDm)
11044             {
11045                 _DoFavRetweetFlags = true;
11046                 FavoriteChange(true);
11047                 if (!_curPost.IsProtect && _DoFavRetweetFlags)
11048                 {
11049                     _DoFavRetweetFlags = false;
11050                     doReTweetUnofficial();
11051                 }
11052             }
11053         }
11054
11055         /// <summary>
11056         /// TweetFormatterクラスによって整形された状態のHTMLを、非公式RT用に元のツイートに復元します
11057         /// </summary>
11058         /// <param name="statusHtml">TweetFormatterによって整形された状態のHTML</param>
11059         /// <param name="multiline">trueであればBRタグを改行に、falseであればスペースに変換します</param>
11060         /// <returns>復元されたツイート本文</returns>
11061         internal static string CreateRetweetUnofficial(string statusHtml, bool multiline)
11062         {
11063             // TweetFormatterクラスによって整形された状態のHTMLを元のツイートに復元します
11064
11065             // 通常の URL
11066             statusHtml = Regex.Replace(statusHtml, "<a href=\"(?<href>.+?)\" title=\"(?<title>.+?)\">(?<text>.+?)</a>", "${title}");
11067             // メンション
11068             statusHtml = Regex.Replace(statusHtml, "<a class=\"mention\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
11069             // ハッシュタグ
11070             statusHtml = Regex.Replace(statusHtml, "<a class=\"hashtag\" href=\"(?<href>.+?)\">(?<text>.+?)</a>", "${text}");
11071
11072             // <br> 除去
11073             if (multiline)
11074                 statusHtml = statusHtml.Replace("<br>", Environment.NewLine);
11075             else
11076                 statusHtml = statusHtml.Replace("<br>", " ");
11077
11078             // &nbsp; は本来であれば U+00A0 (NON-BREAK SPACE) に置換すべきですが、
11079             // 現状では半角スペースの代用として &nbsp; を使用しているため U+0020 に置換します
11080             statusHtml = statusHtml.Replace("&nbsp;", " ");
11081
11082             return WebUtility.HtmlDecode(statusHtml);
11083         }
11084
11085         private void DumpPostClassToolStripMenuItem_Click(object sender, EventArgs e)
11086         {
11087             if (_curPost != null)
11088                 DispSelectedPost(true);
11089         }
11090
11091         private void MenuItemHelp_DropDownOpening(object sender, EventArgs e)
11092         {
11093             if (MyCommon.DebugBuild || MyCommon.IsKeyDown(Keys.CapsLock, Keys.Control, Keys.Shift))
11094                 DebugModeToolStripMenuItem.Visible = true;
11095             else
11096                 DebugModeToolStripMenuItem.Visible = false;
11097         }
11098
11099         private void ToolStripMenuItemUrlAutoShorten_CheckedChanged(object sender, EventArgs e)
11100         {
11101             SettingDialog.UrlConvertAuto = ToolStripMenuItemUrlAutoShorten.Checked;
11102         }
11103
11104         private void ContextMenuPostMode_Opening(object sender, CancelEventArgs e)
11105         {
11106             ToolStripMenuItemUrlAutoShorten.Checked = SettingDialog.UrlConvertAuto;
11107         }
11108
11109         private void TraceOutToolStripMenuItem_Click(object sender, EventArgs e)
11110         {
11111             if (TraceOutToolStripMenuItem.Checked)
11112                 MyCommon.TraceFlag = true;
11113             else
11114                 MyCommon.TraceFlag = false;
11115         }
11116
11117         private void TweenMain_Deactivate(object sender, EventArgs e)
11118         {
11119             //画面が非アクティブになったら、発言欄の背景色をデフォルトへ
11120             this.StatusText_Leave(StatusText, System.EventArgs.Empty);
11121         }
11122
11123         private void TabRenameMenuItem_Click(object sender, EventArgs e)
11124         {
11125             if (string.IsNullOrEmpty(_rclickTabName)) return;
11126             TabRename(ref _rclickTabName);
11127         }
11128
11129         private void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
11130         {
11131             UrlConvert(MyCommon.UrlConverter.Bitly);
11132         }
11133
11134         private void JmpToolStripMenuItem_Click(object sender, EventArgs e)
11135         {
11136             UrlConvert(MyCommon.UrlConverter.Jmp);
11137         }
11138
11139
11140         private void GetApiInfo_Dowork(object sender, DoWorkEventArgs e)
11141         {
11142             e.Result = tw.GetInfoApi();
11143         }
11144
11145         private void ApiUsageInfoMenuItem_Click(object sender, EventArgs e)
11146         {
11147             StringBuilder tmp = new StringBuilder();
11148
11149             using (FormInfo dlg = new FormInfo(this, Properties.Resources.ApiInfo6, GetApiInfo_Dowork))
11150             {
11151                 dlg.ShowDialog();
11152
11153                 var result = (TwitterApiStatus)dlg.Result;
11154
11155                 if (result == null)
11156                 {
11157                     var accessLevel = result.AccessLevel;
11158                     var timelineLimit = result.AccessLimit["/statuses/home_timeline"];
11159                     var mediaLimit = result.MediaUploadLimit;
11160
11161                     tmp.AppendLine(Properties.Resources.ApiInfo1 + timelineLimit.AccessLimitCount);
11162                     tmp.AppendLine(Properties.Resources.ApiInfo2 + timelineLimit.AccessLimitRemain);
11163                     tmp.AppendLine(Properties.Resources.ApiInfo3 + timelineLimit.AccessLimitResetDate);
11164                     tmp.AppendLine(Properties.Resources.ApiInfo7 + (tw.UserStreamEnabled ? Properties.Resources.Enable : Properties.Resources.Disable));
11165
11166                     tmp.AppendLine();
11167                     tmp.AppendLine(Properties.Resources.ApiInfo8 + accessLevel);
11168                     SetStatusLabelUrl();
11169
11170                     tmp.AppendLine();
11171                     tmp.AppendLine(Properties.Resources.ApiInfo9 + (mediaLimit == null ? Properties.Resources.ApiInfo91 : mediaLimit.AccessLimitCount.ToString()));
11172                     tmp.AppendLine(Properties.Resources.ApiInfo10 + (mediaLimit == null ? Properties.Resources.ApiInfo91 : mediaLimit.AccessLimitRemain.ToString()));
11173                     tmp.AppendLine(Properties.Resources.ApiInfo11 + (mediaLimit == null ? Properties.Resources.ApiInfo91 : mediaLimit.AccessLimitResetDate.ToString()));
11174                 }
11175                 else
11176                 {
11177                     tmp.Append(Properties.Resources.ApiInfo5);
11178                 }
11179             }
11180
11181             MessageBox.Show(tmp.ToString(), Properties.Resources.ApiInfo4, MessageBoxButtons.OK, MessageBoxIcon.Information);
11182         }
11183
11184         private void FollowCommandMenuItem_Click(object sender, EventArgs e)
11185         {
11186             string id = "";
11187             if (_curPost != null) id = _curPost.ScreenName;
11188             FollowCommand(id);
11189         }
11190
11191         private void FollowCommand_DoWork(object sender, DoWorkEventArgs e)
11192         {
11193             FollowRemoveCommandArgs arg = (FollowRemoveCommandArgs)e.Argument;
11194             e.Result = arg.tw.PostFollowCommand(arg.id);
11195         }
11196
11197         private void FollowCommand(string id)
11198         {
11199             using (InputTabName inputName = new InputTabName())
11200             {
11201                 inputName.FormTitle = "Follow";
11202                 inputName.FormDescription = Properties.Resources.FRMessage1;
11203                 inputName.TabName = id;
11204                 if (inputName.ShowDialog() == DialogResult.OK &&
11205                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
11206                 {
11207                     FollowRemoveCommandArgs arg = new FollowRemoveCommandArgs();
11208                     arg.tw = tw;
11209                     arg.id = inputName.TabName.Trim();
11210                     using (FormInfo _info = new FormInfo(this, Properties.Resources.FollowCommandText1,
11211                                                          FollowCommand_DoWork,
11212                                                          null,
11213                                                          arg))
11214                     {
11215                         _info.ShowDialog();
11216                         string ret = (string)_info.Result;
11217                         if (!string.IsNullOrEmpty(ret))
11218                             MessageBox.Show(Properties.Resources.FRMessage2 + ret);
11219                         else
11220                             MessageBox.Show(Properties.Resources.FRMessage3);
11221                     }
11222                 }
11223             }
11224         }
11225
11226         private void RemoveCommandMenuItem_Click(object sender, EventArgs e)
11227         {
11228             string id = "";
11229             if (_curPost != null) id = _curPost.ScreenName;
11230             RemoveCommand(id, false);
11231         }
11232
11233         private class FollowRemoveCommandArgs
11234         {
11235             public Twitter tw;
11236             public string id;
11237         }
11238
11239         private void RemoveCommand_DoWork(object sender , DoWorkEventArgs e)
11240         {
11241             FollowRemoveCommandArgs arg = (FollowRemoveCommandArgs)e.Argument;
11242             e.Result = arg.tw.PostRemoveCommand(arg.id);
11243         }
11244
11245         private void RemoveCommand(string id, bool skipInput)
11246         {
11247             FollowRemoveCommandArgs arg = new FollowRemoveCommandArgs();
11248             arg.tw = tw;
11249             arg.id = id;
11250             if (!skipInput)
11251             {
11252                 using (InputTabName inputName = new InputTabName())
11253                 {
11254                     inputName.FormTitle = "Unfollow";
11255                     inputName.FormDescription = Properties.Resources.FRMessage1;
11256                     inputName.TabName = id;
11257                     if (inputName.ShowDialog() == DialogResult.OK &&
11258                         !string.IsNullOrEmpty(inputName.TabName.Trim()))
11259                     {
11260                         arg.tw = tw;
11261                         arg.id = inputName.TabName.Trim();
11262                     }
11263                     else
11264                     {
11265                         return;
11266                     }
11267                 }
11268             }
11269
11270             using (FormInfo _info = new FormInfo(this, Properties.Resources.RemoveCommandText1,
11271                                                  RemoveCommand_DoWork,
11272                                                  null,
11273                                                  arg))
11274             {
11275                 _info.ShowDialog();
11276                 string ret = (string)_info.Result;
11277                 if (!string.IsNullOrEmpty(ret))
11278                     MessageBox.Show(Properties.Resources.FRMessage2 + ret);
11279                 else
11280                     MessageBox.Show(Properties.Resources.FRMessage3);
11281             }
11282         }
11283
11284         private void FriendshipMenuItem_Click(object sender, EventArgs e)
11285         {
11286             string id = "";
11287             if (_curPost != null)
11288                 id = _curPost.ScreenName;
11289
11290             ShowFriendship(id);
11291         }
11292
11293         private class ShowFriendshipArgs
11294         {
11295             public Twitter tw;
11296             public class FriendshipInfo
11297             {
11298                 public string id = "";
11299                 public bool isFollowing = false;
11300                 public bool isFollowed = false;
11301                 public bool isError = false;
11302                 public FriendshipInfo(string id)
11303                 {
11304                     this.id = id;
11305                 }
11306             }
11307             public List<FriendshipInfo> ids = new List<FriendshipInfo>();
11308         }
11309
11310         private void ShowFriendship_DoWork(object sender, DoWorkEventArgs e)
11311         {
11312             ShowFriendshipArgs arg = (ShowFriendshipArgs)e.Argument;
11313             string result = "";
11314             foreach (ShowFriendshipArgs.FriendshipInfo fInfo in arg.ids)
11315             {
11316                 string rt = arg.tw.GetFriendshipInfo(fInfo.id, ref fInfo.isFollowing, ref fInfo.isFollowed);
11317                 if (!string.IsNullOrEmpty(rt))
11318                 {
11319                     if (string.IsNullOrEmpty(result)) result = rt;
11320                     fInfo.isError = true;
11321                 }
11322             }
11323             e.Result = result;
11324         }
11325
11326         private void ShowFriendship(string id)
11327         {
11328             ShowFriendshipArgs args = new ShowFriendshipArgs();
11329             args.tw = tw;
11330             using (InputTabName inputName = new InputTabName())
11331             {
11332                 inputName.FormTitle = "Show Friendships";
11333                 inputName.FormDescription = Properties.Resources.FRMessage1;
11334                 inputName.TabName = id;
11335                 if (inputName.ShowDialog() == DialogResult.OK &&
11336                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
11337                 {
11338                     string ret = "";
11339                     args.ids.Add(new ShowFriendshipArgs.FriendshipInfo(inputName.TabName.Trim()));
11340                     using (FormInfo _info = new FormInfo(this, Properties.Resources.ShowFriendshipText1,
11341                                                          ShowFriendship_DoWork,
11342                                                          null,
11343                                                          args))
11344                     {
11345                         _info.ShowDialog();
11346                         ret = (string)_info.Result;
11347                     }
11348                     string result = "";
11349                     if (string.IsNullOrEmpty(ret))
11350                     {
11351                         if (args.ids[0].isFollowing)
11352                         {
11353                             result = Properties.Resources.GetFriendshipInfo1 + System.Environment.NewLine;
11354                         }
11355                         else
11356                         {
11357                             result = Properties.Resources.GetFriendshipInfo2 + System.Environment.NewLine;
11358                         }
11359                         if (args.ids[0].isFollowed)
11360                         {
11361                             result += Properties.Resources.GetFriendshipInfo3;
11362                         }
11363                         else
11364                         {
11365                             result += Properties.Resources.GetFriendshipInfo4;
11366                         }
11367                         result = args.ids[0].id + Properties.Resources.GetFriendshipInfo5 + System.Environment.NewLine + result;
11368                     }
11369                     else
11370                     {
11371                         result = ret;
11372                     }
11373                     MessageBox.Show(result);
11374                 }
11375             }
11376         }
11377
11378         private void ShowFriendship(string[] ids)
11379         {
11380             foreach (string id in ids)
11381             {
11382                 string ret = "";
11383                 ShowFriendshipArgs args = new ShowFriendshipArgs();
11384                 args.tw = tw;
11385                 args.ids.Add(new ShowFriendshipArgs.FriendshipInfo(id.Trim()));
11386                 using (FormInfo _info = new FormInfo(this, Properties.Resources.ShowFriendshipText1,
11387                                                      ShowFriendship_DoWork,
11388                                                      null,
11389                                                      args))
11390                 {
11391                     _info.ShowDialog();
11392                     ret = (string)_info.Result;
11393                 }
11394                 string result = "";
11395                 ShowFriendshipArgs.FriendshipInfo fInfo = args.ids[0];
11396                 string ff = "";
11397                 if (string.IsNullOrEmpty(ret))
11398                 {
11399                     ff = "  ";
11400                     if (fInfo.isFollowing)
11401                     {
11402                         ff += Properties.Resources.GetFriendshipInfo1;
11403                     }
11404                     else
11405                     {
11406                         ff += Properties.Resources.GetFriendshipInfo2;
11407                     }
11408
11409                     ff += System.Environment.NewLine + "  ";
11410                     if (fInfo.isFollowed)
11411                     {
11412                         ff += Properties.Resources.GetFriendshipInfo3;
11413                     }
11414                     else
11415                     {
11416                         ff += Properties.Resources.GetFriendshipInfo4;
11417                     }
11418                     result += fInfo.id + Properties.Resources.GetFriendshipInfo5 + System.Environment.NewLine + ff;
11419                     if (fInfo.isFollowing)
11420                     {
11421                         if (MessageBox.Show(
11422                             Properties.Resources.GetFriendshipInfo7 + System.Environment.NewLine + result, Properties.Resources.GetFriendshipInfo8,
11423                             MessageBoxButtons.YesNo,
11424                             MessageBoxIcon.Question,
11425                             MessageBoxDefaultButton.Button2) == DialogResult.Yes)
11426                         {
11427                             RemoveCommand(fInfo.id, true);
11428                         }
11429                     }
11430                     else
11431                     {
11432                         MessageBox.Show(result);
11433                     }
11434                 }
11435                 else
11436                 {
11437                     MessageBox.Show(ret);
11438                 }
11439             }
11440         }
11441
11442         private void OwnStatusMenuItem_Click(object sender, EventArgs e)
11443         {
11444             doShowUserStatus(tw.Username, false);
11445             //if (!string.IsNullOrEmpty(tw.UserInfoXml))
11446             //{
11447             //    doShowUserStatus(tw.Username, false);
11448             //}
11449             //else
11450             //{
11451             //    MessageBox.Show(Properties.Resources.ShowYourProfileText1, "Your status", MessageBoxButtons.OK, MessageBoxIcon.Information);
11452             //    return;
11453             //}
11454         }
11455
11456         // TwitterIDでない固定文字列を調べる(文字列検証のみ 実際に取得はしない)
11457         // URLから切り出した文字列を渡す
11458
11459         public bool IsTwitterId(string name)
11460         {
11461             if (SettingDialog.TwitterConfiguration.NonUsernamePaths == null || SettingDialog.TwitterConfiguration.NonUsernamePaths.Length == 0)
11462                 return !Regex.Match(name, @"^(about|jobs|tos|privacy|who_to_follow|download|messages)$", RegexOptions.IgnoreCase).Success;
11463             else
11464                 return !SettingDialog.TwitterConfiguration.NonUsernamePaths.Contains(name.ToLower());
11465         }
11466
11467         private string GetUserId()
11468         {
11469             Match m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?$");
11470             if (m.Success && IsTwitterId(m.Result("${ScreenName}")))
11471                 return m.Result("${ScreenName}");
11472             else
11473                 return null;
11474         }
11475
11476         private void FollowContextMenuItem_Click(object sender, EventArgs e)
11477         {
11478             string name = GetUserId();
11479             if (name != null) FollowCommand(name);
11480         }
11481
11482         private void RemoveContextMenuItem_Click(object sender, EventArgs e)
11483         {
11484             string name = GetUserId();
11485             if (name != null) RemoveCommand(name, false);
11486         }
11487
11488         private void FriendshipContextMenuItem_Click(object sender, EventArgs e)
11489         {
11490             string name = GetUserId();
11491             if (name != null) ShowFriendship(name);
11492         }
11493
11494         private void FriendshipAllMenuItem_Click(object sender, EventArgs e)
11495         {
11496             MatchCollection ma = Regex.Matches(this.PostBrowser.DocumentText, @"href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?""");
11497             List<string> ids = new List<string>();
11498             foreach (Match mu in ma)
11499             {
11500                 if (mu.Result("${ScreenName}").ToLower() != tw.Username.ToLower())
11501                 {
11502                     ids.Add(mu.Result("${ScreenName}"));
11503                 }
11504             }
11505             ShowFriendship(ids.ToArray());
11506         }
11507
11508         private void ShowUserStatusContextMenuItem_Click(object sender, EventArgs e)
11509         {
11510             string name = GetUserId();
11511             if (name != null) ShowUserStatus(name);
11512         }
11513
11514         private void SearchPostsDetailToolStripMenuItem_Click(object sender, EventArgs e)
11515         {
11516             string name = GetUserId();
11517             if (name != null) AddNewTabForUserTimeline(name);
11518         }
11519
11520         private void SearchAtPostsDetailToolStripMenuItem_Click(object sender, EventArgs e)
11521         {
11522             string name = GetUserId();
11523             if (name != null) AddNewTabForSearch("@" + name);
11524         }
11525
11526         private void IdeographicSpaceToSpaceToolStripMenuItem_Click(object sender, EventArgs e)
11527         {
11528             _modifySettingCommon = true;
11529         }
11530
11531         private void ToolStripFocusLockMenuItem_CheckedChanged(object sender, EventArgs e)
11532         {
11533             _modifySettingCommon = true;
11534         }
11535
11536         private void doQuote()
11537         {
11538             //QT @id:内容
11539             //返信先情報付加
11540             if (this.ExistCurrentPost)
11541             {
11542                 if (_curPost.IsDm ||
11543                     !StatusText.Enabled) return;
11544
11545                 if (_curPost.IsProtect)
11546                 {
11547                     MessageBox.Show("Protected.");
11548                     return;
11549                 }
11550                 string rtdata = _curPost.Text;
11551                 rtdata = CreateRetweetUnofficial(rtdata, this.StatusText.Multiline);
11552
11553                 StatusText.Text = " QT @" + _curPost.ScreenName + ": " + rtdata;
11554                 if (_curPost.RetweetedId == null)
11555                 {
11556                     _reply_to_id = _curPost.StatusId;
11557                 }
11558                 else
11559                 {
11560                     _reply_to_id = _curPost.RetweetedId.Value;
11561                 }
11562                 _reply_to_name = _curPost.ScreenName;
11563
11564                 StatusText.SelectionStart = 0;
11565                 StatusText.Focus();
11566             }
11567         }
11568
11569         private void QuoteStripMenuItem_Click(object sender, EventArgs e) // Handles QuoteStripMenuItem.Click, QtOpMenuItem.Click
11570         {
11571             doQuote();
11572         }
11573
11574         private void SearchButton_Click(object sender, EventArgs e)
11575         {
11576             //公式検索
11577             Control pnl = ((Control)sender).Parent;
11578             if (pnl == null) return;
11579             string tbName = pnl.Parent.Text;
11580             TabClass tb = _statuses.Tabs[tbName];
11581             ComboBox cmb = (ComboBox)pnl.Controls["comboSearch"];
11582             ComboBox cmbLang = (ComboBox)pnl.Controls["comboLang"];
11583             ComboBox cmbusline = (ComboBox)pnl.Controls["comboUserline"];
11584             cmb.Text = cmb.Text.Trim();
11585             // 検索式演算子 OR についてのみ大文字しか認識しないので強制的に大文字とする
11586             bool Quote = false;
11587             StringBuilder buf = new StringBuilder();
11588             char[] c = cmb.Text.ToCharArray();
11589             for (int cnt = 0; cnt < cmb.Text.Length; cnt++)
11590             {
11591                 if (cnt > cmb.Text.Length - 4)
11592                 {
11593                     buf.Append(cmb.Text.Substring(cnt));
11594                     break;
11595                 }
11596                 if (c[cnt] == '"')
11597                 {
11598                     Quote = !Quote;
11599                 }
11600                 else
11601                 {
11602                     if (!Quote && cmb.Text.Substring(cnt, 4).Equals(" or ", StringComparison.OrdinalIgnoreCase))
11603                     {
11604                         buf.Append(" OR ");
11605                         cnt += 3;
11606                         continue;
11607                     }
11608                 }
11609                 buf.Append(c[cnt]);
11610             }
11611             cmb.Text = buf.ToString();
11612
11613             tb.SearchWords = cmb.Text;
11614             tb.SearchLang = cmbLang.Text;
11615             if (string.IsNullOrEmpty(cmb.Text))
11616             {
11617                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
11618                 SaveConfigsTabs();
11619                 return;
11620             }
11621             if (tb.IsQueryChanged())
11622             {
11623                 int idx = ((ComboBox)pnl.Controls["comboSearch"]).Items.IndexOf(tb.SearchWords);
11624                 if (idx > -1) ((ComboBox)pnl.Controls["comboSearch"]).Items.RemoveAt(idx);
11625                 ((ComboBox)pnl.Controls["comboSearch"]).Items.Insert(0, tb.SearchWords);
11626                 cmb.Text = tb.SearchWords;
11627                 cmb.SelectAll();
11628                 DetailsListView lst = (DetailsListView)pnl.Parent.Tag;
11629                 lst.VirtualListSize = 0;
11630                 lst.Items.Clear();
11631                 _statuses.ClearTabIds(tbName);
11632                 SaveConfigsTabs();   //検索条件の保存
11633             }
11634
11635             GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, tbName);
11636             ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
11637         }
11638
11639         private void RefreshMoreStripMenuItem_Click(object sender, EventArgs e)
11640         {
11641             //もっと前を取得
11642             DoRefreshMore();
11643         }
11644
11645         private void UndoRemoveTabMenuItem_Click(object sender, EventArgs e)
11646         {
11647             if (_statuses.RemovedTab.Count == 0)
11648             {
11649                 MessageBox.Show("There isn't removed tab.", "Undo", MessageBoxButtons.OK, MessageBoxIcon.Information);
11650                 return;
11651             }
11652             else
11653             {
11654                 TabClass tb = _statuses.RemovedTab.Pop();
11655                 if (tb.TabType == MyCommon.TabUsageType.Related)
11656                 {
11657                     var relatedTab = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
11658                     if (relatedTab != null)
11659                     {
11660                         // 関連発言なら既存のタブを置き換える
11661                         tb.TabName = relatedTab.TabName;
11662                         this.ClearTab(tb.TabName, false);
11663                         _statuses.Tabs[tb.TabName] = tb;
11664                         for (int i = 0; i < ListTab.TabPages.Count; i++)
11665                         {
11666                             if (tb.TabName == ListTab.TabPages[i].Text)
11667                             {
11668                                 ListTab.SelectedIndex = i;
11669                                 ListTabSelect(ListTab.TabPages[i]);
11670                                 break;
11671                             }
11672                         }
11673                     }
11674                     else
11675                     {
11676                         const string TabName = "Related Tweets";
11677                         string renamed = TabName;
11678                         for (int i = 2; i <= 100; i++)
11679                         {
11680                             if (!_statuses.ContainsTab(renamed)) break;
11681                             renamed = TabName + i.ToString();
11682                         }
11683                         tb.TabName = renamed;
11684                         AddNewTab(renamed, false, tb.TabType, tb.ListInfo);
11685                         _statuses.Tabs.Add(renamed, tb);  // 後に
11686                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
11687                         ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
11688                     }
11689                 }
11690                 else
11691                 {
11692                     string renamed = tb.TabName;
11693                     for (int i = 1; i < int.MaxValue; i++)
11694                     {
11695                         if (!_statuses.ContainsTab(renamed)) break;
11696                         renamed = tb.TabName + "(" + i.ToString() + ")";
11697                     }
11698                     tb.TabName = renamed;
11699                     _statuses.Tabs.Add(renamed, tb);  // 先に
11700                     AddNewTab(renamed, false, tb.TabType, tb.ListInfo);
11701                     ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
11702                     ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
11703                 }
11704                 SaveConfigsTabs();
11705             }
11706         }
11707
11708         private void doMoveToRTHome()
11709         {
11710             if (_curList.SelectedIndices.Count > 0)
11711             {
11712                 PostClass post = GetCurTabPost(_curList.SelectedIndices[0]);
11713                 if (post.RetweetedId != null)
11714                 {
11715                     OpenUriAsync("https://twitter.com/" + GetCurTabPost(_curList.SelectedIndices[0]).RetweetedBy);
11716                 }
11717             }
11718         }
11719
11720         private void MoveToRTHomeMenuItem_Click(object sender, EventArgs e)
11721         {
11722             doMoveToRTHome();
11723         }
11724
11725         private void IdFilterAddMenuItem_Click(object sender, EventArgs e)
11726         {
11727             string name = GetUserId();
11728             if (name != null)
11729             {
11730                 string tabName;
11731
11732                 //未選択なら処理終了
11733                 if (_curList.SelectedIndices.Count == 0) return;
11734
11735                 //タブ選択(or追加)
11736                 if (!SelectTab(out tabName)) return;
11737
11738                 bool mv = false;
11739                 bool mk = false;
11740                 MoveOrCopy(ref mv, ref mk);
11741
11742                 PostFilterRule fc = new PostFilterRule();
11743                 fc.FilterName = name;
11744                 fc.UseNameField = true;
11745                 fc.MoveMatches = mv;
11746                 fc.MarkMatches = mk;
11747                 fc.UseRegex = false;
11748                 fc.FilterByUrl = false;
11749                 _statuses.Tabs[tabName].AddFilter(fc);
11750
11751                 try
11752                 {
11753                     this.Cursor = Cursors.WaitCursor;
11754                     this.PurgeListViewItemCache();
11755                     _curPost = null;
11756                     _curItemIndex = -1;
11757                     _statuses.FilterAll();
11758                     foreach (TabPage tb in ListTab.TabPages)
11759                     {
11760                         ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
11761                         if (_statuses.Tabs[tb.Text].UnreadCount > 0)
11762                         {
11763                             if (SettingDialog.TabIconDisp)
11764                                 tb.ImageIndex = 0;
11765                         }
11766                         else
11767                         {
11768                             if (SettingDialog.TabIconDisp)
11769                                 tb.ImageIndex = -1;
11770                         }
11771                     }
11772                     if (!SettingDialog.TabIconDisp) ListTab.Refresh();
11773                 }
11774                 finally
11775                 {
11776                     this.Cursor = Cursors.Default;
11777                 }
11778                 SaveConfigsTabs();
11779             }
11780         }
11781
11782         private void ListManageUserContextToolStripMenuItem_Click(object sender, EventArgs e)
11783         {
11784             string user;
11785
11786             ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
11787
11788             if (menuItem.Owner == this.ContextMenuPostBrowser)
11789             {
11790                 user = GetUserId();
11791                 if (user == null) return;
11792             }
11793             else if (this._curPost != null)
11794             {
11795                 user = this._curPost.ScreenName;
11796             }
11797             else
11798             {
11799                 return;
11800             }
11801
11802             if (TabInformations.GetInstance().SubscribableLists.Count == 0)
11803             {
11804                 string res = this.tw.GetListsApi();
11805
11806                 if (!string.IsNullOrEmpty(res))
11807                 {
11808                     MessageBox.Show("Failed to get lists. (" + res + ")");
11809                     return;
11810                 }
11811             }
11812
11813             using (MyLists listSelectForm = new MyLists(user, this.tw))
11814             {
11815                 listSelectForm.ShowDialog(this);
11816             }
11817         }
11818
11819         private void SearchControls_Enter(object sender, EventArgs e)
11820         {
11821             Control pnl = (Control)sender;
11822             foreach (Control ctl in pnl.Controls)
11823             {
11824                 ctl.TabStop = true;
11825             }
11826         }
11827
11828         private void SearchControls_Leave(object sender, EventArgs e)
11829         {
11830             Control pnl = (Control)sender;
11831             foreach (Control ctl in pnl.Controls)
11832             {
11833                 ctl.TabStop = false;
11834             }
11835         }
11836
11837         private void PublicSearchQueryMenuItem_Click(object sender, EventArgs e)
11838         {
11839             if (ListTab.SelectedTab != null)
11840             {
11841                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.PublicSearch) return;
11842                 ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
11843             }
11844         }
11845
11846         private void UseHashtagMenuItem_Click(object sender, EventArgs e)
11847         {
11848             Match m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/search\?q=%23(?<hash>.+)$");
11849             if (m.Success)
11850             {
11851                 HashMgr.SetPermanentHash("#" + m.Result("${hash}"));
11852                 HashStripSplitButton.Text = HashMgr.UseHash;
11853                 HashToggleMenuItem.Checked = true;
11854                 HashToggleToolStripMenuItem.Checked = true;
11855                 //使用ハッシュタグとして設定
11856                 _modifySettingCommon = true;
11857             }
11858         }
11859
11860         private void StatusLabel_DoubleClick(object sender, EventArgs e)
11861         {
11862             MessageBox.Show(StatusLabel.TextHistory, "Logs", MessageBoxButtons.OK, MessageBoxIcon.None);
11863         }
11864
11865         private void HashManageMenuItem_Click(object sender, EventArgs e)
11866         {
11867             DialogResult rslt = DialogResult.Cancel;
11868             try
11869             {
11870                 rslt = HashMgr.ShowDialog();
11871             }
11872             catch (Exception)
11873             {
11874                 return;
11875             }
11876             this.TopMost = SettingDialog.AlwaysTop;
11877             if (rslt == DialogResult.Cancel) return;
11878             if (!string.IsNullOrEmpty(HashMgr.UseHash))
11879             {
11880                 HashStripSplitButton.Text = HashMgr.UseHash;
11881                 HashToggleMenuItem.Checked = true;
11882                 HashToggleToolStripMenuItem.Checked = true;
11883             }
11884             else
11885             {
11886                 HashStripSplitButton.Text = "#[-]";
11887                 HashToggleMenuItem.Checked = false;
11888                 HashToggleToolStripMenuItem.Checked = false;
11889             }
11890             //if (HashMgr.IsInsert && HashMgr.UseHash != "")
11891             //{
11892             //    int sidx = StatusText.SelectionStart;
11893             //    string hash = HashMgr.UseHash + " ";
11894             //    if (sidx > 0)
11895             //    {
11896             //        if (StatusText.Text.Substring(sidx - 1, 1) != " ")
11897             //            hash = " " + hash;
11898             //    }
11899             //    StatusText.Text = StatusText.Text.Insert(sidx, hash);
11900             //    sidx += hash.Length;
11901             //    StatusText.SelectionStart = sidx;
11902             //    StatusText.Focus();
11903             //}
11904             _modifySettingCommon = true;
11905             this.StatusText_TextChanged(null, null);
11906         }
11907
11908         private void HashToggleMenuItem_Click(object sender, EventArgs e)
11909         {
11910             HashMgr.ToggleHash();
11911             if (!string.IsNullOrEmpty(HashMgr.UseHash))
11912             {
11913                 HashStripSplitButton.Text = HashMgr.UseHash;
11914                 HashToggleMenuItem.Checked = true;
11915                 HashToggleToolStripMenuItem.Checked = true;
11916             }
11917             else
11918             {
11919                 HashStripSplitButton.Text = "#[-]";
11920                 HashToggleMenuItem.Checked = false;
11921                 HashToggleToolStripMenuItem.Checked = false;
11922             }
11923             _modifySettingCommon = true;
11924             this.StatusText_TextChanged(null, null);
11925         }
11926
11927         private void HashStripSplitButton_ButtonClick(object sender, EventArgs e)
11928         {
11929             HashToggleMenuItem_Click(null, null);
11930         }
11931
11932         private void MenuItemOperate_DropDownOpening(object sender, EventArgs e)
11933         {
11934             if (ListTab.SelectedTab == null) return;
11935             if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
11936             if (!this.ExistCurrentPost)
11937             {
11938                 this.ReplyOpMenuItem.Enabled = false;
11939                 this.ReplyAllOpMenuItem.Enabled = false;
11940                 this.DmOpMenuItem.Enabled = false;
11941                 this.ShowProfMenuItem.Enabled = false;
11942                 this.ShowUserTimelineToolStripMenuItem.Enabled = false;
11943                 this.ListManageMenuItem.Enabled = false;
11944                 this.OpenFavOpMenuItem.Enabled = false;
11945                 this.CreateTabRuleOpMenuItem.Enabled = false;
11946                 this.CreateIdRuleOpMenuItem.Enabled = false;
11947                 this.ReadOpMenuItem.Enabled = false;
11948                 this.UnreadOpMenuItem.Enabled = false;
11949             }
11950             else
11951             {
11952                 this.ReplyOpMenuItem.Enabled = true;
11953                 this.ReplyAllOpMenuItem.Enabled = true;
11954                 this.DmOpMenuItem.Enabled = true;
11955                 this.ShowProfMenuItem.Enabled = true;
11956                 this.ShowUserTimelineToolStripMenuItem.Enabled = true;
11957                 this.ListManageMenuItem.Enabled = true;
11958                 this.OpenFavOpMenuItem.Enabled = true;
11959                 this.CreateTabRuleOpMenuItem.Enabled = true;
11960                 this.CreateIdRuleOpMenuItem.Enabled = true;
11961                 this.ReadOpMenuItem.Enabled = true;
11962                 this.UnreadOpMenuItem.Enabled = true;
11963             }
11964
11965             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
11966             {
11967                 this.FavOpMenuItem.Enabled = false;
11968                 this.UnFavOpMenuItem.Enabled = false;
11969                 this.OpenStatusOpMenuItem.Enabled = false;
11970                 this.OpenFavotterOpMenuItem.Enabled = false;
11971                 this.ShowRelatedStatusesMenuItem2.Enabled = false;
11972                 this.RtOpMenuItem.Enabled = false;
11973                 this.RtUnOpMenuItem.Enabled = false;
11974                 this.QtOpMenuItem.Enabled = false;
11975                 this.FavoriteRetweetMenuItem.Enabled = false;
11976                 this.FavoriteRetweetUnofficialMenuItem.Enabled = false;
11977                 if (this.ExistCurrentPost && _curPost.IsDm) this.DelOpMenuItem.Enabled = true;
11978             }
11979             else
11980             {
11981                 this.FavOpMenuItem.Enabled = true;
11982                 this.UnFavOpMenuItem.Enabled = true;
11983                 this.OpenStatusOpMenuItem.Enabled = true;
11984                 this.OpenFavotterOpMenuItem.Enabled = true;
11985                 this.ShowRelatedStatusesMenuItem2.Enabled = true;  //PublicSearchの時問題出るかも
11986
11987                 if (_curPost.IsMe)
11988                 {
11989                     this.RtOpMenuItem.Enabled = false;
11990                     this.FavoriteRetweetMenuItem.Enabled = false;
11991                     this.DelOpMenuItem.Enabled = true;
11992                 }
11993                 else
11994                 {
11995                     this.DelOpMenuItem.Enabled = false;
11996                     if (_curPost.IsProtect)
11997                     {
11998                         this.RtOpMenuItem.Enabled = false;
11999                         this.RtUnOpMenuItem.Enabled = false;
12000                         this.QtOpMenuItem.Enabled = false;
12001                         this.FavoriteRetweetMenuItem.Enabled = false;
12002                         this.FavoriteRetweetUnofficialMenuItem.Enabled = false;
12003                     }
12004                     else
12005                     {
12006                         this.RtOpMenuItem.Enabled = true;
12007                         this.RtUnOpMenuItem.Enabled = true;
12008                         this.QtOpMenuItem.Enabled = true;
12009                         this.FavoriteRetweetMenuItem.Enabled = true;
12010                         this.FavoriteRetweetUnofficialMenuItem.Enabled = true;
12011                     }
12012                 }
12013             }
12014
12015             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.Favorites)
12016             {
12017                 this.RefreshPrevOpMenuItem.Enabled = true;
12018             }
12019             else
12020             {
12021                 this.RefreshPrevOpMenuItem.Enabled = false;
12022             }
12023             if (!this.ExistCurrentPost
12024                 || _curPost.InReplyToStatusId == null)
12025             {
12026                 OpenRepSourceOpMenuItem.Enabled = false;
12027             }
12028             else
12029             {
12030                 OpenRepSourceOpMenuItem.Enabled = true;
12031             }
12032             if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
12033             {
12034                 OpenRterHomeMenuItem.Enabled = false;
12035             }
12036             else
12037             {
12038                 OpenRterHomeMenuItem.Enabled = true;
12039             }
12040         }
12041
12042         private void MenuItemTab_DropDownOpening(object sender, EventArgs e)
12043         {
12044             ContextMenuTabProperty_Opening(sender, null);
12045         }
12046
12047         public Twitter TwitterInstance
12048         {
12049             get { return tw; }
12050         }
12051
12052         private void SplitContainer3_SplitterMoved(object sender, SplitterEventArgs e)
12053         {
12054             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
12055             {
12056                 _mySpDis3 = SplitContainer3.SplitterDistance;
12057                 _modifySettingLocal = true;
12058             }
12059         }
12060
12061         private void MenuItemEdit_DropDownOpening(object sender, EventArgs e)
12062         {
12063             if (_statuses.RemovedTab.Count == 0)
12064             {
12065                 UndoRemoveTabMenuItem.Enabled = false;
12066             }
12067             else
12068             {
12069                 UndoRemoveTabMenuItem.Enabled = true;
12070             }
12071             if (ListTab.SelectedTab != null)
12072             {
12073                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
12074                     PublicSearchQueryMenuItem.Enabled = true;
12075                 else
12076                     PublicSearchQueryMenuItem.Enabled = false;
12077             }
12078             else
12079             {
12080                 PublicSearchQueryMenuItem.Enabled = false;
12081             }
12082             if (!this.ExistCurrentPost)
12083             {
12084                 this.CopySTOTMenuItem.Enabled = false;
12085                 this.CopyURLMenuItem.Enabled = false;
12086                 this.CopyUserIdStripMenuItem.Enabled = false;
12087             }
12088             else
12089             {
12090                 this.CopySTOTMenuItem.Enabled = true;
12091                 this.CopyURLMenuItem.Enabled = true;
12092                 this.CopyUserIdStripMenuItem.Enabled = true;
12093                 if (_curPost.IsDm) this.CopyURLMenuItem.Enabled = false;
12094                 if (_curPost.IsProtect) this.CopySTOTMenuItem.Enabled = false;
12095             }
12096         }
12097
12098         private void NotifyIcon1_MouseMove(object sender, MouseEventArgs e)
12099         {
12100             SetNotifyIconText();
12101         }
12102
12103         private void UserStatusToolStripMenuItem_Click(object sender, EventArgs e)
12104         {
12105             string id = "";
12106             if (_curPost != null)
12107             {
12108                 id = _curPost.ScreenName;
12109             }
12110             ShowUserStatus(id);
12111         }
12112
12113         private class GetUserInfoArgs
12114         {
12115             public Twitter tw;
12116             public string id;
12117             public TwitterDataModel.User user;
12118         }
12119
12120         private void GetUserInfo_DoWork(object sender, DoWorkEventArgs e)
12121         {
12122             GetUserInfoArgs args = (GetUserInfoArgs)e.Argument;
12123             e.Result = args.tw.GetUserInfo(args.id, ref args.user);
12124         }
12125
12126         private void doShowUserStatus(string id, bool ShowInputDialog)
12127         {
12128             TwitterDataModel.User user = null;
12129             GetUserInfoArgs args = new GetUserInfoArgs();
12130             if (ShowInputDialog)
12131             {
12132                 using (InputTabName inputName = new InputTabName())
12133                 {
12134                     inputName.FormTitle = "Show UserStatus";
12135                     inputName.FormDescription = Properties.Resources.FRMessage1;
12136                     inputName.TabName = id;
12137                     if (inputName.ShowDialog() == DialogResult.OK &&
12138                         !string.IsNullOrEmpty(inputName.TabName.Trim()))
12139                     {
12140                         id = inputName.TabName.Trim();
12141                         args.tw = tw;
12142                         args.id = id;
12143                         args.user = user;
12144                         using (FormInfo _info = new FormInfo(this, Properties.Resources.doShowUserStatusText1,
12145                                                              GetUserInfo_DoWork,
12146                                                              null,
12147                                                              args))
12148                         {
12149                             _info.ShowDialog();
12150                             string ret = (string)_info.Result;
12151                             if (string.IsNullOrEmpty(ret))
12152                                 doShowUserStatus(args.user);
12153                             else
12154                                 MessageBox.Show(ret);
12155                         }
12156                     }
12157                 }
12158             }
12159             else
12160             {
12161                 args.tw = tw;
12162                 args.id = id;
12163                 args.user = user;
12164                 using (FormInfo _info = new FormInfo(this, Properties.Resources.doShowUserStatusText1,
12165                                                      GetUserInfo_DoWork,
12166                                                      null,
12167                                                      args))
12168                 {
12169                     _info.ShowDialog();
12170                     string ret = (string)_info.Result;
12171                     if (string.IsNullOrEmpty(ret))
12172                     {
12173                         doShowUserStatus(args.user);
12174                     }
12175                     else
12176                     {
12177                         MessageBox.Show(ret);
12178                     }
12179                 }
12180             }
12181         }
12182
12183         private void doShowUserStatus(TwitterDataModel.User user)
12184         {
12185             using (ShowUserInfo userinfo = new ShowUserInfo())
12186             {
12187                 userinfo.Owner = this;
12188                 userinfo.User = user;
12189                 userinfo.ShowDialog(this);
12190                 this.Activate();
12191                 this.BringToFront();
12192             }
12193         }
12194
12195         private void ShowUserStatus(string id, bool ShowInputDialog)
12196         {
12197             doShowUserStatus(id, ShowInputDialog);
12198         }
12199
12200         private void ShowUserStatus(string id)
12201         {
12202             doShowUserStatus(id, true);
12203         }
12204
12205         private void FollowToolStripMenuItem_Click(object sender, EventArgs e)
12206         {
12207             if (NameLabel.Tag != null)
12208             {
12209                 string id = (string)NameLabel.Tag;
12210                 if (id != tw.Username)
12211                 {
12212                     FollowCommand(id);
12213                 }
12214             }
12215         }
12216
12217         private void UnFollowToolStripMenuItem_Click(object sender, EventArgs e)
12218         {
12219             if (NameLabel.Tag != null)
12220             {
12221                 string id = (string)NameLabel.Tag;
12222                 if (id != tw.Username)
12223                 {
12224                     RemoveCommand(id, false);
12225                 }
12226             }
12227         }
12228
12229         private void ShowFriendShipToolStripMenuItem_Click(object sender, EventArgs e)
12230         {
12231             if (NameLabel.Tag != null)
12232             {
12233                 string id = (string)NameLabel.Tag;
12234                 if (id != tw.Username)
12235                 {
12236                     ShowFriendship(id);
12237                 }
12238             }
12239         }
12240
12241         private void ShowUserStatusToolStripMenuItem_Click(object sender, EventArgs e)
12242         {
12243             if (NameLabel.Tag != null)
12244             {
12245                 string id = (string)NameLabel.Tag;
12246                 ShowUserStatus(id, false);
12247             }
12248         }
12249
12250         private void SearchPostsDetailNameToolStripMenuItem_Click(object sender, EventArgs e)
12251         {
12252             if (NameLabel.Tag != null)
12253             {
12254                 string id = (string)NameLabel.Tag;
12255                 AddNewTabForUserTimeline(id);
12256             }
12257         }
12258
12259         private void SearchAtPostsDetailNameToolStripMenuItem_Click(object sender, EventArgs e)
12260         {
12261             if (NameLabel.Tag != null)
12262             {
12263                 string id = (string)NameLabel.Tag;
12264                 AddNewTabForSearch("@" + id);
12265             }
12266         }
12267
12268         private void ShowProfileMenuItem_Click(object sender, EventArgs e)
12269         {
12270             if (_curPost != null)
12271             {
12272                 ShowUserStatus(_curPost.ScreenName, false);
12273             }
12274         }
12275
12276         private void GetRetweet_DoWork(object sender, DoWorkEventArgs e)
12277         {
12278             int counter = 0;
12279
12280             long statusid;
12281             if (_curPost.RetweetedId != null)
12282             {
12283                 statusid = _curPost.RetweetedId.Value;
12284             }
12285             else
12286             {
12287                 statusid = _curPost.StatusId;
12288             }
12289             tw.GetStatus_Retweeted_Count(statusid, ref counter);
12290
12291             e.Result = counter;
12292         }
12293
12294         private void RtCountMenuItem_Click(object sender, EventArgs e)
12295         {
12296             if (this.ExistCurrentPost)
12297             {
12298                 using (FormInfo _info = new FormInfo(this, Properties.Resources.RtCountMenuItem_ClickText1,
12299                                                      GetRetweet_DoWork))
12300                 {
12301                     int retweet_count = 0;
12302
12303                     // ダイアログ表示
12304                     _info.ShowDialog();
12305                     retweet_count = (int)_info.Result;
12306                     if (retweet_count < 0)
12307                     {
12308                         MessageBox.Show(Properties.Resources.RtCountText2);
12309                     }
12310                     else
12311                     {
12312                         MessageBox.Show(retweet_count.ToString() + Properties.Resources.RtCountText1);
12313                     }
12314                 }
12315             }
12316         }
12317
12318         private HookGlobalHotkey _hookGlobalHotkey;
12319         public TweenMain()
12320         {
12321             _hookGlobalHotkey = new HookGlobalHotkey(this);
12322             // この呼び出しは、Windows フォーム デザイナで必要です。
12323             InitializeComponent();
12324
12325             // InitializeComponent() 呼び出しの後で初期化を追加します。
12326
12327             this.SettingDialog.IntervalChanged += this.TimerInterval_Changed;
12328             this.TimerTimeline.Elapsed += this.TimerTimeline_Elapsed;
12329             this._hookGlobalHotkey.HotkeyPressed += _hookGlobalHotkey_HotkeyPressed;
12330             this.gh.NotifyClicked += GrowlHelper_Callback;
12331
12332             // メイリオフォント指定時にタブの最小幅が広くなる問題の対策
12333             this.ListTab.HandleCreated += (s, e) => Win32Api.SetMinTabWidth((TabControl)s, 40);
12334
12335             this._apiGauge = new ToolStripAPIGauge();
12336             this._apiGauge.BorderSides = ToolStripStatusLabelBorderSides.Right;
12337             this.StatusStrip1.Items.Insert(2, this._apiGauge);
12338
12339             this.ReplaceAppName();
12340         }
12341
12342         private void _hookGlobalHotkey_HotkeyPressed(object sender, KeyEventArgs e)
12343         {
12344             if ((this.WindowState == FormWindowState.Normal || this.WindowState == FormWindowState.Maximized) && this.Visible && Form.ActiveForm == this)
12345             {
12346                 //アイコン化
12347                 this.Visible = false;
12348             }
12349             else if (Form.ActiveForm == null)
12350             {
12351                 this.Visible = true;
12352                 if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
12353                 this.Activate();
12354                 this.BringToFront();
12355                 this.StatusText.Focus();
12356             }
12357         }
12358
12359         private void UserPicture_MouseEnter(object sender, EventArgs e)
12360         {
12361             this.UserPicture.Cursor = Cursors.Hand;
12362         }
12363
12364         private void UserPicture_MouseLeave(object sender, EventArgs e)
12365         {
12366             this.UserPicture.Cursor = Cursors.Default;
12367         }
12368
12369         private void UserPicture_DoubleClick(object sender, EventArgs e)
12370         {
12371             if (NameLabel.Tag != null)
12372             {
12373                 OpenUriAsync(MyCommon.TwitterUrl + NameLabel.Tag.ToString());
12374             }
12375         }
12376
12377         private void SplitContainer2_MouseDoubleClick(object sender, MouseEventArgs e)
12378         {
12379             this.MultiLineMenuItem.PerformClick();
12380         }
12381
12382         public PostClass CurPost
12383         {
12384             get { return _curPost; }
12385         }
12386
12387         public bool IsPreviewEnable
12388         {
12389             get { return SettingDialog.PreviewEnable; }
12390         }
12391
12392 #region "画像投稿"
12393         private void ImageSelectMenuItem_Click(object sender, EventArgs e)
12394         {
12395             if (ImageSelectionPanel.Visible == true)
12396             {
12397                 ImagefilePathText.CausesValidation = false;
12398                 TimelinePanel.Visible = true;
12399                 TimelinePanel.Enabled = true;
12400                 ImageSelectionPanel.Visible = false;
12401                 ImageSelectionPanel.Enabled = false;
12402                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12403                 ImagefilePathText.CausesValidation = true;
12404             }
12405             else
12406             {
12407                 ImageSelectionPanel.Visible = true;
12408                 ImageSelectionPanel.Enabled = true;
12409                 TimelinePanel.Visible = false;
12410                 TimelinePanel.Enabled = false;
12411                 ImagefilePathText.Focus();
12412             }
12413         }
12414
12415         private void FilePickButton_Click(object sender, EventArgs e)
12416         {
12417             if (string.IsNullOrEmpty(this.ImageService)) return;
12418             OpenFileDialog1.Filter = this.pictureService[this.ImageService].GetFileOpenDialogFilter();
12419             OpenFileDialog1.Title = Properties.Resources.PickPictureDialog1;
12420             OpenFileDialog1.FileName = "";
12421
12422             try
12423             {
12424                 this.AllowDrop = false;
12425                 if (OpenFileDialog1.ShowDialog() == DialogResult.Cancel) return;
12426             }
12427             finally
12428             {
12429                 this.AllowDrop = true;
12430             }
12431
12432             ImagefilePathText.Text = OpenFileDialog1.FileName;
12433             ImageFromSelectedFile();
12434         }
12435
12436         private void ImagefilePathText_Validating(object sender, CancelEventArgs e)
12437         {
12438             if (ImageCancelButton.Focused)
12439             {
12440                 ImagefilePathText.CausesValidation = false;
12441                 return;
12442             }
12443             ImagefilePathText.Text = ImagefilePathText.Text.Trim();
12444             if (string.IsNullOrEmpty(ImagefilePathText.Text))
12445             {
12446                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12447                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12448             }
12449             else
12450             {
12451                 ImageFromSelectedFile();
12452             }
12453         }
12454
12455         private void ImageFromSelectedFile()
12456         {
12457             try
12458             {
12459                 if (string.IsNullOrEmpty(ImagefilePathText.Text.Trim()) || string.IsNullOrEmpty(this.ImageService))
12460                 {
12461                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12462                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12463                     ImagefilePathText.Text = "";
12464                     return;
12465                 }
12466
12467                 FileInfo fl = new FileInfo(ImagefilePathText.Text.Trim());
12468                 if (!this.pictureService[this.ImageService].CheckValidExtension(fl.Extension))
12469                 {
12470                     //画像以外の形式
12471                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12472                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12473                     ImagefilePathText.Text = "";
12474                     return;
12475                 }
12476
12477                 if (!this.pictureService[this.ImageService].CheckValidFilesize(fl.Extension, fl.Length))
12478                 {
12479                     // ファイルサイズが大きすぎる
12480                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12481                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12482                     ImagefilePathText.Text = "";
12483                     MessageBox.Show("File is too large.");
12484                     return;
12485                 }
12486
12487                 switch (this.pictureService[this.ImageService].GetFileType(fl.Extension))
12488                 {
12489                     case MyCommon.UploadFileType.Invalid:
12490                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12491                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12492                         ImagefilePathText.Text = "";
12493                         break;
12494                     case MyCommon.UploadFileType.Picture:
12495                         Image img = null;
12496                         using (FileStream fs = new FileStream(ImagefilePathText.Text, FileMode.Open, FileAccess.Read))
12497                         {
12498                             img = Image.FromStream(fs);
12499                         }
12500                         ImageSelectedPicture.Image = (new HttpVarious()).CheckValidImage(
12501                                     img,
12502                                     img.Width,
12503                                     img.Height);
12504                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Picture;
12505                         break;
12506                     case MyCommon.UploadFileType.MultiMedia:
12507                         ImageSelectedPicture.Image = Properties.Resources.MultiMediaImage;
12508                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.MultiMedia;
12509                         break;
12510                     default:
12511                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12512                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12513                         ImagefilePathText.Text = "";
12514                         break;
12515                 }
12516             }
12517             catch (FileNotFoundException)
12518             {
12519                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12520                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12521                 ImagefilePathText.Text = "";
12522                 MessageBox.Show("File not found.");
12523             }
12524             catch (Exception)
12525             {
12526                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12527                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12528                 ImagefilePathText.Text = "";
12529                 MessageBox.Show("The type of this file is not image.");
12530             }
12531         }
12532
12533         private void ImageSelection_KeyDown(object sender, KeyEventArgs e)
12534         {
12535             if (e.KeyCode == Keys.Escape)
12536             {
12537                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12538                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12539                 TimelinePanel.Visible = true;
12540                 TimelinePanel.Enabled = true;
12541                 ImageSelectionPanel.Visible = false;
12542                 ImageSelectionPanel.Enabled = false;
12543                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12544                 ImagefilePathText.CausesValidation = true;
12545             }
12546         }
12547
12548         private void ImageSelection_KeyPress(object sender, KeyPressEventArgs e)
12549         {
12550             if (Convert.ToInt32(e.KeyChar) == 0x1B)
12551             {
12552                 ImagefilePathText.CausesValidation = false;
12553                 e.Handled = true;
12554             }
12555         }
12556
12557         private void ImageSelection_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
12558         {
12559             if (e.KeyCode == Keys.Escape)
12560             {
12561                 ImagefilePathText.CausesValidation = false;
12562             }
12563         }
12564
12565         private void SetImageServiceCombo()
12566         {
12567             string svc = "";
12568             if (ImageServiceCombo.SelectedIndex > -1) svc = ImageServiceCombo.SelectedItem.ToString();
12569             ImageServiceCombo.Items.Clear();
12570             
12571             // Add service names to combobox
12572             foreach (var key in pictureService.Keys)
12573             {
12574                 ImageServiceCombo.Items.Add(key);
12575             }
12576
12577             SelectImageServiceComboItem(svc);
12578         }
12579
12580         private void SelectImageServiceComboItem(string svc, int? index = null)
12581         {
12582             int idx;
12583             if (string.IsNullOrEmpty(svc))
12584             {
12585                 idx = index ?? 0;
12586             }
12587             else
12588             {
12589                 idx = ImageServiceCombo.Items.IndexOf(svc);
12590                 if (idx == -1) idx = index ?? 0;
12591             }
12592
12593             try
12594             {
12595                 ImageServiceCombo.SelectedIndex = idx;
12596             }
12597             catch (ArgumentOutOfRangeException)
12598             {
12599                 ImageServiceCombo.SelectedIndex = 0;
12600             }
12601         }
12602
12603         private string ImageService
12604         {
12605             get { return ImageServiceCombo.SelectedItem.ToString(); }
12606         }
12607
12608         private void ImageCancelButton_Click(object sender, EventArgs e)
12609         {
12610             ImagefilePathText.CausesValidation = false;
12611             TimelinePanel.Visible = true;
12612             TimelinePanel.Enabled = true;
12613             ImageSelectionPanel.Visible = false;
12614             ImageSelectionPanel.Enabled = false;
12615             ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12616             ImagefilePathText.CausesValidation = true;
12617         }
12618
12619         private void ImageServiceCombo_SelectedIndexChanged(object sender, EventArgs e)
12620         {
12621             if (ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
12622             {
12623                 try
12624                 {
12625                     FileInfo fi = new FileInfo(ImagefilePathText.Text.Trim());
12626                     if (!this.pictureService[this.ImageService].CheckValidFilesize(fi.Extension, fi.Length))
12627                     {
12628                         ImagefilePathText.Text = "";
12629                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12630                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12631                     }
12632                 }
12633                 catch (Exception)
12634                 {
12635                 }
12636                 _modifySettingCommon = true;
12637                 SaveConfigsAll(false);
12638                 if (this.ImageService == "Twitter")
12639                 {
12640                     this.StatusText_TextChanged(null, null);
12641                 }
12642             }
12643         }
12644 #endregion
12645
12646         private void ListManageToolStripMenuItem_Click(object sender, EventArgs e)
12647         {
12648             using (ListManage form = new ListManage(tw))
12649             {
12650                 form.ShowDialog(this);
12651             }
12652         }
12653
12654         public bool ModifySettingCommon
12655         {
12656             set { _modifySettingCommon = value; }
12657         }
12658
12659         public bool ModifySettingLocal
12660         {
12661             set { _modifySettingLocal = value; }
12662         }
12663
12664         public bool ModifySettingAtId
12665         {
12666             set { _modifySettingAtId = value; }
12667         }
12668
12669         private void SourceLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
12670         {
12671             string link = (string)SourceLinkLabel.Tag;
12672             if (!string.IsNullOrEmpty(link) && e.Button == MouseButtons.Left)
12673             {
12674                 OpenUriAsync(link);
12675             }
12676         }
12677
12678         private void SourceLinkLabel_MouseEnter(object sender, EventArgs e)
12679         {
12680             string link = (string)SourceLinkLabel.Tag;
12681             if (!string.IsNullOrEmpty(link))
12682             {
12683                 StatusLabelUrl.Text = MyCommon.ConvertToReadableUrl(link);
12684             }
12685         }
12686
12687         private void SourceLinkLabel_MouseLeave(object sender, EventArgs e)
12688         {
12689             SetStatusLabelUrl();
12690         }
12691
12692         private void MenuItemCommand_DropDownOpening(object sender, EventArgs e)
12693         {
12694             if (this.ExistCurrentPost && !_curPost.IsDm)
12695                 RtCountMenuItem.Enabled = true;
12696             else
12697                 RtCountMenuItem.Enabled = false;
12698
12699             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco)
12700             //    TinyUrlConvertToolStripMenuItem.Enabled = false;
12701             //else
12702             //    TinyUrlConvertToolStripMenuItem.Enabled = true;
12703         }
12704
12705         private void CopyUserIdStripMenuItem_Click(object sender, EventArgs e)
12706         {
12707             CopyUserId();
12708         }
12709
12710         private void CopyUserId()
12711         {
12712             if (_curPost == null) return;
12713             string clstr = _curPost.ScreenName;
12714             try
12715             {
12716                 Clipboard.SetDataObject(clstr, false, 5, 100);
12717             }
12718             catch (Exception ex)
12719             {
12720                 MessageBox.Show(ex.Message);
12721             }
12722         }
12723
12724         private void ShowRelatedStatusesMenuItem_Click(object sender, EventArgs e) // Handles ShowRelatedStatusesMenuItem.Click, ShowRelatedStatusesMenuItem2.Click
12725         {
12726             if (this.ExistCurrentPost && !_curPost.IsDm)
12727             {
12728                 try
12729                 {
12730                     this.OpenRelatedTab(this._curPost);
12731                 }
12732                 catch (TabException ex)
12733                 {
12734                     MessageBox.Show(this, ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
12735                 }
12736             }
12737         }
12738
12739         /// <summary>
12740         /// 指定されたツイートに対する関連発言タブを開きます
12741         /// </summary>
12742         /// <param name="post">表示する対象となるツイート</param>
12743         /// <exception cref="TabException">名前の重複が多すぎてタブを作成できない場合</exception>
12744         private void OpenRelatedTab(PostClass post)
12745         {
12746             var tabRelated = this._statuses.GetTabByType(MyCommon.TabUsageType.Related);
12747             string tabName;
12748
12749             if (tabRelated == null)
12750             {
12751                 tabName = this._statuses.MakeTabName("Related Tweets");
12752
12753                 this.AddNewTab(tabName, false, MyCommon.TabUsageType.Related);
12754                 this._statuses.AddTab(tabName, MyCommon.TabUsageType.Related, null);
12755
12756                 tabRelated = this._statuses.GetTabByType(MyCommon.TabUsageType.Related);
12757                 tabRelated.UnreadManage = false;
12758                 tabRelated.Notify = false;
12759             }
12760             else
12761             {
12762                 tabName = tabRelated.TabName;
12763             }
12764
12765             tabRelated.RelationTargetPost = post;
12766             this.ClearTab(tabName, false);
12767
12768             for (int i = 0; i < this.ListTab.TabPages.Count; i++)
12769             {
12770                 var tabPage = this.ListTab.TabPages[i];
12771                 if (tabName == tabPage.Text)
12772                 {
12773                     this.ListTab.SelectedIndex = i;
12774                     this.ListTabSelect(tabPage);
12775                     break;
12776                 }
12777             }
12778
12779             this.GetTimeline(MyCommon.WORKERTYPE.Related, 1, 1, tabName);
12780         }
12781
12782         private void CacheInfoMenuItem_Click(object sender, EventArgs e)
12783         {
12784             StringBuilder buf = new StringBuilder();
12785             //buf.AppendFormat("キャッシュメモリ容量         : {0}bytes({1}MB)" + Environment.NewLine, IconCache.CacheMemoryLimit, ((ImageDictionary)IconCache).CacheMemoryLimit / 1048576);
12786             //buf.AppendFormat("物理メモリ使用割合           : {0}%" + Environment.NewLine, IconCache.PhysicalMemoryLimit);
12787             buf.AppendFormat("キャッシュエントリ保持数     : {0}" + Environment.NewLine, IconCache.CacheCount);
12788             buf.AppendFormat("キャッシュエントリ破棄数     : {0}" + Environment.NewLine, IconCache.CacheRemoveCount);
12789             MessageBox.Show(buf.ToString(), "アイコンキャッシュ使用状況");
12790         }
12791
12792         private void tw_UserIdChanged()
12793         {
12794             this._modifySettingCommon = true;
12795         }
12796
12797 #region "Userstream"
12798         private bool _isActiveUserstream = false;
12799
12800         private void tw_PostDeleted(long id)
12801         {
12802             try
12803             {
12804                 if (InvokeRequired && !IsDisposed)
12805                 {
12806                     Invoke((Action) (() =>
12807                            {
12808                                _statuses.RemovePostReserve(id);
12809                                if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(id))
12810                                {
12811                                    this.PurgeListViewItemCache();
12812                                    ((DetailsListView)_curTab.Tag).Update();
12813                                    if (_curPost != null && _curPost.StatusId == id) DispSelectedPost(true);
12814                                }
12815                            }));
12816                     return;
12817                 }
12818             }
12819             catch (ObjectDisposedException)
12820             {
12821                 return;
12822             }
12823             catch (InvalidOperationException)
12824             {
12825                 return;
12826             }
12827         }
12828
12829         private void tw_NewPostFromStream()
12830         {
12831             if (SettingDialog.ReadOldPosts)
12832             {
12833                 _statuses.SetRead(); //新着時未読クリア
12834             }
12835
12836             int rsltAddCount = _statuses.DistributePosts();
12837             lock (_syncObject)
12838             {
12839                 DateTime tm = DateTime.Now;
12840                 if (_tlTimestamps.ContainsKey(tm))
12841                 {
12842                     _tlTimestamps[tm] += rsltAddCount;
12843                 }
12844                 else
12845                 {
12846                     _tlTimestamps.Add(tm, rsltAddCount);
12847                 }
12848                 DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
12849                 List<DateTime> keys = new List<DateTime>();
12850                 _tlCount = 0;
12851                 foreach (DateTime key in _tlTimestamps.Keys)
12852                 {
12853                     if (key.CompareTo(oneHour) < 0)
12854                         keys.Add(key);
12855                     else
12856                         _tlCount += _tlTimestamps[key];
12857                 }
12858                 foreach (DateTime key in keys)
12859                 {
12860                     _tlTimestamps.Remove(key);
12861                 }
12862                 keys.Clear();
12863
12864                 //Static DateTime before = Now;
12865                 //if (before.Subtract(Now).Seconds > -5) return;
12866                 //before = Now;
12867             }
12868
12869             if (SettingDialog.UserstreamPeriodInt > 0) return;
12870
12871             try
12872             {
12873                 if (InvokeRequired && !IsDisposed)
12874                 {
12875                     Invoke(new Action<bool>(RefreshTimeline), true);
12876                     return;
12877                 }
12878             }
12879             catch (ObjectDisposedException)
12880             {
12881                 return;
12882             }
12883             catch (InvalidOperationException)
12884             {
12885                 return;
12886             }
12887         }
12888
12889         private void tw_UserStreamStarted()
12890         {
12891             this._isActiveUserstream = true;
12892             try
12893             {
12894                 if (InvokeRequired && !IsDisposed)
12895                 {
12896                     Invoke(new MethodInvoker(tw_UserStreamStarted));
12897                     return;
12898                 }
12899             }
12900             catch (ObjectDisposedException)
12901             {
12902                 return;
12903             }
12904             catch (InvalidOperationException)
12905             {
12906                 return;
12907             }
12908
12909             MenuItemUserStream.Text = "&UserStream ▶";
12910             MenuItemUserStream.Enabled = true;
12911             StopToolStripMenuItem.Text = "&Stop";
12912             StopToolStripMenuItem.Enabled = true;
12913
12914             StatusLabel.Text = "UserStream Started.";
12915         }
12916
12917         private void tw_UserStreamStopped()
12918         {
12919             this._isActiveUserstream = false;
12920             try
12921             {
12922                 if (InvokeRequired && !IsDisposed)
12923                 {
12924                     Invoke(new MethodInvoker(tw_UserStreamStopped));
12925                     return;
12926                 }
12927             }
12928             catch (ObjectDisposedException)
12929             {
12930                 return;
12931             }
12932             catch (InvalidOperationException)
12933             {
12934                 return;
12935             }
12936
12937             MenuItemUserStream.Text = "&UserStream ■";
12938             MenuItemUserStream.Enabled = true;
12939             StopToolStripMenuItem.Text = "&Start";
12940             StopToolStripMenuItem.Enabled = true;
12941
12942             StatusLabel.Text = "UserStream Stopped.";
12943         }
12944
12945         private void tw_UserStreamEventArrived(Twitter.FormattedEvent ev)
12946         {
12947             try
12948             {
12949                 if (InvokeRequired && !IsDisposed)
12950                 {
12951                     Invoke(new Action<Twitter.FormattedEvent>(tw_UserStreamEventArrived), ev);
12952                     return;
12953                 }
12954             }
12955             catch (ObjectDisposedException)
12956             {
12957                 return;
12958             }
12959             catch (InvalidOperationException)
12960             {
12961                 return;
12962             }
12963             StatusLabel.Text = "Event: " + ev.Event;
12964             //if (ev.Event == "favorite")
12965             //{
12966             //    NotifyFavorite(ev);
12967             //}
12968             NotifyEvent(ev);
12969             if (ev.Event == "favorite" || ev.Event == "unfavorite")
12970             {
12971                 if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(ev.Id))
12972                 {
12973                     this.PurgeListViewItemCache();
12974                     ((DetailsListView)_curTab.Tag).Update();
12975                 }
12976                 if (ev.Event == "unfavorite" && ev.Username.ToLower().Equals(tw.Username.ToLower()))
12977                 {
12978                     RemovePostFromFavTab(new long[] {ev.Id});
12979                 }
12980             }
12981         }
12982
12983         private void NotifyEvent(Twitter.FormattedEvent ev)
12984         {
12985             //新着通知 
12986             if (BalloonRequired(ev))
12987             {
12988                 NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
12989                 //if (SettingDialog.DispUsername) NotifyIcon1.BalloonTipTitle = tw.Username + " - "; else NotifyIcon1.BalloonTipTitle = "";
12990                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [" + ev.Event.ToUpper() + "] by " + ((string)(!string.IsNullOrEmpty(ev.Username) ? ev.Username : ""), string);
12991                 StringBuilder title = new StringBuilder();
12992                 if (SettingDialog.DispUsername)
12993                 {
12994                     title.Append(tw.Username);
12995                     title.Append(" - ");
12996                 }
12997                 else
12998                 {
12999                     //title.Clear();
13000                 }
13001                 title.Append(Application.ProductName);
13002                 title.Append(" [");
13003                 title.Append(ev.Event.ToUpper());
13004                 title.Append("] by ");
13005                 if (!string.IsNullOrEmpty(ev.Username))
13006                 {
13007                     title.Append(ev.Username.ToString());
13008                 }
13009                 else
13010                 {
13011                     //title.Append("");
13012                 }
13013                 string text;
13014                 if (!string.IsNullOrEmpty(ev.Target))
13015                 {
13016                     //NotifyIcon1.BalloonTipText = ev.Target;
13017                     text = ev.Target;
13018                 }
13019                 else
13020                 {
13021                     //NotifyIcon1.BalloonTipText = " ";
13022                     text = " ";
13023                 }
13024                 //NotifyIcon1.ShowBalloonTip(500);
13025                 if (SettingDialog.IsNotifyUseGrowl)
13026                 {
13027                     gh.Notify(GrowlHelper.NotifyType.UserStreamEvent,
13028                               ev.Id.ToString(), title.ToString(), text);
13029                 }
13030                 else
13031                 {
13032                     NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
13033                     NotifyIcon1.BalloonTipTitle = title.ToString();
13034                     NotifyIcon1.BalloonTipText = text;
13035                     NotifyIcon1.ShowBalloonTip(500);
13036                 }
13037             }
13038
13039             //サウンド再生
13040             string snd = SettingDialog.EventSoundFile;
13041             if (!_initial && SettingDialog.PlaySound && !string.IsNullOrEmpty(snd))
13042             {
13043                 if ((ev.Eventtype & SettingDialog.EventNotifyFlag) != 0 && IsMyEventNotityAsEventType(ev))
13044                 {
13045                     try
13046                     {
13047                         string dir = Application.StartupPath;
13048                         if (Directory.Exists(Path.Combine(dir, "Sounds")))
13049                         {
13050                             dir = Path.Combine(dir, "Sounds");
13051                         }
13052                         using (SoundPlayer player = new SoundPlayer(Path.Combine(dir, snd)))
13053                         {
13054                             player.Play();
13055                         }
13056                     }
13057                     catch (Exception)
13058                     {
13059                     }
13060                 }
13061             }
13062         }
13063
13064         private void StopToolStripMenuItem_Click(object sender, EventArgs e)
13065         {
13066             MenuItemUserStream.Enabled = false;
13067             if (StopRefreshAllMenuItem.Checked)
13068             {
13069                 StopRefreshAllMenuItem.Checked = false;
13070                 return;
13071             }
13072             if (this._isActiveUserstream)
13073             {
13074                 tw.StopUserStream();
13075             }
13076             else
13077             {
13078                 tw.StartUserStream();
13079             }
13080         }
13081
13082         private static string inputTrack = "";
13083
13084         private void TrackToolStripMenuItem_Click(object sender, EventArgs e)
13085         {
13086             if (TrackToolStripMenuItem.Checked)
13087             {
13088                 using (InputTabName inputForm = new InputTabName())
13089                 {
13090                     inputForm.TabName = inputTrack;
13091                     inputForm.FormTitle = "Input track word";
13092                     inputForm.FormDescription = "Track word";
13093                     if (inputForm.ShowDialog() != DialogResult.OK)
13094                     {
13095                         TrackToolStripMenuItem.Checked = false;
13096                         return;
13097                     }
13098                     inputTrack = inputForm.TabName.Trim();
13099                 }
13100                 if (!inputTrack.Equals(tw.TrackWord))
13101                 {
13102                     tw.TrackWord = inputTrack;
13103                     this._modifySettingCommon = true;
13104                     TrackToolStripMenuItem.Checked = !string.IsNullOrEmpty(inputTrack);
13105                     tw.ReconnectUserStream();
13106                 }
13107             }
13108             else
13109             {
13110                 tw.TrackWord = "";
13111                 tw.ReconnectUserStream();
13112             }
13113             this._modifySettingCommon = true;
13114         }
13115
13116         private void AllrepliesToolStripMenuItem_Click(object sender, EventArgs e)
13117         {
13118             tw.AllAtReply = AllrepliesToolStripMenuItem.Checked;
13119             this._modifySettingCommon = true;
13120             tw.ReconnectUserStream();
13121         }
13122
13123         private void EventViewerMenuItem_Click(object sender, EventArgs e)
13124         {
13125             if (evtDialog == null || evtDialog.IsDisposed)
13126             {
13127                 evtDialog = null;
13128                 evtDialog = new EventViewerDialog();
13129                 evtDialog.Owner = this;
13130                 //親の中央に表示
13131                 Point pos = evtDialog.Location;
13132                 pos.X = Convert.ToInt32(this.Location.X + this.Size.Width / 2 - evtDialog.Size.Width / 2);
13133                 pos.Y = Convert.ToInt32(this.Location.Y + this.Size.Height / 2 - evtDialog.Size.Height / 2);
13134                 evtDialog.Location = pos;
13135             }
13136             evtDialog.EventSource = tw.StoredEvent;
13137             if (!evtDialog.Visible)
13138             {
13139                 evtDialog.Show(this);
13140             }
13141             else
13142             {
13143                 evtDialog.Activate();
13144             }
13145             this.TopMost = this.SettingDialog.AlwaysTop;
13146         }
13147 #endregion
13148
13149         private void TweenRestartMenuItem_Click(object sender, EventArgs e)
13150         {
13151             MyCommon._endingFlag = true;
13152             try
13153             {
13154                 this.Close();
13155                 Application.Restart();
13156             }
13157             catch (Exception)
13158             {
13159                 MessageBox.Show("Failed to restart. Please run " + Application.ProductName + " manually.");
13160             }
13161         }
13162
13163         private void OpenOwnFavedMenuItem_Click(object sender, EventArgs e)
13164         {
13165             if (!string.IsNullOrEmpty(tw.Username)) OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + tw.Username + "/recent");
13166         }
13167
13168         private void OpenOwnHomeMenuItem_Click(object sender, EventArgs e)
13169         {
13170             OpenUriAsync(MyCommon.TwitterUrl + tw.Username);
13171         }
13172
13173         private void doTranslation(string str)
13174         {
13175             Bing _bing = new Bing();
13176             string buf = "";
13177             if (string.IsNullOrEmpty(str)) return;
13178             string srclng = "";
13179             string dstlng = SettingDialog.TranslateLanguage;
13180             string msg = "";
13181             if (srclng != dstlng && _bing.Translate("", dstlng, str, out buf))
13182             {
13183                 PostBrowser.DocumentText = createDetailHtml(buf);
13184             }
13185             else
13186             {
13187                 if (msg.StartsWith("Err:"))
13188                     StatusLabel.Text = msg;
13189             }
13190         }
13191
13192         private void TranslationToolStripMenuItem_Click(object sender, EventArgs e)
13193         {
13194             if (!this.ExistCurrentPost) return;
13195             doTranslation(_curPost.TextFromApi);
13196         }
13197
13198         private void SelectionTranslationToolStripMenuItem_Click(object sender, EventArgs e)
13199         {
13200             doTranslation(WebBrowser_GetSelectionText(ref PostBrowser));
13201         }
13202
13203         private bool ExistCurrentPost
13204         {
13205             get
13206             {
13207                 if (_curPost == null) return false;
13208                 if (_curPost.IsDeleted) return false;
13209                 return true;
13210             }
13211         }
13212
13213         private void ShowUserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
13214         {
13215             ShowUserTimeline();
13216         }
13217
13218         public bool FavEventChangeUnread
13219         {
13220             get { return SettingDialog.FavEventUnread; }
13221         }
13222
13223         private string GetUserIdFromCurPostOrInput(string caption)
13224         {
13225             string id = "";
13226             if (_curPost != null)
13227             {
13228                 id = _curPost.ScreenName;
13229             }
13230             using (InputTabName inputName = new InputTabName())
13231             {
13232                 inputName.FormTitle = caption;
13233                 inputName.FormDescription = Properties.Resources.FRMessage1;
13234                 inputName.TabName = id;
13235                 if (inputName.ShowDialog() == DialogResult.OK &&
13236                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
13237                 {
13238                     id = inputName.TabName.Trim();
13239                 }
13240                 else
13241                 {
13242                     id = "";
13243                 }
13244             }
13245             return id;
13246         }
13247
13248         private void UserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
13249         {
13250             string id = GetUserIdFromCurPostOrInput("Show UserTimeline");
13251             if (!string.IsNullOrEmpty(id))
13252             {
13253                 AddNewTabForUserTimeline(id);
13254             }
13255         }
13256
13257         private void UserFavorareToolStripMenuItem_Click(object sender, EventArgs e)
13258         {
13259             string id = GetUserIdFromCurPostOrInput("Show Favstar");
13260             if (!string.IsNullOrEmpty(id))
13261             {
13262                 OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + id + "/recent");
13263             }
13264         }
13265
13266         private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
13267         {
13268             if (e.Mode == Microsoft.Win32.PowerModes.Resume) osResumed = true;
13269         }
13270
13271         private void TimelineRefreshEnableChange(bool isEnable)
13272         {
13273             if (isEnable)
13274             {
13275                 tw.StartUserStream();
13276             }
13277             else
13278             {
13279                 tw.StopUserStream();
13280             }
13281             TimerTimeline.Enabled = isEnable;
13282         }
13283
13284         private void StopRefreshAllMenuItem_CheckedChanged(object sender, EventArgs e)
13285         {
13286             TimelineRefreshEnableChange(!StopRefreshAllMenuItem.Checked);
13287         }
13288
13289         private void OpenUserAppointUrl()
13290         {
13291             if (SettingDialog.UserAppointUrl != null)
13292             {
13293                 if (SettingDialog.UserAppointUrl.Contains("{ID}") || SettingDialog.UserAppointUrl.Contains("{STATUS}"))
13294                 {
13295                     if (_curPost != null)
13296                     {
13297                         string xUrl = SettingDialog.UserAppointUrl;
13298                         xUrl = xUrl.Replace("{ID}", _curPost.ScreenName);
13299                         if (_curPost.RetweetedId != null)
13300                         {
13301                             xUrl = xUrl.Replace("{STATUS}", _curPost.RetweetedId.ToString());
13302                         }
13303                         else
13304                         {
13305                             xUrl = xUrl.Replace("{STATUS}", _curPost.StatusId.ToString());
13306                         }
13307                         OpenUriAsync(xUrl);
13308                     }
13309                 }
13310                 else
13311                 {
13312                     OpenUriAsync(SettingDialog.UserAppointUrl);
13313                 }
13314             }
13315         }
13316
13317         private void OpenUserSpecifiedUrlMenuItem_Click(object sender, EventArgs e)
13318         {
13319             OpenUserAppointUrl();
13320         }
13321
13322         private void ImageSelectionPanel_VisibleChanged(object sender, EventArgs e)
13323         {
13324             this.StatusText_TextChanged(null, null);
13325         }
13326
13327         private void SourceCopyMenuItem_Click(object sender, EventArgs e)
13328         {
13329             string selText = SourceLinkLabel.Text;
13330             try
13331             {
13332                 Clipboard.SetDataObject(selText, false, 5, 100);
13333             }
13334             catch (Exception ex)
13335             {
13336                 MessageBox.Show(ex.Message);
13337             }
13338         }
13339
13340         private void SourceUrlCopyMenuItem_Click(object sender, EventArgs e)
13341         {
13342             string selText = (string)SourceLinkLabel.Tag;
13343             try
13344             {
13345                 Clipboard.SetDataObject(selText, false, 5, 100);
13346             }
13347             catch (Exception ex)
13348             {
13349                 MessageBox.Show(ex.Message);
13350             }
13351         }
13352
13353         private void ContextMenuSource_Opening(object sender, CancelEventArgs e)
13354         {
13355             if (_curPost == null || !ExistCurrentPost || _curPost.IsDm)
13356             {
13357                 SourceCopyMenuItem.Enabled = false;
13358                 SourceUrlCopyMenuItem.Enabled = false;
13359             }
13360             else
13361             {
13362                 SourceCopyMenuItem.Enabled = true;
13363                 SourceUrlCopyMenuItem.Enabled = true;
13364             }
13365         }
13366
13367         private void GrowlHelper_Callback(object sender, GrowlHelper.NotifyCallbackEventArgs e)
13368         {
13369             if (Form.ActiveForm == null)
13370             {
13371                 this.BeginInvoke((Action) (() =>
13372                 {
13373                     this.Visible = true;
13374                     if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
13375                     this.Activate();
13376                     this.BringToFront();
13377                     if (e.NotifyType == GrowlHelper.NotifyType.DirectMessage)
13378                     {
13379                         if (!this.GoDirectMessage(e.StatusId)) this.StatusText.Focus();
13380                     }
13381                     else
13382                     {
13383                         if (!this.GoStatus(e.StatusId)) this.StatusText.Focus();
13384                     }
13385                 }));
13386             }
13387         }
13388
13389         private void ReplaceAppName()
13390         {
13391             MatomeMenuItem.Text = MyCommon.ReplaceAppName(MatomeMenuItem.Text);
13392             AboutMenuItem.Text = MyCommon.ReplaceAppName(AboutMenuItem.Text);
13393         }
13394
13395         private void tweetThumbnail1_ThumbnailLoading(object sender, EventArgs e)
13396         {
13397             this.SplitContainer3.Panel2Collapsed = false;
13398         }
13399
13400         private void tweetThumbnail1_ThumbnailDoubleClick(object sender, ThumbnailDoubleClickEventArgs e)
13401         {
13402             this.OpenThumbnailPicture(e.Thumbnail);
13403         }
13404
13405         private void tweetThumbnail1_ThumbnailImageSearchClick(object sender, ThumbnailImageSearchEventArgs e)
13406         {
13407             this.OpenUriAsync(e.ImageUrl);
13408         }
13409
13410         private void OpenThumbnailPicture(ThumbnailInfo thumbnail)
13411         {
13412             this.OpenUriAsync(Uri.EscapeUriString(thumbnail.ImageUrl));
13413         }
13414
13415         private void TwitterApiStatusToolStripMenuItem_Click(object sender, EventArgs e)
13416         {
13417             this.OpenUriAsync(Twitter.ServiceAvailabilityStatusUrl);
13418         }
13419
13420         private void PostButton_KeyDown(object sender, KeyEventArgs e)
13421         {
13422             if (e.KeyCode == Keys.Space)
13423             {
13424                 this.JumpUnreadMenuItem_Click(null, null);
13425
13426                 e.SuppressKeyPress = true;
13427             }
13428         }
13429     }
13430 }