OSDN Git Service

サムネイル表示を無効にする設定が効かないバグを修正 (thx @5px!)
[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.Data;
35 using System.Drawing;
36 using System.Linq;
37 using System.Text;
38 using System.Windows.Forms;
39 using OpenTween.OpenTweenCustomControl;
40 using System.IO;
41 using System.Text.RegularExpressions;
42 using System.Reflection;
43 using System.Threading;
44 using System.Media;
45 using System.Web;
46 using System.Diagnostics;
47 using OpenTween.Thumbnail;
48
49 namespace OpenTween
50 {
51     public partial class TweenMain : Form
52     {
53         //各種設定
54         private Size _mySize;           //画面サイズ
55         private Point _myLoc;           //画面位置
56         private int _mySpDis;           //区切り位置
57         private int _mySpDis2;          //発言欄区切り位置
58         private int _mySpDis3;          //プレビュー区切り位置
59         private int _myAdSpDis;         //Ad区切り位置
60         private int _iconSz;            //アイコンサイズ(現在は16、24、48の3種類。将来直接数字指定可能とする 注:24x24の場合に26と指定しているのはMSゴシック系フォントのための仕様)
61         private bool _iconCol;          //1列表示の時true(48サイズのとき)
62
63         //雑多なフラグ類
64         private bool _initial;         //true:起動時処理中
65         private bool _initialLayout = true;
66         private bool _ignoreConfigSave;         //true:起動時処理中
67         private bool _tabDrag;           //タブドラッグ中フラグ(DoDragDropを実行するかの判定用)
68         private TabPage _beforeSelectedTab; //タブが削除されたときに前回選択されていたときのタブを選択する為に保持
69         private Point _tabMouseDownPoint;
70         private string _rclickTabName;      //右クリックしたタブの名前(Tabコントロール機能不足対応)
71         private readonly object _syncObject = new object();    //ロック用
72         private const string detailHtmlFormatMono1 = "<html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=8\"><style type=\"text/css\"><!-- pre {font-family: \"";
73         private const string detailHtmlFormat2 = "\", sans-serif; font-size: ";
74         private const string detailHtmlFormat3 = "pt; margin: 0; word-wrap: break-word; color:rgb(";
75         private const string detailHtmlFormat4 = ");} a:link, a:visited, a:active, a:hover {color:rgb(";
76         private const string detailHtmlFormat5 = "); } --></style></head><body style=\"margin:0px; background-color:rgb(";
77         private const string detailHtmlFormatMono6 = ");\"><pre>";
78         private const string detailHtmlFormatMono7 = "</pre></body></html>";
79         private const string detailHtmlFormat1 = "<html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=8\"><style type=\"text/css\"><!-- p {font-family: \"";
80         private const string detailHtmlFormat6 = ");\"><p><span style=\"vertical-align:text-bottom\">";
81         private const string detailHtmlFormat7 = "</span></p></body></html>";
82         private string detailHtmlFormatHeader;
83         private string detailHtmlFormatFooter;
84         private bool _myStatusError = false;
85         private bool _myStatusOnline = false;
86         private bool soundfileListup = false;
87         private SpaceKeyCanceler _spaceKeyCanceler;
88         private FormWindowState _formWindowState = FormWindowState.Normal; // フォームの状態保存用 通知領域からアイコンをクリックして復帰した際に使用する
89
90         //設定ファイル関連
91         //private SettingToConfig _cfg; //旧
92         private SettingLocal _cfgLocal;
93         private SettingCommon _cfgCommon;
94         private bool _modifySettingLocal = false;
95         private bool _modifySettingCommon = false;
96         private bool _modifySettingAtId = false;
97
98         //twitter解析部
99         private Twitter tw = new Twitter();
100
101         //Growl呼び出し部
102         private GrowlHelper gh = new GrowlHelper(Application.ProductName);
103
104         //サブ画面インスタンス
105         private AppendSettingDialog SettingDialog = AppendSettingDialog.Instance;       //設定画面インスタンス
106         private SearchWord SearchDialog = new SearchWord();     //検索画面インスタンス
107         private FilterDialog fltDialog = new FilterDialog(); //フィルター編集画面
108         private OpenURL UrlDialog = new OpenURL();
109         public AtIdSupplement AtIdSupl;     //@id補助
110         public AtIdSupplement HashSupl;    //Hashtag補助
111         public HashtagManage HashMgr;
112         private EventViewerDialog evtDialog;
113
114         //表示フォント、色、アイコン
115         private Font _fntUnread;            //未読用フォント
116         private Color _clUnread;            //未読用文字色
117         private Font _fntReaded;            //既読用フォント
118         private Color _clReaded;            //既読用文字色
119         private Color _clFav;               //Fav用文字色
120         private Color _clOWL;               //片思い用文字色
121         private Color _clRetweet;               //Retweet用文字色
122         private Font _fntDetail;            //発言詳細部用フォント
123         private Color _clDetail;              //発言詳細部用色
124         private Color _clDetailLink;          //発言詳細部用リンク文字色
125         private Color _clDetailBackcolor;     //発言詳細部用背景色
126         private Color _clSelf;              //自分の発言用背景色
127         private Color _clAtSelf;            //自分宛返信用背景色
128         private Color _clTarget;            //選択発言者の他の発言用背景色
129         private Color _clAtTarget;          //選択発言中の返信先用背景色
130         private Color _clAtFromTarget;      //選択発言者への返信発言用背景色
131         private Color _clAtTo;              //選択発言の唯一@先
132         private Color _clListBackcolor;       //リスト部通常発言背景色
133         private Color _clInputBackcolor;      //入力欄背景色
134         private Color _clInputFont;           //入力欄文字色
135         private Font _fntInputFont;           //入力欄フォント
136         private IDictionary<string, Image> TIconDic;        //アイコン画像リスト
137         private Icon NIconAt;               //At.ico             タスクトレイアイコン:通常時
138         private Icon NIconAtRed;            //AtRed.ico          タスクトレイアイコン:通信エラー時
139         private Icon NIconAtSmoke;          //AtSmoke.ico        タスクトレイアイコン:オフライン時
140         private Icon[] NIconRefresh = new Icon[4];       //Refresh.ico        タスクトレイアイコン:更新中(アニメーション用に4種類を保持するリスト)
141         private Icon TabIcon;               //Tab.ico            未読のあるタブ用アイコン
142         private Icon MainIcon;              //Main.ico           画面左上のアイコン
143         private Icon ReplyIcon;               //5g
144         private Icon ReplyIconBlink;          //6g
145
146         private PostClass _anchorPost;
147         private bool _anchorFlag;        //true:関連発言移動中(関連移動以外のオペレーションをするとfalseへ。trueだとリスト背景色をアンカー発言選択中として描画)
148
149         private List<PostingStatus> _history = new List<PostingStatus>();   //発言履歴
150         private int _hisIdx;                  //発言履歴カレントインデックス
151
152         //発言投稿時のAPI引数(発言編集時に設定。手書きreplyでは設定されない)
153         private long _reply_to_id;     // リプライ先のステータスID 0の場合はリプライではない 注:複数あてのものはリプライではない
154         private string _reply_to_name;    // リプライ先ステータスの書き込み者の名前
155
156         //時速表示用
157         private List<DateTime> _postTimestamps = new List<DateTime>();
158         private List<DateTime> _favTimestamps = new List<DateTime>();
159         private Dictionary<DateTime, int> _tlTimestamps = new Dictionary<DateTime, int>();
160         private int _tlCount;
161
162         // 以下DrawItem関連
163         private SolidBrush _brsHighLight = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
164         private SolidBrush _brsHighLightText = new SolidBrush(Color.FromKnownColor(KnownColor.HighlightText));
165         private SolidBrush _brsForeColorUnread;
166         private SolidBrush _brsForeColorReaded;
167         private SolidBrush _brsForeColorFav;
168         private SolidBrush _brsForeColorOWL;
169         private SolidBrush _brsForeColorRetweet;
170         private SolidBrush _brsBackColorMine;
171         private SolidBrush _brsBackColorAt;
172         private SolidBrush _brsBackColorYou;
173         private SolidBrush _brsBackColorAtYou;
174         private SolidBrush _brsBackColorAtFromTarget;
175         private SolidBrush _brsBackColorAtTo;
176         private SolidBrush _brsBackColorNone;
177         private SolidBrush _brsDeactiveSelection = new SolidBrush(Color.FromKnownColor(KnownColor.ButtonFace)); //Listにフォーカスないときの選択行の背景色
178         private StringFormat sfTab = new StringFormat();
179
180         //////////////////////////////////////////////////////////////////////////////////////////////////////////
181         private ToolStripAPIGauge _apiGauge = new ToolStripAPIGauge();
182         private TabInformations _statuses;
183         private ListViewItem[] _itemCache;
184         private int _itemCacheIndex;
185         private PostClass[] _postCache;
186         private TabPage _curTab;
187         private int _curItemIndex;
188         private DetailsListView _curList;
189         private PostClass _curPost;
190         private bool _isColumnChanged = false;
191         private bool _waitTimeline = false;
192         private bool _waitReply = false;
193         private bool _waitDm = false;
194         private bool _waitFav = false;
195         private bool _waitPubSearch = false;
196         private bool _waitUserTimeline = false;
197         private bool _waitLists = false;
198         private BackgroundWorker[] _bw = new BackgroundWorker[20];
199         private BackgroundWorker _bwFollower;
200         private InternetSecurityManager SecurityManager;
201
202         private int UnreadCounter = -1;
203         private int UnreadAtCounter = -1;
204
205         private string[] ColumnOrgText = new string[9];
206         private string[] ColumnText = new string[9];
207
208         private bool _DoFavRetweetFlags = false;
209         private bool osResumed = false;
210         private Dictionary<string, IMultimediaShareService> pictureService;
211
212         //////////////////////////////////////////////////////////////////////////////////////////////////////////
213         private string _postBrowserStatusText = "";
214
215         private bool _colorize = false;
216
217         private System.Timers.Timer TimerTimeline = new System.Timers.Timer();
218
219         private ImageListViewItem displayItem;
220
221         //URL短縮のUndo用
222         private struct urlUndo
223         {
224             public string Before;
225             public string After;
226         }
227
228         private List<urlUndo> urlUndoBuffer = null;
229
230         private struct ReplyChain
231         {
232             public long OriginalId;
233             public long InReplyToId;
234             public TabPage OriginalTab;
235
236             public ReplyChain(long originalId, long inReplyToId, TabPage originalTab)
237             {
238                 this.OriginalId = originalId;
239                 this.InReplyToId = inReplyToId;
240                 this.OriginalTab = originalTab;
241             }
242         }
243
244         private Stack<ReplyChain> replyChains; //[, ]でのリプライ移動の履歴
245         private Stack<Tuple<TabPage, PostClass>> selectPostChains = new Stack<Tuple<TabPage, PostClass>>(); //ポスト選択履歴
246
247         //Backgroundworkerの処理結果通知用引数構造体
248         private class GetWorkerResult
249         {
250             public string retMsg = "";                     //処理結果詳細メッセージ。エラー時に値がセットされる
251             public int page;                      //取得対象ページ番号
252             public int endPage = 0;                   //取得終了ページ番号(継続可能ならインクリメントされて返る。pageと比較して継続判定)
253             public MyCommon.WORKERTYPE type;                   //処理種別
254             public Dictionary<string, Image> imgs = null;                    //新規取得したアイコンイメージ
255             public string tName = "";                  //Fav追加・削除時のタブ名
256             public List<long> ids = null;               //Fav追加・削除時のID
257             public List<long> sIds = null;                  //Fav追加・削除成功分のID
258             public bool newDM = false;
259             public int addCount;
260             public PostingStatus status;
261         }
262
263         //Backgroundworkerへ処理内容を通知するための引数用構造体
264         private class GetWorkerArg
265         {
266             public int page;                      //処理対象ページ番号
267             public int endPage;                   //処理終了ページ番号(起動時の読み込みページ数。通常時はpageと同じ値をセット)
268             public MyCommon.WORKERTYPE type;                   //処理種別
269             public string url = "";            //URLをブラウザで開くときのアドレス
270             public PostingStatus status = new PostingStatus();          //発言POST時の発言内容
271             public List<long> ids;               //Fav追加・削除時のItemIndex
272             public List<long> sIds;              //Fav追加・削除成功分のItemIndex
273             public string tName = "";            //Fav追加・削除時のタブ名
274         }
275
276         //検索処理タイプ
277         private enum SEARCHTYPE
278         {
279             DialogSearch,
280             NextSearch,
281             PrevSearch,
282         }
283
284         private class PostingStatus
285         {
286             public string status = "";
287             public long inReplyToId = 0;
288             public string inReplyToName = "";
289             public string imageService = "";      //画像投稿サービス名
290             public string imagePath = "";
291             public PostingStatus()
292             {
293             }
294             public PostingStatus(string status, long replyToId, string replyToName)
295             {
296                 this.status = status;
297                 this.inReplyToId = replyToId;
298                 this.inReplyToName = replyToName;
299             }
300         }
301
302         private class SpaceKeyCanceler : NativeWindow, IDisposable
303         {
304             int WM_KEYDOWN = 0x100;
305             int VK_SPACE = 0x20;
306
307             public SpaceKeyCanceler(Control control)
308             {
309                 this.AssignHandle(control.Handle);
310             }
311
312             protected override void WndProc(ref Message m)
313             {
314                 if ((m.Msg == WM_KEYDOWN) && ((int)m.WParam == VK_SPACE))
315                 {
316                     if (SpaceCancel != null)
317                         SpaceCancel(this, EventArgs.Empty);
318                     return;
319                 }
320
321                 base.WndProc(ref m);
322             }
323
324             public event EventHandler SpaceCancel;
325
326             public void Dispose()
327             {
328                 this.ReleaseHandle();
329             }
330         }
331
332         private void TweenMain_Activated(object sender, EventArgs e)
333         {
334             //画面がアクティブになったら、発言欄の背景色戻す
335             if (StatusText.Focused)
336             {
337                 this.StatusText_Enter(this.StatusText, System.EventArgs.Empty);
338             }
339         }
340
341         private void TweenMain_Disposed(object sender, EventArgs e)
342         {
343             //後始末
344             SettingDialog.Dispose();
345             SearchDialog.Dispose();
346             fltDialog.Dispose();
347             UrlDialog.Dispose();
348             _spaceKeyCanceler.Dispose();
349             if (NIconAt != null) NIconAt.Dispose();
350             if (NIconAtRed != null) NIconAtRed.Dispose();
351             if (NIconAtSmoke != null) NIconAtSmoke.Dispose();
352             if (NIconRefresh[0] != null) NIconRefresh[0].Dispose();
353             if (NIconRefresh[1] != null) NIconRefresh[1].Dispose();
354             if (NIconRefresh[2] != null) NIconRefresh[2].Dispose();
355             if (NIconRefresh[3] != null) NIconRefresh[3].Dispose();
356             if (TabIcon != null) TabIcon.Dispose();
357             if (MainIcon != null) MainIcon.Dispose();
358             if (ReplyIcon != null) ReplyIcon.Dispose();
359             if (ReplyIconBlink != null) ReplyIconBlink.Dispose();
360             _brsHighLight.Dispose();
361             _brsHighLightText.Dispose();
362             if (_brsForeColorUnread != null) _brsForeColorUnread.Dispose();
363             if (_brsForeColorReaded != null) _brsForeColorReaded.Dispose();
364             if (_brsForeColorFav != null) _brsForeColorFav.Dispose();
365             if (_brsForeColorOWL != null) _brsForeColorOWL.Dispose();
366             if (_brsForeColorRetweet != null) _brsForeColorRetweet.Dispose();
367             if (_brsBackColorMine != null) _brsBackColorMine.Dispose();
368             if (_brsBackColorAt != null) _brsBackColorAt.Dispose();
369             if (_brsBackColorYou != null) _brsBackColorYou.Dispose();
370             if (_brsBackColorAtYou != null) _brsBackColorAtYou.Dispose();
371             if (_brsBackColorAtFromTarget != null) _brsBackColorAtFromTarget.Dispose();
372             if (_brsBackColorAtTo != null) _brsBackColorAtTo.Dispose();
373             if (_brsBackColorNone != null) _brsBackColorNone.Dispose();
374             if (_brsDeactiveSelection != null) _brsDeactiveSelection.Dispose();
375             //sf.Dispose();
376             sfTab.Dispose();
377             foreach (BackgroundWorker bw in _bw)
378             {
379                 if (bw != null)
380                     bw.Dispose();
381             }
382             if (_bwFollower != null)
383             {
384                 _bwFollower.Dispose();
385             }
386             this._apiGauge.Dispose();
387             if (TIconDic != null)
388             {
389                 ((ImageDictionary)this.TIconDic).PauseGetImage = true;
390                 ((IDisposable)TIconDic).Dispose();
391             }
392             // 終了時にRemoveHandlerしておかないとメモリリークする
393             // http://msdn.microsoft.com/ja-jp/library/microsoft.win32.systemevents.powermodechanged.aspx
394             Microsoft.Win32.SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
395         }
396
397         private void LoadIcon(ref Icon IconInstance, string FileName)
398         {
399             string dir = Application.StartupPath;
400             if (File.Exists(Path.Combine(dir, FileName)))
401             {
402                 try
403                 {
404                     IconInstance = new Icon(Path.Combine(dir, FileName));
405                 }
406                 catch (Exception)
407                 {
408                 }
409             }
410         }
411
412         private void LoadIcons()
413         {
414             //着せ替えアイコン対応
415             //タスクトレイ通常時アイコン
416             string dir = Application.StartupPath;
417
418             NIconAt = Properties.Resources.At;
419             NIconAtRed = Properties.Resources.AtRed;
420             NIconAtSmoke = Properties.Resources.AtSmoke;
421             NIconRefresh[0] = Properties.Resources.Refresh;
422             NIconRefresh[1] = Properties.Resources.Refresh2;
423             NIconRefresh[2] = Properties.Resources.Refresh3;
424             NIconRefresh[3] = Properties.Resources.Refresh4;
425             TabIcon = Properties.Resources.TabIcon;
426             MainIcon = Properties.Resources.MIcon;
427             ReplyIcon = Properties.Resources.Reply;
428             ReplyIconBlink = Properties.Resources.ReplyBlink;
429
430             if (!Directory.Exists(Path.Combine(dir, "Icons")))
431                 return;
432
433             LoadIcon(ref NIconAt, "Icons\\At.ico");
434
435             //タスクトレイエラー時アイコン
436             LoadIcon(ref NIconAtRed, "Icons\\AtRed.ico");
437
438             //タスクトレイオフライン時アイコン
439             LoadIcon(ref NIconAtSmoke, "Icons\\AtSmoke.ico");
440
441             //タスクトレイ更新中アイコン
442             //アニメーション対応により4種類読み込み
443             LoadIcon(ref NIconRefresh[0], "Icons\\Refresh.ico");
444             LoadIcon(ref NIconRefresh[1], "Icons\\Refresh2.ico");
445             LoadIcon(ref NIconRefresh[2], "Icons\\Refresh3.ico");
446             LoadIcon(ref NIconRefresh[3], "Icons\\Refresh4.ico");
447
448             //タブ見出し未読表示アイコン
449             LoadIcon(ref TabIcon, "Icons\\Tab.ico");
450
451             //画面のアイコン
452             LoadIcon(ref MainIcon, "Icons\\MIcon.ico");
453
454             //Replyのアイコン
455             LoadIcon(ref ReplyIcon, "Icons\\Reply.ico");
456
457             //Reply点滅のアイコン
458             LoadIcon(ref ReplyIconBlink, "Icons\\ReplyBlink.ico");
459         }
460
461         private void InitColumnText()
462         {
463             ColumnText[0] = "";
464             ColumnText[1] = Properties.Resources.AddNewTabText2;
465             ColumnText[2] = Properties.Resources.AddNewTabText3;
466             ColumnText[3] = Properties.Resources.AddNewTabText4_2;
467             ColumnText[4] = Properties.Resources.AddNewTabText5;
468             ColumnText[5] = "";
469             ColumnText[6] = "";
470             ColumnText[7] = "Source";
471
472             ColumnOrgText[0] = "";
473             ColumnOrgText[1] = Properties.Resources.AddNewTabText2;
474             ColumnOrgText[2] = Properties.Resources.AddNewTabText3;
475             ColumnOrgText[3] = Properties.Resources.AddNewTabText4_2;
476             ColumnOrgText[4] = Properties.Resources.AddNewTabText5;
477             ColumnOrgText[5] = "";
478             ColumnOrgText[6] = "";
479             ColumnOrgText[7] = "Source";
480
481             int c = 0;
482             switch (_statuses.SortMode)
483             {
484                 case IdComparerClass.ComparerMode.Nickname:  //ニックネーム
485                     c = 1;
486                     break;
487                 case IdComparerClass.ComparerMode.Data:  //本文
488                     c = 2;
489                     break;
490                 case IdComparerClass.ComparerMode.Id:  //時刻=発言Id
491                     c = 3;
492                     break;
493                 case IdComparerClass.ComparerMode.Name:  //名前
494                     c = 4;
495                     break;
496                 case IdComparerClass.ComparerMode.Source:  //Source
497                     c = 7;
498                     break;
499             }
500
501             if (_iconCol)
502             {
503                 if (_statuses.SortOrder == SortOrder.Descending)
504                 {
505                     // U+25BE BLACK DOWN-POINTING SMALL TRIANGLE
506                     ColumnText[2] = ColumnOrgText[2] + "▾";
507                 }
508                 else
509                 {
510                     // U+25B4 BLACK UP-POINTING SMALL TRIANGLE
511                     ColumnText[2] = ColumnOrgText[2] + "▴";
512                 }
513             }
514             else
515             {
516                 if (_statuses.SortOrder == SortOrder.Descending)
517                 {
518                     // U+25BE BLACK DOWN-POINTING SMALL TRIANGLE
519                     ColumnText[c] = ColumnOrgText[c] + "▾";
520                 }
521                 else
522                 {
523                     // U+25B4 BLACK UP-POINTING SMALL TRIANGLE
524                     ColumnText[c] = ColumnOrgText[c] + "▴";
525                 }
526             }
527         }
528
529         private void InitializeTraceFrag()
530         {
531 #if DEBUG
532             TraceOutToolStripMenuItem.Checked = true;
533             MyCommon.TraceFlag = true;
534 #endif
535             if (!MyCommon.fileVersion.EndsWith("0"))
536             {
537                 TraceOutToolStripMenuItem.Checked = true;
538                 MyCommon.TraceFlag = true;
539             }
540         }
541
542         private void Form1_Load(object sender, EventArgs e)
543         {
544             _ignoreConfigSave = true;
545             this.Visible = false;
546
547             //Win32Api.SetProxy(HttpConnection.ProxyType.Specified, "127.0.0.1", 8080, "user", "pass")
548
549             SecurityManager = new InternetSecurityManager(PostBrowser);
550
551             MyCommon.TwitterApiInfo.Changed += SetStatusLabelApiHandler;
552             Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
553
554             string[] cmdArgs = Environment.GetCommandLineArgs();
555             if (cmdArgs.Length != 0 && cmdArgs.Contains("/d")) MyCommon.TraceFlag = true;
556
557             this._spaceKeyCanceler = new SpaceKeyCanceler(this.PostButton);
558             this._spaceKeyCanceler.SpaceCancel += spaceKeyCanceler_SpaceCancel;
559
560             Regex.CacheSize = 100;
561
562             MyCommon.fileVersion = ((AssemblyFileVersionAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)[0]).Version;
563             InitializeTraceFrag();
564             LoadIcons(); // アイコン読み込み
565
566             ThumbnailGenerator.InitializeGenerator();
567
568             //発言保持クラス
569             _statuses = TabInformations.GetInstance();
570
571             //アイコン設定
572             this.Icon = MainIcon;              //メインフォーム(TweenMain)
573             NotifyIcon1.Icon = NIconAt;      //タスクトレイ
574             TabImage.Images.Add(TabIcon);    //タブ見出し
575
576             SettingDialog.Owner = this;;
577             SearchDialog.Owner = this;
578             fltDialog.Owner = this;
579             UrlDialog.Owner = this;
580
581             _history.Add(new PostingStatus());
582             _hisIdx = 0;
583             _reply_to_id = 0;
584             _reply_to_name = "";
585
586             //<<<<<<<<<設定関連>>>>>>>>>
587             //設定コンバージョン
588             //ConvertConfig();
589
590             ////設定読み出し
591             LoadConfig();
592
593             //新着バルーン通知のチェック状態設定
594             NewPostPopMenuItem.Checked = _cfgCommon.NewAllPop;
595             this.NotifyFileMenuItem.Checked = NewPostPopMenuItem.Checked;
596
597             //フォント&文字色&背景色保持
598             _fntUnread = _cfgLocal.FontUnread;
599             _clUnread = _cfgLocal.ColorUnread;
600             _fntReaded = _cfgLocal.FontRead;
601             _clReaded = _cfgLocal.ColorRead;
602             _clFav = _cfgLocal.ColorFav;
603             _clOWL = _cfgLocal.ColorOWL;
604             _clRetweet = _cfgLocal.ColorRetweet;
605             _fntDetail = _cfgLocal.FontDetail;
606             _clDetail = _cfgLocal.ColorDetail;
607             _clDetailLink = _cfgLocal.ColorDetailLink;
608             _clDetailBackcolor = _cfgLocal.ColorDetailBackcolor;
609             _clSelf = _cfgLocal.ColorSelf;
610             _clAtSelf = _cfgLocal.ColorAtSelf;
611             _clTarget = _cfgLocal.ColorTarget;
612             _clAtTarget = _cfgLocal.ColorAtTarget;
613             _clAtFromTarget = _cfgLocal.ColorAtFromTarget;
614             _clAtTo = _cfgLocal.ColorAtTo;
615             _clListBackcolor = _cfgLocal.ColorListBackcolor;
616             _clInputBackcolor = _cfgLocal.ColorInputBackcolor;
617             _clInputFont = _cfgLocal.ColorInputFont;
618             _fntInputFont = _cfgLocal.FontInputFont;
619
620             _brsForeColorUnread = new SolidBrush(_clUnread);
621             _brsForeColorReaded = new SolidBrush(_clReaded);
622             _brsForeColorFav = new SolidBrush(_clFav);
623             _brsForeColorOWL = new SolidBrush(_clOWL);
624             _brsForeColorRetweet = new SolidBrush(_clRetweet);
625             _brsBackColorMine = new SolidBrush(_clSelf);
626             _brsBackColorAt = new SolidBrush(_clAtSelf);
627             _brsBackColorYou = new SolidBrush(_clTarget);
628             _brsBackColorAtYou = new SolidBrush(_clAtTarget);
629             _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
630             _brsBackColorAtTo = new SolidBrush(_clAtTo);
631             //_brsBackColorNone = new SolidBrush(Color.FromKnownColor(KnownColor.Window));
632             _brsBackColorNone = new SolidBrush(_clListBackcolor);
633
634             // StringFormatオブジェクトへの事前設定
635             //sf.Alignment = StringAlignment.Near;             // Textを近くへ配置(左から右の場合は左寄せ)
636             //sf.LineAlignment = StringAlignment.Near;         // Textを近くへ配置(上寄せ)
637             //sf.FormatFlags = StringFormatFlags.LineLimit;    // 
638             sfTab.Alignment = StringAlignment.Center;
639             sfTab.LineAlignment = StringAlignment.Center;
640
641             //設定画面への反映
642             HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
643             HttpTwitter.TwitterSearchUrl = _cfgCommon.TwitterSearchUrl;
644             SettingDialog.TwitterApiUrl = _cfgCommon.TwitterUrl;
645             SettingDialog.TwitterSearchApiUrl = _cfgCommon.TwitterSearchUrl;
646
647             //認証関連
648             if (string.IsNullOrEmpty(_cfgCommon.Token)) _cfgCommon.UserName = "";
649             tw.Initialize(_cfgCommon.Token, _cfgCommon.TokenSecret, _cfgCommon.UserName, _cfgCommon.UserId);
650
651             SettingDialog.UserAccounts = _cfgCommon.UserAccounts;
652
653             SettingDialog.TimelinePeriodInt = _cfgCommon.TimelinePeriod;
654             SettingDialog.ReplyPeriodInt = _cfgCommon.ReplyPeriod;
655             SettingDialog.DMPeriodInt = _cfgCommon.DMPeriod;
656             SettingDialog.PubSearchPeriodInt = _cfgCommon.PubSearchPeriod;
657             SettingDialog.UserTimelinePeriodInt = _cfgCommon.UserTimelinePeriod;
658             SettingDialog.ListsPeriodInt = _cfgCommon.ListsPeriod;
659             //不正値チェック
660             if (!cmdArgs.Contains("nolimit"))
661             {
662                 if (SettingDialog.TimelinePeriodInt < 15 && SettingDialog.TimelinePeriodInt > 0) SettingDialog.TimelinePeriodInt = 15;
663                 if (SettingDialog.ReplyPeriodInt < 15 && SettingDialog.ReplyPeriodInt > 0) SettingDialog.ReplyPeriodInt = 15;
664                 if (SettingDialog.DMPeriodInt < 15 && SettingDialog.DMPeriodInt > 0) SettingDialog.DMPeriodInt = 15;
665                 if (SettingDialog.PubSearchPeriodInt < 30 && SettingDialog.PubSearchPeriodInt > 0) SettingDialog.PubSearchPeriodInt = 30;
666                 if (SettingDialog.UserTimelinePeriodInt < 15 && SettingDialog.UserTimelinePeriodInt > 0) SettingDialog.UserTimelinePeriodInt = 15;
667                 if (SettingDialog.ListsPeriodInt < 15 && SettingDialog.ListsPeriodInt > 0) SettingDialog.ListsPeriodInt = 15;
668             }
669
670             //起動時読み込み分を既読にするか。trueなら既読として処理
671             SettingDialog.Readed = _cfgCommon.Read;
672             //新着取得時のリストスクロールをするか。trueならスクロールしない
673             ListLockMenuItem.Checked = _cfgCommon.ListLock;
674             this.LockListFileMenuItem.Checked = _cfgCommon.ListLock;
675             SettingDialog.IconSz = _cfgCommon.IconSize;
676             //文末ステータス
677             SettingDialog.Status = _cfgLocal.StatusText;
678             //未読管理。trueなら未読管理する
679             SettingDialog.UnreadManage = _cfgCommon.UnreadManage;
680             //サウンド再生(タブ別設定より優先)
681             SettingDialog.PlaySound = _cfgCommon.PlaySound;
682             PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
683             this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
684             //片思い表示。trueなら片思い表示する
685             SettingDialog.OneWayLove = _cfgCommon.OneWayLove;
686             //フォント&文字色&背景色
687             SettingDialog.FontUnread = _fntUnread;
688             SettingDialog.ColorUnread = _clUnread;
689             SettingDialog.FontReaded = _fntReaded;
690             SettingDialog.ColorReaded = _clReaded;
691             SettingDialog.ColorFav = _clFav;
692             SettingDialog.ColorOWL = _clOWL;
693             SettingDialog.ColorRetweet = _clRetweet;
694             SettingDialog.FontDetail = _fntDetail;
695             SettingDialog.ColorDetail = _clDetail;
696             SettingDialog.ColorDetailLink = _clDetailLink;
697             SettingDialog.ColorDetailBackcolor = _clDetailBackcolor;
698             SettingDialog.ColorSelf = _clSelf;
699             SettingDialog.ColorAtSelf = _clAtSelf;
700             SettingDialog.ColorTarget = _clTarget;
701             SettingDialog.ColorAtTarget = _clAtTarget;
702             SettingDialog.ColorAtFromTarget = _clAtFromTarget;
703             SettingDialog.ColorAtTo = _clAtTo;
704             SettingDialog.ColorListBackcolor = _clListBackcolor;
705             SettingDialog.ColorInputBackcolor = _clInputBackcolor;
706             SettingDialog.ColorInputFont = _clInputFont;
707             SettingDialog.FontInputFont = _fntInputFont;
708
709             SettingDialog.NameBalloon = _cfgCommon.NameBalloon;
710             SettingDialog.PostCtrlEnter = _cfgCommon.PostCtrlEnter;
711             SettingDialog.PostShiftEnter = _cfgCommon.PostShiftEnter;
712
713             SettingDialog.CountApi = _cfgCommon.CountApi;
714             SettingDialog.CountApiReply = _cfgCommon.CountApiReply;
715             if (SettingDialog.CountApi < 20 || SettingDialog.CountApi > 200) SettingDialog.CountApi = 60;
716             if (SettingDialog.CountApiReply < 20 || SettingDialog.CountApiReply > 200) SettingDialog.CountApiReply = 40;
717
718             SettingDialog.BrowserPath = _cfgLocal.BrowserPath;
719             SettingDialog.PostAndGet = _cfgCommon.PostAndGet;
720             SettingDialog.UseRecommendStatus = _cfgLocal.UseRecommendStatus;
721             SettingDialog.DispUsername = _cfgCommon.DispUsername;
722             SettingDialog.CloseToExit = _cfgCommon.CloseToExit;
723             SettingDialog.MinimizeToTray = _cfgCommon.MinimizeToTray;
724             SettingDialog.DispLatestPost = _cfgCommon.DispLatestPost;
725             SettingDialog.SortOrderLock = _cfgCommon.SortOrderLock;
726             SettingDialog.TinyUrlResolve = _cfgCommon.TinyUrlResolve;
727             SettingDialog.ShortUrlForceResolve = _cfgCommon.ShortUrlForceResolve;
728
729             SettingDialog.SelectedProxyType = _cfgLocal.ProxyType;
730             SettingDialog.ProxyAddress = _cfgLocal.ProxyAddress;
731             SettingDialog.ProxyPort = _cfgLocal.ProxyPort;
732             SettingDialog.ProxyUser = _cfgLocal.ProxyUser;
733             SettingDialog.ProxyPassword = _cfgLocal.ProxyPassword;
734
735             SettingDialog.PeriodAdjust = _cfgCommon.PeriodAdjust;
736             SettingDialog.StartupVersion = _cfgCommon.StartupVersion;
737             SettingDialog.StartupFollowers = _cfgCommon.StartupFollowers;
738             SettingDialog.RestrictFavCheck = _cfgCommon.RestrictFavCheck;
739             SettingDialog.AlwaysTop = _cfgCommon.AlwaysTop;
740             SettingDialog.UrlConvertAuto = false;
741             //SettingDialog.UrlConvertAuto = _cfgCommon.UrlConvertAuto;
742
743             SettingDialog.OutputzEnabled = _cfgCommon.Outputz;
744             SettingDialog.OutputzKey = _cfgCommon.OutputzKey;
745             SettingDialog.OutputzUrlmode = _cfgCommon.OutputzUrlMode;
746
747             SettingDialog.UseUnreadStyle = _cfgCommon.UseUnreadStyle;
748             SettingDialog.DefaultTimeOut = _cfgCommon.DefaultTimeOut;
749             SettingDialog.RetweetNoConfirm = _cfgCommon.RetweetNoConfirm;
750             SettingDialog.PlaySound = _cfgCommon.PlaySound;
751             SettingDialog.DateTimeFormat = _cfgCommon.DateTimeFormat;
752             SettingDialog.LimitBalloon = _cfgCommon.LimitBalloon;
753             SettingDialog.EventNotifyEnabled = _cfgCommon.EventNotifyEnabled;
754             SettingDialog.EventNotifyFlag = _cfgCommon.EventNotifyFlag;
755             SettingDialog.IsMyEventNotifyFlag = _cfgCommon.IsMyEventNotifyFlag;
756             SettingDialog.ForceEventNotify = _cfgCommon.ForceEventNotify;
757             SettingDialog.FavEventUnread = _cfgCommon.FavEventUnread;
758             SettingDialog.TranslateLanguage = _cfgCommon.TranslateLanguage;
759             SettingDialog.EventSoundFile = _cfgCommon.EventSoundFile;
760
761             //廃止サービスが選択されていた場合bit.lyへ読み替え
762             if (_cfgCommon.AutoShortUrlFirst < 0)
763                 _cfgCommon.AutoShortUrlFirst = MyCommon.UrlConverter.Uxnu;
764
765             SettingDialog.AutoShortUrlFirst = _cfgCommon.AutoShortUrlFirst;
766             SettingDialog.TabIconDisp = _cfgCommon.TabIconDisp;
767             SettingDialog.ReplyIconState = _cfgCommon.ReplyIconState;
768             SettingDialog.ReadOwnPost = _cfgCommon.ReadOwnPost;
769             SettingDialog.GetFav = _cfgCommon.GetFav;
770             SettingDialog.ReadOldPosts = _cfgCommon.ReadOldPosts;
771             SettingDialog.UseSsl = _cfgCommon.UseSsl;
772             SettingDialog.BitlyUser = _cfgCommon.BilyUser;
773             SettingDialog.BitlyPwd = _cfgCommon.BitlyPwd;
774             SettingDialog.ShowGrid = _cfgCommon.ShowGrid;
775             SettingDialog.Language = _cfgCommon.Language;
776             SettingDialog.UseAtIdSupplement = _cfgCommon.UseAtIdSupplement;
777             SettingDialog.UseHashSupplement = _cfgCommon.UseHashSupplement;
778             SettingDialog.PreviewEnable = _cfgCommon.PreviewEnable;
779             AtIdSupl = new AtIdSupplement(SettingAtIdList.Load().AtIdList, "@");
780
781             SettingDialog.IsMonospace = _cfgCommon.IsMonospace;
782             if (SettingDialog.IsMonospace)
783             {
784                 detailHtmlFormatHeader = detailHtmlFormatMono1;
785                 detailHtmlFormatFooter = detailHtmlFormatMono7;
786             }
787             else
788             {
789                 detailHtmlFormatHeader = detailHtmlFormat1;
790                 detailHtmlFormatFooter = detailHtmlFormat7;
791             }
792             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();
793             if (SettingDialog.IsMonospace)
794             {
795                 detailHtmlFormatHeader += detailHtmlFormatMono6;
796             }
797             else
798             {
799                 detailHtmlFormatHeader += detailHtmlFormat6;
800             }
801             this.IdeographicSpaceToSpaceToolStripMenuItem.Checked = _cfgCommon.WideSpaceConvert;
802             this.ToolStripFocusLockMenuItem.Checked = _cfgCommon.FocusLockToStatusText;
803
804             //Regex statregex = new Regex("^0*");
805             SettingDialog.RecommendStatusText = " [TWNv" + Regex.Replace(MyCommon.fileVersion.Replace(".", ""), "^0*", "") + "]";
806
807             //書式指定文字列エラーチェック
808             try
809             {
810                 if (DateTime.Now.ToString(SettingDialog.DateTimeFormat).Length == 0)
811                 {
812                     // このブロックは絶対に実行されないはず
813                     // 変換が成功した場合にLengthが0にならない
814                     SettingDialog.DateTimeFormat = "yyyy/MM/dd H:mm:ss";
815                 }
816             }
817             catch (FormatException)
818             {
819                 // FormatExceptionが発生したら初期値を設定 (=yyyy/MM/dd H:mm:ssとみなされる)
820                 SettingDialog.DateTimeFormat = "yyyy/MM/dd H:mm:ss";
821             }
822
823             SettingDialog.Nicoms = _cfgCommon.Nicoms;
824             SettingDialog.HotkeyEnabled = _cfgCommon.HotkeyEnabled;
825             SettingDialog.HotkeyMod = _cfgCommon.HotkeyModifier;
826             SettingDialog.HotkeyKey = _cfgCommon.HotkeyKey;
827             SettingDialog.HotkeyValue = _cfgCommon.HotkeyValue;
828
829             SettingDialog.BlinkNewMentions = _cfgCommon.BlinkNewMentions;
830
831             SettingDialog.UseAdditionalCount = _cfgCommon.UseAdditionalCount;
832             SettingDialog.MoreCountApi = _cfgCommon.MoreCountApi;
833             SettingDialog.FirstCountApi = _cfgCommon.FirstCountApi;
834             SettingDialog.SearchCountApi = _cfgCommon.SearchCountApi;
835             SettingDialog.FavoritesCountApi = _cfgCommon.FavoritesCountApi;
836             SettingDialog.UserTimelineCountApi = _cfgCommon.UserTimelineCountApi;
837             SettingDialog.ListCountApi = _cfgCommon.ListCountApi;
838
839             SettingDialog.UserstreamStartup = _cfgCommon.UserstreamStartup;
840             SettingDialog.UserstreamPeriodInt = _cfgCommon.UserstreamPeriod;
841             SettingDialog.OpenUserTimeline = _cfgCommon.OpenUserTimeline;
842             SettingDialog.ListDoubleClickAction = _cfgCommon.ListDoubleClickAction;
843             SettingDialog.UserAppointUrl = _cfgCommon.UserAppointUrl;
844             SettingDialog.HideDuplicatedRetweets = _cfgCommon.HideDuplicatedRetweets;
845
846             SettingDialog.IsPreviewFoursquare = _cfgCommon.IsPreviewFoursquare;
847             SettingDialog.MapThumbnailProvider = _cfgCommon.MapThumbnailProvider;
848             SettingDialog.MapThumbnailHeight = _cfgCommon.MapThumbnailHeight;
849             SettingDialog.MapThumbnailWidth = _cfgCommon.MapThumbnailWidth;
850             SettingDialog.MapThumbnailZoom = _cfgCommon.MapThumbnailZoom;
851             SettingDialog.IsListStatusesIncludeRts = _cfgCommon.IsListsIncludeRts;
852             SettingDialog.TabMouseLock = _cfgCommon.TabMouseLock;
853             SettingDialog.IsRemoveSameEvent = _cfgCommon.IsRemoveSameEvent;
854             SettingDialog.IsNotifyUseGrowl = _cfgCommon.IsUseNotifyGrowl;
855
856             //ハッシュタグ関連
857             HashSupl = new AtIdSupplement(_cfgCommon.HashTags, "#");
858             HashMgr = new HashtagManage(HashSupl,
859                                     _cfgCommon.HashTags.ToArray(),
860                                     _cfgCommon.HashSelected,
861                                     _cfgCommon.HashIsPermanent,
862                                     _cfgCommon.HashIsHead,
863                                     _cfgCommon.HashIsNotAddToAtReply);
864             if (!string.IsNullOrEmpty(HashMgr.UseHash) && HashMgr.IsPermanent) HashStripSplitButton.Text = HashMgr.UseHash;
865
866             _initial = true;
867
868             //アイコンリスト作成
869             try
870             {
871                 TIconDic = new ImageDictionary(5);
872             }
873             catch (Exception)
874             {
875                 MessageBox.Show("Please install [.NET Framework 4 (Full)].");
876                 Application.Exit();
877                 return;
878             }
879             ((ImageDictionary)this.TIconDic).PauseGetImage = false;
880
881             bool saveRequired = false;
882             bool firstRun = false;
883
884             //ユーザー名、パスワードが未設定なら設定画面を表示(初回起動時など)
885             if (string.IsNullOrEmpty(tw.Username))
886             {
887                 saveRequired = true;
888                 firstRun = true;
889                 SettingDialog.ShowInTaskbar = true;
890
891                 //設定せずにキャンセルされた場合はプログラム終了
892                 if (SettingDialog.ShowDialog(this) == DialogResult.Cancel)
893                 {
894                     Application.Exit();  //強制終了
895                     return;
896                 }
897                 //設定されたが、依然ユーザー名とパスワードが未設定ならプログラム終了
898                 if (string.IsNullOrEmpty(tw.Username))
899                 {
900                     Application.Exit();  //強制終了
901                     return;
902                 }
903                 SettingDialog.ShowInTaskbar = false;
904                 //新しい設定を反映
905                 //フォント&文字色&背景色保持
906                 _fntUnread = SettingDialog.FontUnread;
907                 _clUnread = SettingDialog.ColorUnread;
908                 _fntReaded = SettingDialog.FontReaded;
909                 _clReaded = SettingDialog.ColorReaded;
910                 _clFav = SettingDialog.ColorFav;
911                 _clOWL = SettingDialog.ColorOWL;
912                 _clRetweet = SettingDialog.ColorRetweet;
913                 _fntDetail = SettingDialog.FontDetail;
914                 _clDetail = SettingDialog.ColorDetail;
915                 _clDetailLink = SettingDialog.ColorDetailLink;
916                 _clDetailBackcolor = SettingDialog.ColorDetailBackcolor;
917                 _clSelf = SettingDialog.ColorSelf;
918                 _clAtSelf = SettingDialog.ColorAtSelf;
919                 _clTarget = SettingDialog.ColorTarget;
920                 _clAtTarget = SettingDialog.ColorAtTarget;
921                 _clAtFromTarget = SettingDialog.ColorAtFromTarget;
922                 _clAtTo = SettingDialog.ColorAtTo;
923                 _clListBackcolor = SettingDialog.ColorListBackcolor;
924                 _clInputBackcolor = SettingDialog.ColorInputBackcolor;
925                 _clInputFont = SettingDialog.ColorInputFont;
926                 _fntInputFont = SettingDialog.FontInputFont;
927                 _brsForeColorUnread.Dispose();
928                 _brsForeColorReaded.Dispose();
929                 _brsForeColorFav.Dispose();
930                 _brsForeColorOWL.Dispose();
931                 _brsForeColorRetweet.Dispose();
932                 _brsForeColorUnread = new SolidBrush(_clUnread);
933                 _brsForeColorReaded = new SolidBrush(_clReaded);
934                 _brsForeColorFav = new SolidBrush(_clFav);
935                 _brsForeColorOWL = new SolidBrush(_clOWL);
936                 _brsForeColorRetweet = new SolidBrush(_clRetweet);
937                 _brsBackColorMine.Dispose();
938                 _brsBackColorAt.Dispose();
939                 _brsBackColorYou.Dispose();
940                 _brsBackColorAtYou.Dispose();
941                 _brsBackColorAtFromTarget.Dispose();
942                 _brsBackColorAtTo.Dispose();
943                 _brsBackColorNone.Dispose();
944                 _brsBackColorMine = new SolidBrush(_clSelf);
945                 _brsBackColorAt = new SolidBrush(_clAtSelf);
946                 _brsBackColorYou = new SolidBrush(_clTarget);
947                 _brsBackColorAtYou = new SolidBrush(_clAtTarget);
948                 _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
949                 _brsBackColorAtTo = new SolidBrush(_clAtTo);
950                 _brsBackColorNone = new SolidBrush(_clListBackcolor);
951
952                 if (SettingDialog.IsMonospace)
953                 {
954                     detailHtmlFormatHeader = detailHtmlFormatMono1;
955                     detailHtmlFormatFooter = detailHtmlFormatMono7;
956                 }
957                 else
958                 {
959                     detailHtmlFormatHeader = detailHtmlFormat1;
960                     detailHtmlFormatFooter = detailHtmlFormat7;
961                 }
962                 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();
963                 if (SettingDialog.IsMonospace)
964                 {
965                     detailHtmlFormatHeader += detailHtmlFormatMono6;
966                 }
967                 else
968                 {
969                     detailHtmlFormatHeader += detailHtmlFormat6;
970                 }
971                 //他の設定項目は、随時設定画面で保持している値を読み出して使用
972             }
973
974             if (SettingDialog.HotkeyEnabled)
975             {
976                 //////グローバルホットキーの登録
977                 HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
978                 if ((SettingDialog.HotkeyMod & Keys.Alt) == Keys.Alt) modKey = modKey | HookGlobalHotkey.ModKeys.Alt;
979                 if ((SettingDialog.HotkeyMod & Keys.Control) == Keys.Control) modKey = modKey | HookGlobalHotkey.ModKeys.Ctrl;
980                 if ((SettingDialog.HotkeyMod & Keys.Shift) == Keys.Shift) modKey = modKey | HookGlobalHotkey.ModKeys.Shift;
981                 if ((SettingDialog.HotkeyMod & Keys.LWin) == Keys.LWin) modKey = modKey | HookGlobalHotkey.ModKeys.Win;
982
983                 _hookGlobalHotkey.RegisterOriginalHotkey(SettingDialog.HotkeyKey, SettingDialog.HotkeyValue, modKey);
984             }
985
986             //Twitter用通信クラス初期化
987             HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
988                                                 SettingDialog.SelectedProxyType,
989                                                 SettingDialog.ProxyAddress,
990                                                 SettingDialog.ProxyPort,
991                                                 SettingDialog.ProxyUser,
992                                                 SettingDialog.ProxyPassword);
993
994             tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
995             tw.ReadOwnPost = SettingDialog.ReadOwnPost;
996             tw.UseSsl = SettingDialog.UseSsl;
997             ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
998             ShortUrl.IsForceResolve = SettingDialog.ShortUrlForceResolve;
999             ShortUrl.BitlyId = SettingDialog.BitlyUser;
1000             ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
1001             HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
1002             HttpTwitter.TwitterSearchUrl = _cfgCommon.TwitterSearchUrl;
1003             tw.TrackWord = _cfgCommon.TrackWord;
1004             TrackToolStripMenuItem.Checked = !String.IsNullOrEmpty(tw.TrackWord);
1005             tw.AllAtReply = _cfgCommon.AllAtReply;
1006             AllrepliesToolStripMenuItem.Checked = tw.AllAtReply;
1007
1008             Outputz.Key = SettingDialog.OutputzKey;
1009             Outputz.Enabled = SettingDialog.OutputzEnabled;
1010             switch (SettingDialog.OutputzUrlmode)
1011             {
1012                 case MyCommon.OutputzUrlmode.twittercom:
1013                     Outputz.OutUrl = "http://twitter.com/";
1014                     break;
1015                 case MyCommon.OutputzUrlmode.twittercomWithUsername:
1016                     Outputz.OutUrl = "http://twitter.com/" + tw.Username;
1017                     break;
1018             }
1019
1020             //画像投稿サービス
1021             this.CreatePictureServices();
1022             SetImageServiceCombo();
1023             ImageSelectionPanel.Enabled = false;
1024
1025             ImageServiceCombo.SelectedIndex = _cfgCommon.UseImageService;
1026
1027             //ウィンドウ設定
1028             this.ClientSize = _cfgLocal.FormSize;
1029             _mySize = _cfgLocal.FormSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
1030             _myLoc = _cfgLocal.FormLocation;
1031             //タイトルバー領域
1032             if (this.WindowState != FormWindowState.Minimized)
1033             {
1034                 this.DesktopLocation = _cfgLocal.FormLocation;
1035                 Rectangle tbarRect = new Rectangle(this.Location, new Size(_mySize.Width, SystemInformation.CaptionHeight));
1036                 bool outOfScreen = true;
1037                 if (Screen.AllScreens.Length == 1)    //ハングするとの報告
1038                 {
1039                     foreach (Screen scr in Screen.AllScreens)
1040                     {
1041                         if (!Rectangle.Intersect(tbarRect, scr.Bounds).IsEmpty)
1042                         {
1043                             outOfScreen = false;
1044                             break;
1045                         }
1046                     }
1047                     if (outOfScreen)
1048                     {
1049                         this.DesktopLocation = new Point(0, 0);
1050                         _myLoc = this.DesktopLocation;
1051                     }
1052                 }
1053             }
1054             this.TopMost = SettingDialog.AlwaysTop;
1055             _mySpDis = _cfgLocal.SplitterDistance;
1056             _mySpDis2 = _cfgLocal.StatusTextHeight;
1057             _mySpDis3 = _cfgLocal.PreviewDistance;
1058             if (_mySpDis3 == -1)
1059             {
1060                 _mySpDis3 = _mySize.Width - 150;
1061                 if (_mySpDis3 < 1) _mySpDis3 = 50;
1062                 _cfgLocal.PreviewDistance = _mySpDis3;
1063             }
1064             _myAdSpDis = _cfgLocal.AdSplitterDistance;
1065             MultiLineMenuItem.Checked = _cfgLocal.StatusMultiline;
1066             //this.Tween_ClientSizeChanged(this, null);
1067             PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
1068             this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
1069             //入力欄
1070             StatusText.Font = _fntInputFont;
1071             StatusText.ForeColor = _clInputFont;
1072
1073             //全新着通知のチェック状態により、Reply&DMの新着通知有効無効切り替え(タブ別設定にするため削除予定)
1074             if (SettingDialog.UnreadManage == false)
1075             {
1076                 ReadedStripMenuItem.Enabled = false;
1077                 UnreadStripMenuItem.Enabled = false;
1078             }
1079
1080             if (SettingDialog.IsNotifyUseGrowl) gh.RegisterGrowl();
1081
1082             //タイマー設定
1083             TimerTimeline.AutoReset = true;
1084             TimerTimeline.SynchronizingObject = this;
1085             //Recent取得間隔
1086             TimerTimeline.Interval = 1000;
1087             TimerTimeline.Enabled = true;
1088
1089             //更新中アイコンアニメーション間隔
1090             TimerRefreshIcon.Interval = 200;
1091             TimerRefreshIcon.Enabled = true;
1092
1093             //状態表示部の初期化(画面右下)
1094             StatusLabel.Text = "";
1095             StatusLabel.AutoToolTip = false;
1096             StatusLabel.ToolTipText = "";
1097             //文字カウンタ初期化
1098             lblLen.Text = GetRestStatusCount(true, false).ToString();
1099
1100             ////////////////////////////////////////////////////////////////////////////////
1101             _statuses.SortOrder = (SortOrder)_cfgCommon.SortOrder;
1102             IdComparerClass.ComparerMode mode = IdComparerClass.ComparerMode.Id;
1103             switch (_cfgCommon.SortColumn)
1104             {
1105                 case 0:    //0:アイコン,5:未読マーク,6:プロテクト・フィルターマーク
1106                 case 5:
1107                 case 6:
1108                     //ソートしない
1109                     mode = IdComparerClass.ComparerMode.Id;  //Idソートに読み替え
1110                     break;
1111                 case 1:  //ニックネーム
1112                     mode = IdComparerClass.ComparerMode.Nickname;
1113                     break;
1114                 case 2:  //本文
1115                     mode = IdComparerClass.ComparerMode.Data;
1116                     break;
1117                 case 3:  //時刻=発言Id
1118                     mode = IdComparerClass.ComparerMode.Id;
1119                     break;
1120                 case 4:  //名前
1121                     mode = IdComparerClass.ComparerMode.Name;
1122                     break;
1123                 case 7:  //Source
1124                     mode = IdComparerClass.ComparerMode.Source;
1125                     break;
1126             }
1127             _statuses.SortMode = mode;
1128             ////////////////////////////////////////////////////////////////////////////////
1129
1130             switch (SettingDialog.IconSz)
1131             {
1132                 case MyCommon.IconSizes.IconNone:
1133                     _iconSz = 0;
1134                     break;
1135                 case MyCommon.IconSizes.Icon16:
1136                     _iconSz = 16;
1137                     break;
1138                 case MyCommon.IconSizes.Icon24:
1139                     _iconSz = 26;
1140                     break;
1141                 case MyCommon.IconSizes.Icon48:
1142                     _iconSz = 48;
1143                     break;
1144                 case MyCommon.IconSizes.Icon48_2:
1145                     _iconSz = 48;
1146                     _iconCol = true;
1147                     break;
1148             }
1149             if (_iconSz == 0)
1150             {
1151                 tw.GetIcon = false;
1152             }
1153             else
1154             {
1155                 tw.GetIcon = true;
1156                 tw.IconSize = _iconSz;
1157             }
1158             tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
1159             ShortUrl.IsForceResolve = SettingDialog.ShortUrlForceResolve;
1160
1161             //発言詳細部アイコンをリストアイコンにサイズ変更
1162             int sz = _iconSz;
1163             if (_iconSz == 0)
1164             {
1165                 sz = 16;
1166             }
1167
1168             tw.DetailIcon = TIconDic;
1169
1170             StatusLabel.Text = Properties.Resources.Form1_LoadText1;       //画面右下の状態表示を変更
1171             StatusLabelUrl.Text = "";            //画面左下のリンク先URL表示部を初期化
1172             NameLabel.Text = "";                 //発言詳細部名前ラベル初期化
1173             DateTimeLabel.Text = "";             //発言詳細部日時ラベル初期化
1174             SourceLinkLabel.Text = "";           //Source部分初期化
1175
1176             //<<<<<<<<タブ関連>>>>>>>
1177             //デフォルトタブの存在チェック、ない場合には追加
1178             if (_statuses.GetTabByType(MyCommon.TabUsageType.Home) == null)
1179             {
1180                 if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.RECENT))
1181                 {
1182                     _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
1183                 }
1184                 else
1185                 {
1186                     _statuses.Tabs[MyCommon.DEFAULTTAB.RECENT].TabType = MyCommon.TabUsageType.Home;
1187                 }
1188             }
1189             if (_statuses.GetTabByType(MyCommon.TabUsageType.Mentions) == null)
1190             {
1191                 if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.REPLY))
1192                 {
1193                     _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
1194                 }
1195                 else
1196                 {
1197                     _statuses.Tabs[MyCommon.DEFAULTTAB.REPLY].TabType = MyCommon.TabUsageType.Mentions;
1198                 }
1199             }
1200             if (_statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage) == null)
1201             {
1202                 if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.DM))
1203                 {
1204                     _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
1205                 }
1206                 else
1207                 {
1208                     _statuses.Tabs[MyCommon.DEFAULTTAB.DM].TabType = MyCommon.TabUsageType.DirectMessage;
1209                 }
1210             }
1211             if (_statuses.GetTabByType(MyCommon.TabUsageType.Favorites) == null)
1212             {
1213                 if (!_statuses.Tabs.ContainsKey(MyCommon.DEFAULTTAB.FAV))
1214                 {
1215                     _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
1216                 }
1217                 else
1218                 {
1219                     _statuses.Tabs[MyCommon.DEFAULTTAB.FAV].TabType = MyCommon.TabUsageType.Favorites;
1220                 }
1221             }
1222             foreach (string tn in _statuses.Tabs.Keys)
1223             {
1224                 if (_statuses.Tabs[tn].TabType == MyCommon.TabUsageType.Undefined)
1225                 {
1226                     _statuses.Tabs[tn].TabType = MyCommon.TabUsageType.UserDefined;
1227                 }
1228                 if (!AddNewTab(tn, true, _statuses.Tabs[tn].TabType, _statuses.Tabs[tn].ListInfo)) throw new Exception(Properties.Resources.TweenMain_LoadText1);
1229             }
1230
1231             this.JumpReadOpMenuItem.ShortcutKeyDisplayString = "Space";
1232             CopySTOTMenuItem.ShortcutKeyDisplayString = "Ctrl+C";
1233             CopyURLMenuItem.ShortcutKeyDisplayString = "Ctrl+Shift+C";
1234             CopyUserIdStripMenuItem.ShortcutKeyDisplayString = "Shift+Alt+C";
1235
1236             if (SettingDialog.MinimizeToTray == false || this.WindowState != FormWindowState.Minimized)
1237             {
1238                 this.Visible = true;
1239             }
1240             _curTab = ListTab.SelectedTab;
1241             _curItemIndex = -1;
1242             _curList = (DetailsListView)_curTab.Tag;
1243             SetMainWindowTitle();
1244             SetNotifyIconText();
1245
1246             if (SettingDialog.TabIconDisp)
1247             {
1248                 ListTab.DrawMode = TabDrawMode.Normal;
1249             }
1250             else
1251             {
1252                 ListTab.DrawMode = TabDrawMode.OwnerDrawFixed;
1253                 ListTab.DrawItem += ListTab_DrawItem;
1254                 ListTab.ImageList = null;
1255             }
1256
1257             _ignoreConfigSave = false;
1258             this.TweenMain_Resize(null, null);
1259             if (saveRequired) SaveConfigsAll(false);
1260
1261             if (tw.UserId == 0)
1262             {
1263                 tw.VerifyCredentials();
1264                 foreach (UserAccount ua in _cfgCommon.UserAccounts)
1265                 {
1266                     if (ua.Username.ToLower() == tw.Username.ToLower())
1267                     {
1268                         ua.UserId = tw.UserId;
1269                         break;
1270                     }
1271                 }
1272             }
1273             foreach (UserAccount ua in SettingDialog.UserAccounts)
1274             {
1275                 if (ua.UserId == 0 && ua.Username.ToLower() == tw.Username.ToLower())
1276                 {
1277                     ua.UserId = tw.UserId;
1278                     break;
1279                 }
1280             }
1281
1282             if (firstRun)
1283             {
1284                 // 初回起動時だけ右下のメニューを目立たせる
1285                 HashStripSplitButton.ShowDropDown();
1286             }
1287         }
1288
1289         private void CreatePictureServices()
1290         {
1291             if (this.pictureService != null) this.pictureService.Clear();
1292             this.pictureService = null;
1293             this.pictureService = new Dictionary<string, IMultimediaShareService> {
1294                 {"TwitPic", new TwitPic(tw)},
1295                 {"img.ly", new imgly(tw)},
1296                 {"yfrog", new yfrog(tw)},
1297                 {"lockerz", new Plixi(tw)},
1298                 {"Twitter", new TwitterPhoto(tw)}
1299             };
1300         }
1301
1302         private void spaceKeyCanceler_SpaceCancel(object sender, EventArgs e)
1303         {
1304             JumpUnreadMenuItem_Click(null, null);
1305         }
1306
1307         private void ListTab_DrawItem(object sender, DrawItemEventArgs e)
1308         {
1309             string txt;
1310             try
1311             {
1312                 txt = ListTab.TabPages[e.Index].Text;
1313             }
1314             catch (Exception)
1315             {
1316                 return;
1317             }
1318
1319             e.Graphics.FillRectangle(System.Drawing.SystemBrushes.Control, e.Bounds);
1320             if (e.State == DrawItemState.Selected)
1321             {
1322                 e.DrawFocusRectangle();
1323             }
1324             Brush fore;
1325             try
1326             {
1327                 if (_statuses.Tabs[txt].UnreadCount > 0)
1328                     fore = Brushes.Red;
1329                 else
1330                     fore = System.Drawing.SystemBrushes.ControlText;
1331             }
1332             catch (Exception)
1333             {
1334                 fore = System.Drawing.SystemBrushes.ControlText;
1335             }
1336             e.Graphics.DrawString(txt, e.Font, fore, e.Bounds, sfTab);
1337         }
1338
1339         private void LoadConfig()
1340         {
1341             _cfgCommon = SettingCommon.Load();
1342             if (_cfgCommon.UserAccounts == null || _cfgCommon.UserAccounts.Count == 0)
1343             {
1344                 _cfgCommon.UserAccounts = new List<UserAccount>();
1345                 if (!string.IsNullOrEmpty(_cfgCommon.UserName))
1346                 {
1347                     UserAccount account = new UserAccount();
1348                     account.Username = _cfgCommon.UserName;
1349                     account.UserId = _cfgCommon.UserId;
1350                     account.Token = _cfgCommon.Token;
1351                     account.TokenSecret = _cfgCommon.TokenSecret;
1352
1353                     _cfgCommon.UserAccounts.Add(account);
1354                 }
1355             }
1356             _cfgLocal = SettingLocal.Load();
1357             List<TabClass> tabs = SettingTabs.Load().Tabs;
1358             foreach (TabClass tb in tabs)
1359             {
1360                 try
1361                 {
1362                     _statuses.Tabs.Add(tb.TabName, tb);
1363                 }
1364                 catch (Exception)
1365                 {
1366                     tb.TabName = _statuses.GetUniqueTabName();
1367                     _statuses.Tabs.Add(tb.TabName, tb);
1368                 }
1369             }
1370             if (_statuses.Tabs.Count == 0)
1371             {
1372                 _statuses.AddTab(MyCommon.DEFAULTTAB.RECENT, MyCommon.TabUsageType.Home, null);
1373                 _statuses.AddTab(MyCommon.DEFAULTTAB.REPLY, MyCommon.TabUsageType.Mentions, null);
1374                 _statuses.AddTab(MyCommon.DEFAULTTAB.DM, MyCommon.TabUsageType.DirectMessage, null);
1375                 _statuses.AddTab(MyCommon.DEFAULTTAB.FAV, MyCommon.TabUsageType.Favorites, null);
1376             }
1377         }
1378
1379         private void TimerInterval_Changed(object sender, AppendSettingDialog.IntervalChangedEventArgs e) //Handles SettingDialog.IntervalChanged
1380         {
1381             if (!TimerTimeline.Enabled) return;
1382             ResetTimers = e;
1383         }
1384
1385         private AppendSettingDialog.IntervalChangedEventArgs ResetTimers = new AppendSettingDialog.IntervalChangedEventArgs();
1386
1387         private static int homeCounter = 0;
1388         private static int mentionCounter = 0;
1389         private static int dmCounter = 0;
1390         private static int pubSearchCounter = 0;
1391         private static int userTimelineCounter = 0;
1392         private static int listsCounter = 0;
1393         private static int usCounter = 0;
1394         private static int ResumeWait = 0;
1395         private static int refreshFollowers = 0;
1396
1397         private void TimerTimeline_Elapsed(object sender, EventArgs e)
1398         {
1399             if (homeCounter > 0) Interlocked.Decrement(ref homeCounter);
1400             if (mentionCounter > 0) Interlocked.Decrement(ref mentionCounter);
1401             if (dmCounter > 0) Interlocked.Decrement(ref dmCounter);
1402             if (pubSearchCounter > 0) Interlocked.Decrement(ref pubSearchCounter);
1403             if (userTimelineCounter > 0) Interlocked.Decrement(ref userTimelineCounter);
1404             if (listsCounter > 0) Interlocked.Decrement(ref listsCounter);
1405             if (usCounter > 0) Interlocked.Decrement(ref usCounter);
1406             Interlocked.Increment(ref refreshFollowers);
1407
1408             ////タイマー初期化
1409             if (ResetTimers.Timeline || homeCounter <= 0 && SettingDialog.TimelinePeriodInt > 0)
1410             {
1411                 Interlocked.Exchange(ref homeCounter, SettingDialog.TimelinePeriodInt);
1412                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Timeline) GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
1413                 ResetTimers.Timeline = false;
1414             }
1415             if (ResetTimers.Reply || mentionCounter <= 0 && SettingDialog.ReplyPeriodInt > 0)
1416             {
1417                 Interlocked.Exchange(ref mentionCounter, SettingDialog.ReplyPeriodInt);
1418                 if (!tw.IsUserstreamDataReceived && !ResetTimers.Reply) GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
1419                 ResetTimers.Reply = false;
1420             }
1421             if (ResetTimers.DirectMessage || dmCounter <= 0 && SettingDialog.DMPeriodInt > 0)
1422             {
1423                 Interlocked.Exchange(ref dmCounter, SettingDialog.DMPeriodInt);
1424                 if (!tw.IsUserstreamDataReceived && !ResetTimers.DirectMessage) GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
1425                 ResetTimers.DirectMessage = false;
1426             }
1427             if (ResetTimers.PublicSearch || pubSearchCounter <= 0 && SettingDialog.PubSearchPeriodInt > 0)
1428             {
1429                 Interlocked.Exchange(ref pubSearchCounter, SettingDialog.PubSearchPeriodInt);
1430                 if (!ResetTimers.PublicSearch) GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");
1431                 ResetTimers.PublicSearch = false;
1432             }
1433             if (ResetTimers.UserTimeline || userTimelineCounter <= 0 && SettingDialog.UserTimelinePeriodInt > 0)
1434             {
1435                 Interlocked.Exchange(ref userTimelineCounter, SettingDialog.UserTimelinePeriodInt);
1436                 if (!ResetTimers.UserTimeline) GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");
1437                 ResetTimers.UserTimeline = false;
1438             }
1439             if (ResetTimers.Lists || listsCounter <= 0 && SettingDialog.ListsPeriodInt > 0)
1440             {
1441                 Interlocked.Exchange(ref listsCounter, SettingDialog.ListsPeriodInt);
1442                 if (!ResetTimers.Lists) GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");
1443                 ResetTimers.Lists = false;
1444             }
1445             if (ResetTimers.UserStream || usCounter <= 0 && SettingDialog.UserstreamPeriodInt > 0)
1446             {
1447                 Interlocked.Exchange(ref usCounter, SettingDialog.UserstreamPeriodInt);
1448                 if (this._isActiveUserstream) RefreshTimeline(true);
1449                 ResetTimers.UserStream = false;
1450             }
1451             if (refreshFollowers > 6 * 3600)
1452             {
1453                 Interlocked.Exchange(ref refreshFollowers, 0);
1454                 doGetFollowersMenu();
1455                 GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
1456                 if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
1457             }
1458             if (osResumed)
1459             {
1460                 Interlocked.Increment(ref ResumeWait);
1461                 if (ResumeWait > 30)
1462                 {
1463                     osResumed = false;
1464                     Interlocked.Exchange(ref ResumeWait, 0);
1465                     GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
1466                     GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
1467                     GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
1468                     GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");
1469                     GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");
1470                     GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");
1471                     doGetFollowersMenu();
1472                     GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
1473                     if (InvokeRequired && !IsDisposed) this.Invoke(new MethodInvoker(this.TrimPostChain));
1474                 }
1475             }
1476         }
1477
1478         private void RefreshTimeline(bool isUserStream)
1479         {
1480             if (isUserStream) this.RefreshTasktrayIcon(true);
1481             //スクロール制御準備
1482             int smode = -1;    //-1:制御しない,-2:最新へ,その他:topitem使用
1483             long topId = GetScrollPos(ref smode);
1484             int befCnt = _curList.VirtualListSize;
1485
1486             //現在の選択状態を退避
1487             Dictionary<string, long[]> selId = new Dictionary<string, long[]>();
1488             Dictionary<string, long> focusedId = new Dictionary<string, long>();
1489             SaveSelectedStatus(selId, focusedId);
1490
1491             //mentionsの更新前件数を保持
1492             int dmCount = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).AllCount;
1493
1494             //更新確定
1495             PostClass[] notifyPosts = null;
1496             string soundFile = "";
1497             int addCount = 0;
1498             bool isMention = false;
1499             bool isDelete = false;
1500             addCount = _statuses.SubmitUpdate(ref soundFile, ref notifyPosts, ref isMention, ref isDelete, isUserStream);
1501
1502             if (MyCommon._endingFlag) return;
1503
1504             //リストに反映&選択状態復元
1505             try
1506             {
1507                 foreach (TabPage tab in ListTab.TabPages)
1508                 {
1509                     DetailsListView lst = (DetailsListView)tab.Tag;
1510                     TabClass tabInfo = _statuses.Tabs[tab.Text];
1511                     lst.BeginUpdate();
1512                     if (isDelete || lst.VirtualListSize != tabInfo.AllCount)
1513                     {
1514                         if (lst.Equals(_curList))
1515                         {
1516                             _itemCache = null;
1517                             _postCache = null;
1518                         }
1519                         try
1520                         {
1521                             lst.VirtualListSize = tabInfo.AllCount; //リスト件数更新
1522                         }
1523                         catch (Exception)
1524                         {
1525                             //アイコン描画不具合あり?
1526                         }
1527                         this.SelectListItem(lst,
1528                                           _statuses.IndexOf(tab.Text, selId[tab.Text]),
1529                                           _statuses.IndexOf(tab.Text, focusedId[tab.Text]));
1530                     }
1531                     lst.EndUpdate();
1532                     if (tabInfo.UnreadCount > 0)
1533                         if (SettingDialog.TabIconDisp)
1534                             if (tab.ImageIndex == -1) tab.ImageIndex = 0; //タブアイコン
1535                 }
1536                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
1537             }
1538             catch (Exception)
1539             {
1540                 //ex.Data["Msg"] = "Ref1, UseAPI=" + SettingDialog.UseAPI.ToString();
1541                 //throw;
1542             }
1543
1544             //スクロール制御後処理
1545             if (smode != -1)
1546             {
1547                 try
1548                 {
1549                     if (befCnt != _curList.VirtualListSize)
1550                     {
1551                         switch (smode)
1552                         {
1553                             case -3:
1554                                 //最上行
1555                                 if (_curList.VirtualListSize > 0) _curList.EnsureVisible(0);
1556                                 break;
1557                             case -2:
1558                                 //最下行へ
1559                                 if (_curList.VirtualListSize > 0) _curList.EnsureVisible(_curList.VirtualListSize - 1);
1560                                 break;
1561                             case -1:
1562                                 //制御しない
1563                                 break;
1564                             default:
1565                                 //表示位置キープ
1566                                 if (_curList.VirtualListSize > 0 && _statuses.IndexOf(_curTab.Text, topId) > -1)
1567                                 {
1568                                     _curList.EnsureVisible(_curList.VirtualListSize - 1);
1569                                     _curList.EnsureVisible(_statuses.IndexOf(_curTab.Text, topId));
1570                                 }
1571                                 break;
1572                         }
1573                     }
1574                 }
1575                 catch (Exception ex)
1576                 {
1577                     ex.Data["Msg"] = "Ref2";
1578                     throw;
1579                 }
1580             }
1581
1582             //新着通知
1583             NotifyNewPosts(notifyPosts,
1584                            soundFile,
1585                            addCount,
1586                            isMention || dmCount != _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).AllCount);
1587
1588             SetMainWindowTitle();
1589             if (!StatusLabelUrl.Text.StartsWith("http")) SetStatusLabelUrl();
1590
1591             HashSupl.AddRangeItem(tw.GetHashList());
1592
1593         }
1594
1595         private long GetScrollPos(ref int smode)
1596         {
1597             long topId = -1;
1598             if (_curList != null && _curTab != null && _curList.VirtualListSize > 0)
1599             {
1600                 if (_statuses.SortMode == IdComparerClass.ComparerMode.Id)
1601                 {
1602                     if (_statuses.SortOrder == SortOrder.Ascending)
1603                     {
1604                         //Id昇順
1605                         if (ListLockMenuItem.Checked)
1606                         {
1607                             //制御しない
1608                             smode = -1;
1609                             ////現在表示位置へ強制スクロール
1610                             //if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1611                             //smode = 0;
1612                         }
1613                         else
1614                         {
1615                             //最下行が表示されていたら、最下行へ強制スクロール。最下行が表示されていなかったら制御しない
1616                             ListViewItem _item;
1617                             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);   //一番下
1618                             if (_item == null) _item = _curList.Items[_curList.Items.Count - 1];
1619                             if (_item.Index == _curList.Items.Count - 1)
1620                             {
1621                                 smode = -2;
1622                             }
1623                             else
1624                             {
1625                                 smode = -1;
1626                                 //if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1627                                 //smode = 0;
1628                             }
1629                         }
1630                     }
1631                     else
1632                     {
1633                         //Id降順
1634                         if (ListLockMenuItem.Checked)
1635                         {
1636                             //現在表示位置へ強制スクロール
1637                             if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1638                             smode = 0;
1639                         }
1640                         else
1641                         {
1642                             //最上行が表示されていたら、制御しない。最上行が表示されていなかったら、現在表示位置へ強制スクロール
1643                             ListViewItem _item;
1644
1645                             _item = _curList.GetItemAt(0, 10);     //一番上
1646                             if (_item == null) _item = _curList.Items[0];
1647                             if (_item.Index == 0)
1648                             {
1649                                 smode = -3;  //最上行
1650                             }
1651                             else
1652                             {
1653                                 if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1654                                 smode = 0;
1655                             }
1656                         }
1657                     }
1658                 }
1659                 else
1660                 {
1661                     //現在表示位置へ強制スクロール
1662                     if (_curList.TopItem != null) topId = _statuses.GetId(_curTab.Text, _curList.TopItem.Index);
1663                     smode = 0;
1664                 }
1665             }
1666             else
1667             {
1668                 smode = -1;
1669             }
1670             return topId;
1671         }
1672
1673         private void SaveSelectedStatus(Dictionary<string, long[]> selId, Dictionary<string, long> focusedId)
1674         {
1675             if (MyCommon._endingFlag) return;
1676             foreach (TabPage tab in ListTab.TabPages)
1677             {
1678                 DetailsListView lst = (DetailsListView)tab.Tag;
1679                 if (lst.SelectedIndices.Count > 0 && lst.SelectedIndices.Count < 61)
1680                 {
1681                     selId.Add(tab.Text, _statuses.GetId(tab.Text, lst.SelectedIndices));
1682                 }
1683                 else
1684                 {
1685                     selId.Add(tab.Text, new long[1] {-2});
1686                 }
1687                 if (lst.FocusedItem != null)
1688                     focusedId.Add(tab.Text, _statuses.GetId(tab.Text, lst.FocusedItem.Index));
1689                 else
1690                     focusedId.Add(tab.Text, -2);
1691             }
1692
1693         }
1694
1695         private bool BalloonRequired()
1696         {
1697             Twitter.FormattedEvent ev = new Twitter.FormattedEvent();
1698             ev.Eventtype = MyCommon.EVENTTYPE.None;
1699
1700             return BalloonRequired(ev);
1701         }
1702
1703         private bool IsEventNotifyAsEventType(MyCommon.EVENTTYPE type)
1704         {
1705             return SettingDialog.EventNotifyEnabled && (type & SettingDialog.EventNotifyFlag) != 0 || type == MyCommon.EVENTTYPE.None;
1706         }
1707
1708         private bool IsMyEventNotityAsEventType(Twitter.FormattedEvent ev)
1709         {
1710             return (ev.Eventtype & SettingDialog.IsMyEventNotifyFlag) != 0 ? true : !ev.IsMe;
1711         }
1712
1713         private bool BalloonRequired(Twitter.FormattedEvent ev)
1714         {
1715             if ((
1716                 IsEventNotifyAsEventType(ev.Eventtype) && IsMyEventNotityAsEventType(ev) &&
1717                 (NewPostPopMenuItem.Checked || (SettingDialog.ForceEventNotify && ev.Eventtype != MyCommon.EVENTTYPE.None)) &&
1718                 !_initial &&
1719                 (
1720                     (
1721                         SettingDialog.LimitBalloon &&
1722                         (
1723                             this.WindowState == FormWindowState.Minimized ||
1724                             !this.Visible ||
1725                             Form.ActiveForm == null
1726                             )
1727                         ) ||
1728                     !SettingDialog.LimitBalloon
1729                     )
1730                 ) &&
1731                 !Win32Api.IsScreenSaverRunning())
1732             {
1733                 return true;
1734             }
1735             else
1736             {
1737                 return false;
1738             }
1739         }
1740
1741         private void NotifyNewPosts(PostClass[] notifyPosts, string soundFile, int addCount, bool newMentions)
1742         {
1743             if (notifyPosts != null &&
1744                 notifyPosts.Length > 0 &&
1745                 this.SettingDialog.ReadOwnPost &&
1746                 notifyPosts.All((post) => { return post.UserId == tw.UserId || post.ScreenName == tw.Username; }))
1747             {
1748                 return;
1749             }
1750
1751             //新着通知
1752             if (BalloonRequired())
1753             {
1754                 if (notifyPosts != null && notifyPosts.Length > 0)
1755                 {
1756                     //Growlは一個ずつばらして通知。ただし、3ポスト以上あるときはまとめる
1757                     if (SettingDialog.IsNotifyUseGrowl)
1758                     {
1759                         StringBuilder sb = new StringBuilder();
1760                         bool reply = false;
1761                         bool dm = false;
1762
1763                         foreach (PostClass post in notifyPosts)
1764                         {
1765                             if (!(notifyPosts.Length > 3))
1766                             {
1767                                 sb.Clear();
1768                                 reply = false;
1769                                 dm = false;
1770                             }
1771                             if (post.IsReply && !post.IsExcludeReply) reply = true;
1772                             if (post.IsDm) dm = true;
1773                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
1774                             switch (SettingDialog.NameBalloon)
1775                             {
1776                                 case MyCommon.NameBalloonEnum.UserID:
1777                                     sb.Append(post.ScreenName).Append(" : ");
1778                                     break;
1779                                 case MyCommon.NameBalloonEnum.NickName:
1780                                     sb.Append(post.Nickname).Append(" : ");
1781                                     break;
1782                             }
1783                             sb.Append(post.TextFromApi);
1784                             if (notifyPosts.Length > 3)
1785                             {
1786                                 if (notifyPosts.Last() != post) continue;
1787                             }
1788
1789                             StringBuilder title = new StringBuilder();
1790                             GrowlHelper.NotifyType nt;
1791                             if (SettingDialog.DispUsername)
1792                             {
1793                                 title.Append(tw.Username);
1794                                 title.Append(" - ");
1795                             }
1796                             else
1797                             {
1798                                 //title.Clear();
1799                             }
1800                             if (dm)
1801                             {
1802                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1803                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
1804                                 title.Append(Application.ProductName);
1805                                 title.Append(" [DM] ");
1806                                 title.Append(Properties.Resources.RefreshDirectMessageText1);
1807                                 title.Append(" ");
1808                                 title.Append(addCount);
1809                                 title.Append(Properties.Resources.RefreshDirectMessageText2);
1810                                 nt = GrowlHelper.NotifyType.DirectMessage;
1811                             }
1812                             else if (reply)
1813                             {
1814                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1815                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1816                                 title.Append(Application.ProductName);
1817                                 title.Append(" [Reply!] ");
1818                                 title.Append(Properties.Resources.RefreshTimelineText1);
1819                                 title.Append(" ");
1820                                 title.Append(addCount);
1821                                 title.Append(Properties.Resources.RefreshTimelineText2);
1822                                 nt = GrowlHelper.NotifyType.Reply;
1823                             }
1824                             else
1825                             {
1826                                 //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
1827                                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1828                                 title.Append(Application.ProductName);
1829                                 title.Append(" ");
1830                                 title.Append(Properties.Resources.RefreshTimelineText1);
1831                                 title.Append(" ");
1832                                 title.Append(addCount);
1833                                 title.Append(Properties.Resources.RefreshTimelineText2);
1834                                 nt = GrowlHelper.NotifyType.Notify;
1835                             }
1836                             string bText = sb.ToString();
1837                             if (string.IsNullOrEmpty(bText)) return;
1838
1839                             gh.Notify(nt, post.StatusId.ToString(), title.ToString(), bText, this.TIconDic[post.ImageUrl], post.ImageUrl);
1840                         }
1841                     }
1842                     else
1843                     {
1844                         StringBuilder sb = new StringBuilder();
1845                         bool reply = false;
1846                         bool dm = false;
1847                         foreach (PostClass post in notifyPosts)
1848                         {
1849                             if (post.IsReply && !post.IsExcludeReply) reply = true;
1850                             if (post.IsDm) dm = true;
1851                             if (sb.Length > 0) sb.Append(System.Environment.NewLine);
1852                             switch (SettingDialog.NameBalloon)
1853                             {
1854                                 case MyCommon.NameBalloonEnum.UserID:
1855                                     sb.Append(post.ScreenName).Append(" : ");
1856                                     break;
1857                                 case MyCommon.NameBalloonEnum.NickName:
1858                                     sb.Append(post.Nickname).Append(" : ");
1859                                     break;
1860                             }
1861                             sb.Append(post.TextFromApi);
1862
1863                         }
1864                         //if (SettingDialog.DispUsername) { NotifyIcon1.BalloonTipTitle = tw.Username + " - "; } else { NotifyIcon1.BalloonTipTitle = ""; }
1865                         StringBuilder title = new StringBuilder();
1866                         ToolTipIcon ntIcon;
1867                         if (SettingDialog.DispUsername)
1868                         {
1869                             title.Append(tw.Username);
1870                             title.Append(" - ");
1871                         }
1872                         else
1873                         {
1874                             //title.Clear();
1875                         }
1876                         if (dm)
1877                         {
1878                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1879                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [DM] " + Properties.Resources.RefreshDirectMessageText1 + " " + addCount.ToString() + Properties.Resources.RefreshDirectMessageText2;
1880                             ntIcon = ToolTipIcon.Warning;
1881                             title.Append(Application.ProductName);
1882                             title.Append(" [DM] ");
1883                             title.Append(Properties.Resources.RefreshDirectMessageText1);
1884                             title.Append(" ");
1885                             title.Append(addCount);
1886                             title.Append(Properties.Resources.RefreshDirectMessageText2);
1887                         }
1888                         else if (reply)
1889                         {
1890                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
1891                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [Reply!] " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1892                             ntIcon = ToolTipIcon.Warning;
1893                             title.Append(Application.ProductName);
1894                             title.Append(" [Reply!] ");
1895                             title.Append(Properties.Resources.RefreshTimelineText1);
1896                             title.Append(" ");
1897                             title.Append(addCount);
1898                             title.Append(Properties.Resources.RefreshTimelineText2);
1899                         }
1900                         else
1901                         {
1902                             //NotifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
1903                             //NotifyIcon1.BalloonTipTitle += Application.ProductName + " " + Properties.Resources.RefreshTimelineText1 + " " + addCount.ToString() + Properties.Resources.RefreshTimelineText2;
1904                             ntIcon = ToolTipIcon.Info;
1905                             title.Append(Application.ProductName);
1906                             title.Append(" ");
1907                             title.Append(Properties.Resources.RefreshTimelineText1);
1908                             title.Append(" ");
1909                             title.Append(addCount);
1910                             title.Append(Properties.Resources.RefreshTimelineText2);
1911                         }
1912                         string bText = sb.ToString();
1913                         if (string.IsNullOrEmpty(bText)) return;
1914                         //NotifyIcon1.BalloonTipText = sb.ToString();
1915                         //NotifyIcon1.ShowBalloonTip(500);
1916                         NotifyIcon1.BalloonTipTitle = title.ToString();
1917                         NotifyIcon1.BalloonTipText = bText;
1918                         NotifyIcon1.BalloonTipIcon = ntIcon;
1919                         NotifyIcon1.ShowBalloonTip(500);
1920                     }
1921                 }
1922             }
1923
1924             //サウンド再生
1925             if (!_initial && SettingDialog.PlaySound && !string.IsNullOrEmpty(soundFile))
1926             {
1927                 try
1928                 {
1929                     string dir = Application.StartupPath;
1930                     if (Directory.Exists(Path.Combine(dir, "Sounds")))
1931                     {
1932                         dir = Path.Combine(dir, "Sounds");
1933                     }
1934                     using (SoundPlayer player = new SoundPlayer(Path.Combine(dir, soundFile)))
1935                     {
1936                         player.Play();
1937                     }
1938                 }
1939                 catch (Exception)
1940                 {
1941                 }
1942             }
1943
1944             //mentions新着時に画面ブリンク
1945             if (!_initial && SettingDialog.BlinkNewMentions && newMentions && Form.ActiveForm == null)
1946             {
1947                 Win32Api.FlashMyWindow(this.Handle, Win32Api.FlashSpecification.FlashTray, 3);
1948             }
1949         }
1950
1951         private void MyList_SelectedIndexChanged(object sender, EventArgs e)
1952         {
1953             if (_curList == null || _curList.SelectedIndices.Count != 1) return;
1954
1955             _curItemIndex = _curList.SelectedIndices[0];
1956             if (_curItemIndex > _curList.VirtualListSize - 1) return;
1957
1958             try
1959             {
1960                 _curPost = GetCurTabPost(_curItemIndex);
1961             }
1962             catch (ArgumentException)
1963             {
1964                 return;
1965             }
1966
1967             this.PushSelectPostChain();
1968
1969             if (SettingDialog.UnreadManage) _statuses.SetReadAllTab(true, _curTab.Text, _curItemIndex);
1970             //キャッシュの書き換え
1971             ChangeCacheStyleRead(true, _curItemIndex, _curTab);   //既読へ(フォント、文字色)
1972
1973             ColorizeList();
1974             _colorize = true;
1975         }
1976
1977         private void ChangeCacheStyleRead(bool Read, int Index, TabPage Tab)
1978         {
1979             //Read:true=既読 false=未読
1980             //未読管理していなかったら既読として扱う
1981             if (!_statuses.Tabs[_curTab.Text].UnreadManage ||
1982                !SettingDialog.UnreadManage) Read = true;
1983
1984             //対象の特定
1985             ListViewItem itm;
1986             PostClass post;
1987             if (Tab.Equals(_curTab) && _itemCache != null && Index >= _itemCacheIndex && Index < _itemCacheIndex + _itemCache.Length)
1988             {
1989                 itm = _itemCache[Index - _itemCacheIndex];
1990                 post = _postCache[Index - _itemCacheIndex];
1991             }
1992             else
1993             {
1994                 itm = ((DetailsListView)Tab.Tag).Items[Index];
1995                 post = _statuses[Tab.Text, Index];
1996             }
1997
1998             ChangeItemStyleRead(Read, itm, post, ((DetailsListView)Tab.Tag));
1999         }
2000
2001         private void ChangeItemStyleRead(bool Read, ListViewItem Item, PostClass Post, DetailsListView DList)
2002         {
2003             Font fnt;
2004             //フォント
2005             if (Read)
2006             {
2007                 fnt = _fntReaded;
2008                 Item.SubItems[5].Text = "";
2009             }
2010             else
2011             {
2012                 fnt = _fntUnread;
2013                 Item.SubItems[5].Text = "★";
2014             }
2015             //文字色
2016             Color cl;
2017             if (Post.IsFav)
2018                 cl = _clFav;
2019             else if (Post.RetweetedId > 0)
2020                 cl = _clRetweet;
2021             else if (Post.IsOwl && (Post.IsDm || SettingDialog.OneWayLove))
2022                 cl = _clOWL;
2023             else if (Read || !SettingDialog.UseUnreadStyle)
2024                 cl = _clReaded;
2025             else
2026                 cl = _clUnread;
2027
2028             if (DList == null || Item.Index == -1)
2029             {
2030                 Item.ForeColor = cl;
2031                 if (SettingDialog.UseUnreadStyle)
2032                     Item.Font = fnt;
2033             }
2034             else
2035             {
2036                 DList.Update();
2037                 if (SettingDialog.UseUnreadStyle)
2038                     DList.ChangeItemFontAndColor(Item.Index, cl, fnt);
2039                 else
2040                     DList.ChangeItemForeColor(Item.Index, cl);
2041                 //if (_itemCache != null) DList.RedrawItems(_itemCacheIndex, _itemCacheIndex + _itemCache.Length - 1, false);
2042             }
2043         }
2044
2045         private void ColorizeList()
2046         {
2047             //Index:更新対象のListviewItem.Index。Colorを返す。
2048             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
2049             PostClass _post;
2050             if (_anchorFlag)
2051                 _post = _anchorPost;
2052             else
2053                 _post = _curPost;
2054
2055             if (_itemCache == null) return;
2056
2057             if (_post == null) return;
2058
2059             try
2060             {
2061                 for (int cnt = 0; cnt <= _itemCache.Length - 1; cnt++)
2062                 {
2063                     _curList.ChangeItemBackColor(_itemCacheIndex + cnt, JudgeColor(_post, _postCache[cnt]));
2064                 }
2065             }
2066             catch (Exception)
2067             {
2068             }
2069         }
2070
2071         private void ColorizeList(ListViewItem Item, int Index)
2072         {
2073             //Index:更新対象のListviewItem.Index。Colorを返す。
2074             //-1は全キャッシュ。Colorは返さない(ダミーを戻す)
2075             PostClass _post;
2076             if (_anchorFlag)
2077                 _post = _anchorPost;
2078             else
2079                 _post = _curPost;
2080
2081             PostClass tPost = GetCurTabPost(Index);
2082
2083             if (_post == null) return;
2084
2085             if (Item.Index == -1)
2086                 Item.BackColor = JudgeColor(_post, tPost);
2087             else
2088                 _curList.ChangeItemBackColor(Item.Index, JudgeColor(_post, tPost));
2089         }
2090
2091         private Color JudgeColor(PostClass BasePost, PostClass TargetPost)
2092         {
2093             Color cl;
2094             if (TargetPost.StatusId == BasePost.InReplyToStatusId)
2095                 //@先
2096                 cl = _clAtTo;
2097             else if (TargetPost.IsMe)
2098                 //自分=発言者
2099                 cl = _clSelf;
2100             else if (TargetPost.IsReply)
2101                 //自分宛返信
2102                 cl = _clAtSelf;
2103             else if (BasePost.ReplyToList.Contains(TargetPost.ScreenName.ToLower()))
2104                 //返信先
2105                 cl = _clAtFromTarget;
2106             else if (TargetPost.ReplyToList.Contains(BasePost.ScreenName.ToLower()))
2107                 //その人への返信
2108                 cl = _clAtTarget;
2109             else if (TargetPost.ScreenName.Equals(BasePost.ScreenName, StringComparison.OrdinalIgnoreCase))
2110                 //発言者
2111                 cl = _clTarget;
2112             else
2113                 //その他
2114                 cl = _clListBackcolor;
2115
2116             return cl;
2117         }
2118
2119         private void PostButton_Click(object sender, EventArgs e)
2120         {
2121             if (StatusText.Text.Trim().Length == 0)
2122             {
2123                 if (!ImageSelectionPanel.Enabled)
2124                 {
2125                     DoRefresh();
2126                     return;
2127                 }
2128             }
2129
2130             if (this.ExistCurrentPost && StatusText.Text.Trim() == string.Format("RT @{0}: {1}", _curPost.ScreenName, _curPost.TextFromApi))
2131             {
2132                 DialogResult rtResult = MessageBox.Show(string.Format(Properties.Resources.PostButton_Click1, Environment.NewLine),
2133                                                                "Retweet",
2134                                                                MessageBoxButtons.YesNoCancel,
2135                                                                MessageBoxIcon.Question);
2136                 switch (rtResult)
2137                 {
2138                     case DialogResult.Yes:
2139                         doReTweetOfficial(false);
2140                         StatusText.Text = "";
2141                         return;
2142                     case DialogResult.Cancel:
2143                         return;
2144                 }
2145             }
2146
2147             _history[_history.Count - 1] = new PostingStatus(StatusText.Text.Trim(), _reply_to_id, _reply_to_name);
2148
2149             if (SettingDialog.Nicoms)
2150             {
2151                 StatusText.SelectionStart = StatusText.Text.Length;
2152                 UrlConvert(MyCommon.UrlConverter.Nicoms);
2153             }
2154             //if (SettingDialog.UrlConvertAuto)
2155             //{
2156             //    StatusText.SelectionStart = StatusText.Text.Length;
2157             //    UrlConvertAutoToolStripMenuItem_Click(null, null);
2158             //}
2159             //else if (SettingDialog.Nicoms)
2160             //{
2161             //    StatusText.SelectionStart = StatusText.Text.Length;
2162             //    UrlConvert(UrlConverter.Nicoms);
2163             //}
2164             StatusText.SelectionStart = StatusText.Text.Length;
2165             GetWorkerArg args = new GetWorkerArg();
2166             args.page = 0;
2167             args.endPage = 0;
2168             args.type = MyCommon.WORKERTYPE.PostMessage;
2169             CheckReplyTo(StatusText.Text);
2170
2171             //整形によって増加する文字数を取得
2172             int adjustCount = 0;
2173             string tmpStatus = StatusText.Text.Trim();
2174             if (ToolStripMenuItemApiCommandEvasion.Checked)
2175             {
2176                 // APIコマンド回避
2177                 if (Regex.IsMatch(tmpStatus,
2178                     @"^[+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]*(get|g|fav|follow|f|on|off|stop|quit|leave|l|whois|w|nudge|n|stats|invite|track|untrack|tracks|tracking|\*)([+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]+|$)",
2179                     RegexOptions.IgnoreCase)
2180                    && tmpStatus.EndsWith(" .") == false) adjustCount += 2;
2181             }
2182
2183             if (ToolStripMenuItemUrlMultibyteSplit.Checked)
2184             {
2185                 // URLと全角文字の切り離し
2186                 adjustCount += Regex.Matches(tmpStatus, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+").Count;
2187             }
2188
2189             bool isCutOff = false;
2190             bool isRemoveFooter = MyCommon.IsKeyDown(Keys.Shift);
2191             if (StatusText.Multiline && !SettingDialog.PostCtrlEnter)
2192             {
2193                 //複数行でEnter投稿の場合、Ctrlも押されていたらフッタ付加しない
2194                 isRemoveFooter = MyCommon.IsKeyDown(Keys.Control);
2195             }
2196             if (SettingDialog.PostShiftEnter)
2197             {
2198                 isRemoveFooter = MyCommon.IsKeyDown(Keys.Control);
2199             }
2200             if (!isRemoveFooter && (StatusText.Text.Contains("RT @") || StatusText.Text.Contains("QT @")))
2201             {
2202                 isRemoveFooter = true;
2203             }
2204             if (GetRestStatusCount(false, !isRemoveFooter) - adjustCount < 0)
2205             {
2206                 if (MessageBox.Show(Properties.Resources.PostLengthOverMessage1, Properties.Resources.PostLengthOverMessage2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.OK)
2207                 {
2208                     isCutOff = true;
2209                     //if (!SettingDialog.UrlConvertAuto) UrlConvertAutoToolStripMenuItem_Click(null, null);
2210                     if (GetRestStatusCount(false, !isRemoveFooter) - adjustCount < 0)
2211                     {
2212                         isRemoveFooter = true;
2213                     }
2214                 }
2215                 else
2216                 {
2217                     return;
2218                 }
2219             }
2220
2221             string footer = "";
2222             string header = "";
2223             if (StatusText.Text.StartsWith("D ") || StatusText.Text.StartsWith("d "))
2224             {
2225                 //DM時は何もつけない
2226                 footer = "";
2227             }
2228             else
2229             {
2230                 //ハッシュタグ
2231                 if (HashMgr.IsNotAddToAtReply)
2232                 {
2233                     if (!string.IsNullOrEmpty(HashMgr.UseHash) && _reply_to_id == 0 && string.IsNullOrEmpty(_reply_to_name))
2234                     {
2235                         if (HashMgr.IsHead)
2236                             header = HashMgr.UseHash + " ";
2237                         else
2238                             footer = " " + HashMgr.UseHash;
2239                     }
2240                 }
2241                 else
2242                 {
2243                     if (!string.IsNullOrEmpty(HashMgr.UseHash))
2244                     {
2245                         if (HashMgr.IsHead)
2246                             header = HashMgr.UseHash + " ";
2247                         else
2248                             footer = " " + HashMgr.UseHash;
2249                     }
2250                 }
2251                 if (!isRemoveFooter)
2252                 {
2253                     if (SettingDialog.UseRecommendStatus)
2254                         // 推奨ステータスを使用する
2255                         footer += SettingDialog.RecommendStatusText;
2256                     else
2257                         // テキストボックスに入力されている文字列を使用する
2258                         footer += " " + SettingDialog.Status.Trim();
2259                 }
2260             }
2261             args.status.status = header + StatusText.Text.Trim() + footer;
2262
2263             if (ToolStripMenuItemApiCommandEvasion.Checked)
2264             {
2265                 // APIコマンド回避
2266                 if (Regex.IsMatch(args.status.status,
2267                     @"^[+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]*(get|g|fav|follow|f|on|off|stop|quit|leave|l|whois|w|nudge|n|stats|invite|track|untrack|tracks|tracking|\*)([+\-\[\]\s\\.,*/(){}^~|='&%$#""<>?]+|$)",
2268                     RegexOptions.IgnoreCase)
2269                    && args.status.status.EndsWith(" .") == false) args.status.status += " .";
2270             }
2271
2272             if (ToolStripMenuItemUrlMultibyteSplit.Checked)
2273             {
2274                 // URLと全角文字の切り離し
2275                 Match mc2 = Regex.Match(args.status.status, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+");
2276                 if (mc2.Success) args.status.status = Regex.Replace(args.status.status, @"https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#^]+", "$& ");
2277             }
2278
2279             if (IdeographicSpaceToSpaceToolStripMenuItem.Checked)
2280             {
2281                 // 文中の全角スペースを半角スペース1個にする
2282                 args.status.status = args.status.status.Replace(" ", " ");
2283             }
2284
2285             if (isCutOff && args.status.status.Length > 140)
2286             {
2287                 args.status.status = args.status.status.Substring(0, 140);
2288                 string AtId = @"(@|@)[a-z0-9_/]+$";
2289                 string HashTag = @"(^|[^0-9A-Z&\/\?]+)(#|#)([0-9A-Z_]*[A-Z_]+)$";
2290                 string Url = @"https?:\/\/[a-z0-9!\*'\(\);:&=\+\$\/%#\[\]\-_\.,~?]+$"; //簡易判定
2291                 string pattern = string.Format("({0})|({1})|({2})", AtId, HashTag, Url);
2292                 Match mc = Regex.Match(args.status.status, pattern, RegexOptions.IgnoreCase);
2293                 if (mc.Success)
2294                 {
2295                     //さらに@ID、ハッシュタグ、URLと推測される文字列をカットする
2296                     args.status.status = args.status.status.Substring(0, 140 - mc.Value.Length);
2297                 }
2298                 if (MessageBox.Show(args.status.status, "Post or Cancel?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel) return;
2299             }
2300
2301             args.status.inReplyToId = _reply_to_id;
2302             args.status.inReplyToName = _reply_to_name;
2303             if (ImageSelectionPanel.Visible)
2304             {
2305                 //画像投稿
2306                 if (ImageSelectedPicture.Image != ImageSelectedPicture.InitialImage &&
2307                     ImageServiceCombo.SelectedIndex > -1 &&
2308                     !string.IsNullOrEmpty(ImagefilePathText.Text))
2309                 {
2310                     if (MessageBox.Show(Properties.Resources.PostPictureConfirm1,
2311                                        Properties.Resources.PostPictureConfirm2,
2312                                        MessageBoxButtons.OKCancel,
2313                                        MessageBoxIcon.Question,
2314                                        MessageBoxDefaultButton.Button1)
2315                                    == DialogResult.Cancel)
2316                     {
2317                         TimelinePanel.Visible = true;
2318                         TimelinePanel.Enabled = true;
2319                         ImageSelectionPanel.Visible = false;
2320                         ImageSelectionPanel.Enabled = false;
2321                         if (_curList != null)
2322                             _curList.Focus();
2323                         return;
2324                     }
2325                     args.status.imageService = ImageServiceCombo.Text;
2326                     args.status.imagePath = ImagefilePathText.Text;
2327                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
2328                     ImagefilePathText.Text = "";
2329                     TimelinePanel.Visible = true;
2330                     TimelinePanel.Enabled = true;
2331                     ImageSelectionPanel.Visible = false;
2332                     ImageSelectionPanel.Enabled = false;
2333                     if (_curList != null)
2334                         _curList.Focus();
2335                 }
2336                 else
2337                 {
2338                     MessageBox.Show(Properties.Resources.PostPictureWarn1, Properties.Resources.PostPictureWarn2);
2339                     return;
2340                 }
2341             }
2342
2343             RunAsync(args);
2344
2345             //Google検索(試験実装)
2346             if (StatusText.Text.StartsWith("Google:", StringComparison.OrdinalIgnoreCase) && StatusText.Text.Trim().Length > 7)
2347             {
2348                 string tmp = string.Format(Properties.Resources.SearchItem2Url, HttpUtility.UrlEncode(StatusText.Text.Substring(7)));
2349                 OpenUriAsync(tmp);
2350             }
2351
2352             _reply_to_id = 0;
2353             _reply_to_name = "";
2354             StatusText.Text = "";
2355             _history.Add(new PostingStatus());
2356             _hisIdx = _history.Count - 1;
2357             if (!ToolStripFocusLockMenuItem.Checked)
2358                 ((Control)ListTab.SelectedTab.Tag).Focus();
2359             urlUndoBuffer = null;
2360             UrlUndoToolStripMenuItem.Enabled = false;  //Undoをできないように設定
2361         }
2362
2363         private void EndToolStripMenuItem_Click(object sender, EventArgs e)
2364         {
2365             MyCommon._endingFlag = true;
2366             this.Close();
2367         }
2368
2369         private void Tween_FormClosing(object sender, FormClosingEventArgs e)
2370         {
2371             if (!SettingDialog.CloseToExit && e.CloseReason == CloseReason.UserClosing && MyCommon._endingFlag == false)
2372             {
2373                 //_endingFlag=false:フォームの×ボタン
2374                 e.Cancel = true;
2375                 this.Visible = false;
2376             }
2377             else
2378             {
2379                 //Google.GASender.GetInstance().TrackEventWithCategory("post", "end", tw.UserId);
2380                 _hookGlobalHotkey.UnregisterAllOriginalHotkey();
2381                 _ignoreConfigSave = true;
2382                 MyCommon._endingFlag = true;
2383                 TimerTimeline.Enabled = false;
2384                 TimerRefreshIcon.Enabled = false;
2385             }
2386         }
2387
2388         private void NotifyIcon1_BalloonTipClicked(object sender, EventArgs e)
2389         {
2390             this.Visible = true;
2391             if (this.WindowState == FormWindowState.Minimized)
2392             {
2393                 this.WindowState = FormWindowState.Normal;
2394             }
2395             this.Activate();
2396             this.BringToFront();
2397         }
2398
2399         private static int errorCount = 0;
2400
2401         private static bool CheckAccountValid()
2402         {
2403             if (Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid)
2404             {
2405                 errorCount += 1;
2406                 if (errorCount > 5)
2407                 {
2408                     errorCount = 0;
2409                     Twitter.AccountState = MyCommon.ACCOUNT_STATE.Valid;
2410                     return true;
2411                 }
2412                 return false;
2413             }
2414             errorCount = 0;
2415             return true;
2416         }
2417
2418         private void GetTimelineWorker_DoWork(object sender, DoWorkEventArgs e)
2419         {
2420             BackgroundWorker bw = (BackgroundWorker)sender;
2421             if (bw.CancellationPending || MyCommon._endingFlag)
2422             {
2423                 e.Cancel = true;
2424                 return;
2425             }
2426
2427             Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
2428
2429             MyApplication.InitCulture();
2430
2431             string ret = "";
2432             GetWorkerResult rslt = new GetWorkerResult();
2433
2434             bool read = !SettingDialog.UnreadManage;
2435             if (_initial && SettingDialog.UnreadManage) read = SettingDialog.Readed;
2436
2437             GetWorkerArg args = (GetWorkerArg)e.Argument;
2438
2439             if (!CheckAccountValid())
2440             {
2441                 rslt.retMsg = "Auth error. Check your account";
2442                 rslt.type = MyCommon.WORKERTYPE.ErrorState;  //エラー表示のみ行ない、後処理キャンセル
2443                 rslt.tName = args.tName;
2444                 e.Result = rslt;
2445                 return;
2446             }
2447
2448             if (args.type != MyCommon.WORKERTYPE.OpenUri) bw.ReportProgress(0, ""); //Notifyアイコンアニメーション開始
2449             switch (args.type)
2450             {
2451                 case MyCommon.WORKERTYPE.Timeline:
2452                 case MyCommon.WORKERTYPE.Reply:
2453                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2454                     ret = tw.GetTimelineApi(read, args.type, args.page == -1, _initial);
2455                     //新着時未読クリア
2456                     if (string.IsNullOrEmpty(ret) && args.type == MyCommon.WORKERTYPE.Timeline && SettingDialog.ReadOldPosts)
2457                         _statuses.SetRead();
2458                     //振り分け
2459                     rslt.addCount = _statuses.DistributePosts();
2460                     break;
2461                 case MyCommon.WORKERTYPE.DirectMessegeRcv:    //送信分もまとめて取得
2462                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2463                     ret = tw.GetDirectMessageApi(read, MyCommon.WORKERTYPE.DirectMessegeRcv, args.page == -1);
2464                     if (string.IsNullOrEmpty(ret)) ret = tw.GetDirectMessageApi(read, MyCommon.WORKERTYPE.DirectMessegeSnt, args.page == -1);
2465                     rslt.addCount = _statuses.DistributePosts();
2466                     break;
2467                 case MyCommon.WORKERTYPE.FavAdd:
2468                     //スレッド処理はしない
2469                     if (_statuses.Tabs.ContainsKey(args.tName))
2470                     {
2471                         TabClass tbc = _statuses.Tabs[args.tName];
2472                         for (int i = 0; i <= args.ids.Count - 1; i++)
2473                         {
2474                             PostClass post = null;
2475                             if (tbc.IsInnerStorageTabType)
2476                                 post = tbc.Posts[args.ids[i]];
2477                             else
2478                                 post = _statuses[args.ids[i]];
2479
2480                             args.page = i + 1;
2481                             bw.ReportProgress(50, MakeStatusMessage(args, false));
2482                             if (!post.IsFav)
2483                             {
2484                                 if (post.RetweetedId == 0)
2485                                     ret = tw.PostFavAdd(post.StatusId);
2486                                 else
2487                                     ret = tw.PostFavAdd(post.RetweetedId);
2488
2489                                 if (ret.Length == 0)
2490                                 {
2491                                     args.sIds.Add(post.StatusId);
2492                                     post.IsFav = true;    //リスト再描画必要
2493                                     _favTimestamps.Add(DateTime.Now);
2494                                     if (string.IsNullOrEmpty(post.RelTabName))
2495                                     {
2496                                         //検索,リストUserTimeline.Relatedタブからのfavは、favタブへ追加せず。それ以外は追加
2497                                         _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).Add(post.StatusId, post.IsRead, false);
2498                                     }
2499                                     else
2500                                     {
2501                                         //検索,リスト,UserTimeline.Relatedタブからのfavで、TLでも取得済みならfav反映
2502                                         if (_statuses.ContainsKey(post.StatusId))
2503                                         {
2504                                             PostClass postTl = _statuses[post.StatusId];
2505                                             postTl.IsFav = true;
2506                                             _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).Add(postTl.StatusId, postTl.IsRead, false);
2507                                         }
2508                                     }
2509                                     //検索,リスト,UserTimeline,Relatedの各タブに反映
2510                                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch | MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.UserTimeline | MyCommon.TabUsageType.Related))
2511                                     {
2512                                         if (tb.Contains(post.StatusId)) tb.Posts[post.StatusId].IsFav = true;
2513                                     }
2514                                 }
2515                             }
2516                         }
2517                     }
2518                     rslt.sIds = args.sIds;
2519                     break;
2520                 case MyCommon.WORKERTYPE.FavRemove:
2521                     //スレッド処理はしない
2522                     if (_statuses.Tabs.ContainsKey(args.tName))
2523                     {
2524                         TabClass tbc = _statuses.Tabs[args.tName];
2525                         for (int i = 0; i <= args.ids.Count - 1; i++)
2526                         {
2527                             PostClass post = null;
2528                             if (tbc.IsInnerStorageTabType)
2529                                 post = tbc.Posts[args.ids[i]];
2530                             else
2531                                 post = _statuses[args.ids[i]];
2532
2533                             args.page = i + 1;
2534                             bw.ReportProgress(50, MakeStatusMessage(args, false));
2535                             if (post.IsFav)
2536                             {
2537                                 if (post.RetweetedId == 0)
2538                                     ret = tw.PostFavRemove(post.StatusId);
2539                                 else
2540                                     ret = tw.PostFavRemove(post.RetweetedId);
2541
2542                                 if (ret.Length == 0)
2543                                 {
2544                                     args.sIds.Add(post.StatusId);
2545                                     post.IsFav = false;    //リスト再描画必要
2546                                     if (_statuses.ContainsKey(post.StatusId)) _statuses[post.StatusId].IsFav = false;
2547                                     //検索,リスト,UserTimeline,Relatedの各タブに反映
2548                                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch | MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.UserTimeline | MyCommon.TabUsageType.Related))
2549                                     {
2550                                         if (tb.Contains(post.StatusId)) tb.Posts[post.StatusId].IsFav = false;
2551                                     }
2552                                 }
2553                             }
2554                         }
2555                     }
2556                     rslt.sIds = args.sIds;
2557                     break;
2558                 case MyCommon.WORKERTYPE.PostMessage:
2559                     bw.ReportProgress(200);
2560                     if (string.IsNullOrEmpty(args.status.imagePath))
2561                     {
2562                         for (int i = 0; i <= 1; i++)
2563                         {
2564                             ret = tw.PostStatus(args.status.status, args.status.inReplyToId);
2565                             if (string.IsNullOrEmpty(ret) ||
2566                                 ret.StartsWith("OK:") ||
2567                                 ret.StartsWith("Outputz:") ||
2568                                 ret.StartsWith("Warn:") ||
2569                                 ret == "Err:Status is a duplicate." ||
2570                                 args.status.status.StartsWith("D", StringComparison.OrdinalIgnoreCase) ||
2571                                 args.status.status.StartsWith("DM", StringComparison.OrdinalIgnoreCase) ||
2572                                 Twitter.AccountState != MyCommon.ACCOUNT_STATE.Valid)
2573                                 break;
2574                         }
2575                     }
2576                     else
2577                     {
2578                         ret = this.pictureService[args.status.imageService].Upload(ref args.status.imagePath,
2579                                                                                    ref args.status.status,
2580                                                                                    args.status.inReplyToId);
2581                     }
2582                     bw.ReportProgress(300);
2583                     rslt.status = args.status;
2584                     break;
2585                 case MyCommon.WORKERTYPE.Retweet:
2586                     bw.ReportProgress(200);
2587                     for (int i = 0; i <= args.ids.Count - 1; i++)
2588                     {
2589                         ret = tw.PostRetweet(args.ids[i], read);
2590                     }
2591                     bw.ReportProgress(300);
2592                     break;
2593                 case MyCommon.WORKERTYPE.Follower:
2594                     bw.ReportProgress(50, Properties.Resources.UpdateFollowersMenuItem1_ClickText1);
2595                     ret = tw.GetFollowersApi();
2596                     if (string.IsNullOrEmpty(ret))
2597                     {
2598                         ret = tw.GetNoRetweetIdsApi();
2599                     }
2600                     break;
2601                 case MyCommon.WORKERTYPE.Configuration:
2602                     ret = tw.ConfigurationApi();
2603                     break;
2604                 case MyCommon.WORKERTYPE.OpenUri:
2605                     string myPath = Convert.ToString(args.url);
2606
2607                     try
2608                     {
2609                         if (!string.IsNullOrEmpty(SettingDialog.BrowserPath))
2610                         {
2611                             if (SettingDialog.BrowserPath.StartsWith("\"") && SettingDialog.BrowserPath.Length > 2 && SettingDialog.BrowserPath.IndexOf("\"", 2) > -1)
2612                             {
2613                                 int sep = SettingDialog.BrowserPath.IndexOf("\"", 2);
2614                                 string browserPath = SettingDialog.BrowserPath.Substring(1, sep - 1);
2615                                 string arg = "";
2616                                 if (sep < SettingDialog.BrowserPath.Length - 1)
2617                                 {
2618                                     arg = SettingDialog.BrowserPath.Substring(sep + 1);
2619                                 }
2620                                 myPath = arg + " " + myPath;
2621                                 System.Diagnostics.Process.Start(browserPath, myPath);
2622                             }
2623                             else
2624                             {
2625                                 System.Diagnostics.Process.Start(SettingDialog.BrowserPath, myPath);
2626                             }
2627                         }
2628                         else
2629                         {
2630                             System.Diagnostics.Process.Start(myPath);
2631                         }
2632                     }
2633                     catch (Exception)
2634                     {
2635     //                  MessageBox.Show("ブラウザの起動に失敗、またはタイムアウトしました。" + ex.ToString());
2636                     }
2637                     break;
2638                 case MyCommon.WORKERTYPE.Favorites:
2639                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2640                     ret = tw.GetFavoritesApi(read, args.type, args.page == -1);
2641                     rslt.addCount = _statuses.DistributePosts();
2642                     break;
2643                 case MyCommon.WORKERTYPE.PublicSearch:
2644                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2645                     if (string.IsNullOrEmpty(args.tName))
2646                     {
2647                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch))
2648                         {
2649                             //if (!string.IsNullOrEmpty(tb.SearchWords)) ret = tw.GetPhoenixSearch(read, tb, false);
2650                             if (!string.IsNullOrEmpty(tb.SearchWords)) ret = tw.GetSearch(read, tb, false);
2651                         }
2652                     }
2653                     else
2654                     {
2655                         TabClass tb = _statuses.GetTabByName(args.tName);
2656                         if (tb != null)
2657                         {
2658                             //ret = tw.GetPhoenixSearch(read, tb, false);
2659                             ret = tw.GetSearch(read, tb, false);
2660                             if (string.IsNullOrEmpty(ret) && args.page == -1)
2661                             {
2662                                 //ret = tw.GetPhoenixSearch(read, tb, true)
2663                                 ret = tw.GetSearch(read, tb, true);
2664                             }
2665                         }
2666                     }
2667                     //振り分け
2668                     rslt.addCount = _statuses.DistributePosts();
2669                     break;
2670                 case MyCommon.WORKERTYPE.UserTimeline:
2671                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2672                     int count = 20;
2673                     if (SettingDialog.UseAdditionalCount) count = SettingDialog.UserTimelineCountApi;
2674                     if (string.IsNullOrEmpty(args.tName))
2675                     {
2676                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline))
2677                         {
2678                             if (!string.IsNullOrEmpty(tb.User)) ret = tw.GetUserTimelineApi(read, count, tb.User, tb, false);
2679                         }
2680                     }
2681                     else
2682                     {
2683                         TabClass tb = _statuses.GetTabByName(args.tName);
2684                         if (tb != null)
2685                         {
2686                             ret = tw.GetUserTimelineApi(read, count, tb.User, tb, args.page == -1);
2687                         }
2688                     }
2689                     //振り分け
2690                     rslt.addCount = _statuses.DistributePosts();
2691                     break;
2692                 case MyCommon.WORKERTYPE.List:
2693                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2694                     if (string.IsNullOrEmpty(args.tName))
2695                     {
2696                         //定期更新
2697                         foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists))
2698                         {
2699                             if (tb.ListInfo != null && tb.ListInfo.Id != 0) ret = tw.GetListStatus(read, tb, false, _initial);
2700                         }
2701                     }
2702                     else
2703                     {
2704                         //手動更新(特定タブのみ更新)
2705                         TabClass tb = _statuses.GetTabByName(args.tName);
2706                         if (tb != null)
2707                         {
2708                             ret = tw.GetListStatus(read, tb, args.page == -1, _initial);
2709                         }
2710                     }
2711                     //振り分け
2712                     rslt.addCount = _statuses.DistributePosts();
2713                     break;
2714                 case MyCommon.WORKERTYPE.Related:
2715                     bw.ReportProgress(50, MakeStatusMessage(args, false));
2716                     TabClass tab = _statuses.GetTabByName(args.tName);
2717                     ret = tw.GetRelatedResult(read, tab);
2718                     rslt.addCount = _statuses.DistributePosts();
2719                     break;
2720                 case MyCommon.WORKERTYPE.BlockIds:
2721                     bw.ReportProgress(50, Properties.Resources.UpdateBlockUserText1);
2722                     ret = tw.GetBlockUserIds();
2723                     if (TabInformations.GetInstance().BlockIds.Count == 0)
2724                     {
2725                         tw.GetBlockUserIds();
2726                     }
2727                     break;
2728             }
2729             //キャンセル要求
2730             if (bw.CancellationPending)
2731             {
2732                 e.Cancel = true;
2733                 return;
2734             }
2735
2736             //時速表示用
2737             if (args.type == MyCommon.WORKERTYPE.FavAdd)
2738             {
2739                 DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
2740                 for (int i = _favTimestamps.Count - 1; i >= 0; i--)
2741                 {
2742                     if (_favTimestamps[i].CompareTo(oneHour) < 0)
2743                     {
2744                         _favTimestamps.RemoveAt(i);
2745                     }
2746                 }
2747             }
2748             if (args.type == MyCommon.WORKERTYPE.Timeline && !_initial)
2749             {
2750                 lock (_syncObject)
2751                 {
2752                     DateTime tm = DateTime.Now;
2753                     if (_tlTimestamps.ContainsKey(tm))
2754                         _tlTimestamps[tm] += rslt.addCount;
2755                     else
2756                         _tlTimestamps.Add(tm, rslt.addCount);
2757
2758                     DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
2759                     List<DateTime> keys = new List<DateTime>();
2760                     _tlCount = 0;
2761                     foreach (DateTime key in _tlTimestamps.Keys)
2762                     {
2763                         if (key.CompareTo(oneHour) < 0)
2764                         {
2765                             keys.Add(key);
2766                         }
2767                         else
2768                         {
2769                             _tlCount += _tlTimestamps[key];
2770                         }
2771                     }
2772                     foreach (DateTime key in keys)
2773                     {
2774                         _tlTimestamps.Remove(key);
2775                     }
2776                     keys.Clear();
2777                 }
2778             }
2779
2780             //終了ステータス
2781             if (args.type != MyCommon.WORKERTYPE.OpenUri) bw.ReportProgress(100, MakeStatusMessage(args, true)); //ステータス書き換え、Notifyアイコンアニメーション開始
2782
2783             rslt.retMsg = ret;
2784             rslt.type = args.type;
2785             rslt.tName = args.tName;
2786             if (args.type == MyCommon.WORKERTYPE.DirectMessegeRcv ||
2787                 args.type == MyCommon.WORKERTYPE.DirectMessegeSnt ||
2788                 args.type == MyCommon.WORKERTYPE.Reply ||
2789                 args.type == MyCommon.WORKERTYPE.Timeline ||
2790                 args.type == MyCommon.WORKERTYPE.Favorites)
2791             {
2792                 rslt.page = args.page - 1;   //値が正しいか後でチェック。10ページ毎の継続確認
2793             }
2794
2795             e.Result = rslt;
2796         }
2797
2798         private string MakeStatusMessage(GetWorkerArg AsyncArg, bool Finish)
2799         {
2800             string smsg = "";
2801             if (!Finish)
2802             {
2803                 //継続中メッセージ
2804                 switch (AsyncArg.type)
2805                 {
2806                     case MyCommon.WORKERTYPE.Timeline:
2807                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText5 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2808                         break;
2809                     case MyCommon.WORKERTYPE.Reply:
2810                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText4 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2811                         break;
2812                     case MyCommon.WORKERTYPE.DirectMessegeRcv:
2813                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText8 + AsyncArg.page.ToString() + Properties.Resources.GetTimelineWorker_RunWorkerCompletedText6;
2814                         break;
2815                     case MyCommon.WORKERTYPE.FavAdd:
2816                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText15 + AsyncArg.page.ToString() + "/" + AsyncArg.ids.Count.ToString() +
2817                                             Properties.Resources.GetTimelineWorker_RunWorkerCompletedText16 + (AsyncArg.page - AsyncArg.sIds.Count - 1).ToString();
2818                         break;
2819                     case MyCommon.WORKERTYPE.FavRemove:
2820                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText17 + AsyncArg.page.ToString() + "/" + AsyncArg.ids.Count.ToString() +
2821                                             Properties.Resources.GetTimelineWorker_RunWorkerCompletedText18 + (AsyncArg.page - AsyncArg.sIds.Count - 1).ToString();
2822                         break;
2823                     case MyCommon.WORKERTYPE.Favorites:
2824                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText19;
2825                         break;
2826                     case MyCommon.WORKERTYPE.PublicSearch:
2827                         smsg = "Search refreshing...";
2828                         break;
2829                     case MyCommon.WORKERTYPE.List:
2830                         smsg = "List refreshing...";
2831                         break;
2832                     case MyCommon.WORKERTYPE.Related:
2833                         smsg = "Related refreshing...";
2834                         break;
2835                     case MyCommon.WORKERTYPE.UserTimeline:
2836                         smsg = "UserTimeline refreshing...";
2837                         break;
2838                 }
2839             }
2840             else
2841             {
2842                 //完了メッセージ
2843                 switch (AsyncArg.type)
2844                 {
2845                     case MyCommon.WORKERTYPE.Timeline:
2846                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText1;
2847                         break;
2848                     case MyCommon.WORKERTYPE.Reply:
2849                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText9;
2850                         break;
2851                     case MyCommon.WORKERTYPE.DirectMessegeRcv:
2852                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText11;
2853                         break;
2854                     case MyCommon.WORKERTYPE.DirectMessegeSnt:
2855                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText13;
2856                         break;
2857                     case MyCommon.WORKERTYPE.FavAdd:
2858                         //進捗メッセージ残す
2859                         break;
2860                     case MyCommon.WORKERTYPE.FavRemove:
2861                         //進捗メッセージ残す
2862                         break;
2863                     case MyCommon.WORKERTYPE.Favorites:
2864                         smsg = Properties.Resources.GetTimelineWorker_RunWorkerCompletedText20;
2865                         break;
2866                     case MyCommon.WORKERTYPE.Follower:
2867                         smsg = Properties.Resources.UpdateFollowersMenuItem1_ClickText3;
2868                         break;
2869                     case MyCommon.WORKERTYPE.Configuration:
2870                         //進捗メッセージ残す
2871                         break;
2872                     case MyCommon.WORKERTYPE.PublicSearch:
2873                         smsg = "Search refreshed";
2874                         break;
2875                     case MyCommon.WORKERTYPE.List:
2876                         smsg = "List refreshed";
2877                         break;
2878                     case MyCommon.WORKERTYPE.Related:
2879                         smsg = "Related refreshed";
2880                         break;
2881                     case MyCommon.WORKERTYPE.UserTimeline:
2882                         smsg = "UserTimeline refreshed";
2883                         break;
2884                     case MyCommon.WORKERTYPE.BlockIds:
2885                         smsg = Properties.Resources.UpdateBlockUserText3;
2886                         break;
2887                 }
2888             }
2889             return smsg;
2890         }
2891
2892         private void GetTimelineWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
2893         {
2894             if (MyCommon._endingFlag) return;
2895             if (e.ProgressPercentage > 100)
2896             {
2897                 //発言投稿
2898                 if (e.ProgressPercentage == 200)    //開始
2899                     StatusLabel.Text = "Posting...";
2900                 if (e.ProgressPercentage == 300)  //終了
2901                     StatusLabel.Text = Properties.Resources.PostWorker_RunWorkerCompletedText4;
2902             }
2903             else
2904             {
2905                 string smsg = (string)e.UserState;
2906                 if (smsg.Length > 0) StatusLabel.Text = smsg;
2907             }
2908         }
2909
2910         private void GetTimelineWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
2911         {
2912             if (MyCommon._endingFlag || e.Cancelled) return; //キャンセル
2913
2914             if (e.Error != null)
2915             {
2916                 _myStatusError = true;
2917                 _waitTimeline = false;
2918                 _waitReply = false;
2919                 _waitDm = false;
2920                 _waitFav = false;
2921                 _waitPubSearch = false;
2922                 _waitUserTimeline = false;
2923                 _waitLists = false;
2924                 throw new Exception("BackgroundWorker Exception", e.Error);
2925             }
2926
2927             GetWorkerResult rslt = (GetWorkerResult)e.Result;
2928
2929             if (rslt.type == MyCommon.WORKERTYPE.OpenUri) return;
2930
2931             //エラー
2932             if (rslt.retMsg.Length > 0)
2933             {
2934                 _myStatusError = true;
2935                 StatusLabel.Text = rslt.retMsg;
2936             }
2937
2938             if (rslt.type == MyCommon.WORKERTYPE.ErrorState) return;
2939
2940             if (rslt.type == MyCommon.WORKERTYPE.FavRemove)
2941             {
2942                 this.RemovePostFromFavTab(rslt.sIds.ToArray());
2943             }
2944
2945             //リストに反映
2946             //bool busy = false;
2947             //foreach (BackgroundWorker bw in _bw)
2948             //{
2949             //    if (bw != null && bw.IsBusy)
2950             //    {
2951             //        busy = true;
2952             //        break;
2953             //    }
2954             //}
2955             //if (!busy) RefreshTimeline(); //background処理なければ、リスト反映
2956             if (rslt.type == MyCommon.WORKERTYPE.Timeline ||
2957                 rslt.type == MyCommon.WORKERTYPE.Reply ||
2958                 rslt.type == MyCommon.WORKERTYPE.List ||
2959                 rslt.type == MyCommon.WORKERTYPE.PublicSearch ||
2960                 rslt.type == MyCommon.WORKERTYPE.DirectMessegeRcv ||
2961                 rslt.type == MyCommon.WORKERTYPE.DirectMessegeSnt ||
2962                 rslt.type == MyCommon.WORKERTYPE.Favorites ||
2963                 rslt.type == MyCommon.WORKERTYPE.Follower ||
2964                 rslt.type == MyCommon.WORKERTYPE.FavAdd ||
2965                 rslt.type == MyCommon.WORKERTYPE.FavRemove ||
2966                 rslt.type == MyCommon.WORKERTYPE.Related ||
2967                 rslt.type == MyCommon.WORKERTYPE.UserTimeline ||
2968                 rslt.type == MyCommon.WORKERTYPE.BlockIds ||
2969                 rslt.type == MyCommon.WORKERTYPE.Configuration)
2970             {
2971                 RefreshTimeline(false); //リスト反映
2972             }
2973
2974             switch (rslt.type)
2975             {
2976                 case MyCommon.WORKERTYPE.Timeline:
2977                     _waitTimeline = false;
2978                     if (!_initial)
2979                     {
2980                         //    //API使用時の取得調整は別途考える(カウント調整?)
2981                     }
2982                     break;
2983                 case MyCommon.WORKERTYPE.Reply:
2984                     _waitReply = false;
2985                     if (rslt.newDM && !_initial)
2986                     {
2987                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
2988                     }
2989                     break;
2990                 case MyCommon.WORKERTYPE.Favorites:
2991                     _waitFav = false;
2992                     break;
2993                 case MyCommon.WORKERTYPE.DirectMessegeRcv:
2994                     _waitDm = false;
2995                     break;
2996                 case MyCommon.WORKERTYPE.FavAdd:
2997                 case MyCommon.WORKERTYPE.FavRemove:
2998                     if (_curList != null && _curTab != null)
2999                     {
3000                         _curList.BeginUpdate();
3001                         if (rslt.type == MyCommon.WORKERTYPE.FavRemove && _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.Favorites)
3002                         {
3003                             //色変えは不要
3004                         }
3005                         else
3006                         {
3007                             for (int i = 0; i <= rslt.sIds.Count - 1; i++)
3008                             {
3009                                 if (_curTab.Text.Equals(rslt.tName))
3010                                 {
3011                                     int idx = _statuses.Tabs[rslt.tName].IndexOf(rslt.sIds[i]);
3012                                     if (idx > -1)
3013                                     {
3014                                         PostClass post = null;
3015                                         TabClass tb = _statuses.Tabs[rslt.tName];
3016                                         if (tb != null)
3017                                         {
3018                                             if (tb.TabType == MyCommon.TabUsageType.Lists || tb.TabType == MyCommon.TabUsageType.PublicSearch)
3019                                             {
3020                                                 post = tb.Posts[rslt.sIds[i]];
3021                                             }
3022                                             else
3023                                             {
3024                                                 post = _statuses[rslt.sIds[i]];
3025                                             }
3026                                             ChangeCacheStyleRead(post.IsRead, idx, _curTab);
3027                                         }
3028                                         if (idx == _curItemIndex) DispSelectedPost(true); //選択アイテム再表示
3029                                     }
3030                                 }
3031                             }
3032                         }
3033                         _curList.EndUpdate();
3034                     }
3035                     break;
3036                 case MyCommon.WORKERTYPE.PostMessage:
3037                     if (string.IsNullOrEmpty(rslt.retMsg) ||
3038                         rslt.retMsg.StartsWith("Outputz") ||
3039                         rslt.retMsg.StartsWith("OK:") ||
3040                         rslt.retMsg == "Warn:Status is a duplicate.")
3041                     {
3042                         _postTimestamps.Add(DateTime.Now);
3043                         DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
3044                         for (int i = _postTimestamps.Count - 1; i >= 0; i--)
3045                         {
3046                             if (_postTimestamps[i].CompareTo(oneHour) < 0)
3047                             {
3048                                 _postTimestamps.RemoveAt(i);
3049                             }
3050                         }
3051
3052                         if (!HashMgr.IsPermanent && !string.IsNullOrEmpty(HashMgr.UseHash))
3053                         {
3054                             HashMgr.ClearHashtag();
3055                             this.HashStripSplitButton.Text = "#[-]";
3056                             this.HashToggleMenuItem.Checked = false;
3057                             this.HashToggleToolStripMenuItem.Checked = false;
3058                         }
3059                         SetMainWindowTitle();
3060                         rslt.retMsg = "";
3061                     }
3062                     else
3063                     {
3064                         DialogResult retry;
3065                         try
3066                         {
3067                             retry = MessageBox.Show(string.Format("{0}   --->   [ " + rslt.retMsg + " ]" + Environment.NewLine + "\"" + rslt.status.status + "\"" + Environment.NewLine + "{1}",
3068                                                                 Properties.Resources.StatusUpdateFailed1,
3069                                                                 Properties.Resources.StatusUpdateFailed2),
3070                                                             "Failed to update status",
3071                                                             MessageBoxButtons.RetryCancel,
3072                                                             MessageBoxIcon.Question);
3073                         }
3074                         catch (Exception)
3075                         {
3076                             retry = DialogResult.Abort;
3077                         }
3078                         if (retry == DialogResult.Retry)
3079                         {
3080                             GetWorkerArg args = new GetWorkerArg();
3081                             args.page = 0;
3082                             args.endPage = 0;
3083                             args.type = MyCommon.WORKERTYPE.PostMessage;
3084                             args.status = rslt.status;
3085                             RunAsync(args);
3086                         }
3087                         else
3088                         {
3089                             if (ToolStripFocusLockMenuItem.Checked)
3090                             {
3091                                 //連投モードのときだけEnterイベントが起きないので強制的に背景色を戻す
3092                                 StatusText_Enter(StatusText, new EventArgs());
3093                             }
3094                         }
3095                     }
3096                     if (rslt.retMsg.Length == 0 && SettingDialog.PostAndGet)
3097                     {
3098                         if (_isActiveUserstream)
3099                         {
3100                             RefreshTimeline(true);
3101                         }
3102                         else
3103                         {
3104                             GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3105                         }
3106                     }
3107                     break;
3108                 case MyCommon.WORKERTYPE.Retweet:
3109                     if (rslt.retMsg.Length == 0)
3110                     {
3111                         _postTimestamps.Add(DateTime.Now);
3112                         DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
3113                         for (int i = _postTimestamps.Count - 1; i >= 0; i--)
3114                         {
3115                             if (_postTimestamps[i].CompareTo(oneHour) < 0)
3116                             {
3117                                 _postTimestamps.RemoveAt(i);
3118                             }
3119                         }
3120                         if (!_isActiveUserstream && SettingDialog.PostAndGet) GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3121                     }
3122                     break;
3123                 case MyCommon.WORKERTYPE.Follower:
3124                     //_waitFollower = false;
3125                     _itemCache = null;
3126                     _postCache = null;
3127                     if (_curList != null) _curList.Refresh();
3128                     break;
3129                 case MyCommon.WORKERTYPE.Configuration:
3130                     //_waitFollower = false
3131                     if (SettingDialog.TwitterConfiguration.PhotoSizeLimit != 0)
3132                     {
3133                         pictureService["Twitter"].Configuration("MaxUploadFilesize", SettingDialog.TwitterConfiguration.PhotoSizeLimit);
3134                     }
3135                     _itemCache = null;
3136                     _postCache = null;
3137                     if (_curList != null) _curList.Refresh();
3138                     break;
3139                 case MyCommon.WORKERTYPE.PublicSearch:
3140                     _waitPubSearch = false;
3141                     break;
3142                 case MyCommon.WORKERTYPE.UserTimeline:
3143                     _waitUserTimeline = false;
3144                     break;
3145                 case MyCommon.WORKERTYPE.List:
3146                     _waitLists = false;
3147                     break;
3148                 case MyCommon.WORKERTYPE.Related:
3149                     TabClass tab = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
3150                     if (tab != null && tab.RelationTargetPost != null && tab.Contains(tab.RelationTargetPost.StatusId))
3151                     {
3152                         foreach (TabPage tp in ListTab.TabPages)
3153                         {
3154                             if (tp.Text == tab.TabName)
3155                             {
3156                                 ((DetailsListView)tp.Tag).SelectedIndices.Add(tab.IndexOf(tab.RelationTargetPost.StatusId));
3157                                 ((DetailsListView)tp.Tag).Items[tab.IndexOf(tab.RelationTargetPost.StatusId)].Focused = true;
3158                                 break;
3159                             }
3160                         }
3161                     }
3162                     break;
3163             }
3164         }
3165
3166         private void RemovePostFromFavTab(Int64[] ids)
3167         {
3168             string favTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Favorites).TabName;
3169             int fidx = 0;
3170             if (_curTab.Text.Equals(favTabName))
3171             {
3172                 if (_curList.FocusedItem != null)
3173                     fidx = _curList.FocusedItem.Index;
3174                 else if (_curList.TopItem != null)
3175                     fidx = _curList.TopItem.Index;
3176                 else
3177                     fidx = 0;
3178             }
3179
3180             foreach (long i in ids)
3181             {
3182                 try
3183                 {
3184                     _statuses.RemoveFavPost(i);
3185                 }
3186                 catch (Exception)
3187                 {
3188                     continue;
3189                 }
3190             }
3191             if (_curTab != null && _curTab.Text.Equals(favTabName))
3192             {
3193                 _itemCache = null;    //キャッシュ破棄
3194                 _postCache = null;
3195                 _curPost = null;
3196                 //_curItemIndex = -1;
3197             }
3198             foreach (TabPage tp in ListTab.TabPages)
3199             {
3200                 if (tp.Text == favTabName)
3201                 {
3202                     ((DetailsListView)tp.Tag).VirtualListSize = _statuses.Tabs[favTabName].AllCount;
3203                     break;
3204                 }
3205             }
3206             if (_curTab.Text.Equals(favTabName))
3207             {
3208                 do
3209                 {
3210                     _curList.SelectedIndices.Clear();
3211                 }
3212                 while (_curList.SelectedIndices.Count > 0);
3213
3214                 if (_statuses.Tabs[favTabName].AllCount > 0)
3215                 {
3216                     if (_statuses.Tabs[favTabName].AllCount - 1 > fidx && fidx > -1)
3217                     {
3218                         _curList.SelectedIndices.Add(fidx);
3219                     }
3220                     else
3221                     {
3222                         _curList.SelectedIndices.Add(_statuses.Tabs[favTabName].AllCount - 1);
3223                     }
3224                     if (_curList.SelectedIndices.Count > 0)
3225                     {
3226                         _curList.EnsureVisible(_curList.SelectedIndices[0]);
3227                         _curList.FocusedItem = _curList.Items[_curList.SelectedIndices[0]];
3228                     }
3229                 }
3230             }
3231         }
3232
3233         private static Dictionary<MyCommon.WORKERTYPE, DateTime> lastTime = new Dictionary<MyCommon.WORKERTYPE, DateTime>();
3234
3235         private void GetTimeline(MyCommon.WORKERTYPE WkType, int fromPage, int toPage, string tabName)
3236         {
3237             if (!this.IsNetworkAvailable()) return;
3238
3239             //非同期実行引数設定
3240             GetWorkerArg args = new GetWorkerArg();
3241             args.page = fromPage;
3242             args.endPage = toPage;
3243             args.type = WkType;
3244             args.tName = tabName;
3245
3246             if (!lastTime.ContainsKey(WkType)) lastTime.Add(WkType, new DateTime());
3247             double period = DateTime.Now.Subtract(lastTime[WkType]).TotalSeconds;
3248             if (period > 1 || period < -1)
3249             {
3250                 lastTime[WkType] = DateTime.Now;
3251                 RunAsync(args);
3252             }
3253
3254             //Timeline取得モードの場合はReplyも同時に取得
3255             //if (!SettingDialog.UseAPI &&
3256             //   !_initial &&
3257             //   WkType == MyCommon.WORKERTYPE.Timeline &&
3258             //   SettingDialog.CheckReply)
3259             //{
3260             //    //TimerReply.Enabled = false;
3261             //    _mentionCounter = SettingDialog.ReplyPeriodInt;
3262             //    GetWorkerArg _args = new GetWorkerArg();
3263             //    _args.page = fromPage;
3264             //    _args.endPage = toPage;
3265             //    _args.type = MyCommon.WORKERTYPE.Reply;
3266             //    RunAsync(_args);
3267             //}
3268         }
3269
3270         private void NotifyIcon1_MouseClick(object sender, MouseEventArgs e)
3271         {
3272             if (e.Button == MouseButtons.Left)
3273             {
3274                 this.Visible = true;
3275                 if (this.WindowState == FormWindowState.Minimized)
3276                 {
3277                     this.WindowState = _formWindowState;
3278                 }
3279                 this.Activate();
3280                 this.BringToFront();
3281             }
3282         }
3283
3284         private void MyList_MouseDoubleClick(object sender, MouseEventArgs e)
3285         {
3286             switch (SettingDialog.ListDoubleClickAction)
3287             {
3288                 case 0:
3289                     MakeReplyOrDirectStatus();
3290                     break;
3291                 case 1:
3292                     FavoriteChange(true);
3293                     break;
3294                 case 2:
3295                     if (_curPost != null)
3296                         ShowUserStatus(_curPost.ScreenName, false);
3297                     break;
3298                 case 3:
3299                     ShowUserTimeline();
3300                     break;
3301                 case 4:
3302                     ShowRelatedStatusesMenuItem_Click(null, null);
3303                     break;
3304                 case 5:
3305                     MoveToHomeToolStripMenuItem_Click(null, null);
3306                     break;
3307                 case 6:
3308                     StatusOpenMenuItem_Click(null, null);
3309                     break;
3310                 case 7:
3311                     //動作なし
3312                     break;
3313             }
3314         }
3315
3316         private void FavAddToolStripMenuItem_Click(object sender, EventArgs e)
3317         {
3318             FavoriteChange(true);
3319         }
3320
3321         private void FavRemoveToolStripMenuItem_Click(object sender, EventArgs e)
3322         {
3323             FavoriteChange(false);
3324         }
3325
3326
3327         private void FavoriteRetweetMenuItem_Click(object sender, EventArgs e)
3328         {
3329             FavoritesRetweetOriginal();
3330         }
3331
3332         private void FavoriteRetweetUnofficialMenuItem_Click(object sender, EventArgs e)
3333         {
3334             FavoritesRetweetUnofficial();
3335         }
3336
3337         private void FavoriteChange(bool FavAdd , bool multiFavoriteChangeDialogEnable = true)
3338         {
3339             //trueでFavAdd,falseでFavRemove
3340             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || _curList.SelectedIndices.Count == 0
3341                 || !this.ExistCurrentPost) return;
3342
3343             //複数fav確認msg
3344             if (_curList.SelectedIndices.Count > 250 && FavAdd)
3345             {
3346                 MessageBox.Show(Properties.Resources.FavoriteLimitCountText);
3347                 _DoFavRetweetFlags = false;
3348                 return;
3349             }
3350             else if (multiFavoriteChangeDialogEnable && _curList.SelectedIndices.Count > 1)
3351             {
3352                 if (FavAdd)
3353                 {
3354                     string QuestionText = Properties.Resources.FavAddToolStripMenuItem_ClickText1;
3355                     if (_DoFavRetweetFlags) QuestionText = Properties.Resources.FavoriteRetweetQuestionText3;
3356                     if (MessageBox.Show(QuestionText, Properties.Resources.FavAddToolStripMenuItem_ClickText2,
3357                                        MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
3358                     {
3359                         _DoFavRetweetFlags = false;
3360                         return;
3361                     }
3362                 }
3363                 else
3364                 {
3365                     if (MessageBox.Show(Properties.Resources.FavRemoveToolStripMenuItem_ClickText1, Properties.Resources.FavRemoveToolStripMenuItem_ClickText2,
3366                                     MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
3367                     {
3368                         return;
3369                     }
3370                 }
3371             }
3372
3373             GetWorkerArg args = new GetWorkerArg();
3374             args.ids = new List<long>();
3375             args.sIds = new List<long>();
3376             args.tName = _curTab.Text;
3377             if (FavAdd)
3378             {
3379                 args.type = MyCommon.WORKERTYPE.FavAdd;
3380             }
3381             else
3382             {
3383                 args.type = MyCommon.WORKERTYPE.FavRemove;
3384             }
3385             foreach (int idx in _curList.SelectedIndices)
3386             {
3387                 PostClass post = GetCurTabPost(idx);
3388                 if (FavAdd)
3389                 {
3390                     if (!post.IsFav) args.ids.Add(post.StatusId);
3391                 }
3392                 else
3393                 {
3394                     if (post.IsFav) args.ids.Add(post.StatusId);
3395                 }
3396             }
3397             if (args.ids.Count == 0)
3398             {
3399                 if (FavAdd)
3400                     StatusLabel.Text = Properties.Resources.FavAddToolStripMenuItem_ClickText4;
3401                 else
3402                     StatusLabel.Text = Properties.Resources.FavRemoveToolStripMenuItem_ClickText4;
3403
3404                 return;
3405             }
3406
3407             RunAsync(args);
3408         }
3409
3410         private PostClass GetCurTabPost(int Index)
3411         {
3412             if (_postCache != null && Index >= _itemCacheIndex && Index < _itemCacheIndex + _postCache.Length)
3413                 return _postCache[Index - _itemCacheIndex];
3414             else
3415                 return _statuses[_curTab.Text, Index];
3416         }
3417
3418
3419         private void MoveToHomeToolStripMenuItem_Click(object sender, EventArgs e)
3420         {
3421             if (_curList.SelectedIndices.Count > 0)
3422                 OpenUriAsync(MyCommon.TwitterUrl + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName);
3423             else if (_curList.SelectedIndices.Count == 0)
3424                 OpenUriAsync(MyCommon.TwitterUrl);
3425         }
3426
3427         private void MoveToFavToolStripMenuItem_Click(object sender, EventArgs e)
3428         {
3429             if (_curList.SelectedIndices.Count > 0)
3430                 OpenUriAsync(MyCommon.TwitterUrl + "#!/" + GetCurTabPost(_curList.SelectedIndices[0]).ScreenName + "/favorites");
3431         }
3432
3433         private void Tween_ClientSizeChanged(object sender, EventArgs e)
3434         {
3435             if ((!_initialLayout) && this.Visible)
3436             {
3437                 if (this.WindowState == FormWindowState.Normal)
3438                 {
3439                     _mySize = this.ClientSize;
3440                     _mySpDis = this.SplitContainer1.SplitterDistance;
3441                     _mySpDis3 = this.SplitContainer3.SplitterDistance;
3442                     if (StatusText.Multiline) _mySpDis2 = this.StatusText.Height;
3443                     _modifySettingLocal = true;
3444                 }
3445             }
3446         }
3447
3448         private void MyList_ColumnClick(object sender, ColumnClickEventArgs e)
3449         {
3450             if (SettingDialog.SortOrderLock) return;
3451             IdComparerClass.ComparerMode mode = IdComparerClass.ComparerMode.Id;
3452             if (_iconCol)
3453             {
3454                 mode = IdComparerClass.ComparerMode.Id;
3455             }
3456             else
3457             {
3458                 switch (e.Column)
3459                 {
3460                     case 0:
3461                     case 5:
3462                     case 6:    //0:アイコン,5:未読マーク,6:プロテクト・フィルターマーク
3463                         //ソートしない
3464                         return;
3465                     case 1:  //ニックネーム
3466                         mode = IdComparerClass.ComparerMode.Nickname;
3467                         break;
3468                     case 2:  //本文
3469                         mode = IdComparerClass.ComparerMode.Data;
3470                         break;
3471                     case 3:  //時刻=発言Id
3472                         mode = IdComparerClass.ComparerMode.Id;
3473                         break;
3474                     case 4:  //名前
3475                         mode = IdComparerClass.ComparerMode.Name;
3476                         break;
3477                     case 7:  //Source
3478                         mode = IdComparerClass.ComparerMode.Source;
3479                         break;
3480                 }
3481             }
3482             _statuses.ToggleSortOrder(mode);
3483             InitColumnText();
3484
3485             DetailsListView list = (DetailsListView)sender;
3486             if (_iconCol)
3487             {
3488                 list.Columns[0].Text = ColumnOrgText[0];
3489                 list.Columns[1].Text = ColumnText[2];
3490             }
3491             else
3492             {
3493                 for (int i = 0; i <= 7; i++)
3494                 {
3495                     list.Columns[i].Text = ColumnOrgText[i];
3496                 }
3497                 list.Columns[e.Column].Text = ColumnText[e.Column];
3498             }
3499
3500             _itemCache = null;
3501             _postCache = null;
3502
3503             if (_statuses.Tabs[_curTab.Text].AllCount > 0 && _curPost != null)
3504             {
3505                 int idx = _statuses.Tabs[_curTab.Text].IndexOf(_curPost.StatusId);
3506                 if (idx > -1)
3507                 {
3508                     SelectListItem(_curList, idx);
3509                     _curList.EnsureVisible(idx);
3510                 }
3511             }
3512             _curList.Refresh();
3513             _modifySettingCommon = true;
3514         }
3515
3516         private void Tween_LocationChanged(object sender, EventArgs e)
3517         {
3518             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
3519             {
3520                 _myLoc = this.DesktopLocation;
3521                 _modifySettingLocal = true;
3522             }
3523         }
3524
3525         private void ContextMenuOperate_Opening(object sender, CancelEventArgs e)
3526         {
3527             if (ListTab.SelectedTab == null) return;
3528             if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
3529             if (!this.ExistCurrentPost)
3530             {
3531                 ReplyStripMenuItem.Enabled = false;
3532                 ReplyAllStripMenuItem.Enabled = false;
3533                 DMStripMenuItem.Enabled = false;
3534                 ShowProfileMenuItem.Enabled = false;
3535                 ShowUserTimelineContextMenuItem.Enabled = false;
3536                 ListManageUserContextToolStripMenuItem2.Enabled = false;
3537                 MoveToFavToolStripMenuItem.Enabled = false;
3538                 TabMenuItem.Enabled = false;
3539                 IDRuleMenuItem.Enabled = false;
3540                 ReadedStripMenuItem.Enabled = false;
3541                 UnreadStripMenuItem.Enabled = false;
3542             }
3543             else
3544             {
3545                 ShowProfileMenuItem.Enabled = true;
3546                 ListManageUserContextToolStripMenuItem2.Enabled = true;
3547                 ReplyStripMenuItem.Enabled = true;
3548                 ReplyAllStripMenuItem.Enabled = true;
3549                 DMStripMenuItem.Enabled = true;
3550                 ShowUserTimelineContextMenuItem.Enabled = true;
3551                 MoveToFavToolStripMenuItem.Enabled = true;
3552                 TabMenuItem.Enabled = true;
3553                 IDRuleMenuItem.Enabled = true;
3554                 ReadedStripMenuItem.Enabled = true;
3555                 UnreadStripMenuItem.Enabled = true;
3556             }
3557             DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3558             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
3559             {
3560                 FavAddToolStripMenuItem.Enabled = false;
3561                 FavRemoveToolStripMenuItem.Enabled = false;
3562                 StatusOpenMenuItem.Enabled = false;
3563                 FavorareMenuItem.Enabled = false;
3564                 ShowRelatedStatusesMenuItem.Enabled = false;
3565
3566                 ReTweetStripMenuItem.Enabled = false;
3567                 ReTweetOriginalStripMenuItem.Enabled = false;
3568                 QuoteStripMenuItem.Enabled = false;
3569                 FavoriteRetweetContextMenu.Enabled = false;
3570                 FavoriteRetweetUnofficialContextMenu.Enabled = false;
3571                 if (this.ExistCurrentPost && _curPost.IsDm)
3572                     DeleteStripMenuItem.Enabled = true;
3573                 else
3574                     DeleteStripMenuItem.Enabled = false;
3575             }
3576             else
3577             {
3578                 FavAddToolStripMenuItem.Enabled = true;
3579                 FavRemoveToolStripMenuItem.Enabled = true;
3580                 StatusOpenMenuItem.Enabled = true;
3581                 FavorareMenuItem.Enabled = true;
3582                 ShowRelatedStatusesMenuItem.Enabled = true;  //PublicSearchの時問題出るかも
3583
3584                 if (_curPost.IsMe)
3585                 {
3586                     ReTweetOriginalStripMenuItem.Enabled = false;
3587                     FavoriteRetweetContextMenu.Enabled = false;
3588                     if (string.IsNullOrEmpty(_curPost.RetweetedBy))
3589                     {
3590                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3591                     }
3592                     else
3593                     {
3594                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText2;
3595                     }
3596                     DeleteStripMenuItem.Enabled = true;
3597                 }
3598                 else
3599                 {
3600                     if (string.IsNullOrEmpty(_curPost.RetweetedBy))
3601                     {
3602                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText1;
3603                     }
3604                     else
3605                     {
3606                         DeleteStripMenuItem.Text = Properties.Resources.DeleteMenuText2;
3607                     }
3608                     DeleteStripMenuItem.Enabled = false;
3609                     if (_curPost.IsProtect)
3610                     {
3611                         ReTweetOriginalStripMenuItem.Enabled = false;
3612                         ReTweetStripMenuItem.Enabled = false;
3613                         QuoteStripMenuItem.Enabled = false;
3614                         FavoriteRetweetContextMenu.Enabled = false;
3615                         FavoriteRetweetUnofficialContextMenu.Enabled = false;
3616                     }
3617                     else
3618                     {
3619                         ReTweetOriginalStripMenuItem.Enabled = true;
3620                         ReTweetStripMenuItem.Enabled = true;
3621                         QuoteStripMenuItem.Enabled = true;
3622                         FavoriteRetweetContextMenu.Enabled = true;
3623                         FavoriteRetweetUnofficialContextMenu.Enabled = true;
3624                     }
3625                 }
3626             }
3627             //if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.Favorites)
3628             //{
3629             //    RefreshMoreStripMenuItem.Enabled = true;
3630             //}
3631             //else
3632             //{
3633             //    RefreshMoreStripMenuItem.Enabled = false;
3634             //}
3635             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch
3636                                 || !this.ExistCurrentPost
3637                                 || !(_curPost.InReplyToStatusId > 0))
3638             {
3639                 RepliedStatusOpenMenuItem.Enabled = false;
3640             }
3641             else
3642             {
3643                 RepliedStatusOpenMenuItem.Enabled = true;
3644             }
3645             if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
3646             {
3647                 MoveToRTHomeMenuItem.Enabled = false;
3648             }
3649             else
3650             {
3651                 MoveToRTHomeMenuItem.Enabled = true;
3652             }
3653         }
3654
3655         private void ReplyStripMenuItem_Click(object sender, EventArgs e)
3656         {
3657             MakeReplyOrDirectStatus(false, true);
3658         }
3659
3660         private void DMStripMenuItem_Click(object sender, EventArgs e)
3661         {
3662             MakeReplyOrDirectStatus(false, false);
3663         }
3664
3665         private void doStatusDelete()
3666         {
3667             if (_curTab == null || _curList == null) return;
3668             if (_statuses.Tabs[_curTab.Text].TabType != MyCommon.TabUsageType.DirectMessage)
3669             {
3670                 bool myPost = false;
3671                 foreach (int idx in _curList.SelectedIndices)
3672                 {
3673                     if (GetCurTabPost(idx).IsMe ||
3674                        GetCurTabPost(idx).RetweetedBy.ToLower() == tw.Username.ToLower())
3675                     {
3676                         myPost = true;
3677                         break;
3678                     }
3679                 }
3680                 if (!myPost) return;
3681             }
3682             else
3683             {
3684                 if (_curList.SelectedIndices.Count == 0)
3685                     return;
3686             }
3687
3688             string tmp = string.Format(Properties.Resources.DeleteStripMenuItem_ClickText1, Environment.NewLine);
3689
3690             if (MessageBox.Show(tmp, Properties.Resources.DeleteStripMenuItem_ClickText2,
3691                   MessageBoxButtons.OKCancel,
3692                   MessageBoxIcon.Question) == DialogResult.Cancel) return;
3693
3694             int fidx;
3695             if (_curList.FocusedItem != null)
3696                 fidx = _curList.FocusedItem.Index;
3697             else if (_curList.TopItem != null)
3698                 fidx = _curList.TopItem.Index;
3699             else
3700                 fidx = 0;
3701
3702             try
3703             {
3704                 this.Cursor = Cursors.WaitCursor;
3705
3706                 bool rslt = true;
3707                 foreach (long Id in _statuses.GetId(_curTab.Text, _curList.SelectedIndices))
3708                 {
3709                     string rtn = "";
3710                     if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)
3711                     {
3712                         rtn = tw.RemoveDirectMessage(Id, _statuses[Id]);
3713                     }
3714                     else
3715                     {
3716                         if (_statuses[Id].IsMe || _statuses[Id].RetweetedBy.ToLower() == tw.Username.ToLower())
3717                             rtn = tw.RemoveStatus(Id);
3718                         else
3719                             continue;
3720                     }
3721                     if (rtn.Length > 0)
3722                     {
3723                         //エラー
3724                         rslt = false;
3725                     }
3726                     else
3727                     {
3728                         _statuses.RemovePost(Id);
3729                     }
3730                 }
3731
3732                 if (!rslt)
3733                     StatusLabel.Text = Properties.Resources.DeleteStripMenuItem_ClickText3;  //失敗
3734                 else
3735                     StatusLabel.Text = Properties.Resources.DeleteStripMenuItem_ClickText4;  //成功
3736
3737                 _itemCache = null;    //キャッシュ破棄
3738                 _postCache = null;
3739                 _curPost = null;
3740                 _curItemIndex = -1;
3741                 foreach (TabPage tb in ListTab.TabPages)
3742                 {
3743                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
3744                     if (_curTab.Equals(tb))
3745                     {
3746                         do
3747                         {
3748                             _curList.SelectedIndices.Clear();
3749                         }
3750                         while (_curList.SelectedIndices.Count > 0);
3751
3752                         if (_statuses.Tabs[tb.Text].AllCount > 0)
3753                         {
3754                             if (_statuses.Tabs[tb.Text].AllCount - 1 > fidx && fidx > -1)
3755                                 _curList.SelectedIndices.Add(fidx);
3756                             else
3757                                 _curList.SelectedIndices.Add(_statuses.Tabs[tb.Text].AllCount - 1);
3758
3759                             if (_curList.SelectedIndices.Count > 0)
3760                             {
3761                                 _curList.EnsureVisible(_curList.SelectedIndices[0]);
3762                                 _curList.FocusedItem = _curList.Items[_curList.SelectedIndices[0]];
3763                             }
3764                         }
3765                     }
3766                     if (_statuses.Tabs[tb.Text].UnreadCount == 0)
3767                     {
3768                         if (SettingDialog.TabIconDisp)
3769                         {
3770                             if (tb.ImageIndex == 0) tb.ImageIndex = -1; //タブアイコン
3771                         }
3772                     }
3773                 }
3774                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3775             }
3776             finally
3777             {
3778                 this.Cursor = Cursors.Default;
3779             }
3780         }
3781
3782         private void DeleteStripMenuItem_Click(object sender, EventArgs e)
3783         {
3784             doStatusDelete();
3785         }
3786
3787         private void ReadedStripMenuItem_Click(object sender, EventArgs e)
3788         {
3789             _curList.BeginUpdate();
3790             if (SettingDialog.UnreadManage)
3791             {
3792                 foreach (int idx in _curList.SelectedIndices)
3793                 {
3794                     _statuses.SetReadAllTab(true, _curTab.Text, idx);
3795                 }
3796             }
3797             foreach (int idx in _curList.SelectedIndices)
3798             {
3799                 ChangeCacheStyleRead(true, idx, _curTab);
3800             }
3801             ColorizeList();
3802             _curList.EndUpdate();
3803             foreach (TabPage tb in ListTab.TabPages)
3804             {
3805                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
3806                 {
3807                     if (SettingDialog.TabIconDisp)
3808                     {
3809                         if (tb.ImageIndex == 0) tb.ImageIndex = -1; //タブアイコン
3810                     }
3811                 }
3812             }
3813             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3814         }
3815
3816         private void UnreadStripMenuItem_Click(object sender, EventArgs e)
3817         {
3818             _curList.BeginUpdate();
3819             if (SettingDialog.UnreadManage)
3820             {
3821                 foreach (int idx in _curList.SelectedIndices)
3822                 {
3823                     _statuses.SetReadAllTab(false, _curTab.Text, idx);
3824                 }
3825             }
3826             foreach (int idx in _curList.SelectedIndices)
3827             {
3828                 ChangeCacheStyleRead(false, idx, _curTab);
3829             }
3830             ColorizeList();
3831             _curList.EndUpdate();
3832             foreach (TabPage tb in ListTab.TabPages)
3833             {
3834                 if (_statuses.Tabs[tb.Text].UnreadCount > 0)
3835                 {
3836                     if (SettingDialog.TabIconDisp)
3837                     {
3838                         if (tb.ImageIndex == -1) tb.ImageIndex = 0; //タブアイコン
3839                     }
3840                 }
3841             }
3842             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
3843         }
3844
3845         private void RefreshStripMenuItem_Click(object sender, EventArgs e)
3846         {
3847             DoRefresh();
3848         }
3849
3850         private void DoRefresh()
3851         {
3852             if (_curTab != null)
3853             {
3854                 switch (_statuses.Tabs[_curTab.Text].TabType)
3855                 {
3856                     case MyCommon.TabUsageType.Mentions:
3857                         GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
3858                         break;
3859                     case MyCommon.TabUsageType.DirectMessage:
3860                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
3861                         break;
3862                     case MyCommon.TabUsageType.Favorites:
3863                         GetTimeline(MyCommon.WORKERTYPE.Favorites, 1, 0, "");
3864                         break;
3865                     //case MyCommon.TabUsageType.Profile:
3866                         //// TODO
3867                     case MyCommon.TabUsageType.PublicSearch:
3868                         //// TODO
3869                         TabClass tb = _statuses.Tabs[_curTab.Text];
3870                         if (string.IsNullOrEmpty(tb.SearchWords)) return;
3871                         GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, _curTab.Text);
3872                         break;
3873                     case MyCommon.TabUsageType.UserTimeline:
3874                         GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, _curTab.Text);
3875                         break;
3876                     case MyCommon.TabUsageType.Lists:
3877                         //// TODO
3878                         TabClass tab = _statuses.Tabs[_curTab.Text];
3879                         if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
3880                         GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, _curTab.Text);
3881                         break;
3882                     default:
3883                         GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3884                         break;
3885                 }
3886             }
3887             else
3888             {
3889                 GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 0, "");
3890             }
3891         }
3892
3893         private void DoRefreshMore()
3894         {
3895             //ページ指定をマイナス1に
3896             if (_curTab != null)
3897             {
3898                 switch (_statuses.Tabs[_curTab.Text].TabType)
3899                 {
3900                     case MyCommon.TabUsageType.Mentions:
3901                         GetTimeline(MyCommon.WORKERTYPE.Reply, -1, 0, "");
3902                         break;
3903                     case MyCommon.TabUsageType.DirectMessage:
3904                         GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, -1, 0, "");
3905                         break;
3906                     case MyCommon.TabUsageType.Favorites:
3907                         GetTimeline(MyCommon.WORKERTYPE.Favorites, -1, 0, "");
3908                         break;
3909                     case MyCommon.TabUsageType.Profile:
3910                         //// TODO
3911                         break;
3912                     case MyCommon.TabUsageType.PublicSearch:
3913                         // TODO
3914                         TabClass tb = _statuses.Tabs[_curTab.Text];
3915                         if (string.IsNullOrEmpty(tb.SearchWords)) return;
3916                         GetTimeline(MyCommon.WORKERTYPE.PublicSearch, -1, 0, _curTab.Text);
3917                         break;
3918                     case MyCommon.TabUsageType.UserTimeline:
3919                         GetTimeline(MyCommon.WORKERTYPE.UserTimeline, -1, 0, _curTab.Text);
3920                         break;
3921                     case MyCommon.TabUsageType.Lists:
3922                         //// TODO
3923                         TabClass tab = _statuses.Tabs[_curTab.Text];
3924                         if (tab.ListInfo == null || tab.ListInfo.Id == 0) return;
3925                         GetTimeline(MyCommon.WORKERTYPE.List, -1, 0, _curTab.Text);
3926                         break;
3927                     default:
3928                         GetTimeline(MyCommon.WORKERTYPE.Timeline, -1, 0, "");
3929                         break;
3930                 }
3931             }
3932             else
3933             {
3934                 GetTimeline(MyCommon.WORKERTYPE.Timeline, -1, 0, "");
3935             }
3936         }
3937
3938         private void SettingStripMenuItem_Click(object sender, EventArgs e)
3939         {
3940             DialogResult result;
3941             string uid = tw.Username.ToLower();
3942
3943             try
3944             {
3945                 result = SettingDialog.ShowDialog(this);
3946             }
3947             catch (Exception)
3948             {
3949                 return;
3950             }
3951
3952             if (result == DialogResult.OK)
3953             {
3954                 lock (_syncObject)
3955                 {
3956                     tw.TinyUrlResolve = SettingDialog.TinyUrlResolve;
3957                     tw.RestrictFavCheck = SettingDialog.RestrictFavCheck;
3958                     tw.ReadOwnPost = SettingDialog.ReadOwnPost;
3959                     tw.UseSsl = SettingDialog.UseSsl;
3960                     ShortUrl.IsResolve = SettingDialog.TinyUrlResolve;
3961                     ShortUrl.IsForceResolve = SettingDialog.ShortUrlForceResolve;
3962                     ShortUrl.BitlyId = SettingDialog.BitlyUser;
3963                     ShortUrl.BitlyKey = SettingDialog.BitlyPwd;
3964                     HttpTwitter.TwitterUrl = _cfgCommon.TwitterUrl;
3965                     HttpTwitter.TwitterSearchUrl = _cfgCommon.TwitterSearchUrl;
3966
3967                     HttpConnection.InitializeConnection(SettingDialog.DefaultTimeOut,
3968                                                         SettingDialog.SelectedProxyType,
3969                                                         SettingDialog.ProxyAddress,
3970                                                         SettingDialog.ProxyPort,
3971                                                         SettingDialog.ProxyUser,
3972                                                         SettingDialog.ProxyPassword);
3973                     this.CreatePictureServices();
3974     #if UA
3975                     this.SplitContainer4.Panel2.Controls.RemoveAt(0);
3976                     this.ab = new AdsBrowser();
3977                     this.SplitContainer4.Panel2.Controls.Add(ab);
3978     #endif
3979                     try
3980                     {
3981                         if (SettingDialog.TabIconDisp)
3982                         {
3983                             ListTab.DrawItem -= ListTab_DrawItem;
3984                             ListTab.DrawMode = TabDrawMode.Normal;
3985                             ListTab.ImageList = this.TabImage;
3986                         }
3987                         else
3988                         {
3989                             ListTab.DrawItem -= ListTab_DrawItem;
3990                             ListTab.DrawItem += ListTab_DrawItem;
3991                             ListTab.DrawMode = TabDrawMode.OwnerDrawFixed;
3992                             ListTab.ImageList = null;
3993                         }
3994                     }
3995                     catch (Exception ex)
3996                     {
3997                         ex.Data["Instance"] = "ListTab(TabIconDisp)";
3998                         ex.Data["IsTerminatePermission"] = false;
3999                         throw;
4000                     }
4001
4002                     try
4003                     {
4004                         if (!SettingDialog.UnreadManage)
4005                         {
4006                             ReadedStripMenuItem.Enabled = false;
4007                             UnreadStripMenuItem.Enabled = false;
4008                             if (SettingDialog.TabIconDisp)
4009                             {
4010                                 foreach (TabPage myTab in ListTab.TabPages)
4011                                 {
4012                                     myTab.ImageIndex = -1;
4013                                 }
4014                             }
4015                         }
4016                         else
4017                         {
4018                             ReadedStripMenuItem.Enabled = true;
4019                             UnreadStripMenuItem.Enabled = true;
4020                         }
4021                     }
4022                     catch (Exception ex)
4023                     {
4024                         ex.Data["Instance"] = "ListTab(UnreadManage)";
4025                         ex.Data["IsTerminatePermission"] = false;
4026                         throw;
4027                     }
4028
4029                     try
4030                     {
4031                         foreach (TabPage mytab in ListTab.TabPages)
4032                         {
4033                             DetailsListView lst = (DetailsListView)mytab.Tag;
4034                             lst.GridLines = SettingDialog.ShowGrid;
4035                         }
4036                     }
4037                     catch (Exception ex)
4038                     {
4039                         ex.Data["Instance"] = "ListTab(ShowGrid)";
4040                         ex.Data["IsTerminatePermission"] = false;
4041                         throw;
4042                     }
4043
4044                     PlaySoundMenuItem.Checked = SettingDialog.PlaySound;
4045                     this.PlaySoundFileMenuItem.Checked = SettingDialog.PlaySound;
4046                     _fntUnread = SettingDialog.FontUnread;
4047                     _clUnread = SettingDialog.ColorUnread;
4048                     _fntReaded = SettingDialog.FontReaded;
4049                     _clReaded = SettingDialog.ColorReaded;
4050                     _clFav = SettingDialog.ColorFav;
4051                     _clOWL = SettingDialog.ColorOWL;
4052                     _clRetweet = SettingDialog.ColorRetweet;
4053                     _fntDetail = SettingDialog.FontDetail;
4054                     _clDetail = SettingDialog.ColorDetail;
4055                     _clDetailLink = SettingDialog.ColorDetailLink;
4056                     _clDetailBackcolor = SettingDialog.ColorDetailBackcolor;
4057                     _clSelf = SettingDialog.ColorSelf;
4058                     _clAtSelf = SettingDialog.ColorAtSelf;
4059                     _clTarget = SettingDialog.ColorTarget;
4060                     _clAtTarget = SettingDialog.ColorAtTarget;
4061                     _clAtFromTarget = SettingDialog.ColorAtFromTarget;
4062                     _clAtTo = SettingDialog.ColorAtTo;
4063                     _clListBackcolor = SettingDialog.ColorListBackcolor;
4064                     _clInputBackcolor = SettingDialog.ColorInputBackcolor;
4065                     _clInputFont = SettingDialog.ColorInputFont;
4066                     _fntInputFont = SettingDialog.FontInputFont;
4067                     try
4068                     {
4069                         if (StatusText.Focused) StatusText.BackColor = _clInputBackcolor;
4070                         StatusText.Font = _fntInputFont;
4071                         StatusText.ForeColor = _clInputFont;
4072                     }
4073                     catch (Exception ex)
4074                     {
4075                         MessageBox.Show(ex.Message);
4076                     }
4077
4078                     _brsForeColorUnread.Dispose();
4079                     _brsForeColorReaded.Dispose();
4080                     _brsForeColorFav.Dispose();
4081                     _brsForeColorOWL.Dispose();
4082                     _brsForeColorRetweet.Dispose();
4083                     _brsForeColorUnread = new SolidBrush(_clUnread);
4084                     _brsForeColorReaded = new SolidBrush(_clReaded);
4085                     _brsForeColorFav = new SolidBrush(_clFav);
4086                     _brsForeColorOWL = new SolidBrush(_clOWL);
4087                     _brsForeColorRetweet = new SolidBrush(_clRetweet);
4088                     _brsBackColorMine.Dispose();
4089                     _brsBackColorAt.Dispose();
4090                     _brsBackColorYou.Dispose();
4091                     _brsBackColorAtYou.Dispose();
4092                     _brsBackColorAtFromTarget.Dispose();
4093                     _brsBackColorAtTo.Dispose();
4094                     _brsBackColorNone.Dispose();
4095                     _brsBackColorMine = new SolidBrush(_clSelf);
4096                     _brsBackColorAt = new SolidBrush(_clAtSelf);
4097                     _brsBackColorYou = new SolidBrush(_clTarget);
4098                     _brsBackColorAtYou = new SolidBrush(_clAtTarget);
4099                     _brsBackColorAtFromTarget = new SolidBrush(_clAtFromTarget);
4100                     _brsBackColorAtTo = new SolidBrush(_clAtTo);
4101                     _brsBackColorNone = new SolidBrush(_clListBackcolor);
4102                     try
4103                     {
4104                         if (SettingDialog.IsMonospace)
4105                         {
4106                             detailHtmlFormatHeader = detailHtmlFormatMono1;
4107                             detailHtmlFormatFooter = detailHtmlFormatMono7;
4108                         }
4109                         else
4110                         {
4111                             detailHtmlFormatHeader = detailHtmlFormat1;
4112                             detailHtmlFormatFooter = detailHtmlFormat7;
4113                         }
4114                         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();
4115                         if (SettingDialog.IsMonospace)
4116                         {
4117                             detailHtmlFormatHeader += detailHtmlFormatMono6;
4118                         }
4119                         else
4120                         {
4121                             detailHtmlFormatHeader += detailHtmlFormat6;
4122                         }
4123                     }
4124                     catch (Exception ex)
4125                     {
4126                         ex.Data["Instance"] = "Font";
4127                         ex.Data["IsTerminatePermission"] = false;
4128                         throw;
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                             if (tb.Tag != null && tb.Controls.Count > 0)
4153                             {
4154                                 ((DetailsListView)tb.Tag).Font = _fntReaded;
4155                                 ((DetailsListView)tb.Tag).BackColor = _clListBackcolor;
4156                             }
4157                         }
4158                     }
4159                     catch (Exception ex)
4160                     {
4161                         ex.Data["Instance"] = "ListTab(TabIconDisp no2)";
4162                         ex.Data["IsTerminatePermission"] = false;
4163                         throw;
4164                     }
4165                     SetMainWindowTitle();
4166                     SetNotifyIconText();
4167
4168                     _itemCache = null;
4169                     _postCache = null;
4170                     if (_curList != null) _curList.Refresh();
4171                     ListTab.Refresh();
4172
4173                     Outputz.Key = SettingDialog.OutputzKey;
4174                     Outputz.Enabled = SettingDialog.OutputzEnabled;
4175                     switch (SettingDialog.OutputzUrlmode)
4176                     {
4177                         case MyCommon.OutputzUrlmode.twittercom:
4178                             Outputz.OutUrl = "http://twitter.com/";
4179                             break;
4180                         case MyCommon.OutputzUrlmode.twittercomWithUsername:
4181                             Outputz.OutUrl = "http://twitter.com/" + tw.Username;
4182                             break;
4183                     }
4184
4185                     _hookGlobalHotkey.UnregisterAllOriginalHotkey();
4186                     if (SettingDialog.HotkeyEnabled)
4187                     {
4188                         ///グローバルホットキーの登録。設定で変更可能にするかも
4189                         HookGlobalHotkey.ModKeys modKey = HookGlobalHotkey.ModKeys.None;
4190                         if ((SettingDialog.HotkeyMod & Keys.Alt) == Keys.Alt) modKey = modKey | HookGlobalHotkey.ModKeys.Alt;
4191                         if ((SettingDialog.HotkeyMod & Keys.Control) == Keys.Control) modKey = modKey | HookGlobalHotkey.ModKeys.Ctrl;
4192                         if ((SettingDialog.HotkeyMod & Keys.Shift) == Keys.Shift) modKey = modKey | HookGlobalHotkey.ModKeys.Shift;
4193                         if ((SettingDialog.HotkeyMod & Keys.LWin) == Keys.LWin) modKey = modKey | HookGlobalHotkey.ModKeys.Win;
4194
4195                         _hookGlobalHotkey.RegisterOriginalHotkey(SettingDialog.HotkeyKey, SettingDialog.HotkeyValue, modKey);
4196                     }
4197
4198                     if (uid != tw.Username) this.doGetFollowersMenu();
4199
4200                     SetImageServiceCombo();
4201                     if (SettingDialog.IsNotifyUseGrowl) gh.RegisterGrowl();
4202                     try
4203                     {
4204                         StatusText_TextChanged(null, null);
4205                     }
4206                     catch (Exception)
4207                     {
4208                     }
4209                 }
4210             }
4211
4212             Twitter.AccountState = MyCommon.ACCOUNT_STATE.Valid;
4213
4214             this.TopMost = SettingDialog.AlwaysTop;
4215             SaveConfigsAll(false);
4216         }
4217
4218         private void PostBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
4219         {
4220             if (e.Url.AbsoluteUri != "about:blank")
4221             {
4222                 DispSelectedPost();
4223                 OpenUriAsync(e.Url.OriginalString);
4224             }
4225         }
4226
4227         private void PostBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
4228         {
4229             if (e.Url.Scheme == "data")
4230             {
4231                 StatusLabelUrl.Text = PostBrowser.StatusText.Replace("&", "&&");
4232             }
4233             else if (e.Url.AbsoluteUri != "about:blank")
4234             {
4235                 e.Cancel = true;
4236
4237                 if (e.Url.AbsoluteUri.StartsWith("http://twitter.com/search?q=%23") ||
4238                    e.Url.AbsoluteUri.StartsWith("https://twitter.com/search?q=%23"))
4239                 {
4240                     //ハッシュタグの場合は、タブで開く
4241                     string urlStr = HttpUtility.UrlDecode(e.Url.AbsoluteUri);
4242                     int i = urlStr.IndexOf('#');
4243                     if (i == -1) return;
4244
4245                     string hash = urlStr.Substring(i);
4246                     HashSupl.AddItem(hash);
4247                     HashMgr.AddHashToHistory(hash.Trim(), false);
4248                     AddNewTabForSearch(hash);
4249                     return;
4250                 }
4251                 else
4252                 {
4253                     Match m = Regex.Match(e.Url.AbsoluteUri, "^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
4254                     if (m.Success && IsTwitterId(m.Result("${ScreenName}")))
4255                     {
4256                         // Ctrlを押しながらリンクをクリックした場合は設定と逆の動作をする
4257                         if (SettingDialog.OpenUserTimeline)
4258                         {
4259                             if (MyCommon.IsKeyDown(Keys.Control))
4260                                 OpenUriAsync(e.Url.OriginalString);
4261                             else
4262                                 this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
4263                         }
4264                         else
4265                         {
4266                             if (MyCommon.IsKeyDown(Keys.Control))
4267                                 this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
4268                             else
4269                                 OpenUriAsync(e.Url.OriginalString);
4270                         }
4271                     }
4272                     else
4273                     {
4274                         OpenUriAsync(e.Url.OriginalString);
4275                     }
4276                 }
4277             }
4278         }
4279
4280         public void AddNewTabForSearch(string searchWord)
4281         {
4282             //同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
4283             foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.PublicSearch))
4284             {
4285                 if (tb.SearchWords == searchWord && string.IsNullOrEmpty(tb.SearchLang))
4286                 {
4287                     foreach (TabPage tp in ListTab.TabPages)
4288                     {
4289                         if (tb.TabName == tp.Text)
4290                         {
4291                             ListTab.SelectedTab = tp;
4292                             return;
4293                         }
4294                     }
4295                 }
4296             }
4297             //ユニークなタブ名生成
4298             string tabName = searchWord;
4299             for (int i = 0; i <= 100; i++)
4300             {
4301                 if (_statuses.ContainsTab(tabName))
4302                     tabName += "_";
4303                 else
4304                     break;
4305             }
4306             //タブ追加
4307             _statuses.AddTab(tabName, MyCommon.TabUsageType.PublicSearch, null);
4308             AddNewTab(tabName, false, MyCommon.TabUsageType.PublicSearch);
4309             //追加したタブをアクティブに
4310             ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
4311             //検索条件の設定
4312             ComboBox cmb = (ComboBox)ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"];
4313             cmb.Items.Add(searchWord);
4314             cmb.Text = searchWord;
4315             SaveConfigsTabs();
4316             //検索実行
4317             this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
4318         }
4319
4320         private void ShowUserTimeline()
4321         {
4322             if (!this.ExistCurrentPost) return;
4323             AddNewTabForUserTimeline(_curPost.ScreenName);
4324         }
4325
4326         private void SearchComboBox_KeyDown(object sender, KeyEventArgs e)
4327         {
4328             if (e.KeyCode == Keys.Escape)
4329             {
4330                 TabPage relTp = ListTab.SelectedTab;
4331                 RemoveSpecifiedTab(relTp.Text, false);
4332                 SaveConfigsTabs();
4333                 e.SuppressKeyPress = true;
4334             }
4335         }
4336
4337         public void AddNewTabForUserTimeline(string user)
4338         {
4339             //同一検索条件のタブが既に存在すれば、そのタブアクティブにして終了
4340             foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.UserTimeline))
4341             {
4342                 if (tb.User == user)
4343                 {
4344                     foreach (TabPage tp in ListTab.TabPages)
4345                     {
4346                         if (tb.TabName == tp.Text)
4347                         {
4348                             ListTab.SelectedTab = tp;
4349                             return;
4350                         }
4351                     }
4352                 }
4353             }
4354             //ユニークなタブ名生成
4355             string tabName = "user:" + user;
4356             while (_statuses.ContainsTab(tabName))
4357             {
4358                 tabName += "_";
4359             }
4360             //タブ追加
4361             _statuses.AddTab(tabName, MyCommon.TabUsageType.UserTimeline, null);
4362             _statuses.Tabs[tabName].User = user;
4363             AddNewTab(tabName, false, MyCommon.TabUsageType.UserTimeline);
4364             //追加したタブをアクティブに
4365             ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
4366             SaveConfigsTabs();
4367             //検索実行
4368
4369             GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, tabName);
4370         }
4371
4372         public bool AddNewTab(string tabName, bool startup, MyCommon.TabUsageType tabType, ListElement listInfo = null)
4373         {
4374             //重複チェック
4375             foreach (TabPage tb in ListTab.TabPages)
4376             {
4377                 if (tb.Text == tabName) return false;
4378             }
4379
4380             //新規タブ名チェック
4381             if (tabName == Properties.Resources.AddNewTabText1) return false;
4382
4383             //タブタイプ重複チェック
4384             if (!startup)
4385             {
4386                 if (tabType == MyCommon.TabUsageType.DirectMessage ||
4387                    tabType == MyCommon.TabUsageType.Favorites ||
4388                    tabType == MyCommon.TabUsageType.Home ||
4389                    tabType == MyCommon.TabUsageType.Mentions ||
4390                    tabType == MyCommon.TabUsageType.Related)
4391                 {
4392                     if (_statuses.GetTabByType(tabType) != null) return false;
4393                 }
4394             }
4395
4396             TabPage _tabPage = new TabPage();
4397             DetailsListView _listCustom = new DetailsListView();
4398             ColumnHeader _colHd1 = new ColumnHeader();  //アイコン
4399             ColumnHeader _colHd2 = new ColumnHeader();   //ニックネーム
4400             ColumnHeader _colHd3 = new ColumnHeader();   //本文
4401             ColumnHeader _colHd4 = new ColumnHeader();   //日付
4402             ColumnHeader _colHd5 = new ColumnHeader();   //ユーザID
4403             ColumnHeader _colHd6 = new ColumnHeader();   //未読
4404             ColumnHeader _colHd7 = new ColumnHeader();   //マーク&プロテクト
4405             ColumnHeader _colHd8 = new ColumnHeader();   //ソース
4406
4407             int cnt = ListTab.TabPages.Count;
4408
4409             ///ToDo:Create and set controls follow tabtypes
4410
4411             this.SplitContainer1.Panel1.SuspendLayout();
4412             this.SplitContainer1.Panel2.SuspendLayout();
4413             this.SplitContainer1.SuspendLayout();
4414             this.ListTab.SuspendLayout();
4415             this.SuspendLayout();
4416
4417             _tabPage.SuspendLayout();
4418
4419             /// UserTimeline関連
4420             Label label = null;
4421             if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists)
4422             {
4423                 label = new Label();
4424                 label.Dock = DockStyle.Top;
4425                 label.Name = "labelUser";
4426                 if (tabType == MyCommon.TabUsageType.Lists)
4427                 {
4428                     label.Text = listInfo.ToString();
4429                 }
4430                 else
4431                 {
4432                     label.Text = _statuses.Tabs[tabName].User + "'s Timeline";
4433                 }
4434                 label.TextAlign = ContentAlignment.MiddleLeft;
4435                 using (ComboBox tmpComboBox = new ComboBox())
4436                 {
4437                     label.Height = tmpComboBox.Height;
4438                 }
4439                 _tabPage.Controls.Add(label);
4440             }
4441
4442             /// 検索関連の準備
4443             Panel pnl = null;
4444             if (tabType == MyCommon.TabUsageType.PublicSearch)
4445             {
4446                 pnl = new Panel();
4447
4448                 Label lbl = new Label();
4449                 ComboBox cmb = new ComboBox();
4450                 Button btn = new Button();
4451                 ComboBox cmbLang = new ComboBox();
4452
4453                 pnl.SuspendLayout();
4454
4455                 pnl.Controls.Add(cmb);
4456                 pnl.Controls.Add(cmbLang);
4457                 pnl.Controls.Add(btn);
4458                 pnl.Controls.Add(lbl);
4459                 pnl.Name = "panelSearch";
4460                 pnl.Dock = DockStyle.Top;
4461                 pnl.Height = cmb.Height;
4462                 pnl.Enter += SearchControls_Enter;
4463                 pnl.Leave += SearchControls_Leave;
4464
4465                 cmb.Text = "";
4466                 cmb.Anchor = AnchorStyles.Left | AnchorStyles.Right;
4467                 cmb.Dock = DockStyle.Fill;
4468                 cmb.Name = "comboSearch";
4469                 cmb.DropDownStyle = ComboBoxStyle.DropDown;
4470                 cmb.ImeMode = ImeMode.NoControl;
4471                 cmb.TabStop = false;
4472                 cmb.AutoCompleteMode = AutoCompleteMode.None;
4473                 cmb.KeyDown += SearchComboBox_KeyDown;
4474
4475                 if (_statuses.ContainsTab(tabName))
4476                 {
4477                     cmb.Items.Add(_statuses.Tabs[tabName].SearchWords);
4478                     cmb.Text = _statuses.Tabs[tabName].SearchWords;
4479                 }
4480
4481                 cmbLang.Text = "";
4482                 cmbLang.Anchor = AnchorStyles.Left | AnchorStyles.Right;
4483                 cmbLang.Dock = DockStyle.Right;
4484                 cmbLang.Width = 50;
4485                 cmbLang.Name = "comboLang";
4486                 cmbLang.DropDownStyle = ComboBoxStyle.DropDownList;
4487                 cmbLang.TabStop = false;
4488                 cmbLang.Items.Add("");
4489                 cmbLang.Items.Add("ja");
4490                 cmbLang.Items.Add("en");
4491                 cmbLang.Items.Add("ar");
4492                 cmbLang.Items.Add("da");
4493                 cmbLang.Items.Add("nl");
4494                 cmbLang.Items.Add("fa");
4495                 cmbLang.Items.Add("fi");
4496                 cmbLang.Items.Add("fr");
4497                 cmbLang.Items.Add("de");
4498                 cmbLang.Items.Add("hu");
4499                 cmbLang.Items.Add("is");
4500                 cmbLang.Items.Add("it");
4501                 cmbLang.Items.Add("no");
4502                 cmbLang.Items.Add("pl");
4503                 cmbLang.Items.Add("pt");
4504                 cmbLang.Items.Add("ru");
4505                 cmbLang.Items.Add("es");
4506                 cmbLang.Items.Add("sv");
4507                 cmbLang.Items.Add("th");
4508                 if (_statuses.ContainsTab(tabName)) cmbLang.Text = _statuses.Tabs[tabName].SearchLang;
4509             
4510                 lbl.Text = "Search(C-S-f)";
4511                 lbl.Name = "label1";
4512                 lbl.Dock = DockStyle.Left;
4513                 lbl.Width = 90;
4514                 lbl.Height = cmb.Height;
4515                 lbl.TextAlign = ContentAlignment.MiddleLeft;
4516
4517                 btn.Text = "Search";
4518                 btn.Name = "buttonSearch";
4519                 btn.UseVisualStyleBackColor = true;
4520                 btn.Dock = DockStyle.Right;
4521                 btn.TabStop = false;
4522                 btn.Click += SearchButton_Click;
4523             }
4524
4525             this.ListTab.Controls.Add(_tabPage);
4526             _tabPage.Controls.Add(_listCustom);
4527
4528             if (tabType == MyCommon.TabUsageType.PublicSearch) _tabPage.Controls.Add(pnl);
4529             if (tabType == MyCommon.TabUsageType.UserTimeline || tabType == MyCommon.TabUsageType.Lists) _tabPage.Controls.Add(label);
4530
4531             _tabPage.Location = new Point(4, 4);
4532             _tabPage.Name = "CTab" + cnt.ToString();
4533             _tabPage.Size = new Size(380, 260);
4534             _tabPage.TabIndex = 2 + cnt;
4535             _tabPage.Text = tabName;
4536             _tabPage.UseVisualStyleBackColor = true;
4537
4538             _listCustom.AllowColumnReorder = true;
4539             if (!_iconCol)
4540             {
4541                 _listCustom.Columns.AddRange(new ColumnHeader[] {_colHd1, _colHd2, _colHd3, _colHd4, _colHd5, _colHd6, _colHd7, _colHd8});
4542             }
4543             else
4544             {
4545                 _listCustom.Columns.AddRange(new ColumnHeader[] {_colHd1, _colHd3});
4546             }
4547             _listCustom.ContextMenuStrip = this.ContextMenuOperate;
4548             _listCustom.Dock = DockStyle.Fill;
4549             _listCustom.FullRowSelect = true;
4550             _listCustom.HideSelection = false;
4551             _listCustom.Location = new Point(0, 0);
4552             _listCustom.Margin = new Padding(0);
4553             _listCustom.Name = "CList" + Environment.TickCount.ToString();
4554             _listCustom.ShowItemToolTips = true;
4555             _listCustom.Size = new Size(380, 260);
4556             _listCustom.UseCompatibleStateImageBehavior = false;
4557             _listCustom.View = View.Details;
4558             _listCustom.OwnerDraw = true;
4559             _listCustom.VirtualMode = true;
4560             _listCustom.Font = _fntReaded;
4561             _listCustom.BackColor = _clListBackcolor;
4562
4563             _listCustom.GridLines = SettingDialog.ShowGrid;
4564             _listCustom.AllowDrop = true;
4565
4566             _listCustom.SelectedIndexChanged += MyList_SelectedIndexChanged;
4567             _listCustom.MouseDoubleClick += MyList_MouseDoubleClick;
4568             _listCustom.ColumnClick += MyList_ColumnClick;
4569             _listCustom.DrawColumnHeader += MyList_DrawColumnHeader;
4570             _listCustom.DragDrop += TweenMain_DragDrop;
4571             _listCustom.DragOver += TweenMain_DragOver;
4572             _listCustom.DrawItem += MyList_DrawItem;
4573             _listCustom.MouseClick += MyList_MouseClick;
4574             _listCustom.ColumnReordered += MyList_ColumnReordered;
4575             _listCustom.ColumnWidthChanged += MyList_ColumnWidthChanged;
4576             _listCustom.CacheVirtualItems += MyList_CacheVirtualItems;
4577             _listCustom.RetrieveVirtualItem += MyList_RetrieveVirtualItem;
4578             _listCustom.DrawSubItem += MyList_DrawSubItem;
4579             _listCustom.HScrolled += MyList_HScrolled;
4580
4581             InitColumnText();
4582             _colHd1.Text = ColumnText[0];
4583             _colHd1.Width = 48;
4584             _colHd2.Text = ColumnText[1];
4585             _colHd2.Width = 80;
4586             _colHd3.Text = ColumnText[2];
4587             _colHd3.Width = 300;
4588             _colHd4.Text = ColumnText[3];
4589             _colHd4.Width = 50;
4590             _colHd5.Text = ColumnText[4];
4591             _colHd5.Width = 50;
4592             _colHd6.Text = ColumnText[5];
4593             _colHd6.Width = 16;
4594             _colHd7.Text = ColumnText[6];
4595             _colHd7.Width = 16;
4596             _colHd8.Text = ColumnText[7];
4597             _colHd8.Width = 50;
4598
4599             _listCustom.SmallImageList = new ImageList();
4600             if (_iconSz > 0)
4601             {
4602                 _listCustom.SmallImageList.ImageSize = new Size(_iconSz, _iconSz);
4603             }
4604             else
4605             {
4606                 _listCustom.SmallImageList.ImageSize = new Size(1, 1);
4607             }
4608
4609             int[] dispOrder = new int[8];
4610             if (!startup)
4611             {
4612                 for (int i = 0; i < _curList.Columns.Count; i++)
4613                 {
4614                     for (int j = 0; j < _curList.Columns.Count; j++)
4615                     {
4616                         if (_curList.Columns[j].DisplayIndex == i)
4617                         {
4618                             dispOrder[i] = j;
4619                             break;
4620                         }
4621                     }
4622                 }
4623                 for (int i = 0; i < _curList.Columns.Count; i++)
4624                 {
4625                     _listCustom.Columns[i].Width = _curList.Columns[i].Width;
4626                     _listCustom.Columns[dispOrder[i]].DisplayIndex = i;
4627                 }
4628             }
4629             else
4630             {
4631                 if (_iconCol)
4632                 {
4633                     _listCustom.Columns[0].Width = _cfgLocal.Width1;
4634                     _listCustom.Columns[1].Width = _cfgLocal.Width3;
4635                     _listCustom.Columns[0].DisplayIndex = 0;
4636                     _listCustom.Columns[1].DisplayIndex = 1;
4637                 }
4638                 else
4639                 {
4640                     for (int i = 0; i <= 7; i++)
4641                     {
4642                         if (_cfgLocal.DisplayIndex1 == i)
4643                             dispOrder[i] = 0;
4644                         else if (_cfgLocal.DisplayIndex2 == i)
4645                             dispOrder[i] = 1;
4646                         else if (_cfgLocal.DisplayIndex3 == i)
4647                             dispOrder[i] = 2;
4648                         else if (_cfgLocal.DisplayIndex4 == i)
4649                             dispOrder[i] = 3;
4650                         else if (_cfgLocal.DisplayIndex5 == i)
4651                             dispOrder[i] = 4;
4652                         else if (_cfgLocal.DisplayIndex6 == i)
4653                             dispOrder[i] = 5;
4654                         else if (_cfgLocal.DisplayIndex7 == i)
4655                             dispOrder[i] = 6;
4656                         else if (_cfgLocal.DisplayIndex8 == i)
4657                             dispOrder[i] = 7;
4658                     }
4659                     _listCustom.Columns[0].Width = _cfgLocal.Width1;
4660                     _listCustom.Columns[1].Width = _cfgLocal.Width2;
4661                     _listCustom.Columns[2].Width = _cfgLocal.Width3;
4662                     _listCustom.Columns[3].Width = _cfgLocal.Width4;
4663                     _listCustom.Columns[4].Width = _cfgLocal.Width5;
4664                     _listCustom.Columns[5].Width = _cfgLocal.Width6;
4665                     _listCustom.Columns[6].Width = _cfgLocal.Width7;
4666                     _listCustom.Columns[7].Width = _cfgLocal.Width8;
4667                     for (int i = 0; i <= 7; i++)
4668                     {
4669                         _listCustom.Columns[dispOrder[i]].DisplayIndex = i;
4670                     }
4671                 }
4672             }
4673
4674             if (tabType == MyCommon.TabUsageType.PublicSearch) pnl.ResumeLayout(false);
4675         
4676             _tabPage.ResumeLayout(false);
4677
4678             this.SplitContainer1.Panel1.ResumeLayout(false);
4679             this.SplitContainer1.Panel2.ResumeLayout(false);
4680             this.SplitContainer1.ResumeLayout(false);
4681             this.ListTab.ResumeLayout(false);
4682             this.ResumeLayout(false);
4683             this.PerformLayout();
4684             _tabPage.Tag = _listCustom;
4685             return true;
4686         }
4687
4688         public bool RemoveSpecifiedTab(string TabName, bool confirm)
4689         {
4690             int idx = 0;
4691             for (idx = 0; idx < ListTab.TabPages.Count; idx++)
4692             {
4693                 if (ListTab.TabPages[idx].Text == TabName) break;
4694             }
4695
4696             if (_statuses.IsDefaultTab(TabName) || _statuses.Tabs[TabName].Protected) return false;
4697
4698             if (confirm)
4699             {
4700                 string tmp = string.Format(Properties.Resources.RemoveSpecifiedTabText1, Environment.NewLine);
4701                 if (MessageBox.Show(tmp, TabName + " " + Properties.Resources.RemoveSpecifiedTabText2,
4702                                  MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Cancel)
4703                 {
4704                     return false;
4705                 }
4706             }
4707
4708             SetListProperty();   //他のタブに列幅等を反映
4709
4710             MyCommon.TabUsageType tabType = _statuses.Tabs[TabName].TabType;
4711
4712             //オブジェクトインスタンスの削除
4713             this.SplitContainer1.Panel1.SuspendLayout();
4714             this.SplitContainer1.Panel2.SuspendLayout();
4715             this.SplitContainer1.SuspendLayout();
4716             this.ListTab.SuspendLayout();
4717             this.SuspendLayout();
4718
4719             TabPage _tabPage = ListTab.TabPages[idx];
4720             DetailsListView _listCustom = (DetailsListView)_tabPage.Tag;
4721             _tabPage.Tag = null;
4722
4723             _tabPage.SuspendLayout();
4724
4725             if (this.ListTab.SelectedTab == this.ListTab.TabPages[idx])
4726             {
4727                 this.ListTab.SelectTab((this._beforeSelectedTab != null && this.ListTab.TabPages.Contains(this._beforeSelectedTab)) ? this._beforeSelectedTab : this.ListTab.TabPages[0]);
4728             }
4729             this.ListTab.Controls.Remove(_tabPage);
4730
4731             Control pnl = null;
4732             if (tabType == MyCommon.TabUsageType.PublicSearch)
4733             {
4734                 pnl = _tabPage.Controls["panelSearch"];
4735                 foreach (Control ctrl in pnl.Controls)
4736                 {
4737                     if (ctrl.Name == "buttonSearch")
4738                     {
4739                         ctrl.Click -= SearchButton_Click;
4740                     }
4741                     ctrl.Enter -= SearchControls_Enter;
4742                     ctrl.Leave -= SearchControls_Leave;
4743                     pnl.Controls.Remove(ctrl);
4744                     ctrl.Dispose();
4745                 }
4746                 _tabPage.Controls.Remove(pnl);
4747             }
4748
4749             _tabPage.Controls.Remove(_listCustom);
4750             _listCustom.Columns.Clear();
4751             _listCustom.ContextMenuStrip = null;
4752
4753             _listCustom.SelectedIndexChanged -= MyList_SelectedIndexChanged;
4754             _listCustom.MouseDoubleClick -= MyList_MouseDoubleClick;
4755             _listCustom.ColumnClick -= MyList_ColumnClick;
4756             _listCustom.DrawColumnHeader -= MyList_DrawColumnHeader;
4757             _listCustom.DragDrop -= TweenMain_DragDrop;
4758             _listCustom.DragOver -= TweenMain_DragOver;
4759             _listCustom.DrawItem -= MyList_DrawItem;
4760             _listCustom.MouseClick -= MyList_MouseClick;
4761             _listCustom.ColumnReordered -= MyList_ColumnReordered;
4762             _listCustom.ColumnWidthChanged -= MyList_ColumnWidthChanged;
4763             _listCustom.CacheVirtualItems -= MyList_CacheVirtualItems;
4764             _listCustom.RetrieveVirtualItem -= MyList_RetrieveVirtualItem;
4765             _listCustom.DrawSubItem -= MyList_DrawSubItem;
4766             _listCustom.HScrolled -= MyList_HScrolled;
4767
4768             _listCustom.SmallImageList = null;
4769             _listCustom.ListViewItemSorter = null;
4770
4771             //キャッシュのクリア
4772             if (_curTab.Equals(_tabPage))
4773             {
4774                 _curTab = null;
4775                 _curItemIndex = -1;
4776                 _curList = null;
4777                 _curPost = null;
4778             }
4779             _itemCache = null;
4780             _itemCacheIndex = -1;
4781             _postCache = null;
4782
4783             _tabPage.ResumeLayout(false);
4784
4785             this.SplitContainer1.Panel1.ResumeLayout(false);
4786             this.SplitContainer1.Panel2.ResumeLayout(false);
4787             this.SplitContainer1.ResumeLayout(false);
4788             this.ListTab.ResumeLayout(false);
4789             this.ResumeLayout(false);
4790             this.PerformLayout();
4791
4792             _tabPage.Dispose();
4793             _listCustom.Dispose();
4794             _statuses.RemoveTab(TabName);
4795
4796             foreach (TabPage tp in ListTab.TabPages)
4797             {
4798                 DetailsListView lst = (DetailsListView)tp.Tag;
4799                 if (lst.VirtualListSize != _statuses.Tabs[tp.Text].AllCount)
4800                 {
4801                     lst.VirtualListSize = _statuses.Tabs[tp.Text].AllCount;
4802                 }
4803             }
4804
4805             return true;
4806         }
4807
4808         private void ListTab_Deselected(object sender, TabControlEventArgs e)
4809         {
4810             _itemCache = null;
4811             _itemCacheIndex = -1;
4812             _postCache = null;
4813             _beforeSelectedTab = e.TabPage;
4814         }
4815
4816         private void ListTab_MouseMove(object sender, MouseEventArgs e)
4817         {
4818             //タブのD&D
4819
4820             if (!SettingDialog.TabMouseLock && e.Button == MouseButtons.Left && _tabDrag)
4821             {
4822                 string tn = "";
4823                 Rectangle dragEnableRectangle = new Rectangle((int)(_tabMouseDownPoint.X - (SystemInformation.DragSize.Width / 2)), (int)(_tabMouseDownPoint.Y - (SystemInformation.DragSize.Height / 2)), SystemInformation.DragSize.Width, SystemInformation.DragSize.Height);
4824                 if (!dragEnableRectangle.Contains(e.Location))
4825                 {
4826                     //タブが多段の場合にはMouseDownの前の段階で選択されたタブの段が変わっているので、このタイミングでカーソルの位置からタブを判定出来ない。
4827                     tn = ListTab.SelectedTab.Text;
4828                 }
4829
4830                 if (string.IsNullOrEmpty(tn)) return;
4831
4832                 foreach (TabPage tb in ListTab.TabPages)
4833                 {
4834                     if (tb.Text == tn)
4835                     {
4836                         ListTab.DoDragDrop(tb, DragDropEffects.All);
4837                         break;
4838                     }
4839                 }
4840             }
4841             else
4842             {
4843                 _tabDrag = false;
4844             }
4845
4846             Point cpos = new Point(e.X, e.Y);
4847             for (int i = 0; i < ListTab.TabPages.Count; i++)
4848             {
4849                 Rectangle rect = ListTab.GetTabRect(i);
4850                 if (rect.Left <= cpos.X & cpos.X <= rect.Right &
4851                    rect.Top <= cpos.Y & cpos.Y <= rect.Bottom)
4852                 {
4853                     _rclickTabName = ListTab.TabPages[i].Text;
4854                     break;
4855                 }
4856             }
4857         }
4858
4859         private void ListTab_SelectedIndexChanged(object sender, EventArgs e)
4860         {
4861             //_curList.Refresh();
4862             DispSelectedPost();
4863             SetMainWindowTitle();
4864             SetStatusLabelUrl();
4865             if (ListTab.Focused || ((Control)ListTab.SelectedTab.Tag).Focused) this.Tag = ListTab.Tag;
4866             TabMenuControl(ListTab.SelectedTab.Text);
4867             this.PushSelectPostChain();
4868         }
4869
4870         private void SetListProperty()
4871         {
4872             //削除などで見つからない場合は処理せず
4873             if (_curList == null) return;
4874             if (!_isColumnChanged) return;
4875
4876             int[] dispOrder = new int[_curList.Columns.Count];
4877             for (int i = 0; i < _curList.Columns.Count; i++)
4878             {
4879                 for (int j = 0; j < _curList.Columns.Count; j++)
4880                 {
4881                     if (_curList.Columns[j].DisplayIndex == i)
4882                     {
4883                         dispOrder[i] = j;
4884                         break;
4885                     }
4886                 }
4887             }
4888
4889             //列幅、列並びを他のタブに設定
4890             foreach (TabPage tb in ListTab.TabPages)
4891             {
4892                 if (!tb.Equals(_curTab))
4893                 {
4894                     if (tb.Tag != null && tb.Controls.Count > 0)
4895                     {
4896                         DetailsListView lst = (DetailsListView)tb.Tag;
4897                         for (int i = 0; i < lst.Columns.Count; i++)
4898                         {
4899                             lst.Columns[dispOrder[i]].DisplayIndex = i;
4900                             lst.Columns[i].Width = _curList.Columns[i].Width;
4901                         }
4902                     }
4903                 }
4904             }
4905
4906             _isColumnChanged = false;
4907         }
4908
4909         private void PostBrowser_StatusTextChanged(object sender, EventArgs e)
4910         {
4911             try
4912             {
4913                 if (PostBrowser.StatusText.StartsWith("http") || PostBrowser.StatusText.StartsWith("ftp")
4914                         || PostBrowser.StatusText.StartsWith("data"))
4915                 {
4916                     StatusLabelUrl.Text = PostBrowser.StatusText.Replace("&", "&&");
4917                 }
4918                 if (string.IsNullOrEmpty(PostBrowser.StatusText))
4919                 {
4920                     SetStatusLabelUrl();
4921                 }
4922             }
4923             catch (Exception)
4924             {
4925             }
4926         }
4927
4928         private void StatusText_KeyPress(object sender, KeyPressEventArgs e)
4929         {
4930             if (e.KeyChar == '@')
4931             {
4932                 if (!SettingDialog.UseAtIdSupplement) return;
4933                 //@マーク
4934                 int cnt = AtIdSupl.ItemCount;
4935                 ShowSuplDialog(StatusText, AtIdSupl);
4936                 if (cnt != AtIdSupl.ItemCount) _modifySettingAtId = true;
4937                 e.Handled = true;
4938             }
4939             else if (e.KeyChar == '#')
4940             {
4941                 if (!SettingDialog.UseHashSupplement) return;
4942                 ShowSuplDialog(StatusText, HashSupl);
4943                 e.Handled = true;
4944             }
4945         }
4946
4947         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog)
4948         {
4949             ShowSuplDialog(owner, dialog, 0, "");
4950         }
4951
4952         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset)
4953         {
4954             ShowSuplDialog(owner, dialog, offset, "");
4955         }
4956
4957         public void ShowSuplDialog(TextBox owner, AtIdSupplement dialog, int offset, string startswith)
4958         {
4959             dialog.StartsWith = startswith;
4960             if (dialog.Visible)
4961             {
4962                 dialog.Focus();
4963             }
4964             else
4965             {
4966                 dialog.ShowDialog();
4967             }
4968             this.TopMost = SettingDialog.AlwaysTop;
4969             int selStart = owner.SelectionStart;
4970             string fHalf = "";
4971             string eHalf = "";
4972             if (dialog.DialogResult == DialogResult.OK)
4973             {
4974                 if (!string.IsNullOrEmpty(dialog.inputText))
4975                 {
4976                     if (selStart > 0)
4977                     {
4978                         fHalf = owner.Text.Substring(0, selStart - offset);
4979                     }
4980                     if (selStart < owner.Text.Length)
4981                     {
4982                         eHalf = owner.Text.Substring(selStart);
4983                     }
4984                     owner.Text = fHalf + dialog.inputText + eHalf;
4985                     owner.SelectionStart = selStart + dialog.inputText.Length;
4986                 }
4987             }
4988             else
4989             {
4990                 if (selStart > 0)
4991                 {
4992                     fHalf = owner.Text.Substring(0, selStart);
4993                 }
4994                 if (selStart < owner.Text.Length)
4995                 {
4996                     eHalf = owner.Text.Substring(selStart);
4997                 }
4998                 owner.Text = fHalf + eHalf;
4999                 if (selStart > 0)
5000                 {
5001                     owner.SelectionStart = selStart;
5002                 }
5003             }
5004             owner.Focus();
5005         }
5006
5007         private void StatusText_KeyUp(object sender, KeyEventArgs e)
5008         {
5009             //スペースキーで未読ジャンプ
5010             if (!e.Alt && !e.Control && !e.Shift)
5011             {
5012                 if (e.KeyCode == Keys.Space || e.KeyCode == Keys.ProcessKey)
5013                 {
5014                     bool isSpace = false;
5015                     foreach (char c in StatusText.Text.ToCharArray())
5016                     {
5017                         if (c == ' ' || c == ' ')
5018                         {
5019                             isSpace = true;
5020                         }
5021                         else
5022                         {
5023                             isSpace = false;
5024                             break;
5025                         }
5026                     }
5027                     if (isSpace)
5028                     {
5029                         e.Handled = true;
5030                         StatusText.Text = "";
5031                         JumpUnreadMenuItem_Click(null, null);
5032                     }
5033                 }
5034             }
5035             this.StatusText_TextChanged(null, null);
5036         }
5037
5038         private void StatusText_TextChanged(object sender, EventArgs e)
5039         {
5040             //文字数カウント
5041             int pLen = GetRestStatusCount(true, false);
5042             lblLen.Text = pLen.ToString();
5043             if (pLen < 0)
5044             {
5045                 StatusText.ForeColor = Color.Red;
5046             }
5047             else
5048             {
5049                 StatusText.ForeColor = _clInputFont;
5050             }
5051             if (string.IsNullOrEmpty(StatusText.Text))
5052             {
5053                 _reply_to_id = 0;
5054                 _reply_to_name = "";
5055             }
5056         }
5057
5058         private int GetRestStatusCount(bool isAuto, bool isAddFooter)
5059         {
5060             //文字数カウント
5061             int pLen = 140 - StatusText.Text.Length;
5062             if (this.NotifyIcon1 == null || !this.NotifyIcon1.Visible) return pLen;
5063             if ((isAuto && !MyCommon.IsKeyDown(Keys.Control) && SettingDialog.PostShiftEnter) ||
5064                 (isAuto && !MyCommon.IsKeyDown(Keys.Shift) && !SettingDialog.PostShiftEnter) ||
5065                 (!isAuto && isAddFooter))
5066             {
5067                 if (SettingDialog.UseRecommendStatus)
5068                     pLen -= SettingDialog.RecommendStatusText.Length;
5069                 else if (SettingDialog.Status.Length > 0)
5070                     pLen -= SettingDialog.Status.Length + 1;
5071             }
5072             if (!string.IsNullOrEmpty(HashMgr.UseHash))
5073             {
5074                 pLen -= HashMgr.UseHash.Length + 1;
5075             }
5076             //foreach (Match m in Regex.Matches(StatusText.Text, "https?:\/\/[-_.!~*//()a-zA-Z0-9;\/?:\@&=+\$,%#^]+"))
5077             //{
5078             //    pLen += m.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5079             //}
5080             foreach (Match m in Regex.Matches(StatusText.Text, Twitter.rgUrl, RegexOptions.IgnoreCase))
5081             {
5082                 string before = m.Result("${before}");
5083                 string url = m.Result("${url}");
5084                 string protocol = m.Result("${protocol}");
5085                 string domain = m.Result("${domain}");
5086                 string path = m.Result("${path}");
5087                 if (protocol.Length == 0)
5088                 {
5089                     if (Regex.IsMatch(before, Twitter.url_invalid_without_protocol_preceding_chars))
5090                     {
5091                         continue;
5092                     }
5093
5094                     bool last_url_invalid_match = false;
5095                     string lasturl = null;
5096                     foreach (Match mm in Regex.Matches(domain, Twitter.url_valid_ascii_domain, RegexOptions.IgnoreCase))
5097                     {
5098                         lasturl = mm.ToString();
5099                         last_url_invalid_match = Regex.IsMatch(lasturl, Twitter.url_invalid_short_domain, RegexOptions.IgnoreCase);
5100                         if (!last_url_invalid_match)
5101                         {
5102                             pLen += lasturl.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5103                         }
5104                     }
5105
5106                     if (path.Length != 0)
5107                     {
5108                         if (last_url_invalid_match)
5109                         {
5110                             pLen += lasturl.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5111                         }
5112                         pLen += path.Length;
5113                     }
5114                 }
5115                 else
5116                 {
5117                     pLen += url.Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5118                 }
5119                 
5120                 //if (m.Result("${url}").Length > SettingDialog.TwitterConfiguration.ShortUrlLength)
5121                 //{
5122                 //    pLen += m.Result("${url}").Length - SettingDialog.TwitterConfiguration.ShortUrlLength;
5123                 //}
5124             }
5125             if (ImageSelectionPanel.Visible && ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
5126             {
5127                 pLen -= SettingDialog.TwitterConfiguration.CharactersReservedPerMedia;
5128             }
5129             return pLen;
5130         }
5131
5132         private void MyList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
5133         {
5134             if (_itemCache != null &&
5135                e.StartIndex >= _itemCacheIndex &&
5136                e.EndIndex < _itemCacheIndex + _itemCache.Length &&
5137                _curList.Equals(sender))
5138             {
5139                 //If the newly requested cache is a subset of the old cache, 
5140                 //no need to rebuild everything, so do nothing.
5141                 return;
5142             }
5143
5144             //Now we need to rebuild the cache.
5145             if (_curList.Equals(sender)) CreateCache(e.StartIndex, e.EndIndex);
5146         }
5147
5148         private void MyList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
5149         {
5150             if (_itemCache != null && e.ItemIndex >= _itemCacheIndex && e.ItemIndex < _itemCacheIndex + _itemCache.Length && _curList.Equals(sender))
5151             {
5152                 //A cache hit, so get the ListViewItem from the cache instead of making a new one.
5153                 e.Item = _itemCache[e.ItemIndex - _itemCacheIndex];
5154             }
5155             else
5156             {
5157                 //A cache miss, so create a new ListViewItem and pass it back.
5158                 TabPage tb = (TabPage)((DetailsListView)sender).Parent;
5159                 try
5160                 {
5161                     e.Item = CreateItem(tb,
5162                                         _statuses[tb.Text, e.ItemIndex],
5163                                         e.ItemIndex);
5164                 }
5165                 catch (Exception)
5166                 {
5167                     //不正な要求に対する間に合わせの応答
5168                     string[] sitem = {"", "", "", "", "", "", "", ""};
5169                     e.Item = new ImageListViewItem(sitem, "");
5170                 }
5171             }
5172         }
5173
5174         private void CreateCache(int StartIndex, int EndIndex)
5175         {
5176             try
5177             {
5178                 //キャッシュ要求(要求範囲±30を作成)
5179                 StartIndex -= 30;
5180                 if (StartIndex < 0) StartIndex = 0;
5181                 EndIndex += 30;
5182                 if (EndIndex >= _statuses.Tabs[_curTab.Text].AllCount) EndIndex = _statuses.Tabs[_curTab.Text].AllCount - 1;
5183                 _postCache = _statuses[_curTab.Text, StartIndex, EndIndex]; //配列で取得
5184                 _itemCacheIndex = StartIndex;
5185
5186                 _itemCache = new ListViewItem[0] {};
5187                 Array.Resize(ref _itemCache, _postCache.Length);
5188
5189                 for (int i = 0; i < _postCache.Length; i++)
5190                 {
5191                     _itemCache[i] = CreateItem(_curTab, _postCache[i], StartIndex + i);
5192                 }
5193             }
5194             catch (Exception)
5195             {
5196                 //キャッシュ要求が実データとずれるため(イベントの遅延?)
5197                 _postCache = null;
5198                 _itemCache = null;
5199             }
5200         }
5201
5202         private ListViewItem CreateItem(TabPage Tab, PostClass Post, int Index)
5203         {
5204             StringBuilder mk = new StringBuilder();
5205             //if (Post.IsDeleted) mk.Append("×");
5206             //if (Post.IsMark) mk.Append("♪");
5207             //if (Post.IsProtect) mk.Append("Ю");
5208             //if (Post.InReplyToStatusId > 0) mk.Append("⇒");
5209             if (Post.FavoritedCount > 0) mk.Append("+" + Post.FavoritedCount.ToString());
5210             ImageListViewItem itm;
5211             if (Post.RetweetedId == 0)
5212             {
5213                 string[] sitem= {"",
5214                                  Post.Nickname,
5215                                  Post.IsDeleted ? "(DELETED)" : Post.TextSingleLine,
5216                                  Post.CreatedAt.ToString(SettingDialog.DateTimeFormat),
5217                                  Post.ScreenName,
5218                                  "",
5219                                  mk.ToString(),
5220                                  Post.Source};
5221                 itm = new ImageListViewItem(sitem, (ImageDictionary)this.TIconDic, Post.ImageUrl);
5222             }
5223             else
5224             {
5225                 string[] sitem = {"",
5226                                   Post.Nickname,
5227                                   Post.IsDeleted ? "(DELETED)" : Post.TextSingleLine,
5228                                   Post.CreatedAt.ToString(SettingDialog.DateTimeFormat),
5229                                   Post.ScreenName + Environment.NewLine + "(RT:" + Post.RetweetedBy + ")",
5230                                   "",
5231                                   mk.ToString(),
5232                                   Post.Source};
5233                 itm = new ImageListViewItem(sitem, (ImageDictionary)this.TIconDic, Post.ImageUrl);
5234             }
5235             itm.StateImageIndex = Post.StateIndex;
5236
5237             bool read = Post.IsRead;
5238             //未読管理していなかったら既読として扱う
5239             if (!_statuses.Tabs[Tab.Text].UnreadManage || !SettingDialog.UnreadManage) read = true;
5240             ChangeItemStyleRead(read, itm, Post, null);
5241             if (Tab.Equals(_curTab)) ColorizeList(itm, Index);
5242             return itm;
5243         }
5244
5245         private void MyList_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
5246         {
5247             e.DrawDefault = true;
5248         }
5249
5250         private void MyList_HScrolled(object sender, EventArgs e)
5251         {
5252             DetailsListView listView = (DetailsListView)sender;
5253             listView.Refresh();
5254         }
5255
5256         private void MyList_DrawItem(object sender, DrawListViewItemEventArgs e)
5257         {
5258             if (e.State == 0) return;
5259             e.DrawDefault = false;
5260             if (!e.Item.Selected)     //e.ItemStateでうまく判定できない???
5261             {
5262                 SolidBrush brs2 = null;
5263
5264                 if (e.Item.BackColor == _clSelf)
5265                     brs2 = _brsBackColorMine;
5266                 else if (e.Item.BackColor == _clAtSelf)
5267                     brs2 = _brsBackColorAt;
5268                 else if (e.Item.BackColor == _clTarget)
5269                     brs2 = _brsBackColorYou;
5270                 else if (e.Item.BackColor == _clAtTarget)
5271                     brs2 = _brsBackColorAtYou;
5272                 else if (e.Item.BackColor == _clAtFromTarget)
5273                     brs2 = _brsBackColorAtFromTarget;
5274                 else if (e.Item.BackColor == _clAtTo)
5275                     brs2 = _brsBackColorAtTo;
5276                 else
5277                     brs2 = _brsBackColorNone;
5278
5279                 e.Graphics.FillRectangle(brs2, e.Bounds);
5280             }
5281             else
5282             {
5283                 //選択中の行
5284                 if (((Control)sender).Focused)
5285                     e.Graphics.FillRectangle(_brsHighLight, e.Bounds);
5286                 else
5287                     e.Graphics.FillRectangle(_brsDeactiveSelection, e.Bounds);
5288             }
5289             if ((e.State & ListViewItemStates.Focused) == ListViewItemStates.Focused) e.DrawFocusRectangle();
5290             this.DrawListViewItemIcon(e);
5291         }
5292
5293         private void MyList_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
5294         {
5295             if (e.ItemState == 0) return;
5296
5297             if (e.ColumnIndex > 0)
5298             {
5299                 //アイコン以外の列
5300                 RectangleF rct = e.Bounds;
5301                 RectangleF rctB = e.Bounds;
5302                 rct.Width = e.Header.Width;
5303                 rctB.Width = e.Header.Width;
5304                 if (_iconCol)
5305                 {
5306                     rct.Y += e.Item.Font.Height;
5307                     rct.Height -= e.Item.Font.Height;
5308                     rctB.Height = e.Item.Font.Height;
5309                 }
5310
5311
5312                 int heightDiff;
5313                 int drawLineCount = Math.Max(1, Math.DivRem((int)rct.Height, e.Item.Font.Height, out heightDiff));
5314
5315                 //if (heightDiff > e.Item.Font.Height * 0.7)
5316                 //{
5317                 //    rct.Height += e.Item.Font.Height;
5318                 //    drawLineCount += 1;
5319                 //}
5320
5321                 //フォントの高さの半分を足してるのは保険。無くてもいいかも。
5322                 if (!_iconCol && drawLineCount <= 1)
5323                 {
5324                     //rct.Inflate(0, heightDiff / -2);
5325                     //rct.Height += e.Item.Font.Height / 2;
5326                 }
5327                 else if (heightDiff < e.Item.Font.Height * 0.7)
5328                 {
5329                     //最終行が70%以上欠けていたら、最終行は表示しない
5330                     //rct.Height = (float)((e.Item.Font.Height * drawLineCount) + (e.Item.Font.Height / 2));
5331                     rct.Height = (e.Item.Font.Height * drawLineCount) - 1;
5332                 }
5333                 else
5334                 {
5335                     drawLineCount += 1;
5336                 }
5337
5338                 //if (!_iconCol && drawLineCount > 1)
5339                 //{
5340                 //    rct.Y += e.Item.Font.Height * 0.2;
5341                 //    if (heightDiff >= e.Item.Font.Height * 0.8) rct.Height -= e.Item.Font.Height * 0.2;
5342                 //}
5343                 if (!e.Item.Selected)     //e.ItemStateでうまく判定できない???
5344                 {
5345                     //選択されていない行
5346                     //文字色
5347                     SolidBrush brs = null;
5348                     bool flg = false;
5349
5350                     if (e.Item.ForeColor == _clUnread)
5351                     {
5352                         brs = _brsForeColorUnread;
5353                     }
5354                     else if (e.Item.ForeColor == _clReaded)
5355                     {
5356                         brs = _brsForeColorReaded;
5357                     }
5358                     else if (e.Item.ForeColor == _clFav)
5359                     {
5360                         brs = _brsForeColorFav;
5361                     }
5362                     else if (e.Item.ForeColor == _clOWL)
5363                     {
5364                         brs = _brsForeColorOWL;
5365                     }
5366                     else if (e.Item.ForeColor == _clRetweet)
5367                     {
5368                         brs = _brsForeColorRetweet;
5369                     }
5370                     else
5371                     {
5372                         brs = new SolidBrush(e.Item.ForeColor);
5373                         flg = true;
5374                     }
5375
5376                     if (rct.Width > 0)
5377                     {
5378                         if (_iconCol)
5379                         {
5380                             using (Font fnt = new Font(e.Item.Font, FontStyle.Bold))
5381                             {
5382                                 //e.Graphics.DrawString(System.Environment.NewLine + e.Item.SubItems[2].Text, e.Item.Font, brs, rct, sf);
5383                                 //e.Graphics.DrawString(e.Item.SubItems[4].Text + " / " + e.Item.SubItems[1].Text + " (" + e.Item.SubItems[3].Text + ") " + e.Item.SubItems[5].Text + e.Item.SubItems[6].Text + " [" + e.Item.SubItems[7].Text + "]", fnt, brs, rctB, sf);
5384                                 TextRenderer.DrawText(e.Graphics,
5385                                                       e.Item.SubItems[2].Text,
5386                                                       e.Item.Font,
5387                                                       Rectangle.Round(rct),
5388                                                       brs.Color,
5389                                                       TextFormatFlags.WordBreak |
5390                                                       TextFormatFlags.EndEllipsis |
5391                                                       TextFormatFlags.GlyphOverhangPadding |
5392                                                       TextFormatFlags.NoPrefix);
5393                                 TextRenderer.DrawText(e.Graphics,
5394                                                       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 + "]",
5395                                                       fnt,
5396                                                       Rectangle.Round(rctB),
5397                                                       brs.Color,
5398                                                       TextFormatFlags.SingleLine |
5399                                                       TextFormatFlags.EndEllipsis |
5400                                                       TextFormatFlags.GlyphOverhangPadding |
5401                                                       TextFormatFlags.NoPrefix);
5402                             }
5403                         }
5404                         else if (drawLineCount == 1)
5405                         {
5406                             TextRenderer.DrawText(e.Graphics,
5407                                                   e.SubItem.Text,
5408                                                   e.Item.Font,
5409                                                   Rectangle.Round(rct),
5410                                                   brs.Color,
5411                                                   TextFormatFlags.SingleLine |
5412                                                   TextFormatFlags.EndEllipsis |
5413                                                   TextFormatFlags.GlyphOverhangPadding |
5414                                                   TextFormatFlags.NoPrefix |
5415                                                   TextFormatFlags.VerticalCenter);
5416                         }
5417                         else
5418                         {
5419                             //e.Graphics.DrawString(e.SubItem.Text, e.Item.Font, brs, rct, sf);
5420                             TextRenderer.DrawText(e.Graphics,
5421                                                   e.SubItem.Text,
5422                                                   e.Item.Font,
5423                                                   Rectangle.Round(rct),
5424                                                   brs.Color,
5425                                                   TextFormatFlags.WordBreak |
5426                                                   TextFormatFlags.EndEllipsis |
5427                                                   TextFormatFlags.GlyphOverhangPadding |
5428                                                   TextFormatFlags.NoPrefix);
5429                         }
5430                     }
5431                     if (flg) brs.Dispose();
5432                 }
5433                 else
5434                 {
5435                     if (rct.Width > 0)
5436                     {
5437                         //選択中の行
5438                         using (Font fnt = new Font(e.Item.Font, FontStyle.Bold))
5439                         {
5440                             if (((Control)sender).Focused)
5441                             {
5442                                 if (_iconCol)
5443                                 {
5444                                     //e.Graphics.DrawString(System.Environment.NewLine + e.Item.SubItems[2].Text, e.Item.Font, _brsHighLightText, rct, sf);
5445                                     //e.Graphics.DrawString(e.Item.SubItems[4].Text + " / " + e.Item.SubItems[1].Text + " (" + e.Item.SubItems[3].Text + ") " + e.Item.SubItems[5].Text + e.Item.SubItems[6].Text + " [" + e.Item.SubItems[7].Text + "]", fnt, _brsHighLightText, rctB, sf);
5446                                     TextRenderer.DrawText(e.Graphics,
5447                                                           e.Item.SubItems[2].Text,
5448                                                           e.Item.Font,
5449                                                           Rectangle.Round(rct),
5450                                                           _brsHighLightText.Color,
5451                                                           TextFormatFlags.WordBreak |
5452                                                           TextFormatFlags.EndEllipsis |
5453                                                           TextFormatFlags.GlyphOverhangPadding |
5454                                                           TextFormatFlags.NoPrefix);
5455                                     TextRenderer.DrawText(e.Graphics,
5456                                                           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 + "]",
5457                                                           fnt,
5458                                                           Rectangle.Round(rctB),
5459                                                           _brsHighLightText.Color,
5460                                                           TextFormatFlags.SingleLine |
5461                                                           TextFormatFlags.EndEllipsis |
5462                                                           TextFormatFlags.GlyphOverhangPadding |
5463                                                           TextFormatFlags.NoPrefix);
5464                                 }
5465                                 else if (drawLineCount == 1)
5466                                 {
5467                                     TextRenderer.DrawText(e.Graphics,
5468                                                           e.SubItem.Text,
5469                                                           e.Item.Font,
5470                                                           Rectangle.Round(rct),
5471                                                           _brsHighLightText.Color,
5472                                                           TextFormatFlags.SingleLine |
5473                                                           TextFormatFlags.EndEllipsis |
5474                                                           TextFormatFlags.GlyphOverhangPadding |
5475                                                           TextFormatFlags.NoPrefix |
5476                                                           TextFormatFlags.VerticalCenter);
5477                                 }
5478                                 else
5479                                 {
5480                                     //e.Graphics.DrawString(e.SubItem.Text, e.Item.Font, _brsHighLightText, rct, sf);
5481                                     TextRenderer.DrawText(e.Graphics,
5482                                                           e.SubItem.Text,
5483                                                           e.Item.Font,
5484                                                           Rectangle.Round(rct),
5485                                                           _brsHighLightText.Color,
5486                                                           TextFormatFlags.WordBreak |
5487                                                           TextFormatFlags.EndEllipsis |
5488                                                           TextFormatFlags.GlyphOverhangPadding |
5489                                                           TextFormatFlags.NoPrefix);
5490                                 }
5491                             }
5492                             else
5493                             {
5494                                 if (_iconCol)
5495                                 {
5496                                     //e.Graphics.DrawString(System.Environment.NewLine + e.Item.SubItems[2].Text, e.Item.Font, _brsForeColorUnread, rct, sf);
5497                                     //e.Graphics.DrawString(e.Item.SubItems[4].Text + " / " + e.Item.SubItems[1].Text + " (" + e.Item.SubItems[3].Text + ") " + e.Item.SubItems[5].Text + e.Item.SubItems[6].Text + " [" + e.Item.SubItems[7].Text + "]", fnt, _brsForeColorUnread, rctB, sf);
5498                                     TextRenderer.DrawText(e.Graphics,
5499                                                           e.Item.SubItems[2].Text,
5500                                                           e.Item.Font,
5501                                                           Rectangle.Round(rct),
5502                                                           _brsForeColorUnread.Color,
5503                                                           TextFormatFlags.WordBreak |
5504                                                           TextFormatFlags.EndEllipsis |
5505                                                           TextFormatFlags.GlyphOverhangPadding |
5506                                                           TextFormatFlags.NoPrefix);
5507                                     TextRenderer.DrawText(e.Graphics,
5508                                                           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 + "]",
5509                                                           fnt,
5510                                                           Rectangle.Round(rctB),
5511                                                           _brsForeColorUnread.Color,
5512                                                           TextFormatFlags.SingleLine |
5513                                                           TextFormatFlags.EndEllipsis |
5514                                                           TextFormatFlags.GlyphOverhangPadding |
5515                                                           TextFormatFlags.NoPrefix);
5516                                 }
5517                                 else if (drawLineCount == 1)
5518                                 {
5519                                     TextRenderer.DrawText(e.Graphics,
5520                                                           e.SubItem.Text,
5521                                                           e.Item.Font,
5522                                                           Rectangle.Round(rct),
5523                                                           _brsForeColorUnread.Color,
5524                                                           TextFormatFlags.SingleLine |
5525                                                           TextFormatFlags.EndEllipsis |
5526                                                           TextFormatFlags.GlyphOverhangPadding |
5527                                                           TextFormatFlags.NoPrefix |
5528                                                           TextFormatFlags.VerticalCenter);
5529                                 }
5530                                 else
5531                                 {
5532                                     //e.Graphics.DrawString(e.SubItem.Text, e.Item.Font, _brsForeColorUnread, rct, sf);
5533                                     TextRenderer.DrawText(e.Graphics,
5534                                                           e.SubItem.Text,
5535                                                           e.Item.Font,
5536                                                           Rectangle.Round(rct),
5537                                                           _brsForeColorUnread.Color,
5538                                                           TextFormatFlags.WordBreak |
5539                                                           TextFormatFlags.EndEllipsis |
5540                                                           TextFormatFlags.GlyphOverhangPadding |
5541                                                           TextFormatFlags.NoPrefix);
5542                                 }
5543                             }
5544                         }
5545                     }
5546                 }
5547                 //if (e.ColumnIndex == 6) this.DrawListViewItemStateIcon(e, rct);
5548             }
5549         }
5550
5551         private void DrawListViewItemIcon(DrawListViewItemEventArgs e)
5552         {
5553             ImageListViewItem item = (ImageListViewItem)e.Item;
5554             Rectangle stateRect;
5555
5556             //e.Bounds.Leftが常に0を指すから自前で計算
5557             Rectangle itemRect = item.Bounds;
5558             itemRect.Width = e.Item.ListView.Columns[0].Width;
5559
5560             foreach (ColumnHeader clm in e.Item.ListView.Columns)
5561             {
5562                 if (clm.DisplayIndex < e.Item.ListView.Columns[0].DisplayIndex)
5563                     itemRect.X += clm.Width;
5564             }
5565
5566             Rectangle iconRect;
5567             if (item.Image != null)
5568             {
5569                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(_iconSz, _iconSz)), itemRect);
5570                 iconRect.Offset(0, Math.Max(0, (itemRect.Height - _iconSz) / 2));
5571                 stateRect = Rectangle.Intersect(new Rectangle(iconRect.Location.X + _iconSz + 2, iconRect.Location.Y, 18, 16), itemRect);
5572             }
5573             else
5574             {
5575                 iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(1, 1)), itemRect);
5576                 //iconRect.Offset(0, Math.Max(0, (itemRect.Height - _iconSz) / 2));
5577                 stateRect = Rectangle.Intersect(new Rectangle(iconRect.Location.X + _iconSz + 2, iconRect.Location.Y, 18, 16), itemRect);
5578             }
5579
5580             if (item.Image != null && iconRect.Width > 0)
5581             {
5582                 e.Graphics.FillRectangle(Brushes.White, iconRect);
5583                 e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
5584                 try
5585                 {
5586                     e.Graphics.DrawImage(item.Image, iconRect);
5587                 }
5588                 catch (ArgumentException)
5589                 {
5590                     item.RegetImage();
5591                 }
5592             }
5593
5594             if (item.StateImageIndex > -1)
5595             {
5596                 if (stateRect.Width > 0)
5597                 {
5598                     //e.Graphics.FillRectangle(Brushes.White, stateRect);
5599                     //e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High;
5600                     e.Graphics.DrawImage(this.PostStateImageList.Images[item.StateImageIndex], stateRect);
5601                 }
5602             }
5603         }
5604
5605         //private void DrawListViewItemStateIcon(DrawListViewSubItemEventArgs e, RectangleF rct)
5606         //{
5607         //    ImageListViewItem item = (ImageListViewItem)e.Item;
5608         //    if (item.StateImageIndex > -1)
5609         //    {
5610         //        ////e.Bounds.Leftが常に0を指すから自前で計算
5611         //        //Rectangle itemRect = item.Bounds;
5612         //        //itemRect.Width = e.Item.ListView.Columns[4].Width;
5613
5614         //        //foreach (ColumnHeader clm in e.Item.ListView.Columns)
5615         //        //{
5616         //        //    if (clm.DisplayIndex < e.Item.ListView.Columns[4].DisplayIndex)
5617         //        //    {
5618         //        //        itemRect.X += clm.Width;
5619         //        //    }
5620         //        //}
5621
5622         //        //Rectangle iconRect = Rectangle.Intersect(new Rectangle(e.Item.GetBounds(ItemBoundsPortion.Icon).Location, new Size(_iconSz, _iconSz)), itemRect);
5623         //        //iconRect.Offset(0, Math.Max(0, (itemRect.Height - _iconSz) / 2));
5624
5625         //        if (rct.Width > 0)
5626         //        {
5627         //            RectangleF stateRect = RectangleF.Intersect(rct, new RectangleF(rct.Location, new Size(18, 16)));
5628         //            //e.Graphics.FillRectangle(Brushes.White, rct);
5629         //            //e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.High;
5630         //            e.Graphics.DrawImage(this.PostStateImageList.Images(item.StateImageIndex), stateRect);
5631         //        }
5632         //    }
5633         //}
5634
5635         private void DoTabSearch(string _word,
5636                                  bool CaseSensitive,
5637                                  bool UseRegex,
5638                                  SEARCHTYPE SType)
5639         {
5640             int cidx = 0;
5641             bool fnd = false;
5642             int toIdx;
5643             int stp = 1;
5644
5645             if (_curList.VirtualListSize == 0)
5646             {
5647                 MessageBox.Show(Properties.Resources.DoTabSearchText2, Properties.Resources.DoTabSearchText3, MessageBoxButtons.OK, MessageBoxIcon.Information);
5648             }
5649
5650             if (_curList.SelectedIndices.Count > 0)
5651             {
5652                 cidx = _curList.SelectedIndices[0];
5653             }
5654             toIdx = _curList.VirtualListSize;
5655
5656             switch (SType)
5657             {
5658                 case SEARCHTYPE.DialogSearch:    //ダイアログからの検索
5659                     if (_curList.SelectedIndices.Count > 0)
5660                         cidx = _curList.SelectedIndices[0];
5661                     else
5662                         cidx = 0;
5663                     break;
5664                 case SEARCHTYPE.NextSearch:      //次を検索
5665                     if (_curList.SelectedIndices.Count > 0)
5666                     {
5667                         cidx = _curList.SelectedIndices[0] + 1;
5668                         if (cidx > toIdx) cidx = toIdx;
5669                     }
5670                     else
5671                     {
5672                         cidx = 0;
5673                     }
5674                     break;
5675                 case SEARCHTYPE.PrevSearch:      //前を検索
5676                     if (_curList.SelectedIndices.Count > 0)
5677                     {
5678                         cidx = _curList.SelectedIndices[0] - 1;
5679                         if (cidx < 0) cidx = 0;
5680                     }
5681                     else
5682                     {
5683                         cidx = toIdx;
5684                     }
5685                     toIdx = -1;
5686                     stp = -1;
5687                     break;
5688             }
5689
5690             RegexOptions regOpt = RegexOptions.None;
5691             StringComparison fndOpt = StringComparison.Ordinal;
5692             if (!CaseSensitive)
5693             {
5694                 regOpt = RegexOptions.IgnoreCase;
5695                 fndOpt = StringComparison.OrdinalIgnoreCase;
5696             }
5697             try
5698             {
5699     RETRY:
5700                 if (UseRegex)
5701                 {
5702                     // 正規表現検索
5703                     Regex _search;
5704                     try
5705                     {
5706                         _search = new Regex(_word, regOpt);
5707                         for (int idx = cidx; idx != toIdx; idx += stp)
5708                         {
5709                             PostClass post;
5710                             try
5711                             {
5712                                 post = _statuses[_curTab.Text, idx];
5713                             }
5714                             catch (Exception)
5715                             {
5716                                 continue;
5717                             }
5718                             if (_search.IsMatch(post.Nickname)
5719                                 || _search.IsMatch(post.TextFromApi)
5720                                 || _search.IsMatch(post.ScreenName))
5721                             {
5722                                 SelectListItem(_curList, idx);
5723                                 _curList.EnsureVisible(idx);
5724                                 return;
5725                             }
5726                         }
5727                     }
5728                     catch (ArgumentException)
5729                     {
5730                         MessageBox.Show(Properties.Resources.DoTabSearchText1, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
5731                         return;
5732                     }
5733                 }
5734                 else
5735                 {
5736                     // 通常検索
5737                     for (int idx = cidx; idx != toIdx; idx += stp)
5738                     {
5739                         PostClass post;
5740                         try
5741                         {
5742                             post = _statuses[_curTab.Text, idx];
5743                         }
5744                         catch (Exception)
5745                         {
5746                             continue;
5747                         }
5748                         if (post.Nickname.IndexOf(_word, fndOpt) > -1
5749                             || post.TextFromApi.IndexOf(_word, fndOpt) > -1
5750                             || post.ScreenName.IndexOf(_word, fndOpt) > -1)
5751                         {
5752                             SelectListItem(_curList, idx);
5753                             _curList.EnsureVisible(idx);
5754                             return;
5755                         }
5756                     }
5757                 }
5758
5759                 if (!fnd)
5760                 {
5761                     switch (SType)
5762                     {
5763                         case SEARCHTYPE.DialogSearch:
5764                         case SEARCHTYPE.NextSearch:
5765                             toIdx = cidx;
5766                             cidx = 0;
5767                             break;
5768                         case SEARCHTYPE.PrevSearch:
5769                             toIdx = cidx;
5770                             cidx = _curList.Items.Count - 1;
5771                             break;
5772                     }
5773                     fnd = true;
5774                     goto RETRY;
5775                 }
5776             }
5777             catch (ArgumentOutOfRangeException)
5778             {
5779             }
5780             MessageBox.Show(Properties.Resources.DoTabSearchText2, Properties.Resources.DoTabSearchText3, MessageBoxButtons.OK, MessageBoxIcon.Information);
5781         }
5782
5783         private void MenuItemSubSearch_Click(object sender, EventArgs e)
5784         {
5785             //検索メニュー
5786             SearchDialog.Owner = this;
5787             if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5788             {
5789                 this.TopMost = SettingDialog.AlwaysTop;
5790                 return;
5791             }
5792             this.TopMost = SettingDialog.AlwaysTop;
5793
5794             if (!string.IsNullOrEmpty(SearchDialog.SWord))
5795             {
5796                 DoTabSearch(SearchDialog.SWord,
5797                             SearchDialog.CheckCaseSensitive,
5798                             SearchDialog.CheckRegex,
5799                             SEARCHTYPE.DialogSearch);
5800             }
5801         }
5802
5803         private void MenuItemSearchNext_Click(object sender, EventArgs e)
5804         {
5805             //次を検索
5806             if (string.IsNullOrEmpty(SearchDialog.SWord))
5807             {
5808                 if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5809                 {
5810                     this.TopMost = SettingDialog.AlwaysTop;
5811                     return;
5812                 }
5813                 this.TopMost = SettingDialog.AlwaysTop;
5814                 if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
5815
5816                 DoTabSearch(SearchDialog.SWord,
5817                             SearchDialog.CheckCaseSensitive,
5818                             SearchDialog.CheckRegex,
5819                             SEARCHTYPE.DialogSearch);
5820             }
5821             else
5822             {
5823                 DoTabSearch(SearchDialog.SWord,
5824                             SearchDialog.CheckCaseSensitive,
5825                             SearchDialog.CheckRegex,
5826                             SEARCHTYPE.NextSearch);
5827             }
5828         }
5829
5830         private void MenuItemSearchPrev_Click(object sender, EventArgs e)
5831         {
5832             //前を検索
5833             if (string.IsNullOrEmpty(SearchDialog.SWord))
5834             {
5835                 if (SearchDialog.ShowDialog() == DialogResult.Cancel)
5836                 {
5837                     this.TopMost = SettingDialog.AlwaysTop;
5838                     return;
5839                 }
5840                 this.TopMost = SettingDialog.AlwaysTop;
5841                 if (string.IsNullOrEmpty(SearchDialog.SWord)) return;
5842             }
5843
5844             DoTabSearch(SearchDialog.SWord,
5845                         SearchDialog.CheckCaseSensitive,
5846                         SearchDialog.CheckRegex,
5847                         SEARCHTYPE.PrevSearch);
5848         }
5849
5850         private void AboutMenuItem_Click(object sender, EventArgs e)
5851         {
5852             using (TweenAboutBox about = new TweenAboutBox())
5853             {
5854                 about.ShowDialog(this);
5855             }
5856             this.TopMost = SettingDialog.AlwaysTop;
5857         }
5858
5859         private void JumpUnreadMenuItem_Click(object sender, EventArgs e)
5860         {
5861             int bgnIdx = ListTab.TabPages.IndexOf(_curTab);
5862             int idx = -1;
5863             DetailsListView lst = null;
5864
5865             if (ImageSelectionPanel.Enabled)
5866                 return;
5867
5868             //現在タブから最終タブまで探索
5869             for (int i = bgnIdx; i < ListTab.TabPages.Count; i++)
5870             {
5871                 //未読Index取得
5872                 idx = _statuses.GetOldestUnreadIndex(ListTab.TabPages[i].Text);
5873                 if (idx > -1)
5874                 {
5875                     ListTab.SelectedIndex = i;
5876                     lst = (DetailsListView)ListTab.TabPages[i].Tag;
5877                     //_curTab = ListTab.TabPages[i];
5878                     break;
5879                 }
5880             }
5881
5882             //未読みつからず&現在タブが先頭ではなかったら、先頭タブから現在タブの手前まで探索
5883             if (idx == -1 && bgnIdx > 0)
5884             {
5885                 for (int i = 0; i < bgnIdx; i++)
5886                 {
5887                     idx = _statuses.GetOldestUnreadIndex(ListTab.TabPages[i].Text);
5888                     if (idx > -1)
5889                     {
5890                         ListTab.SelectedIndex = i;
5891                         lst = (DetailsListView)ListTab.TabPages[i].Tag;
5892                         //_curTab = ListTab.TabPages[i];
5893                         break;
5894                     }
5895                 }
5896             }
5897
5898             //全部調べたが未読見つからず→先頭タブの最新発言へ
5899             if (idx == -1)
5900             {
5901                 ListTab.SelectedIndex = 0;
5902                 lst = (DetailsListView)ListTab.TabPages[0].Tag;
5903                 //_curTab = ListTab.TabPages[0];
5904                 if (_statuses.SortOrder == SortOrder.Ascending)
5905                     idx = lst.VirtualListSize - 1;
5906                 else
5907                     idx = 0;
5908             }
5909
5910             if (lst.VirtualListSize > 0 && idx > -1 && lst.VirtualListSize > idx)
5911             {
5912                 SelectListItem(lst, idx);
5913                 if (_statuses.SortMode == IdComparerClass.ComparerMode.Id)
5914                 {
5915                     if (_statuses.SortOrder == SortOrder.Ascending && lst.Items[idx].Position.Y > lst.ClientSize.Height - _iconSz - 10 ||
5916                        _statuses.SortOrder == SortOrder.Descending && lst.Items[idx].Position.Y < _iconSz + 10)
5917                     {
5918                         MoveTop();
5919                     }
5920                     else
5921                     {
5922                         lst.EnsureVisible(idx);
5923                     }
5924                 }
5925                 else
5926                 {
5927                     lst.EnsureVisible(idx);
5928                 }
5929             }
5930             lst.Focus();
5931         }
5932
5933         private void StatusOpenMenuItem_Click(object sender, EventArgs e)
5934         {
5935             if (_curList.SelectedIndices.Count > 0 && _statuses.Tabs[_curTab.Text].TabType != MyCommon.TabUsageType.DirectMessage)
5936             {
5937                 var post = _statuses[_curTab.Text, _curList.SelectedIndices[0]];
5938                 OpenUriAsync(MyCommon.GetStatusUrl(post));
5939             }
5940         }
5941
5942         private void FavorareMenuItem_Click(object sender, EventArgs e)
5943         {
5944             if (_curList.SelectedIndices.Count > 0)
5945             {
5946                 PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[0]];
5947                 OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + post.ScreenName + "/recent");
5948             }
5949         }
5950
5951         private void VerUpMenuItem_Click(object sender, EventArgs e)
5952         {
5953             CheckNewVersion();
5954         }
5955
5956         private void RunTweenUp()
5957         {
5958             ProcessStartInfo pinfo = new ProcessStartInfo();
5959             pinfo.UseShellExecute = true;
5960             pinfo.WorkingDirectory = MyCommon.settingPath;
5961             pinfo.FileName = Path.Combine(MyCommon.settingPath, "TweenUp3.exe");
5962             pinfo.Arguments = "\"" + Application.StartupPath + "\"";
5963             try
5964             {
5965                 Process.Start(pinfo);
5966             }
5967             catch (Exception)
5968             {
5969                 MessageBox.Show("Failed to execute TweenUp3.exe.");
5970             }
5971         }
5972
5973         private void CheckNewVersion(bool startup = false)
5974         {
5975             if (string.IsNullOrEmpty(MyCommon.fileVersion))
5976             {
5977                 return;
5978             }
5979
5980             string retMsg;
5981             try
5982             {
5983                 retMsg = tw.GetVersionInfo();
5984             }
5985             catch
5986             {
5987                 retMsg = "";
5988             }
5989
5990             if (string.IsNullOrEmpty(retMsg))
5991             {
5992                 StatusLabel.Text = Properties.Resources.CheckNewVersionText9;
5993                 if (!startup) MessageBox.Show(Properties.Resources.CheckNewVersionText10, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
5994                 return;
5995             }
5996
5997             // 改行2つで前後パートを分割(前半がバージョン番号など、後半が詳細テキスト)
5998             string[] msgPart = retMsg.Split(new string[] {"\n\n", "\r\n\r\n"}, 2, StringSplitOptions.None);
5999
6000             string[] msgHeader = msgPart[0].Split(new string[] {"\n", "\r\n"}, StringSplitOptions.None);
6001             string msgBody = msgPart.Length == 2 ? msgPart[1] : "";
6002
6003             msgBody = Regex.Replace(msgBody, "(?<!\r)\n", "\r\n"); // LF -> CRLF
6004
6005             string currentVersion = msgHeader[0];
6006             string downloadUrl = msgHeader[1];
6007
6008             if (currentVersion.Replace(".", "").CompareTo(MyCommon.fileVersion.Replace(".", "")) > 0)
6009             {
6010                 using (var dialog = new UpdateDialog())
6011                 {
6012                     dialog.SummaryText = string.Format(Properties.Resources.CheckNewVersionText3, MyCommon.GetReadableVersion(currentVersion));
6013                     dialog.DetailsText = msgBody;
6014                     if (dialog.ShowDialog(this) == DialogResult.Yes)
6015                     {
6016                         this.OpenUriAsync(downloadUrl);
6017                     }
6018                 }
6019             }
6020             else
6021             {
6022                 if (!startup)
6023                 {
6024                     var msgtext = MyCommon.ReplaceAppName(string.Format(Properties.Resources.CheckNewVersionText7, MyCommon.GetReadableVersion(), MyCommon.GetReadableVersion(currentVersion)));
6025                     MessageBox.Show(msgtext, MyCommon.ReplaceAppName(Properties.Resources.CheckNewVersionText2), MessageBoxButtons.OK, MessageBoxIcon.Information);
6026                 }
6027             }
6028         }
6029
6030         private void Colorize()
6031         {
6032             _colorize = false;
6033             DispSelectedPost();
6034             //件数関連の場合、タイトル即時書き換え
6035             if (SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.None &&
6036                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Post &&
6037                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
6038                SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
6039             {
6040                 SetMainWindowTitle();
6041             }
6042             if (!StatusLabelUrl.Text.StartsWith("http")) SetStatusLabelUrl();
6043             foreach (TabPage tb in ListTab.TabPages)
6044             {
6045                 if (_statuses.Tabs[tb.Text].UnreadCount == 0)
6046                 {
6047                     if (SettingDialog.TabIconDisp)
6048                     {
6049                         if (tb.ImageIndex == 0) tb.ImageIndex = -1;
6050                     }
6051                 }
6052             }
6053             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
6054         }
6055
6056         public string createDetailHtml(string orgdata)
6057         {
6058             return detailHtmlFormatHeader + orgdata + detailHtmlFormatFooter;
6059         }
6060
6061         private void DisplayItemImage_Downloaded(object sender, EventArgs e)
6062         {
6063             if (sender.Equals(displayItem))
6064             {
6065                 if (UserPicture.Image != null) UserPicture.Image.Dispose();
6066                 if (displayItem.Image != null)
6067                 {
6068                     try
6069                     {
6070                         UserPicture.Image = new Bitmap(displayItem.Image);
6071                     }
6072                     catch (Exception)
6073                     {
6074                         UserPicture.Image = null;
6075                     }
6076                 }
6077                 else
6078                 {
6079                     UserPicture.Image = null;
6080                 }
6081             }
6082         }
6083
6084         private void DispSelectedPost()
6085         {
6086             DispSelectedPost(false);
6087         }
6088
6089         private static PostClass displaypost = new PostClass();
6090
6091         private void DispSelectedPost(bool forceupdate)
6092         {
6093             if (_curList.SelectedIndices.Count == 0 || _curPost == null)
6094                 return;
6095
6096             if (!forceupdate && _curPost.Equals(displaypost))
6097                 return;
6098
6099             displaypost = _curPost;
6100             if (displayItem != null)
6101             {
6102                 displayItem.ImageDownloaded -= this.DisplayItemImage_Downloaded;
6103                 displayItem = null;
6104             }
6105             displayItem = (ImageListViewItem)_curList.Items[_curList.SelectedIndices[0]];
6106             displayItem.ImageDownloaded += this.DisplayItemImage_Downloaded;
6107
6108             string dTxt = createDetailHtml(_curPost.IsDeleted ? "(DELETED)" : _curPost.Text);
6109             if (_curPost.IsDm)
6110             {
6111                 SourceLinkLabel.Tag = null;
6112                 SourceLinkLabel.Text = "";
6113             }
6114             else
6115             {
6116                 Match mc = Regex.Match(_curPost.SourceHtml, "<a href=\"(?<sourceurl>.+?)\"");
6117                 if (mc.Success)
6118                 {
6119                     string src = mc.Groups["sourceurl"].Value;
6120                     SourceLinkLabel.Tag = mc.Groups["sourceurl"].Value;
6121                     mc = Regex.Match(src, "^https?://");
6122                     if (!mc.Success)
6123                     {
6124                         src = src.Insert(0, "http://twitter.com");
6125                     }
6126                     SourceLinkLabel.Tag = src;
6127                 }
6128                 else
6129                 {
6130                     SourceLinkLabel.Tag = null;
6131                 }
6132                 if (string.IsNullOrEmpty(_curPost.Source))
6133                 {
6134                     SourceLinkLabel.Text = "";
6135                     //SourceLinkLabel.Visible = false;
6136                 }
6137                 else
6138                 {
6139                     SourceLinkLabel.Text = _curPost.Source;
6140                     //SourceLinkLabel.Visible = true;
6141                 }
6142             }
6143             SourceLinkLabel.TabStop = false;
6144
6145             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && !_curPost.IsOwl)
6146             {
6147                 NameLabel.Text = "DM TO -> ";
6148             }
6149             else if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)
6150             {
6151                 NameLabel.Text = "DM FROM <- ";
6152             }
6153             else
6154             {
6155                 NameLabel.Text = "";
6156             }
6157             NameLabel.Text += _curPost.ScreenName + "/" + _curPost.Nickname;
6158             NameLabel.Tag = _curPost.ScreenName;
6159             if (!string.IsNullOrEmpty(_curPost.RetweetedBy))
6160             {
6161                 NameLabel.Text += " (RT:" + _curPost.RetweetedBy + ")";
6162             }
6163             if (UserPicture.Image != null) UserPicture.Image.Dispose();
6164             if (!string.IsNullOrEmpty(_curPost.ImageUrl) && TIconDic[_curPost.ImageUrl] != null)
6165             {
6166                 try
6167                 {
6168                     UserPicture.Image = new Bitmap(TIconDic[_curPost.ImageUrl]);
6169                 }
6170                 catch (Exception)
6171                 {
6172                     UserPicture.Image = null;
6173                 }
6174             }
6175             else
6176             {
6177                 UserPicture.Image = null;
6178             }
6179
6180             NameLabel.ForeColor = System.Drawing.SystemColors.ControlText;
6181             DateTimeLabel.Text = _curPost.CreatedAt.ToString();
6182             if (_curPost.IsOwl && (SettingDialog.OneWayLove || _statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage)) NameLabel.ForeColor = _clOWL;
6183             if (_curPost.RetweetedId > 0) NameLabel.ForeColor = _clRetweet;
6184             if (_curPost.IsFav) NameLabel.ForeColor = _clFav;
6185
6186             if (DumpPostClassToolStripMenuItem.Checked)
6187             {
6188                 StringBuilder sb = new StringBuilder(512);
6189
6190                 sb.Append("-----Start PostClass Dump<br>");
6191                 sb.AppendFormat("TextFromApi           : {0}<br>", _curPost.TextFromApi);
6192                 sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.TextFromApi);
6193                 sb.AppendFormat("StatusId             : {0}<br>", _curPost.StatusId.ToString());
6194                 //sb.AppendFormat("ImageIndex     : {0}<br>", _curPost.ImageIndex.ToString());
6195                 sb.AppendFormat("ImageUrl       : {0}<br>", _curPost.ImageUrl);
6196                 sb.AppendFormat("InReplyToStatusId    : {0}<br>", _curPost.InReplyToStatusId.ToString());
6197                 sb.AppendFormat("InReplyToUser  : {0}<br>", _curPost.InReplyToUser);
6198                 sb.AppendFormat("IsDM           : {0}<br>", _curPost.IsDm.ToString());
6199                 sb.AppendFormat("IsFav          : {0}<br>", _curPost.IsFav.ToString());
6200                 sb.AppendFormat("IsMark         : {0}<br>", _curPost.IsMark.ToString());
6201                 sb.AppendFormat("IsMe           : {0}<br>", _curPost.IsMe.ToString());
6202                 sb.AppendFormat("IsOwl          : {0}<br>", _curPost.IsOwl.ToString());
6203                 sb.AppendFormat("IsProtect      : {0}<br>", _curPost.IsProtect.ToString());
6204                 sb.AppendFormat("IsRead         : {0}<br>", _curPost.IsRead.ToString());
6205                 sb.AppendFormat("IsReply        : {0}<br>", _curPost.IsReply.ToString());
6206             
6207                 foreach (string nm in _curPost.ReplyToList)
6208                 {
6209                     sb.AppendFormat("ReplyToList    : {0}<br>", nm);
6210                 }
6211
6212                 sb.AppendFormat("ScreenName           : {0}<br>", _curPost.ScreenName);
6213                 sb.AppendFormat("NickName       : {0}<br>", _curPost.Nickname);
6214                 sb.AppendFormat("Text   : {0}<br>", _curPost.Text);
6215                 sb.AppendFormat("(PlainText)    : <xmp>{0}</xmp><br>", _curPost.Text);
6216                 sb.AppendFormat("CreatedAt          : {0}<br>", _curPost.CreatedAt.ToString());
6217                 sb.AppendFormat("Source         : {0}<br>", _curPost.Source);
6218                 sb.AppendFormat("UserId            : {0}<br>", _curPost.UserId);
6219                 sb.AppendFormat("FilterHit      : {0}<br>", _curPost.FilterHit);
6220                 sb.AppendFormat("RetweetedBy    : {0}<br>", _curPost.RetweetedBy);
6221                 sb.AppendFormat("RetweetedId    : {0}<br>", _curPost.RetweetedId);
6222                 sb.AppendFormat("SearchTabName  : {0}<br>", _curPost.RelTabName);
6223                 sb.Append("-----End PostClass Dump<br>");
6224
6225                 PostBrowser.Visible = false;
6226                 PostBrowser.DocumentText = detailHtmlFormatHeader + sb.ToString() + detailHtmlFormatFooter;
6227                 PostBrowser.Visible = true;
6228             }
6229             else
6230             {
6231                 try
6232                 {
6233                     if (PostBrowser.DocumentText != dTxt)
6234                     {
6235                         PostBrowser.Visible = false;
6236                         PostBrowser.DocumentText = dTxt;
6237
6238                         this.SplitContainer3.Panel2Collapsed = true;
6239
6240                         if (this.IsPreviewEnable)
6241                             this.tweetThumbnail1.ShowThumbnailAsync(_curPost);
6242                     }
6243                 }
6244                 catch (System.Runtime.InteropServices.COMException)
6245                 {
6246                     //原因不明
6247                 }
6248                 catch (UriFormatException)
6249                 {
6250                     PostBrowser.DocumentText = dTxt;
6251                 }
6252                 finally
6253                 {
6254                     PostBrowser.Visible = true;
6255                 }
6256             }
6257         }
6258
6259         private void MatomeMenuItem_Click(object sender, EventArgs e)
6260         {
6261             OpenApplicationWebsite();
6262         }
6263
6264         private void OpenApplicationWebsite()
6265         {
6266             OpenUriAsync(ApplicationSettings.WebsiteUrl);
6267         }
6268
6269         private void ShortcutKeyListMenuItem_Click(object sender, EventArgs e)
6270         {
6271             OpenUriAsync(ApplicationSettings.ShortcutKeyUrl);
6272         }
6273
6274         private void ListTab_KeyDown(object sender, KeyEventArgs e)
6275         {
6276             if (ListTab.SelectedTab != null)
6277             {
6278                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
6279                 {
6280                     Control pnl = ListTab.SelectedTab.Controls["panelSearch"];
6281                     if (pnl.Controls["comboSearch"].Focused ||
6282                         pnl.Controls["comboLang"].Focused ||
6283                         pnl.Controls["buttonSearch"].Focused) return;
6284                 }
6285                 ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
6286                 if (State == ModifierState.NotFlags) return;
6287                 if (State != ModifierState.None) _anchorFlag = false;
6288                 if (CommonKeyDown(e.KeyCode, FocusedControl.ListTab, State))
6289                 {
6290                     e.Handled = true;
6291                     e.SuppressKeyPress = true;
6292                 }
6293             }
6294         }
6295
6296         private ModifierState GetModifierState(bool sControl, bool sShift, bool sAlt)
6297         {
6298             ModifierState state = ModifierState.None;
6299             if (sControl) state = state | ModifierState.Ctrl;
6300             if (sShift) state = state | ModifierState.Shift;
6301             if (sAlt) state = state | ModifierState.Alt;
6302             return state;
6303         }
6304
6305         [FlagsAttribute]
6306         private enum ModifierState
6307         {
6308             None = 0,
6309             Alt = 1,
6310             Shift = 2,
6311             Ctrl = 4,
6312             //CShift = 11,
6313             //CAlt = 12,
6314             //AShift = 13,
6315             NotFlags = 8,
6316
6317             //ListTab = 101,
6318             //PostBrowser = 102,
6319             //StatusText = 103,
6320         }
6321
6322         private enum FocusedControl : int
6323         {
6324             None,
6325             ListTab,
6326             StatusText,
6327             PostBrowser,
6328         }
6329
6330         private bool CommonKeyDown(Keys KeyCode, FocusedControl Focused, ModifierState Modifier)
6331         {
6332             //リストのカーソル移動関係(上下キー、PageUp/Downに該当)
6333             if (Focused == FocusedControl.ListTab)
6334             {
6335                 if (Modifier == (ModifierState.Ctrl | ModifierState.Shift) ||
6336                     Modifier == ModifierState.Ctrl ||
6337                     Modifier == ModifierState.None ||
6338                     Modifier == ModifierState.Shift)
6339                 {
6340                     if (KeyCode == Keys.J)
6341                     {
6342                         SendKeys.Send("{DOWN}");
6343                         return true;
6344                     }
6345                     else if (KeyCode == Keys.K)
6346                     {
6347                         SendKeys.Send("{UP}");
6348                         return true;
6349                     }
6350                 }
6351                 if (Modifier == ModifierState.Shift ||
6352                     Modifier == ModifierState.None)
6353                 {
6354                     if (KeyCode == Keys.F)
6355                     {
6356                         SendKeys.Send("{PGDN}");
6357                         return true;
6358                     }
6359                     else if (KeyCode == Keys.B)
6360                     {
6361                         SendKeys.Send("{PGUP}");
6362                         return true;
6363                     }
6364                 }
6365             }
6366
6367             //修飾キーなし
6368             switch (Modifier)
6369             {
6370                 case ModifierState.None:
6371                     //フォーカス関係なし
6372                     switch (KeyCode)
6373                     {
6374                         case Keys.F1:
6375                             OpenApplicationWebsite();
6376                             return true;
6377                         case Keys.F3:
6378                             MenuItemSearchNext_Click(null, null);
6379                             return true;
6380                         case Keys.F5:
6381                             DoRefresh();
6382                             return true;
6383                         case Keys.F6:
6384                             GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 0, "");
6385                             return true;
6386                         case Keys.F7:
6387                             GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 0, "");
6388                             return true;
6389                     }
6390                     if (Focused != FocusedControl.StatusText)
6391                     {
6392                         //フォーカスStatusText以外
6393                         switch (KeyCode)
6394                         {
6395                             case Keys.Space:
6396                             case Keys.ProcessKey:
6397                                 if (Focused == FocusedControl.ListTab) _anchorFlag = false;
6398                                 JumpUnreadMenuItem_Click(null, null);
6399                                 return true;
6400                             case Keys.G:
6401                                 if (Focused == FocusedControl.ListTab) _anchorFlag = false;
6402                                 ShowRelatedStatusesMenuItem_Click(null, null);
6403                                 return true;
6404                         }
6405                     }
6406                     if (Focused == FocusedControl.ListTab)
6407                     {
6408                         //フォーカスList
6409                         switch (KeyCode)
6410                         {
6411                             case Keys.N:
6412                             case Keys.Right:
6413                                 GoRelPost(true);
6414                                 return true;
6415                             case Keys.P:
6416                             case Keys.Left:
6417                                 GoRelPost(false);
6418                                 return true;
6419                             case Keys.OemPeriod:
6420                                 GoAnchor();
6421                                 return true;
6422                             case Keys.I:
6423                                 if (this.StatusText.Enabled) this.StatusText.Focus();
6424                                 return true;
6425                             case Keys.Enter:
6426                                 MakeReplyOrDirectStatus();
6427                                 return true;
6428                             case Keys.R:
6429                                 DoRefresh();
6430                                 return true;
6431                         }
6432                         //以下、アンカー初期化
6433                         _anchorFlag = false;
6434                         switch (KeyCode)
6435                         {
6436                             case Keys.L:
6437                                 GoPost(true);
6438                                 return true;
6439                             case Keys.H:
6440                                 GoPost(false);
6441                                 return true;
6442                             case Keys.Z:
6443                             case Keys.Oemcomma:
6444                                 MoveTop();
6445                                 return true;
6446                             case Keys.S:
6447                                 GoNextTab(true);
6448                                 return true;
6449                             case Keys.A:
6450                                 GoNextTab(false);
6451                                 return true;
6452                             case Keys.Oem4:
6453                                 // ] in_reply_to参照元へ戻る
6454                                 GoInReplyToPostTree();
6455                                 return true;
6456                             case Keys.Oem6:
6457                                 // [ in_reply_toへジャンプ
6458                                 GoBackInReplyToPostTree();
6459                                 return true;
6460                             case Keys.Escape:
6461                                 if (ListTab.SelectedTab != null)
6462                                 {
6463                                     MyCommon.TabUsageType tabtype = _statuses.Tabs[ListTab.SelectedTab.Text].TabType;
6464                                     if (tabtype == MyCommon.TabUsageType.Related || tabtype == MyCommon.TabUsageType.UserTimeline || tabtype == MyCommon.TabUsageType.PublicSearch)
6465                                     {
6466                                         TabPage relTp = ListTab.SelectedTab;
6467                                         RemoveSpecifiedTab(relTp.Text, false);
6468                                         SaveConfigsTabs();
6469                                         return true;
6470                                     }
6471                                 }
6472                                 break;
6473                         }
6474                     }
6475                     break;
6476                 case ModifierState.Ctrl:
6477                     //フォーカス関係なし
6478                     switch (KeyCode)
6479                     {
6480                         case Keys.R:
6481                             MakeReplyOrDirectStatus(false, true);
6482                             return true;
6483                         case Keys.D:
6484                             doStatusDelete();
6485                             return true;
6486                         case Keys.M:
6487                             MakeReplyOrDirectStatus(false, false);
6488                             return true;
6489                         case Keys.S:
6490                             FavoriteChange(true);
6491                             return true;
6492                         case Keys.I:
6493                             doRepliedStatusOpen();
6494                             return true;
6495                         case Keys.Q:
6496                             doQuote();
6497                             return true;
6498                         case Keys.B:
6499                             ReadedStripMenuItem_Click(null, null);
6500                             return true;
6501                         case Keys.T:
6502                             HashManageMenuItem_Click(null, null);
6503                             return true;
6504                         case Keys.L:
6505                             UrlConvertAutoToolStripMenuItem_Click(null, null);
6506                             return true;
6507                         case Keys.Y:
6508                             if (Focused != FocusedControl.PostBrowser)
6509                             {
6510                                 MultiLineMenuItem_Click(null, null);
6511                                 return true;
6512                             }
6513                             break;
6514                         case Keys.F:
6515                             MenuItemSubSearch_Click(null, null);
6516                             return true;
6517                         case Keys.U:
6518                             ShowUserTimeline();
6519                             return true;
6520                         case Keys.H:
6521                             // Webページを開く動作
6522                             MoveToHomeToolStripMenuItem_Click(null, null);
6523                             return true;
6524                         case Keys.G:
6525                             // Webページを開く動作
6526                             MoveToFavToolStripMenuItem_Click(null, null);
6527                             return true;
6528                         case Keys.O:
6529                             // Webページを開く動作
6530                             StatusOpenMenuItem_Click(null, null);
6531                             return true;
6532                         case Keys.E:
6533                             // Webページを開く動作
6534                             OpenURLMenuItem_Click(null, null);
6535                             return true;
6536                     }
6537                     //フォーカスList
6538                     if (Focused == FocusedControl.ListTab)
6539                     {
6540                         switch (KeyCode)
6541                         {
6542                             case Keys.Home:
6543                             case Keys.End:
6544                                 _colorize = true;
6545                                 return false;            //スルーする
6546                             case Keys.N:
6547                                 GoNextTab(true);
6548                                 return true;
6549                             case Keys.P:
6550                                 GoNextTab(false);
6551                                 return true;
6552                             case Keys.C:
6553                                 CopyStot();
6554                                 return true;
6555                             case Keys.D1:
6556                             case Keys.D2:
6557                             case Keys.D3:
6558                             case Keys.D4:
6559                             case Keys.D5:
6560                             case Keys.D6:
6561                             case Keys.D7:
6562                             case Keys.D8:
6563                                 // タブダイレクト選択(Ctrl+1~8,Ctrl+9)
6564                                 int tabNo = KeyCode - Keys.D1;
6565                                 if (ListTab.TabPages.Count < tabNo)
6566                                     return false;
6567                                 ListTab.SelectedIndex = tabNo;
6568                                 ListTabSelect(ListTab.TabPages[tabNo]);
6569                                 return true;
6570                             case Keys.D9:
6571                                 ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
6572                                 ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
6573                                 return true;
6574                         }
6575                     }
6576                     else if (Focused == FocusedControl.StatusText)
6577                     {
6578                         //フォーカスStatusText
6579                         switch (KeyCode)
6580                         {
6581                             case Keys.A:
6582                                 StatusText.SelectAll();
6583                                 return true;
6584                             case Keys.Up:
6585                             case Keys.Down:
6586                                 if (!string.IsNullOrWhiteSpace(StatusText.Text))
6587                                 {
6588                                     _history[_hisIdx] = new PostingStatus(StatusText.Text, _reply_to_id, _reply_to_name);
6589                                 }
6590                                 if (KeyCode == Keys.Up)
6591                                 {
6592                                     _hisIdx -= 1;
6593                                     if (_hisIdx < 0) _hisIdx = 0;
6594                                 }
6595                                 else
6596                                 {
6597                                     _hisIdx += 1;
6598                                     if (_hisIdx > _history.Count - 1) _hisIdx = _history.Count - 1;
6599                                 }
6600                                 StatusText.Text = _history[_hisIdx].status;
6601                                 _reply_to_id = _history[_hisIdx].inReplyToId;
6602                                 _reply_to_name = _history[_hisIdx].inReplyToName;
6603                                 StatusText.SelectionStart = StatusText.Text.Length;
6604                                 return true;
6605                             case Keys.PageUp:
6606                             case Keys.P:
6607                                 if (ListTab.SelectedIndex == 0)
6608                                 {
6609                                     ListTab.SelectedIndex = ListTab.TabCount - 1;
6610                                 }
6611                                 else
6612                                 {
6613                                     ListTab.SelectedIndex -= 1;
6614                                 }
6615                                 StatusText.Focus();
6616                                 return true;
6617                             case Keys.PageDown:
6618                             case Keys.N:
6619                                 if (ListTab.SelectedIndex == ListTab.TabCount - 1)
6620                                 {
6621                                     ListTab.SelectedIndex = 0;
6622                                 }
6623                                 else
6624                                 {
6625                                     ListTab.SelectedIndex += 1;
6626                                 }
6627                                 StatusText.Focus();
6628                                 return true;
6629                         }
6630                     }
6631                     else
6632                     {
6633                         //フォーカスPostBrowserもしくは関係なし
6634                         switch (KeyCode)
6635                         {
6636                             case Keys.A:
6637                                 PostBrowser.Document.ExecCommand("SelectAll", false, null);
6638                                 return true;
6639                             case Keys.C:
6640                             case Keys.Insert:
6641                                 string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
6642                                 if (!string.IsNullOrEmpty(_selText))
6643                                 {
6644                                     try
6645                                     {
6646                                         Clipboard.SetDataObject(_selText, false, 5, 100);
6647                                     }
6648                                     catch (Exception ex)
6649                                     {
6650                                         MessageBox.Show(ex.Message);
6651                                     }
6652                                 }
6653                                 return true;
6654                             case Keys.Y:
6655                                 MultiLineMenuItem.Checked = !MultiLineMenuItem.Checked;
6656                                 MultiLineMenuItem_Click(null, null);
6657                                 return true;
6658                         }
6659                     }
6660                     break;
6661                 case ModifierState.Shift:
6662                     //フォーカス関係なし
6663                     switch (KeyCode)
6664                     {
6665                         case Keys.F3:
6666                             MenuItemSearchPrev_Click(null, null);
6667                             return true;
6668                         case Keys.F5:
6669                             DoRefreshMore();
6670                             return true;
6671                         case Keys.F6:
6672                             GetTimeline(MyCommon.WORKERTYPE.Reply, -1, 0, "");
6673                             return true;
6674                         case Keys.F7:
6675                             GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, -1, 0, "");
6676                             return true;
6677                     }
6678                     //フォーカスStatusText以外
6679                     if (Focused != FocusedControl.StatusText)
6680                     {
6681                         if (KeyCode == Keys.R)
6682                         {
6683                             DoRefreshMore();
6684                             return true;
6685                         }
6686                     }
6687                     //フォーカスリスト
6688                     if (Focused == FocusedControl.ListTab)
6689                     {
6690                         switch (KeyCode)
6691                         {
6692                             case Keys.H:
6693                                 GoTopEnd(true);
6694                                 return true;
6695                             case Keys.L:
6696                                 GoTopEnd(false);
6697                                 return true;
6698                             case Keys.M:
6699                                 GoMiddle();
6700                                 return true;
6701                             case Keys.G:
6702                                 GoLast();
6703                                 return true;
6704                             case Keys.Z:
6705                                 MoveMiddle();
6706                                 return true;
6707                             case Keys.Oem4:
6708                                 GoBackInReplyToPostTree(true, false);
6709                                 return true;
6710                             case Keys.Oem6:
6711                                 GoBackInReplyToPostTree(true, true);
6712                                 return true;
6713                             case Keys.N:
6714                             case Keys.Right:
6715                                 // お気に入り前後ジャンプ(SHIFT+N←/P→)
6716                                 GoFav(true);
6717                                 return true;
6718                             case Keys.P:
6719                             case Keys.Left:
6720                                 // お気に入り前後ジャンプ(SHIFT+N←/P→)
6721                                 GoFav(false);
6722                                 return true;
6723                             case Keys.Space:
6724                                 this.GoBackSelectPostChain();
6725                                 return true;
6726                         }
6727                     }
6728                     break;
6729                 case ModifierState.Alt:
6730                     switch (KeyCode)
6731                     {
6732                         case Keys.R:
6733                             doReTweetOfficial(true);
6734                             return true;
6735                         case Keys.P:
6736                             if (_curPost != null)
6737                             {
6738                                 doShowUserStatus(_curPost.ScreenName, false);
6739                                 return true;
6740                             }
6741                             break;
6742                         case Keys.Up:
6743                             ScrollDownPostBrowser(false);
6744                             return true;
6745                         case Keys.Down:
6746                             ScrollDownPostBrowser(true);
6747                             return true;
6748                         case Keys.PageUp:
6749                             PageDownPostBrowser(false);
6750                             return true;
6751                         case Keys.PageDown:
6752                             PageDownPostBrowser(true);
6753                             return true;
6754                     }
6755                     if (Focused == FocusedControl.ListTab)
6756                     {
6757                         // 別タブの同じ書き込みへ(ALT+←/→)
6758                         if (KeyCode == Keys.Right)
6759                         {
6760                             GoSamePostToAnotherTab(false);
6761                             return true;
6762                         }
6763                         else if (KeyCode == Keys.Left)
6764                         {
6765                             GoSamePostToAnotherTab(true);
6766                             return true;
6767                         }
6768                     }
6769                     break;
6770                 case ModifierState.Ctrl | ModifierState.Shift:
6771                     switch (KeyCode)
6772                     {
6773                         case Keys.R:
6774                             MakeReplyOrDirectStatus(false, true, true);
6775                             return true;
6776                         case Keys.C:
6777                             CopyIdUri();
6778                             return true;
6779                         case Keys.F:
6780                             if (ListTab.SelectedTab != null)
6781                             {
6782                                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
6783                                 {
6784                                     ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
6785                                     return true;
6786                                 }
6787                             }
6788                             break;
6789                         case Keys.S:
6790                             FavoriteChange(false);
6791                             return true;
6792                         case Keys.B:
6793                             UnreadStripMenuItem_Click(null, null);
6794                             return true;
6795                         case Keys.T:
6796                             HashToggleMenuItem_Click(null, null);
6797                             return true;
6798                         case Keys.P:
6799                             ImageSelectMenuItem_Click(null, null);
6800                             return true;
6801                         case Keys.H:
6802                             doMoveToRTHome();
6803                             return true;
6804                         case Keys.O:
6805                             FavorareMenuItem_Click(null, null);
6806                             return true;
6807                     }
6808                     if (Focused == FocusedControl.StatusText)
6809                     {
6810                         int idx = 0;
6811                         switch (KeyCode)
6812                         {
6813                             case Keys.Up:
6814                                 if (_curList != null && _curList.Items.Count != 0 &&
6815                                             _curList.SelectedIndices.Count > 0 && _curList.SelectedIndices[0] > 0)
6816                                 {
6817                                     idx = _curList.SelectedIndices[0] - 1;
6818                                     SelectListItem(_curList, idx);
6819                                     _curList.EnsureVisible(idx);
6820                                     return true;
6821                                 }
6822                                 break;
6823                             case Keys.Down:
6824                                 if (_curList != null && _curList.Items.Count != 0 && _curList.SelectedIndices.Count > 0
6825                                             && _curList.SelectedIndices[0] < _curList.Items.Count - 1)
6826                                 {
6827                                     idx = _curList.SelectedIndices[0] + 1;
6828                                     SelectListItem(_curList, idx);
6829                                     _curList.EnsureVisible(idx);
6830                                     return true;
6831                                 }
6832                                 break;
6833                             case Keys.Space:
6834                                 if (StatusText.SelectionStart > 0)
6835                                 {
6836                                     int endidx = StatusText.SelectionStart - 1;
6837                                     string startstr = "";
6838                                     bool pressed = false;
6839                                     for (int i = StatusText.SelectionStart - 1; i >= 0; i--)
6840                                     {
6841                                         char c = StatusText.Text[i];
6842                                         if (Char.IsLetterOrDigit(c) || c == '_')
6843                                         {
6844                                             continue;
6845                                         }
6846                                         if (c == '@')
6847                                         {
6848                                             pressed = true;
6849                                             startstr = StatusText.Text.Substring(i + 1, endidx - i);
6850                                             int cnt = AtIdSupl.ItemCount;
6851                                             ShowSuplDialog(StatusText, AtIdSupl, startstr.Length + 1, startstr);
6852                                             if (AtIdSupl.ItemCount != cnt) _modifySettingAtId = true;
6853                                         }
6854                                         else if (c == '#')
6855                                         {
6856                                             pressed = true;
6857                                             startstr = StatusText.Text.Substring(i + 1, endidx - i);
6858                                             ShowSuplDialog(StatusText, HashSupl, startstr.Length + 1, startstr);
6859                                         }
6860                                         else
6861                                         {
6862                                             break;
6863                                         }
6864                                     }
6865                                     return pressed;
6866                                 }
6867                                 break;
6868                         }
6869                     }
6870                     else if (Focused == FocusedControl.ListTab)
6871                     {
6872                         DetailsListView lst = (DetailsListView)ListTab.SelectedTab.Tag;
6873                         ColumnHeader col;
6874                         switch (KeyCode)
6875                         {
6876                             case Keys.D1:
6877                             case Keys.D2:
6878                             case Keys.D3:
6879                             case Keys.D4:
6880                             case Keys.D5:
6881                             case Keys.D6:
6882                             case Keys.D7:
6883                             case Keys.D8:
6884                                 // ソートダイレクト選択(Ctrl+Shift+1~8,Ctrl+Shift+9)
6885                                 int colNo = KeyCode - Keys.D1;
6886                                 if (lst.Columns.Count < colNo) return false;
6887                                 col = lst.Columns.Cast<ColumnHeader>().Where((x) => { return x.DisplayIndex == colNo; }).FirstOrDefault();
6888                                 if (col == null) return false;
6889                                 MyList_ColumnClick(lst, new ColumnClickEventArgs(col.Index));
6890                                 return true;
6891                             case Keys.D9:
6892                                 col = lst.Columns.Cast<ColumnHeader>().OrderByDescending((x) => { return x.DisplayIndex; }).First();
6893                                 MyList_ColumnClick(lst, new ColumnClickEventArgs(col.Index));
6894                                 return true;
6895                         }
6896                     }
6897                     break;
6898                 case ModifierState.Ctrl | ModifierState.Alt:
6899                     if (KeyCode == Keys.S)
6900                     {
6901                         FavoritesRetweetOriginal();
6902                         return true;
6903                     }
6904                     else if (KeyCode == Keys.R)
6905                     {
6906                         FavoritesRetweetUnofficial();
6907                         return true;
6908                     }
6909                     else if (KeyCode == Keys.H)
6910                     {
6911                         OpenUserAppointUrl();
6912                         return true;
6913                     }
6914                     break;
6915                 case ModifierState.Alt | ModifierState.Shift:
6916                     if (Focused == FocusedControl.PostBrowser)
6917                     {
6918                         if (KeyCode == Keys.R)
6919                             doReTweetUnofficial();
6920                         else if (KeyCode == Keys.C)
6921                             CopyUserId();
6922                         return true;
6923                     }
6924                     switch (KeyCode)
6925                     {
6926                         case Keys.T:
6927                             if (!this.ExistCurrentPost) return false;
6928                             doTranslation(_curPost.TextFromApi);
6929                             return true;
6930                         case Keys.R:
6931                             doReTweetUnofficial();
6932                             return true;
6933                         case Keys.C:
6934                             CopyUserId();
6935                             return true;
6936                         case Keys.Up:
6937                             this.tweetThumbnail1.ScrollUp();
6938                             return true;
6939                         case Keys.Down:
6940                             this.tweetThumbnail1.ScrollDown();
6941                             return true;
6942                     }
6943                     if (Focused == FocusedControl.ListTab && KeyCode == Keys.Enter)
6944                     {
6945                         if (!this.SplitContainer3.Panel2Collapsed)
6946                         {
6947                             OpenThumbnailPicture(this.tweetThumbnail1.Thumbnail);
6948                         }
6949                         return true;
6950                     }
6951                     break;
6952             }
6953
6954             return false;
6955         }
6956
6957         private void ScrollDownPostBrowser(bool forward)
6958         {
6959             HtmlDocument doc = PostBrowser.Document;
6960             if (doc == null) return;
6961             if (doc.Body == null) return;
6962
6963             if (forward)
6964                 doc.Body.ScrollTop += SettingDialog.FontDetail.Height;
6965             else
6966                 doc.Body.ScrollTop -= SettingDialog.FontDetail.Height;
6967         }
6968
6969         private void PageDownPostBrowser(bool forward)
6970         {
6971             HtmlDocument doc = PostBrowser.Document;
6972             if (doc == null) return;
6973             if (doc.Body == null) return;
6974
6975             if (forward)
6976                 doc.Body.ScrollTop += PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
6977             else
6978                 doc.Body.ScrollTop -= PostBrowser.ClientRectangle.Height - SettingDialog.FontDetail.Height;
6979         }
6980
6981         private void GoNextTab(bool forward)
6982         {
6983             int idx = ListTab.SelectedIndex;
6984             if (forward)
6985             {
6986                 idx += 1;
6987                 if (idx > ListTab.TabPages.Count - 1) idx = 0;
6988             }
6989             else
6990             {
6991                 idx -= 1;
6992                 if (idx < 0) idx = ListTab.TabPages.Count - 1;
6993             }
6994             ListTab.SelectedIndex = idx;
6995             ListTabSelect(ListTab.TabPages[idx]);
6996         }
6997
6998         private void CopyStot()
6999         {
7000             string clstr = "";
7001             StringBuilder sb = new StringBuilder();
7002             bool IsProtected = false;
7003             bool isDm = false;
7004             if (this._curTab != null && this._statuses.GetTabByName(this._curTab.Text) != null) isDm = this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage;
7005             foreach (int idx in _curList.SelectedIndices)
7006             {
7007                 PostClass post = _statuses[_curTab.Text, idx];
7008                 if (post.IsProtect)
7009                 {
7010                     IsProtected = true;
7011                     continue;
7012                 }
7013                 if (post.IsDeleted) continue;
7014                 if (!isDm)
7015                 {
7016                     if (post.RetweetedId > 0)
7017                         sb.AppendFormat("{0}:{1} [http://twitter.com/{0}/status/{2}]{3}", post.ScreenName, post.TextSingleLine, post.RetweetedId, Environment.NewLine);
7018                     else
7019                         sb.AppendFormat("{0}:{1} [http://twitter.com/{0}/status/{2}]{3}", post.ScreenName, post.TextSingleLine, post.StatusId, Environment.NewLine);
7020                 }
7021                 else
7022                 {
7023                     sb.AppendFormat("{0}:{1} [{2}]{3}", post.ScreenName, post.TextSingleLine, post.StatusId, Environment.NewLine);
7024                 }
7025             }
7026             if (IsProtected)
7027             {
7028                 MessageBox.Show(Properties.Resources.CopyStotText1);
7029             }
7030             if (sb.Length > 0)
7031             {
7032                 clstr = sb.ToString();
7033                 try
7034                 {
7035                     Clipboard.SetDataObject(clstr, false, 5, 100);
7036                 }
7037                 catch (Exception ex)
7038                 {
7039                     MessageBox.Show(ex.Message);
7040                 }
7041             }
7042         }
7043
7044         private void CopyIdUri()
7045         {
7046             string clstr = "";
7047             StringBuilder sb = new StringBuilder();
7048             if (this._curTab == null) return;
7049             if (this._statuses.GetTabByName(this._curTab.Text) == null) return;
7050             if (this._statuses.GetTabByName(this._curTab.Text).TabType == MyCommon.TabUsageType.DirectMessage) return;
7051             foreach (int idx in _curList.SelectedIndices)
7052             {
7053                 var post = _statuses[_curTab.Text, idx];
7054                 sb.Append(MyCommon.GetStatusUrl(post));
7055             }
7056             if (sb.Length > 0)
7057             {
7058                 clstr = sb.ToString();
7059                 try
7060                 {
7061                     Clipboard.SetDataObject(clstr, false, 5, 100);
7062                 }
7063                 catch (Exception ex)
7064                 {
7065                     MessageBox.Show(ex.Message);
7066                 }
7067             }
7068         }
7069
7070         private void GoFav(bool forward)
7071         {
7072             if (_curList.VirtualListSize == 0) return;
7073             int fIdx = 0;
7074             int toIdx = 0;
7075             int stp = 1;
7076
7077             if (forward)
7078             {
7079                 if (_curList.SelectedIndices.Count == 0)
7080                 {
7081                     fIdx = 0;
7082                 }
7083                 else
7084                 {
7085                     fIdx = _curList.SelectedIndices[0] + 1;
7086                     if (fIdx > _curList.VirtualListSize - 1) return;
7087                 }
7088                 toIdx = _curList.VirtualListSize;
7089                 stp = 1;
7090             }
7091             else
7092             {
7093                 if (_curList.SelectedIndices.Count == 0)
7094                 {
7095                     fIdx = _curList.VirtualListSize - 1;
7096                 }
7097                 else
7098                 {
7099                     fIdx = _curList.SelectedIndices[0] - 1;
7100                     if (fIdx < 0) return;
7101                 }
7102                 toIdx = -1;
7103                 stp = -1;
7104             }
7105
7106             for (int idx = fIdx; idx != toIdx; idx += stp)
7107             {
7108                 if (_statuses[_curTab.Text, idx].IsFav)
7109                 {
7110                     SelectListItem(_curList, idx);
7111                     _curList.EnsureVisible(idx);
7112                     break;
7113                 }
7114             }
7115         }
7116
7117         private void GoSamePostToAnotherTab(bool left)
7118         {
7119             if (_curList.VirtualListSize == 0) return;
7120             int fIdx = 0;
7121             int toIdx = 0;
7122             int stp = 1;
7123             long targetId = 0;
7124
7125             if (_statuses.Tabs[_curTab.Text].TabType == MyCommon.TabUsageType.DirectMessage) return; // Directタブは対象外(見つかるはずがない)
7126             if (_curList.SelectedIndices.Count == 0) return; //未選択も処理しない
7127
7128             targetId = GetCurTabPost(_curList.SelectedIndices[0]).StatusId;
7129
7130             if (left)
7131             {
7132                 // 左のタブへ
7133                 if (ListTab.SelectedIndex == 0)
7134                 {
7135                     return;
7136                 }
7137                 else
7138                 {
7139                     fIdx = ListTab.SelectedIndex - 1;
7140                 }
7141                 toIdx = -1;
7142                 stp = -1;
7143             }
7144             else
7145             {
7146                 // 右のタブへ
7147                 if (ListTab.SelectedIndex == ListTab.TabCount - 1)
7148                 {
7149                     return;
7150                 }
7151                 else
7152                 {
7153                     fIdx = ListTab.SelectedIndex + 1;
7154                 }
7155                 toIdx = ListTab.TabCount;
7156                 stp = 1;
7157             }
7158
7159             bool found = false;
7160             for (int tabidx = fIdx; tabidx != toIdx; tabidx += stp)
7161             {
7162                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage) continue; // Directタブは対象外
7163                 for (int idx = 0; idx < ((DetailsListView)ListTab.TabPages[tabidx].Tag).VirtualListSize; idx++)
7164                 {
7165                     if (_statuses[ListTab.TabPages[tabidx].Text, idx].StatusId == targetId)
7166                     {
7167                         ListTab.SelectedIndex = tabidx;
7168                         ListTabSelect(ListTab.TabPages[tabidx]);
7169                         SelectListItem(_curList, idx);
7170                         _curList.EnsureVisible(idx);
7171                         found = true;
7172                         break;
7173                     }
7174                 }
7175                 if (found) break;
7176             }
7177         }
7178
7179         private void GoPost(bool forward)
7180         {
7181             if (_curList.SelectedIndices.Count == 0 || _curPost == null) return;
7182             int fIdx = 0;
7183             int toIdx = 0;
7184             int stp = 1;
7185
7186             if (forward)
7187             {
7188                 fIdx = _curList.SelectedIndices[0] + 1;
7189                 if (fIdx > _curList.VirtualListSize - 1) return;
7190                 toIdx = _curList.VirtualListSize;
7191                 stp = 1;
7192             }
7193             else
7194             {
7195                 fIdx = _curList.SelectedIndices[0] - 1;
7196                 if (fIdx < 0) return;
7197                 toIdx = -1;
7198                 stp = -1;
7199             }
7200
7201             string name = "";
7202             if (_curPost.RetweetedId == 0)
7203             {
7204                 name = _curPost.ScreenName;
7205             }
7206             else
7207             {
7208                 name = _curPost.RetweetedBy;
7209             }
7210             for (int idx = fIdx; idx != toIdx; idx += stp)
7211             {
7212                 if (_statuses[_curTab.Text, idx].RetweetedId == 0)
7213                 {
7214                     if (_statuses[_curTab.Text, idx].ScreenName == name)
7215                     {
7216                         SelectListItem(_curList, idx);
7217                         _curList.EnsureVisible(idx);
7218                         break;
7219                     }
7220                 }
7221                 else
7222                 {
7223                     if (_statuses[_curTab.Text, idx].RetweetedBy == name)
7224                     {
7225                         SelectListItem(_curList, idx);
7226                         _curList.EnsureVisible(idx);
7227                         break;
7228                     }
7229                 }
7230             }
7231         }
7232
7233         private void GoRelPost(bool forward)
7234         {
7235             if (_curList.SelectedIndices.Count == 0) return;
7236
7237             int fIdx = 0;
7238             int toIdx = 0;
7239             int stp = 1;
7240             if (forward)
7241             {
7242                 fIdx = _curList.SelectedIndices[0] + 1;
7243                 if (fIdx > _curList.VirtualListSize - 1) return;
7244                 toIdx = _curList.VirtualListSize;
7245                 stp = 1;
7246             }
7247             else
7248             {
7249                 fIdx = _curList.SelectedIndices[0] - 1;
7250                 if (fIdx < 0) return;
7251                 toIdx = -1;
7252                 stp = -1;
7253             }
7254
7255             if (!_anchorFlag)
7256             {
7257                 if (_curPost == null) return;
7258                 _anchorPost = _curPost;
7259                 _anchorFlag = true;
7260             }
7261             else
7262             {
7263                 if (_anchorPost == null) return;
7264             }
7265
7266             for (int idx = fIdx; idx != toIdx; idx += stp)
7267             {
7268                 PostClass post = _statuses[_curTab.Text, idx];
7269                 if (post.ScreenName == _anchorPost.ScreenName ||
7270                     post.RetweetedBy == _anchorPost.ScreenName ||
7271                     post.ScreenName == _anchorPost.RetweetedBy ||
7272                     (!string.IsNullOrEmpty(post.RetweetedBy) && post.RetweetedBy == _anchorPost.RetweetedBy) ||
7273                     _anchorPost.ReplyToList.Contains(post.ScreenName.ToLower()) ||
7274                     _anchorPost.ReplyToList.Contains(post.RetweetedBy.ToLower()) ||
7275                     post.ReplyToList.Contains(_anchorPost.ScreenName.ToLower()) ||
7276                     post.ReplyToList.Contains(_anchorPost.RetweetedBy.ToLower()))
7277                 {
7278                     SelectListItem(_curList, idx);
7279                     _curList.EnsureVisible(idx);
7280                     break;
7281                 }
7282             }
7283         }
7284
7285         private void GoAnchor()
7286         {
7287             if (_anchorPost == null) return;
7288             int idx = _statuses.Tabs[_curTab.Text].IndexOf(_anchorPost.StatusId);
7289             if (idx == -1) return;
7290
7291             SelectListItem(_curList, idx);
7292             _curList.EnsureVisible(idx);
7293         }
7294
7295         private void GoTopEnd(bool GoTop)
7296         {
7297             ListViewItem _item;
7298             int idx;
7299
7300             if (GoTop)
7301             {
7302                 _item = _curList.GetItemAt(0, 25);
7303                 if (_item == null)
7304                     idx = 0;
7305                 else
7306                     idx = _item.Index;
7307             }
7308             else
7309             {
7310                 _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
7311                 if (_item == null)
7312                     idx = _curList.VirtualListSize - 1;
7313                 else
7314                     idx = _item.Index;
7315             }
7316             SelectListItem(_curList, idx);
7317         }
7318
7319         private void GoMiddle()
7320         {
7321             ListViewItem _item;
7322             int idx1;
7323             int idx2;
7324             int idx3;
7325
7326             _item = _curList.GetItemAt(0, 0);
7327             if (_item == null)
7328             {
7329                 idx1 = 0;
7330             }
7331             else
7332             {
7333                 idx1 = _item.Index;
7334             }
7335
7336             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
7337             if (_item == null)
7338             {
7339                 idx2 = _curList.VirtualListSize - 1;
7340             }
7341             else
7342             {
7343                 idx2 = _item.Index;
7344             }
7345             idx3 = (idx1 + idx2) / 2;
7346
7347             SelectListItem(_curList, idx3);
7348         }
7349
7350         private void GoLast()
7351         {
7352             if (_curList.VirtualListSize == 0) return;
7353
7354             if (_statuses.SortOrder == SortOrder.Ascending)
7355             {
7356                 SelectListItem(_curList, _curList.VirtualListSize - 1);
7357                 _curList.EnsureVisible(_curList.VirtualListSize - 1);
7358             }
7359             else
7360             {
7361                 SelectListItem(_curList, 0);
7362                 _curList.EnsureVisible(0);
7363             }
7364         }
7365
7366         private void MoveTop()
7367         {
7368             if (_curList.SelectedIndices.Count == 0) return;
7369             int idx = _curList.SelectedIndices[0];
7370             if (_statuses.SortOrder == SortOrder.Ascending)
7371             {
7372                 _curList.EnsureVisible(_curList.VirtualListSize - 1);
7373             }
7374             else
7375             {
7376                 _curList.EnsureVisible(0);
7377             }
7378             _curList.EnsureVisible(idx);
7379         }
7380
7381         private void GoInReplyToPostTree()
7382         {
7383             if (_curPost == null) return;
7384
7385             TabClass curTabClass = _statuses.Tabs[_curTab.Text];
7386
7387             if (curTabClass.TabType == MyCommon.TabUsageType.PublicSearch && _curPost.InReplyToStatusId == 0 && _curPost.TextFromApi.Contains("@"))
7388             {
7389                 PostClass post = null;
7390                 string r = tw.GetStatusApi(false, _curPost.StatusId, ref post);
7391                 if (string.IsNullOrEmpty(r) && post != null)
7392                 {
7393                     _curPost.InReplyToStatusId = post.InReplyToStatusId;
7394                     _curPost.InReplyToUser = post.InReplyToUser;
7395                     _curPost.IsReply = post.IsReply;
7396                     _itemCache = null;
7397                     _curList.RedrawItems(_curItemIndex, _curItemIndex, false);
7398                 }
7399                 else
7400                 {
7401                     this.StatusLabel.Text = r;
7402                 }
7403             }
7404
7405             if (!(this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId > 0)) return;
7406
7407             if (replyChains == null || (replyChains.Count > 0 && replyChains.Peek().InReplyToId != _curPost.StatusId))
7408             {
7409                 replyChains = new Stack<ReplyChain>();
7410             }
7411             replyChains.Push(new ReplyChain(_curPost.StatusId, _curPost.InReplyToStatusId, _curTab));
7412
7413             int inReplyToIndex;
7414             string inReplyToTabName;
7415             long inReplyToId = _curPost.InReplyToStatusId;
7416             string inReplyToUser = _curPost.InReplyToUser;
7417             Dictionary<long, PostClass> curTabPosts;
7418
7419             if (_statuses.Tabs[_curTab.Text].IsInnerStorageTabType)
7420                 curTabPosts = curTabClass.Posts;
7421             else
7422                 curTabPosts = _statuses.Posts;
7423
7424             var inReplyToPosts = from tab in _statuses.Tabs.Values
7425                                  orderby tab != curTabClass
7426                                  from post in ((Dictionary<long, PostClass>)(tab.IsInnerStorageTabType ? tab.Posts : _statuses.Posts)).Values
7427                                  where post.StatusId == inReplyToId
7428                                  let index = tab.IndexOf(post.StatusId)
7429                                  where index != -1
7430                                  select new {Tab = tab, Index = index};
7431
7432             try
7433             {
7434                 var inReplyPost = inReplyToPosts.First();
7435                 inReplyToTabName = inReplyPost.Tab.TabName;
7436                 inReplyToIndex = inReplyPost.Index;
7437             }
7438             catch (InvalidOperationException)
7439             {
7440                 PostClass post = null;
7441                 string r = tw.GetStatusApi(false, _curPost.InReplyToStatusId, ref post);
7442                 if (string.IsNullOrEmpty(r) && post != null)
7443                 {
7444                     post.IsRead = true;
7445                     _statuses.AddPost(post);
7446                     _statuses.DistributePosts();
7447                     //_statuses.SubmitUpdate(null, null, null, false);
7448                     this.RefreshTimeline(false);
7449                     try
7450                     {
7451                         var inReplyPost = inReplyToPosts.First();
7452                         inReplyToTabName = inReplyPost.Tab.TabName;
7453                         inReplyToIndex = inReplyPost.Index;
7454                     }
7455                     catch (InvalidOperationException)
7456                     {
7457                         OpenUriAsync("http://twitter.com/" + inReplyToUser + "/statuses/" + inReplyToId.ToString());
7458                         return;
7459                     }
7460                 }
7461                 else
7462                 {
7463                     this.StatusLabel.Text = r;
7464                     OpenUriAsync("http://twitter.com/" + inReplyToUser + "/statuses/" + inReplyToId.ToString());
7465                     return;
7466                 }
7467             }
7468
7469             TabPage tabPage = this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == inReplyToTabName; });
7470             DetailsListView listView = (DetailsListView)tabPage.Tag;
7471
7472             if (_curTab != tabPage)
7473             {
7474                 this.ListTab.SelectTab(tabPage);
7475             }
7476
7477             this.SelectListItem(listView, inReplyToIndex);
7478             listView.EnsureVisible(inReplyToIndex);
7479         }
7480
7481         private void GoBackInReplyToPostTree(bool parallel = false, bool isForward = true)
7482         {
7483             if (_curPost == null) return;
7484
7485             TabClass curTabClass = _statuses.Tabs[_curTab.Text];
7486             Dictionary<long, PostClass> curTabPosts = curTabClass.IsInnerStorageTabType ? curTabClass.Posts : _statuses.Posts;
7487
7488             if (parallel)
7489             {
7490                 if (_curPost.InReplyToStatusId != 0)
7491                 {
7492                     var posts = from t in _statuses.Tabs
7493                                 from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
7494                                 where p.Value.StatusId != _curPost.StatusId && p.Value.InReplyToStatusId == _curPost.InReplyToStatusId
7495                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
7496                                 where indexOf > -1
7497                                 orderby isForward ? indexOf : indexOf * -1
7498                                 orderby t.Value != curTabClass
7499                                 select new {Tab = t.Value, Post = p.Value, Index = indexOf};
7500                     try
7501                     {
7502                         var postList = posts.ToList();
7503                         for (int i = postList.Count - 1; i >= 0; i--)
7504                         {
7505                             int index = i;
7506                             if (postList.FindIndex((pst) => { return pst.Post.StatusId == postList[index].Post.StatusId; }) != index)
7507                             {
7508                                 postList.RemoveAt(index);
7509                             }
7510                         }
7511                         var post = postList.FirstOrDefault((pst) => { return pst.Tab == curTabClass && isForward ? pst.Index > _curItemIndex : pst.Index < _curItemIndex; });
7512                         if (post == null) post = postList.FirstOrDefault((pst) => { return pst.Tab != curTabClass; });
7513                         if (post == null) post = postList.First();
7514                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
7515                         DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
7516                         SelectListItem(listView, post.Index);
7517                         listView.EnsureVisible(post.Index);
7518                     }
7519                     catch (InvalidOperationException)
7520                     {
7521                         return;
7522                     }
7523                 }
7524             }
7525             else
7526             {
7527                 if (replyChains == null || replyChains.Count < 1)
7528                 {
7529                     var posts = from t in _statuses.Tabs
7530                                 from p in t.Value.IsInnerStorageTabType ? t.Value.Posts : _statuses.Posts
7531                                 where p.Value.InReplyToStatusId == _curPost.StatusId
7532                                 let indexOf = t.Value.IndexOf(p.Value.StatusId)
7533                                 where indexOf > -1
7534                                 orderby indexOf
7535                                 orderby t.Value != curTabClass
7536                                 select new {Tab = t.Value, Index = indexOf};
7537                     try
7538                     {
7539                         var post = posts.First();
7540                         this.ListTab.SelectTab(this.ListTab.TabPages.Cast<TabPage>().First((tp) => { return tp.Text == post.Tab.TabName; }));
7541                         DetailsListView listView = (DetailsListView)this.ListTab.SelectedTab.Tag;
7542                         SelectListItem(listView, post.Index);
7543                         listView.EnsureVisible(post.Index);
7544                     }
7545                     catch (InvalidOperationException)
7546                     {
7547                         return;
7548                     }
7549                 }
7550                 else
7551                 {
7552                     ReplyChain chainHead = replyChains.Pop();
7553                     if (chainHead.InReplyToId == _curPost.StatusId)
7554                     {
7555                         int idx = _statuses.Tabs[chainHead.OriginalTab.Text].IndexOf(chainHead.OriginalId);
7556                         if (idx == -1)
7557                         {
7558                             replyChains = null;
7559                         }
7560                         else
7561                         {
7562                             try
7563                             {
7564                                 ListTab.SelectTab(chainHead.OriginalTab);
7565                             }
7566                             catch (Exception)
7567                             {
7568                                 replyChains = null;
7569                             }
7570                             SelectListItem(_curList, idx);
7571                             _curList.EnsureVisible(idx);
7572                         }
7573                     }
7574                     else
7575                     {
7576                         replyChains = null;
7577                         this.GoBackInReplyToPostTree(parallel);
7578                     }
7579                 }
7580             }
7581         }
7582
7583         private void GoBackSelectPostChain()
7584         {
7585             try
7586             {
7587                 this.selectPostChains.Pop();
7588                 Tuple<TabPage, PostClass> tabPostPair = this.selectPostChains.Pop();
7589                 if (!this.ListTab.TabPages.Contains(tabPostPair.Item1)) return;
7590                 this.ListTab.SelectedTab = tabPostPair.Item1;
7591                 if (tabPostPair.Item2 != null && this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId) > -1)
7592                 {
7593                     this.SelectListItem(this._curList, this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
7594                     this._curList.EnsureVisible(this._statuses.Tabs[this._curTab.Text].IndexOf(tabPostPair.Item2.StatusId));
7595                 }
7596             }
7597             catch (InvalidOperationException)
7598             {
7599             }
7600         }
7601
7602         private void PushSelectPostChain()
7603         {
7604             if (this.selectPostChains.Count == 0 || (this.selectPostChains.Peek().Item1.Text != this._curTab.Text || this._curPost != this.selectPostChains.Peek().Item2))
7605             {
7606                 this.selectPostChains.Push(Tuple.Create(this._curTab, _curPost));
7607             }
7608         }
7609
7610         private void TrimPostChain()
7611         {
7612             if (this.selectPostChains.Count < 2000) return;
7613             Stack<Tuple<TabPage, PostClass>> p = new Stack<Tuple<TabPage, PostClass>>();
7614             for (int i = 0; i < 2000; i++)
7615             {
7616                 p.Push(this.selectPostChains.Pop());
7617             }
7618             this.selectPostChains.Clear();
7619             for (int i = 0; i < 2000; i++)
7620             {
7621                 this.selectPostChains.Push(p.Pop());
7622             }
7623         }
7624
7625         private bool GoStatus(long statusId)
7626         {
7627             if (statusId == 0) return false;
7628             for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
7629             {
7630                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType != MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
7631                 {
7632                     int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
7633                     ListTab.SelectedIndex = tabidx;
7634                     ListTabSelect(ListTab.TabPages[tabidx]);
7635                     SelectListItem(_curList, idx);
7636                     _curList.EnsureVisible(idx);
7637                     return true;
7638                 }
7639             }
7640             return false;
7641         }
7642
7643         private bool GoDirectMessage(long statusId)
7644         {
7645             if (statusId == 0) return false;
7646             for (int tabidx = 0; tabidx < ListTab.TabCount; tabidx++)
7647             {
7648                 if (_statuses.Tabs[ListTab.TabPages[tabidx].Text].TabType == MyCommon.TabUsageType.DirectMessage && _statuses.Tabs[ListTab.TabPages[tabidx].Text].Contains(statusId))
7649                 {
7650                     int idx = _statuses.Tabs[ListTab.TabPages[tabidx].Text].IndexOf(statusId);
7651                     ListTab.SelectedIndex = tabidx;
7652                     ListTabSelect(ListTab.TabPages[tabidx]);
7653                     SelectListItem(_curList, idx);
7654                     _curList.EnsureVisible(idx);
7655                     return true;
7656                 }
7657             }
7658             return false;
7659         }
7660
7661         private void MyList_MouseClick(object sender, MouseEventArgs e)
7662         {
7663             _anchorFlag = false;
7664         }
7665
7666         private void StatusText_Enter(object sender, EventArgs e)
7667         {
7668             // フォーカスの戻り先を StatusText に設定
7669             this.Tag = StatusText;
7670             StatusText.BackColor = _clInputBackcolor;
7671         }
7672
7673         public Color InputBackColor
7674         {
7675             get { return _clInputBackcolor; }
7676             set { _clInputBackcolor = value; }
7677         }
7678
7679         private void StatusText_Leave(object sender, EventArgs e)
7680         {
7681             // フォーカスがメニューに遷移しないならばフォーカスはタブに移ることを期待
7682             if (ListTab.SelectedTab != null && MenuStrip1.Tag == null) this.Tag = ListTab.SelectedTab.Tag;
7683             StatusText.BackColor = Color.FromKnownColor(KnownColor.Window);
7684         }
7685
7686         private void StatusText_KeyDown(object sender, KeyEventArgs e)
7687         {
7688             ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
7689             if (State == ModifierState.NotFlags) return;
7690             if (CommonKeyDown(e.KeyCode, FocusedControl.StatusText, State))
7691             {
7692                 e.Handled = true;
7693                 e.SuppressKeyPress = true;
7694             }
7695
7696             this.StatusText_TextChanged(null, null);
7697         }
7698
7699         private void SaveConfigsAll(bool ifModified)
7700         {
7701             if (!ifModified)
7702             {
7703                 SaveConfigsCommon();
7704                 SaveConfigsLocal();
7705                 SaveConfigsTabs();
7706                 SaveConfigsAtId();
7707             }
7708             else
7709             {
7710                 if (_modifySettingCommon) SaveConfigsCommon();
7711                 if (_modifySettingLocal) SaveConfigsLocal();
7712                 if (_modifySettingAtId) SaveConfigsAtId();
7713             }
7714         }
7715
7716         private void SaveConfigsAtId()
7717         {
7718             if (_ignoreConfigSave || !SettingDialog.UseAtIdSupplement && AtIdSupl == null) return;
7719
7720             _modifySettingAtId = false;
7721             SettingAtIdList cfgAtId = new SettingAtIdList(AtIdSupl.GetItemList());
7722             cfgAtId.Save();
7723         }
7724
7725         private void SaveConfigsCommon()
7726         {
7727             if (_ignoreConfigSave) return;
7728
7729             _modifySettingCommon = false;
7730             lock (_syncObject)
7731             {
7732                 _cfgCommon.UserName = tw.Username;
7733                 _cfgCommon.UserId = tw.UserId;
7734                 _cfgCommon.Password = tw.Password;
7735                 _cfgCommon.Token = tw.AccessToken;
7736                 _cfgCommon.TokenSecret = tw.AccessTokenSecret;
7737                 _cfgCommon.UserAccounts = SettingDialog.UserAccounts;
7738                 _cfgCommon.UserstreamStartup = SettingDialog.UserstreamStartup;
7739                 _cfgCommon.UserstreamPeriod = SettingDialog.UserstreamPeriodInt;
7740                 _cfgCommon.TimelinePeriod = SettingDialog.TimelinePeriodInt;
7741                 _cfgCommon.ReplyPeriod = SettingDialog.ReplyPeriodInt;
7742                 _cfgCommon.DMPeriod = SettingDialog.DMPeriodInt;
7743                 _cfgCommon.PubSearchPeriod = SettingDialog.PubSearchPeriodInt;
7744                 _cfgCommon.ListsPeriod = SettingDialog.ListsPeriodInt;
7745                 _cfgCommon.UserTimelinePeriod = SettingDialog.UserTimelinePeriodInt;
7746                 _cfgCommon.Read = SettingDialog.Readed;
7747                 _cfgCommon.IconSize = SettingDialog.IconSz;
7748                 _cfgCommon.UnreadManage = SettingDialog.UnreadManage;
7749                 _cfgCommon.PlaySound = SettingDialog.PlaySound;
7750                 _cfgCommon.OneWayLove = SettingDialog.OneWayLove;
7751
7752                 _cfgCommon.NameBalloon = SettingDialog.NameBalloon;
7753                 _cfgCommon.PostCtrlEnter = SettingDialog.PostCtrlEnter;
7754                 _cfgCommon.PostShiftEnter = SettingDialog.PostShiftEnter;
7755                 _cfgCommon.CountApi = SettingDialog.CountApi;
7756                 _cfgCommon.CountApiReply = SettingDialog.CountApiReply;
7757                 _cfgCommon.PostAndGet = SettingDialog.PostAndGet;
7758                 _cfgCommon.DispUsername = SettingDialog.DispUsername;
7759                 _cfgCommon.MinimizeToTray = SettingDialog.MinimizeToTray;
7760                 _cfgCommon.CloseToExit = SettingDialog.CloseToExit;
7761                 _cfgCommon.DispLatestPost = SettingDialog.DispLatestPost;
7762                 _cfgCommon.SortOrderLock = SettingDialog.SortOrderLock;
7763                 _cfgCommon.TinyUrlResolve = SettingDialog.TinyUrlResolve;
7764                 _cfgCommon.ShortUrlForceResolve = SettingDialog.ShortUrlForceResolve;
7765                 _cfgCommon.PeriodAdjust = SettingDialog.PeriodAdjust;
7766                 _cfgCommon.StartupVersion = SettingDialog.StartupVersion;
7767                 _cfgCommon.StartupFollowers = SettingDialog.StartupFollowers;
7768                 _cfgCommon.RestrictFavCheck = SettingDialog.RestrictFavCheck;
7769                 _cfgCommon.AlwaysTop = SettingDialog.AlwaysTop;
7770                 _cfgCommon.UrlConvertAuto = SettingDialog.UrlConvertAuto;
7771                 _cfgCommon.Outputz = SettingDialog.OutputzEnabled;
7772                 _cfgCommon.OutputzKey = SettingDialog.OutputzKey;
7773                 _cfgCommon.OutputzUrlMode = SettingDialog.OutputzUrlmode;
7774                 _cfgCommon.UseUnreadStyle = SettingDialog.UseUnreadStyle;
7775                 _cfgCommon.DateTimeFormat = SettingDialog.DateTimeFormat;
7776                 _cfgCommon.DefaultTimeOut = SettingDialog.DefaultTimeOut;
7777                 _cfgCommon.RetweetNoConfirm = SettingDialog.RetweetNoConfirm;
7778                 _cfgCommon.LimitBalloon = SettingDialog.LimitBalloon;
7779                 _cfgCommon.EventNotifyEnabled = SettingDialog.EventNotifyEnabled;
7780                 _cfgCommon.EventNotifyFlag = SettingDialog.EventNotifyFlag;
7781                 _cfgCommon.IsMyEventNotifyFlag = SettingDialog.IsMyEventNotifyFlag;
7782                 _cfgCommon.ForceEventNotify = SettingDialog.ForceEventNotify;
7783                 _cfgCommon.FavEventUnread = SettingDialog.FavEventUnread;
7784                 _cfgCommon.TranslateLanguage = SettingDialog.TranslateLanguage;
7785                 _cfgCommon.EventSoundFile = SettingDialog.EventSoundFile;
7786                 _cfgCommon.AutoShortUrlFirst = SettingDialog.AutoShortUrlFirst;
7787                 _cfgCommon.TabIconDisp = SettingDialog.TabIconDisp;
7788                 _cfgCommon.ReplyIconState = SettingDialog.ReplyIconState;
7789                 _cfgCommon.ReadOwnPost = SettingDialog.ReadOwnPost;
7790                 _cfgCommon.GetFav = SettingDialog.GetFav;
7791                 _cfgCommon.IsMonospace = SettingDialog.IsMonospace;
7792                 if (IdeographicSpaceToSpaceToolStripMenuItem != null &&
7793                    IdeographicSpaceToSpaceToolStripMenuItem.IsDisposed == false)
7794                 {
7795                     _cfgCommon.WideSpaceConvert = this.IdeographicSpaceToSpaceToolStripMenuItem.Checked;
7796                 }
7797                 _cfgCommon.ReadOldPosts = SettingDialog.ReadOldPosts;
7798                 _cfgCommon.UseSsl = SettingDialog.UseSsl;
7799                 _cfgCommon.BilyUser = SettingDialog.BitlyUser;
7800                 _cfgCommon.BitlyPwd = SettingDialog.BitlyPwd;
7801                 _cfgCommon.ShowGrid = SettingDialog.ShowGrid;
7802                 _cfgCommon.UseAtIdSupplement = SettingDialog.UseAtIdSupplement;
7803                 _cfgCommon.UseHashSupplement = SettingDialog.UseHashSupplement;
7804                 _cfgCommon.PreviewEnable = SettingDialog.PreviewEnable;
7805                 _cfgCommon.Language = SettingDialog.Language;
7806
7807                 _cfgCommon.SortOrder = (int)_statuses.SortOrder;
7808                 switch (_statuses.SortMode)
7809                 {
7810                     case IdComparerClass.ComparerMode.Nickname:  //ニックネーム
7811                         _cfgCommon.SortColumn = 1;
7812                         break;
7813                     case IdComparerClass.ComparerMode.Data:  //本文
7814                         _cfgCommon.SortColumn = 2;
7815                         break;
7816                     case IdComparerClass.ComparerMode.Id:  //時刻=発言Id
7817                         _cfgCommon.SortColumn = 3;
7818                         break;
7819                     case IdComparerClass.ComparerMode.Name:  //名前
7820                         _cfgCommon.SortColumn = 4;
7821                         break;
7822                     case IdComparerClass.ComparerMode.Source:  //Source
7823                         _cfgCommon.SortColumn = 7;
7824                         break;
7825                 }
7826
7827                 _cfgCommon.Nicoms = SettingDialog.Nicoms;
7828                 _cfgCommon.HashTags = HashMgr.HashHistories;
7829                 if (HashMgr.IsPermanent)
7830                 {
7831                     _cfgCommon.HashSelected = HashMgr.UseHash;
7832                 }
7833                 else
7834                 {
7835                     _cfgCommon.HashSelected = "";
7836                 }
7837                 _cfgCommon.HashIsHead = HashMgr.IsHead;
7838                 _cfgCommon.HashIsPermanent = HashMgr.IsPermanent;
7839                 _cfgCommon.HashIsNotAddToAtReply = HashMgr.IsNotAddToAtReply;
7840                 _cfgCommon.TwitterUrl = SettingDialog.TwitterApiUrl;
7841                 _cfgCommon.TwitterSearchUrl = SettingDialog.TwitterSearchApiUrl;
7842                 _cfgCommon.HotkeyEnabled = SettingDialog.HotkeyEnabled;
7843                 _cfgCommon.HotkeyModifier = SettingDialog.HotkeyMod;
7844                 _cfgCommon.HotkeyKey = SettingDialog.HotkeyKey;
7845                 _cfgCommon.HotkeyValue = SettingDialog.HotkeyValue;
7846                 _cfgCommon.BlinkNewMentions = SettingDialog.BlinkNewMentions;
7847                 if (ToolStripFocusLockMenuItem != null &&
7848                         ToolStripFocusLockMenuItem.IsDisposed == false)
7849                 {
7850                     _cfgCommon.FocusLockToStatusText = this.ToolStripFocusLockMenuItem.Checked;
7851                 }
7852                 _cfgCommon.UseAdditionalCount = SettingDialog.UseAdditionalCount;
7853                 _cfgCommon.MoreCountApi = SettingDialog.MoreCountApi;
7854                 _cfgCommon.FirstCountApi = SettingDialog.FirstCountApi;
7855                 _cfgCommon.SearchCountApi = SettingDialog.SearchCountApi;
7856                 _cfgCommon.FavoritesCountApi = SettingDialog.FavoritesCountApi;
7857                 _cfgCommon.UserTimelineCountApi = SettingDialog.UserTimelineCountApi;
7858                 _cfgCommon.TrackWord = tw.TrackWord;
7859                 _cfgCommon.AllAtReply = tw.AllAtReply;
7860                 _cfgCommon.OpenUserTimeline = SettingDialog.OpenUserTimeline;
7861                 _cfgCommon.ListCountApi = SettingDialog.ListCountApi;
7862                 _cfgCommon.UseImageService = ImageServiceCombo.SelectedIndex;
7863                 _cfgCommon.ListDoubleClickAction = SettingDialog.ListDoubleClickAction;
7864                 _cfgCommon.UserAppointUrl = SettingDialog.UserAppointUrl;
7865                 _cfgCommon.HideDuplicatedRetweets = SettingDialog.HideDuplicatedRetweets;
7866                 _cfgCommon.IsPreviewFoursquare = SettingDialog.IsPreviewFoursquare;
7867                 _cfgCommon.MapThumbnailProvider = SettingDialog.MapThumbnailProvider;
7868                 _cfgCommon.MapThumbnailHeight = SettingDialog.MapThumbnailHeight;
7869                 _cfgCommon.MapThumbnailWidth = SettingDialog.MapThumbnailWidth;
7870                 _cfgCommon.MapThumbnailZoom = SettingDialog.MapThumbnailZoom;
7871                 _cfgCommon.IsListsIncludeRts = SettingDialog.IsListStatusesIncludeRts;
7872                 _cfgCommon.TabMouseLock = SettingDialog.TabMouseLock;
7873                 _cfgCommon.IsRemoveSameEvent = SettingDialog.IsRemoveSameEvent;
7874                 _cfgCommon.IsUseNotifyGrowl = SettingDialog.IsNotifyUseGrowl;
7875
7876                 _cfgCommon.Save();
7877             }
7878         }
7879
7880         private void SaveConfigsLocal()
7881         {
7882             if (_ignoreConfigSave) return;
7883             lock (_syncObject)
7884             {
7885                 _modifySettingLocal = false;
7886                 _cfgLocal.FormSize = _mySize;
7887                 _cfgLocal.FormLocation = _myLoc;
7888                 _cfgLocal.SplitterDistance = _mySpDis;
7889                 _cfgLocal.PreviewDistance = _mySpDis3;
7890                 _cfgLocal.StatusMultiline = StatusText.Multiline;
7891                 _cfgLocal.StatusTextHeight = _mySpDis2;
7892                 _cfgLocal.AdSplitterDistance = _myAdSpDis;
7893                 _cfgLocal.StatusText = SettingDialog.Status;
7894
7895                 _cfgLocal.FontUnread = _fntUnread;
7896                 _cfgLocal.ColorUnread = _clUnread;
7897                 _cfgLocal.FontRead = _fntReaded;
7898                 _cfgLocal.ColorRead = _clReaded;
7899                 _cfgLocal.FontDetail = _fntDetail;
7900                 _cfgLocal.ColorDetail = _clDetail;
7901                 _cfgLocal.ColorDetailBackcolor = _clDetailBackcolor;
7902                 _cfgLocal.ColorDetailLink = _clDetailLink;
7903                 _cfgLocal.ColorFav = _clFav;
7904                 _cfgLocal.ColorOWL = _clOWL;
7905                 _cfgLocal.ColorRetweet = _clRetweet;
7906                 _cfgLocal.ColorSelf = _clSelf;
7907                 _cfgLocal.ColorAtSelf = _clAtSelf;
7908                 _cfgLocal.ColorTarget = _clTarget;
7909                 _cfgLocal.ColorAtTarget = _clAtTarget;
7910                 _cfgLocal.ColorAtFromTarget = _clAtFromTarget;
7911                 _cfgLocal.ColorAtTo = _clAtTo;
7912                 _cfgLocal.ColorListBackcolor = _clListBackcolor;
7913                 _cfgLocal.ColorInputBackcolor = _clInputBackcolor;
7914                 _cfgLocal.ColorInputFont = _clInputFont;
7915                 _cfgLocal.FontInputFont = _fntInputFont;
7916
7917                 _cfgLocal.BrowserPath = SettingDialog.BrowserPath;
7918                 _cfgLocal.UseRecommendStatus = SettingDialog.UseRecommendStatus;
7919                 _cfgLocal.ProxyType = SettingDialog.SelectedProxyType;
7920                 _cfgLocal.ProxyAddress = SettingDialog.ProxyAddress;
7921                 _cfgLocal.ProxyPort = SettingDialog.ProxyPort;
7922                 _cfgLocal.ProxyUser = SettingDialog.ProxyUser;
7923                 _cfgLocal.ProxyPassword = SettingDialog.ProxyPassword;
7924                 if (_ignoreConfigSave) return;
7925                 _cfgLocal.Save();
7926             }
7927         }
7928
7929         private void SaveConfigsTabs()
7930         {
7931             SettingTabs tabSetting = new SettingTabs();
7932             for (int i = 0; i < ListTab.TabPages.Count; i++)
7933             {
7934                 if (_statuses.Tabs[ListTab.TabPages[i].Text].TabType != MyCommon.TabUsageType.Related) tabSetting.Tabs.Add(_statuses.Tabs[ListTab.TabPages[i].Text]);
7935             }
7936             tabSetting.Save();
7937         }
7938
7939         private void SaveLogMenuItem_Click(object sender, EventArgs e)
7940         {
7941             DialogResult rslt = MessageBox.Show(string.Format(Properties.Resources.SaveLogMenuItem_ClickText1, Environment.NewLine),
7942                     Properties.Resources.SaveLogMenuItem_ClickText2,
7943                     MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
7944             if (rslt == DialogResult.Cancel) return;
7945
7946             SaveFileDialog1.FileName = MyCommon.GetAssemblyName() + "Posts" + DateTime.Now.ToString("yyMMdd-HHmmss") + ".tsv";
7947             SaveFileDialog1.InitialDirectory = Application.ExecutablePath;
7948             SaveFileDialog1.Filter = Properties.Resources.SaveLogMenuItem_ClickText3;
7949             SaveFileDialog1.FilterIndex = 0;
7950             SaveFileDialog1.Title = Properties.Resources.SaveLogMenuItem_ClickText4;
7951             SaveFileDialog1.RestoreDirectory = true;
7952
7953             if (SaveFileDialog1.ShowDialog() == DialogResult.OK)
7954             {
7955                 if (!SaveFileDialog1.ValidateNames) return;
7956                 using (StreamWriter sw = new StreamWriter(SaveFileDialog1.FileName, false, Encoding.UTF8))
7957                 {
7958                     if (rslt == DialogResult.Yes)
7959                     {
7960                         //All
7961                         for (int idx = 0; idx < _curList.VirtualListSize; idx++)
7962                         {
7963                             PostClass post = _statuses[_curTab.Text, idx];
7964                             string protect = "";
7965                             if (post.IsProtect) protect = "Protect";
7966                             sw.WriteLine(post.Nickname + "\t" +
7967                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7968                                      post.CreatedAt.ToString() + "\t" +
7969                                      post.ScreenName + "\t" +
7970                                      post.StatusId.ToString() + "\t" +
7971                                      post.ImageUrl + "\t" +
7972                                      "\"" + post.Text.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7973                                      protect);
7974                         }
7975                     }
7976                     else
7977                     {
7978                         foreach (int idx in _curList.SelectedIndices)
7979                         {
7980                             PostClass post = _statuses[_curTab.Text, idx];
7981                             string protect = "";
7982                             if (post.IsProtect) protect = "Protect";
7983                             sw.WriteLine(post.Nickname + "\t" +
7984                                      "\"" + post.TextFromApi.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7985                                      post.CreatedAt.ToString() + "\t" +
7986                                      post.ScreenName + "\t" +
7987                                      post.StatusId.ToString() + "\t" +
7988                                      post.ImageUrl + "\t" +
7989                                      "\"" + post.Text.Replace("\n", "").Replace("\"", "\"\"") + "\"" + "\t" +
7990                                      protect);
7991                         }
7992                     }
7993                 }
7994             }
7995             this.TopMost = SettingDialog.AlwaysTop;
7996         }
7997
7998         private void PostBrowser_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
7999         {
8000             ModifierState State = GetModifierState(e.Control, e.Shift, e.Alt);
8001             if (State == ModifierState.NotFlags) return;
8002             bool KeyRes = CommonKeyDown(e.KeyCode, FocusedControl.PostBrowser, State);
8003             if (KeyRes)
8004             {
8005                 e.IsInputKey = true;
8006             }
8007         }
8008         public bool TabRename(ref string tabName)
8009         {
8010             //タブ名変更
8011             string newTabText = null;
8012             using (InputTabName inputName = new InputTabName())
8013             {
8014                 inputName.TabName = tabName;
8015                 inputName.ShowDialog();
8016                 if (inputName.DialogResult == DialogResult.Cancel) return false;
8017                 newTabText = inputName.TabName;
8018             }
8019             this.TopMost = SettingDialog.AlwaysTop;
8020             if (!string.IsNullOrEmpty(newTabText))
8021             {
8022                 //新タブ名存在チェック
8023                 for (int i = 0; i < ListTab.TabCount; i++)
8024                 {
8025                     if (ListTab.TabPages[i].Text == newTabText)
8026                     {
8027                         string tmp = string.Format(Properties.Resources.Tabs_DoubleClickText1, newTabText);
8028                         MessageBox.Show(tmp, Properties.Resources.Tabs_DoubleClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
8029                         return false;
8030                     }
8031                 }
8032                 //タブ名のリスト作り直し(デフォルトタブ以外は再作成)
8033                 for (int i = 0; i < ListTab.TabCount; i++)
8034                 {
8035                     if (ListTab.TabPages[i].Text == tabName)
8036                     {
8037                         ListTab.TabPages[i].Text = newTabText;
8038                     }
8039                 }
8040                 _statuses.RenameTab(tabName, newTabText);
8041
8042                 for (int i = 0; i < ListTab.TabCount; i++)
8043                 {
8044                     if (_statuses.IsDistributableTab(ListTab.TabPages[i].Text))
8045                     {
8046                         if (ListTab.TabPages[i].Text == tabName)
8047                         {
8048                             ListTab.TabPages[i].Text = newTabText;
8049                         }
8050                     }
8051                 }
8052                 SaveConfigsCommon();
8053                 SaveConfigsTabs();
8054                 _rclickTabName = newTabText;
8055                 tabName = newTabText;
8056                 return true;
8057             }
8058             else
8059             {
8060                 return false;
8061             }
8062         }
8063
8064         private void ListTab_MouseClick(object sender, MouseEventArgs e)
8065         {
8066             if (e.Button == MouseButtons.Middle)
8067             {
8068                 for (int i = 0; i < this.ListTab.TabPages.Count; i++)
8069                 {
8070                     if (this.ListTab.GetTabRect(i).Contains(e.Location))
8071                     {
8072                         this.RemoveSpecifiedTab(this.ListTab.TabPages[i].Text, true);
8073                         this.SaveConfigsTabs();
8074                         break;
8075                     }
8076                 }
8077             }
8078         }
8079
8080         private void Tabs_DoubleClick(object sender, MouseEventArgs e)
8081         {
8082             string tn = ListTab.SelectedTab.Text;
8083             TabRename(ref tn);
8084         }
8085
8086         private void Tabs_MouseDown(object sender, MouseEventArgs e)
8087         {
8088             if (SettingDialog.TabMouseLock) return;
8089             Point cpos = new Point(e.X, e.Y);
8090             if (e.Button == MouseButtons.Left)
8091             {
8092                 for (int i = 0; i < ListTab.TabPages.Count; i++)
8093                 {
8094                     if (this.ListTab.GetTabRect(i).Contains(e.Location))
8095                     {
8096                         _tabDrag = true;
8097                         _tabMouseDownPoint = e.Location;
8098                         break;
8099                     }
8100                 }
8101             }
8102             else
8103             {
8104                 _tabDrag = false;
8105             }
8106         }
8107
8108         private void Tabs_DragEnter(object sender, DragEventArgs e)
8109         {
8110             if (e.Data.GetDataPresent(typeof(TabPage)))
8111                 e.Effect = DragDropEffects.Move;
8112             else
8113                 e.Effect = DragDropEffects.None;
8114         }
8115
8116         private void Tabs_DragDrop(object sender, DragEventArgs e)
8117         {
8118             if (!e.Data.GetDataPresent(typeof(TabPage))) return;
8119
8120             _tabDrag = false;
8121             string tn = "";
8122             bool bef = false;
8123             Point cpos = new Point(e.X, e.Y);
8124             Point spos = ListTab.PointToClient(cpos);
8125             int i;
8126             for (i = 0; i < ListTab.TabPages.Count; i++)
8127             {
8128                 Rectangle rect = ListTab.GetTabRect(i);
8129                 if (rect.Left <= spos.X && spos.X <= rect.Right &&
8130                     rect.Top <= spos.Y && spos.Y <= rect.Bottom)
8131                 {
8132                     tn = ListTab.TabPages[i].Text;
8133                     if (spos.X <= (rect.Left + rect.Right) / 2)
8134                         bef = true;
8135                     else
8136                         bef = false;
8137
8138                     break;
8139                 }
8140             }
8141
8142             //タブのないところにドロップ->最後尾へ移動
8143             if (string.IsNullOrEmpty(tn))
8144             {
8145                 tn = ListTab.TabPages[ListTab.TabPages.Count - 1].Text;
8146                 bef = false;
8147                 i = ListTab.TabPages.Count - 1;
8148             }
8149
8150             TabPage tp = (TabPage)e.Data.GetData(typeof(TabPage));
8151             if (tp.Text == tn) return;
8152
8153             ReOrderTab(tp.Text, tn, bef);
8154         }
8155
8156         public void ReOrderTab(string targetTabText, string baseTabText, bool isBeforeBaseTab)
8157         {
8158             int baseIndex = 0;
8159             for (baseIndex = 0; baseIndex < ListTab.TabPages.Count; baseIndex++)
8160             {
8161                 if (ListTab.TabPages[baseIndex].Text == baseTabText) break;
8162             }
8163
8164             ListTab.SuspendLayout();
8165
8166             TabPage mTp = null;
8167             for (int j = 0; j < ListTab.TabPages.Count; j++)
8168             {
8169                 if (ListTab.TabPages[j].Text == targetTabText)
8170                 {
8171                     mTp = ListTab.TabPages[j];
8172                     ListTab.TabPages.Remove(mTp);
8173                     if (j < baseIndex) baseIndex -= 1;
8174                     break;
8175                 }
8176             }
8177             if (isBeforeBaseTab)
8178                 ListTab.TabPages.Insert(baseIndex, mTp);
8179             else
8180                 ListTab.TabPages.Insert(baseIndex + 1, mTp);
8181
8182             ListTab.ResumeLayout();
8183
8184             SaveConfigsTabs();
8185         }
8186
8187         private void MakeReplyOrDirectStatus(bool isAuto = true, bool isReply = true, bool isAll = false)
8188         {
8189             //isAuto:true=先頭に挿入、false=カーソル位置に挿入
8190             //isReply:true=@,false=DM
8191             if (!StatusText.Enabled) return;
8192             if (_curList == null) return;
8193             if (_curTab == null) return;
8194             if (!this.ExistCurrentPost) return;
8195
8196             // 複数あてリプライはReplyではなく通常ポスト
8197             //↑仕様変更で全部リプライ扱いでOK(先頭ドット付加しない)
8198             //090403暫定でドットを付加しないようにだけ修正。単独と複数の処理は統合できると思われる。
8199             //090513 all @ replies 廃止の仕様変更によりドット付加に戻し(syo68k)
8200
8201             if (_curList.SelectedIndices.Count > 0)
8202             {
8203                 // アイテムが1件以上選択されている
8204                 if (_curList.SelectedIndices.Count == 1 && !isAll && this.ExistCurrentPost)
8205                 {
8206                     // 単独ユーザー宛リプライまたはDM
8207                     if ((_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage && isAuto) || (!isAuto && !isReply))
8208                     {
8209                         // ダイレクトメッセージ
8210                         StatusText.Text = "D " + _curPost.ScreenName + " " + StatusText.Text;
8211                         StatusText.SelectionStart = StatusText.Text.Length;
8212                         StatusText.Focus();
8213                         _reply_to_id = 0;
8214                         _reply_to_name = "";
8215                         return;
8216                     }
8217                     if (string.IsNullOrEmpty(StatusText.Text))
8218                     {
8219                         //空の場合
8220
8221                         // ステータステキストが入力されていない場合先頭に@ユーザー名を追加する
8222                         StatusText.Text = "@" + _curPost.ScreenName + " ";
8223                         if (_curPost.RetweetedId > 0)
8224                         {
8225                             _reply_to_id = _curPost.RetweetedId;
8226                         }
8227                         else
8228                         {
8229                             _reply_to_id = _curPost.StatusId;
8230                         }
8231                         _reply_to_name = _curPost.ScreenName;
8232                     }
8233                     else
8234                     {
8235                         //何か入力済の場合
8236
8237                         if (isAuto)
8238                         {
8239                             //1件選んでEnter or DoubleClick
8240                             if (StatusText.Text.Contains("@" + _curPost.ScreenName + " "))
8241                             {
8242                                 if (_reply_to_id > 0 && _reply_to_name == _curPost.ScreenName)
8243                                 {
8244                                     //返信先書き換え
8245                                     if (_curPost.RetweetedId > 0)
8246                                     {
8247                                         _reply_to_id = _curPost.RetweetedId;
8248                                     }
8249                                     else
8250                                     {
8251                                         _reply_to_id = _curPost.StatusId;
8252                                     }
8253                                     _reply_to_name = _curPost.ScreenName;
8254                                 }
8255                                 return;
8256                             }
8257                             if (!StatusText.Text.StartsWith("@"))
8258                             {
8259                                 //文頭@以外
8260                                 if (StatusText.Text.StartsWith(". "))
8261                                 {
8262                                     // 複数リプライ
8263                                     StatusText.Text = StatusText.Text.Insert(2, "@" + _curPost.ScreenName + " ");
8264                                     _reply_to_id = 0;
8265                                     _reply_to_name = "";
8266                                 }
8267                                 else
8268                                 {
8269                                     // 単独リプライ
8270                                     StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
8271                                     if (_curPost.RetweetedId > 0)
8272                                     {
8273                                         _reply_to_id = _curPost.RetweetedId;
8274                                     }
8275                                     else
8276                                     {
8277                                         _reply_to_id = _curPost.StatusId;
8278                                     }
8279                                     _reply_to_name = _curPost.ScreenName;
8280                                 }
8281                             }
8282                             else
8283                             {
8284                                 //文頭@
8285                                 // 複数リプライ
8286                                 StatusText.Text = ". @" + _curPost.ScreenName + " " + StatusText.Text;
8287                                 //StatusText.Text = "@" + _curPost.ScreenName + " " + StatusText.Text;
8288                                 _reply_to_id = 0;
8289                                 _reply_to_name = "";
8290                             }
8291                         }
8292                         else
8293                         {
8294                             //1件選んでCtrl-Rの場合(返信先操作せず)
8295                             int sidx = StatusText.SelectionStart;
8296                             string id = "@" + _curPost.ScreenName + " ";
8297                             if (sidx > 0)
8298                             {
8299                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8300                                 {
8301                                     id = " " + id;
8302                                 }
8303                             }
8304                             StatusText.Text = StatusText.Text.Insert(sidx, id);
8305                             sidx += id.Length;
8306                             //if (StatusText.Text.StartsWith("@"))
8307                             //{
8308                             //    //複数リプライ
8309                             //    StatusText.Text = ". " + StatusText.Text.Insert(sidx, " @" + _curPost.ScreenName + " ");
8310                             //    sidx += 5 + _curPost.ScreenName.Length;
8311                             //}
8312                             //else
8313                             //{
8314                             //    // 複数リプライ
8315                             //    StatusText.Text = StatusText.Text.Insert(sidx, " @" + _curPost.ScreenName + " ");
8316                             //    sidx += 3 + _curPost.ScreenName.Length;
8317                             //}
8318                             StatusText.SelectionStart = sidx;
8319                             StatusText.Focus();
8320                             //_reply_to_id = 0;
8321                             //_reply_to_name = null;
8322                             return;
8323                         }
8324                     }
8325                 }
8326                 else
8327                 {
8328                     // 複数リプライ
8329                     if (!isAuto && !isReply) return;
8330
8331                     //C-S-rか、複数の宛先を選択中にEnter/DoubleClick/C-r/C-S-r
8332
8333                     if (isAuto)
8334                     {
8335                         //Enter or DoubleClick
8336
8337                         string sTxt = StatusText.Text;
8338                         if (!sTxt.StartsWith(". "))
8339                         {
8340                             sTxt = ". " + sTxt;
8341                             _reply_to_id = 0;
8342                             _reply_to_name = "";
8343                         }
8344                         for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
8345                         {
8346                             PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[cnt]];
8347                             if (!sTxt.Contains("@" + post.ScreenName + " "))
8348                             {
8349                                 sTxt = sTxt.Insert(2, "@" + post.ScreenName + " ");
8350                                 //sTxt = "@" + post.ScreenName + " " + sTxt;
8351                             }
8352                         }
8353                         StatusText.Text = sTxt;
8354                     }
8355                     else
8356                     {
8357                         //C-S-r or C-r
8358                         if (_curList.SelectedIndices.Count > 1)
8359                         {
8360                             //複数ポスト選択
8361
8362                             string ids = "";
8363                             int sidx = StatusText.SelectionStart;
8364                             for (int cnt = 0; cnt < _curList.SelectedIndices.Count; cnt++)
8365                             {
8366                                 PostClass post = _statuses[_curTab.Text, _curList.SelectedIndices[cnt]];
8367                                 if (!ids.Contains("@" + post.ScreenName + " ") &&
8368                                     !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8369                                 {
8370                                     ids += "@" + post.ScreenName + " ";
8371                                 }
8372                                 if (isAll)
8373                                 {
8374                                     foreach (string nm in post.ReplyToList)
8375                                     {
8376                                         if (!ids.Contains("@" + nm + " ") &&
8377                                             !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8378                                         {
8379                                             Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
8380                                             if (m.Success)
8381                                                 ids += "@" + m.Result("${id}") + " ";
8382                                             else
8383                                                 ids += "@" + nm + " ";
8384                                         }
8385                                     }
8386                                 }
8387                             }
8388                             if (ids.Length == 0) return;
8389                             if (!StatusText.Text.StartsWith(". "))
8390                             {
8391                                 StatusText.Text = ". " + StatusText.Text;
8392                                 sidx += 2;
8393                                 _reply_to_id = 0;
8394                                 _reply_to_name = "";
8395                             }
8396                             if (sidx > 0)
8397                             {
8398                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8399                                 {
8400                                     ids = " " + ids;
8401                                 }
8402                             }
8403                             StatusText.Text = StatusText.Text.Insert(sidx, ids);
8404                             sidx += ids.Length;
8405                             //if (StatusText.Text.StartsWith("@"))
8406                             //{
8407                             //    StatusText.Text = ". " + StatusText.Text.Insert(sidx, ids);
8408                             //    sidx += 2 + ids.Length;
8409                             //}
8410                             //else
8411                             //{
8412                             //    StatusText.Text = StatusText.Text.Insert(sidx, ids);
8413                             //    sidx += 1 + ids.Length;
8414                             //}
8415                             StatusText.SelectionStart = sidx;
8416                             StatusText.Focus();
8417                             return;
8418                         }
8419                         else
8420                         {
8421                             //1件のみ選択のC-S-r(返信元付加する可能性あり)
8422
8423                             string ids = "";
8424                             int sidx = StatusText.SelectionStart;
8425                             PostClass post = _curPost;
8426                             if (!ids.Contains("@" + post.ScreenName + " ") &&
8427                                 !post.ScreenName.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8428                             {
8429                                 ids += "@" + post.ScreenName + " ";
8430                             }
8431                             foreach (string nm in post.ReplyToList)
8432                             {
8433                                 if (!ids.Contains("@" + nm + " ") &&
8434                                     !nm.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8435                                 {
8436                                     Match m = Regex.Match(post.TextFromApi, "[@@](?<id>" + nm + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase);
8437                                     if (m.Success)
8438                                         ids += "@" + m.Result("${id}") + " ";
8439                                     else
8440                                         ids += "@" + nm + " ";
8441                                 }
8442                             }
8443                             if (!string.IsNullOrEmpty(post.RetweetedBy))
8444                             {
8445                                 if (!ids.Contains("@" + post.RetweetedBy + " ") &&
8446                                    !post.RetweetedBy.Equals(tw.Username, StringComparison.CurrentCultureIgnoreCase))
8447                                 {
8448                                     ids += "@" + post.RetweetedBy + " ";
8449                                 }
8450                             }
8451                             if (ids.Length == 0) return;
8452                             if (string.IsNullOrEmpty(StatusText.Text))
8453                             {
8454                                 //未入力の場合のみ返信先付加
8455                                 StatusText.Text = ids;
8456                                 StatusText.SelectionStart = ids.Length;
8457                                 StatusText.Focus();
8458                                 if (post.RetweetedId > 0)
8459                                 {
8460                                     _reply_to_id = post.RetweetedId;
8461                                 }
8462                                 else
8463                                 {
8464                                     _reply_to_id = post.StatusId;
8465                                 }
8466                                 _reply_to_name = post.ScreenName;
8467                                 return;
8468                             }
8469
8470                             if (sidx > 0)
8471                             {
8472                                 if (StatusText.Text.Substring(sidx - 1, 1) != " ")
8473                                 {
8474                                     ids = " " + ids;
8475                                 }
8476                             }
8477                             StatusText.Text = StatusText.Text.Insert(sidx, ids);
8478                             sidx += ids.Length;
8479                             StatusText.SelectionStart = sidx;
8480                             StatusText.Focus();
8481                             return;
8482                         }
8483                     }
8484                 }
8485                 StatusText.SelectionStart = StatusText.Text.Length;
8486                 StatusText.Focus();
8487             }
8488         }
8489
8490         private void ListTab_MouseUp(object sender, MouseEventArgs e)
8491         {
8492             _tabDrag = false;
8493         }
8494
8495         private static int iconCnt = 0;
8496         private static int blinkCnt = 0;
8497         private static bool blink = false;
8498         private static bool idle = false;
8499
8500         private void RefreshTasktrayIcon(bool forceRefresh)
8501         {
8502             if (_colorize) Colorize();
8503             if (!TimerRefreshIcon.Enabled) return;
8504             //Static usCheckCnt As int = 0
8505
8506             //Static iconDlListTopItem As ListViewItem = null
8507
8508             if (forceRefresh) idle = false;
8509
8510             //if (((ListView)ListTab.SelectedTab.Tag).TopItem == iconDlListTopItem)
8511             //    ((ImageDictionary)this.TIconDic).PauseGetImage = false;
8512             //else
8513             //    ((ImageDictionary)this.TIconDic).PauseGetImage = true;
8514             //
8515             //iconDlListTopItem = ((ListView)ListTab.SelectedTab.Tag).TopItem;
8516
8517             iconCnt += 1;
8518             blinkCnt += 1;
8519             //usCheckCnt += 1;
8520
8521             //if (usCheckCnt > 300)    //1min
8522             //{
8523             //    usCheckCnt = 0;
8524             //    if (!this.IsReceivedUserStream)
8525             //    {
8526             //        TraceOut("ReconnectUserStream");
8527             //        tw.ReconnectUserStream();
8528             //    }
8529             //}
8530
8531             bool busy = false;
8532             foreach (BackgroundWorker bw in this._bw)
8533             {
8534                 if (bw != null && bw.IsBusy)
8535                 {
8536                     busy = true;
8537                     break;
8538                 }
8539             }
8540
8541             if (iconCnt > 3)
8542             {
8543                 iconCnt = 0;
8544             }
8545             if (blinkCnt > 10)
8546             {
8547                 blinkCnt = 0;
8548                 //未保存の変更を保存
8549                 SaveConfigsAll(true);
8550             }
8551
8552             if (busy)
8553             {
8554                 NotifyIcon1.Icon = NIconRefresh[iconCnt];
8555                 idle = false;
8556                 _myStatusError = false;
8557                 return;
8558             }
8559
8560             TabClass tb = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
8561             if (SettingDialog.ReplyIconState != MyCommon.REPLY_ICONSTATE.None && tb != null && tb.UnreadCount > 0)
8562             {
8563                 if (blinkCnt > 0) return;
8564                 blink = !blink;
8565                 if (blink || SettingDialog.ReplyIconState == MyCommon.REPLY_ICONSTATE.StaticIcon)
8566                 {
8567                     NotifyIcon1.Icon = ReplyIcon;
8568                 }
8569                 else
8570                 {
8571                     NotifyIcon1.Icon = ReplyIconBlink;
8572                 }
8573                 idle = false;
8574                 return;
8575             }
8576
8577             if (idle) return;
8578             idle = true;
8579             //優先度:エラー→オフライン→アイドル
8580             //エラーは更新アイコンでクリアされる
8581             if (_myStatusError)
8582             {
8583                 NotifyIcon1.Icon = NIconAtRed;
8584                 return;
8585             }
8586             if (_myStatusOnline)
8587             {
8588                 NotifyIcon1.Icon = NIconAt;
8589             }
8590             else
8591             {
8592                 NotifyIcon1.Icon = NIconAtSmoke;
8593             }
8594         }
8595
8596         private void TimerRefreshIcon_Tick(object sender, EventArgs e)
8597         {
8598             //200ms
8599             this.RefreshTasktrayIcon(false);
8600         }
8601
8602         private void ContextMenuTabProperty_Opening(object sender, CancelEventArgs e)
8603         {
8604             //右クリックの場合はタブ名が設定済。アプリケーションキーの場合は現在のタブを対象とする
8605             if (string.IsNullOrEmpty(_rclickTabName) || sender != ContextMenuTabProperty)
8606             {
8607                 if (ListTab != null && ListTab.SelectedTab != null)
8608                     _rclickTabName = ListTab.SelectedTab.Text;
8609                 else
8610                     return;
8611             }
8612
8613             if (_statuses == null) return;
8614             if (_statuses.Tabs == null) return;
8615
8616             TabClass tb = _statuses.Tabs[_rclickTabName];
8617             if (tb == null) return;
8618
8619             NotifyDispMenuItem.Checked = tb.Notify;
8620             this.NotifyTbMenuItem.Checked = tb.Notify;
8621
8622             soundfileListup = true;
8623             SoundFileComboBox.Items.Clear();
8624             this.SoundFileTbComboBox.Items.Clear();
8625             SoundFileComboBox.Items.Add("");
8626             this.SoundFileTbComboBox.Items.Add("");
8627             DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
8628             if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
8629             {
8630                 oDir = oDir.GetDirectories("Sounds")[0];
8631             }
8632             foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
8633             {
8634                 SoundFileComboBox.Items.Add(oFile.Name);
8635                 this.SoundFileTbComboBox.Items.Add(oFile.Name);
8636             }
8637             int idx = SoundFileComboBox.Items.IndexOf(tb.SoundFile);
8638             if (idx == -1) idx = 0;
8639             SoundFileComboBox.SelectedIndex = idx;
8640             this.SoundFileTbComboBox.SelectedIndex = idx;
8641             soundfileListup = false;
8642             UreadManageMenuItem.Checked = tb.UnreadManage;
8643             this.UnreadMngTbMenuItem.Checked = tb.UnreadManage;
8644
8645             TabMenuControl(_rclickTabName);
8646         }
8647
8648         private void TabMenuControl(string tabName)
8649         {
8650             this.FilterEditMenuItem.Enabled = true;
8651             this.EditRuleTbMenuItem.Enabled = true;
8652
8653             if (_statuses.IsDefaultTab(tabName))
8654             {
8655                 this.ProtectTabMenuItem.Enabled = false;
8656                 this.ProtectTbMenuItem.Enabled = false;
8657             }
8658             else
8659             {
8660                 this.ProtectTabMenuItem.Enabled = true;
8661                 this.ProtectTbMenuItem.Enabled = true;
8662             }
8663
8664             if (_statuses.IsDefaultTab(tabName) || _statuses.Tabs[tabName].Protected)
8665             {
8666                 this.ProtectTabMenuItem.Checked = true;
8667                 this.ProtectTbMenuItem.Checked = true;
8668                 this.DeleteTabMenuItem.Enabled = false;
8669                 this.DeleteTbMenuItem.Enabled = false;
8670             }
8671             else
8672             {
8673                 this.ProtectTabMenuItem.Checked = false;
8674                 this.ProtectTbMenuItem.Checked = false;
8675                 this.DeleteTabMenuItem.Enabled = true;
8676                 this.DeleteTbMenuItem.Enabled = true;
8677             }
8678         }
8679
8680         private void ProtectTabMenuItem_Click(object sender, EventArgs e)
8681         {
8682             var checkState = ((ToolStripMenuItem)sender).Checked;
8683
8684             // チェック状態を同期
8685             this.ProtectTbMenuItem.Checked = checkState;
8686             this.ProtectTabMenuItem.Checked = checkState;
8687
8688             // ロック中はタブの削除を無効化
8689             this.DeleteTabMenuItem.Enabled = !checkState;
8690             this.DeleteTbMenuItem.Enabled = !checkState;
8691
8692             if (string.IsNullOrEmpty(_rclickTabName)) return;
8693             _statuses.Tabs[_rclickTabName].Protected = checkState;
8694
8695             SaveConfigsTabs();
8696         }
8697
8698         private void UreadManageMenuItem_Click(object sender, EventArgs e)
8699         {
8700             UreadManageMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
8701             this.UnreadMngTbMenuItem.Checked = UreadManageMenuItem.Checked;
8702
8703             if (string.IsNullOrEmpty(_rclickTabName)) return;
8704             ChangeTabUnreadManage(_rclickTabName, UreadManageMenuItem.Checked);
8705
8706             SaveConfigsTabs();
8707         }
8708
8709         public void ChangeTabUnreadManage(string tabName, bool isManage)
8710         {
8711             int idx;
8712             for (idx = 0; idx < ListTab.TabCount; idx++)
8713             {
8714                 if (ListTab.TabPages[idx].Text == tabName) break;
8715             }
8716
8717             _statuses.SetTabUnreadManage(tabName, isManage);
8718             if (SettingDialog.TabIconDisp)
8719             {
8720                 if (_statuses.Tabs[tabName].UnreadCount > 0)
8721                     ListTab.TabPages[idx].ImageIndex = 0;
8722                 else
8723                     ListTab.TabPages[idx].ImageIndex = -1;
8724             }
8725
8726             if (_curTab.Text == tabName)
8727             {
8728                 _itemCache = null;
8729                 _postCache = null;
8730                 _curList.Refresh();
8731             }
8732
8733             SetMainWindowTitle();
8734             SetStatusLabelUrl();
8735             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8736         }
8737
8738         private void NotifyDispMenuItem_Click(object sender, EventArgs e)
8739         {
8740             NotifyDispMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
8741             this.NotifyTbMenuItem.Checked = NotifyDispMenuItem.Checked;
8742
8743             if (string.IsNullOrEmpty(_rclickTabName)) return;
8744
8745             _statuses.Tabs[_rclickTabName].Notify = NotifyDispMenuItem.Checked;
8746
8747             SaveConfigsTabs();
8748         }
8749
8750         private void SoundFileComboBox_SelectedIndexChanged(object sender, EventArgs e)
8751         {
8752             if (soundfileListup || string.IsNullOrEmpty(_rclickTabName)) return;
8753
8754             _statuses.Tabs[_rclickTabName].SoundFile = (string)((ToolStripComboBox)sender).SelectedItem;
8755
8756             SaveConfigsTabs();
8757         }
8758
8759         private void DeleteTabMenuItem_Click(object sender, EventArgs e)
8760         {
8761             if (string.IsNullOrEmpty(_rclickTabName) || sender == this.DeleteTbMenuItem) _rclickTabName = ListTab.SelectedTab.Text;
8762
8763             RemoveSpecifiedTab(_rclickTabName, true);
8764             SaveConfigsTabs();
8765         }
8766
8767         private void FilterEditMenuItem_Click(object sender, EventArgs e)
8768         {
8769             if (string.IsNullOrEmpty(_rclickTabName)) _rclickTabName = _statuses.GetTabByType(MyCommon.TabUsageType.Home).TabName;
8770             fltDialog.SetCurrent(_rclickTabName);
8771             fltDialog.ShowDialog(this);
8772             this.TopMost = SettingDialog.AlwaysTop;
8773
8774             try
8775             {
8776                 this.Cursor = Cursors.WaitCursor;
8777                 _itemCache = null;
8778                 _postCache = null;
8779                 _curPost = null;
8780                 _curItemIndex = -1;
8781                 _statuses.FilterAll();
8782                 foreach (TabPage tb in ListTab.TabPages)
8783                 {
8784                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
8785                     if (_statuses.Tabs[tb.Text].UnreadCount > 0)
8786                     {
8787                         if (SettingDialog.TabIconDisp)
8788                             tb.ImageIndex = 0;
8789                     }
8790                     else
8791                     {
8792                         if (SettingDialog.TabIconDisp)
8793                             tb.ImageIndex = -1;
8794                     }
8795                 }
8796                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8797             }
8798             finally
8799             {
8800                 this.Cursor = Cursors.Default;
8801             }
8802             SaveConfigsTabs();
8803         }
8804
8805         private void AddTabMenuItem_Click(object sender, EventArgs e)
8806         {
8807             string tabName = null;
8808             MyCommon.TabUsageType tabUsage;
8809             using (InputTabName inputName = new InputTabName())
8810             {
8811                 inputName.TabName = _statuses.GetUniqueTabName();
8812                 inputName.IsShowUsage = true;
8813                 inputName.ShowDialog();
8814                 if (inputName.DialogResult == DialogResult.Cancel) return;
8815                 tabName = inputName.TabName;
8816                 tabUsage = inputName.Usage;
8817             }
8818             this.TopMost = SettingDialog.AlwaysTop;
8819             if (!string.IsNullOrEmpty(tabName))
8820             {
8821                 //List対応
8822                 ListElement list = null;
8823                 if (tabUsage == MyCommon.TabUsageType.Lists)
8824                 {
8825                     using (ListAvailable listAvail = new ListAvailable())
8826                     {
8827                         if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
8828                         if (listAvail.SelectedList == null) return;
8829                         list = listAvail.SelectedList;
8830                     }
8831                 }
8832                 if (!_statuses.AddTab(tabName, tabUsage, list) || !AddNewTab(tabName, false, tabUsage, list))
8833                 {
8834                     string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
8835                     MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
8836                 }
8837                 else
8838                 {
8839                     //成功
8840                     SaveConfigsTabs();
8841                     if (tabUsage == MyCommon.TabUsageType.PublicSearch)
8842                     {
8843                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
8844                         ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
8845                         ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
8846                     }
8847                     if (tabUsage == MyCommon.TabUsageType.Lists)
8848                     {
8849                         ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
8850                         ListTabSelect(ListTab.TabPages[ListTab.TabPages.Count - 1]);
8851                         GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, tabName);
8852                     }
8853                 }
8854             }
8855         }
8856
8857         private void TabMenuItem_Click(object sender, EventArgs e)
8858         {
8859             //選択発言を元にフィルタ追加
8860             foreach (int idx in _curList.SelectedIndices)
8861             {
8862                 string tabName;
8863                 //タブ選択(or追加)
8864                 if (!SelectTab(out tabName)) return;
8865
8866                 fltDialog.SetCurrent(tabName);
8867                 if (_statuses[_curTab.Text, idx].RetweetedId == 0)
8868                 {
8869                     fltDialog.AddNewFilter(_statuses[_curTab.Text, idx].ScreenName, _statuses[_curTab.Text, idx].TextFromApi);
8870                 }
8871                 else
8872                 {
8873                     fltDialog.AddNewFilter(_statuses[_curTab.Text, idx].RetweetedBy, _statuses[_curTab.Text, idx].TextFromApi);
8874                 }
8875                 fltDialog.ShowDialog(this);
8876                 this.TopMost = SettingDialog.AlwaysTop;
8877             }
8878
8879             try
8880             {
8881                 this.Cursor = Cursors.WaitCursor;
8882                 _itemCache = null;
8883                 _postCache = null;
8884                 _curPost = null;
8885                 _curItemIndex = -1;
8886                 _statuses.FilterAll();
8887                 foreach (TabPage tb in ListTab.TabPages)
8888                 {
8889                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
8890                     if (_statuses.Tabs[tb.Text].UnreadCount > 0)
8891                     {
8892                         if (SettingDialog.TabIconDisp)
8893                             tb.ImageIndex = 0;
8894                     }
8895                     else
8896                     {
8897                         if (SettingDialog.TabIconDisp)
8898                             tb.ImageIndex = -1;
8899                     }
8900                 }
8901                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
8902             }
8903             finally
8904             {
8905                 this.Cursor = Cursors.Default;
8906             }
8907             SaveConfigsTabs();
8908             if (this.ListTab.SelectedTab != null &&
8909                 ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices.Count > 0)
8910             {
8911                 _curPost = _statuses[this.ListTab.SelectedTab.Text, ((DetailsListView)this.ListTab.SelectedTab.Tag).SelectedIndices[0]];
8912             }
8913         }
8914
8915         protected override bool ProcessDialogKey(Keys keyData)
8916         {
8917             //TextBox1でEnterを押してもビープ音が鳴らないようにする
8918             if ((keyData & Keys.KeyCode) == Keys.Enter)
8919             {
8920                 if (StatusText.Focused)
8921                 {
8922                     bool _NewLine = false;
8923                     bool _Post = false;
8924
8925                     if (SettingDialog.PostCtrlEnter) //Ctrl+Enter投稿時
8926                     {
8927                         if (StatusText.Multiline)
8928                         {
8929                             if ((keyData & Keys.Shift) == Keys.Shift && (keyData & Keys.Control) != Keys.Control) _NewLine = true;
8930
8931                             if ((keyData & Keys.Control) == Keys.Control) _Post = true;
8932                         }
8933                         else
8934                         {
8935                             if (((keyData & Keys.Control) == Keys.Control)) _Post = true;
8936                         }
8937
8938                     }
8939                     else if (SettingDialog.PostShiftEnter) //SHift+Enter投稿時
8940                     {
8941                         if (StatusText.Multiline)
8942                         {
8943                             if ((keyData & Keys.Control) == Keys.Control && (keyData & Keys.Shift) != Keys.Shift) _NewLine = true;
8944
8945                             if ((keyData & Keys.Shift) == Keys.Shift) _Post = true;
8946                         }
8947                         else
8948                         {
8949                             if (((keyData & Keys.Shift) == Keys.Shift)) _Post = true;
8950                         }
8951
8952                     }
8953                     else //Enter投稿時
8954                     {
8955                         if (StatusText.Multiline)
8956                         {
8957                             if ((keyData & Keys.Shift) == Keys.Shift && (keyData & Keys.Control) != Keys.Control) _NewLine = true;
8958
8959                             if (((keyData & Keys.Control) != Keys.Control && (keyData & Keys.Shift) != Keys.Shift) ||
8960                                 ((keyData & Keys.Control) == Keys.Control && (keyData & Keys.Shift) == Keys.Shift)) _Post = true;
8961                         }
8962                         else
8963                         {
8964                             if (((keyData & Keys.Shift) == Keys.Shift) ||
8965                                 (((keyData & Keys.Control) != Keys.Control) &&
8966                                 ((keyData & Keys.Shift) != Keys.Shift))) _Post = true;
8967                         }
8968                     }
8969
8970                     if (_NewLine)
8971                     {
8972                         int pos1 = StatusText.SelectionStart;
8973                         if (StatusText.SelectionLength > 0)
8974                         {
8975                             StatusText.Text = StatusText.Text.Remove(pos1, StatusText.SelectionLength);  //選択状態文字列削除
8976                         }
8977                         StatusText.Text = StatusText.Text.Insert(pos1, Environment.NewLine);  //改行挿入
8978                         StatusText.SelectionStart = pos1 + Environment.NewLine.Length;    //カーソルを改行の次の文字へ移動
8979                         return true;
8980                     }
8981                     else if (_Post)
8982                     {
8983                         PostButton_Click(null, null);
8984                         return true;
8985                     }
8986                 }
8987                 else if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch &&
8988                          (ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focused ||
8989                          ListTab.SelectedTab.Controls["panelSearch"].Controls["comboLang"].Focused))
8990                 {
8991                     this.SearchButton_Click(ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"], null);
8992                     return true;
8993                 }
8994             }
8995
8996             return base.ProcessDialogKey(keyData);
8997         }
8998
8999         private void ReplyAllStripMenuItem_Click(object sender, EventArgs e)
9000         {
9001             MakeReplyOrDirectStatus(false, true, true);
9002         }
9003
9004         private void IDRuleMenuItem_Click(object sender, EventArgs e)
9005         {
9006             string tabName;
9007
9008             //未選択なら処理終了
9009             if (_curList.SelectedIndices.Count == 0) return;
9010
9011             //タブ選択(or追加)
9012             if (!SelectTab(out tabName)) return;
9013
9014             bool mv = false;
9015             bool mk = false;
9016             MoveOrCopy(ref mv, ref mk);
9017
9018             List<string> ids = new List<string>();
9019             foreach (int idx in _curList.SelectedIndices)
9020             {
9021                 PostClass post = _statuses[_curTab.Text, idx];
9022                 if (!ids.Contains(post.ScreenName))
9023                 {
9024                     FiltersClass fc = new FiltersClass();
9025                     ids.Add(post.ScreenName);
9026                     if (post.RetweetedId == 0)
9027                     {
9028                         fc.NameFilter = post.ScreenName;
9029                     }
9030                     else
9031                     {
9032                         fc.NameFilter = post.RetweetedBy;
9033                     }
9034                     fc.SearchBoth = true;
9035                     fc.MoveFrom = mv;
9036                     fc.SetMark = mk;
9037                     fc.UseRegex = false;
9038                     fc.SearchUrl = false;
9039                     _statuses.Tabs[tabName].AddFilter(fc);
9040                 }
9041             }
9042             if (ids.Count != 0)
9043             {
9044                 List<string> atids = new List<string>();
9045                 foreach (string id in ids)
9046                 {
9047                     atids.Add("@" + id);
9048                 }
9049                 int cnt = AtIdSupl.ItemCount;
9050                 AtIdSupl.AddRangeItem(atids.ToArray());
9051                 if (AtIdSupl.ItemCount != cnt) _modifySettingAtId = true;
9052             }
9053
9054             try
9055             {
9056                 this.Cursor = Cursors.WaitCursor;
9057                 _itemCache = null;
9058                 _postCache = null;
9059                 _curPost = null;
9060                 _curItemIndex = -1;
9061                 _statuses.FilterAll();
9062                 foreach (TabPage tb in ListTab.TabPages)
9063                 {
9064                     ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
9065                     if (_statuses.ContainsTab(tb.Text))
9066                     {
9067                         if (_statuses.Tabs[tb.Text].UnreadCount > 0)
9068                         {
9069                             if (SettingDialog.TabIconDisp)
9070                                 tb.ImageIndex = 0;
9071                         }
9072                         else
9073                         {
9074                             if (SettingDialog.TabIconDisp)
9075                                 tb.ImageIndex = -1;
9076                         }
9077                     }
9078                 }
9079                 if (!SettingDialog.TabIconDisp) ListTab.Refresh();
9080             }
9081             finally
9082             {
9083                 this.Cursor = Cursors.Default;
9084             }
9085             SaveConfigsTabs();
9086         }
9087
9088         private bool SelectTab(out string tabName)
9089         {
9090             do
9091             {
9092                 tabName = null;
9093
9094                 //振り分け先タブ選択
9095                 using (var dialog = new TabsDialog(_statuses))
9096                 {
9097                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return false;
9098
9099                     var selectedTab = dialog.SelectedTab;
9100                     tabName = selectedTab == null ? null : selectedTab.TabName;
9101                 }
9102
9103                 ListTab.SelectedTab.Focus();
9104                 //新規タブを選択→タブ作成
9105                 if (tabName == null)
9106                 {
9107                     using (InputTabName inputName = new InputTabName())
9108                     {
9109                         inputName.TabName = _statuses.GetUniqueTabName();
9110                         inputName.ShowDialog();
9111                         if (inputName.DialogResult == DialogResult.Cancel) return false;
9112                         tabName = inputName.TabName;
9113                     }
9114                     this.TopMost = SettingDialog.AlwaysTop;
9115                     if (!string.IsNullOrEmpty(tabName))
9116                     {
9117                         if (!_statuses.AddTab(tabName, MyCommon.TabUsageType.UserDefined, null) || !AddNewTab(tabName, false, MyCommon.TabUsageType.UserDefined))
9118                         {
9119                             string tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText2, tabName);
9120                             MessageBox.Show(tmp, Properties.Resources.IDRuleMenuItem_ClickText3, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
9121                             //もう一度タブ名入力
9122                         }
9123                         else
9124                         {
9125                             return true;
9126                         }
9127                     }
9128                 }
9129                 else
9130                 {
9131                     //既存タブを選択
9132                     return true;
9133                 }
9134             }
9135             while (true);
9136         }
9137
9138         private void MoveOrCopy(ref bool move, ref bool mark)
9139         {
9140             {
9141                 //移動するか?
9142                 string _tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText4, Environment.NewLine);
9143                 if (MessageBox.Show(_tmp, Properties.Resources.IDRuleMenuItem_ClickText5, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
9144                     move = false;
9145                 else
9146                     move = true;
9147             }
9148             if (!move)
9149             {
9150                 //マークするか?
9151                 string _tmp = string.Format(Properties.Resources.IDRuleMenuItem_ClickText6, Environment.NewLine);
9152                 if (MessageBox.Show(_tmp, Properties.Resources.IDRuleMenuItem_ClickText7, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
9153                     mark = true;
9154                 else
9155                     mark = false;
9156             }
9157         }
9158         private void CopySTOTMenuItem_Click(object sender, EventArgs e)
9159         {
9160             this.CopyStot();
9161         }
9162
9163         private void CopyURLMenuItem_Click(object sender, EventArgs e)
9164         {
9165             this.CopyIdUri();
9166         }
9167
9168         private void SelectAllMenuItem_Click(object sender, EventArgs e)
9169         {
9170             if (StatusText.Focused)
9171             {
9172                 // 発言欄でのCtrl+A
9173                 StatusText.SelectAll();
9174             }
9175             else
9176             {
9177                 // ListView上でのCtrl+A
9178                 for (int i = 0; i < _curList.VirtualListSize; i++)
9179                 {
9180                     _curList.SelectedIndices.Add(i);
9181                 }
9182             }
9183         }
9184
9185         private void MoveMiddle()
9186         {
9187             ListViewItem _item;
9188             int idx1;
9189             int idx2;
9190
9191             if (_curList.SelectedIndices.Count == 0) return;
9192
9193             int idx = _curList.SelectedIndices[0];
9194
9195             _item = _curList.GetItemAt(0, 25);
9196             if (_item == null)
9197                 idx1 = 0;
9198             else
9199                 idx1 = _item.Index;
9200
9201             _item = _curList.GetItemAt(0, _curList.ClientSize.Height - 1);
9202             if (_item == null)
9203                 idx2 = _curList.VirtualListSize - 1;
9204             else
9205                 idx2 = _item.Index;
9206
9207             idx -= Math.Abs(idx1 - idx2) / 2;
9208             if (idx < 0) idx = 0;
9209
9210             _curList.EnsureVisible(_curList.VirtualListSize - 1);
9211             _curList.EnsureVisible(idx);
9212         }
9213
9214         private void OpenURLMenuItem_Click(object sender, EventArgs e)
9215         {
9216             if (PostBrowser.Document.Links.Count > 0)
9217             {
9218                 UrlDialog.ClearUrl();
9219
9220                 string openUrlStr = "";
9221
9222                 if (PostBrowser.Document.Links.Count == 1)
9223                 {
9224                     string urlStr = "";
9225                     try
9226                     {
9227                         urlStr = MyCommon.IDNDecode(PostBrowser.Document.Links[0].GetAttribute("href"));
9228                     }
9229                     catch (ArgumentException)
9230                     {
9231                         //変なHTML?
9232                         return;
9233                     }
9234                     catch (Exception)
9235                     {
9236                         return;
9237                     }
9238                     if (string.IsNullOrEmpty(urlStr)) return;
9239                     openUrlStr = MyCommon.urlEncodeMultibyteChar(urlStr);
9240                 }
9241                 else
9242                 {
9243                     foreach (HtmlElement linkElm in PostBrowser.Document.Links)
9244                     {
9245                         string urlStr = "";
9246                         string linkText = "";
9247                         string href = "";
9248                         try
9249                         {
9250                             urlStr = linkElm.GetAttribute("title");
9251                             href = MyCommon.IDNDecode(linkElm.GetAttribute("href"));
9252                             if (string.IsNullOrEmpty(urlStr)) urlStr = href;
9253                             linkText = linkElm.InnerText;
9254                             if (!linkText.StartsWith("http") && !linkText.StartsWith("#") && !linkText.Contains("."))
9255                             {
9256                                 linkText = "@" + linkText;
9257                             }
9258                         }
9259                         catch (ArgumentException)
9260                         {
9261                             //変なHTML?
9262                             return;
9263                         }
9264                         catch (Exception)
9265                         {
9266                             return;
9267                         }
9268                         if (string.IsNullOrEmpty(urlStr)) continue;
9269                         UrlDialog.AddUrl(new OpenUrlItem(linkText, MyCommon.urlEncodeMultibyteChar(urlStr), href));
9270                     }
9271                     try
9272                     {
9273                         if (UrlDialog.ShowDialog() == DialogResult.OK)
9274                         {
9275                             openUrlStr = UrlDialog.SelectedUrl;
9276                         }
9277                     }
9278                     catch (Exception)
9279                     {
9280                         return;
9281                     }
9282                     this.TopMost = SettingDialog.AlwaysTop;
9283                 }
9284                 if (string.IsNullOrEmpty(openUrlStr)) return;
9285
9286                 if (openUrlStr.StartsWith("http://twitter.com/search?q=") ||
9287                     openUrlStr.StartsWith("https://twitter.com/search?q="))
9288                 {
9289                     //ハッシュタグの場合は、タブで開く
9290                     string urlStr = HttpUtility.UrlDecode(openUrlStr);
9291                     string hash = urlStr.Substring(urlStr.IndexOf("#"));
9292                     HashSupl.AddItem(hash);
9293                     HashMgr.AddHashToHistory(hash.Trim(), false);
9294                     AddNewTabForSearch(hash);
9295                     return;
9296                 }
9297                 else
9298                 {
9299                     Match m = Regex.Match(openUrlStr, "^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)$");
9300                     if (SettingDialog.OpenUserTimeline && m.Success && IsTwitterId(m.Result("${ScreenName}")))
9301                         this.AddNewTabForUserTimeline(m.Result("${ScreenName}"));
9302                     else
9303                         OpenUriAsync(openUrlStr);
9304                     return;
9305                 }
9306             }
9307         }
9308
9309         private void ClearTabMenuItem_Click(object sender, EventArgs e)
9310         {
9311             if (string.IsNullOrEmpty(_rclickTabName)) return;
9312             ClearTab(_rclickTabName, true);
9313         }
9314
9315         private void ClearTab(string tabName, bool showWarning)
9316         {
9317             if (showWarning)
9318             {
9319                 string tmp = string.Format(Properties.Resources.ClearTabMenuItem_ClickText1, Environment.NewLine);
9320                 if (MessageBox.Show(tmp, tabName + " " + Properties.Resources.ClearTabMenuItem_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
9321                 {
9322                     return;
9323                 }
9324             }
9325
9326             _statuses.ClearTabIds(tabName);
9327             if (ListTab.SelectedTab.Text == tabName)
9328             {
9329                 _anchorPost = null;
9330                 _anchorFlag = false;
9331                 _itemCache = null;
9332                 _postCache = null;
9333                 _itemCacheIndex = -1;
9334                 _curItemIndex = -1;
9335                 _curPost = null;
9336             }
9337             foreach (TabPage tb in ListTab.TabPages)
9338             {
9339                 if (tb.Text == tabName)
9340                 {
9341                     tb.ImageIndex = -1;
9342                     ((DetailsListView)tb.Tag).VirtualListSize = 0;
9343                     break;
9344                 }
9345             }
9346             if (!SettingDialog.TabIconDisp) ListTab.Refresh();
9347
9348             SetMainWindowTitle();
9349             SetStatusLabelUrl();
9350         }
9351
9352         private static long followers = 0;
9353
9354         private void SetMainWindowTitle()
9355         {
9356             //メインウインドウタイトルの書き換え
9357             StringBuilder ttl = new StringBuilder(256);
9358             int ur = 0;
9359             int al = 0;
9360             if (SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.None &&
9361                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Post &&
9362                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.Ver &&
9363                 SettingDialog.DispLatestPost != MyCommon.DispTitleEnum.OwnStatus)
9364             {
9365                 foreach (string key in _statuses.Tabs.Keys)
9366                 {
9367                     ur += _statuses.Tabs[key].UnreadCount;
9368                     al += _statuses.Tabs[key].AllCount;
9369                 }
9370             }
9371
9372             if (SettingDialog.DispUsername) ttl.Append(tw.Username).Append(" - ");
9373             ttl.Append(Application.ProductName);
9374             ttl.Append("  ");
9375             switch (SettingDialog.DispLatestPost)
9376             {
9377                 case MyCommon.DispTitleEnum.Ver:
9378                     ttl.Append("Ver:").Append(MyCommon.GetReadableVersion());
9379                     break;
9380                 case MyCommon.DispTitleEnum.Post:
9381                     if (_history != null && _history.Count > 1)
9382                         ttl.Append(_history[_history.Count - 2].status.Replace("\r\n", " "));
9383                     break;
9384                 case MyCommon.DispTitleEnum.UnreadRepCount:
9385                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText1, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
9386                     break;
9387                 case MyCommon.DispTitleEnum.UnreadAllCount:
9388                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText2, ur);
9389                     break;
9390                 case MyCommon.DispTitleEnum.UnreadAllRepCount:
9391                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText3, ur, _statuses.GetTabByType(MyCommon.TabUsageType.Mentions).UnreadCount + _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage).UnreadCount);
9392                     break;
9393                 case MyCommon.DispTitleEnum.UnreadCountAllCount:
9394                     ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText4, ur, al);
9395                     break;
9396                 case MyCommon.DispTitleEnum.OwnStatus:
9397                     if (followers == 0 && tw.FollowersCount > 0) followers = tw.FollowersCount;
9398                     ttl.AppendFormat(Properties.Resources.OwnStatusTitle, tw.StatusesCount, tw.FriendsCount, tw.FollowersCount, tw.FollowersCount - followers);
9399                     break;
9400             }
9401
9402             try
9403             {
9404                 this.Text = ttl.ToString();
9405             }
9406             catch (AccessViolationException)
9407             {
9408                 //原因不明。ポスト内容に依存か?たまーに発生するが再現せず。
9409             }
9410         }
9411
9412         private string GetStatusLabelText()
9413         {
9414             //ステータス欄にカウント表示
9415             //タブ未読数/タブ発言数 全未読数/総発言数 (未読@+未読DM数)
9416             if (_statuses == null) return "";
9417             TabClass tbRep = _statuses.GetTabByType(MyCommon.TabUsageType.Mentions);
9418             TabClass tbDm = _statuses.GetTabByType(MyCommon.TabUsageType.DirectMessage);
9419             if (tbRep == null || tbDm == null) return "";
9420             int urat = tbRep.UnreadCount + tbDm.UnreadCount;
9421             int ur = 0;
9422             int al = 0;
9423             int tur = 0;
9424             int tal = 0;
9425             StringBuilder slbl = new StringBuilder(256);
9426             try
9427             {
9428                 foreach (string key in _statuses.Tabs.Keys)
9429                 {
9430                     ur += _statuses.Tabs[key].UnreadCount;
9431                     al += _statuses.Tabs[key].AllCount;
9432                     if (key.Equals(_curTab.Text))
9433                     {
9434                         tur = _statuses.Tabs[key].UnreadCount;
9435                         tal = _statuses.Tabs[key].AllCount;
9436                     }
9437                 }
9438             }
9439             catch (Exception)
9440             {
9441                 return "";
9442             }
9443
9444             UnreadCounter = ur;
9445             UnreadAtCounter = urat;
9446
9447             slbl.AppendFormat(Properties.Resources.SetStatusLabelText1, tur, tal, ur, al, urat, _postTimestamps.Count, _favTimestamps.Count, _tlCount);
9448             if (SettingDialog.TimelinePeriodInt == 0)
9449             {
9450                 slbl.Append(Properties.Resources.SetStatusLabelText2);
9451             }
9452             else
9453             {
9454                 slbl.Append(SettingDialog.TimelinePeriodInt.ToString() + Properties.Resources.SetStatusLabelText3);
9455             }
9456             return slbl.ToString();
9457         }
9458
9459         delegate void SetStatusLabelApiDelegate();
9460
9461         private void SetStatusLabelApiHandler(object sender, ApiInformationChangedEventArgs e)
9462         {
9463             try
9464             {
9465                 if (InvokeRequired && !IsDisposed)
9466                 {
9467                     Invoke(new SetStatusLabelApiDelegate(SetStatusLabelApi));
9468                 }
9469                 else
9470                 {
9471                     SetStatusLabelApi();
9472                 }
9473             }
9474             catch (ObjectDisposedException)
9475             {
9476                 return;
9477             }
9478             catch (InvalidOperationException)
9479             {
9480                 return;
9481             }
9482         }
9483
9484         private void SetStatusLabelApi()
9485         {
9486             this._apiGauge.RemainCount = MyCommon.TwitterApiInfo.RemainCount;
9487             this._apiGauge.MaxCount = MyCommon.TwitterApiInfo.MaxCount;
9488             this._apiGauge.ResetTime = MyCommon.TwitterApiInfo.ResetTime;
9489         }
9490
9491         private void SetStatusLabelUrl()
9492         {
9493             StatusLabelUrl.Text = GetStatusLabelText();
9494         }
9495
9496         public void SetStatusLabel(string text)
9497         {
9498             StatusLabel.Text = text;
9499         }
9500
9501         private static StringBuilder ur = new StringBuilder(64);
9502
9503         private void SetNotifyIconText()
9504         {
9505             // タスクトレイアイコンのツールチップテキスト書き換え
9506             // Tween [未読/@]
9507             ur.Remove(0, ur.Length);
9508             if (SettingDialog.DispUsername)
9509             {
9510                 ur.Append(tw.Username);
9511                 ur.Append(" - ");
9512             }
9513             ur.Append(Application.ProductName);
9514 #if DEBUG
9515             ur.Append("(Debug Build)");
9516 #endif
9517             if (UnreadCounter != -1 && UnreadAtCounter != -1)
9518             {
9519                 ur.Append(" [");
9520                 ur.Append(UnreadCounter);
9521                 ur.Append("/@");
9522                 ur.Append(UnreadAtCounter);
9523                 ur.Append("]");
9524             }
9525             NotifyIcon1.Text = ur.ToString();
9526         }
9527
9528         internal void CheckReplyTo(string StatusText)
9529         {
9530             MatchCollection m;
9531             //ハッシュタグの保存
9532             m = Regex.Matches(StatusText, Twitter.HASHTAG, RegexOptions.IgnoreCase);
9533             string hstr = "";
9534             foreach (Match hm in m)
9535             {
9536                 if (!hstr.Contains("#" + hm.Result("$3") + " "))
9537                 {
9538                     hstr += "#" + hm.Result("$3") + " ";
9539                     HashSupl.AddItem("#" + hm.Result("$3"));
9540                 }
9541             }
9542             if (!string.IsNullOrEmpty(HashMgr.UseHash) && !hstr.Contains(HashMgr.UseHash + " "))
9543             {
9544                 hstr += HashMgr.UseHash;
9545             }
9546             if (!string.IsNullOrEmpty(hstr)) HashMgr.AddHashToHistory(hstr.Trim(), false);
9547
9548             // 本当にリプライ先指定すべきかどうかの判定
9549             m = Regex.Matches(StatusText, "(^|[ -/:-@[-^`{-~])(?<id>@[a-zA-Z0-9_]+)");
9550
9551             if (SettingDialog.UseAtIdSupplement)
9552             {
9553                 int bCnt = AtIdSupl.ItemCount;
9554                 foreach (Match mid in m)
9555                 {
9556                     AtIdSupl.AddItem(mid.Result("${id}"));
9557                 }
9558                 if (bCnt != AtIdSupl.ItemCount) _modifySettingAtId = true;
9559             }
9560
9561             // リプライ先ステータスIDの指定がない場合は指定しない
9562             if (_reply_to_id == 0) return;
9563
9564             // リプライ先ユーザー名がない場合も指定しない
9565             if (string.IsNullOrEmpty(_reply_to_name))
9566             {
9567                 _reply_to_id = 0;
9568                 return;
9569             }
9570
9571             // 通常Reply
9572             // 次の条件を満たす場合に in_reply_to_status_id 指定
9573             // 1. Twitterによりリンクと判定される @idが文中に1つ含まれる (2009/5/28 リンク化される@IDのみカウントするように修正)
9574             // 2. リプライ先ステータスIDが設定されている(リストをダブルクリックで返信している)
9575             // 3. 文中に含まれた@idがリプライ先のポスト者のIDと一致する
9576
9577             if (m != null)
9578             {
9579                 if (StatusText.StartsWith("@"))
9580                 {
9581                     if (StatusText.StartsWith("@" + _reply_to_name)) return;
9582                 }
9583                 else
9584                 {
9585                     foreach (Match mid in m)
9586                     {
9587                         if (StatusText.Contains("QT " + mid.Result("${id}") + ":") && mid.Result("${id}") == "@" + _reply_to_name) return;
9588                     }
9589                 }
9590             }
9591
9592             _reply_to_id = 0;
9593             _reply_to_name = "";
9594
9595         }
9596
9597         private void TweenMain_Resize(object sender, EventArgs e)
9598         {
9599             if (!_initialLayout && SettingDialog.MinimizeToTray && WindowState == FormWindowState.Minimized)
9600             {
9601                 this.Visible = false;
9602             }
9603             if (_initialLayout && _cfgLocal != null && this.WindowState == FormWindowState.Normal && this.Visible)
9604             {
9605                 this.ClientSize = _cfgLocal.FormSize;
9606                 //_mySize = this.ClientSize;                     //サイズ保持(最小化・最大化されたまま終了した場合の対応用)
9607                 this.DesktopLocation = _cfgLocal.FormLocation;
9608                 //_myLoc = this.DesktopLocation;                        //位置保持(最小化・最大化されたまま終了した場合の対応用)
9609                 //if (_cfgLocal.AdSplitterDistance > this.SplitContainer4.Panel1MinSize &&
9610                 //    _cfgLocal.AdSplitterDistance < this.SplitContainer4.Height - this.SplitContainer4.Panel2MinSize - this.SplitContainer4.SplitterWidth)
9611                 //{
9612                 //    this.SplitContainer4.SplitterDistance = _cfgLocal.AdSplitterDistance; //Splitterの位置設定
9613                 //}
9614                 if (_cfgLocal.SplitterDistance > this.SplitContainer1.Panel1MinSize &&
9615                     _cfgLocal.SplitterDistance < this.SplitContainer1.Height - this.SplitContainer1.Panel2MinSize - this.SplitContainer1.SplitterWidth)
9616                 {
9617                     this.SplitContainer1.SplitterDistance = _cfgLocal.SplitterDistance; //Splitterの位置設定
9618                 }
9619                 //発言欄複数行
9620                 StatusText.Multiline = _cfgLocal.StatusMultiline;
9621                 if (StatusText.Multiline)
9622                 {
9623                     int dis = SplitContainer2.Height - _cfgLocal.StatusTextHeight - SplitContainer2.SplitterWidth;
9624                     if (dis > SplitContainer2.Panel1MinSize && dis < SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth)
9625                     {
9626                         SplitContainer2.SplitterDistance = SplitContainer2.Height - _cfgLocal.StatusTextHeight - SplitContainer2.SplitterWidth;
9627                     }
9628                     StatusText.Height = _cfgLocal.StatusTextHeight;
9629                 }
9630                 else
9631                 {
9632                     if (SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth > 0)
9633                     {
9634                         SplitContainer2.SplitterDistance = SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth;
9635                     }
9636                 }
9637                 if (_cfgLocal.PreviewDistance > this.SplitContainer3.Panel1MinSize && _cfgLocal.PreviewDistance < this.SplitContainer3.Width - this.SplitContainer3.Panel2MinSize - this.SplitContainer3.SplitterWidth)
9638                 {
9639                     this.SplitContainer3.SplitterDistance = _cfgLocal.PreviewDistance;
9640                 }
9641                 _initialLayout = false;
9642             }
9643             if (this.WindowState != FormWindowState.Minimized)
9644             {
9645                 _formWindowState = this.WindowState;
9646             }
9647         }
9648
9649         private void PlaySoundMenuItem_CheckedChanged(object sender, EventArgs e)
9650         {
9651             PlaySoundMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
9652             this.PlaySoundFileMenuItem.Checked = PlaySoundMenuItem.Checked;
9653             if (PlaySoundMenuItem.Checked)
9654             {
9655                 SettingDialog.PlaySound = true;
9656             }
9657             else
9658             {
9659                 SettingDialog.PlaySound = false;
9660             }
9661             _modifySettingCommon = true;
9662         }
9663
9664         private void SplitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
9665         {
9666             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
9667             {
9668                 _mySpDis = SplitContainer1.SplitterDistance;
9669                 if (StatusText.Multiline) _mySpDis2 = StatusText.Height;
9670                 _modifySettingLocal = true;
9671             }
9672         }
9673
9674         private void doRepliedStatusOpen()
9675         {
9676             if (this.ExistCurrentPost && _curPost.InReplyToUser != null && _curPost.InReplyToStatusId > 0)
9677             {
9678                 if (MyCommon.IsKeyDown(Keys.Shift))
9679                 {
9680                     OpenUriAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId));
9681                     return;
9682                 }
9683                 if (_statuses.ContainsKey(_curPost.InReplyToStatusId))
9684                 {
9685                     PostClass repPost = _statuses[_curPost.InReplyToStatusId];
9686                     MessageBox.Show(repPost.ScreenName + " / " + repPost.Nickname + "   (" + repPost.CreatedAt.ToString() + ")" + Environment.NewLine + repPost.TextFromApi);
9687                 }
9688                 else
9689                 {
9690                     foreach (TabClass tb in _statuses.GetTabsByType(MyCommon.TabUsageType.Lists | MyCommon.TabUsageType.PublicSearch))
9691                     {
9692                         if (tb == null || !tb.Contains(_curPost.InReplyToStatusId)) break;
9693                         PostClass repPost = _statuses[_curPost.InReplyToStatusId];
9694                         MessageBox.Show(repPost.ScreenName + " / " + repPost.Nickname + "   (" + repPost.CreatedAt.ToString() + ")" + Environment.NewLine + repPost.TextFromApi);
9695                         return;
9696                     }
9697                     OpenUriAsync(MyCommon.GetStatusUrl(_curPost.InReplyToUser, _curPost.InReplyToStatusId));
9698                 }
9699             }
9700         }
9701
9702         private void RepliedStatusOpenMenuItem_Click(object sender, EventArgs e)
9703         {
9704             doRepliedStatusOpen();
9705         }
9706
9707         private void ContextMenuUserPicture_Opening(object sender, CancelEventArgs e)
9708         {
9709             //発言詳細のアイコン右クリック時のメニュー制御
9710             if (_curList.SelectedIndices.Count > 0 && _curPost != null)
9711             {
9712                 string name = _curPost.ImageUrl;
9713                 if (name != null && name.Length > 0)
9714                 {
9715                     int idx = name.LastIndexOf('/');
9716                     if (idx != -1)
9717                     {
9718                         name = Path.GetFileName(name.Substring(idx));
9719                         if (name.Contains("_normal.") || name.EndsWith("_normal"))
9720                         {
9721                             name = name.Replace("_normal", "");
9722                             this.IconNameToolStripMenuItem.Text = name;
9723                             this.IconNameToolStripMenuItem.Enabled = true;
9724                         }
9725                         else
9726                         {
9727                             this.IconNameToolStripMenuItem.Enabled = false;
9728                             this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9729                         }
9730                     }
9731                     else
9732                     {
9733                         this.IconNameToolStripMenuItem.Enabled = false;
9734                         this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9735                     }
9736                     if (this.TIconDic[_curPost.ImageUrl] != null)
9737                     {
9738                         this.SaveIconPictureToolStripMenuItem.Enabled = true;
9739                     }
9740                     else
9741                     {
9742                         this.SaveIconPictureToolStripMenuItem.Enabled = false;
9743                     }
9744                 }
9745                 else
9746                 {
9747                     this.IconNameToolStripMenuItem.Enabled = false;
9748                     this.SaveIconPictureToolStripMenuItem.Enabled = false;
9749                     this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText1;
9750                 }
9751             }
9752             else
9753             {
9754                 this.IconNameToolStripMenuItem.Enabled = false;
9755                 this.SaveIconPictureToolStripMenuItem.Enabled = false;
9756                 this.IconNameToolStripMenuItem.Text = Properties.Resources.ContextMenuStrip3_OpeningText2;
9757             }
9758             if (NameLabel.Tag != null)
9759             {
9760                 string id = (string)NameLabel.Tag;
9761                 if (id == tw.Username)
9762                 {
9763                     FollowToolStripMenuItem.Enabled = false;
9764                     UnFollowToolStripMenuItem.Enabled = false;
9765                     ShowFriendShipToolStripMenuItem.Enabled = false;
9766                     ShowUserStatusToolStripMenuItem.Enabled = true;
9767                     SearchPostsDetailNameToolStripMenuItem.Enabled = true;
9768                     SearchAtPostsDetailNameToolStripMenuItem.Enabled = false;
9769                     ListManageUserContextToolStripMenuItem3.Enabled = true;
9770                 }
9771                 else
9772                 {
9773                     FollowToolStripMenuItem.Enabled = true;
9774                     UnFollowToolStripMenuItem.Enabled = true;
9775                     ShowFriendShipToolStripMenuItem.Enabled = true;
9776                     ShowUserStatusToolStripMenuItem.Enabled = true;
9777                     SearchPostsDetailNameToolStripMenuItem.Enabled = true;
9778                     SearchAtPostsDetailNameToolStripMenuItem.Enabled = true;
9779                     ListManageUserContextToolStripMenuItem3.Enabled = true;
9780                 }
9781             }
9782             else
9783             {
9784                 FollowToolStripMenuItem.Enabled = false;
9785                 UnFollowToolStripMenuItem.Enabled = false;
9786                 ShowFriendShipToolStripMenuItem.Enabled = false;
9787                 ShowUserStatusToolStripMenuItem.Enabled = false;
9788                 SearchPostsDetailNameToolStripMenuItem.Enabled = false;
9789                 SearchAtPostsDetailNameToolStripMenuItem.Enabled = false;
9790                 ListManageUserContextToolStripMenuItem3.Enabled = false;
9791             }
9792         }
9793
9794         private void IconNameToolStripMenuItem_Click(object sender, EventArgs e)
9795         {
9796             if (_curPost == null) return;
9797             string name = _curPost.ImageUrl;
9798             OpenUriAsync(name.Remove(name.LastIndexOf("_normal"), 7)); // "_normal".Length
9799         }
9800
9801         private void SaveOriginalSizeIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
9802         {
9803             if (_curPost == null) return;
9804             string name = _curPost.ImageUrl;
9805             name = Path.GetFileNameWithoutExtension(name.Substring(name.LastIndexOf('/')));
9806
9807             this.SaveFileDialog1.FileName = name.Substring(0, name.Length - 8); // "_normal".Length + 1
9808
9809             if (this.SaveFileDialog1.ShowDialog() == DialogResult.OK)
9810             {
9811                 // STUB
9812             }
9813         }
9814
9815         private void SaveIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
9816         {
9817             if (_curPost == null) return;
9818             string name = _curPost.ImageUrl;
9819
9820             this.SaveFileDialog1.FileName = name.Substring(name.LastIndexOf('/') + 1);
9821
9822             if (this.SaveFileDialog1.ShowDialog() == DialogResult.OK)
9823             {
9824                 try
9825                 {
9826                     using (Image orgBmp = new Bitmap(TIconDic[name]))
9827                     {
9828                         using (Bitmap bmp2 = new Bitmap(orgBmp.Size.Width, orgBmp.Size.Height))
9829                         {
9830                             using (Graphics g = Graphics.FromImage(bmp2))
9831                             {
9832                                 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
9833                                 g.DrawImage(orgBmp, 0, 0, orgBmp.Size.Width, orgBmp.Size.Height);
9834                             }
9835                             bmp2.Save(this.SaveFileDialog1.FileName);
9836                         }
9837                     }
9838                 }
9839                 catch (Exception)
9840                 {
9841                     //処理中にキャッシュアウトする可能性あり
9842                 }
9843             }
9844         }
9845
9846         private void SplitContainer2_Panel2_Resize(object sender, EventArgs e)
9847         {
9848             this.StatusText.Multiline = this.SplitContainer2.Panel2.Height > this.SplitContainer2.Panel2MinSize + 2;
9849             MultiLineMenuItem.Checked = this.StatusText.Multiline;
9850             _modifySettingLocal = true;
9851         }
9852
9853         private void StatusText_MultilineChanged(object sender, EventArgs e)
9854         {
9855             if (this.StatusText.Multiline)
9856                 this.StatusText.ScrollBars = ScrollBars.Vertical;
9857             else
9858                 this.StatusText.ScrollBars = ScrollBars.None;
9859
9860             _modifySettingLocal = true;
9861         }
9862
9863         private void MultiLineMenuItem_Click(object sender, EventArgs e)
9864         {
9865             //発言欄複数行
9866             StatusText.Multiline = MultiLineMenuItem.Checked;
9867             _cfgLocal.StatusMultiline = MultiLineMenuItem.Checked;
9868             if (MultiLineMenuItem.Checked)
9869             {
9870                 if (SplitContainer2.Height - _mySpDis2 - SplitContainer2.SplitterWidth < 0)
9871                     SplitContainer2.SplitterDistance = 0;
9872                 else
9873                     SplitContainer2.SplitterDistance = SplitContainer2.Height - _mySpDis2 - SplitContainer2.SplitterWidth;
9874             }
9875             else
9876             {
9877                 SplitContainer2.SplitterDistance = SplitContainer2.Height - SplitContainer2.Panel2MinSize - SplitContainer2.SplitterWidth;
9878             }
9879             _modifySettingLocal = true;
9880         }
9881
9882         private bool UrlConvert(MyCommon.UrlConverter Converter_Type)
9883         {
9884             //t.coで投稿時自動短縮する場合は、外部サービスでの短縮禁止
9885             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco) return;
9886
9887             //Converter_Type=Nicomsの場合は、nicovideoのみ短縮する
9888             //参考資料 RFC3986 Uniform Resource Identifier (URI): Generic Syntax
9889             //Appendix A.  Collected ABNF for URI
9890             //http://www.ietf.org/rfc/rfc3986.txt
9891
9892             string result = "";
9893
9894             const string nico = @"^https?://[a-z]+\.(nicovideo|niconicommons|nicolive)\.jp/[a-z]+/[a-z0-9]+$";
9895
9896             if (StatusText.SelectionLength > 0)
9897             {
9898                 string tmp = StatusText.SelectedText;
9899                 // httpから始まらない場合、ExcludeStringで指定された文字列で始まる場合は対象としない
9900                 if (tmp.StartsWith("http"))
9901                 {
9902                     // 文字列が選択されている場合はその文字列について処理
9903
9904                     //nico.ms使用、nicovideoにマッチしたら変換
9905                     if (SettingDialog.Nicoms && Regex.IsMatch(tmp, nico))
9906                     {
9907                         result = nicoms.Shorten(tmp);
9908                     }
9909                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
9910                     {
9911                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
9912                         result = ShortUrl.Make(Converter_Type, tmp);
9913                         if (result.Equals("Can't convert"))
9914                         {
9915                             StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
9916                             return false;
9917                         }
9918                     }
9919                     else
9920                     {
9921                         return true;
9922                     }
9923
9924                     if (!string.IsNullOrEmpty(result))
9925                     {
9926                         urlUndo undotmp = new urlUndo();
9927
9928                         StatusText.Select(StatusText.Text.IndexOf(tmp, StringComparison.Ordinal), tmp.Length);
9929                         StatusText.SelectedText = result;
9930
9931                         //undoバッファにセット
9932                         undotmp.Before = tmp;
9933                         undotmp.After = result;
9934
9935                         if (urlUndoBuffer == null)
9936                         {
9937                             urlUndoBuffer = new List<urlUndo>();
9938                             UrlUndoToolStripMenuItem.Enabled = true;
9939                         }
9940
9941                         urlUndoBuffer.Add(undotmp);
9942                     }
9943                 }
9944             }
9945             else
9946             {
9947                 const string url = @"(?<before>(?:[^\""':!=]|^|\:))" +
9948                                    @"(?<url>(?<protocol>https?://)" +
9949                                    @"(?<domain>(?:[\.-]|[^\p{P}\s])+\.[a-z]{2,}(?::[0-9]+)?)" +
9950                                    @"(?<path>/[a-z0-9!*//();:&=+$/%#\-_.,~@]*[a-z0-9)=#/]?)?" +
9951                                    @"(?<query>\?[a-z0-9!*//();:&=+$/%#\-_.,~@?]*[a-z0-9_&=#/])?)";
9952                 // 正規表現にマッチしたURL文字列をtinyurl化
9953                 foreach (Match mt in Regex.Matches(StatusText.Text, url, RegexOptions.IgnoreCase))
9954                 {
9955                     if (StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal) == -1) continue;
9956                     string tmp = mt.Result("${url}");
9957                     if (tmp.StartsWith("w", StringComparison.OrdinalIgnoreCase)) tmp = "http://" + tmp;
9958                     urlUndo undotmp = new urlUndo();
9959
9960                     //選んだURLを選択(?)
9961                     StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
9962
9963                     //nico.ms使用、nicovideoにマッチしたら変換
9964                     if (SettingDialog.Nicoms && Regex.IsMatch(tmp, nico))
9965                     {
9966                         result = nicoms.Shorten(tmp);
9967                     }
9968                     else if (Converter_Type != MyCommon.UrlConverter.Nicoms)
9969                     {
9970                         //短縮URL変換 日本語を含むかもしれないのでURLエンコードする
9971                         result = ShortUrl.Make(Converter_Type, tmp);
9972                         if (result.Equals("Can't convert"))
9973                         {
9974                             StatusLabel.Text = result.Insert(0, Converter_Type.ToString() + ":");
9975                             continue;
9976                         }
9977                     }
9978                     else
9979                     {
9980                         continue;
9981                     }
9982
9983                     if (!string.IsNullOrEmpty(result))
9984                     {
9985                         StatusText.Select(StatusText.Text.IndexOf(mt.Result("${url}"), StringComparison.Ordinal), mt.Result("${url}").Length);
9986                         StatusText.SelectedText = result;
9987                         //undoバッファにセット
9988                         undotmp.Before = mt.Result("${url}");
9989                         undotmp.After = result;
9990
9991                         if (urlUndoBuffer == null)
9992                         {
9993                             urlUndoBuffer = new List<urlUndo>();
9994                             UrlUndoToolStripMenuItem.Enabled = true;
9995                         }
9996
9997                         urlUndoBuffer.Add(undotmp);
9998                     }
9999                 }
10000             }
10001
10002             return true;
10003         }
10004
10005         private void doUrlUndo()
10006         {
10007             if (urlUndoBuffer != null)
10008             {
10009                 string tmp = StatusText.Text;
10010                 foreach (urlUndo data in urlUndoBuffer)
10011                 {
10012                     tmp = tmp.Replace(data.After, data.Before);
10013                 }
10014                 StatusText.Text = tmp;
10015                 urlUndoBuffer = null;
10016                 UrlUndoToolStripMenuItem.Enabled = false;
10017                 StatusText.SelectionStart = 0;
10018                 StatusText.SelectionLength = 0;
10019             }
10020         }
10021
10022         private void TinyURLToolStripMenuItem_Click(object sender, EventArgs e)
10023         {
10024             UrlConvert(MyCommon.UrlConverter.TinyUrl);
10025         }
10026
10027         private void IsgdToolStripMenuItem_Click(object sender, EventArgs e)
10028         {
10029             UrlConvert(MyCommon.UrlConverter.Isgd);
10030         }
10031
10032         private void TwurlnlToolStripMenuItem_Click(object sender, EventArgs e)
10033         {
10034             UrlConvert(MyCommon.UrlConverter.Twurl);
10035         }
10036
10037         private void UxnuMenuItem_Click(object sender, EventArgs e)
10038         {
10039             UrlConvert(MyCommon.UrlConverter.Uxnu);
10040         }
10041
10042         private void UrlConvertAutoToolStripMenuItem_Click(object sender, EventArgs e) 
10043         {
10044             if (!UrlConvert(SettingDialog.AutoShortUrlFirst))
10045             {
10046                 MyCommon.UrlConverter svc = SettingDialog.AutoShortUrlFirst;
10047                 Random rnd = new Random();
10048                 // 前回使用した短縮URLサービス以外を選択する
10049                 do
10050                 {
10051                     svc = (MyCommon.UrlConverter)rnd.Next(System.Enum.GetNames(typeof(MyCommon.UrlConverter)).Length);
10052                 }
10053                 while (svc == SettingDialog.AutoShortUrlFirst || svc == MyCommon.UrlConverter.Nicoms || svc == MyCommon.UrlConverter.Unu);
10054                 UrlConvert(svc);
10055             }
10056         }
10057
10058         private void UrlUndoToolStripMenuItem_Click(object sender, EventArgs e)
10059         {
10060             doUrlUndo();
10061         }
10062
10063         private void NewPostPopMenuItem_CheckStateChanged(object sender, EventArgs e)
10064         {
10065             this.NotifyFileMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
10066             this.NewPostPopMenuItem.Checked = this.NotifyFileMenuItem.Checked;
10067             _cfgCommon.NewAllPop = NewPostPopMenuItem.Checked;
10068             _modifySettingCommon = true;
10069         }
10070
10071         private void ListLockMenuItem_CheckStateChanged(object sender, EventArgs e)
10072         {
10073             ListLockMenuItem.Checked = ((ToolStripMenuItem)sender).Checked;
10074             this.LockListFileMenuItem.Checked = ListLockMenuItem.Checked;
10075             _cfgCommon.ListLock = ListLockMenuItem.Checked;
10076             _modifySettingCommon = true;
10077         }
10078
10079         private void MenuStrip1_MenuActivate(object sender, EventArgs e)
10080         {
10081             // フォーカスがメニューに移る (MenuStrip1.Tag フラグを立てる)
10082             MenuStrip1.Tag = new Object();
10083             MenuStrip1.Select(); // StatusText がフォーカスを持っている場合 Leave が発生
10084         }
10085
10086         private void MenuStrip1_MenuDeactivate(object sender, EventArgs e)
10087         {
10088             if (this.Tag != null) // 設定された戻り先へ遷移
10089             {
10090                 if (this.Tag == this.ListTab.SelectedTab)
10091                     ((Control)this.ListTab.SelectedTab.Tag).Select();
10092                 else
10093                     ((Control)this.Tag).Select();
10094             }
10095             else // 戻り先が指定されていない (初期状態) 場合はタブに遷移
10096             {
10097                 if (ListTab.SelectedIndex > -1 && ListTab.SelectedTab.HasChildren)
10098                 {
10099                     this.Tag = ListTab.SelectedTab.Tag;
10100                     ((Control)this.Tag).Select();
10101                 }
10102             }
10103             // フォーカスがメニューに遷移したかどうかを表すフラグを降ろす
10104             MenuStrip1.Tag = null;
10105         }
10106
10107         private void MyList_ColumnReordered(object sender, ColumnReorderedEventArgs e)
10108         {
10109             DetailsListView lst = (DetailsListView)sender;
10110             if (_cfgLocal == null) return;
10111
10112             if (_iconCol)
10113             {
10114                 _cfgLocal.Width1 = lst.Columns[0].Width;
10115                 _cfgLocal.Width3 = lst.Columns[1].Width;
10116             }
10117             else
10118             {
10119                 int[] darr = new int[lst.Columns.Count];
10120                 for (int i = 0; i < lst.Columns.Count; i++)
10121                 {
10122                     darr[lst.Columns[i].DisplayIndex] = i;
10123                 }
10124                 MyCommon.MoveArrayItem(darr, e.OldDisplayIndex, e.NewDisplayIndex);
10125
10126                 for (int i = 0; i < lst.Columns.Count; i++)
10127                 {
10128                     switch (darr[i])
10129                     {
10130                         case 0:
10131                             _cfgLocal.DisplayIndex1 = i;
10132                             break;
10133                         case 1:
10134                             _cfgLocal.DisplayIndex2 = i;
10135                             break;
10136                         case 2:
10137                             _cfgLocal.DisplayIndex3 = i;
10138                             break;
10139                         case 3:
10140                             _cfgLocal.DisplayIndex4 = i;
10141                             break;
10142                         case 4:
10143                             _cfgLocal.DisplayIndex5 = i;
10144                             break;
10145                         case 5:
10146                             _cfgLocal.DisplayIndex6 = i;
10147                             break;
10148                         case 6:
10149                             _cfgLocal.DisplayIndex7 = i;
10150                             break;
10151                         case 7:
10152                             _cfgLocal.DisplayIndex8 = i;
10153                             break;
10154                     }
10155                 }
10156                 _cfgLocal.Width1 = lst.Columns[0].Width;
10157                 _cfgLocal.Width2 = lst.Columns[1].Width;
10158                 _cfgLocal.Width3 = lst.Columns[2].Width;
10159                 _cfgLocal.Width4 = lst.Columns[3].Width;
10160                 _cfgLocal.Width5 = lst.Columns[4].Width;
10161                 _cfgLocal.Width6 = lst.Columns[5].Width;
10162                 _cfgLocal.Width7 = lst.Columns[6].Width;
10163                 _cfgLocal.Width8 = lst.Columns[7].Width;
10164             }
10165             _modifySettingLocal = true;
10166             _isColumnChanged = true;
10167         }
10168
10169         private void MyList_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
10170         {
10171             DetailsListView lst = (DetailsListView)sender;
10172             if (_cfgLocal == null) return;
10173             if (_iconCol)
10174             {
10175                 if (_cfgLocal.Width1 != lst.Columns[0].Width)
10176                 {
10177                     _cfgLocal.Width1 = lst.Columns[0].Width;
10178                     _modifySettingLocal = true;
10179                     _isColumnChanged = true;
10180                 }
10181                 if (_cfgLocal.Width3 != lst.Columns[1].Width)
10182                 {
10183                     _cfgLocal.Width3 = lst.Columns[1].Width;
10184                     _modifySettingLocal = true;
10185                     _isColumnChanged = true;
10186                 }
10187             }
10188             else
10189             {
10190                 if (_cfgLocal.Width1 != lst.Columns[0].Width)
10191                 {
10192                     _cfgLocal.Width1 = lst.Columns[0].Width;
10193                     _modifySettingLocal = true;
10194                     _isColumnChanged = true;
10195                 }
10196                 if (_cfgLocal.Width2 != lst.Columns[1].Width)
10197                 {
10198                     _cfgLocal.Width2 = lst.Columns[1].Width;
10199                     _modifySettingLocal = true;
10200                     _isColumnChanged = true;
10201                 }
10202                 if (_cfgLocal.Width3 != lst.Columns[2].Width)
10203                 {
10204                     _cfgLocal.Width3 = lst.Columns[2].Width;
10205                     _modifySettingLocal = true;
10206                     _isColumnChanged = true;
10207                 }
10208                 if (_cfgLocal.Width4 != lst.Columns[3].Width)
10209                 {
10210                     _cfgLocal.Width4 = lst.Columns[3].Width;
10211                     _modifySettingLocal = true;
10212                     _isColumnChanged = true;
10213                 }
10214                 if (_cfgLocal.Width5 != lst.Columns[4].Width)
10215                 {
10216                     _cfgLocal.Width5 = lst.Columns[4].Width;
10217                     _modifySettingLocal = true;
10218                     _isColumnChanged = true;
10219                 }
10220                 if (_cfgLocal.Width6 != lst.Columns[5].Width)
10221                 {
10222                     _cfgLocal.Width6 = lst.Columns[5].Width;
10223                     _modifySettingLocal = true;
10224                     _isColumnChanged = true;
10225                 }
10226                 if (_cfgLocal.Width7 != lst.Columns[6].Width)
10227                 {
10228                     _cfgLocal.Width7 = lst.Columns[6].Width;
10229                     _modifySettingLocal = true;
10230                     _isColumnChanged = true;
10231                 }
10232                 if (_cfgLocal.Width8 != lst.Columns[7].Width)
10233                 {
10234                     _cfgLocal.Width8 = lst.Columns[7].Width;
10235                     _modifySettingLocal = true;
10236                     _isColumnChanged = true;
10237                 }
10238             }
10239             // 非表示の時にColumnChangedが呼ばれた場合はForm初期化処理中なので保存しない
10240             //if (changed)
10241             //{
10242             //    SaveConfigsLocal();
10243             //}
10244         }
10245
10246         public string WebBrowser_GetSelectionText(ref WebBrowser ComponentInstance)
10247         {
10248             //発言詳細で「選択文字列をコピー」を行う
10249             //WebBrowserコンポーネントのインスタンスを渡す
10250             Type typ = ComponentInstance.ActiveXInstance.GetType();
10251             object _SelObj = typ.InvokeMember("selection", BindingFlags.GetProperty, null, ComponentInstance.Document.DomDocument, null);
10252             object _objRange = _SelObj.GetType().InvokeMember("createRange", BindingFlags.InvokeMethod, null, _SelObj, null);
10253             return (string)_objRange.GetType().InvokeMember("text", BindingFlags.GetProperty, null, _objRange, null);
10254         }
10255
10256         private void SelectionCopyContextMenuItem_Click(object sender, EventArgs e)
10257         {
10258             //発言詳細で「選択文字列をコピー」
10259             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10260             try
10261             {
10262                 Clipboard.SetDataObject(_selText, false, 5, 100);
10263             }
10264             catch (Exception ex)
10265             {
10266                 MessageBox.Show(ex.Message);
10267             }
10268         }
10269
10270         private void doSearchToolStrip(string url)
10271         {
10272             //発言詳細で「選択文字列で検索」(選択文字列取得)
10273             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10274
10275             if (_selText != null)
10276             {
10277                 if (url == Properties.Resources.SearchItem4Url)
10278                 {
10279                     //公式検索
10280                     AddNewTabForSearch(_selText);
10281                     return;
10282                 }
10283
10284                 string tmp = string.Format(url, HttpUtility.UrlEncode(_selText));
10285                 OpenUriAsync(tmp);
10286             }
10287         }
10288
10289         private void SelectionAllContextMenuItem_Click(object sender, EventArgs e)
10290         {
10291             //発言詳細ですべて選択
10292             PostBrowser.Document.ExecCommand("SelectAll", false, null);
10293         }
10294
10295         private void SearchWikipediaContextMenuItem_Click(object sender, EventArgs e)
10296         {
10297             doSearchToolStrip(Properties.Resources.SearchItem1Url);
10298         }
10299
10300         private void SearchGoogleContextMenuItem_Click(object sender, EventArgs e)
10301         {
10302             doSearchToolStrip(Properties.Resources.SearchItem2Url);
10303         }
10304
10305         private void SearchPublicSearchContextMenuItem_Click(object sender, EventArgs e)
10306         {
10307             doSearchToolStrip(Properties.Resources.SearchItem4Url);
10308         }
10309
10310         private void UrlCopyContextMenuItem_Click(object sender, EventArgs e)
10311         {
10312             try
10313             {
10314                 MatchCollection mc = Regex.Matches(this.PostBrowser.DocumentText, @"<a[^>]*href=""(?<url>" + this._postBrowserStatusText.Replace(".", @"\.") + @")""[^>]*title=""(?<title>https?://[^""]+)""", RegexOptions.IgnoreCase);
10315                 foreach (Match m in mc)
10316                 {
10317                     if (m.Groups["url"].Value == this._postBrowserStatusText)
10318                     {
10319                         Clipboard.SetDataObject(m.Groups["title"].Value, false, 5, 100);
10320                         break;
10321                     }
10322                 }
10323                 if (mc.Count == 0)
10324                 {
10325                     Clipboard.SetDataObject(this._postBrowserStatusText, false, 5, 100);
10326                 }
10327                 //Clipboard.SetDataObject(this._postBrowserStatusText, false, 5, 100);
10328             }
10329             catch (Exception ex)
10330             {
10331                 MessageBox.Show(ex.Message);
10332             }
10333         }
10334
10335         private void ContextMenuPostBrowser_Opening(object ender, CancelEventArgs e)
10336         {
10337             // URLコピーの項目の表示/非表示
10338             if (PostBrowser.StatusText.StartsWith("http"))
10339             {
10340                 this._postBrowserStatusText = PostBrowser.StatusText;
10341                 string name = GetUserId();
10342                 UrlCopyContextMenuItem.Enabled = true;
10343                 if (name != null)
10344                 {
10345                     FollowContextMenuItem.Enabled = true;
10346                     RemoveContextMenuItem.Enabled = true;
10347                     FriendshipContextMenuItem.Enabled = true;
10348                     ShowUserStatusContextMenuItem.Enabled = true;
10349                     SearchPostsDetailToolStripMenuItem.Enabled = true;
10350                     IdFilterAddMenuItem.Enabled = true;
10351                     ListManageUserContextToolStripMenuItem.Enabled = true;
10352                     SearchAtPostsDetailToolStripMenuItem.Enabled = true;
10353                 }
10354                 else
10355                 {
10356                     FollowContextMenuItem.Enabled = false;
10357                     RemoveContextMenuItem.Enabled = false;
10358                     FriendshipContextMenuItem.Enabled = false;
10359                     ShowUserStatusContextMenuItem.Enabled = false;
10360                     SearchPostsDetailToolStripMenuItem.Enabled = false;
10361                     IdFilterAddMenuItem.Enabled = false;
10362                     ListManageUserContextToolStripMenuItem.Enabled = false;
10363                     SearchAtPostsDetailToolStripMenuItem.Enabled = false;
10364                 }
10365
10366                 if (Regex.IsMatch(this._postBrowserStatusText, @"^https?://twitter.com/search\?q=%23"))
10367                     UseHashtagMenuItem.Enabled = true;
10368                 else
10369                     UseHashtagMenuItem.Enabled = false;
10370             }
10371             else
10372             {
10373                 this._postBrowserStatusText = "";
10374                 UrlCopyContextMenuItem.Enabled = false;
10375                 FollowContextMenuItem.Enabled = false;
10376                 RemoveContextMenuItem.Enabled = false;
10377                 FriendshipContextMenuItem.Enabled = false;
10378                 ShowUserStatusContextMenuItem.Enabled = false;
10379                 SearchPostsDetailToolStripMenuItem.Enabled = false;
10380                 SearchAtPostsDetailToolStripMenuItem.Enabled = false;
10381                 UseHashtagMenuItem.Enabled = false;
10382                 IdFilterAddMenuItem.Enabled = false;
10383                 ListManageUserContextToolStripMenuItem.Enabled = false;
10384             }
10385             // 文字列選択されていないときは選択文字列関係の項目を非表示に
10386             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10387             if (_selText == null)
10388             {
10389                 SelectionSearchContextMenuItem.Enabled = false;
10390                 SelectionCopyContextMenuItem.Enabled = false;
10391                 SelectionTranslationToolStripMenuItem.Enabled = false;
10392             }
10393             else
10394             {
10395                 SelectionSearchContextMenuItem.Enabled = true;
10396                 SelectionCopyContextMenuItem.Enabled = true;
10397                 SelectionTranslationToolStripMenuItem.Enabled = true;
10398             }
10399             //発言内に自分以外のユーザーが含まれてればフォロー状態全表示を有効に
10400             MatchCollection ma = Regex.Matches(this.PostBrowser.DocumentText, @"href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?""");
10401             bool fAllFlag = false;
10402             foreach (Match mu in ma)
10403             {
10404                 if (mu.Result("${ScreenName}").ToLower() != tw.Username.ToLower())
10405                 {
10406                     fAllFlag = true;
10407                     break;
10408                 }
10409             }
10410             this.FriendshipAllMenuItem.Enabled = fAllFlag;
10411
10412             if (_curPost == null)
10413                 TranslationToolStripMenuItem.Enabled = false;
10414             else
10415                 TranslationToolStripMenuItem.Enabled = true;
10416
10417             e.Cancel = false;
10418         }
10419
10420         private void CurrentTabToolStripMenuItem_Click(object sender, EventArgs e)
10421         {
10422             //発言詳細の選択文字列で現在のタブを検索
10423             string _selText = WebBrowser_GetSelectionText(ref PostBrowser);
10424
10425             if (_selText != null)
10426             {
10427                 SearchDialog.SWord = _selText;
10428                 SearchDialog.CheckCaseSensitive = false;
10429                 SearchDialog.CheckRegex = false;
10430
10431                 DoTabSearch(SearchDialog.SWord,
10432                             SearchDialog.CheckCaseSensitive,
10433                             SearchDialog.CheckRegex,
10434                             SEARCHTYPE.NextSearch);
10435             }
10436         }
10437
10438         private void SplitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
10439         {
10440             if (StatusText.Multiline) _mySpDis2 = StatusText.Height;
10441             _modifySettingLocal = true;
10442         }
10443
10444         private void TweenMain_DragDrop(object sender, DragEventArgs e)
10445         {
10446             if (e.Data.GetDataPresent(DataFormats.FileDrop))
10447             {
10448                 ImageSelectionPanel.Visible = true;
10449                 ImageSelectionPanel.Enabled = true;
10450                 TimelinePanel.Visible = false;
10451                 TimelinePanel.Enabled = false;
10452                 ImagefilePathText.Text = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
10453                 ImageFromSelectedFile();
10454                 this.Activate();
10455                 this.BringToFront();
10456                 StatusText.Focus();
10457             }
10458             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
10459             {
10460                 string data = (string)e.Data.GetData(DataFormats.StringFormat, true);
10461                 if (data != null) StatusText.Text += data;
10462             }
10463         }
10464
10465         private void TweenMain_DragOver(object sender, DragEventArgs e)
10466         {
10467             if (e.Data.GetDataPresent(DataFormats.FileDrop))
10468             {
10469                 string filename = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];
10470                 FileInfo fl = new FileInfo(filename);
10471                 string ext = fl.Extension;
10472
10473                 if (!string.IsNullOrEmpty(this.ImageService) && this.pictureService[this.ImageService].CheckValidFilesize(ext, fl.Length))
10474                 {
10475                     e.Effect = DragDropEffects.Copy;
10476                     return;
10477                 }
10478                 foreach (string svc in ImageServiceCombo.Items)
10479                 {
10480                     if (string.IsNullOrEmpty(svc)) continue;
10481                     if (this.pictureService[svc].CheckValidFilesize(ext, fl.Length))
10482                     {
10483                         ImageServiceCombo.SelectedItem = svc;
10484                         e.Effect = DragDropEffects.Copy;
10485                         return;
10486                     }
10487                 }
10488                 e.Effect = DragDropEffects.None;
10489             }
10490             else if (e.Data.GetDataPresent(DataFormats.StringFormat))
10491             {
10492                 e.Effect = DragDropEffects.Copy;
10493             }
10494             else
10495             {
10496                 e.Effect = DragDropEffects.None;
10497             }
10498         }
10499
10500         public bool IsNetworkAvailable()
10501         {
10502             bool nw = true;
10503             nw = MyCommon.IsNetworkAvailable();
10504             _myStatusOnline = nw;
10505             return nw;
10506         }
10507
10508         public void OpenUriAsync(string UriString)
10509         {
10510             GetWorkerArg args = new GetWorkerArg();
10511             args.type = MyCommon.WORKERTYPE.OpenUri;
10512             args.url = UriString;
10513
10514             RunAsync(args);
10515         }
10516
10517         private void ListTabSelect(TabPage _tab)
10518         {
10519             SetListProperty();
10520
10521             _itemCache = null;
10522             _itemCacheIndex = -1;
10523             _postCache = null;
10524
10525             _curTab = _tab;
10526             _curList = (DetailsListView)_tab.Tag;
10527             if (_curList.SelectedIndices.Count > 0)
10528             {
10529                 _curItemIndex = _curList.SelectedIndices[0];
10530                 _curPost = GetCurTabPost(_curItemIndex);
10531             }
10532             else
10533             {
10534                 _curItemIndex = -1;
10535                 _curPost = null;
10536             }
10537
10538             _anchorPost = null;
10539             _anchorFlag = false;
10540
10541             if (_iconCol)
10542             {
10543                 ((DetailsListView)_tab.Tag).Columns[1].Text = ColumnText[2];
10544             }
10545             else
10546             {
10547                 for (int i = 0; i < _curList.Columns.Count; i++)
10548                 {
10549                     ((DetailsListView)_tab.Tag).Columns[i].Text = ColumnText[i];
10550                 }
10551             }
10552         }
10553
10554         private void ListTab_Selecting(object sender, TabControlCancelEventArgs e)
10555         {
10556             ListTabSelect(e.TabPage);
10557         }
10558
10559         private void SelectListItem(DetailsListView LView, int Index)
10560         {
10561             //単一
10562             Rectangle bnd = new Rectangle();
10563             bool flg = false;
10564             if (LView.FocusedItem != null)
10565             {
10566                 bnd = LView.FocusedItem.Bounds;
10567                 flg = true;
10568             }
10569
10570             do
10571             {
10572                 LView.SelectedIndices.Clear();
10573             }
10574             while (LView.SelectedIndices.Count > 0);
10575             LView.Items[Index].Selected = true;
10576             //LView.SelectedIndices.Add(Index);
10577             LView.Items[Index].Focused = true;
10578
10579             if (flg) LView.Invalidate(bnd);
10580         }
10581
10582         private void SelectListItem(DetailsListView LView , int[] Index, int FocusedIndex)
10583         {
10584             //複数
10585             Rectangle bnd = new Rectangle();
10586             bool flg = false;
10587             if (LView.FocusedItem != null)
10588             {
10589                 bnd = LView.FocusedItem.Bounds;
10590                 flg = true;
10591             }
10592
10593             int fIdx = -1;
10594             if (Index != null && !(Index.Length == 1 && Index[0] == -1))
10595             {
10596                 do
10597                 {
10598                     LView.SelectedIndices.Clear();
10599                 }
10600                 while (LView.SelectedIndices.Count > 0);
10601                 foreach (int idx in Index)
10602                 {
10603                     if (idx > -1 && LView.VirtualListSize > idx)
10604                     {
10605                         LView.SelectedIndices.Add(idx);
10606                         if (fIdx == -1) fIdx = idx;
10607                     }
10608                 }
10609             }
10610             if (FocusedIndex > -1 && LView.VirtualListSize > FocusedIndex)
10611             {
10612                 LView.Items[FocusedIndex].Focused = true;
10613             }
10614             else if (fIdx > -1)
10615             {
10616                 LView.Items[fIdx].Focused = true;
10617             }
10618             if (flg) LView.Invalidate(bnd);
10619         }
10620
10621         private void RunAsync(GetWorkerArg args)
10622         {
10623             BackgroundWorker bw = null;
10624             if (args.type != MyCommon.WORKERTYPE.Follower)
10625             {
10626                 for (int i = 0; i < _bw.Length; i++)
10627                 {
10628                     if (_bw[i] != null && !_bw[i].IsBusy)
10629                     {
10630                         bw = _bw[i];
10631                         break;
10632                     }
10633                 }
10634                 if (bw == null)
10635                 {
10636                     for (int i = 0; i < _bw.Length; i++)
10637                     {
10638                         if (_bw[i] == null)
10639                         {
10640                             _bw[i] = new BackgroundWorker();
10641                             bw = _bw[i];
10642                             bw.WorkerReportsProgress = true;
10643                             bw.WorkerSupportsCancellation = true;
10644                             bw.DoWork += GetTimelineWorker_DoWork;
10645                             bw.ProgressChanged += GetTimelineWorker_ProgressChanged;
10646                             bw.RunWorkerCompleted += GetTimelineWorker_RunWorkerCompleted;
10647                             break;
10648                         }
10649                     }
10650                 }
10651             }
10652             else
10653             {
10654                 if (_bwFollower == null)
10655                 {
10656                     _bwFollower = new BackgroundWorker();
10657                     bw = _bwFollower;
10658                     bw.WorkerReportsProgress = true;
10659                     bw.WorkerSupportsCancellation = true;
10660                     bw.DoWork += GetTimelineWorker_DoWork;
10661                     bw.ProgressChanged += GetTimelineWorker_ProgressChanged;
10662                     bw.RunWorkerCompleted += GetTimelineWorker_RunWorkerCompleted;
10663                 }
10664                 else
10665                 {
10666                     if (_bwFollower.IsBusy == false)
10667                         bw = _bwFollower;
10668                 }
10669             }
10670             if (bw == null) return;
10671
10672             bw.RunWorkerAsync(args);
10673         }
10674
10675         private void StartUserStream()
10676         {
10677             tw.NewPostFromStream += tw_NewPostFromStream;
10678             tw.UserStreamStarted += tw_UserStreamStarted;
10679             tw.UserStreamStopped += tw_UserStreamStopped;
10680             tw.PostDeleted += tw_PostDeleted;
10681             tw.UserStreamEventReceived += tw_UserStreamEventArrived;
10682
10683             MenuItemUserStream.Text = "&UserStream ■";
10684             MenuItemUserStream.Enabled = true;
10685             StopToolStripMenuItem.Text = "&Start";
10686             StopToolStripMenuItem.Enabled = true;
10687             if (SettingDialog.UserstreamStartup) tw.StartUserStream();
10688         }
10689
10690         private void TweenMain_Shown(object sender, EventArgs e)
10691         {
10692             try
10693             {
10694                 PostBrowser.Url = new Uri("about:blank");
10695                 PostBrowser.DocumentText = "";       //発言詳細部初期化
10696             }
10697             catch (Exception)
10698             {
10699             }
10700
10701             NotifyIcon1.Visible = true;
10702
10703             if (this.IsNetworkAvailable())
10704             {
10705                 GetTimeline(MyCommon.WORKERTYPE.BlockIds, 0, 0, "");
10706                 if (SettingDialog.StartupFollowers)
10707                 {
10708                     GetTimeline(MyCommon.WORKERTYPE.Follower, 0, 0, "");
10709                 }
10710                 GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
10711                 StartUserStream();
10712                 _waitTimeline = true;
10713                 GetTimeline(MyCommon.WORKERTYPE.Timeline, 1, 1, "");
10714                 _waitReply = true;
10715                 GetTimeline(MyCommon.WORKERTYPE.Reply, 1, 1, "");
10716                 _waitDm = true;
10717                 GetTimeline(MyCommon.WORKERTYPE.DirectMessegeRcv, 1, 1, "");
10718                 if (SettingDialog.GetFav)
10719                 {
10720                     _waitFav = true;
10721                     GetTimeline(MyCommon.WORKERTYPE.Favorites, 1, 1, "");
10722                 }
10723                 _waitPubSearch = true;
10724                 GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, "");  //tabname="":全タブ
10725                 _waitUserTimeline = true;
10726                 GetTimeline(MyCommon.WORKERTYPE.UserTimeline, 1, 0, "");  //tabname="":全タブ
10727                 _waitLists = true;
10728                 GetTimeline(MyCommon.WORKERTYPE.List, 1, 0, "");  //tabname="":全タブ
10729                 int i = 0;
10730                 int j = 0;
10731                 while (IsInitialRead() && !MyCommon._endingFlag)
10732                 {
10733                     System.Threading.Thread.Sleep(100);
10734                     Application.DoEvents();
10735                     i += 1;
10736                     j += 1;
10737                     if (j > 1200) break; // 120秒間初期処理が終了しなかったら強制的に打ち切る
10738                     if (i > 50)
10739                     {
10740                         if (MyCommon._endingFlag)
10741                             return;
10742                         i = 0;
10743                     }
10744                 }
10745
10746                 if (MyCommon._endingFlag) return;
10747
10748                 //バージョンチェック(引数:起動時チェックの場合はtrue・・・チェック結果のメッセージを表示しない)
10749                 if (SettingDialog.StartupVersion)
10750                     CheckNewVersion(true);
10751
10752                 // 取得失敗の場合は再試行する
10753                 if (!tw.GetFollowersSuccess && SettingDialog.StartupFollowers)
10754                     GetTimeline(MyCommon.WORKERTYPE.Follower, 0, 0, "");
10755
10756                 // 取得失敗の場合は再試行する
10757                 if (SettingDialog.TwitterConfiguration.PhotoSizeLimit == 0)
10758                     GetTimeline(MyCommon.WORKERTYPE.Configuration, 0, 0, "");
10759
10760                 // 権限チェック read/write権限(xAuthで取得したトークン)の場合は再認証を促す
10761                 if (MyCommon.TwitterApiInfo.AccessLevel == ApiAccessLevel.ReadWrite)
10762                 {
10763                     MessageBox.Show(Properties.Resources.ReAuthorizeText);
10764                     SettingStripMenuItem_Click(null, null);
10765                 }
10766
10767                 //
10768             }
10769             _initial = false;
10770
10771             TimerTimeline.Enabled = true;
10772         }
10773
10774         private bool IsInitialRead()
10775         {
10776             return _waitTimeline || _waitReply || _waitDm || _waitFav || _waitPubSearch || _waitUserTimeline || _waitLists;
10777         }
10778
10779         private void doGetFollowersMenu()
10780         {
10781             GetTimeline(MyCommon.WORKERTYPE.Follower, 1, 0, "");
10782             DispSelectedPost(true);
10783         }
10784
10785         private void GetFollowersAllToolStripMenuItem_Click(object sender, EventArgs e)
10786         {
10787             doGetFollowersMenu();
10788         }
10789
10790         private void doReTweetUnofficial()
10791         {
10792             //RT @id:内容
10793             if (this.ExistCurrentPost)
10794             {
10795                 if (_curPost.IsDm ||
10796                     !StatusText.Enabled) return;
10797
10798                 if (_curPost.IsProtect)
10799                 {
10800                     MessageBox.Show("Protected.");
10801                     return;
10802                 }
10803                 string rtdata = _curPost.Text;
10804                 rtdata = CreateRetweetUnofficial(rtdata);
10805
10806                 StatusText.Text = "RT @" + _curPost.ScreenName + ": " + HttpUtility.HtmlDecode(rtdata);
10807
10808                 StatusText.SelectionStart = 0;
10809                 StatusText.Focus();
10810             }
10811         }
10812
10813         private void ReTweetStripMenuItem_Click(object sender, EventArgs e)
10814         {
10815             doReTweetUnofficial();
10816         }
10817
10818         private void doReTweetOfficial(bool isConfirm)
10819         {
10820             //公式RT
10821             if (this.ExistCurrentPost)
10822             {
10823                 if (_curPost.IsProtect)
10824                 {
10825                     MessageBox.Show("Protected.");
10826                     _DoFavRetweetFlags = false;
10827                     return;
10828                 }
10829                 if (_curList.SelectedIndices.Count > 15)
10830                 {
10831                     MessageBox.Show(Properties.Resources.RetweetLimitText);
10832                     _DoFavRetweetFlags = false;
10833                     return;
10834                 }
10835                 else if (_curList.SelectedIndices.Count > 1)
10836                 {
10837                     string QuestionText = Properties.Resources.RetweetQuestion2;
10838                     if (_DoFavRetweetFlags) QuestionText = Properties.Resources.FavoriteRetweetQuestionText1;
10839                     switch (MessageBox.Show(QuestionText, "Retweet", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
10840                     {
10841                         case DialogResult.Cancel:
10842                         case DialogResult.No:
10843                             _DoFavRetweetFlags = false;
10844                             return;
10845                     }
10846                 }
10847                 else
10848                 {
10849                     if (_curPost.IsDm || _curPost.IsMe)
10850                     {
10851                         _DoFavRetweetFlags = false;
10852                         return;
10853                     }
10854                     if (!SettingDialog.RetweetNoConfirm)
10855                     {
10856                         string Questiontext = Properties.Resources.RetweetQuestion1;
10857                         if (_DoFavRetweetFlags) Questiontext = Properties.Resources.FavoritesRetweetQuestionText2;
10858                         if (isConfirm && MessageBox.Show(Questiontext, "Retweet", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
10859                         {
10860                             _DoFavRetweetFlags = false;
10861                             return;
10862                         }
10863                     }
10864                 }
10865                 GetWorkerArg args = new GetWorkerArg();
10866                 args.ids = new List<long>();
10867                 args.sIds = new List<long>();
10868                 args.tName = _curTab.Text;
10869                 args.type = MyCommon.WORKERTYPE.Retweet;
10870                 foreach (int idx in _curList.SelectedIndices)
10871                 {
10872                     PostClass post = GetCurTabPost(idx);
10873                     if (!post.IsMe && !post.IsProtect && !post.IsDm) args.ids.Add(post.StatusId);
10874                 }
10875                 RunAsync(args);
10876             }
10877         }
10878
10879         private void ReTweetOriginalStripMenuItem_Click(object sender, EventArgs e)
10880         {
10881             doReTweetOfficial(true);
10882         }
10883
10884         private void FavoritesRetweetOriginal()
10885         {
10886             if (!this.ExistCurrentPost) return;
10887             _DoFavRetweetFlags = true;
10888             doReTweetOfficial(true);
10889             if (_DoFavRetweetFlags)
10890             {
10891                 _DoFavRetweetFlags = false;
10892                 FavoriteChange(true, false);
10893             }
10894         }
10895
10896         private void FavoritesRetweetUnofficial()
10897         {
10898             if (this.ExistCurrentPost && !_curPost.IsDm)
10899             {
10900                 _DoFavRetweetFlags = true;
10901                 FavoriteChange(true);
10902                 if (!_curPost.IsProtect && _DoFavRetweetFlags)
10903                 {
10904                     _DoFavRetweetFlags = false;
10905                     doReTweetUnofficial();
10906                 }
10907             }
10908         }
10909
10910         private string CreateRetweetUnofficial(string status)
10911         {
10912             // Twitterにより省略されているURLを含むaタグをキャプチャしてリンク先URLへ置き換える
10913             status = Regex.Replace(status, @"<a target=""_self"" href=""(?<url>[^""]+)"" title=""(?<title>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${title}");
10914
10915             //その他のリンク(@IDなど)を置き換える
10916             status = Regex.Replace(status, @"@<a target=""_self"" href=""https?://twitter.com/(#!/)?(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "@${url}");
10917             //ハッシュタグ
10918             status = Regex.Replace(status, @"<a target=""_self"" href=""(?<url>[^""]+)""[^>]*>(?<link>[^<]+)</a>", "${link}");
10919             //<br>タグ除去
10920             if (StatusText.Multiline)
10921                 status = Regex.Replace(status, @"(\r\n|\n|\r)?<br>", "\r\n", RegexOptions.IgnoreCase | RegexOptions.Multiline);
10922             else
10923                 status = Regex.Replace(status, @"(\r\n|\n|\r)?<br>", " ", RegexOptions.IgnoreCase | RegexOptions.Multiline);
10924
10925             _reply_to_id = 0;
10926             _reply_to_name = "";
10927             status = status.Replace("&nbsp;", " ");
10928
10929             return status;
10930         }
10931
10932         private void DumpPostClassToolStripMenuItem_Click(object sender, EventArgs e)
10933         {
10934             if (_curPost != null)
10935                 DispSelectedPost(true);
10936         }
10937
10938         private void MenuItemHelp_DropDownOpening(object sender, EventArgs e)
10939         {
10940             if (MyCommon.DebugBuild || MyCommon.IsKeyDown(Keys.CapsLock, Keys.Control, Keys.Shift))
10941                 DebugModeToolStripMenuItem.Visible = true;
10942             else
10943                 DebugModeToolStripMenuItem.Visible = false;
10944         }
10945
10946         private void ToolStripMenuItemUrlAutoShorten_CheckedChanged(object sender, EventArgs e)
10947         {
10948             SettingDialog.UrlConvertAuto = ToolStripMenuItemUrlAutoShorten.Checked;
10949         }
10950
10951         private void ContextMenuPostMode_Opening(object sender, CancelEventArgs e)
10952         {
10953             ToolStripMenuItemUrlAutoShorten.Checked = SettingDialog.UrlConvertAuto;
10954         }
10955
10956         private void TraceOutToolStripMenuItem_Click(object sender, EventArgs e)
10957         {
10958             if (TraceOutToolStripMenuItem.Checked)
10959                 MyCommon.TraceFlag = true;
10960             else
10961                 MyCommon.TraceFlag = false;
10962         }
10963
10964         private void TweenMain_Deactivate(object sender, EventArgs e)
10965         {
10966             //画面が非アクティブになったら、発言欄の背景色をデフォルトへ
10967             this.StatusText_Leave(StatusText, System.EventArgs.Empty);
10968         }
10969
10970         private void TabRenameMenuItem_Click(object sender, EventArgs e)
10971         {
10972             if (string.IsNullOrEmpty(_rclickTabName)) return;
10973             TabRename(ref _rclickTabName);
10974         }
10975
10976         private void BitlyToolStripMenuItem_Click(object sender, EventArgs e)
10977         {
10978             UrlConvert(MyCommon.UrlConverter.Bitly);
10979         }
10980
10981         private void JmpToolStripMenuItem_Click(object sender, EventArgs e)
10982         {
10983             UrlConvert(MyCommon.UrlConverter.Jmp);
10984         }
10985
10986
10987         private class GetApiInfoArgs
10988         {
10989             public Twitter tw;
10990             public ApiInfo info;
10991         }
10992
10993         private void GetApiInfo_Dowork(object sender, DoWorkEventArgs e)
10994         {
10995             GetApiInfoArgs args = (GetApiInfoArgs)e.Argument;
10996             e.Result = tw.GetInfoApi(args.info);
10997         }
10998
10999         private void ApiInfoMenuItem_Click(object sender, EventArgs e)
11000         {
11001             ApiInfo info = new ApiInfo();
11002             StringBuilder tmp = new StringBuilder();
11003             GetApiInfoArgs args = new GetApiInfoArgs() {tw = tw, info = info};
11004
11005             using (FormInfo dlg = new FormInfo(this, Properties.Resources.ApiInfo6, GetApiInfo_Dowork, null, args))
11006             {
11007                 dlg.ShowDialog();
11008                 if ((bool)dlg.Result)
11009                 {
11010                     tmp.AppendLine(Properties.Resources.ApiInfo1 + args.info.MaxCount.ToString());
11011                     tmp.AppendLine(Properties.Resources.ApiInfo2 + args.info.RemainCount.ToString());
11012                     tmp.AppendLine(Properties.Resources.ApiInfo3 + args.info.ResetTime.ToString());
11013                     tmp.AppendLine(Properties.Resources.ApiInfo7 + (tw.UserStreamEnabled ? Properties.Resources.Enable : Properties.Resources.Disable).ToString());
11014
11015                     tmp.AppendLine();
11016                     tmp.AppendLine(Properties.Resources.ApiInfo8 + args.info.AccessLevel.ToString());
11017                     SetStatusLabelUrl();
11018
11019                     tmp.AppendLine();
11020                     tmp.AppendLine(Properties.Resources.ApiInfo9 + (args.info.MediaMaxCount < 0 ? Properties.Resources.ApiInfo91 : args.info.MediaMaxCount.ToString()));
11021                     tmp.AppendLine(Properties.Resources.ApiInfo10 + (args.info.MediaRemainCount < 0 ? Properties.Resources.ApiInfo91 : args.info.MediaRemainCount.ToString()));
11022                     tmp.AppendLine(Properties.Resources.ApiInfo11 + (args.info.MediaResetTime == new DateTime() ? Properties.Resources.ApiInfo91 : args.info.MediaResetTime.ToString()));
11023                 }
11024                 else
11025                 {
11026                     tmp.Append(Properties.Resources.ApiInfo5);
11027                 }
11028             }
11029
11030             MessageBox.Show(tmp.ToString(), Properties.Resources.ApiInfo4, MessageBoxButtons.OK, MessageBoxIcon.Information);
11031         }
11032
11033         private void FollowCommandMenuItem_Click(object sender, EventArgs e)
11034         {
11035             string id = "";
11036             if (_curPost != null) id = _curPost.ScreenName;
11037             FollowCommand(id);
11038         }
11039
11040         private void FollowCommand_DoWork(object sender, DoWorkEventArgs e)
11041         {
11042             FollowRemoveCommandArgs arg = (FollowRemoveCommandArgs)e.Argument;
11043             e.Result = arg.tw.PostFollowCommand(arg.id);
11044         }
11045
11046         private void FollowCommand(string id)
11047         {
11048             using (InputTabName inputName = new InputTabName())
11049             {
11050                 inputName.FormTitle = "Follow";
11051                 inputName.FormDescription = Properties.Resources.FRMessage1;
11052                 inputName.TabName = id;
11053                 if (inputName.ShowDialog() == DialogResult.OK &&
11054                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
11055                 {
11056                     FollowRemoveCommandArgs arg = new FollowRemoveCommandArgs();
11057                     arg.tw = tw;
11058                     arg.id = inputName.TabName.Trim();
11059                     using (FormInfo _info = new FormInfo(this, Properties.Resources.FollowCommandText1,
11060                                                          FollowCommand_DoWork,
11061                                                          null,
11062                                                          arg))
11063                     {
11064                         _info.ShowDialog();
11065                         string ret = (string)_info.Result;
11066                         if (!string.IsNullOrEmpty(ret))
11067                             MessageBox.Show(Properties.Resources.FRMessage2 + ret);
11068                         else
11069                             MessageBox.Show(Properties.Resources.FRMessage3);
11070                     }
11071                 }
11072             }
11073         }
11074
11075         private void RemoveCommandMenuItem_Click(object sender, EventArgs e)
11076         {
11077             string id = "";
11078             if (_curPost != null) id = _curPost.ScreenName;
11079             RemoveCommand(id, false);
11080         }
11081
11082         private class FollowRemoveCommandArgs
11083         {
11084             public Twitter tw;
11085             public string id;
11086         }
11087
11088         private void RemoveCommand_DoWork(object sender , DoWorkEventArgs e)
11089         {
11090             FollowRemoveCommandArgs arg = (FollowRemoveCommandArgs)e.Argument;
11091             e.Result = arg.tw.PostRemoveCommand(arg.id);
11092         }
11093
11094         private void RemoveCommand(string id, bool skipInput)
11095         {
11096             FollowRemoveCommandArgs arg = new FollowRemoveCommandArgs();
11097             arg.tw = tw;
11098             arg.id = id;
11099             if (!skipInput)
11100             {
11101                 using (InputTabName inputName = new InputTabName())
11102                 {
11103                     inputName.FormTitle = "Unfollow";
11104                     inputName.FormDescription = Properties.Resources.FRMessage1;
11105                     inputName.TabName = id;
11106                     if (inputName.ShowDialog() == DialogResult.OK &&
11107                         !string.IsNullOrEmpty(inputName.TabName.Trim()))
11108                     {
11109                         arg.tw = tw;
11110                         arg.id = inputName.TabName.Trim();
11111                     }
11112                     else
11113                     {
11114                         return;
11115                     }
11116                 }
11117             }
11118
11119             using (FormInfo _info = new FormInfo(this, Properties.Resources.RemoveCommandText1,
11120                                                  RemoveCommand_DoWork,
11121                                                  null,
11122                                                  arg))
11123             {
11124                 _info.ShowDialog();
11125                 string ret = (string)_info.Result;
11126                 if (!string.IsNullOrEmpty(ret))
11127                     MessageBox.Show(Properties.Resources.FRMessage2 + ret);
11128                 else
11129                     MessageBox.Show(Properties.Resources.FRMessage3);
11130             }
11131         }
11132
11133         private void FriendshipMenuItem_Click(object sender, EventArgs e)
11134         {
11135             string id = "";
11136             if (_curPost != null)
11137                 id = _curPost.ScreenName;
11138
11139             ShowFriendship(id);
11140         }
11141
11142         private class ShowFriendshipArgs
11143         {
11144             public Twitter tw;
11145             public class FriendshipInfo
11146             {
11147                 public string id = "";
11148                 public bool isFollowing = false;
11149                 public bool isFollowed = false;
11150                 public bool isError = false;
11151                 public FriendshipInfo(string id)
11152                 {
11153                     this.id = id;
11154                 }
11155             }
11156             public List<FriendshipInfo> ids = new List<FriendshipInfo>();
11157         }
11158
11159         private void ShowFriendship_DoWork(object sender, DoWorkEventArgs e)
11160         {
11161             ShowFriendshipArgs arg = (ShowFriendshipArgs)e.Argument;
11162             string result = "";
11163             foreach (ShowFriendshipArgs.FriendshipInfo fInfo in arg.ids)
11164             {
11165                 string rt = arg.tw.GetFriendshipInfo(fInfo.id, ref fInfo.isFollowing, ref fInfo.isFollowed);
11166                 if (!string.IsNullOrEmpty(rt))
11167                 {
11168                     if (string.IsNullOrEmpty(result)) result = rt;
11169                     fInfo.isError = true;
11170                 }
11171             }
11172             e.Result = result;
11173         }
11174
11175         private void ShowFriendship(string id)
11176         {
11177             ShowFriendshipArgs args = new ShowFriendshipArgs();
11178             args.tw = tw;
11179             using (InputTabName inputName = new InputTabName())
11180             {
11181                 inputName.FormTitle = "Show Friendships";
11182                 inputName.FormDescription = Properties.Resources.FRMessage1;
11183                 inputName.TabName = id;
11184                 if (inputName.ShowDialog() == DialogResult.OK &&
11185                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
11186                 {
11187                     string ret = "";
11188                     args.ids.Add(new ShowFriendshipArgs.FriendshipInfo(inputName.TabName.Trim()));
11189                     using (FormInfo _info = new FormInfo(this, Properties.Resources.ShowFriendshipText1,
11190                                                          ShowFriendship_DoWork,
11191                                                          null,
11192                                                          args))
11193                     {
11194                         _info.ShowDialog();
11195                         ret = (string)_info.Result;
11196                     }
11197                     string result = "";
11198                     if (string.IsNullOrEmpty(ret))
11199                     {
11200                         if (args.ids[0].isFollowing)
11201                         {
11202                             result = Properties.Resources.GetFriendshipInfo1 + System.Environment.NewLine;
11203                         }
11204                         else
11205                         {
11206                             result = Properties.Resources.GetFriendshipInfo2 + System.Environment.NewLine;
11207                         }
11208                         if (args.ids[0].isFollowed)
11209                         {
11210                             result += Properties.Resources.GetFriendshipInfo3;
11211                         }
11212                         else
11213                         {
11214                             result += Properties.Resources.GetFriendshipInfo4;
11215                         }
11216                         result = args.ids[0].id + Properties.Resources.GetFriendshipInfo5 + System.Environment.NewLine + result;
11217                     }
11218                     else
11219                     {
11220                         result = ret;
11221                     }
11222                     MessageBox.Show(result);
11223                 }
11224             }
11225         }
11226
11227         private void ShowFriendship(string[] ids)
11228         {
11229             foreach (string id in ids)
11230             {
11231                 string ret = "";
11232                 ShowFriendshipArgs args = new ShowFriendshipArgs();
11233                 args.tw = tw;
11234                 args.ids.Add(new ShowFriendshipArgs.FriendshipInfo(id.Trim()));
11235                 using (FormInfo _info = new FormInfo(this, Properties.Resources.ShowFriendshipText1,
11236                                                      ShowFriendship_DoWork,
11237                                                      null,
11238                                                      args))
11239                 {
11240                     _info.ShowDialog();
11241                     ret = (string)_info.Result;
11242                 }
11243                 string result = "";
11244                 ShowFriendshipArgs.FriendshipInfo fInfo = args.ids[0];
11245                 string ff = "";
11246                 if (string.IsNullOrEmpty(ret))
11247                 {
11248                     ff = "  ";
11249                     if (fInfo.isFollowing)
11250                     {
11251                         ff += Properties.Resources.GetFriendshipInfo1;
11252                     }
11253                     else
11254                     {
11255                         ff += Properties.Resources.GetFriendshipInfo2;
11256                     }
11257
11258                     ff += System.Environment.NewLine + "  ";
11259                     if (fInfo.isFollowed)
11260                     {
11261                         ff += Properties.Resources.GetFriendshipInfo3;
11262                     }
11263                     else
11264                     {
11265                         ff += Properties.Resources.GetFriendshipInfo4;
11266                     }
11267                     result += fInfo.id + Properties.Resources.GetFriendshipInfo5 + System.Environment.NewLine + ff;
11268                     if (fInfo.isFollowing)
11269                     {
11270                         if (MessageBox.Show(
11271                             Properties.Resources.GetFriendshipInfo7 + System.Environment.NewLine + result, Properties.Resources.GetFriendshipInfo8,
11272                             MessageBoxButtons.YesNo,
11273                             MessageBoxIcon.Question,
11274                             MessageBoxDefaultButton.Button2) == DialogResult.Yes)
11275                         {
11276                             RemoveCommand(fInfo.id, true);
11277                         }
11278                     }
11279                     else
11280                     {
11281                         MessageBox.Show(result);
11282                     }
11283                 }
11284                 else
11285                 {
11286                     MessageBox.Show(ret);
11287                 }
11288             }
11289         }
11290
11291         private void OwnStatusMenuItem_Click(object sender, EventArgs e)
11292         {
11293             doShowUserStatus(tw.Username, false);
11294             //if (!string.IsNullOrEmpty(tw.UserInfoXml))
11295             //{
11296             //    doShowUserStatus(tw.Username, false);
11297             //}
11298             //else
11299             //{
11300             //    MessageBox.Show(Properties.Resources.ShowYourProfileText1, "Your status", MessageBoxButtons.OK, MessageBoxIcon.Information);
11301             //    return;
11302             //}
11303         }
11304
11305         // TwitterIDでない固定文字列を調べる(文字列検証のみ 実際に取得はしない)
11306         // URLから切り出した文字列を渡す
11307
11308         public bool IsTwitterId(string name)
11309         {
11310             if (SettingDialog.TwitterConfiguration.NonUsernamePaths == null || SettingDialog.TwitterConfiguration.NonUsernamePaths.Length == 0)
11311                 return !Regex.Match(name, @"^(about|jobs|tos|privacy|who_to_follow|download|messages)$", RegexOptions.IgnoreCase).Success;
11312             else
11313                 return !SettingDialog.TwitterConfiguration.NonUsernamePaths.Contains(name.ToLower());
11314         }
11315
11316         private string GetUserId()
11317         {
11318             Match m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?$");
11319             if (m.Success && IsTwitterId(m.Result("${ScreenName}")))
11320                 return m.Result("${ScreenName}");
11321             else
11322                 return null;
11323         }
11324
11325         private void FollowContextMenuItem_Click(object sender, EventArgs e)
11326         {
11327             string name = GetUserId();
11328             if (name != null) FollowCommand(name);
11329         }
11330
11331         private void RemoveContextMenuItem_Click(object sender, EventArgs e)
11332         {
11333             string name = GetUserId();
11334             if (name != null) RemoveCommand(name, false);
11335         }
11336
11337         private void FriendshipContextMenuItem_Click(object sender, EventArgs e)
11338         {
11339             string name = GetUserId();
11340             if (name != null) ShowFriendship(name);
11341         }
11342
11343         private void FriendshipAllMenuItem_Click(object sender, EventArgs e)
11344         {
11345             MatchCollection ma = Regex.Matches(this.PostBrowser.DocumentText, @"href=""https?://twitter.com/(#!/)?(?<ScreenName>[a-zA-Z0-9_]+)(/status(es)?/[0-9]+)?""");
11346             List<string> ids = new List<string>();
11347             foreach (Match mu in ma)
11348             {
11349                 if (mu.Result("${ScreenName}").ToLower() != tw.Username.ToLower())
11350                 {
11351                     ids.Add(mu.Result("${ScreenName}"));
11352                 }
11353             }
11354             ShowFriendship(ids.ToArray());
11355         }
11356
11357         private void ShowUserStatusContextMenuItem_Click(object sender, EventArgs e)
11358         {
11359             string name = GetUserId();
11360             if (name != null) ShowUserStatus(name);
11361         }
11362
11363         private void SearchPostsDetailToolStripMenuItem_Click(object sender, EventArgs e)
11364         {
11365             string name = GetUserId();
11366             if (name != null) AddNewTabForUserTimeline(name);
11367         }
11368
11369         private void SearchAtPostsDetailToolStripMenuItem_Click(object sender, EventArgs e)
11370         {
11371             string name = GetUserId();
11372             if (name != null) AddNewTabForSearch("@" + name);
11373         }
11374
11375         private void IdeographicSpaceToSpaceToolStripMenuItem_Click(object sender, EventArgs e)
11376         {
11377             _modifySettingCommon = true;
11378         }
11379
11380         private void ToolStripFocusLockMenuItem_CheckedChanged(object sender, EventArgs e)
11381         {
11382             _modifySettingCommon = true;
11383         }
11384
11385         private void doQuote()
11386         {
11387             //QT @id:内容
11388             //返信先情報付加
11389             if (this.ExistCurrentPost)
11390             {
11391                 if (_curPost.IsDm ||
11392                     !StatusText.Enabled) return;
11393
11394                 if (_curPost.IsProtect)
11395                 {
11396                     MessageBox.Show("Protected.");
11397                     return;
11398                 }
11399                 string rtdata = _curPost.Text;
11400                 rtdata = CreateRetweetUnofficial(rtdata);
11401
11402                 StatusText.Text = " QT @" + _curPost.ScreenName + ": " + HttpUtility.HtmlDecode(rtdata);
11403                 if (_curPost.RetweetedId == 0)
11404                 {
11405                     _reply_to_id = _curPost.StatusId;
11406                 }
11407                 else
11408                 {
11409                     _reply_to_id = _curPost.RetweetedId;
11410                 }
11411                 _reply_to_name = _curPost.ScreenName;
11412
11413                 StatusText.SelectionStart = 0;
11414                 StatusText.Focus();
11415             }
11416         }
11417
11418         private void QuoteStripMenuItem_Click(object sender, EventArgs e) // Handles QuoteStripMenuItem.Click, QtOpMenuItem.Click
11419         {
11420             doQuote();
11421         }
11422
11423         private void SearchButton_Click(object sender, EventArgs e)
11424         {
11425             //公式検索
11426             Control pnl = ((Control)sender).Parent;
11427             if (pnl == null) return;
11428             string tbName = pnl.Parent.Text;
11429             TabClass tb = _statuses.Tabs[tbName];
11430             ComboBox cmb = (ComboBox)pnl.Controls["comboSearch"];
11431             ComboBox cmbLang = (ComboBox)pnl.Controls["comboLang"];
11432             ComboBox cmbusline = (ComboBox)pnl.Controls["comboUserline"];
11433             cmb.Text = cmb.Text.Trim();
11434             // 検索式演算子 OR についてのみ大文字しか認識しないので強制的に大文字とする
11435             bool Quote = false;
11436             StringBuilder buf = new StringBuilder();
11437             char[] c = cmb.Text.ToCharArray();
11438             for (int cnt = 0; cnt < cmb.Text.Length; cnt++)
11439             {
11440                 if (cnt > cmb.Text.Length - 4)
11441                 {
11442                     buf.Append(cmb.Text.Substring(cnt));
11443                     break;
11444                 }
11445                 if (c[cnt] == '"')
11446                 {
11447                     Quote = !Quote;
11448                 }
11449                 else
11450                 {
11451                     if (!Quote && cmb.Text.Substring(cnt, 4).Equals(" or ", StringComparison.OrdinalIgnoreCase))
11452                     {
11453                         buf.Append(" OR ");
11454                         cnt += 3;
11455                         continue;
11456                     }
11457                 }
11458                 buf.Append(c[cnt]);
11459             }
11460             cmb.Text = buf.ToString();
11461
11462             tb.SearchWords = cmb.Text;
11463             tb.SearchLang = cmbLang.Text;
11464             if (string.IsNullOrEmpty(cmb.Text))
11465             {
11466                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
11467                 SaveConfigsTabs();
11468                 return;
11469             }
11470             if (tb.IsQueryChanged())
11471             {
11472                 int idx = ((ComboBox)pnl.Controls["comboSearch"]).Items.IndexOf(tb.SearchWords);
11473                 if (idx > -1) ((ComboBox)pnl.Controls["comboSearch"]).Items.RemoveAt(idx);
11474                 ((ComboBox)pnl.Controls["comboSearch"]).Items.Insert(0, tb.SearchWords);
11475                 cmb.Text = tb.SearchWords;
11476                 cmb.SelectAll();
11477                 DetailsListView lst = (DetailsListView)pnl.Parent.Tag;
11478                 lst.VirtualListSize = 0;
11479                 lst.Items.Clear();
11480                 _statuses.ClearTabIds(tbName);
11481                 SaveConfigsTabs();   //検索条件の保存
11482             }
11483
11484             GetTimeline(MyCommon.WORKERTYPE.PublicSearch, 1, 0, tbName);
11485             ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
11486         }
11487
11488         private void RefreshMoreStripMenuItem_Click(object sender, EventArgs e)
11489         {
11490             //もっと前を取得
11491             DoRefreshMore();
11492         }
11493
11494         private void UndoRemoveTabMenuItem_Click(object sender, EventArgs e)
11495         {
11496             if (_statuses.RemovedTab.Count == 0)
11497             {
11498                 MessageBox.Show("There isn't removed tab.", "Undo", MessageBoxButtons.OK, MessageBoxIcon.Information);
11499                 return;
11500             }
11501             else
11502             {
11503                 TabClass tb = _statuses.RemovedTab.Pop();
11504                 string renamed = tb.TabName;
11505                 for (int i = 1; i < int.MaxValue; i++)
11506                 {
11507                     if (!_statuses.ContainsTab(renamed)) break;
11508                     renamed = tb.TabName + "(" + i.ToString() + ")";
11509                 }
11510                 tb.TabName = renamed;
11511                 _statuses.Tabs.Add(renamed, tb);
11512                 AddNewTab(renamed, false, tb.TabType, tb.ListInfo);
11513                 ListTab.SelectedIndex = ListTab.TabPages.Count - 1;
11514                 SaveConfigsTabs();
11515             }
11516         }
11517
11518         private void doMoveToRTHome()
11519         {
11520             if (_curList.SelectedIndices.Count > 0)
11521             {
11522                 PostClass post = GetCurTabPost(_curList.SelectedIndices[0]);
11523                 if (post.RetweetedId > 0)
11524                 {
11525                     OpenUriAsync("http://twitter.com/" + GetCurTabPost(_curList.SelectedIndices[0]).RetweetedBy);
11526                 }
11527             }
11528         }
11529
11530         private void MoveToRTHomeMenuItem_Click(object sender, EventArgs e)
11531         {
11532             doMoveToRTHome();
11533         }
11534
11535         private void IdFilterAddMenuItem_Click(object sender, EventArgs e)
11536         {
11537             string name = GetUserId();
11538             if (name != null)
11539             {
11540                 string tabName;
11541
11542                 //未選択なら処理終了
11543                 if (_curList.SelectedIndices.Count == 0) return;
11544
11545                 //タブ選択(or追加)
11546                 if (!SelectTab(out tabName)) return;
11547
11548                 bool mv = false;
11549                 bool mk = false;
11550                 MoveOrCopy(ref mv, ref mk);
11551
11552                 FiltersClass fc = new FiltersClass();
11553                 fc.NameFilter = name;
11554                 fc.SearchBoth = true;
11555                 fc.MoveFrom = mv;
11556                 fc.SetMark = mk;
11557                 fc.UseRegex = false;
11558                 fc.SearchUrl = false;
11559                 _statuses.Tabs[tabName].AddFilter(fc);
11560
11561                 try
11562                 {
11563                     this.Cursor = Cursors.WaitCursor;
11564                     _itemCache = null;
11565                     _postCache = null;
11566                     _curPost = null;
11567                     _curItemIndex = -1;
11568                     _statuses.FilterAll();
11569                     foreach (TabPage tb in ListTab.TabPages)
11570                     {
11571                         ((DetailsListView)tb.Tag).VirtualListSize = _statuses.Tabs[tb.Text].AllCount;
11572                         if (_statuses.Tabs[tb.Text].UnreadCount > 0)
11573                         {
11574                             if (SettingDialog.TabIconDisp)
11575                                 tb.ImageIndex = 0;
11576                         }
11577                         else
11578                         {
11579                             if (SettingDialog.TabIconDisp)
11580                                 tb.ImageIndex = -1;
11581                         }
11582                     }
11583                     if (!SettingDialog.TabIconDisp) ListTab.Refresh();
11584                 }
11585                 finally
11586                 {
11587                     this.Cursor = Cursors.Default;
11588                 }
11589                 SaveConfigsTabs();
11590             }
11591         }
11592
11593         private void ListManageUserContextToolStripMenuItem_Click(object sender, EventArgs e)
11594         {
11595             string user;
11596
11597             ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
11598
11599             if (menuItem.Owner == this.ContextMenuPostBrowser)
11600             {
11601                 user = GetUserId();
11602                 if (user == null) return;
11603             }
11604             else if (this._curPost != null)
11605             {
11606                 user = this._curPost.ScreenName;
11607             }
11608             else
11609             {
11610                 return;
11611             }
11612
11613             if (TabInformations.GetInstance().SubscribableLists.Count == 0)
11614             {
11615                 string res = this.tw.GetListsApi();
11616
11617                 if (!string.IsNullOrEmpty(res))
11618                 {
11619                     MessageBox.Show("Failed to get lists. (" + res + ")");
11620                     return;
11621                 }
11622             }
11623
11624             using (MyLists listSelectForm = new MyLists(user, this.tw))
11625             {
11626                 listSelectForm.ShowDialog(this);
11627             }
11628         }
11629
11630         private void SearchControls_Enter(object sender, EventArgs e)
11631         {
11632             Control pnl = (Control)sender;
11633             foreach (Control ctl in pnl.Controls)
11634             {
11635                 ctl.TabStop = true;
11636             }
11637         }
11638
11639         private void SearchControls_Leave(object sender, EventArgs e)
11640         {
11641             Control pnl = (Control)sender;
11642             foreach (Control ctl in pnl.Controls)
11643             {
11644                 ctl.TabStop = false;
11645             }
11646         }
11647
11648         private void PublicSearchQueryMenuItem_Click(object sender, EventArgs e)
11649         {
11650             if (ListTab.SelectedTab != null)
11651             {
11652                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.PublicSearch) return;
11653                 ListTab.SelectedTab.Controls["panelSearch"].Controls["comboSearch"].Focus();
11654             }
11655         }
11656
11657         private void UseHashtagMenuItem_Click(object sender, EventArgs e)
11658         {
11659             Match m = Regex.Match(this._postBrowserStatusText, @"^https?://twitter.com/search\?q=%23(?<hash>.+)$");
11660             if (m.Success)
11661             {
11662                 HashMgr.SetPermanentHash("#" + m.Result("${hash}"));
11663                 HashStripSplitButton.Text = HashMgr.UseHash;
11664                 HashToggleMenuItem.Checked = true;
11665                 HashToggleToolStripMenuItem.Checked = true;
11666                 //使用ハッシュタグとして設定
11667                 _modifySettingCommon = true;
11668             }
11669         }
11670
11671         private void StatusLabel_DoubleClick(object sender, EventArgs e)
11672         {
11673             MessageBox.Show(StatusLabel.TextHistory, "Logs", MessageBoxButtons.OK, MessageBoxIcon.None);
11674         }
11675
11676         private void HashManageMenuItem_Click(object sender, EventArgs e)
11677         {
11678             DialogResult rslt = DialogResult.Cancel;
11679             try
11680             {
11681                 rslt = HashMgr.ShowDialog();
11682             }
11683             catch (Exception)
11684             {
11685                 return;
11686             }
11687             this.TopMost = SettingDialog.AlwaysTop;
11688             if (rslt == DialogResult.Cancel) return;
11689             if (!string.IsNullOrEmpty(HashMgr.UseHash))
11690             {
11691                 HashStripSplitButton.Text = HashMgr.UseHash;
11692                 HashToggleMenuItem.Checked = true;
11693                 HashToggleToolStripMenuItem.Checked = true;
11694             }
11695             else
11696             {
11697                 HashStripSplitButton.Text = "#[-]";
11698                 HashToggleMenuItem.Checked = false;
11699                 HashToggleToolStripMenuItem.Checked = false;
11700             }
11701             //if (HashMgr.IsInsert && HashMgr.UseHash != "")
11702             //{
11703             //    int sidx = StatusText.SelectionStart;
11704             //    string hash = HashMgr.UseHash + " ";
11705             //    if (sidx > 0)
11706             //    {
11707             //        if (StatusText.Text.Substring(sidx - 1, 1) != " ")
11708             //            hash = " " + hash;
11709             //    }
11710             //    StatusText.Text = StatusText.Text.Insert(sidx, hash);
11711             //    sidx += hash.Length;
11712             //    StatusText.SelectionStart = sidx;
11713             //    StatusText.Focus();
11714             //}
11715             _modifySettingCommon = true;
11716             this.StatusText_TextChanged(null, null);
11717         }
11718
11719         private void HashToggleMenuItem_Click(object sender, EventArgs e)
11720         {
11721             HashMgr.ToggleHash();
11722             if (!string.IsNullOrEmpty(HashMgr.UseHash))
11723             {
11724                 HashStripSplitButton.Text = HashMgr.UseHash;
11725                 HashToggleMenuItem.Checked = true;
11726                 HashToggleToolStripMenuItem.Checked = true;
11727             }
11728             else
11729             {
11730                 HashStripSplitButton.Text = "#[-]";
11731                 HashToggleMenuItem.Checked = false;
11732                 HashToggleToolStripMenuItem.Checked = false;
11733             }
11734             _modifySettingCommon = true;
11735             this.StatusText_TextChanged(null, null);
11736         }
11737
11738         private void HashStripSplitButton_ButtonClick(object sender, EventArgs e)
11739         {
11740             HashToggleMenuItem_Click(null, null);
11741         }
11742
11743         private void MenuItemOperate_DropDownOpening(object sender, EventArgs e)
11744         {
11745             if (ListTab.SelectedTab == null) return;
11746             if (_statuses == null || _statuses.Tabs == null || !_statuses.Tabs.ContainsKey(ListTab.SelectedTab.Text)) return;
11747             if (!this.ExistCurrentPost)
11748             {
11749                 this.ReplyOpMenuItem.Enabled = false;
11750                 this.ReplyAllOpMenuItem.Enabled = false;
11751                 this.DmOpMenuItem.Enabled = false;
11752                 this.ShowProfMenuItem.Enabled = false;
11753                 this.ShowUserTimelineToolStripMenuItem.Enabled = false;
11754                 this.ListManageMenuItem.Enabled = false;
11755                 this.OpenFavOpMenuItem.Enabled = false;
11756                 this.CreateTabRuleOpMenuItem.Enabled = false;
11757                 this.CreateIdRuleOpMenuItem.Enabled = false;
11758                 this.ReadOpMenuItem.Enabled = false;
11759                 this.UnreadOpMenuItem.Enabled = false;
11760             }
11761             else
11762             {
11763                 this.ReplyOpMenuItem.Enabled = true;
11764                 this.ReplyAllOpMenuItem.Enabled = true;
11765                 this.DmOpMenuItem.Enabled = true;
11766                 this.ShowProfMenuItem.Enabled = true;
11767                 this.ShowUserTimelineToolStripMenuItem.Enabled = true;
11768                 this.ListManageMenuItem.Enabled = true;
11769                 this.OpenFavOpMenuItem.Enabled = true;
11770                 this.CreateTabRuleOpMenuItem.Enabled = true;
11771                 this.CreateIdRuleOpMenuItem.Enabled = true;
11772                 this.ReadOpMenuItem.Enabled = true;
11773                 this.UnreadOpMenuItem.Enabled = true;
11774             }
11775
11776             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.DirectMessage || !this.ExistCurrentPost || _curPost.IsDm)
11777             {
11778                 this.FavOpMenuItem.Enabled = false;
11779                 this.UnFavOpMenuItem.Enabled = false;
11780                 this.OpenStatusOpMenuItem.Enabled = false;
11781                 this.OpenFavotterOpMenuItem.Enabled = false;
11782                 this.ShowRelatedStatusesMenuItem2.Enabled = false;
11783                 this.RtOpMenuItem.Enabled = false;
11784                 this.RtUnOpMenuItem.Enabled = false;
11785                 this.QtOpMenuItem.Enabled = false;
11786                 this.FavoriteRetweetMenuItem.Enabled = false;
11787                 this.FavoriteRetweetUnofficialMenuItem.Enabled = false;
11788                 if (this.ExistCurrentPost && _curPost.IsDm) this.DelOpMenuItem.Enabled = true;
11789             }
11790             else
11791             {
11792                 this.FavOpMenuItem.Enabled = true;
11793                 this.UnFavOpMenuItem.Enabled = true;
11794                 this.OpenStatusOpMenuItem.Enabled = true;
11795                 this.OpenFavotterOpMenuItem.Enabled = true;
11796                 this.ShowRelatedStatusesMenuItem2.Enabled = true;  //PublicSearchの時問題出るかも
11797
11798                 if (_curPost.IsMe)
11799                 {
11800                     this.RtOpMenuItem.Enabled = false;
11801                     this.FavoriteRetweetMenuItem.Enabled = false;
11802                     this.DelOpMenuItem.Enabled = true;
11803                 }
11804                 else
11805                 {
11806                     this.DelOpMenuItem.Enabled = false;
11807                     if (_curPost.IsProtect)
11808                     {
11809                         this.RtOpMenuItem.Enabled = false;
11810                         this.RtUnOpMenuItem.Enabled = false;
11811                         this.QtOpMenuItem.Enabled = false;
11812                         this.FavoriteRetweetMenuItem.Enabled = false;
11813                         this.FavoriteRetweetUnofficialMenuItem.Enabled = false;
11814                     }
11815                     else
11816                     {
11817                         this.RtOpMenuItem.Enabled = true;
11818                         this.RtUnOpMenuItem.Enabled = true;
11819                         this.QtOpMenuItem.Enabled = true;
11820                         this.FavoriteRetweetMenuItem.Enabled = true;
11821                         this.FavoriteRetweetUnofficialMenuItem.Enabled = true;
11822                     }
11823                 }
11824             }
11825
11826             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType != MyCommon.TabUsageType.Favorites)
11827             {
11828                 this.RefreshPrevOpMenuItem.Enabled = true;
11829             }
11830             else
11831             {
11832                 this.RefreshPrevOpMenuItem.Enabled = false;
11833             }
11834             if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch
11835                                 || !this.ExistCurrentPost
11836                                 || !(_curPost.InReplyToStatusId > 0))
11837             {
11838                 OpenRepSourceOpMenuItem.Enabled = false;
11839             }
11840             else
11841             {
11842                 OpenRepSourceOpMenuItem.Enabled = true;
11843             }
11844             if (!this.ExistCurrentPost || string.IsNullOrEmpty(_curPost.RetweetedBy))
11845             {
11846                 OpenRterHomeMenuItem.Enabled = false;
11847             }
11848             else
11849             {
11850                 OpenRterHomeMenuItem.Enabled = true;
11851             }
11852         }
11853
11854         private void MenuItemTab_DropDownOpening(object sender, EventArgs e)
11855         {
11856             ContextMenuTabProperty_Opening(sender, null);
11857         }
11858
11859         public Twitter TwitterInstance
11860         {
11861             get { return tw; }
11862         }
11863
11864         private void SplitContainer3_SplitterMoved(object sender, SplitterEventArgs e)
11865         {
11866             if (this.WindowState == FormWindowState.Normal && !_initialLayout)
11867             {
11868                 _mySpDis3 = SplitContainer3.SplitterDistance;
11869                 _modifySettingLocal = true;
11870             }
11871         }
11872
11873         private void MenuItemEdit_DropDownOpening(object sender, EventArgs e)
11874         {
11875             if (_statuses.RemovedTab.Count == 0)
11876             {
11877                 UndoRemoveTabMenuItem.Enabled = false;
11878             }
11879             else
11880             {
11881                 UndoRemoveTabMenuItem.Enabled = true;
11882             }
11883             if (ListTab.SelectedTab != null)
11884             {
11885                 if (_statuses.Tabs[ListTab.SelectedTab.Text].TabType == MyCommon.TabUsageType.PublicSearch)
11886                     PublicSearchQueryMenuItem.Enabled = true;
11887                 else
11888                     PublicSearchQueryMenuItem.Enabled = false;
11889             }
11890             else
11891             {
11892                 PublicSearchQueryMenuItem.Enabled = false;
11893             }
11894             if (!this.ExistCurrentPost)
11895             {
11896                 this.CopySTOTMenuItem.Enabled = false;
11897                 this.CopyURLMenuItem.Enabled = false;
11898                 this.CopyUserIdStripMenuItem.Enabled = false;
11899             }
11900             else
11901             {
11902                 this.CopySTOTMenuItem.Enabled = true;
11903                 this.CopyURLMenuItem.Enabled = true;
11904                 this.CopyUserIdStripMenuItem.Enabled = true;
11905                 if (_curPost.IsDm) this.CopyURLMenuItem.Enabled = false;
11906                 if (_curPost.IsProtect) this.CopySTOTMenuItem.Enabled = false;
11907             }
11908         }
11909
11910         private void NotifyIcon1_MouseMove(object sender, MouseEventArgs e)
11911         {
11912             SetNotifyIconText();
11913         }
11914
11915         private void UserStatusToolStripMenuItem_Click(object sender, EventArgs e)
11916         {
11917             string id = "";
11918             if (_curPost != null)
11919             {
11920                 id = _curPost.ScreenName;
11921             }
11922             ShowUserStatus(id);
11923         }
11924
11925         private class GetUserInfoArgs
11926         {
11927             public Twitter tw;
11928             public string id;
11929             public TwitterDataModel.User user;
11930         }
11931
11932         private void GetUserInfo_DoWork(object sender, DoWorkEventArgs e)
11933         {
11934             GetUserInfoArgs args = (GetUserInfoArgs)e.Argument;
11935             e.Result = args.tw.GetUserInfo(args.id, ref args.user);
11936         }
11937
11938         private void doShowUserStatus(string id, bool ShowInputDialog)
11939         {
11940             TwitterDataModel.User user = null;
11941             GetUserInfoArgs args = new GetUserInfoArgs();
11942             if (ShowInputDialog)
11943             {
11944                 using (InputTabName inputName = new InputTabName())
11945                 {
11946                     inputName.FormTitle = "Show UserStatus";
11947                     inputName.FormDescription = Properties.Resources.FRMessage1;
11948                     inputName.TabName = id;
11949                     if (inputName.ShowDialog() == DialogResult.OK &&
11950                         !string.IsNullOrEmpty(inputName.TabName.Trim()))
11951                     {
11952                         id = inputName.TabName.Trim();
11953                         args.tw = tw;
11954                         args.id = id;
11955                         args.user = user;
11956                         using (FormInfo _info = new FormInfo(this, Properties.Resources.doShowUserStatusText1,
11957                                                              GetUserInfo_DoWork,
11958                                                              null,
11959                                                              args))
11960                         {
11961                             _info.ShowDialog();
11962                             string ret = (string)_info.Result;
11963                             if (string.IsNullOrEmpty(ret))
11964                                 doShowUserStatus(args.user);
11965                             else
11966                                 MessageBox.Show(ret);
11967                         }
11968                     }
11969                 }
11970             }
11971             else
11972             {
11973                 args.tw = tw;
11974                 args.id = id;
11975                 args.user = user;
11976                 using (FormInfo _info = new FormInfo(this, Properties.Resources.doShowUserStatusText1,
11977                                                      GetUserInfo_DoWork,
11978                                                      null,
11979                                                      args))
11980                 {
11981                     _info.ShowDialog();
11982                     string ret = (string)_info.Result;
11983                     if (string.IsNullOrEmpty(ret))
11984                     {
11985                         doShowUserStatus(args.user);
11986                     }
11987                     else
11988                     {
11989                         MessageBox.Show(ret);
11990                     }
11991                 }
11992             }
11993         }
11994
11995         private void doShowUserStatus(TwitterDataModel.User user)
11996         {
11997             using (ShowUserInfo userinfo = new ShowUserInfo())
11998             {
11999                 userinfo.Owner = this;
12000                 userinfo.User = user;
12001                 userinfo.ShowDialog(this);
12002                 this.Activate();
12003                 this.BringToFront();
12004             }
12005         }
12006
12007         private void ShowUserStatus(string id, bool ShowInputDialog)
12008         {
12009             doShowUserStatus(id, ShowInputDialog);
12010         }
12011
12012         private void ShowUserStatus(string id)
12013         {
12014             doShowUserStatus(id, true);
12015         }
12016
12017         private void FollowToolStripMenuItem_Click(object sender, EventArgs e)
12018         {
12019             if (NameLabel.Tag != null)
12020             {
12021                 string id = (string)NameLabel.Tag;
12022                 if (id != tw.Username)
12023                 {
12024                     FollowCommand(id);
12025                 }
12026             }
12027         }
12028
12029         private void UnFollowToolStripMenuItem_Click(object sender, EventArgs e)
12030         {
12031             if (NameLabel.Tag != null)
12032             {
12033                 string id = (string)NameLabel.Tag;
12034                 if (id != tw.Username)
12035                 {
12036                     RemoveCommand(id, false);
12037                 }
12038             }
12039         }
12040
12041         private void ShowFriendShipToolStripMenuItem_Click(object sender, EventArgs e)
12042         {
12043             if (NameLabel.Tag != null)
12044             {
12045                 string id = (string)NameLabel.Tag;
12046                 if (id != tw.Username)
12047                 {
12048                     ShowFriendship(id);
12049                 }
12050             }
12051         }
12052
12053         private void ShowUserStatusToolStripMenuItem_Click(object sender, EventArgs e)
12054         {
12055             if (NameLabel.Tag != null)
12056             {
12057                 string id = (string)NameLabel.Tag;
12058                 ShowUserStatus(id, false);
12059             }
12060         }
12061
12062         private void SearchPostsDetailNameToolStripMenuItem_Click(object sender, EventArgs e)
12063         {
12064             if (NameLabel.Tag != null)
12065             {
12066                 string id = (string)NameLabel.Tag;
12067                 AddNewTabForUserTimeline(id);
12068             }
12069         }
12070
12071         private void SearchAtPostsDetailNameToolStripMenuItem_Click(object sender, EventArgs e)
12072         {
12073             if (NameLabel.Tag != null)
12074             {
12075                 string id = (string)NameLabel.Tag;
12076                 AddNewTabForSearch("@" + id);
12077             }
12078         }
12079
12080         private void ShowProfileMenuItem_Click(object sender, EventArgs e)
12081         {
12082             if (_curPost != null)
12083             {
12084                 ShowUserStatus(_curPost.ScreenName, false);
12085             }
12086         }
12087
12088         private void GetRetweet_DoWork(object sender, DoWorkEventArgs e)
12089         {
12090             int counter = 0;
12091
12092             long statusid;
12093             if (_curPost.RetweetedId > 0)
12094             {
12095                 statusid = _curPost.RetweetedId;
12096             }
12097             else
12098             {
12099                 statusid = _curPost.StatusId;
12100             }
12101             tw.GetStatus_Retweeted_Count(statusid, ref counter);
12102
12103             e.Result = counter;
12104         }
12105
12106         private void RtCountMenuItem_Click(object sender, EventArgs e)
12107         {
12108             if (this.ExistCurrentPost)
12109             {
12110                 using (FormInfo _info = new FormInfo(this, Properties.Resources.RtCountMenuItem_ClickText1,
12111                                                      GetRetweet_DoWork))
12112                 {
12113                     int retweet_count = 0;
12114
12115                     // ダイアログ表示
12116                     _info.ShowDialog();
12117                     retweet_count = (int)_info.Result;
12118                     if (retweet_count < 0)
12119                     {
12120                         MessageBox.Show(Properties.Resources.RtCountText2);
12121                     }
12122                     else
12123                     {
12124                         MessageBox.Show(retweet_count.ToString() + Properties.Resources.RtCountText1);
12125                     }
12126                 }
12127             }
12128         }
12129
12130         private HookGlobalHotkey _hookGlobalHotkey;
12131         public TweenMain()
12132         {
12133             _hookGlobalHotkey = new HookGlobalHotkey(this);
12134             // この呼び出しは、Windows フォーム デザイナで必要です。
12135             InitializeComponent();
12136
12137             // InitializeComponent() 呼び出しの後で初期化を追加します。
12138
12139             this.SettingDialog.IntervalChanged += this.TimerInterval_Changed;
12140             this.TimerTimeline.Elapsed += this.TimerTimeline_Elapsed;
12141             this._hookGlobalHotkey.HotkeyPressed += _hookGlobalHotkey_HotkeyPressed;
12142             this.gh.NotifyClicked += GrowlHelper_Callback;
12143
12144             this._apiGauge.Control.Size = new Size(70, 22);
12145             this._apiGauge.Control.Margin = new Padding(0, 3, 0, 2);
12146             this._apiGauge.GaugeHeight = 8;
12147             this._apiGauge.Control.DoubleClick += this.ApiInfoMenuItem_Click;
12148             this.StatusStrip1.Items.Insert(2, this._apiGauge);
12149
12150             this.ReplaceAppName();
12151         }
12152
12153         private void _hookGlobalHotkey_HotkeyPressed(object sender, KeyEventArgs e)
12154         {
12155             if ((this.WindowState == FormWindowState.Normal || this.WindowState == FormWindowState.Maximized) && this.Visible && Form.ActiveForm == this)
12156             {
12157                 //アイコン化
12158                 this.Visible = false;
12159             }
12160             else if (Form.ActiveForm == null)
12161             {
12162                 this.Visible = true;
12163                 if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
12164                 this.Activate();
12165                 this.BringToFront();
12166                 this.StatusText.Focus();
12167             }
12168         }
12169
12170         private void UserPicture_MouseEnter(object sender, EventArgs e)
12171         {
12172             this.UserPicture.Cursor = Cursors.Hand;
12173         }
12174
12175         private void UserPicture_MouseLeave(object sender, EventArgs e)
12176         {
12177             this.UserPicture.Cursor = Cursors.Default;
12178         }
12179
12180         private void UserPicture_DoubleClick(object sender, EventArgs e)
12181         {
12182             if (NameLabel.Tag != null)
12183             {
12184                 OpenUriAsync(MyCommon.TwitterUrl + NameLabel.Tag.ToString());
12185             }
12186         }
12187
12188         private void SplitContainer2_MouseDoubleClick(object sender, MouseEventArgs e)
12189         {
12190             this.MultiLineMenuItem.PerformClick();
12191         }
12192
12193         public PostClass CurPost
12194         {
12195             get { return _curPost; }
12196         }
12197
12198         public bool IsPreviewEnable
12199         {
12200             get { return SettingDialog.PreviewEnable; }
12201         }
12202
12203 #region "画像投稿"
12204         private void ImageSelectMenuItem_Click(object sender, EventArgs e)
12205         {
12206             if (ImageSelectionPanel.Visible == true)
12207             {
12208                 ImagefilePathText.CausesValidation = false;
12209                 TimelinePanel.Visible = true;
12210                 TimelinePanel.Enabled = true;
12211                 ImageSelectionPanel.Visible = false;
12212                 ImageSelectionPanel.Enabled = false;
12213                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12214                 ImagefilePathText.CausesValidation = true;
12215             }
12216             else
12217             {
12218                 ImageSelectionPanel.Visible = true;
12219                 ImageSelectionPanel.Enabled = true;
12220                 TimelinePanel.Visible = false;
12221                 TimelinePanel.Enabled = false;
12222                 ImagefilePathText.Focus();
12223             }
12224         }
12225
12226         private void FilePickButton_Click(object sender, EventArgs e)
12227         {
12228             if (string.IsNullOrEmpty(this.ImageService)) return;
12229             OpenFileDialog1.Filter = this.pictureService[this.ImageService].GetFileOpenDialogFilter();
12230             OpenFileDialog1.Title = Properties.Resources.PickPictureDialog1;
12231             OpenFileDialog1.FileName = "";
12232
12233             try
12234             {
12235                 this.AllowDrop = false;
12236                 if (OpenFileDialog1.ShowDialog() == DialogResult.Cancel) return;
12237             }
12238             finally
12239             {
12240                 this.AllowDrop = true;
12241             }
12242
12243             ImagefilePathText.Text = OpenFileDialog1.FileName;
12244             ImageFromSelectedFile();
12245         }
12246
12247         private void ImagefilePathText_Validating(object sender, CancelEventArgs e)
12248         {
12249             if (ImageCancelButton.Focused)
12250             {
12251                 ImagefilePathText.CausesValidation = false;
12252                 return;
12253             }
12254             ImagefilePathText.Text = ImagefilePathText.Text.Trim();
12255             if (string.IsNullOrEmpty(ImagefilePathText.Text))
12256             {
12257                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12258                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12259             }
12260             else
12261             {
12262                 ImageFromSelectedFile();
12263             }
12264         }
12265
12266         private void ImageFromSelectedFile()
12267         {
12268             try
12269             {
12270                 if (string.IsNullOrEmpty(ImagefilePathText.Text.Trim()) || string.IsNullOrEmpty(this.ImageService))
12271                 {
12272                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12273                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12274                     ImagefilePathText.Text = "";
12275                     return;
12276                 }
12277
12278                 FileInfo fl = new FileInfo(ImagefilePathText.Text.Trim());
12279                 if (!this.pictureService[this.ImageService].CheckValidExtension(fl.Extension))
12280                 {
12281                     //画像以外の形式
12282                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12283                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12284                     ImagefilePathText.Text = "";
12285                     return;
12286                 }
12287
12288                 if (!this.pictureService[this.ImageService].CheckValidFilesize(fl.Extension, fl.Length))
12289                 {
12290                     // ファイルサイズが大きすぎる
12291                     ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12292                     ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12293                     ImagefilePathText.Text = "";
12294                     MessageBox.Show("File is too large.");
12295                     return;
12296                 }
12297
12298                 switch (this.pictureService[this.ImageService].GetFileType(fl.Extension))
12299                 {
12300                     case MyCommon.UploadFileType.Invalid:
12301                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12302                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12303                         ImagefilePathText.Text = "";
12304                         break;
12305                     case MyCommon.UploadFileType.Picture:
12306                         Image img = null;
12307                         using (FileStream fs = new FileStream(ImagefilePathText.Text, FileMode.Open, FileAccess.Read))
12308                         {
12309                             img = Image.FromStream(fs);
12310                         }
12311                         ImageSelectedPicture.Image = (new HttpVarious()).CheckValidImage(
12312                                     img,
12313                                     img.Width,
12314                                     img.Height);
12315                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Picture;
12316                         break;
12317                     case MyCommon.UploadFileType.MultiMedia:
12318                         ImageSelectedPicture.Image = Properties.Resources.MultiMediaImage;
12319                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.MultiMedia;
12320                         break;
12321                     default:
12322                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12323                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12324                         ImagefilePathText.Text = "";
12325                         break;
12326                 }
12327             }
12328             catch (FileNotFoundException)
12329             {
12330                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12331                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12332                 ImagefilePathText.Text = "";
12333                 MessageBox.Show("File not found.");
12334             }
12335             catch (Exception)
12336             {
12337                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12338                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12339                 ImagefilePathText.Text = "";
12340                 MessageBox.Show("The type of this file is not image.");
12341             }
12342         }
12343
12344         private void ImageSelection_KeyDown(object sender, KeyEventArgs e)
12345         {
12346             if (e.KeyCode == Keys.Escape)
12347             {
12348                 ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12349                 ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12350                 TimelinePanel.Visible = true;
12351                 TimelinePanel.Enabled = true;
12352                 ImageSelectionPanel.Visible = false;
12353                 ImageSelectionPanel.Enabled = false;
12354                 ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12355                 ImagefilePathText.CausesValidation = true;
12356             }
12357         }
12358
12359         private void ImageSelection_KeyPress(object sender, KeyPressEventArgs e)
12360         {
12361             if (Convert.ToInt32(e.KeyChar) == 0x1B)
12362             {
12363                 ImagefilePathText.CausesValidation = false;
12364                 e.Handled = true;
12365             }
12366         }
12367
12368         private void ImageSelection_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
12369         {
12370             if (e.KeyCode == Keys.Escape)
12371             {
12372                 ImagefilePathText.CausesValidation = false;
12373             }
12374         }
12375
12376         private void SetImageServiceCombo()
12377         {
12378             string svc = "";
12379             if (ImageServiceCombo.SelectedIndex > -1) svc = ImageServiceCombo.SelectedItem.ToString();
12380             ImageServiceCombo.Items.Clear();
12381             ImageServiceCombo.Items.Add("TwitPic");
12382             ImageServiceCombo.Items.Add("img.ly");
12383             ImageServiceCombo.Items.Add("yfrog");
12384             ImageServiceCombo.Items.Add("lockerz");
12385             ImageServiceCombo.Items.Add("Twitter");
12386
12387             if (string.IsNullOrEmpty(svc))
12388             {
12389                 ImageServiceCombo.SelectedIndex = 0;
12390             }
12391             else
12392             {
12393                 int idx = ImageServiceCombo.Items.IndexOf(svc);
12394                 if (idx == -1)
12395                     ImageServiceCombo.SelectedIndex = 0;
12396                 else
12397                     ImageServiceCombo.SelectedIndex = idx;
12398             }
12399         }
12400
12401         private string ImageService
12402         {
12403             get { return (string)ImageServiceCombo.SelectedItem; }
12404         }
12405
12406         private void ImageCancelButton_Click(object sender, EventArgs e)
12407         {
12408             ImagefilePathText.CausesValidation = false;
12409             TimelinePanel.Visible = true;
12410             TimelinePanel.Enabled = true;
12411             ImageSelectionPanel.Visible = false;
12412             ImageSelectionPanel.Enabled = false;
12413             ((DetailsListView)ListTab.SelectedTab.Tag).Focus();
12414             ImagefilePathText.CausesValidation = true;
12415         }
12416
12417         private void ImageServiceCombo_SelectedIndexChanged(object sender, EventArgs e)
12418         {
12419             if (ImageSelectedPicture.Tag != null && !string.IsNullOrEmpty(this.ImageService))
12420             {
12421                 try
12422                 {
12423                     FileInfo fi = new FileInfo(ImagefilePathText.Text.Trim());
12424                     if (!this.pictureService[this.ImageService].CheckValidFilesize(fi.Extension, fi.Length))
12425                     {
12426                         ImagefilePathText.Text = "";
12427                         ImageSelectedPicture.Image = ImageSelectedPicture.InitialImage;
12428                         ImageSelectedPicture.Tag = MyCommon.UploadFileType.Invalid;
12429                     }
12430                 }
12431                 catch (Exception)
12432                 {
12433                 }
12434                 _modifySettingCommon = true;
12435                 SaveConfigsAll(false);
12436                 if (this.ImageService == "Twitter")
12437                 {
12438                     this.StatusText_TextChanged(null, null);
12439                 }
12440             }
12441         }
12442 #endregion
12443
12444         private void ListManageToolStripMenuItem_Click(object sender, EventArgs e)
12445         {
12446             using (ListManage form = new ListManage(tw))
12447             {
12448                 form.ShowDialog(this);
12449             }
12450         }
12451
12452         public bool ModifySettingCommon
12453         {
12454             set { _modifySettingCommon = value; }
12455         }
12456
12457         public bool ModifySettingLocal
12458         {
12459             set { _modifySettingLocal = value; }
12460         }
12461
12462         public bool ModifySettingAtId
12463         {
12464             set { _modifySettingAtId = value; }
12465         }
12466
12467         private void SourceLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
12468         {
12469             string link = (string)SourceLinkLabel.Tag;
12470             if (!string.IsNullOrEmpty(link) && e.Button == MouseButtons.Left)
12471             {
12472                 OpenUriAsync(link);
12473             }
12474         }
12475
12476         private void SourceLinkLabel_MouseEnter(object sender, EventArgs e)
12477         {
12478             string link = (string)SourceLinkLabel.Tag;
12479             if (!string.IsNullOrEmpty(link))
12480             {
12481                 StatusLabelUrl.Text = link;
12482             }
12483         }
12484
12485         private void SourceLinkLabel_MouseLeave(object sender, EventArgs e)
12486         {
12487             SetStatusLabelUrl();
12488         }
12489
12490         private void MenuItemCommand_DropDownOpening(object sender, EventArgs e)
12491         {
12492             if (this.ExistCurrentPost && !_curPost.IsDm)
12493                 RtCountMenuItem.Enabled = true;
12494             else
12495                 RtCountMenuItem.Enabled = false;
12496
12497             //if (SettingDialog.UrlConvertAuto && SettingDialog.ShortenTco)
12498             //    TinyUrlConvertToolStripMenuItem.Enabled = false;
12499             //else
12500             //    TinyUrlConvertToolStripMenuItem.Enabled = true;
12501         }
12502
12503         private void CopyUserIdStripMenuItem_Click(object sender, EventArgs e)
12504         {
12505             CopyUserId();
12506         }
12507
12508         private void CopyUserId()
12509         {
12510             if (_curPost == null) return;
12511             string clstr = _curPost.ScreenName;
12512             try
12513             {
12514                 Clipboard.SetDataObject(clstr, false, 5, 100);
12515             }
12516             catch (Exception ex)
12517             {
12518                 MessageBox.Show(ex.Message);
12519             }
12520         }
12521
12522         private void ShowRelatedStatusesMenuItem_Click(object sender, EventArgs e) // Handles ShowRelatedStatusesMenuItem.Click, ShowRelatedStatusesMenuItem2.Click
12523         {
12524             TabClass backToTab = _curTab == null ? _statuses.Tabs[ListTab.SelectedTab.Text] : _statuses.Tabs[_curTab.Text];
12525             if (this.ExistCurrentPost && !_curPost.IsDm)
12526             {
12527                 //PublicSearchも除外した方がよい?
12528                 if (_statuses.GetTabByType(MyCommon.TabUsageType.Related) == null)
12529                 {
12530                     const string TabName = "Related Tweets";
12531                     string tName = TabName;
12532                     if (!this.AddNewTab(tName, false, MyCommon.TabUsageType.Related))
12533                     {
12534                         for (int i = 2; i <= 100; i++)
12535                         {
12536                             tName = TabName + i.ToString();
12537                             if (this.AddNewTab(tName, false, MyCommon.TabUsageType.Related))
12538                             {
12539                                 _statuses.AddTab(tName, MyCommon.TabUsageType.Related, null);
12540                                 break;
12541                             }
12542                         }
12543                     }
12544                     else
12545                     {
12546                         _statuses.AddTab(tName, MyCommon.TabUsageType.Related, null);
12547                     }
12548                     _statuses.GetTabByName(tName).UnreadManage = false;
12549                     _statuses.GetTabByName(tName).Notify = false;
12550                 }
12551
12552                 TabClass tb = _statuses.GetTabByType(MyCommon.TabUsageType.Related);
12553                 tb.RelationTargetPost = _curPost;
12554                 this.ClearTab(tb.TabName, false);
12555                 for (int i = 0; i < ListTab.TabPages.Count; i++)
12556                 {
12557                     if (tb.TabName == ListTab.TabPages[i].Text)
12558                     {
12559                         ListTab.SelectedIndex = i;
12560                         ListTabSelect(ListTab.TabPages[i]);
12561                         break;
12562                     }
12563                 }
12564
12565                 GetTimeline(MyCommon.WORKERTYPE.Related, 1, 1, tb.TabName);
12566             }
12567         }
12568
12569         private void CacheInfoMenuItem_Click(object sender, EventArgs e)
12570         {
12571             StringBuilder buf = new StringBuilder();
12572             buf.AppendFormat("キャッシュメモリ容量         : {0}bytes({1}MB)" + Environment.NewLine, ((ImageDictionary)TIconDic).CacheMemoryLimit, ((ImageDictionary)TIconDic).CacheMemoryLimit / 1048576);
12573             buf.AppendFormat("物理メモリ使用割合           : {0}%" + Environment.NewLine, ((ImageDictionary)TIconDic).PhysicalMemoryLimit);
12574             buf.AppendFormat("キャッシュエントリ保持数     : {0}" + Environment.NewLine, ((ImageDictionary)TIconDic).CacheCount);
12575             buf.AppendFormat("キャッシュエントリ破棄数     : {0}" + Environment.NewLine, ((ImageDictionary)TIconDic).CacheRemoveCount);
12576             MessageBox.Show(buf.ToString(), "アイコンキャッシュ使用状況");
12577         }
12578
12579         private void tw_UserIdChanged()
12580         {
12581             this._modifySettingCommon = true;
12582         }
12583
12584 #region "Userstream"
12585         private bool _isActiveUserstream = false;
12586
12587         private void tw_PostDeleted(long id)
12588         {
12589             try
12590             {
12591                 if (InvokeRequired && !IsDisposed)
12592                 {
12593                     Invoke((Action) (() =>
12594                            {
12595                                _statuses.RemovePostReserve(id);
12596                                if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(id))
12597                                {
12598                                    _itemCache = null;
12599                                    _itemCacheIndex = -1;
12600                                    _postCache = null;
12601                                    ((DetailsListView)_curTab.Tag).Update();
12602                                    if (_curPost != null && _curPost.StatusId == id) DispSelectedPost(true);
12603                                }
12604                            }));
12605                     return;
12606                 }
12607             }
12608             catch (ObjectDisposedException)
12609             {
12610                 return;
12611             }
12612             catch (InvalidOperationException)
12613             {
12614                 return;
12615             }
12616         }
12617
12618         private void tw_NewPostFromStream()
12619         {
12620             if (SettingDialog.ReadOldPosts)
12621             {
12622                 _statuses.SetRead(); //新着時未読クリア
12623             }
12624
12625             int rsltAddCount = _statuses.DistributePosts();
12626             lock (_syncObject)
12627             {
12628                 DateTime tm = DateTime.Now;
12629                 if (_tlTimestamps.ContainsKey(tm))
12630                 {
12631                     _tlTimestamps[tm] += rsltAddCount;
12632                 }
12633                 else
12634                 {
12635                     _tlTimestamps.Add(tm, rsltAddCount);
12636                 }
12637                 DateTime oneHour = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
12638                 List<DateTime> keys = new List<DateTime>();
12639                 _tlCount = 0;
12640                 foreach (DateTime key in _tlTimestamps.Keys)
12641                 {
12642                     if (key.CompareTo(oneHour) < 0)
12643                         keys.Add(key);
12644                     else
12645                         _tlCount += _tlTimestamps[key];
12646                 }
12647                 foreach (DateTime key in keys)
12648                 {
12649                     _tlTimestamps.Remove(key);
12650                 }
12651                 keys.Clear();
12652
12653                 //Static DateTime before = Now;
12654                 //if (before.Subtract(Now).Seconds > -5) return;
12655                 //before = Now;
12656             }
12657
12658             if (SettingDialog.UserstreamPeriodInt > 0) return;
12659
12660             try
12661             {
12662                 if (InvokeRequired && !IsDisposed)
12663                 {
12664                     Invoke(new Action<bool>(RefreshTimeline), true);
12665                     return;
12666                 }
12667             }
12668             catch (ObjectDisposedException)
12669             {
12670                 return;
12671             }
12672             catch (InvalidOperationException)
12673             {
12674                 return;
12675             }
12676         }
12677
12678         private void tw_UserStreamStarted()
12679         {
12680             this._isActiveUserstream = true;
12681             try
12682             {
12683                 if (InvokeRequired && !IsDisposed)
12684                 {
12685                     Invoke(new MethodInvoker(tw_UserStreamStarted));
12686                     return;
12687                 }
12688             }
12689             catch (ObjectDisposedException)
12690             {
12691                 return;
12692             }
12693             catch (InvalidOperationException)
12694             {
12695                 return;
12696             }
12697
12698             MenuItemUserStream.Text = "&UserStream ▶";
12699             MenuItemUserStream.Enabled = true;
12700             StopToolStripMenuItem.Text = "&Stop";
12701             StopToolStripMenuItem.Enabled = true;
12702
12703             StatusLabel.Text = "UserStream Started.";
12704         }
12705
12706         private void tw_UserStreamStopped()
12707         {
12708             this._isActiveUserstream = false;
12709             try
12710             {
12711                 if (InvokeRequired && !IsDisposed)
12712                 {
12713                     Invoke(new MethodInvoker(tw_UserStreamStopped));
12714                     return;
12715                 }
12716             }
12717             catch (ObjectDisposedException)
12718             {
12719                 return;
12720             }
12721             catch (InvalidOperationException)
12722             {
12723                 return;
12724             }
12725
12726             MenuItemUserStream.Text = "&UserStream ■";
12727             MenuItemUserStream.Enabled = true;
12728             StopToolStripMenuItem.Text = "&Start";
12729             StopToolStripMenuItem.Enabled = true;
12730
12731             StatusLabel.Text = "UserStream Stopped.";
12732         }
12733
12734         private void tw_UserStreamEventArrived(Twitter.FormattedEvent ev)
12735         {
12736             try
12737             {
12738                 if (InvokeRequired && !IsDisposed)
12739                 {
12740                     Invoke(new Action<Twitter.FormattedEvent>(tw_UserStreamEventArrived), ev);
12741                     return;
12742                 }
12743             }
12744             catch (ObjectDisposedException)
12745             {
12746                 return;
12747             }
12748             catch (InvalidOperationException)
12749             {
12750                 return;
12751             }
12752             StatusLabel.Text = "Event: " + ev.Event;
12753             //if (ev.Event == "favorite")
12754             //{
12755             //    NotifyFavorite(ev);
12756             //}
12757             NotifyEvent(ev);
12758             if (ev.Event == "favorite" || ev.Event == "unfavorite")
12759             {
12760                 if (_curTab != null && _statuses.Tabs[_curTab.Text].Contains(ev.Id))
12761                 {
12762                     _itemCache = null;
12763                     _itemCacheIndex = -1;
12764                     _postCache = null;
12765                     ((DetailsListView)_curTab.Tag).Update();
12766                 }
12767                 if (ev.Event == "unfavorite" && ev.Username.ToLower().Equals(tw.Username.ToLower()))
12768                 {
12769                     RemovePostFromFavTab(new long[] {ev.Id});
12770                 }
12771             }
12772         }
12773
12774         private void NotifyEvent(Twitter.FormattedEvent ev)
12775         {
12776             //新着通知 
12777             if (BalloonRequired(ev))
12778             {
12779                 NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
12780                 //if (SettingDialog.DispUsername) NotifyIcon1.BalloonTipTitle = tw.Username + " - "; else NotifyIcon1.BalloonTipTitle = "";
12781                 //NotifyIcon1.BalloonTipTitle += Application.ProductName + " [" + ev.Event.ToUpper() + "] by " + ((string)(!string.IsNullOrEmpty(ev.Username) ? ev.Username : ""), string);
12782                 StringBuilder title = new StringBuilder();
12783                 if (SettingDialog.DispUsername)
12784                 {
12785                     title.Append(tw.Username);
12786                     title.Append(" - ");
12787                 }
12788                 else
12789                 {
12790                     //title.Clear();
12791                 }
12792                 title.Append(Application.ProductName);
12793                 title.Append(" [");
12794                 title.Append(ev.Event.ToUpper());
12795                 title.Append("] by ");
12796                 if (!string.IsNullOrEmpty(ev.Username))
12797                 {
12798                     title.Append(ev.Username.ToString());
12799                 }
12800                 else
12801                 {
12802                     //title.Append("");
12803                 }
12804                 string text;
12805                 if (!string.IsNullOrEmpty(ev.Target))
12806                 {
12807                     //NotifyIcon1.BalloonTipText = ev.Target;
12808                     text = ev.Target;
12809                 }
12810                 else
12811                 {
12812                     //NotifyIcon1.BalloonTipText = " ";
12813                     text = " ";
12814                 }
12815                 //NotifyIcon1.ShowBalloonTip(500);
12816                 if (SettingDialog.IsNotifyUseGrowl)
12817                 {
12818                     gh.Notify(GrowlHelper.NotifyType.UserStreamEvent,
12819                               ev.Id.ToString(), title.ToString(), text);
12820                 }
12821                 else
12822                 {
12823                     NotifyIcon1.BalloonTipIcon = ToolTipIcon.Warning;
12824                     NotifyIcon1.BalloonTipTitle = title.ToString();
12825                     NotifyIcon1.BalloonTipText = text;
12826                     NotifyIcon1.ShowBalloonTip(500);
12827                 }
12828             }
12829
12830             //サウンド再生
12831             string snd = SettingDialog.EventSoundFile;
12832             if (!_initial && SettingDialog.PlaySound && !string.IsNullOrEmpty(snd))
12833             {
12834                 if ((ev.Eventtype & SettingDialog.EventNotifyFlag) != 0 && IsMyEventNotityAsEventType(ev))
12835                 {
12836                     try
12837                     {
12838                         string dir = Application.StartupPath;
12839                         if (Directory.Exists(Path.Combine(dir, "Sounds")))
12840                         {
12841                             dir = Path.Combine(dir, "Sounds");
12842                         }
12843                         using (SoundPlayer player = new SoundPlayer(Path.Combine(dir, snd)))
12844                         {
12845                             player.Play();
12846                         }
12847                     }
12848                     catch (Exception)
12849                     {
12850                     }
12851                 }
12852             }
12853         }
12854
12855         private void StopToolStripMenuItem_Click(object sender, EventArgs e)
12856         {
12857             MenuItemUserStream.Enabled = false;
12858             if (StopRefreshAllMenuItem.Checked)
12859             {
12860                 StopRefreshAllMenuItem.Checked = false;
12861                 return;
12862             }
12863             if (this._isActiveUserstream)
12864             {
12865                 tw.StopUserStream();
12866             }
12867             else
12868             {
12869                 tw.StartUserStream();
12870             }
12871         }
12872
12873         private static string inputTrack = "";
12874
12875         private void TrackToolStripMenuItem_Click(object sender, EventArgs e)
12876         {
12877             if (TrackToolStripMenuItem.Checked)
12878             {
12879                 using (InputTabName inputForm = new InputTabName())
12880                 {
12881                     inputForm.TabName = inputTrack;
12882                     inputForm.FormTitle = "Input track word";
12883                     inputForm.FormDescription = "Track word";
12884                     if (inputForm.ShowDialog() != DialogResult.OK)
12885                     {
12886                         TrackToolStripMenuItem.Checked = false;
12887                         return;
12888                     }
12889                     inputTrack = inputForm.TabName.Trim();
12890                 }
12891                 if (!inputTrack.Equals(tw.TrackWord))
12892                 {
12893                     tw.TrackWord = inputTrack;
12894                     this._modifySettingCommon = true;
12895                     TrackToolStripMenuItem.Checked = !string.IsNullOrEmpty(inputTrack);
12896                     tw.ReconnectUserStream();
12897                 }
12898             }
12899             else
12900             {
12901                 tw.TrackWord = "";
12902                 tw.ReconnectUserStream();
12903             }
12904             this._modifySettingCommon = true;
12905         }
12906
12907         private void AllrepliesToolStripMenuItem_Click(object sender, EventArgs e)
12908         {
12909             tw.AllAtReply = AllrepliesToolStripMenuItem.Checked;
12910             this._modifySettingCommon = true;
12911             tw.ReconnectUserStream();
12912         }
12913
12914         private void EventViewerMenuItem_Click(object sender, EventArgs e)
12915         {
12916             if (evtDialog == null || evtDialog.IsDisposed)
12917             {
12918                 evtDialog = null;
12919                 evtDialog = new EventViewerDialog();
12920                 evtDialog.Owner = this;
12921                 //親の中央に表示
12922                 Point pos = evtDialog.Location;
12923                 pos.X = Convert.ToInt32(this.Location.X + this.Size.Width / 2 - evtDialog.Size.Width / 2);
12924                 pos.Y = Convert.ToInt32(this.Location.Y + this.Size.Height / 2 - evtDialog.Size.Height / 2);
12925                 evtDialog.Location = pos;
12926             }
12927             evtDialog.EventSource = tw.StoredEvent;
12928             if (!evtDialog.Visible)
12929             {
12930                 evtDialog.Show(this);
12931             }
12932             else
12933             {
12934                 evtDialog.Activate();
12935             }
12936             this.TopMost = this.SettingDialog.AlwaysTop;
12937         }
12938 #endregion
12939
12940         private void TweenRestartMenuItem_Click(object sender, EventArgs e)
12941         {
12942             MyCommon._endingFlag = true;
12943             try
12944             {
12945                 this.Close();
12946                 Application.Restart();
12947             }
12948             catch (Exception)
12949             {
12950                 MessageBox.Show("Failed to restart. Please run " + Application.ProductName + " manually.");
12951             }
12952         }
12953
12954         private void OpenOwnFavedMenuItem_Click(object sender, EventArgs e)
12955         {
12956             if (!string.IsNullOrEmpty(tw.Username)) OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + tw.Username + "/recent");
12957         }
12958
12959         private void OpenOwnHomeMenuItem_Click(object sender, EventArgs e)
12960         {
12961             OpenUriAsync(MyCommon.TwitterUrl + tw.Username);
12962         }
12963
12964         private void doTranslation(string str)
12965         {
12966             Bing _bing = new Bing();
12967             string buf = "";
12968             if (string.IsNullOrEmpty(str)) return;
12969             string srclng = "";
12970             string dstlng = SettingDialog.TranslateLanguage;
12971             string msg = "";
12972             if (srclng != dstlng && _bing.Translate("", dstlng, str, out buf))
12973             {
12974                 PostBrowser.DocumentText = createDetailHtml(buf);
12975             }
12976             else
12977             {
12978                 if (msg.StartsWith("Err:"))
12979                     StatusLabel.Text = msg;
12980             }
12981         }
12982
12983         private void TranslationToolStripMenuItem_Click(object sender, EventArgs e)
12984         {
12985             if (!this.ExistCurrentPost) return;
12986             doTranslation(_curPost.TextFromApi);
12987         }
12988
12989         private void SelectionTranslationToolStripMenuItem_Click(object sender, EventArgs e)
12990         {
12991             doTranslation(WebBrowser_GetSelectionText(ref PostBrowser));
12992         }
12993
12994         private bool ExistCurrentPost
12995         {
12996             get
12997             {
12998                 if (_curPost == null) return false;
12999                 if (_curPost.IsDeleted) return false;
13000                 return true;
13001             }
13002         }
13003
13004         private void ShowUserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
13005         {
13006             ShowUserTimeline();
13007         }
13008
13009         public bool FavEventChangeUnread
13010         {
13011             get { return SettingDialog.FavEventUnread; }
13012         }
13013
13014         private string GetUserIdFromCurPostOrInput(string caption)
13015         {
13016             string id = "";
13017             if (_curPost != null)
13018             {
13019                 id = _curPost.ScreenName;
13020             }
13021             using (InputTabName inputName = new InputTabName())
13022             {
13023                 inputName.FormTitle = caption;
13024                 inputName.FormDescription = Properties.Resources.FRMessage1;
13025                 inputName.TabName = id;
13026                 if (inputName.ShowDialog() == DialogResult.OK &&
13027                     !string.IsNullOrEmpty(inputName.TabName.Trim()))
13028                 {
13029                     id = inputName.TabName.Trim();
13030                 }
13031                 else
13032                 {
13033                     id = "";
13034                 }
13035             }
13036             return id;
13037         }
13038
13039         private void UserTimelineToolStripMenuItem_Click(object sender, EventArgs e)
13040         {
13041             string id = GetUserIdFromCurPostOrInput("Show UserTimeline");
13042             if (!string.IsNullOrEmpty(id))
13043             {
13044                 AddNewTabForUserTimeline(id);
13045             }
13046         }
13047
13048         private void UserFavorareToolStripMenuItem_Click(object sender, EventArgs e)
13049         {
13050             string id = GetUserIdFromCurPostOrInput("Show Favstar");
13051             if (!string.IsNullOrEmpty(id))
13052             {
13053                 OpenUriAsync(Properties.Resources.FavstarUrl + "users/" + id + "/recent");
13054             }
13055         }
13056
13057         private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e)
13058         {
13059             if (e.Mode == Microsoft.Win32.PowerModes.Resume) osResumed = true;
13060         }
13061
13062         private void TimelineRefreshEnableChange(bool isEnable)
13063         {
13064             if (isEnable)
13065             {
13066                 tw.StartUserStream();
13067             }
13068             else
13069             {
13070                 tw.StopUserStream();
13071             }
13072             TimerTimeline.Enabled = isEnable;
13073         }
13074
13075         private void StopRefreshAllMenuItem_CheckedChanged(object sender, EventArgs e)
13076         {
13077             TimelineRefreshEnableChange(!StopRefreshAllMenuItem.Checked);
13078         }
13079
13080         private void OpenUserAppointUrl()
13081         {
13082             if (SettingDialog.UserAppointUrl != null)
13083             {
13084                 if (SettingDialog.UserAppointUrl.Contains("{ID}") || SettingDialog.UserAppointUrl.Contains("{STATUS}"))
13085                 {
13086                     if (_curPost != null)
13087                     {
13088                         string xUrl = SettingDialog.UserAppointUrl;
13089                         xUrl = xUrl.Replace("{ID}", _curPost.ScreenName);
13090                         if (_curPost.RetweetedId != 0)
13091                         {
13092                             xUrl = xUrl.Replace("{STATUS}", _curPost.RetweetedId.ToString());
13093                         }
13094                         else
13095                         {
13096                             xUrl = xUrl.Replace("{STATUS}", _curPost.StatusId.ToString());
13097                         }
13098                         OpenUriAsync(xUrl);
13099                     }
13100                 }
13101                 else
13102                 {
13103                     OpenUriAsync(SettingDialog.UserAppointUrl);
13104                 }
13105             }
13106         }
13107
13108         private void OpenUserSpecifiedUrlMenuItem_Click(object sender, EventArgs e)
13109         {
13110             OpenUserAppointUrl();
13111         }
13112
13113         private void ImageSelectionPanel_VisibleChanged(object sender, EventArgs e)
13114         {
13115             this.StatusText_TextChanged(null, null);
13116         }
13117
13118         private void SourceCopyMenuItem_Click(object sender, EventArgs e)
13119         {
13120             string selText = SourceLinkLabel.Text;
13121             try
13122             {
13123                 Clipboard.SetDataObject(selText, false, 5, 100);
13124             }
13125             catch (Exception ex)
13126             {
13127                 MessageBox.Show(ex.Message);
13128             }
13129         }
13130
13131         private void SourceUrlCopyMenuItem_Click(object sender, EventArgs e)
13132         {
13133             string selText = (string)SourceLinkLabel.Tag;
13134             try
13135             {
13136                 Clipboard.SetDataObject(selText, false, 5, 100);
13137             }
13138             catch (Exception ex)
13139             {
13140                 MessageBox.Show(ex.Message);
13141             }
13142         }
13143
13144         private void ContextMenuSource_Opening(object sender, CancelEventArgs e)
13145         {
13146             if (_curPost == null || !ExistCurrentPost || _curPost.IsDm)
13147             {
13148                 SourceCopyMenuItem.Enabled = false;
13149                 SourceUrlCopyMenuItem.Enabled = false;
13150             }
13151             else
13152             {
13153                 SourceCopyMenuItem.Enabled = true;
13154                 SourceUrlCopyMenuItem.Enabled = true;
13155             }
13156         }
13157
13158         private void GrowlHelper_Callback(object sender, GrowlHelper.NotifyCallbackEventArgs e)
13159         {
13160             if (Form.ActiveForm == null)
13161             {
13162                 this.BeginInvoke((Action) (() =>
13163                 {
13164                     this.Visible = true;
13165                     if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
13166                     this.Activate();
13167                     this.BringToFront();
13168                     if (e.NotifyType == GrowlHelper.NotifyType.DirectMessage)
13169                     {
13170                         if (!this.GoDirectMessage(e.StatusId)) this.StatusText.Focus();
13171                     }
13172                     else
13173                     {
13174                         if (!this.GoStatus(e.StatusId)) this.StatusText.Focus();
13175                     }
13176                 }));
13177             }
13178         }
13179
13180         private void ReplaceAppName()
13181         {
13182             MatomeMenuItem.Text = MyCommon.ReplaceAppName(MatomeMenuItem.Text);
13183             AboutMenuItem.Text = MyCommon.ReplaceAppName(AboutMenuItem.Text);
13184         }
13185
13186         private void tweetThumbnail1_ThumbnailLoading(object sender, EventArgs e)
13187         {
13188             this.SplitContainer3.Panel2Collapsed = false;
13189         }
13190
13191         private void tweetThumbnail1_ThumbnailDoubleClick(object sender, ThumbnailDoubleClickEventArgs e)
13192         {
13193             this.OpenThumbnailPicture(e.Thumbnail);
13194         }
13195
13196         private void OpenThumbnailPicture(ThumbnailInfo thumbnail)
13197         {
13198             this.OpenUriAsync(thumbnail.ImageUrl);
13199         }
13200     }
13201 }